diff --git a/config.properties b/config.properties
index 8ac5a792d734f459a81d0ff8d0f4455672110a2f..604560a832717535b2aa0417bb47086df60cb8eb 100644
--- a/config.properties
+++ b/config.properties
@@ -3,27 +3,28 @@ BASE_DIR=C:/Users/s1924442/git/plumv2
 YIELD_DIR=C:/Users/s1924442/Documents/PhD/LURG/rcp60
 YIELD_DIR_TOP=rcp60
 
-OUTPUT_DIR = C:/Users/s1924442/Documents/PhD/PLUM outputs/forest_calib
+CALIB_DIR=C:/Users/s1924442/Documents/PhD/PLUM outputs/forest_calib
+OUTPUT_DIR = C:/Users/s1924442/Documents/PhD/PLUM outputs/forest_test
 
 WOOD_AND_CARBON_DIR = C:/Users/s1924442/Documents/PhD/Carbon and wood yields/forestry_dummy_4
 
 BASE_YEAR=2010
 START_TIMESTEP=0
 TIMESTEP_SIZE=1
-END_TIMESTEP=10
+END_TIMESTEP=0
 
-IS_CALIBRATION_RUN=true
-END_FIRST_STAGE_CALIBRATION=0
+IS_CALIBRATION_RUN=false
+END_FIRST_STAGE_CALIBRATION=1
 
 GENERATE_NEW_YIELD_CLUSTERS=false
 
 YIELD_FILENAME=yield.out
 
 DEBUG_LIMIT_COUNTRIES=true
-DEBUG_COUNTRY_NAME=Central America
-GAMS_COUNTRY_TO_SAVE=Central America
+DEBUG_COUNTRY_NAME=United Kingdom
+GAMS_COUNTRY_TO_SAVE=United Kingdom
 
-INIT_WOOD_PRICE=0.4
+INIT_WOOD_PRICE=0.04
 INIT_WOOD_STOCK=1000
 INIT_CARBON_PRICE=0.0
 INFRASTRUCTURE_EXPANSION_COST=0.0
@@ -33,6 +34,6 @@ FOREST_MANAGEMENT_COST=0.25
 FOREST_MAX_CHANGE=0.02
 LAND_CHANGE_COST=0.5
 NATURAL_AREA_VALUE=0.0
-VEGETATION_CLEARING_COST=0.05
+VEGETATION_CLEARING_COST=0.02
 IS_FORESTRY_ON=true
-IS_CARBON_ON=true
+IS_CARBON_ON=false
diff --git a/src/ac/ed/lurg/carbon/CarbonFluxItem.java b/src/ac/ed/lurg/carbon/CarbonFluxItem.java
index 3514e65a58ae7394b6bb85f03fab280c28358ad5..9dd7c6dbece4fc3651e592f849988179bca474c5 100644
--- a/src/ac/ed/lurg/carbon/CarbonFluxItem.java
+++ b/src/ac/ed/lurg/carbon/CarbonFluxItem.java
@@ -10,6 +10,7 @@ import ac.ed.lurg.Timestep;
 import ac.ed.lurg.landuse.LandCoverTile;
 import ac.ed.lurg.landuse.LccKey;
 import ac.ed.lurg.types.LandCoverType;
+import ac.ed.lurg.types.LandProtectionType;
 
 public class CarbonFluxItem implements RasterItem, Serializable {
 	private static final long serialVersionUID = 440720456140537815L;
@@ -24,13 +25,13 @@ public class CarbonFluxItem implements RasterItem, Serializable {
 	public void calcConversionCarbonFlux(LccKey key, Double[] cFluxes, Map<LandCoverType, LandCoverTile> landUseTiles, Timestep timestep) {	
 		LandCoverTile tiles = landUseTiles.get(key.getFromLc());
 		
-		double totalArea = tiles.getTotalConvertibleArea();
+		double totalArea = tiles.getTotalArea(LandProtectionType.CONVERTIBLE);
 		if (totalArea == 0) {
 			this.conversionCarbonFlux.put(key, 0.0);
 		} else {				
 			double totalFlux = 0;
-			for (int age=0; age<=tiles.getMaxAgeBin(); age++) {
-				totalFlux += cFluxes[age] * tiles.getConvertibleArea(age);
+			for (int age=0; age<=LandCoverTile.getMaxAgeBin(); age++) {
+				totalFlux += cFluxes[age] * tiles.getArea(LandProtectionType.CONVERTIBLE, age);
 			}
 			double meanFlux = totalFlux / totalArea;
 			this.conversionCarbonFlux.put(key, meanFlux);
@@ -45,13 +46,13 @@ public class CarbonFluxItem implements RasterItem, Serializable {
 		
 		LandCoverTile tiles = landUseTiles.get(lcType);
 		
-		double totalArea = tiles.getTotalConvertibleArea();
+		double totalArea = tiles.getTotalArea(LandProtectionType.CONVERTIBLE);
 		if (totalArea == 0) {
 			this.ecosystemCarbonFlux.put(lcType, 0.0);
 		} else {				
 			double totalFlux = 0;
-			for (int age=0; age<=tiles.getMaxAgeBin(); age++) {
-				totalFlux += cFluxes[age] * tiles.getConvertibleArea(age);
+			for (int age=0; age<=LandCoverTile.getMaxAgeBin(); age++) {
+				totalFlux += cFluxes[age] * tiles.getArea(LandProtectionType.CONVERTIBLE, age);
 			}
 			double meanFlux = totalFlux / totalArea;
 			this.ecosystemCarbonFlux.put(lcType, meanFlux);
diff --git a/src/ac/ed/lurg/forestry/WoodYieldItem.java b/src/ac/ed/lurg/forestry/WoodYieldItem.java
index e3da5d72aba0015993bb2bd7fe061fc6f9dc56f7..049715c779633fc187cd07e738178d45775cf080 100644
--- a/src/ac/ed/lurg/forestry/WoodYieldItem.java
+++ b/src/ac/ed/lurg/forestry/WoodYieldItem.java
@@ -10,6 +10,7 @@ import ac.ed.lurg.Timestep;
 import ac.ed.lurg.landuse.LandCoverTile;
 import ac.ed.lurg.landuse.LccKey;
 import ac.ed.lurg.types.LandCoverType;
+import ac.ed.lurg.types.LandProtectionType;
 import ac.sac.raster.RasterItem;
 
 public class WoodYieldItem implements RasterItem {
@@ -31,13 +32,13 @@ public class WoodYieldItem implements RasterItem {
 			
 			LandCoverTile tiles = landUseTiles.get(key.getFromLc());
 			
-			double totalArea = tiles.getTotalConvertibleArea(); // Assuming no harvest from protected areas
+			double totalArea = tiles.getTotalArea(LandProtectionType.CONVERTIBLE); // Assuming no harvest from protected areas
 			if (totalArea == 0) {
 				this.yield.put(key, 0.0) ;
 			} else {				
 				double totalYield = 0;
 				for (int age=0; age<=LandCoverTile.getMaxAgeBin(); age++) {
-					totalYield += yields[age] * tiles.getConvertibleArea(age);
+					totalYield += yields[age] * tiles.getArea(LandProtectionType.CONVERTIBLE, age);
 				}
 				double meanYield = totalYield / totalArea;
 
@@ -70,11 +71,11 @@ public class WoodYieldItem implements RasterItem {
 		
 		final double OVER_ROTA_AGE_HARVEST_PROP = 0.05;
 		LandCoverTile timberTiles = landUseTiles.get(LandCoverType.TIMBER_FOREST);
-		double timberForestArea = timberTiles.getTotalConvertibleArea();
+		double timberForestArea = timberTiles.getTotalArea(LandProtectionType.CONVERTIBLE);
 		if (timberForestArea == 0) {
 			currentRotationHarvest = 0.0;
 		} else {
-			currentRotationHarvest += timberTiles.getConvertibleArea(optimalRotation) * yieldAtRotation;
+			currentRotationHarvest += timberTiles.getArea(LandProtectionType.CONVERTIBLE, optimalRotation) * yieldAtRotation;
 			/*
 			timberTiles.resetAreaForAge(optimalRotation); // WARNING: side effect
 			
diff --git a/src/ac/ed/lurg/landuse/LandCoverTile.java b/src/ac/ed/lurg/landuse/LandCoverTile.java
index 73c2b0f5e9969370218efbe32f3a66547457e776..b79af9b860b097f3d2cff7cce1338c5df4170e25 100644
--- a/src/ac/ed/lurg/landuse/LandCoverTile.java
+++ b/src/ac/ed/lurg/landuse/LandCoverTile.java
@@ -2,161 +2,102 @@ package ac.ed.lurg.landuse;
 
 import java.io.Serializable;
 import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
 
 import ac.ed.lurg.ModelConfig;
 import ac.ed.lurg.utils.LogWriter;
 import ac.sac.raster.InterpolatingRasterItem;
+import ac.ed.lurg.types.LandProtectionType;
 
 public class LandCoverTile implements Serializable, InterpolatingRasterItem<LandCoverTile> {
 	private static final long serialVersionUID = 3208516181615267472L;
 	private static final int MAX_AGE = 250;
 	
-	private Double[] convertibleAreas; // area Mha; index = age
-	private Double[] protectedAreas; // area Mha; index = age
-	private double unavailableArea; // unavailable for conversion due to slope, altitude TODO age?
+	private Map<LandProtectionType, LandParcel> areas;
 	
 	public LandCoverTile() {
-		this.convertibleAreas = new Double[MAX_AGE+1];
-		this.protectedAreas = new Double[MAX_AGE+1];
-		Arrays.fill(convertibleAreas, 0.0);
-		Arrays.fill(protectedAreas, 0.0);
-		unavailableArea = 0.0;
+		this.areas = new HashMap<LandProtectionType, LandParcel>();
+		for (LandProtectionType lpType : LandProtectionType.values()) {
+			areas.put(lpType, new LandParcel());
+		}
 	}
 
-	public double getConvertibleArea(int age) {
-		return convertibleAreas[age];
-	}
-	
-	public void setConvertibleArea(int age, double area) {
-		convertibleAreas[age] = area;
+	public double getArea(LandProtectionType lpType, int age) {
+		return areas.get(lpType).get(age);
 	}
 	
-	public void addConvertibleArea(double a) {
-		convertibleAreas[0] += a;
+	public void addArea(LandProtectionType lpType, double a) {
+		areas.get(lpType).add(0, a); // new area is always age=0
 	}
 	
-	public double getTotalConvertibleArea() {
-		double total = 0;
-		for (double d : convertibleAreas) {
-			total += d;
-		}
-		return total;
+	public void addArea(LandProtectionType lpType, int age, double a) {
+		areas.get(lpType).add(age, a);
 	}
 	
-	public void removeConvertibleArea(double a) { // Subtracts area uniformly
-		if (a <= 0)
-			return;
-		double totalArea = getTotalConvertibleArea();
-		double areaToRemove = Math.min(totalArea, a);
-		if (Math.abs(a - areaToRemove) > 1e-10) {
-			LogWriter.printlnError("LandCoverTile.removeConvertibleArea: attempting to remove too much area: " + a + ", available: " + totalArea);
-		}
-		double factor = (totalArea - areaToRemove) / totalArea;
-		for (int i=0; i<convertibleAreas.length; i++) {
-			convertibleAreas[i] *= factor;
-		}
+	public void setArea(LandProtectionType lpType, int age, double a) {
+		areas.get(lpType).set(age, a);
 	}
 	
-	public double getProtectedArea(int age) {
-		return protectedAreas[age];
+	public double getTotalArea(LandProtectionType lpType) {
+		return areas.get(lpType).getTotal();
 	}
 	
-	public void setProtectedArea(int age, double area) {
-		protectedAreas[age] = area;
+	public void removeArea(LandProtectionType lpType, double a) { // Subtracts area uniformly
+		areas.get(lpType).subtractUniform(a);
 	}
 	
-	public void addProtectedArea(double d) {
-		protectedAreas[0] += d;
-		
+	public void removeArea(LandProtectionType lpType, int age, double a) {
+		areas.get(lpType).subtract(age, a);
 	}
 
-	public double getTotalProtectedArea() {
-		double total = 0;
-		for (double d : protectedAreas) {
-			total += d;
-		}
-		return total;
-	}
-	
-	public void removeProtectedArea(double a) { // Subtracts area uniformly
-		if (a <= 0)
-			return;
-		double totalArea = getTotalProtectedArea();
-		double areaToRemove = a;
-		if (a > totalArea) {
-			LogWriter.printlnError("LandCoverTile.removeProtectedArea: attempting to remove too much area: " + a + ", available: " + totalArea);
-			areaToRemove = totalArea;
-		}
-		double factor = (totalArea - areaToRemove) / totalArea;
-		for (int i=0; i<protectedAreas.length; i++) {
-			protectedAreas[i] *= factor;
-		}
-	}
-	
-	public double getUnavailableArea() {
-		return unavailableArea;
-	}
-	
-	public void addUnavailableArea(double d) {
-		unavailableArea += d;
-	}
-	
 	public double getTotalArea() {
-		return getTotalConvertibleArea() + getTotalProtectedArea() + unavailableArea;
+		double area = 0;
+		for (LandProtectionType lpType : LandProtectionType.values()) {
+			area += getTotalArea(lpType);
+		}
+		return area;
 	}
 
-	public void resetAreaForAge(int age) {
-		convertibleAreas[0] += convertibleAreas[age];
-		convertibleAreas[age] = 0.0;
+	public void resetAreaForAge(LandProtectionType lpType, int age) {
+		areas.get(lpType).resetAge(age);
 	}
 	
-	public void resetAreaForAge(int age, double area) {
-		if (area > getConvertibleArea(age)) {
+	public void resetAreaForAge(LandProtectionType lpType, int age, double area) {
+		if (area > getArea(lpType, age)) {
 			LogWriter.printlnError("LandCoverTile.resetAreaForAge: not enough area");
 			return;
 		}
-		convertibleAreas[0] += area;
-		convertibleAreas[age] -= area;
+		addArea(lpType, area);
+		removeArea(lpType, age, area);
 	}
 	
 	public void removeAllArea() {
-		Arrays.fill(convertibleAreas, 0.0);
-		Arrays.fill(protectedAreas, 0.0);
-		unavailableArea = 0.0;
+		for (LandProtectionType lpType : LandProtectionType.values()) {
+			areas.get(lpType).clearAll();
+		}
 	}
 	
 	public void incrementAge() {
 		for (int t = 0; t < ModelConfig.TIMESTEP_SIZE; t++) {
-			int n = convertibleAreas.length;
-			convertibleAreas[n-1] += convertibleAreas[n-2]; // final age bin is all absorbing
-			// shift values
-			for (int i=(n-2); i>0; i--) {
-				convertibleAreas[i] = convertibleAreas[i-1];
-			}
-			convertibleAreas[0]= 0.0;
-
-			int m = protectedAreas.length;
-			protectedAreas[m-1] += protectedAreas[m-2]; // final age bin is all absorbing
-			// shift values
-			for (int i=(m-2); i>0; i--) {
-				protectedAreas[i] = protectedAreas[i-1];
+			for (LandProtectionType lpType : LandProtectionType.values()) {
+				areas.get(lpType).incrementAge();
 			}
-			protectedAreas[0]= 0.0;	
 		}
 	}
 
 	// Moves area from convertible to protected, maintaining age classes
 	public void moveAreaToProtected(double area) {
-		double convertibleA = getTotalConvertibleArea();
+		double convertibleA = getTotalArea(LandProtectionType.CONVERTIBLE);
 		if (area > convertibleA) {
 			LogWriter.printlnWarning("LandCoverTile.moveAreaToProtected cannot protect all required area");
 			area = Math.min(convertibleA, area);
 		}
 		double fractToMove = area / convertibleA;
 		for (int i = 0; i <= MAX_AGE; i ++) {
-			double areaToMove = convertibleAreas[i] * fractToMove;
-			protectedAreas[i] += areaToMove;
-			convertibleAreas[i] -= areaToMove;	
+			double areaToMove = getArea(LandProtectionType.CONVERTIBLE, i) * fractToMove;
+			addArea(LandProtectionType.PROTECTED, i, areaToMove);
+			removeArea(LandProtectionType.CONVERTIBLE, i, areaToMove);
 		}
 	}
 	
diff --git a/src/ac/ed/lurg/landuse/LandParcel.java b/src/ac/ed/lurg/landuse/LandParcel.java
new file mode 100644
index 0000000000000000000000000000000000000000..7dc3aa643328e5ddd8808f64ab2b495c5c7851c2
--- /dev/null
+++ b/src/ac/ed/lurg/landuse/LandParcel.java
@@ -0,0 +1,89 @@
+package ac.ed.lurg.landuse;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+import ac.ed.lurg.utils.LogWriter;
+
+public class LandParcel implements Serializable {
+	private static final long serialVersionUID = -114360206977984739L;
+	Map<Integer, Double> parcels;
+	
+	public LandParcel() {
+		this.parcels = new TreeMap<Integer, Double>();
+	}
+	
+	public void set(int age, double area) {
+		parcels.put(age, area);
+	}
+	
+	public double get(int age) {
+		return parcels.getOrDefault(age, 0.0);
+	}
+	
+	public void add(int age, double area) {
+		double newArea = get(age) + area;
+		set(age, newArea);
+	}
+	
+	public void subtract(int age, double area) {
+		double prevArea = get(age);
+		double newArea;
+		if (prevArea < area) {
+			LogWriter.printlnError("LandParcel: Attempting to subtract too much area");
+			newArea = 0.0;
+		} else {
+			newArea = prevArea - area;
+		}
+		set(age, newArea);
+	}
+	
+	public void subtractUniform(double area) {
+		if (area <= 0)
+			return;
+		double totalArea = getTotal();
+		double areaToRemove = Math.min(totalArea, area);
+		if (Math.abs(area - areaToRemove) > 1e-10) {
+			LogWriter.printlnError("LandParcel.subtractUniform: attempting to remove too much area: " + area + ", available: " + totalArea);
+		}
+		double factor = (totalArea - areaToRemove) / totalArea;
+		for (int i : parcels.keySet()) {
+			double newArea = get(i) * factor;
+			set(i, newArea);
+		}
+	}
+	
+	public double getTotal() {
+		return parcels.values().stream().reduce(0.0, Double::sum);
+	}
+	
+	public void resetAge(int age) {
+		double area = get(age);
+		set(age, 0.0);
+		set(0, area);
+	}
+	
+	public void incrementAge() {
+		if (parcels.size() == 0)
+			return;
+		
+		Set<Integer> keys = parcels.keySet();
+		List<Integer> orderedKeys = new ArrayList<Integer>(keys);
+		Collections.sort(orderedKeys);
+		Collections.reverse(orderedKeys);
+		for (int age : orderedKeys) {
+			double area = get(age);
+			set(age + 1, area);
+			parcels.remove(age);
+		}
+	}	
+	
+	public void clearAll() {
+		parcels.clear();
+	}
+}
diff --git a/src/ac/ed/lurg/landuse/LandUseBinarySerializer.java b/src/ac/ed/lurg/landuse/LandUseBinarySerializer.java
index c31e480981a0b3cbdc0a0bc64d224771b7477bb2..96b62f83e1e50366106a654080316dfef6e6bc89 100644
--- a/src/ac/ed/lurg/landuse/LandUseBinarySerializer.java
+++ b/src/ac/ed/lurg/landuse/LandUseBinarySerializer.java
@@ -14,6 +14,7 @@ import java.util.Map;
 
 import ac.ed.lurg.ModelConfig;
 import ac.ed.lurg.types.LandCoverType;
+import ac.ed.lurg.types.LandProtectionType;
 import ac.ed.lurg.utils.LogWriter;
 import ac.sac.raster.RasterKey;
 import ac.sac.raster.RasterSet;
@@ -56,7 +57,7 @@ public class LandUseBinarySerializer {
 				for (LandCoverType lcType : LandCoverType.values()) {
 					LandCoverTile tile = tiles.get(lcType);
 					for (int a = 0; a < NUM_AGE_CLASSES; a++) {
-						writer.writeDouble(tile.getConvertibleArea(a));
+						writer.writeDouble(tile.getArea(LandProtectionType.CONVERTIBLE, a));
 					}
 				}
 
@@ -64,14 +65,14 @@ public class LandUseBinarySerializer {
 				for (LandCoverType lcType : LandCoverType.values()) {
 					LandCoverTile tile = tiles.get(lcType);
 					for (int a = 0; a < NUM_AGE_CLASSES; a++) {
-						writer.writeDouble(tile.getProtectedArea(a));
+						writer.writeDouble(tile.getArea(LandProtectionType.PROTECTED, a));
 					}
 				}
 
 				// Unavailable
 				for (LandCoverType lcType : LandCoverType.values()) {
 					LandCoverTile tile = tiles.get(lcType);
-					writer.writeDouble(tile.getUnavailableArea());
+					writer.writeDouble(tile.getTotalArea(LandProtectionType.UNAVAILABLE));
 				}
 				//LogWriter.println(""+count);
 			}
@@ -138,7 +139,8 @@ public class LandUseBinarySerializer {
 						for (LandCoverType lcType : LandCoverType.values()) {
 							for (int age = 0; age < NUM_AGE_CLASSES; age++) {
 								double area = reader.readDouble();
-								landCoverAreas.get(lcType).setConvertibleArea(age, area);
+								if (area > 0)
+									landCoverAreas.get(lcType).setArea(LandProtectionType.CONVERTIBLE, age, area);
 							}
 						}
 						break;
@@ -146,14 +148,16 @@ public class LandUseBinarySerializer {
 						for (LandCoverType lcType : LandCoverType.values()) {
 							for (int age = 0; age < NUM_AGE_CLASSES; age++) {
 								double area = reader.readDouble();
-								landCoverAreas.get(lcType).setProtectedArea(age, area);
+								if (area > 0)
+									landCoverAreas.get(lcType).setArea(LandProtectionType.PROTECTED, age, area);
 							}
 						}	
 						break;
 					case UNVAVAILABLE_IDX:
 						for (LandCoverType lcType : LandCoverType.values()) {
 							double area = reader.readDouble();
-							landCoverAreas.get(lcType).addUnavailableArea(area);
+							if (area > 0)
+								landCoverAreas.get(lcType).setArea(LandProtectionType.UNAVAILABLE, 0, area); // TODO Do we need to keep track of age?
 						}
 					}
 				}
diff --git a/src/ac/ed/lurg/landuse/LandUseItem.java b/src/ac/ed/lurg/landuse/LandUseItem.java
index 63e93b16c6d19de8a4c56bf60304dedfa8aae6e0..6baa4028d6fb89f5946c92f5d36a87924a18c93e 100644
--- a/src/ac/ed/lurg/landuse/LandUseItem.java
+++ b/src/ac/ed/lurg/landuse/LandUseItem.java
@@ -8,6 +8,7 @@ import ac.ed.lurg.ModelConfig;
 import ac.ed.lurg.types.CropToDouble;
 import ac.ed.lurg.types.CropType;
 import ac.ed.lurg.types.LandCoverType;
+import ac.ed.lurg.types.LandProtectionType;
 import ac.ed.lurg.utils.Interpolator;
 import ac.ed.lurg.utils.LogWriter;
 import ac.sac.raster.InterpolatingRasterItem;
@@ -67,7 +68,7 @@ public class LandUseItem implements InterpolatingRasterItem<LandUseItem>, Serial
 
 			// static land covers
 			if (!lcType.isConvertible()) { 
-				tiles.addConvertibleArea(totalArea); // Assumes land cover age is 0
+				tiles.addArea(LandProtectionType.UNAVAILABLE, totalArea); // Assumes land cover age is 0
 				continue;
 			}
 			// convertible land covers			
@@ -104,8 +105,8 @@ public class LandUseItem implements InterpolatingRasterItem<LandUseItem>, Serial
 				int minAge = (int) (ageGroup - 1) * AGE_GROUP_SIZE + 1;
 				int maxAge = minAge + (AGE_GROUP_SIZE - 1);
 				for (int a = minAge; a <= maxAge; a++) {
-					landCoverAreas.get(lcType).setConvertibleArea(a, unprotectedArea * prop);
-					landCoverAreas.get(lcType).setProtectedArea(a, protectedArea * prop);
+					landCoverAreas.get(lcType).setArea(LandProtectionType.CONVERTIBLE, a, unprotectedArea * prop);
+					landCoverAreas.get(lcType).setArea(LandProtectionType.PROTECTED, a, protectedArea * prop);
 				}
 			}
 		}
@@ -146,36 +147,36 @@ public class LandUseItem implements InterpolatingRasterItem<LandUseItem>, Serial
 		double unavailFromConvertibleNatural = Math.min(shortfall, convertibleNatural);
 		shortfall -= unavailFromConvertibleNatural;
 		if (unavailFromConvertibleNatural > 0) {
-			landCoverAreas.get(LandCoverType.NATURAL).addUnavailableArea(unavailFromConvertibleNatural);
-			landCoverAreas.get(LandCoverType.NATURAL).removeConvertibleArea(unavailFromConvertibleNatural);
+			landCoverAreas.get(LandCoverType.NATURAL).addArea(LandProtectionType.UNAVAILABLE, unavailFromConvertibleNatural);
+			landCoverAreas.get(LandCoverType.NATURAL).removeArea(LandProtectionType.CONVERTIBLE, unavailFromConvertibleNatural);
 		}
 		
 		double unavailFromProtectedNatural = Math.min(shortfall, protectedNatural);
 		shortfall -= unavailFromProtectedNatural;
 		if (unavailFromProtectedNatural > 0) {
-			landCoverAreas.get(LandCoverType.NATURAL).addUnavailableArea(unavailFromProtectedNatural);
-			landCoverAreas.get(LandCoverType.NATURAL).removeProtectedArea(unavailFromProtectedNatural);
+			landCoverAreas.get(LandCoverType.NATURAL).addArea(LandProtectionType.UNAVAILABLE, unavailFromProtectedNatural);
+			landCoverAreas.get(LandCoverType.NATURAL).removeArea(LandProtectionType.PROTECTED, unavailFromProtectedNatural);
 		}
 		
 		double unavailFromTimberF = Math.min(shortfall, convertibleTimberF);
 		shortfall -= unavailFromTimberF;
 		if (unavailFromTimberF > 0) {
-			landCoverAreas.get(LandCoverType.TIMBER_FOREST).addUnavailableArea(unavailFromTimberF);
-			landCoverAreas.get(LandCoverType.TIMBER_FOREST).removeConvertibleArea(unavailFromTimberF);
+			landCoverAreas.get(LandCoverType.TIMBER_FOREST).addArea(LandProtectionType.UNAVAILABLE, unavailFromTimberF);
+			landCoverAreas.get(LandCoverType.TIMBER_FOREST).removeArea(LandProtectionType.CONVERTIBLE, unavailFromTimberF);
 		}
 		
 		double unavailFromPasture = Math.min(shortfall, convertiblePasture);
 		shortfall -= unavailFromPasture;
 		if (unavailFromPasture > 0) {
-			landCoverAreas.get(LandCoverType.PASTURE).addUnavailableArea(unavailFromPasture);
-			landCoverAreas.get(LandCoverType.PASTURE).removeConvertibleArea(unavailFromPasture);
+			landCoverAreas.get(LandCoverType.PASTURE).addArea(LandProtectionType.UNAVAILABLE, unavailFromPasture);
+			landCoverAreas.get(LandCoverType.PASTURE).removeArea(LandProtectionType.CONVERTIBLE, unavailFromPasture);
 		}
 		
 		double unavailFromCropland = Math.min(shortfall, convertibleCropland);
 		shortfall -= unavailFromCropland;
 		if (unavailFromCropland > 0) {
-			landCoverAreas.get(LandCoverType.CROPLAND).addUnavailableArea(unavailFromCropland);
-			landCoverAreas.get(LandCoverType.CROPLAND).removeConvertibleArea(unavailFromCropland);
+			landCoverAreas.get(LandCoverType.CROPLAND).addArea(LandProtectionType.UNAVAILABLE, unavailFromCropland);
+			landCoverAreas.get(LandCoverType.CROPLAND).removeArea(LandProtectionType.CONVERTIBLE, unavailFromCropland);
 		}
 		
 		if (shortfall > 0) {
@@ -200,7 +201,7 @@ public class LandUseItem implements InterpolatingRasterItem<LandUseItem>, Serial
 	}
 	
 	public void setProtectedLandCoverArea(LandCoverType lcType, double area) {
-		landCoverAreas.get(lcType).setProtectedArea(0, area);
+		landCoverAreas.get(lcType).setArea(LandProtectionType.PROTECTED, 0, area);
 	}
 	
 	public double getProtectedFraction() {
@@ -209,13 +210,13 @@ public class LandUseItem implements InterpolatingRasterItem<LandUseItem>, Serial
 
 	public double getTotalProtectedArea() {
 		if(ModelConfig.PROTECTED_AREAS_ENABLED)
-			return landCoverAreas.values().stream().mapToDouble(o -> o.getTotalProtectedArea()).sum();
+			return landCoverAreas.values().stream().mapToDouble(o -> o.getTotalArea(LandProtectionType.PROTECTED)).sum();
 		else 
 			return 0.0;	
 	}
 	
 	public double getProtectedLandCoverArea(LandCoverType lcType) {
-		return landCoverAreas.get(lcType).getTotalProtectedArea();
+		return landCoverAreas.get(lcType).getTotalArea(LandProtectionType.PROTECTED);
 	}
 
 	public double getSuitableArea() {
@@ -244,8 +245,8 @@ public class LandUseItem implements InterpolatingRasterItem<LandUseItem>, Serial
 		LandCoverTile toTiles = landCoverAreas.get(toType);
 		LandCoverTile fromTiles = landCoverAreas.get(fromType);
 
-		fromTiles.removeConvertibleArea(area);	
-		toTiles.addConvertibleArea(area);
+		fromTiles.removeArea(LandProtectionType.CONVERTIBLE, area);	
+		toTiles.addArea(LandProtectionType.CONVERTIBLE, area);
    
         return area - areaMoved;
 	}
@@ -267,7 +268,7 @@ public class LandUseItem implements InterpolatingRasterItem<LandUseItem>, Serial
 		double landCover = (d < 0.0) ? 0.0 : d;
 		
 		landCoverAreas.get(c).removeAllArea();
-		landCoverAreas.get(c).addConvertibleArea(landCover);;
+		landCoverAreas.get(c).addArea(LandProtectionType.CONVERTIBLE, landCover);;
 	}
 	
 	public double getTotalLandCoverArea() {
@@ -289,13 +290,13 @@ public class LandUseItem implements InterpolatingRasterItem<LandUseItem>, Serial
 	public double getTotalConvertibleNaturalArea() {	
 		double unprotectedNatural = 0;
 		for (LandCoverType landType : LandCoverType.getNaturalTypes()) {
-			unprotectedNatural += landCoverAreas.get(landType).getTotalConvertibleArea();
+			unprotectedNatural += landCoverAreas.get(landType).getTotalArea(LandProtectionType.CONVERTIBLE);
 		}
 		return unprotectedNatural;
 	}
 	
 	public double getConvertibleLandCoverArea(LandCoverType c) {
-		return landCoverAreas.get(c).getTotalConvertibleArea();
+		return landCoverAreas.get(c).getTotalArea(LandProtectionType.CONVERTIBLE);
 	}
 	
 	
@@ -479,8 +480,8 @@ public class LandUseItem implements InterpolatingRasterItem<LandUseItem>, Serial
 	
 	public void doForestRotation(int rotationAge) {
 		LandCoverTile tiles = landCoverAreas.get(LandCoverType.TIMBER_FOREST);
-		for (int a=rotationAge; a<=tiles.getMaxAgeBin(); a++) {
-			tiles.resetAreaForAge(a);
+		for (int a=rotationAge; a<=LandCoverTile.getMaxAgeBin(); a++) {
+			tiles.resetAreaForAge(LandProtectionType.CONVERTIBLE, a);
 		}	
 	}
 	
@@ -532,20 +533,20 @@ public class LandUseItem implements InterpolatingRasterItem<LandUseItem>, Serial
 		
 		for (LandCoverType landCover : LandCoverType.values()) {
 			for (int age = 0; age <= LandCoverTile.getMaxAgeBin(); age++) {
-				Double from = fromItem.landCoverAreas.get(landCover).getConvertibleArea(age);
-				Double to = toItem.landCoverAreas.get(landCover).getConvertibleArea(age);
+				Double from = fromItem.landCoverAreas.get(landCover).getArea(LandProtectionType.CONVERTIBLE, age);
+				Double to = toItem.landCoverAreas.get(landCover).getArea(LandProtectionType.CONVERTIBLE, age);
 				Double d = Interpolator.interpolate(from, to, factor);
 				LandCoverTile tile = landCoverAreas.computeIfAbsent(landCover, k -> new LandCoverTile());
-				tile.setConvertibleArea(age, d);
+				tile.setArea(LandProtectionType.CONVERTIBLE, age, d);
 			}
 		}
 		
 		for (LandCoverType landCover : LandCoverType.values()) {
-			Double from = fromItem.landCoverAreas.get(landCover).getTotalProtectedArea();
-			Double to = toItem.landCoverAreas.get(landCover).getTotalProtectedArea();
+			Double from = fromItem.landCoverAreas.get(landCover).getTotalArea(LandProtectionType.PROTECTED);
+			Double to = toItem.landCoverAreas.get(landCover).getTotalArea(LandProtectionType.PROTECTED);
 			Double d = Interpolator.interpolate(from, to, factor);
 			LandCoverTile tile = landCoverAreas.computeIfAbsent(landCover, k -> new LandCoverTile());
-			tile.addProtectedArea(d);
+			tile.addArea(LandProtectionType.PROTECTED, d);
 		}
 	}
 	
@@ -586,8 +587,8 @@ public class LandUseItem implements InterpolatingRasterItem<LandUseItem>, Serial
 		Map<LandCoverType, Double> convertibleAreas = new HashMap<LandCoverType, Double>();
 		Map<LandCoverType, Double> protectedAreas = new HashMap<LandCoverType, Double>();
 		for (LandCoverType lcType : LandCoverType.values()) {
-			convertibleAreas.put(lcType, landCoverAreas.get(lcType).getTotalConvertibleArea());
-			protectedAreas.put(lcType, landCoverAreas.get(lcType).getTotalProtectedArea());
+			convertibleAreas.put(lcType, landCoverAreas.get(lcType).getTotalArea(LandProtectionType.CONVERTIBLE));
+			protectedAreas.put(lcType, landCoverAreas.get(lcType).getTotalArea(LandProtectionType.PROTECTED));
 		}
 		return "LandUseItem: [landCoverAreas=" + convertibleAreas + ", protectedArea=" + protectedAreas + "]";
 	}
diff --git a/src/ac/ed/lurg/landuse/LandUseSerializer.java b/src/ac/ed/lurg/landuse/LandUseSerializer.java
index 3b9cdb4e7277839b6bd79f08fbbc3584e4aece24..9cfd1e829fc5f7de4d066963edca86df9154bf76 100644
--- a/src/ac/ed/lurg/landuse/LandUseSerializer.java
+++ b/src/ac/ed/lurg/landuse/LandUseSerializer.java
@@ -29,6 +29,7 @@ import javax.xml.parsers.ParserConfigurationException;
 import ac.ed.lurg.ModelConfig;
 import ac.ed.lurg.types.CropType;
 import ac.ed.lurg.types.LandCoverType;
+import ac.ed.lurg.types.LandProtectionType;
 import ac.ed.lurg.utils.LogWriter;
 import ac.sac.raster.RasterKey;
 import ac.sac.raster.RasterSet;
@@ -149,7 +150,7 @@ public class LandUseSerializer {
 				
 				xmlWriter.writeStartElement("convertible");
 				for (int a = 0; a <= LandCoverTile.getMaxAgeBin(); a++) {
-					double area = tiles.getConvertibleArea(a);
+					double area = tiles.getArea(LandProtectionType.CONVERTIBLE, a);
 					if (area == 0) 
 						continue;
 					writeElement("X"+Integer.toString(a), area);
@@ -158,14 +159,14 @@ public class LandUseSerializer {
 				
 				xmlWriter.writeStartElement("protected");
 				for (int a = 0; a <= LandCoverTile.getMaxAgeBin(); a++) {
-					double area = tiles.getProtectedArea(a);
+					double area = tiles.getArea(LandProtectionType.PROTECTED, a);
 					if (area == 0) 
 						continue;
 					writeElement("X"+Integer.toString(a), area);
 				}
 				xmlWriter.writeEndElement();
 				
-				writeElement("unavailable", tiles.getUnavailableArea());
+				writeElement("unavailable", tiles.getTotalArea(LandProtectionType.UNAVAILABLE));
 				
 				xmlWriter.writeEndElement();
 			}
@@ -237,14 +238,14 @@ public class LandUseSerializer {
 							NodeList convElements = lcElement.getElementsByTagName("convertible").item(0).getChildNodes();
 							NodeList protElements = lcElement.getElementsByTagName("protected").item(0).getChildNodes();
 							double unavArea = Double.parseDouble(lcElement.getElementsByTagName("unavailable").item(0).getTextContent());
-							landCoverAreas.get(lcType).addUnavailableArea(unavArea);
+							landCoverAreas.get(lcType).setArea(LandProtectionType.UNAVAILABLE, 0, unavArea);
 							
 							for (int k = 0; k < convElements.getLength(); k++) {
 								Node areaNode = convElements.item(k);
 								int age = Integer.parseInt(areaNode.getNodeName().replace("X", ""));
 								//double area = Double.parseDouble(areaNode.getNodeValue());
 								double area = Double.parseDouble(areaNode.getChildNodes().item(0).getNodeValue());
-								landCoverAreas.get(lcType).setConvertibleArea(age, area);
+								landCoverAreas.get(lcType).setArea(LandProtectionType.CONVERTIBLE, age, area);
 							}
 							
 							for (int k = 0; k < protElements.getLength(); k++) {
@@ -252,7 +253,7 @@ public class LandUseSerializer {
 								int age = Integer.parseInt(areaNode.getNodeName().replace("X", ""));
 								//double area = Double.parseDouble(areaNode.getNodeValue());
 								double area = Double.parseDouble(areaNode.getChildNodes().item(0).getNodeValue());
-								landCoverAreas.get(lcType).setProtectedArea(age, area);
+								landCoverAreas.get(lcType).setArea(LandProtectionType.PROTECTED, age, area);
 							}
 						}
 					}	
diff --git a/src/ac/ed/lurg/types/LandProtectionType.java b/src/ac/ed/lurg/types/LandProtectionType.java
new file mode 100644
index 0000000000000000000000000000000000000000..4f68893e7d9df174a2c45c199890955245e1a6ec
--- /dev/null
+++ b/src/ac/ed/lurg/types/LandProtectionType.java
@@ -0,0 +1,44 @@
+package ac.ed.lurg.types;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import ac.ed.lurg.utils.LogWriter;
+
+public enum LandProtectionType {
+
+	CONVERTIBLE(1, "convertible"),
+	PROTECTED(2, "protected"),
+	UNAVAILABLE(3, "unavailable");
+	
+	private int id;
+	private String name;
+	
+	private LandProtectionType(int id, String name) {
+		this.id = id;
+		this.name = name;
+	}
+
+	public int getId() {
+		return id;
+	}
+
+	public String getName() {
+		return name;
+	}
+	
+	private static final Map<String, LandProtectionType> nameCache = new HashMap<String, LandProtectionType>();
+    static {
+        for (LandProtectionType c : values()) {
+        	nameCache.put(c.getName(), c);
+       }
+    }
+    
+	public static LandProtectionType getForName(String name) {
+		LandProtectionType type = nameCache.get(name);
+		if (type == null) {
+			LogWriter.printlnError("Can't find LandProtectionType for " + name);
+		}
+		return type;
+	}
+}