diff --git a/GAMS/IntExtOpt.gms b/GAMS/IntExtOpt.gms
index 5464729ce5d700be6198d655f076c71a75dc7fc0..dea860ebf7e881f0a8c14aced84e4949736eb748 100644
--- a/GAMS/IntExtOpt.gms
+++ b/GAMS/IntExtOpt.gms
@@ -13,6 +13,7 @@
 
  SET land_cover / cropland, pasture, timberForest, carbonForest, natural /;
  SET managed_forest(land_cover) / timberForest, carbonForest /;
+ SET agriculture(land_cover) / cropland, pasture /;
  ALIAS (land_cover, land_cover_before);
  ALIAS (land_cover, land_cover_after);
 
@@ -61,8 +62,9 @@
  SCALAR unhandledCropRate                    rate of fruit veg and other crops not modelled;
  SCALAR setAsideRate                         rate of set aside and failed crop;
  SCALAR domesticPriceMarkup                  factor price increased from cost of production;
- SCALAR maxLandExpansionRate                 max rate of country land expansion;
- SCALAR energycropsMaxProportion             maximum proportion of croplands for energycriops;
+ SCALAR maxGrossLccRate                      max rate of gross land cover change;
+ SCALAR maxFertChange                        max increase in total fertilizer use;
+ SCALAR maxIrrigChange                       max increase in total irrigation use;
 
  SCALAR forestManagementCost    cost $1000 per ha;
  SCALAR vegClearingCostRate     cost of clearing vegetation $1000 per tC;
@@ -75,10 +77,10 @@ $gdxin %gdxincname%
 $load location, suitableLandArea, demand
 $load previousCropArea, previousFertIntensity, previousIrrigIntensity, previousOtherIntensity, previousRuminantFeed, previousMonogastricFeed, previousImportAmount, previousExportAmount
 $load yieldNone, yieldFertOnly, yieldIrrigOnly, yieldBoth, yieldShock
-$load fertParam, irrigParam, otherIParam, exportPrices, importPrices, maxNetImport, minNetImport, unhandledCropRate, setAsideRate, maxLandExpansionRate, subsidyRate
+$load fertParam, irrigParam, otherIParam, exportPrices, importPrices, maxNetImport, minNetImport, unhandledCropRate, setAsideRate, maxGrossLccRate, subsidyRate
 $load meatEfficency, otherICost, irrigCost, irrigMaxRate, irrigConstraint, fertiliserUnitCost, domesticPriceMarkup, minDemandPerCereal, minDemandPerOilcrop, seedAndWasteRate
 $load previousLandCoverArea, carbonFluxRate, carbonCreditRate, woodYieldRota, woodYieldLUC, forestRotationPeriod, conversionCost
-$load forestManagementCost, vegClearingCostRate, carbonHorizon, energycropsMaxProportion, carbonForestMaxProportion
+$load forestManagementCost, vegClearingCostRate, carbonHorizon, carbonForestMaxProportion, maxFertChange, maxIrrigChange
 $gdxin
 
  SCALAR delta "use to smooth power function see 7.5 www.gams.com dd docs solversconopt.pdf" / 0.00000000001 /;
@@ -152,7 +154,7 @@ $gdxin
        total_cost                         total cost of domestic supply including net imports;
 
  POSITIVE VARIABLE cropArea, fertI, irrigI, otherIntensity, ruminantFeed, monogastricFeed, importAmount, exportAmount, totalFeedDM,
-                   landCoverArea, landCoverChange, totalConversionCost, woodSupplyRota, woodSupplyLUC;
+                   landCoverArea, landCoverChange, totalConversionCost, woodSupplyRota, woodSupplyLUC, animalProd;
 
 
 * POSITIVE VARIABLE A;
@@ -164,6 +166,8 @@ $gdxin
        MAX_IRRIG_INTENSITY_CONSTRAINT(crop, location)   constraint on maximum irrigation intensity
        MAX_OTHER_INTENSITY_CONSTRAINT(crop, location)
        IRRIGATION_CONSTRAINT(location)                  constraint on water usage
+       FERT_RATE_INCREASE_CONSTRAINT
+       IRRIG_RATE_INCREASE_CONSTRAINT
        
        NET_SUPPLY_EQ(crop)                              calc net supply for crops
        CROP_DEMAND_CONSTRAINT(crop)                     satisfy demand for individual crops
@@ -223,11 +227,19 @@ $gdxin
  MAX_IRRIG_INTENSITY_CONSTRAINT(crop, location) .. irrigI(crop, location) =L= 1;
  MAX_OTHER_INTENSITY_CONSTRAINT(crop, location) .. otherIntensity(crop, location) =L= 1;
  
- IRRIGATION_CONSTRAINT(location) .. irrigConstraint(location) * suitableLandArea(location) * (1.0 - unhandledCropRate) =G= sum(crop, irrigMaxRate(crop, location) * irrigI(crop, location) * cropArea(crop, location));
+ IRRIGATION_CONSTRAINT(location) .. irrigConstraint(location) * suitableLandArea(location) * (1.0 - unhandledCropRate) =G=
+                                    sum(crop, irrigMaxRate(crop, location) * irrigI(crop, location) * cropArea(crop, location));
+ 
+ FERT_RATE_INCREASE_CONSTRAINT .. sum((crop, location), fertI(crop, location) * cropArea(crop, location)) =L=
+                                  sum((crop, location), previousFertIntensity(crop, location) * previousCropArea(crop, location)) * (1 + maxFertChange);
+                                  
+ IRRIG_RATE_INCREASE_CONSTRAINT .. sum((crop, location), irrigI(crop, location) * irrigMaxRate(crop, location) * cropArea(crop, location)) =L=
+                                   sum((crop, location), previousIrrigIntensity(crop, location) * irrigMaxRate(crop, location) * previousCropArea(crop, location)) * (1 + maxIrrigChange);
 
 *************** Crop supply *************************
 
- NET_SUPPLY_EQ(crop) .. netSupply(crop) =E= sum(location, cropArea(crop, location) * yield(crop, location)) * (1 - seedAndWasteRate(crop)) - ruminantFeed(crop) - monogastricFeed(crop) + importAmount(crop) - exportAmount(crop);
+ NET_SUPPLY_EQ(crop) .. netSupply(crop) =E= sum(location, cropArea(crop, location) * yield(crop, location)) *
+                                            (1 - seedAndWasteRate(crop)) - ruminantFeed(crop) - monogastricFeed(crop) + importAmount(crop) - exportAmount(crop);
   
  CROP_DEMAND_CONSTRAINT(crop) .. netSupply(crop) =G= demand(crop);
     
@@ -244,6 +256,7 @@ $gdxin
  MONOGASTRICS_DEMAND_CONSTRAINT .. animalProd('monogastrics') =G= (demand('monogastrics') - importAmount('monogastrics') + exportAmount('monogastrics'));
  
  TOTAL_NON_PASTURE_FEED_DM_CALC .. totalFeedDM =E= sum(feed_crop_less_pasture, (ruminantFeed(feed_crop_less_pasture) + monogastricFeed(feed_crop_less_pasture)) * cropDM(feed_crop_less_pasture));
+ 
  FEED_MIX_CONSTRAINT(feed_crop_less_pasture) .. (ruminantFeed(feed_crop_less_pasture) + monogastricFeed(feed_crop_less_pasture)) * cropDM(feed_crop_less_pasture) =L= totalFeedDM * 0.7;
  
 ************** Land Cover *****************************
@@ -261,8 +274,8 @@ $gdxin
 
  LAND_COVER_CHANGE_CONSTRAINT(land_cover, location) .. sum(land_cover_after, landCoverChange(land_cover, land_cover_after, location)) =E= previousLandCoverArea(land_cover, location);
 
- CONVERSION_COST_CALC(location) .. totalConversionCost(location) =E= sum((land_cover_before, land_cover_after), landCoverChange(land_cover_before, land_cover_after, location) * conversionCost(land_cover_before, land_cover_after, location));
-
+ CONVERSION_COST_CALC(location) .. totalConversionCost(location) =E= sum((land_cover_before, land_cover_after),
+                                                                     landCoverChange(land_cover_before, land_cover_after, location) * conversionCost(land_cover_before, land_cover_after, location));
 ************* Forestry ***********************************
 
  WOOD_SUPPLY_ROTA_CALC .. woodSupplyRota =E= sum(location, landCoverArea('timberForest', location) * woodYieldRota(location));
diff --git a/src/ac/ed/lurg/ModelConfig.java b/src/ac/ed/lurg/ModelConfig.java
index ef086d4821dbe2ead5d084addfcd1895b1761bfb..250da78ece152b47cf9cba71e43031b0932e24c2 100755
--- a/src/ac/ed/lurg/ModelConfig.java
+++ b/src/ac/ed/lurg/ModelConfig.java
@@ -391,19 +391,13 @@ public class ModelConfig {
 	public static final double OTHER_WATER_USE_FACTOR = getDoubleProperty("OTHER_WATER_USE_FACTOR", 1.0);
 	public static final boolean USE_BLUE_WATER_FILE_IRRIG_CONSTRAINT = getBooleanProperty("USE_BLUE_WATER_FILE_IRRIG_CONSTRAINT", false);;
 
-	public static final boolean CONVERSION_COSTS_FROM_FILE = getBooleanProperty("CONVERSION_COSTS_FROM_FILE", true);
+	public static final boolean CONVERSION_COSTS_FROM_FILE = getBooleanProperty("CONVERSION_COSTS_FROM_FILE", false);
 	public static final String CONVERSION_COST_FILE = getProperty("CONVERSION_COST_FILE", DATA_DIR + File.separator + "conversion_costs.csv"); // cost of converting from one land cover to another, $1000/ha
-	public static final double LAND_CHANGE_COST = getDoubleProperty("LAND_CHANGE_COST", 0.2);
-	public static final double CROP_TO_PASTURE_COST_FACTOR = getDoubleProperty("CROP_TO_PASTURE_COST_FACTOR", 1.0);
-	public static final double AGRI_LAND_EXPANSION_COST_FACTOR = getDoubleProperty("AGRI_LAND_EXPANSION_COST_FACTOR", 1.0);
-
-	public static final double CROP_INCREASE_COST = getDoubleProperty("CROP_INCREASE_COST", 0.05 * LAND_CHANGE_COST * AGRI_LAND_EXPANSION_COST_FACTOR);
-	public static final double CROP_DECREASE_COST = getDoubleProperty("CROP_DECREASE_COST", 1.65 * LAND_CHANGE_COST);
-	public static final double PASTURE_INCREASE_COST = getDoubleProperty("PASTURE_INCREASE_COST", 0.35 * LAND_CHANGE_COST * CROP_TO_PASTURE_COST_FACTOR * AGRI_LAND_EXPANSION_COST_FACTOR);
-	public static final double PASTURE_DECREASE_COST = getDoubleProperty("PASTURE_DECREASE_COST", LAND_CHANGE_COST);
-	public static final double MANAGED_FOREST_INCREASE_COST = getDoubleProperty("MANAGED_FOREST_INCREASE_COST", LAND_CHANGE_COST); // $1000/ha
-	public static final double MANAGED_FOREST_DECREASE_COST = getDoubleProperty("MANAGED_FOREST_DECREASE_COST", LAND_CHANGE_COST); // $1000/ha
-
+	public static final double LAND_CONVERSION_COST_FACTOR = getDoubleProperty("NATURAL_CONVERSION_COST", 1.0); // for monte carlo
+	public static final double CROPLAND_CONVERSION_COST = getDoubleProperty("CROPLAND_CONVERSION_COST", 0.4 * LAND_CONVERSION_COST_FACTOR);
+	public static final double PASTURE_CONVERSION_COST = getDoubleProperty("PASTURE_CONVERSION_COST", 0.22 * LAND_CONVERSION_COST_FACTOR);
+	public static final double FOREST_CONVERSION_COST = getDoubleProperty("FOREST_CONVERSION_COST", 0.2 * LAND_CONVERSION_COST_FACTOR);
+	public static final double NATURAL_CONVERSION_COST = getDoubleProperty("NATURAL_CONVERSION_COST", 0.03 * LAND_CONVERSION_COST_FACTOR);
 
 	public static final double TECHNOLOGY_CHANGE_ANNUAL_RATE = getDoubleProperty("TECHNOLOGY_CHANGE_ANNUAL_RATE", 0.002);
 	public static final int TECHNOLOGY_CHANGE_START_STEP = getIntProperty("TECHNOLOGY_CHANGE_START_STEP", 0);
@@ -461,7 +455,9 @@ public class ModelConfig {
 
 	public static final boolean PROTECTED_AREAS_ENABLED = getBooleanProperty("PROTECTED_AREAS_ENABLED", true);
 	public static final double MIN_NATURAL_RATE = getDoubleProperty("MIN_NATURAL_RATE", 0.05);
-	public static final double MAX_CHINA_LAND_EXPANSION_RATE = getDoubleProperty("MAX_CHINA_LAND_EXPANSION_RATE", 0.011*0.4); // 1.1% max forest change 40% of natural land is forest
+	public static final double MAX_GROSS_LCC_RATE = getDoubleProperty("MAX_GROSS_LCC_RATE", 0.01); // 1% gross change
+	public static final double MAX_FERT_CHANGE = getDoubleProperty("MAX_FERT_CHANGE", 0.08); // 8% from FAO data 95th percentile
+	public static final double MAX_IRRIG_CHANGE = getDoubleProperty("MAX_IRRIG_CHANGE", 0.03); // 3% from FAO data 95th percentile
 
 	public static final boolean DEBUG_JUST_DEMAND_OUTPUT = getBooleanProperty("DEBUG_JUST_DEMAND_OUTPUT", false);
 	public static final int DEBUG_LOG_LEVEL = getIntProperty("DEBUG_LEVEL", 2); // Print only events below this level. Errors & Warnings always printed (0); Solve status (1); Global events (2); Country events (3)
@@ -515,7 +511,7 @@ public class ModelConfig {
 	public static final double VEGETATION_CLEARING_COST = getDoubleProperty("VEGETATION_CLEARING_COST", 0.001); //$1000/tC
 	public static final double FOREST_MANAGEMENT_COST = IS_FORESTRY_ON ? getDoubleProperty("FOREST_ESTABLISHMENT_COST", 5.0) : 0.0; // establishment, management etc. $1000/ha
 	public static final double WOOD_TRADE_BARRIER = getDoubleProperty("WOOD_TRADE_BARRIER", 0.2); //$1000/tC
-	public static final double INIT_WOOD_PRICE = IS_FORESTRY_ON ? getDoubleProperty("INIT_WOOD_PRICE", 0.38) : 0.0; // $1000/tC-eq
+	public static final double INIT_WOOD_PRICE = IS_FORESTRY_ON ? getDoubleProperty("INIT_WOOD_PRICE", 0.22) : 0.0; // $1000/tC-eq
 	public static final boolean ENABLE_VEGETATION_CLEARANCE_COST = getBooleanProperty("ENABLE_VEGETATION_CLEARANCE_COST", false); // calculates cost of clearing vegetation even if forestry off
 	public static final int MIN_FOREST_ROTATION_PERIOD = getIntProperty("MIN_FOREST_ROTATION_PERIOD", 5); // Minimum forest rotation period; Bauhus et al., 2010. Ecosystem goods and services from plantation forests.
 	
diff --git a/src/ac/ed/lurg/country/AbstractCountryAgent.java b/src/ac/ed/lurg/country/AbstractCountryAgent.java
index d2584ccd0bba9b7af074a3c005f627fa684b062c..dbe33c52f0984f7bd3f29d13ec1502de1ebde6f0 100644
--- a/src/ac/ed/lurg/country/AbstractCountryAgent.java
+++ b/src/ac/ed/lurg/country/AbstractCountryAgent.java
@@ -174,7 +174,7 @@ public abstract class AbstractCountryAgent {
 	}
 
 	protected void updateNetImportsFromProdAndDemand(Map<CommodityType, Double> demands, Map<CommodityType, Map<CropType, Double>>  minDemandFracts, Map<CropType, CropUsageData> cropUsages) {
-		LogWriter.println("AbstractCountryAgent: updateNetImportsFromProdAndDemand for " + country);
+		LogWriter.println("AbstractCountryAgent: updateNetImportsFromProdAndDemand for " + country, 3);
 		
 		for (CommodityType commodity : CommodityType.getAllFoodItems()) {
 				
@@ -200,7 +200,7 @@ public abstract class AbstractCountryAgent {
 						totalExcessProd += netImportsFromMinDemand;
 				}
 				double additionalNetImportsRequired = demand - totalProd - totalmportFromMD;
-				LogWriter.println("additionalNetImportsRequired is " + additionalNetImportsRequired);
+				LogWriter.println("additionalNetImportsRequired is " + additionalNetImportsRequired, 3);
 
 				for (CropType crop : commodity.getCropTypes()) {
 					double netImportsMD = netImportsFromMinDemands.get(crop);
@@ -217,7 +217,7 @@ public abstract class AbstractCountryAgent {
 					}
 					
 					CropUsageData cropUsage = cropUsages.get(crop);	
-					LogWriter.println("Updating " + commodity + " net imports " + crop + " to " + netImports);
+					LogWriter.println("Updating " + commodity + " net imports " + crop + " to " + netImports, 3);
 					cropUsage.updateNetImports(netImports);
 				}
 			}
@@ -227,7 +227,7 @@ public abstract class AbstractCountryAgent {
 					CropUsageData cropUsage = cropUsages.get(crop);
 					double prod =  cropUsage.getProductionExpected() *(1-crop.getSeedAndWasteRate()) - cropUsage.getMonogastricFeed() - cropUsage.getRuminantFeed();
 					double netImports = demand - prod;
-					LogWriter.println("Updating net imports " + crop + " to " + netImports);
+					LogWriter.println("Updating net imports " + crop + " to " + netImports, 3);
 					cropUsage.updateNetImports(netImports);
 				}
 			} 
diff --git a/src/ac/ed/lurg/country/gams/GamsDemandOptimiser.java b/src/ac/ed/lurg/country/gams/GamsDemandOptimiser.java
index 8990d4bc4b7cb11c687d1a947a871bf09d47b4eb..061cd4fa37cb0feeb96365b3e5f91f468c3c92c2 100755
--- a/src/ac/ed/lurg/country/gams/GamsDemandOptimiser.java
+++ b/src/ac/ed/lurg/country/gams/GamsDemandOptimiser.java
@@ -2,9 +2,11 @@ package ac.ed.lurg.country.gams;
 
 import java.io.File;
 import java.io.IOException;
+import java.nio.file.FileSystems;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashSet;
@@ -31,9 +33,11 @@ public class GamsDemandOptimiser {
 
 	private GamsDemandInput inputData;
 	private static final boolean DEBUG = false;
+	private boolean saveGamsGdxFiles;
 
 	public GamsDemandOptimiser(GamsDemandInput inputData) {
 		this.inputData = inputData;
+		saveGamsGdxFiles = (ModelConfig.GAMS_COUNTRY_TO_SAVE != null && inputData.getCountry().getCountryName().equals(ModelConfig.GAMS_COUNTRY_TO_SAVE));
 	}
 	
 	public GamsDemandOutput getDemandPc() {
@@ -62,7 +66,7 @@ public class GamsDemandOptimiser {
 		opt.defines("gdx_prices_and_gdp", inDB.getName());
 
 		if (ModelConfig.ADJUST_DIET_PREFS) {
-			LogWriter.println("Adusting diet params");
+			LogWriter.println("Adjusting diet params", 3);
 			GAMSDatabase originalParamDb = ws.addDatabaseFromGDX(new File(ModelConfig.DEMAND_PARAM_FILE).getAbsolutePath());
 			GAMSDatabase adjustedParamDb = ws.addDatabase(originalParamDb);
 			adjustDietParams(adjustedParamDb);
@@ -79,6 +83,9 @@ public class GamsDemandOptimiser {
 		
 		LogWriter.println("Took " + (System.currentTimeMillis() - startTime) + " ms to run", 3);
 		
+		if (saveGamsGdxFiles)
+			saveGDXFile("demand", workingDirectory.toFile());
+		
 		if (ModelConfig.CLEANUP_GAMS_DIR)  {
 			gamsJob.OutDB().dispose();
 			deleteDirectory(workingDirectory.toFile());
@@ -226,4 +233,22 @@ public class GamsDemandOptimiser {
 	    }
 	    return dir.delete();
 	}
+	
+	private void saveGDXFile(String ext, File tempDir) {
+		// some hacky code for debug purposes that keeps each gams gdx file
+		String country = inputData.getCountry().getCountryName().replaceAll("\\s+","");
+		int year = inputData.getYear();
+		try {
+			Files.copy(
+					FileSystems.getDefault().getPath(tempDir + File.separator + "_gams_java_gdb1.gdx"),
+					FileSystems.getDefault().getPath(ModelConfig.TEMP_DIR + File.separator + country + year + ext + ".gdx"),
+					StandardCopyOption.REPLACE_EXISTING);
+			Files.copy(
+					FileSystems.getDefault().getPath(tempDir + File.separator + "_gams_java_gjo1.lst"),
+					FileSystems.getDefault().getPath(ModelConfig.TEMP_DIR + File.separator + country + year + ext + "Listing" + ".lst"),
+					StandardCopyOption.REPLACE_EXISTING);
+		} catch (IOException e) {
+			LogWriter.print(e);
+		}
+	}
 }
diff --git a/src/ac/ed/lurg/country/gams/GamsLocationOptimiser.java b/src/ac/ed/lurg/country/gams/GamsLocationOptimiser.java
index af511068752166083e3c9bfb72553b5d24f4d499..507a195e8b8f2d004aa2ea5b73f6c2f824a64953 100644
--- a/src/ac/ed/lurg/country/gams/GamsLocationOptimiser.java
+++ b/src/ac/ed/lurg/country/gams/GamsLocationOptimiser.java
@@ -351,12 +351,9 @@ public class GamsLocationOptimiser {
 		addScalar(inDB, "unhandledCropRate", ModelConfig.UNHANDLED_CROP_RATE, 3);
 		addScalar(inDB, "setAsideRate", ModelConfig.SETASIDE_RATE, 5);
 		addScalar(inDB, "domesticPriceMarkup", ModelConfig.DOMESTIC_PRICE_MARKUP, 3);
-		double maxExpansion = 1.0;
-		if (!ModelConfig.IS_CALIBRATION_RUN && countryInput.getCountry().getName().equals("China")) {
-			maxExpansion = ModelConfig.MAX_CHINA_LAND_EXPANSION_RATE;
-		}
-		addScalar(inDB, "maxLandExpansionRate", maxExpansion, 3);
-		addScalar(inDB, "energycropsMaxProportion", ModelConfig.ENERGYCROPS_MAX_PROPORTION, 5);
+		addScalar(inDB, "maxGrossLccRate", ModelConfig.MAX_GROSS_LCC_RATE, 5);
+		addScalar(inDB, "maxFertChange", ModelConfig.MAX_FERT_CHANGE, 5);
+		addScalar(inDB, "maxIrrigChange", ModelConfig.MAX_IRRIG_CHANGE, 5);
 		
 		// Forestry
 		Map<WoodType, Double> woodDemandMap = countryInput.getWoodDemand();
diff --git a/src/ac/ed/lurg/demand/AbstractDemandManager.java b/src/ac/ed/lurg/demand/AbstractDemandManager.java
index b60384ec79b89132c6e60182c84e11c47e7871ca..127c3066470ee92d389b975029c823c3553fd835 100644
--- a/src/ac/ed/lurg/demand/AbstractDemandManager.java
+++ b/src/ac/ed/lurg/demand/AbstractDemandManager.java
@@ -1,5 +1,6 @@
 package ac.ed.lurg.demand;
 
+import java.io.Serializable;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -12,16 +13,21 @@ import ac.ed.lurg.types.CropType;
 import ac.ed.lurg.types.WoodType;
 import ac.ed.lurg.utils.LogWriter;
 
-public abstract class AbstractDemandManager {
+public abstract class AbstractDemandManager implements Serializable {
 
-	protected CompositeCountryManager compositeCountryManager;
-	protected CalorieManager calorieManager;
-	protected BioenergyDemandManager bioenergyDemandManager;
-	protected CerealFractionsManager cerealFractionsManager;
+	private static final long serialVersionUID = 8622023691732185744L;
+	protected transient CompositeCountryManager compositeCountryManager;
+	protected transient CalorieManager calorieManager;
+	protected transient BioenergyDemandManager bioenergyDemandManager;
+	protected transient CerealFractionsManager cerealFractionsManager;
 	protected CarbonDemandManager carbonDemandManager;
 	protected WoodDemandManager woodDemandManager;
 
 	public AbstractDemandManager(CompositeCountryManager compositeCountryManager, CalorieManager calorieManager) {
+		setup(compositeCountryManager, calorieManager);
+	}
+	
+	protected void setup(CompositeCountryManager compositeCountryManager, CalorieManager calorieManager) {
 		this.compositeCountryManager = compositeCountryManager;
 		this.calorieManager = calorieManager; 
 		bioenergyDemandManager = new BioenergyDemandManager();
@@ -40,7 +46,13 @@ public abstract class AbstractDemandManager {
 
 		for (SingleCountry c : compositeCountryManager.getAllForCompositeCountry(cc)) {
 
+			try {
 			foodDemandMap = getFoodDemand(c, year, prices, outputGamsDemand);
+			} catch (Exception e) {
+				LogWriter.printlnError("Error: AbstractDemandManager not including " + c + " due to exception");
+				LogWriter.print(e);
+				continue;
+			}
 
 			for (CommodityType commodity : CommodityType.getAllFoodItems()) {
 
diff --git a/src/ac/ed/lurg/demand/AbstractSSPDemandManager.java b/src/ac/ed/lurg/demand/AbstractSSPDemandManager.java
index beccd91852b98c99c0e5f218a0e24caf194081f9..153d194fa13db7d8eb7d064c4218186362c77268 100644
--- a/src/ac/ed/lurg/demand/AbstractSSPDemandManager.java
+++ b/src/ac/ed/lurg/demand/AbstractSSPDemandManager.java
@@ -15,29 +15,37 @@ import ac.ed.lurg.utils.LogWriter;
 
 public abstract class AbstractSSPDemandManager extends AbstractDemandManager {
 
-	protected SspManager sspManager;
-	protected String ssp_scenario;
-	protected BaseConsumpManager baseConsumpManager;
-	protected CalorieManager calorieManager;
-	private SingleCountry usa;
-	private AgriculturalGDPManager agriculturalGDPManager;
+	private static final long serialVersionUID = 1169375638148027645L;
+	protected transient SspManager sspManager;
+	protected transient String ssp_scenario;
+	protected transient BaseConsumpManager baseConsumpManager;
+	private transient SingleCountry usa;
+	private transient AgriculturalGDPManager agriculturalGDPManager;
 
 	public AbstractSSPDemandManager(String ssp_scenario, BaseConsumpManager baseConsumpManager,CalorieManager calorieManager, CompositeCountryManager compositeCountryManager) {
 		super(compositeCountryManager, calorieManager);
+		setup(ssp_scenario, baseConsumpManager);
+	}
+	
+	public void setup(String ssp_scenario, BaseConsumpManager baseConsumpManager) {
 		this.ssp_scenario = ssp_scenario;
 		this.baseConsumpManager = baseConsumpManager;
-		this.calorieManager = calorieManager;
 		sspManager = new SspManager();
 		usa = CountryManager.getForName("United States of America");
 		agriculturalGDPManager = new AgriculturalGDPManager();
 	}
 
+	protected void setup(String ssp_scenario, BaseConsumpManager baseConsumpManager, CalorieManager calorieManager, CompositeCountryManager compositeCountryManager) {
+		super.setup(compositeCountryManager, calorieManager);
+		setup(ssp_scenario, baseConsumpManager);
+	}
+	
 	@Override
 	public void updateGdpLossesFromShock(CompositeCountry cc, int year, double shockMagnitude) {
 
 		for (SingleCountry c : compositeCountryManager.getAllForCompositeCountry(cc)) {
 			SspData sd = sspManager.get(ssp_scenario, year, c);
-			LogWriter.println("sd data " + sd);
+			LogWriter.println("sd data " + sd, 3);
 			if(sd != null) {
 				double gdp = sd.getGdp();
 				double agriculturalGDPProportion = agriculturalGDPManager.getProportion(c);
diff --git a/src/ac/ed/lurg/demand/DemandManagerFromFile.java b/src/ac/ed/lurg/demand/DemandManagerFromFile.java
index a01eb0907d09c71362e690125b1d19fa1829a910..a4c63b6e44708387acc70ff4bc3798d95a64de47 100644
--- a/src/ac/ed/lurg/demand/DemandManagerFromFile.java
+++ b/src/ac/ed/lurg/demand/DemandManagerFromFile.java
@@ -14,6 +14,7 @@ import ac.ed.lurg.utils.StringTabularReader;
 
 public class DemandManagerFromFile extends AbstractDemandManager {
 
+	private static final long serialVersionUID = -3296655986819599788L;
 	private StringTabularReader historicalConsumptionReader;
 	private StringTabularReader histWoodConsumpReader;
 
diff --git a/src/ac/ed/lurg/demand/DemandManagerSSP.java b/src/ac/ed/lurg/demand/DemandManagerSSP.java
index 833695c185481f0cedbb99678bb2665be44507c0..67c37e4168521eb491749221d6d4a838a9597b8a 100644
--- a/src/ac/ed/lurg/demand/DemandManagerSSP.java
+++ b/src/ac/ed/lurg/demand/DemandManagerSSP.java
@@ -12,6 +12,7 @@ import ac.ed.lurg.types.WoodType;
 
 public class DemandManagerSSP extends AbstractSSPDemandManager {
 
+	private static final long serialVersionUID = 6500619362109439516L;
 	private DemandCurveManager demandCurveManager;
 
 	public DemandManagerSSP(String ssp_scenario, BaseConsumpManager baseConsumpManager, CalorieManager calorieManager, CompositeCountryManager compositeCountryManager) {
diff --git a/src/ac/ed/lurg/demand/ElasticDemandManager.java b/src/ac/ed/lurg/demand/ElasticDemandManager.java
index 0e7537966ad5255f186aa40207036980ce6fcfe1..7d53594ab0bf779fc5366ce7207a8571cc194dd9 100755
--- a/src/ac/ed/lurg/demand/ElasticDemandManager.java
+++ b/src/ac/ed/lurg/demand/ElasticDemandManager.java
@@ -19,15 +19,27 @@ import ac.ed.lurg.utils.LogWriter;
 
 public class ElasticDemandManager extends AbstractSSPDemandManager {
 
-	private Map<SingleCountry, Map<CommodityType, Double>> baseCpcCache = new HashMap<SingleCountry, Map<CommodityType, Double>>();
-	private Map<SingleCountry, GamsDemandOutput> previousGamsDemands = new HashMap<SingleCountry, GamsDemandOutput>();
-	private BufferedWriter outputFile;
+	private static final long serialVersionUID = -8605798315853420916L;
+	private Map<SingleCountry, Map<CommodityType, Double>> baseCpcCache;
+	private transient Map<SingleCountry, GamsDemandOutput> previousGamsDemands;
+	private transient BufferedWriter outputFile;
 	private PriceMarkUps priceMarkups;
+	private int baseYearToRebaseConsumption;
 
+	/** Constructor used in calibration only */
 	public ElasticDemandManager(String ssp_scenario, BaseConsumpManager baseConsumpManager, CalorieManager calorieManager, CompositeCountryManager compositeCountryManager) {
 		super(ssp_scenario, baseConsumpManager, calorieManager, compositeCountryManager);
-		priceMarkups = new PriceMarkUps();
 
+		this.priceMarkups = new PriceMarkUps();
+		baseCpcCache = new HashMap<SingleCountry, Map<CommodityType, Double>>();		
+		baseYearToRebaseConsumption = ModelConfig.BASE_YEAR;
+
+		setup();
+	}
+	
+	protected void setup() {
+		previousGamsDemands = new HashMap<SingleCountry, GamsDemandOutput>();
+		
 		try {
 			outputFile = FileWriterHelper.getFileWriter(true, true, ModelConfig.DEMAND_OPTIMISATION_OUTPUT_FILE, getDamsDemandOutputsHeader());
 		} catch (IOException e) {
@@ -35,6 +47,11 @@ public class ElasticDemandManager extends AbstractSSPDemandManager {
 		}
 	}
 
+	public void setup(String ssp_scenario, BaseConsumpManager baseConsumpManager, CalorieManager calorieManager, CompositeCountryManager compositeCountryManager) {
+		super.setup(ssp_scenario, baseConsumpManager, calorieManager, compositeCountryManager);
+		setup();
+	}
+	
 	@Override
 	Map<CommodityType, Double> getFoodDemandMap(SingleCountry c, int year, double gdpPc, double population, Map<CommodityType, Double> producerPrices, double usaGdpPc, boolean outputGamsDemand) {
 		Map<CommodityType, Double> consumerPrices = new HashMap<CommodityType, Double>();
@@ -50,10 +67,7 @@ public class ElasticDemandManager extends AbstractSSPDemandManager {
 			double producerPrice = producerPricePlum * (1000/kcalPerT.get(commodity) * 2000 *365);  //price per person per year commodity x per year assuming 2000 kcal a day
 
 			double consumerPrice = priceMarkups.markedupPrice(c, commodity, producerPrice);
-						
 			consumerPrices.put(commodity, consumerPrice);
-			LogWriter.println("Consumer price for " + commodity.getGamsName() + " is " + consumerPrice, 3);
-
 		}
 		
 		GamsDemandInput inputData = new GamsDemandInput(c, year, gdpPc, consumerPrices,kcalPerT, usaGdpPc, previousGamsDemands.get(c));
@@ -66,7 +80,7 @@ public class ElasticDemandManager extends AbstractSSPDemandManager {
 		Map<CommodityType, Double> foodPc = gamsOutput.getPlumDemands();
 
 		Map<CommodityType, Double> foodDemands = new HashMap<CommodityType, Double>();
-		SspData baseSspData = sspManager.get(ssp_scenario, ModelConfig.BASE_YEAR, c);
+		SspData baseSspData = sspManager.get(ssp_scenario, baseYearToRebaseConsumption, c);
 		double baseGdpPc = baseSspData.getGdpPc();
 
 		Map<CommodityType, Double> baseExpCpcMap = baseCpcCache.get(c);
@@ -142,6 +156,10 @@ public class ElasticDemandManager extends AbstractSSPDemandManager {
 		}
 	}
 	
+	public PriceMarkUps getPriceMarkups() {
+		return priceMarkups;
+	}
+	
 	@Override
 	public Map<WoodType, Double> getWoodDemandMap(SingleCountry country, double gdpPc, double baseGdpPc, double population, double basePopulation) {
 		Map<WoodType, Double> demandMap = new HashMap<WoodType, Double>();
diff --git a/src/ac/ed/lurg/landuse/ConversionCostReader.java b/src/ac/ed/lurg/landuse/ConversionCostReader.java
index cde141cb02eebef4a0f33b751732772bafd3433e..5b18af6bba3d4c13bfd111dbd46d16aa8d3ef323 100644
--- a/src/ac/ed/lurg/landuse/ConversionCostReader.java
+++ b/src/ac/ed/lurg/landuse/ConversionCostReader.java
@@ -62,31 +62,34 @@ public class ConversionCostReader {
 		LogWriter.println("Processed " + filename, 2);
 	}
 	
-	public void calcFromConfig() {		
-		conversionCosts.put(new LccKey(LandCoverType.CROPLAND, LandCoverType.PASTURE), ModelConfig.CROP_DECREASE_COST + ModelConfig.PASTURE_INCREASE_COST);
-		conversionCosts.put(new LccKey(LandCoverType.CROPLAND, LandCoverType.NATURAL), ModelConfig.CROP_DECREASE_COST);
-		conversionCosts.put(new LccKey(LandCoverType.CROPLAND, LandCoverType.TIMBER_FOREST), ModelConfig.CROP_DECREASE_COST + ModelConfig.MANAGED_FOREST_INCREASE_COST);
-		conversionCosts.put(new LccKey(LandCoverType.CROPLAND, LandCoverType.CARBON_FOREST), ModelConfig.CROP_DECREASE_COST + ModelConfig.MANAGED_FOREST_INCREASE_COST);
-		
-		conversionCosts.put(new LccKey(LandCoverType.PASTURE, LandCoverType.CROPLAND), ModelConfig.PASTURE_DECREASE_COST + ModelConfig.CROP_INCREASE_COST);
-		conversionCosts.put(new LccKey(LandCoverType.PASTURE, LandCoverType.NATURAL), ModelConfig.PASTURE_DECREASE_COST);
-		conversionCosts.put(new LccKey(LandCoverType.PASTURE, LandCoverType.TIMBER_FOREST), ModelConfig.PASTURE_DECREASE_COST + ModelConfig.MANAGED_FOREST_INCREASE_COST);
-		conversionCosts.put(new LccKey(LandCoverType.PASTURE, LandCoverType.CARBON_FOREST), ModelConfig.PASTURE_DECREASE_COST + ModelConfig.MANAGED_FOREST_INCREASE_COST);
-		
-		conversionCosts.put(new LccKey(LandCoverType.NATURAL, LandCoverType.CROPLAND), ModelConfig.CROP_INCREASE_COST);
-		conversionCosts.put(new LccKey(LandCoverType.NATURAL, LandCoverType.PASTURE), ModelConfig.PASTURE_INCREASE_COST);
-		conversionCosts.put(new LccKey(LandCoverType.NATURAL, LandCoverType.TIMBER_FOREST), ModelConfig.MANAGED_FOREST_INCREASE_COST);
-		conversionCosts.put(new LccKey(LandCoverType.NATURAL, LandCoverType.CARBON_FOREST), ModelConfig.MANAGED_FOREST_INCREASE_COST);
-		
-		conversionCosts.put(new LccKey(LandCoverType.TIMBER_FOREST, LandCoverType.CROPLAND), ModelConfig.MANAGED_FOREST_DECREASE_COST + ModelConfig.CROP_INCREASE_COST);
-		conversionCosts.put(new LccKey(LandCoverType.TIMBER_FOREST, LandCoverType.PASTURE), ModelConfig.MANAGED_FOREST_DECREASE_COST + ModelConfig.PASTURE_INCREASE_COST);
-		conversionCosts.put(new LccKey(LandCoverType.TIMBER_FOREST, LandCoverType.NATURAL), ModelConfig.MANAGED_FOREST_DECREASE_COST);
-		conversionCosts.put(new LccKey(LandCoverType.TIMBER_FOREST, LandCoverType.CARBON_FOREST), ModelConfig.MANAGED_FOREST_INCREASE_COST + ModelConfig.MANAGED_FOREST_DECREASE_COST);
-		
-		conversionCosts.put(new LccKey(LandCoverType.CARBON_FOREST, LandCoverType.CROPLAND), ModelConfig.MANAGED_FOREST_DECREASE_COST + ModelConfig.CROP_INCREASE_COST);
-		conversionCosts.put(new LccKey(LandCoverType.CARBON_FOREST, LandCoverType.PASTURE), ModelConfig.MANAGED_FOREST_DECREASE_COST + ModelConfig.PASTURE_INCREASE_COST);
-		conversionCosts.put(new LccKey(LandCoverType.CARBON_FOREST, LandCoverType.NATURAL), ModelConfig.MANAGED_FOREST_DECREASE_COST);
-		conversionCosts.put(new LccKey(LandCoverType.CARBON_FOREST, LandCoverType.TIMBER_FOREST), ModelConfig.MANAGED_FOREST_INCREASE_COST + ModelConfig.MANAGED_FOREST_DECREASE_COST);
+	public void calcFromConfig() {	
+		for (LandCoverType fromLc : LandCoverType.getConvertibleTypes()) {
+			for (LandCoverType toLc : LandCoverType.getConvertibleTypes()) {
+				if (fromLc.equals(toLc)) { // skip
+					continue;
+				}
+				switch(fromLc) {
+				case CROPLAND:
+					conversionCosts.put(new LccKey(fromLc, toLc), ModelConfig.CROPLAND_CONVERSION_COST);
+					break;
+				case PASTURE:
+					conversionCosts.put(new LccKey(fromLc, toLc), ModelConfig.PASTURE_CONVERSION_COST);
+					break;
+				case TIMBER_FOREST:
+					conversionCosts.put(new LccKey(fromLc, toLc), ModelConfig.FOREST_CONVERSION_COST);
+					break;
+				case CARBON_FOREST:
+					conversionCosts.put(new LccKey(fromLc, toLc), ModelConfig.FOREST_CONVERSION_COST);
+					break;
+				case NATURAL:
+					conversionCosts.put(new LccKey(fromLc, toLc), ModelConfig.NATURAL_CONVERSION_COST);
+					break;
+				default:
+					conversionCosts.put(new LccKey(fromLc, toLc), 0.0);
+					break;
+				}
+			}
+		}
 	}
 	
 	public void calcForSecondStageCalib() {
diff --git a/src/ac/ed/lurg/landuse/IrrigationRasterSet.java b/src/ac/ed/lurg/landuse/IrrigationRasterSet.java
index c63d57f9cf33afceb5170181cdd15b8f3f319670..df2d8b9fac50296c78e8220ae94b03fd1ef00185 100644
--- a/src/ac/ed/lurg/landuse/IrrigationRasterSet.java
+++ b/src/ac/ed/lurg/landuse/IrrigationRasterSet.java
@@ -25,7 +25,8 @@ public class IrrigationRasterSet extends RasterSet<IrrigationItem> {
 	}
 
 	public void updateIrrigConstraints(Timestep timestep) {
-		Map<RasterKey, Double> lpjIrrigConstraints = getIrrigFromLpjRunoff(timestep.getYear(), false);
+		int currentYear = ModelConfig.IS_CALIBRATION_RUN ? ModelConfig.BASE_YEAR : timestep.getYear();
+		Map<RasterKey, Double> lpjIrrigConstraints = getIrrigFromLpjRunoff(currentYear, false);
 		
 		for (Map.Entry<RasterKey, IrrigationItem> entry : entrySet()) {
 			IrrigationItem irrigItem = entry.getValue();