diff --git a/GAMS/IntExtOpt.gms b/GAMS/IntExtOpt.gms
index b6cd76f213b41e6827fac3c23c0b231872a292ac..ea7633f87f066438767b97df30803a5a4d549555 100644
--- a/GAMS/IntExtOpt.gms
+++ b/GAMS/IntExtOpt.gms
@@ -9,8 +9,8 @@
  SET feed_crop_less_pasture(feed_crop)                          / wheat, maize, rice, oilcrops, pulses, starchyRoots, fruitveg /;
  SET import_crop(all_types)   / monogastrics, ruminants,           wheat, maize, rice, oilcrops, pulses, starchyRoots, fruitveg, sugar, energycrops/;
 
- SET land_cover / cropland, pasture, timberForest, carbonForest, otherNatural /;
- SET wood_producing / timberForest, carbonForest, otherNatural /;
+ SET land_cover / cropland, pasture, timberForest, carbonForest, natural /;
+* SET wood_producing / timberForest, carbonForest, natural /;
  ALIAS (land_cover, land_cover_before);
  ALIAS (land_cover, land_cover_after);
 
@@ -140,9 +140,9 @@ $gdxin
        totalFeedDM
        total_cost                         total cost of domestic supply including net imports;
 
- POSITIVE VARIABLE cropArea, nonCropArea, fertI, irrigI, otherIntensity, ruminantFeed, monogastricFeed, importAmount, exportAmount,
+ POSITIVE VARIABLE cropArea, fertI, irrigI, otherIntensity, ruminantFeed, monogastricFeed, importAmount, exportAmount,
                    agriLandExpansion, cropIncrease, cropDecrease, pastureDecrease, pastureIncrease, totalFeedDM,
-                   woodHarvest, carbonFlux;
+                   landCoverArea, landCoverChange, woodHarvest, carbonFlux;
 
  EQUATIONS
        UNIT_COST_EQ(crop, location)                     cost per area
@@ -223,9 +223,6 @@ $gdxin
  PASTURE_IMPORT_CONSTRAINT .. importAmount('pasture') =E= 0;
  PASTURE_EXPORT_CONSTRAINT ..  exportAmount('pasture') =E= 0;
 
- MAX_NET_IMPORT_CONSTRAINT(import_crop) .. importAmount(import_crop) - exportAmount(import_crop) =L= maxNetImport(import_crop);
- MIN_NET_IMPORT_CONSTRAINT(import_crop) .. importAmount(import_crop) - exportAmount(import_crop) =G= minNetImport(import_crop);
-
  IRRIGATION_CONSTRAINT(location) .. irrigConstraint(location) * suitableLandArea(location) * (1.0 - unhandledCropRate) =G= sum(crop, irrigMaxRate(crop, location) * irrigI(crop, location) * cropArea(crop, location));
 
  AGRI_LAND_EXPANSION_CALC(location) .. agriLandExpansion(location) =G= sum(crop, cropArea(crop, location) - previousCropArea(crop, location));
@@ -236,20 +233,20 @@ $gdxin
  PASTURE_DECREASE_CONV_CALC(location) .. pastureDecrease(location) =G= -(cropArea('pasture', location) - previousCropArea('pasture', location));
  PASTURE_TOTAL_CHANGE_CONSTRAINT(location) .. pastureIncrease(location) -pastureDecrease(location) =G= cropArea('pasture', location) - previousCropArea('pasture', location);
 
- CROPLAND_LAND_COVER_CAL(location) .. sum(land_cover, landCoverArea('cropland', location)) =E= sum(crop_less_pasture, cropArea(crop, location)) / (1.0 - unhandledCropRate);
+ CROPLAND_LAND_COVER_CALC(location) .. landCoverArea('cropland', location) =E= sum(crop_less_pasture, cropArea(crop_less_pasture, location)) / (1.0 - unhandledCropRate);
 
- PASTURE_LAND_COVER_CAL(location) .. sum(land_cover, landCoverArea('pasture', location)) =E= cropArea('pasture', location);
+ PASTURE_LAND_COVER_CALC(location) .. landCoverArea('pasture', location) =E= cropArea('pasture', location);
 
 * MINIMUM_LAND_COVER_CONSTRAINT(location, land_cover) .. landCoverArea(land_cover, location)) =G= minimumLandCover(land_cover_after, location);
 
- LAND_COVER_CHANGE_CALC(land_cover, location) .. landCoverArea(land_cover, location) =E= previousLandCover(land_cover, location) +
-                     sum(land_cover_before, lcChange(land_cover_before, land_cover, location)) - sum(land_cover_after, lcChange(land_cover, land_cover_after, location));
+ LAND_COVER_CHANGE_CALC(land_cover, location) .. landCoverArea(land_cover, location) =E= previousLandCoverArea(land_cover, location) +
+                     sum(land_cover_before, landCoverChange(land_cover_before, land_cover, location)) - sum(land_cover_after, landCoverChange(land_cover, land_cover_after, location));
 
- LAND_COVER_CHANGE_CONSTRAINT(land_cover, location) .. sum(land_cover_after, landCoverChange(land_cover, land_cover_after, location)) =L= previousLandCover(land_cover, location);
+ LAND_COVER_CHANGE_CONSTRAINT(land_cover, location) .. sum(land_cover_after, landCoverChange(land_cover, land_cover_after, location)) =L= previousLandCoverArea(land_cover, location);
 
 * TOTAL_LAND_COVER_CONSTRAINT(location) .. sum(land_cover, landCoverArea(land_cover, location)) =E= suitableArea(location);
 
- WOOD_HARVEST_CALC(location) .. woodHarvest(location) =E= sum((land_cover_before, land_cover_after, location), landCoverChange(land_cover_before, land_cover_after, location) * woodYield(land_cover_before, land_cover_after, location));
+ WOOD_HARVEST_CALC(location) .. woodHarvest(location) =E= sum((land_cover_before, land_cover_after), landCoverChange(land_cover_before, land_cover_after, location) * woodYield(land_cover_before, land_cover_after, location));
 
  CARBON_FLUX_CALC(location) .. carbonFlux(location) =E= sum((land_cover_before, land_cover_after), landCoverChange(land_cover_before, land_cover_after, location) * carbonFluxRate(land_cover_before, land_cover_after, location));
 
diff --git a/src/ac/ed/lurg/ModelConfig.java b/src/ac/ed/lurg/ModelConfig.java
index 859fc7e0f1caedb95fc34a9e0f2918e6ed27ed9c..8703013576acb0a8e3fe121ed5e10e19c2710b55 100755
--- a/src/ac/ed/lurg/ModelConfig.java
+++ b/src/ac/ed/lurg/ModelConfig.java
@@ -18,7 +18,8 @@ public class ModelConfig {
 	
 	private Properties configFile;
 	private static ModelConfig modelConfig;
-	public static final String CONFIG_FILE = System.getProperty("CONFIG_FILE");
+	//public static final String CONFIG_FILE = System.getProperty("CONFIG_FILE");
+	public static final String CONFIG_FILE = "C:\\Users\\Bart\\git\\plumv2\\debug_config.properties";
 	
 	private static StringTabularReader shocksReader;
 	
@@ -244,8 +245,11 @@ public class ModelConfig {
 	public static final String YIELDSHOCKS_PARAMETER_FILE = getProperty("YIELDSHOCKS_PARAMETER_FILE", OUTPUT_DIR + File.separator+ "yieldshocks.csv");
 	public static final String PRICESHOCKS_PARAMETER_FILE = getProperty("PRICESHOCKS_PARAMETER_FILE", OUTPUT_DIR + File.separator+ "priceshocks.csv");
 	public static final String EXPORT_RESTRICTIONS_FILE = getProperty("EXPORT_RESTRICTIONS_FILE", OUTPUT_DIR + File.separator+ "exportrestictions.csv");
-	public static final String CARBON_FLUX_FILE = SPATIAL_DATA_DIR + File.separator + "carbon_flux_";
-	public static final String WOOD_YIELD_FILE = SPATIAL_DATA_DIR + File.separator + "wood_yield_";
+	
+	// Wood/carbon data
+	public static final String FOREST_DIR = SPATIAL_DATA_DIR + File.separator + "forestry";
+	//public static final String CARBON_FLUX_FILE = FOREST_DIR + File.separator + "carbon_flux_";
+	//public static final String WOOD_YIELD_FILE = FOREST_DIR + File.separator + "wood_yield_";
 
 	// Output
 	public static final String LAND_COVER_OUTPUT_FILE = OUTPUT_DIR + File.separator + "lc.txt";
diff --git a/src/ac/ed/lurg/ModelMain.java b/src/ac/ed/lurg/ModelMain.java
index e8d6d12d0805f86337dc54f3cdeb09846dd314a1..e01d8ac4f9a04483df989dcf3d4951d88ad8b396 100644
--- a/src/ac/ed/lurg/ModelMain.java
+++ b/src/ac/ed/lurg/ModelMain.java
@@ -48,7 +48,6 @@ import ac.ed.lurg.output.LandUseOutputer;
 import ac.ed.lurg.output.LpjgOutputer;
 import ac.ed.lurg.types.CommodityType;
 import ac.ed.lurg.types.CropType;
-import ac.ed.lurg.types.GamsLandCoverType;
 import ac.ed.lurg.types.LandCoverType;
 import ac.ed.lurg.utils.FileWriterHelper;
 import ac.ed.lurg.utils.LogWriter;
@@ -142,6 +141,8 @@ public class ModelMain {
 		double gen2Increase = (gen2EcDDemand>previousGen2EcDDemand) ? gen2EcDDemand - previousGen2EcDDemand : 0.0;
 		
 		CarbonFluxRasterSet currentCarbonFluxData = getCarbonFluxData(timestep);
+		LogWriter.println("Carbon flux data read");
+		LogWriter.println("Data: " + currentCarbonFluxData.get(1, 1).getCarbonFluxes());
 		WoodYieldRasterSet currentWoodYieldData = getWoodYieldData(timestep);
 		
 		countryAgents.determineProductionForAll(timestep, yieldSurfaces, currentIrrigationData, gen2Increase, currentCarbonFluxData, currentWoodYieldData);
@@ -187,7 +188,31 @@ public class ModelMain {
 			LogWriter.print(e);
 		}
 	}
+	
+/*
+	private void writeGamsLandCoverFile(Timestep timestep, RasterSet<LandUseItem> landUseRaster) {
+		try {
+			StringBuffer sbHeadings = new StringBuffer("Year,Cropland,Pasture,timberForest,carbonForest,Natural");
+			BufferedWriter outputFile = FileWriterHelper.getFileWriter(timestep, ModelConfig.LAND_COVER_OUTPUT_FILE, sbHeadings.toString());
+
+			StringBuffer sbData = new StringBuffer();
+			sbData.append(String.format("%d,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f", timestep.getYear(),
+					LandUseItem.getTotalLandCover(landUseRaster.values(), LandCoverType.CROPLAND),
+					LandUseItem.getTotalLandCover(landUseRaster.values(), LandCoverType.PASTURE),
+					LandUseItem.getTotalLandCover(landUseRaster.values(), LandCoverType.TIMBER_FOREST),
+					LandUseItem.getTotalLandCover(landUseRaster.values(), LandCoverType.CARBON_FOREST),
+					LandUseItem.getTotalLandCover(landUseRaster.values(), LandCoverType.NATURAL)
+					));
+						
 
+			outputFile.write(sbData.toString());
+			outputFile.newLine();
+			outputFile.close();
+		} catch (IOException e) {
+			LogWriter.print(e);
+		}
+	}
+*/
 	private void writeGlobalMarketFile(Timestep timestep) {
 		try {
 			BufferedWriter outputFile = FileWriterHelper.getFileWriter(timestep, ModelConfig.PRICES_OUTPUT_FILE, "Year,Crop,Imports (Mt),Exports (Mt),New export price, Stock Levels (Mt)");
@@ -610,11 +635,9 @@ public class ModelMain {
 		
 		// Set initial GAMS land covers
 		for (LandUseItem item : landUseRaster.values()) {
-			item.setGamsLandCoverArea(GamsLandCoverType.CROPLAND, item.getLandCoverArea(LandCoverType.CROPLAND));
-			item.setGamsLandCoverArea(GamsLandCoverType.PASTURE, item.getLandCoverArea(LandCoverType.PASTURE));
-			item.setGamsLandCoverArea(GamsLandCoverType.TIMBER_FOREST, item.getLandCoverArea(LandCoverType.MANAGED_FOREST));
-			item.setGamsLandCoverArea(GamsLandCoverType.CARBON_FOREST, 0.0);
-			item.setGamsLandCoverArea(GamsLandCoverType.OTHER_NATURAL, item.getLandCoverArea(LandCoverType.OTHER_NATURAL) + item.getLandCoverArea(LandCoverType.UNMANAGED_FOREST));
+			item.setLandCoverArea(LandCoverType.TIMBER_FOREST, item.getLandCoverArea(LandCoverType.MANAGED_FOREST));
+			item.setLandCoverArea(LandCoverType.CARBON_FOREST, 0.0);
+			item.setLandCoverArea(LandCoverType.NATURAL, item.getLandCoverArea(LandCoverType.OTHER_NATURAL) + item.getLandCoverArea(LandCoverType.UNMANAGED_FOREST));
 		}
 
 		return landUseRaster;
@@ -640,14 +663,14 @@ public class ModelMain {
 	/** Get carbon flux data */
 	private CarbonFluxRasterSet getCarbonFluxData(Timestep timestep) {
 		CarbonFluxRasterSet carbonFluxData = new CarbonFluxRasterSet(desiredProjection);
-		new CarbonFluxReader(carbonFluxData).getRasterDataFromFile(ModelConfig.CARBON_FLUX_FILE + timestep.getYieldYear() + ".out");
+		new CarbonFluxReader(carbonFluxData).getRasterDataFromFile(timestep.getYearSubDir(ModelConfig.FOREST_DIR) + File.separator + "cflux_net.out");
 		return carbonFluxData;
 	}
 	
 	/** Get carbon wood yield data */
 	private WoodYieldRasterSet getWoodYieldData(Timestep timestep) {
 		WoodYieldRasterSet woodYieldData = new WoodYieldRasterSet(desiredProjection);
-		new WoodYieldReader(woodYieldData).getRasterDataFromFile(ModelConfig.WOOD_YIELD_FILE + timestep.getYieldYear() + ".out");
+		new WoodYieldReader(woodYieldData).getRasterDataFromFile(timestep.getYearSubDir(ModelConfig.FOREST_DIR) + File.separator + "wood_yield.out");
 		return woodYieldData;
 	}
 
diff --git a/src/ac/ed/lurg/country/gams/GamsLocationOptimiser.java b/src/ac/ed/lurg/country/gams/GamsLocationOptimiser.java
index c13a265d968e52ea6a3bf838405e020121acc6d6..616dc301fae2324dda673c220955bb110009a29f 100644
--- a/src/ac/ed/lurg/country/gams/GamsLocationOptimiser.java
+++ b/src/ac/ed/lurg/country/gams/GamsLocationOptimiser.java
@@ -31,7 +31,6 @@ import ac.ed.lurg.landuse.LandUseItem;
 import ac.ed.lurg.landuse.WoodYieldItem;
 import ac.ed.lurg.types.CommodityType;
 import ac.ed.lurg.types.CropType;
-import ac.ed.lurg.types.GamsLandCoverType;
 import ac.ed.lurg.types.LandCoverType;
 import ac.ed.lurg.types.Parameter;
 import ac.ed.lurg.types.YieldType;
@@ -71,14 +70,16 @@ public class GamsLocationOptimiser {
 		opt.defines("gdxincname", inDB.getName());
 
 		long startTime = System.currentTimeMillis();
-		gamsJob.run(opt, inDB);
+		gamsJob.run(opt, inDB);	
 		
 		if (ModelConfig.CLEANUP_GAMS_DIR) 
 			cleanup(ws.workingDirectory());
 		
 		LogWriter.println("Took " + (System.currentTimeMillis() - startTime) + " ms to run");
+		
 
 		return handleResults(gamsJob.OutDB());
+		
 	}
 
 	private void setupInDB(GAMSDatabase inDB) {
@@ -168,11 +169,11 @@ public class GamsLocationOptimiser {
 			}
 			
 			// Previous land covers
-			for (GamsLandCoverType lc : GamsLandCoverType.values()) {
+			for (LandCoverType lc : LandCoverType.getGamsTypes()) {
 				Vector<String> v = new Vector<String>();
 				v.add(lc.getName());
 				v.add(locString);
-				setGamsParamValue(prevLandCoverP.addRecord(v), landUseItem.getGamsLandCoverArea(lc), 3);
+				setGamsParamValue(prevLandCoverP.addRecord(v), landUseItem.getLandCoverArea(lc), 3);
 			}
 		
 		}
@@ -348,8 +349,8 @@ public class GamsLocationOptimiser {
 			String locString = Integer.toString(locationId);
 			CarbonFluxItem cFlux = entry.getValue();
 			
-			for (GamsLandCoverType prevLC : GamsLandCoverType.values()) {
-				for (GamsLandCoverType newLC : GamsLandCoverType.values()) {
+			for (LandCoverType prevLC : LandCoverType.getGamsTypes()) {
+				for (LandCoverType newLC : LandCoverType.getGamsTypes()) {
 					Vector<String> v = new Vector<String>();
 					v.add(prevLC.getName());
 					v.add(newLC.getName());
@@ -368,8 +369,8 @@ public class GamsLocationOptimiser {
 			String locString = Integer.toString(locationId);
 			WoodYieldItem wYield = entry.getValue();
 			
-			for (GamsLandCoverType prevLC : GamsLandCoverType.values()) {
-				for (GamsLandCoverType newLC : GamsLandCoverType.values()) {
+			for (LandCoverType prevLC : LandCoverType.getGamsTypes()) {
+				for (LandCoverType newLC : LandCoverType.getGamsTypes()) {
 					Vector<String> v = new Vector<String>();
 					v.add(prevLC.getName());
 					v.add(newLC.getName());
@@ -508,10 +509,10 @@ public class GamsLocationOptimiser {
 				totalCropArea+totalPastureArea, totalCropArea, totalPastureArea));
 		
 		
-		// Land cover areas
+		// Land cover areas (exc. cropland and pasture)
 		GAMSVariable varLandCoverArea = outDB.getVariable("landCoverArea");
 		double landCoverArea;
-		
+				
 		for (GAMSVariableRecord rec : varLandCoverArea) {
 			String lc = rec.getKeys()[0];
 			String locationName = rec.getKeys()[1];
@@ -521,11 +522,44 @@ public class GamsLocationOptimiser {
 			
 			LandUseItem landUseItem = landUses.lazyGet(locId);
 			
-			landUseItem.setGamsLandCoverArea(GamsLandCoverType.getForName(lc), landCoverArea);
+			switch(lc) {
+			case "forestT":
+				landUseItem.setLandCoverArea(LandCoverType.TIMBER_FOREST, landCoverArea);
+				break;
+			case "forestC":
+				landUseItem.setLandCoverArea(LandCoverType.CARBON_FOREST, landCoverArea);
+				break;
+			case "natural":
+				landUseItem.setLandCoverArea(LandCoverType.NATURAL, landCoverArea);
+				break;
+			}
+							
+		}
+		
+		// Land cover change
+		GAMSVariable varLandCoverChange = outDB.getVariable("landCoverChange");
+		
+		Map<Integer, Map<LandCoverType, Map<LandCoverType, Double>>> landCoverChange = new HashMap<Integer, Map<LandCoverType, Map<LandCoverType, Double>>>();
+		
+		for (GAMSVariableRecord rec : varLandCoverChange) {
+			String fromLC = rec.getKeys()[0];
+			String toLC = rec.getKeys()[1];
+			String locationName = rec.getKeys()[2];
+			int locId = Integer.parseInt(locationName);
+			
+			double change = rec.getLevel();
+			
+			Map<LandCoverType, Double> toMap = new HashMap<LandCoverType, Double>();
+			toMap.put(LandCoverType.getForName(toLC), change);
+			
+			Map<LandCoverType, Map<LandCoverType, Double>> fromMap = new HashMap<LandCoverType, Map<LandCoverType, Double>>();
+			fromMap.put(LandCoverType.getForName(fromLC), toMap);
+			
+			landCoverChange.put(locId, fromMap);
 			
 		}
 
-		GamsLocationOutput results = new GamsLocationOutput(modelStatus, landUses, cropUsageData);
+		GamsLocationOutput results = new GamsLocationOutput(modelStatus, landUses, cropUsageData, landCoverChange);
 		return results;
 	}
 
diff --git a/src/ac/ed/lurg/country/gams/GamsLocationOutput.java b/src/ac/ed/lurg/country/gams/GamsLocationOutput.java
index 48c7ccfd08c2d834ee673a7efeab75c45d7232fe..f750626770b92f66dbe035c9fafb10ca21429431 100644
--- a/src/ac/ed/lurg/country/gams/GamsLocationOutput.java
+++ b/src/ac/ed/lurg/country/gams/GamsLocationOutput.java
@@ -1,5 +1,6 @@
 package ac.ed.lurg.country.gams;
 
+import java.util.HashMap;
 import java.util.Map;
 
 import com.gams.api.GAMSGlobals.ModelStat;
@@ -7,20 +8,24 @@ import com.gams.api.GAMSGlobals.ModelStat;
 import ac.ed.lurg.landuse.CropUsageData;
 import ac.ed.lurg.landuse.LandUseItem;
 import ac.ed.lurg.types.CropType;
+import ac.ed.lurg.types.LandCoverType;
 
 public class GamsLocationOutput {
 	ModelStat status;
 	
 	Map<Integer, LandUseItem> landUses;  // data mapped from id (not raster)
 	private Map<CropType, CropUsageData> cropUsageData;
+	Map<Integer, Map<LandCoverType, Map<LandCoverType, Double>>> landCoverChange = new HashMap<Integer, Map<LandCoverType, Map<LandCoverType, Double>>>();
 	
 	public GamsLocationOutput(ModelStat status, 
 			Map<Integer, LandUseItem> landUses, 
-			Map<CropType, CropUsageData> cropUsageData) {
+			Map<CropType, CropUsageData> cropUsageData,
+			Map<Integer, Map<LandCoverType, Map<LandCoverType, Double>>> landCoverChange) {
 		super();
 		this.status = status;
 		this.landUses = landUses;
 		this.cropUsageData = cropUsageData;
+		this.landCoverChange = landCoverChange;
 	}
 	
 	public ModelStat getStatus() {
@@ -33,4 +38,8 @@ public class GamsLocationOutput {
 	public Map<CropType, CropUsageData> getCommoditiesData() {
 		return cropUsageData;
 	}
+	
+	public Map<Integer, Map<LandCoverType, Map<LandCoverType, Double>>> getLandCoverChange() {
+		return landCoverChange;
+	}
 }
diff --git a/src/ac/ed/lurg/country/gams/GamsRasterOptimiser.java b/src/ac/ed/lurg/country/gams/GamsRasterOptimiser.java
index 23511eec9008d441632e20f371bad387550831b8..f5f18ff404be173ab91daeb38c88c4d222bbbff3 100644
--- a/src/ac/ed/lurg/country/gams/GamsRasterOptimiser.java
+++ b/src/ac/ed/lurg/country/gams/GamsRasterOptimiser.java
@@ -5,14 +5,12 @@ import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
 
-import ac.ed.lurg.ModelConfig;
 import ac.ed.lurg.landuse.CarbonFluxItem;
 import ac.ed.lurg.landuse.Intensity;
 import ac.ed.lurg.landuse.IrrigationItem;
 import ac.ed.lurg.landuse.LandUseItem;
 import ac.ed.lurg.landuse.WoodYieldItem;
 import ac.ed.lurg.types.CropType;
-import ac.ed.lurg.types.GamsLandCoverType;
 import ac.ed.lurg.types.LandCoverType;
 import ac.ed.lurg.types.YieldType;
 import ac.ed.lurg.utils.LazyTreeMap;
@@ -100,7 +98,7 @@ public class GamsRasterOptimiser {
 		for (Map.Entry<Integer, LandUseItem> entry : gamsOutput.getLandUses().entrySet()) {
 			Integer locId = entry.getKey();
 			LandUseItem newLandUseAggItem = entry.getValue();
-			LandUseItem prevLandUseAggItem = prevAreasAgg.get(locId);
+//			LandUseItem prevLandUseAggItem = prevAreasAgg.get(locId);
 
 			Set<RasterKey> keys = new HashSet<RasterKey>();
 			for (Entry<RasterKey, IntegerRasterItem> mapEntry : mapping.entrySet()) {
@@ -109,7 +107,36 @@ public class GamsRasterOptimiser {
 				if (iri != null && locId == iri.getInt())
 					keys.add(mapEntry.getKey());
 			}
-
+			
+			// Allocate land cover change to grid cells
+			// pasture, cropland, carbonForest, timberForest, natural
+			Map<Integer, Map<LandCoverType, Map<LandCoverType, Double>>> landCoverChange = gamsOutput.getLandCoverChange();
+					
+			for (LandCoverType fromLC : LandCoverType.getGamsTypes()) {
+				for (LandCoverType toLC : LandCoverType.getGamsTypes()) {
+					double change = landCoverChange.get(locId).get(fromLC).get(toLC);
+					allocAllLandCropsTop(newLandUseRaster, keys, toLC, fromLC, change, locId);				
+				}
+			}
+			
+			// Allocate derived land cover areas
+			// managedForest, unmanagedForest, otherNatural
+			for (RasterKey key : keys) {
+				LandUseItem newLandUseItem = newLandUseRaster.get(key);
+				LandUseItem prevLandUseItem = rasterInputData.getPreviousLandUses().get(key);			
+				
+				if (newLandUseItem != null) {
+					newLandUseItem.setLandCoverArea(LandCoverType.MANAGED_FOREST, newLandUseItem.getLandCoverArea(LandCoverType.TIMBER_FOREST) + newLandUseItem.getLandCoverArea(LandCoverType.CARBON_FOREST));
+					
+					double prevUnmanagedForest = prevLandUseItem.getLandCoverArea(LandCoverType.UNMANAGED_FOREST);
+					double prevOtherNatural = prevLandUseItem.getLandCoverArea(LandCoverType.OTHER_NATURAL);
+					double prevUnmanagedForestToNaturalProp = (prevOtherNatural > 0 || prevUnmanagedForest > 0) ? prevUnmanagedForest / (prevOtherNatural + prevUnmanagedForest) : 0.5;
+					newLandUseItem.setLandCoverArea(LandCoverType.UNMANAGED_FOREST, newLandUseItem.getLandCoverArea(LandCoverType.NATURAL) * prevUnmanagedForestToNaturalProp);
+					newLandUseItem.setLandCoverArea(LandCoverType.OTHER_NATURAL, newLandUseItem.getLandCoverArea(LandCoverType.NATURAL) * (1 - prevUnmanagedForestToNaturalProp));			
+				
+				}
+			}
+/*
 			double gamsPastureChange = newLandUseAggItem.getLandCoverArea(LandCoverType.PASTURE) - prevLandUseAggItem.getLandCoverArea(LandCoverType.PASTURE);
 			double gamsCroplandChange = newLandUseAggItem.getLandCoverArea(LandCoverType.CROPLAND) - prevLandUseAggItem.getLandCoverArea(LandCoverType.CROPLAND);
 			RasterSet<LandUseItem> landUseItemsForLocation = newLandUseRaster.createSubsetForKeys(keys);
@@ -185,7 +212,7 @@ public class GamsRasterOptimiser {
 
 			double totalPastureChange = protectedAreasPastureChange + gamsPastureChange;
 			double totalCroplandChange = protectedAreasCroplandChange + gamsCroplandChange;
-
+			
 			double pastureFromCrop = 0;
 			double pastureFromNatural = 0;
 			double cropFromNatural = 0;
@@ -230,7 +257,7 @@ public class GamsRasterOptimiser {
 			allocAllLandCropsTop(newLandUseRaster, keys, LandCoverType.CROPLAND, LandCoverType.OTHER_NATURAL, cropFromNatural * (1-prevForestToNaturalFraction), locId);
 
 			if (DEBUG) checkedTotalAreas(landUseItemsForLocation, locId + " after");
-
+*/
 			for (RasterKey key : keys) {
 				LandUseItem newLandUseItem = newLandUseRaster.get(key);
 				if (newLandUseItem != null) {
@@ -241,48 +268,16 @@ public class GamsRasterOptimiser {
 
 				}
 			}
-		}
-		
-		return newLandUseRaster;
-	}
-/*
-	private void allocGamsLandCovers(RasterSet<LandUseItem> newLandUseRaster, Set<RasterKey> keys, GamsLandCoverType toLC, GamsLandCoverType fromLC, double change) {
-		GamsLandCoverType toType = toLC;
-		GamsLandCoverType fromType = fromLC;
+			
 
-		// reverse direction if negative
-		if (change < 0) {
-			change = -change;
-			toType = fromLC;
-			fromType = toLC;
 		}
 		
-		double totalShortfall = 0;
-		Set<RasterKey> keysWithSpace = new HashSet<RasterKey>();
-		double totalUnprotectedLC = 0;
-		
-		for (RasterKey key : keys) {
-			LandUseItem newLandUseItem = newLandUseRaster.get(key);
-			totalUnprotectedLC += newLandUseItem.getUnprotectedLandCoverArea(fromType);
-		}
 
-		for (RasterKey key : keys) {
-			//if (DEBUG) LogWriter.println("  Processing raster key " + key);
-			LandUseItem newLandUseItem = newLandUseRaster.get(key);
-
-			if (newLandUseItem!=null) {
-				double cellChange = (fromType.isProtectable() && totalUnprotectedLC > 0) ? change * newLandUseItem.getUnprotectedLandCoverArea(fromType)/totalUnprotectedLC : change / keys.size();
-				double shortfall = newLandUseItem.moveAreas(toType, fromType, cellChange);
-				if (shortfall == 0)
-					keysWithSpace.add(key);
-				else
-					totalShortfall += shortfall;
-			}
-		}
 		
 		
+
+		return newLandUseRaster;
 	}
-*/
 
 	private void allocAllLandCropsTop(RasterSet<LandUseItem> newLandUseRaster, Set<RasterKey> keys, LandCoverType toLC, LandCoverType fromLC, double change, Integer locId) {
 		LandCoverType toType = toLC;
@@ -459,13 +454,25 @@ public class GamsRasterOptimiser {
 				}
 				
 				// Aggregate carbon fluxes and wood yields
-				for (GamsLandCoverType prevLC : GamsLandCoverType.values()) {
-					for (GamsLandCoverType newLC : GamsLandCoverType.values()) {
-						aggCFlux.setCarbonFlux(prevLC, newLC, aggregateMean(aggCFlux.getCarbonFlux(prevLC, newLC), suitableAreaSoFar, 
-								carbonFluxItem.getCarbonFlux(prevLC, newLC), suitableAreaThisTime));
+				for (LandCoverType prevLC : LandCoverType.getGamsTypes()) {
+					for (LandCoverType newLC : LandCoverType.getGamsTypes()) {
+						
+						if (!aggCFlux.checkForKeys(prevLC, newLC)) { // if not seen yet
+							//LogWriter.println("prevLC: " + prevLC + ", newLC: " + newLC);
+							//LogWriter.println("Data: " +  carbonFluxItem.getCarbonFluxes());
+							aggCFlux.setCarbonFlux(prevLC, newLC, carbonFluxItem.getCarbonFlux(prevLC, newLC));
+						} else {
+							aggCFlux.setCarbonFlux(prevLC, newLC, aggregateMean(aggCFlux.getCarbonFlux(prevLC, newLC), suitableAreaSoFar, 
+									carbonFluxItem.getCarbonFlux(prevLC, newLC), suitableAreaThisTime));
+						}
+						
+						if (!aggWYield.checkForKeys(prevLC, newLC)) {
+							aggWYield.setWoodYield(prevLC, newLC, woodYieldItem.getWoodYield(prevLC, newLC));
+						} else {
+							aggWYield.setWoodYield(prevLC, newLC, aggregateMean(aggWYield.getWoodYield(prevLC, newLC), suitableAreaSoFar, 
+									woodYieldItem.getWoodYield(prevLC, newLC), suitableAreaThisTime));
+						}
 						
-						aggWYield.setWoodYield(prevLC, newLC, aggregateMean(aggWYield.getWoodYield(prevLC, newLC), suitableAreaSoFar, 
-								woodYieldItem.getWoodYield(prevLC, newLC), suitableAreaThisTime));
 					}
 				}
 
@@ -532,12 +539,14 @@ public class GamsRasterOptimiser {
 					aggLandUse.setLandCoverArea(landType, areaSoFar + areaThisTime);
 				}
 				
+				/*
 				// Gams land cover areas
 				for (GamsLandCoverType landType : GamsLandCoverType.values()) {
 					double areaThisTime = landUseItem.getGamsLandCoverArea(landType);
 					double areaSoFar = aggLandUse.getGamsLandCoverArea(landType);
 					aggLandUse.setGamsLandCoverArea(landType, areaSoFar + areaThisTime);
 				}
+				*/
 			}
 		}		
 
diff --git a/src/ac/ed/lurg/landuse/CarbonFluxItem.java b/src/ac/ed/lurg/landuse/CarbonFluxItem.java
index 4aa1ae4187f4333f4373486f27659a72a6a14672..ce7452d61ef1f98bdc2219cbe10043514e9e9eef 100644
--- a/src/ac/ed/lurg/landuse/CarbonFluxItem.java
+++ b/src/ac/ed/lurg/landuse/CarbonFluxItem.java
@@ -4,19 +4,40 @@ import ac.sac.raster.RasterItem;
 import java.util.HashMap;
 import java.util.Map;
 
-import ac.ed.lurg.types.GamsLandCoverType;
+import ac.ed.lurg.types.LandCoverType;
 
 public class CarbonFluxItem implements RasterItem {
-	Map<GamsLandCoverType, Map<GamsLandCoverType, Double>> carbonFluxes = new HashMap<GamsLandCoverType, Map<GamsLandCoverType, Double>>(); 
+	Map<LandCoverType, Map<LandCoverType, Double>> carbonFluxes = new HashMap<LandCoverType, Map<LandCoverType, Double>>(); 
 	
-	public void setCarbonFlux(GamsLandCoverType previousLandCover, GamsLandCoverType newLandCover, double carbonFlux) {
-		Map<GamsLandCoverType, Double> cfMap = new HashMap<GamsLandCoverType, Double>();
-		cfMap.put(newLandCover, carbonFlux);		
-		carbonFluxes.put(previousLandCover, cfMap);
+	public void setCarbonFlux(LandCoverType previousLandCover, LandCoverType newLandCover, double carbonFlux) {
+		
+		if (carbonFluxes.containsKey(previousLandCover)) {
+			carbonFluxes.get(previousLandCover).put(newLandCover, carbonFlux);
+		} else {
+			Map<LandCoverType, Double> cfMap = new HashMap<LandCoverType, Double>();
+			cfMap.put(newLandCover, carbonFlux);
+			carbonFluxes.put(previousLandCover, cfMap);
+		}
 	}
 	
-	public Double getCarbonFlux(GamsLandCoverType previousLandCover, GamsLandCoverType newLandCover) {
+	public double getCarbonFlux(LandCoverType previousLandCover, LandCoverType newLandCover) {
 		return carbonFluxes.get(previousLandCover).get(newLandCover);
 	}
+	
+	public boolean checkForKeys(LandCoverType previousLandCover, LandCoverType newLandCover) {
+		if (carbonFluxes.containsKey(previousLandCover)) {
+			if (carbonFluxes.get(previousLandCover).containsKey(newLandCover)) {
+				return true;
+			} else {
+				return false;
+			}
+		} else {
+			return false;
+		}
+	}
+	
+	public Map<LandCoverType, Map<LandCoverType, Double>> getCarbonFluxes() {
+		return carbonFluxes;
+	}
 
 }
diff --git a/src/ac/ed/lurg/landuse/CarbonFluxReader.java b/src/ac/ed/lurg/landuse/CarbonFluxReader.java
index d5d1087d1e3d067888d4f6bb3e0ef68233644745..b79d5e933bca64cd0d6c20ff0ee6d02b12f17ce8 100644
--- a/src/ac/ed/lurg/landuse/CarbonFluxReader.java
+++ b/src/ac/ed/lurg/landuse/CarbonFluxReader.java
@@ -2,14 +2,14 @@ package ac.ed.lurg.landuse;
 
 import java.util.Map;
 
-import ac.ed.lurg.types.GamsLandCoverType;
+import ac.ed.lurg.types.LandCoverType;
 import ac.sac.raster.AbstractTabularRasterReader;
 import ac.sac.raster.RasterKey;
 import ac.sac.raster.RasterSet;
 
 public class CarbonFluxReader extends AbstractTabularRasterReader<CarbonFluxItem> {
 
-	private static final int MIN_COLS = 18;
+	private static final int MIN_COLS = 27;
 	
 	public CarbonFluxReader(RasterSet<CarbonFluxItem> carbonFluxes) {
 		super("[ |\t]+", MIN_COLS, carbonFluxes);
@@ -17,30 +17,35 @@ public class CarbonFluxReader extends AbstractTabularRasterReader<CarbonFluxItem
 	
 	@Override
 	protected void setData(RasterKey key, CarbonFluxItem item, Map<String, Double> rowValues) {
-		item.setCarbonFlux(GamsLandCoverType.CROPLAND, GamsLandCoverType.OTHER_NATURAL, getValueForCol(rowValues, "crop_to_ntrl"));
-		item.setCarbonFlux(GamsLandCoverType.CROPLAND, GamsLandCoverType.TIMBER_FOREST, getValueForCol(rowValues, "crop_to_forT"));
-		item.setCarbonFlux(GamsLandCoverType.CROPLAND, GamsLandCoverType.CARBON_FOREST, getValueForCol(rowValues, "crop_to_forC"));
-		item.setCarbonFlux(GamsLandCoverType.CROPLAND, GamsLandCoverType.PASTURE,       getValueForCol(rowValues, "crop_to_past"));
+		item.setCarbonFlux(LandCoverType.CROPLAND, LandCoverType.NATURAL, 		 getValueForCol(rowValues, "crop_to_ntrl"));
+		item.setCarbonFlux(LandCoverType.CROPLAND, LandCoverType.TIMBER_FOREST,  getValueForCol(rowValues, "crop_to_forT"));
+		item.setCarbonFlux(LandCoverType.CROPLAND, LandCoverType.CARBON_FOREST,  getValueForCol(rowValues, "crop_to_forC"));
+		item.setCarbonFlux(LandCoverType.CROPLAND, LandCoverType.PASTURE,        getValueForCol(rowValues, "crop_to_past"));
+		item.setCarbonFlux(LandCoverType.CROPLAND, LandCoverType.CROPLAND,       getValueForCol(rowValues, "crop_to_crop"));
 		
-		item.setCarbonFlux(GamsLandCoverType.PASTURE,  GamsLandCoverType.OTHER_NATURAL,  getValueForCol(rowValues, "past_to_ntrl"));
-		item.setCarbonFlux(GamsLandCoverType.PASTURE,  GamsLandCoverType.TIMBER_FOREST,  getValueForCol(rowValues, "past_to_forT"));
-		item.setCarbonFlux(GamsLandCoverType.PASTURE,  GamsLandCoverType.CARBON_FOREST,  getValueForCol(rowValues, "past_to_forC"));
-		item.setCarbonFlux(GamsLandCoverType.PASTURE,  GamsLandCoverType.CROPLAND,       getValueForCol(rowValues, "past_to_crop"));
+		item.setCarbonFlux(LandCoverType.PASTURE,  LandCoverType.NATURAL,  getValueForCol(rowValues, "past_to_ntrl"));
+		item.setCarbonFlux(LandCoverType.PASTURE,  LandCoverType.TIMBER_FOREST,  getValueForCol(rowValues, "past_to_forT"));
+		item.setCarbonFlux(LandCoverType.PASTURE,  LandCoverType.CARBON_FOREST,  getValueForCol(rowValues, "past_to_forC"));
+		item.setCarbonFlux(LandCoverType.PASTURE,  LandCoverType.CROPLAND,       getValueForCol(rowValues, "past_to_crop"));
+		item.setCarbonFlux(LandCoverType.PASTURE,  LandCoverType.PASTURE,        getValueForCol(rowValues, "past_to_past"));
 		
-		item.setCarbonFlux(GamsLandCoverType.OTHER_NATURAL,  GamsLandCoverType.PASTURE,  	   getValueForCol(rowValues, "ntrl_to_past"));
-		item.setCarbonFlux(GamsLandCoverType.OTHER_NATURAL,  GamsLandCoverType.TIMBER_FOREST,  getValueForCol(rowValues, "ntrl_to_forT"));
-		item.setCarbonFlux(GamsLandCoverType.OTHER_NATURAL,  GamsLandCoverType.CARBON_FOREST,  getValueForCol(rowValues, "ntrl_to_forC"));
-		item.setCarbonFlux(GamsLandCoverType.OTHER_NATURAL,  GamsLandCoverType.CROPLAND,       getValueForCol(rowValues, "ntrl_to_crop"));
+		item.setCarbonFlux(LandCoverType.NATURAL,  LandCoverType.PASTURE,  	   	 getValueForCol(rowValues, "ntrl_to_past"));
+		item.setCarbonFlux(LandCoverType.NATURAL,  LandCoverType.TIMBER_FOREST,  getValueForCol(rowValues, "ntrl_to_forT"));
+		item.setCarbonFlux(LandCoverType.NATURAL,  LandCoverType.CARBON_FOREST,  getValueForCol(rowValues, "ntrl_to_forC"));
+		item.setCarbonFlux(LandCoverType.NATURAL,  LandCoverType.CROPLAND,       getValueForCol(rowValues, "ntrl_to_crop"));
+		item.setCarbonFlux(LandCoverType.NATURAL,  LandCoverType.NATURAL,        getValueForCol(rowValues, "ntrl_to_ntrl"));
 		
-		item.setCarbonFlux(GamsLandCoverType.TIMBER_FOREST,  GamsLandCoverType.PASTURE,  	   getValueForCol(rowValues, "forT_to_past"));
-		item.setCarbonFlux(GamsLandCoverType.TIMBER_FOREST,  GamsLandCoverType.OTHER_NATURAL,  getValueForCol(rowValues, "forT_to_ntrl"));
-		item.setCarbonFlux(GamsLandCoverType.TIMBER_FOREST,  GamsLandCoverType.CARBON_FOREST,  getValueForCol(rowValues, "forT_to_forC"));
-		item.setCarbonFlux(GamsLandCoverType.TIMBER_FOREST,  GamsLandCoverType.CROPLAND,       getValueForCol(rowValues, "forT_to_crop"));
+		item.setCarbonFlux(LandCoverType.TIMBER_FOREST,  LandCoverType.PASTURE,  	   getValueForCol(rowValues, "forT_to_past"));
+		item.setCarbonFlux(LandCoverType.TIMBER_FOREST,  LandCoverType.NATURAL,  	   getValueForCol(rowValues, "forT_to_ntrl"));
+		item.setCarbonFlux(LandCoverType.TIMBER_FOREST,  LandCoverType.CARBON_FOREST,  getValueForCol(rowValues, "forT_to_forC"));
+		item.setCarbonFlux(LandCoverType.TIMBER_FOREST,  LandCoverType.CROPLAND,       getValueForCol(rowValues, "forT_to_crop"));
+		item.setCarbonFlux(LandCoverType.TIMBER_FOREST,  LandCoverType.TIMBER_FOREST,  getValueForCol(rowValues, "forT_to_forT"));
 		
-		item.setCarbonFlux(GamsLandCoverType.CARBON_FOREST,  GamsLandCoverType.PASTURE,  	   getValueForCol(rowValues, "forC_to_past"));
-		item.setCarbonFlux(GamsLandCoverType.CARBON_FOREST,  GamsLandCoverType.OTHER_NATURAL,  getValueForCol(rowValues, "forC_to_ntrl"));
-		item.setCarbonFlux(GamsLandCoverType.CARBON_FOREST,  GamsLandCoverType.TIMBER_FOREST,  getValueForCol(rowValues, "forC_to_forT"));
-		item.setCarbonFlux(GamsLandCoverType.CARBON_FOREST,  GamsLandCoverType.CROPLAND,       getValueForCol(rowValues, "forC_to_crop"));
+		item.setCarbonFlux(LandCoverType.CARBON_FOREST,  LandCoverType.PASTURE,  	   getValueForCol(rowValues, "forC_to_past"));
+		item.setCarbonFlux(LandCoverType.CARBON_FOREST,  LandCoverType.NATURAL,  	   getValueForCol(rowValues, "forC_to_ntrl"));
+		item.setCarbonFlux(LandCoverType.CARBON_FOREST,  LandCoverType.TIMBER_FOREST,  getValueForCol(rowValues, "forC_to_forT"));
+		item.setCarbonFlux(LandCoverType.CARBON_FOREST,  LandCoverType.CROPLAND,       getValueForCol(rowValues, "forC_to_crop"));
+		item.setCarbonFlux(LandCoverType.CARBON_FOREST,  LandCoverType.CARBON_FOREST,  getValueForCol(rowValues, "forC_to_forC"));
 		
                                                                                 
 	}
diff --git a/src/ac/ed/lurg/landuse/LandUseItem.java b/src/ac/ed/lurg/landuse/LandUseItem.java
index a01d32a4da168546c64ef4a1ea0b8958dc70db57..f30e7b0673d27347d5b07f8c387a8479626e0b42 100644
--- a/src/ac/ed/lurg/landuse/LandUseItem.java
+++ b/src/ac/ed/lurg/landuse/LandUseItem.java
@@ -8,7 +8,6 @@ import java.util.Map;
 import ac.ed.lurg.ModelConfig;
 import ac.ed.lurg.types.CropToDouble;
 import ac.ed.lurg.types.CropType;
-import ac.ed.lurg.types.GamsLandCoverType;
 import ac.ed.lurg.types.LandCoverType;
 import ac.ed.lurg.utils.Interpolator;
 import ac.sac.raster.InterpolatingRasterItem;
@@ -20,7 +19,7 @@ public class LandUseItem implements InterpolatingRasterItem<LandUseItem>, Serial
 	private Map<CropType, Double> cropFractions = new HashMap<CropType, Double>();
 	private Map<LandCoverType, Double> landCoverAreas = new HashMap<LandCoverType, Double>();
 	private Map<LandCoverType, Double> unprotectedAreas = new HashMap<LandCoverType, Double>();
-	private Map<GamsLandCoverType, Double> gamsLandCoverAreas = new HashMap<GamsLandCoverType, Double>();
+	//private Map<GamsLandCoverType, Double> gamsLandCoverAreas = new HashMap<GamsLandCoverType, Double>();
 	private double protectedArea; //protected area in Mha
 	private double unavailableArea; //area unavailable due to altitude etc 
 	private double suitableArea;
@@ -251,7 +250,7 @@ public class LandUseItem implements InterpolatingRasterItem<LandUseItem>, Serial
 	
 	public double getTotalLandCoverArea() {
 		double d = 0;
-		for (LandCoverType l : LandCoverType.values()) 
+		for (LandCoverType l : LandCoverType.getLuhTypes()) 
 			d += getLandCoverArea(l);
 	
 		return d;
@@ -288,7 +287,7 @@ public class LandUseItem implements InterpolatingRasterItem<LandUseItem>, Serial
 	
 	public double getTotalUnprotectedNatural() {	
 		double unprotectedNatural = 0;
-		for (LandCoverType landType : LandCoverType.values()) {
+		for (LandCoverType landType : LandCoverType.getLuhTypes()) {
 			if (landType.isProtectable()) {
 				unprotectedNatural += unprotectedAreas.get(landType);
 				}
@@ -428,7 +427,7 @@ public class LandUseItem implements InterpolatingRasterItem<LandUseItem>, Serial
 		return total;
 	}
 	
-	
+	/*
 	public double getGamsLandCoverArea(GamsLandCoverType landCoverType) {
 		return gamsLandCoverAreas.get(landCoverType);
 	}
@@ -442,7 +441,8 @@ public class LandUseItem implements InterpolatingRasterItem<LandUseItem>, Serial
 		gamsLandCoverAreas.put(c, landCover);
 	}
 	
-	/** move areas from one land cover to another, return any residual not possible */
+	
+	// move areas from one land cover to another, return any residual not possible
     public void moveGamsAreas(GamsLandCoverType toType, GamsLandCoverType fromType, double changeReq) {
 
         double prevTo = getGamsLandCoverArea(toType);
@@ -452,7 +452,7 @@ public class LandUseItem implements InterpolatingRasterItem<LandUseItem>, Serial
         setGamsLandCoverArea(fromType, prevFrom - changeReq);
 
     }
-
+    */
 	@Override
 	public String toString() {
 		return "LandUseItem: [landCoverAreas=" + landCoverAreas + ", protectedArea=" + protectedArea + ", unavailableArea=" + unavailableArea + "]";
diff --git a/src/ac/ed/lurg/landuse/WoodYieldItem.java b/src/ac/ed/lurg/landuse/WoodYieldItem.java
index 04eef0a1f5b45725773db303da8f5a50c63af210..3da2875900ce54598fe1ee17c7d82b09491d24e9 100644
--- a/src/ac/ed/lurg/landuse/WoodYieldItem.java
+++ b/src/ac/ed/lurg/landuse/WoodYieldItem.java
@@ -3,19 +3,36 @@ package ac.ed.lurg.landuse;
 import java.util.HashMap;
 import java.util.Map;
 
-import ac.ed.lurg.types.GamsLandCoverType;
+import ac.ed.lurg.types.LandCoverType;
 import ac.sac.raster.RasterItem;
 
 public class WoodYieldItem implements RasterItem {
-	Map<GamsLandCoverType, Map<GamsLandCoverType, Double>> woodYields = new HashMap<GamsLandCoverType, Map<GamsLandCoverType, Double>>(); 
+	Map<LandCoverType, Map<LandCoverType, Double>> woodYields = new HashMap<LandCoverType, Map<LandCoverType, Double>>(); 
 	
-	public void setWoodYield(GamsLandCoverType previousLandCover, GamsLandCoverType newLandCover, double woodYield) {
-		Map<GamsLandCoverType, Double> cfMap = new HashMap<GamsLandCoverType, Double>();
-		cfMap.put(newLandCover, woodYield);		
-		woodYields.put(previousLandCover, cfMap);
+	public void setWoodYield(LandCoverType previousLandCover, LandCoverType newLandCover, double woodYield) {
+		if (woodYields.containsKey(previousLandCover)) {
+			woodYields.get(previousLandCover).put(newLandCover, woodYield);
+		} else {
+			Map<LandCoverType, Double> cfMap = new HashMap<LandCoverType, Double>();
+			cfMap.put(newLandCover, woodYield);
+			woodYields.put(previousLandCover, cfMap);
+		}
 	}
 	
-	public Double getWoodYield(GamsLandCoverType previousLandCover, GamsLandCoverType newLandCover) {
+	public double getWoodYield(LandCoverType previousLandCover, LandCoverType newLandCover) {
 		return woodYields.get(previousLandCover).get(newLandCover);
 	}
+	
+	public boolean checkForKeys(LandCoverType previousLandCover, LandCoverType newLandCover) {
+		if (woodYields.containsKey(previousLandCover)) {
+			if (woodYields.get(previousLandCover).containsKey(newLandCover)) {
+				return true;
+			} else {
+				return false;
+			}
+		} else {
+			return false;
+		}
+	}
+
 }
diff --git a/src/ac/ed/lurg/landuse/WoodYieldReader.java b/src/ac/ed/lurg/landuse/WoodYieldReader.java
index b8b5a99f8b8102bd42308c5a8159f27b64ef0b2b..7c693c54036a4cfaf3dcece71f3f9bbe0068f360 100644
--- a/src/ac/ed/lurg/landuse/WoodYieldReader.java
+++ b/src/ac/ed/lurg/landuse/WoodYieldReader.java
@@ -2,44 +2,49 @@ package ac.ed.lurg.landuse;
 
 import java.util.Map;
 
-import ac.ed.lurg.types.GamsLandCoverType;
+import ac.ed.lurg.types.LandCoverType;
 import ac.sac.raster.AbstractTabularRasterReader;
 import ac.sac.raster.RasterKey;
 import ac.sac.raster.RasterSet;
 
 public class WoodYieldReader extends AbstractTabularRasterReader<WoodYieldItem> {
 	
-	private static final int MIN_COLS = 18;
+	private static final int MIN_COLS = 27;
 	
 	public WoodYieldReader(RasterSet<WoodYieldItem> woodYield) {
 		super("[ |\t]+", MIN_COLS, woodYield);
 	}
 
 	protected void setData(RasterKey key, WoodYieldItem item, Map<String, Double> rowValues) {
-		item.setWoodYield(GamsLandCoverType.CROPLAND, GamsLandCoverType.OTHER_NATURAL, getValueForCol(rowValues, "crop_to_ntrl"));
-		item.setWoodYield(GamsLandCoverType.CROPLAND, GamsLandCoverType.TIMBER_FOREST, getValueForCol(rowValues, "crop_to_forT"));
-		item.setWoodYield(GamsLandCoverType.CROPLAND, GamsLandCoverType.CARBON_FOREST, getValueForCol(rowValues, "crop_to_forC"));
-		item.setWoodYield(GamsLandCoverType.CROPLAND, GamsLandCoverType.PASTURE,       getValueForCol(rowValues, "crop_to_past"));
+		item.setWoodYield(LandCoverType.CROPLAND, LandCoverType.NATURAL, 		 getValueForCol(rowValues, "crop_to_ntrl"));
+		item.setWoodYield(LandCoverType.CROPLAND, LandCoverType.TIMBER_FOREST,  getValueForCol(rowValues, "crop_to_forT"));
+		item.setWoodYield(LandCoverType.CROPLAND, LandCoverType.CARBON_FOREST,  getValueForCol(rowValues, "crop_to_forC"));
+		item.setWoodYield(LandCoverType.CROPLAND, LandCoverType.PASTURE,        getValueForCol(rowValues, "crop_to_past"));
+		item.setWoodYield(LandCoverType.CROPLAND, LandCoverType.CROPLAND,       getValueForCol(rowValues, "crop_to_crop"));
 		
-		item.setWoodYield(GamsLandCoverType.PASTURE,  GamsLandCoverType.OTHER_NATURAL,  getValueForCol(rowValues, "past_to_ntrl"));
-		item.setWoodYield(GamsLandCoverType.PASTURE,  GamsLandCoverType.TIMBER_FOREST,  getValueForCol(rowValues, "past_to_forT"));
-		item.setWoodYield(GamsLandCoverType.PASTURE,  GamsLandCoverType.CARBON_FOREST,  getValueForCol(rowValues, "past_to_forC"));
-		item.setWoodYield(GamsLandCoverType.PASTURE,  GamsLandCoverType.CROPLAND,       getValueForCol(rowValues, "past_to_crop"));
+		item.setWoodYield(LandCoverType.PASTURE,  LandCoverType.NATURAL,  getValueForCol(rowValues, "past_to_ntrl"));
+		item.setWoodYield(LandCoverType.PASTURE,  LandCoverType.TIMBER_FOREST,  getValueForCol(rowValues, "past_to_forT"));
+		item.setWoodYield(LandCoverType.PASTURE,  LandCoverType.CARBON_FOREST,  getValueForCol(rowValues, "past_to_forC"));
+		item.setWoodYield(LandCoverType.PASTURE,  LandCoverType.CROPLAND,       getValueForCol(rowValues, "past_to_crop"));
+		item.setWoodYield(LandCoverType.PASTURE,  LandCoverType.PASTURE,        getValueForCol(rowValues, "past_to_past"));
 		
-		item.setWoodYield(GamsLandCoverType.OTHER_NATURAL,  GamsLandCoverType.PASTURE,  	   getValueForCol(rowValues, "ntrl_to_past"));
-		item.setWoodYield(GamsLandCoverType.OTHER_NATURAL,  GamsLandCoverType.TIMBER_FOREST,  getValueForCol(rowValues, "ntrl_to_forT"));
-		item.setWoodYield(GamsLandCoverType.OTHER_NATURAL,  GamsLandCoverType.CARBON_FOREST,  getValueForCol(rowValues, "ntrl_to_forC"));
-		item.setWoodYield(GamsLandCoverType.OTHER_NATURAL,  GamsLandCoverType.CROPLAND,       getValueForCol(rowValues, "ntrl_to_crop"));
+		item.setWoodYield(LandCoverType.NATURAL,  LandCoverType.PASTURE,  	   	 getValueForCol(rowValues, "ntrl_to_past"));
+		item.setWoodYield(LandCoverType.NATURAL,  LandCoverType.TIMBER_FOREST,  getValueForCol(rowValues, "ntrl_to_forT"));
+		item.setWoodYield(LandCoverType.NATURAL,  LandCoverType.CARBON_FOREST,  getValueForCol(rowValues, "ntrl_to_forC"));
+		item.setWoodYield(LandCoverType.NATURAL,  LandCoverType.CROPLAND,       getValueForCol(rowValues, "ntrl_to_crop"));
+		item.setWoodYield(LandCoverType.NATURAL,  LandCoverType.NATURAL,        getValueForCol(rowValues, "ntrl_to_ntrl"));
 		
-		item.setWoodYield(GamsLandCoverType.TIMBER_FOREST,  GamsLandCoverType.PASTURE,  	   getValueForCol(rowValues, "forT_to_past"));
-		item.setWoodYield(GamsLandCoverType.TIMBER_FOREST,  GamsLandCoverType.OTHER_NATURAL,  getValueForCol(rowValues, "forT_to_ntrl"));
-		item.setWoodYield(GamsLandCoverType.TIMBER_FOREST,  GamsLandCoverType.CARBON_FOREST,  getValueForCol(rowValues, "forT_to_forC"));
-		item.setWoodYield(GamsLandCoverType.TIMBER_FOREST,  GamsLandCoverType.CROPLAND,       getValueForCol(rowValues, "forT_to_crop"));
+		item.setWoodYield(LandCoverType.TIMBER_FOREST,  LandCoverType.PASTURE,  	   getValueForCol(rowValues, "forT_to_past"));
+		item.setWoodYield(LandCoverType.TIMBER_FOREST,  LandCoverType.NATURAL,  	   getValueForCol(rowValues, "forT_to_ntrl"));
+		item.setWoodYield(LandCoverType.TIMBER_FOREST,  LandCoverType.CARBON_FOREST,  getValueForCol(rowValues, "forT_to_forC"));
+		item.setWoodYield(LandCoverType.TIMBER_FOREST,  LandCoverType.CROPLAND,       getValueForCol(rowValues, "forT_to_crop"));
+		item.setWoodYield(LandCoverType.TIMBER_FOREST,  LandCoverType.TIMBER_FOREST,  getValueForCol(rowValues, "forT_to_forT"));
 		
-		item.setWoodYield(GamsLandCoverType.CARBON_FOREST,  GamsLandCoverType.PASTURE,  	   getValueForCol(rowValues, "forC_to_past"));
-		item.setWoodYield(GamsLandCoverType.CARBON_FOREST,  GamsLandCoverType.OTHER_NATURAL,  getValueForCol(rowValues, "forC_to_ntrl"));
-		item.setWoodYield(GamsLandCoverType.CARBON_FOREST,  GamsLandCoverType.TIMBER_FOREST,  getValueForCol(rowValues, "forC_to_forT"));
-		item.setWoodYield(GamsLandCoverType.CARBON_FOREST,  GamsLandCoverType.CROPLAND,       getValueForCol(rowValues, "forC_to_crop"));
+		item.setWoodYield(LandCoverType.CARBON_FOREST,  LandCoverType.PASTURE,  	   getValueForCol(rowValues, "forC_to_past"));
+		item.setWoodYield(LandCoverType.CARBON_FOREST,  LandCoverType.NATURAL,  	   getValueForCol(rowValues, "forC_to_ntrl"));
+		item.setWoodYield(LandCoverType.CARBON_FOREST,  LandCoverType.TIMBER_FOREST,  getValueForCol(rowValues, "forC_to_forT"));
+		item.setWoodYield(LandCoverType.CARBON_FOREST,  LandCoverType.CROPLAND,       getValueForCol(rowValues, "forC_to_crop"));
+		item.setWoodYield(LandCoverType.CARBON_FOREST,  LandCoverType.CARBON_FOREST,  getValueForCol(rowValues, "forC_to_forC"));
 		                                                                          
 	}
 }
diff --git a/src/ac/ed/lurg/output/LpjgOutputer.java b/src/ac/ed/lurg/output/LpjgOutputer.java
index 6b0219d277c8946d8af3a66a0ce44d62bff0ae1a..35e23308e4572b31481471ce44fec3c49f9f0e7f 100644
--- a/src/ac/ed/lurg/output/LpjgOutputer.java
+++ b/src/ac/ed/lurg/output/LpjgOutputer.java
@@ -24,6 +24,7 @@ public class LpjgOutputer extends AbstractLandUseOutputer {
 	public void writeOutput() {
 		File outputDir = getOutputDir(year);
 		writeLandUseFile(outputDir);
+		writeGamsLandCoverFile(outputDir);
 		writeIntensity(outputDir);
 		writeMarkerFile(year, false);
 	}
@@ -164,4 +165,52 @@ public class LpjgOutputer extends AbstractLandUseOutputer {
 			}
 		}
 	}
+	
+	protected void writeGamsLandCoverFile(File outputDir) {
+		
+		BufferedWriter landCoverWriter = null;
+		try {
+			String landCoverFileName = outputDir.getPath() + File.separator + "GamsLandCoverFract.txt";
+			landCoverWriter = new BufferedWriter(new FileWriter(landCoverFileName, false));
+			landCoverWriter.write("Lon Lat Year CROPLAND PASTURE TIMBER CARBON NATURAL BARREN URBAN");
+			landCoverWriter.newLine();
+
+			for (Entry<RasterKey, LandUseItem> entry : landUseRaster.entrySet()) {
+				RasterKey key = entry.getKey();
+				LandUseItem item = entry.getValue();
+				double lat = landUseRaster.getXCoordin(key);
+				double lon = landUseRaster.getYCoordin(key);
+
+				double expectedArea = landUseRaster.getAreaMha(key);
+				double area = item.getTotalLandCoverArea();
+				
+				if (area > 0 && Math.abs((expectedArea-area)/expectedArea) > 0.01) {  // zero area, due to data not being found, already reported so ignored here
+					LogWriter.printlnError("Land cover areas look strange " + key + ": expected=" + expectedArea + ", actual=" + area);
+				}
+				
+				double crop = item.getLandCoverFract(LandCoverType.CROPLAND);
+				double pasture = item.getLandCoverFract(LandCoverType.PASTURE);
+				double timberForest = item.getLandCoverFract(LandCoverType.TIMBER_FOREST);
+				double carbonForest = item.getLandCoverFract(LandCoverType.CARBON_FOREST);
+				double natural = item.getLandCoverFract(LandCoverType.NATURAL);
+				double barren = item.getLandCoverFract(LandCoverType.BARREN);
+				double urban = item.getLandCoverFract(LandCoverType.URBAN);
+				landCoverWriter.write(String.format("%.2f %.2f %d %.14f %.14f %.14f %.14f %.14f %.14f %.14f", lat, lon, year, crop, pasture, timberForest, carbonForest, natural, barren, urban));
+				landCoverWriter.newLine();
+			}
+		}
+		catch (IOException e) {
+			LogWriter.print(e);
+		}
+		finally {
+			if (landCoverWriter != null) {
+				try {
+					landCoverWriter.close();
+				} 
+				catch (IOException e) {
+					LogWriter.print(e);
+				}
+			}
+		}
+	}
 }
diff --git a/src/ac/ed/lurg/types/LandCoverType.java b/src/ac/ed/lurg/types/LandCoverType.java
index 6c0c8428eb59c97872fe94902445c4cb1f478179..64eb252de701ce00bbe7607430bc0b3ba295449b 100644
--- a/src/ac/ed/lurg/types/LandCoverType.java
+++ b/src/ac/ed/lurg/types/LandCoverType.java
@@ -1,21 +1,33 @@
 package ac.ed.lurg.types;
 
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+
+import ac.ed.lurg.utils.LogWriter;
+
 public enum LandCoverType {
 	
-	MANAGED_FOREST ("managedForest", true),
-	UNMANAGED_FOREST ("unmanagedForest", true),
-	OTHER_NATURAL ("otherNatural", true),
-	CROPLAND ("cropland", false),
-	PASTURE ("pasture", false),
-	BARREN ("barren", false),
-	URBAN("urban", false);
+	MANAGED_FOREST ("managedForest", true, false), // This is TIMBER_FOREST + CARBON_FOREST
+	UNMANAGED_FOREST ("unmanagedForest", true, false),
+	OTHER_NATURAL ("otherNatural", true, false),
+	CROPLAND ("cropland", false, true),
+	PASTURE ("pasture", false, true),
+	BARREN ("barren", false, false),
+	URBAN("urban", false, false),
+	TIMBER_FOREST("timberForest", true, true),
+	CARBON_FOREST("carbonForest", true, true),
+	NATURAL("natural", true, true); // This is OTHER_NATURAL + UNMANAGED_FOREST
 
 	private String name;
 	private boolean isProtectable;
+	private boolean isGamsType;
 	
-	LandCoverType(String name, boolean isProtectable) {
+	LandCoverType(String name, boolean isProtectable, boolean isGamsType) {
 		this.name = name;
 		this.isProtectable = isProtectable;
+		this.isGamsType = isGamsType;
 	}
 	
 	public String getName() {
@@ -25,5 +37,46 @@ public enum LandCoverType {
 	public boolean isProtectable() {
 		return isProtectable;
 	}
+	
+	private static final Map<String, LandCoverType> nameCache = new HashMap<String, LandCoverType>();
+    static {
+        for (LandCoverType c : values()) {
+        	nameCache.put(c.getName(), c);
+
+       }
+    }
+
+	public static LandCoverType getForName(String name) {
+		LandCoverType type = nameCache.get(name);
+		
+		if (type == null)
+			LogWriter.printlnError("Can't find LandCoverType for " + name);
+		
+		return type;
+	}
+	
+	public static Collection<LandCoverType> getLuhTypes() {
+
+		Collection<LandCoverType> luhTypes = new HashSet<LandCoverType>();
+
+		for (LandCoverType c : values())
+			if (!c.isGamsType)
+				luhTypes.add(c);
+
+		return luhTypes;
+
+	}
+	
+	public static Collection<LandCoverType> getGamsTypes() {
+
+		Collection<LandCoverType> gamsTypes = new HashSet<LandCoverType>();
+
+		for (LandCoverType c : values())
+			if (c.isGamsType)
+				gamsTypes.add(c);
+
+		return gamsTypes;
+
+	}
 }