diff --git a/src/ac/ed/lurg/ModelConfig.java b/src/ac/ed/lurg/ModelConfig.java
index 6fc46c13b22a13b5d79d95e4edc4537af318c7bd..cf5ced4ca1ed4169c32f935b15075ddcd78534af 100755
--- a/src/ac/ed/lurg/ModelConfig.java
+++ b/src/ac/ed/lurg/ModelConfig.java
@@ -554,6 +554,9 @@ public class ModelConfig {
 	public static final double CONSTANT_PROTECTED_AREA_RATE = getDoubleProperty("CONSTANT_PROTECTED_AREA_RATE", Double.NaN);
 	public static final boolean HALFEARTH =  getBooleanProperty("HALFEARTH", false);
 
+	public static final boolean FORCE_LCC = getBooleanProperty("FORCE_LCC", false);
+	public static final String FORCED_LCC_FILES_DIR = getProperty("FORCED_LCC_FILES_DIR", OUTPUT_DIR);
+
 	public static final boolean USE_CRAFTY_COUNTRIES = getBooleanProperty("USE_CRAFTY_COUNTRIES", false);
 	public static final String CRAFTY_COUNTRIES_FILE= getProperty("CRAFTY_COUNTRIES_FILE", DATA_DIR + File.separator + "craftyCountries.csv");
 	public static final String CRAFTY_PRODUCTION_DIR = getProperty("CRAFTY_PRODUCTION_DIR", OUTPUT_DIR + File.separator + "crafty");
diff --git a/src/ac/ed/lurg/ModelMain.java b/src/ac/ed/lurg/ModelMain.java
index 21154b03f31888fe9baa8f81d82f08e021733e84..5ceb915ffa39cb20eaf504c94ebf146824b12beb 100644
--- a/src/ac/ed/lurg/ModelMain.java
+++ b/src/ac/ed/lurg/ModelMain.java
@@ -112,10 +112,14 @@ public class ModelMain {
 		getUpdateIrrigationData(timestep); // updating currentIrrigationData
 
 		// When running half earth we can to alter protected areas data at a point in time
-		if(ModelConfig.HALFEARTH && ModelConfig.FORCE_PROTECTED_AREAS_START_YEAR == timestep.getYear() && !ModelConfig.IS_CALIBRATION_RUN) {
+		if (ModelConfig.HALFEARTH && ModelConfig.FORCE_PROTECTED_AREAS_START_YEAR == timestep.getYear() && !ModelConfig.IS_CALIBRATION_RUN) {
 			new ProtectedAreasReader(globalLandUseRaster).getRasterDataFromFile(ModelConfig.HALF_EARTH_FILE);
 			countryAgents.updateProtectedAreasForAll(globalLandUseRaster);
 		}
+
+		if (ModelConfig.FORCE_LCC) {
+			forceLandCoverChanges(timestep);
+		}
 		
 		getWoodYieldData(timestep);
 		getCarbonFluxData(timestep);
@@ -875,6 +879,21 @@ public class ModelMain {
 			currentIrrigationData.updateIrrigConstraints(timestep);
 		}
 	}
+
+	private void forceLandCoverChanges(Timestep timestep) {
+		String filePath = ModelConfig.FORCED_LCC_FILES_DIR + File.separator + "forcedLcc" + timestep.getYear() + ".txt";
+		File file = new File(filePath);
+		if (file.exists()) {
+			RasterSet<ForcedLccItem> forcedLccRaster = new RasterSet<ForcedLccItem>(desiredProjection) {
+				protected ForcedLccItem createRasterData() {
+					return new ForcedLccItem();
+				}
+			};
+			LandCoverChangeReader lccReader = new LandCoverChangeReader(forcedLccRaster);
+			lccReader.getRasterDataFromFile(filePath);
+			countryAgents.forceLandCoverChangesForAll(forcedLccRaster);
+		}
+	}
 	
 	private void serializeCheckpoint() {
 		serializeLandUse(globalLandUseRaster);
diff --git a/src/ac/ed/lurg/country/CountryAgent.java b/src/ac/ed/lurg/country/CountryAgent.java
index 92c684207d1e8850d0db24310808f2ecdc4d2f80..2b6b2e86c95aa98a1c7adc1bfd15f4aa4711e85c 100644
--- a/src/ac/ed/lurg/country/CountryAgent.java
+++ b/src/ac/ed/lurg/country/CountryAgent.java
@@ -13,14 +13,9 @@ import ac.ed.lurg.country.gams.GamsRasterOptimiser;
 import ac.ed.lurg.country.gams.GamsRasterOutput;
 import ac.ed.lurg.demand.AbstractDemandManager;
 import ac.ed.lurg.forestry.WoodYieldItem;
-import ac.ed.lurg.landuse.CarbonUsageData;
-import ac.ed.lurg.landuse.CropUsageData;
-import ac.ed.lurg.landuse.IrrigationItem;
-import ac.ed.lurg.landuse.LandUseItem;
+import ac.ed.lurg.landuse.*;
 import ac.ed.lurg.shock.MinMaxNetImportManager;
 import ac.ed.lurg.shock.MinMaxNetImportManager.LimitType;
-import ac.ed.lurg.landuse.LccKey;
-import ac.ed.lurg.landuse.WoodUsageData;
 import ac.ed.lurg.types.CommodityType;
 import ac.ed.lurg.types.CropType;
 import ac.ed.lurg.types.LandCoverType;
@@ -347,6 +342,26 @@ public class CountryAgent extends AbstractCountryAgent {
 		}
 		
 	}
+
+	public void forceLandCoverChanges(RasterSet<ForcedLccItem> lccRaster) {
+		for (Map.Entry<RasterKey, ForcedLccItem> entry : lccRaster.entrySet()) {
+			RasterKey key = entry.getKey();
+			ForcedLccItem lccItem = entry.getValue();
+			if (previousGamsRasterOutput.getLandUses().containsKey(key)) {
+				LandUseItem landUseItem = previousGamsRasterOutput.getLandUses().get(key);
+				Map<LandCoverType, Map<LandCoverType, Double>> lccMap = lccItem.getFractions();
+				for (LandCoverType fromLc : lccMap.keySet()) {
+					Map<LandCoverType, Double> toMap = lccMap.get(fromLc);
+					for (LandCoverType toLc : toMap.keySet()) {
+						double fraction = toMap.get(toLc);
+						double previousArea = landUseItem.getLandCoverArea(fromLc, LandProtectionType.CONVERTIBLE);
+						double areaToMove = previousArea * fraction;
+						landUseItem.moveAreas(toLc, fromLc, areaToMove);
+					}
+				}
+			}
+		}
+	}
 	
 	public CarbonUsageData getCarbonUsageData() {
 		return previousGamsRasterOutput.getCarbonUsageData();
diff --git a/src/ac/ed/lurg/country/CountryAgentManager.java b/src/ac/ed/lurg/country/CountryAgentManager.java
index 771ec23089087bea10d7b4a4063abbb34780f6e8..5e4eb03220cba6fcc785cfcfcbd8e40f0349bc61 100644
--- a/src/ac/ed/lurg/country/CountryAgentManager.java
+++ b/src/ac/ed/lurg/country/CountryAgentManager.java
@@ -22,16 +22,10 @@ import ac.ed.lurg.country.crafty.CraftyProdManager;
 import ac.ed.lurg.demand.AbstractDemandManager;
 import ac.ed.lurg.forestry.WoodYieldItem;
 import ac.ed.lurg.forestry.WoodYieldRasterSet;
-import ac.ed.lurg.landuse.CarbonUsageData;
-import ac.ed.lurg.landuse.CropUsageData;
-import ac.ed.lurg.landuse.IrrigationItem;
-import ac.ed.lurg.landuse.IrrigationRasterSet;
-import ac.ed.lurg.landuse.LandUseItem;
+import ac.ed.lurg.landuse.*;
 import ac.ed.lurg.shock.ExportRestrictionManager;
 import ac.ed.lurg.shock.MinMaxNetImportManager;
 import ac.ed.lurg.shock.MinMaxNetImportManager.LimitType;
-import ac.ed.lurg.landuse.LccKey;
-import ac.ed.lurg.landuse.WoodUsageData;
 import ac.ed.lurg.types.CropType;
 import ac.ed.lurg.types.WoodType;
 import ac.ed.lurg.utils.LogWriter;
@@ -190,6 +184,22 @@ public class CountryAgentManager {
 			ca.updateProtectedAreas(newPA);
 		}
 	}
+
+	public void forceLandCoverChangesForAll(RasterSet<ForcedLccItem> lccRaster) {
+		for (CountryAgent ca : gamsCountryAgents) {
+			Collection<RasterKey> countryKeys = countryBoundaryRaster.getKeysFor(ca.getCountry());
+			RasterSet<ForcedLccItem> lccRasterForCountry = new RasterSet<ForcedLccItem>(lccRaster.getHeaderDetails());
+			for (RasterKey key : countryKeys) {
+				if (lccRaster.containsKey(key)) {
+					lccRasterForCountry.put(key, lccRaster.get(key));
+				}
+			}
+			if (!lccRasterForCountry.isEmpty()) {
+				ca.forceLandCoverChanges(lccRasterForCountry);
+			}
+
+		}
+	}
 	
 	public void serializeCropUsageForAll() {
 		Map<CompositeCountry, Map<CropType, CropUsageData>> cropUsageDataMap = new HashMap<CompositeCountry, Map<CropType, CropUsageData>>();
diff --git a/src/ac/ed/lurg/country/gams/GamsLocationOptimiser.java b/src/ac/ed/lurg/country/gams/GamsLocationOptimiser.java
index 74ac942d4ef83baf780d35b8a3e3ec6d4eb249e7..b56b459127479426ea4b0a90256f26a18c26e8cc 100644
--- a/src/ac/ed/lurg/country/gams/GamsLocationOptimiser.java
+++ b/src/ac/ed/lurg/country/gams/GamsLocationOptimiser.java
@@ -27,7 +27,7 @@ import com.gams.api.GAMSWorkspaceInfo;
 import ac.ed.lurg.ModelConfig;
 import ac.ed.lurg.carbon.CarbonFluxItem;
 import ac.ed.lurg.country.CountryPrice;
-import ac.ed.lurg.country.LandCoverChangeItem;
+import ac.ed.lurg.landuse.LandCoverChangeItem;
 import ac.ed.lurg.country.TradeConstraint;
 import ac.ed.lurg.forestry.WoodYieldData;
 import ac.ed.lurg.landuse.CarbonUsageData;
diff --git a/src/ac/ed/lurg/country/gams/GamsLocationOutput.java b/src/ac/ed/lurg/country/gams/GamsLocationOutput.java
index a6d8b4b83d06c8fec04c73d42f3641013b0f3cd2..ebbc2e2e1ea6b7c8e18db80c24baf8a8b17968fa 100644
--- a/src/ac/ed/lurg/country/gams/GamsLocationOutput.java
+++ b/src/ac/ed/lurg/country/gams/GamsLocationOutput.java
@@ -1,6 +1,5 @@
 package ac.ed.lurg.country.gams;
 
-import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
@@ -12,7 +11,7 @@ import ac.ed.lurg.landuse.LandUseItem;
 import ac.ed.lurg.landuse.WoodUsageData;
 import ac.ed.lurg.types.CropType;
 import ac.ed.lurg.types.WoodType;
-import ac.ed.lurg.country.LandCoverChangeItem;
+import ac.ed.lurg.landuse.LandCoverChangeItem;
 
 public class GamsLocationOutput {
 	ModelStat status;
diff --git a/src/ac/ed/lurg/country/gams/GamsRasterOptimiser.java b/src/ac/ed/lurg/country/gams/GamsRasterOptimiser.java
index 019d50d9803c061f69949fa3f214b908ef4d85ab..4427ecb8d1918ce2d3bdba05331684086eb66a27 100644
--- a/src/ac/ed/lurg/country/gams/GamsRasterOptimiser.java
+++ b/src/ac/ed/lurg/country/gams/GamsRasterOptimiser.java
@@ -5,7 +5,7 @@ import java.util.Map.Entry;
 
 import ac.ed.lurg.ModelConfig;
 import ac.ed.lurg.carbon.CarbonFluxItem;
-import ac.ed.lurg.country.LandCoverChangeItem;
+import ac.ed.lurg.landuse.LandCoverChangeItem;
 import ac.ed.lurg.forestry.WoodYieldData;
 import ac.ed.lurg.forestry.WoodYieldItem;
 import ac.ed.lurg.landuse.*;
diff --git a/src/ac/ed/lurg/landuse/ForcedLccItem.java b/src/ac/ed/lurg/landuse/ForcedLccItem.java
new file mode 100644
index 0000000000000000000000000000000000000000..b2d795edb0c6c74072838e95d282fd10e74e0ca9
--- /dev/null
+++ b/src/ac/ed/lurg/landuse/ForcedLccItem.java
@@ -0,0 +1,24 @@
+package ac.ed.lurg.landuse;
+
+import ac.ed.lurg.types.LandCoverType;
+import ac.sac.raster.RasterItem;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class ForcedLccItem implements RasterItem {
+    private final Map<LandCoverType, Map<LandCoverType, Double>> fractions;
+
+    public ForcedLccItem() {
+        fractions = new HashMap<>();
+    }
+
+    public void setFraction(LandCoverType fromLc, LandCoverType toLc, double fract) {
+        Map<LandCoverType, Double> toMap = fractions.computeIfAbsent(fromLc, k -> new HashMap<>());
+        toMap.put(toLc, fract);
+    }
+
+    public Map<LandCoverType, Map<LandCoverType, Double>> getFractions() {
+        return fractions;
+    }
+}
diff --git a/src/ac/ed/lurg/country/LandCoverChangeItem.java b/src/ac/ed/lurg/landuse/LandCoverChangeItem.java
similarity index 61%
rename from src/ac/ed/lurg/country/LandCoverChangeItem.java
rename to src/ac/ed/lurg/landuse/LandCoverChangeItem.java
index e464e43946f215be0f2a56b76923bac7e11af1a3..dbc9a8007326156b2ebb10bc58043e1bc969bf17 100644
--- a/src/ac/ed/lurg/country/LandCoverChangeItem.java
+++ b/src/ac/ed/lurg/landuse/LandCoverChangeItem.java
@@ -1,11 +1,11 @@
-package ac.ed.lurg.country;
+package ac.ed.lurg.landuse;
 
 import ac.ed.lurg.types.LandCoverType;
+import ac.sac.raster.RasterItem;
 
-public class LandCoverChangeItem {
+public class LandCoverChangeItem implements RasterItem {
 	private LandCoverType fromLandCover;
 	private LandCoverType toLandCover;
-	private int age;
 	private double area;
 	
 	public LandCoverChangeItem() {}
@@ -16,13 +16,6 @@ public class LandCoverChangeItem {
 		this.area = area;
 	}
 
-	public LandCoverChangeItem(LandCoverType fromLandCover, LandCoverType toLandCover, int age, double area) {
-		this.fromLandCover = fromLandCover;
-		this.toLandCover = toLandCover;
-		this.age = age;
-		this.area = area;
-	}
-
 	public LandCoverType getFromLandCover() {
 		return fromLandCover;
 	}
@@ -31,10 +24,6 @@ public class LandCoverChangeItem {
 		return toLandCover;
 	}
 
-	public int getAge() {
-		return age;
-	}
-
 	public double getArea() {
 		return area;
 	}
diff --git a/src/ac/ed/lurg/landuse/LandCoverChangeReader.java b/src/ac/ed/lurg/landuse/LandCoverChangeReader.java
new file mode 100644
index 0000000000000000000000000000000000000000..76a7f4b4211c702d2e6cd961e19ba98658bc3560
--- /dev/null
+++ b/src/ac/ed/lurg/landuse/LandCoverChangeReader.java
@@ -0,0 +1,29 @@
+package ac.ed.lurg.landuse;
+
+import ac.ed.lurg.types.LandCoverType;
+import ac.sac.raster.AbstractTabularRasterReader;
+import ac.sac.raster.RasterKey;
+import ac.sac.raster.RasterSet;
+
+import java.util.Map;
+
+public class LandCoverChangeReader extends AbstractTabularRasterReader<ForcedLccItem> {
+    private static final int MIN_COLS = 3;
+
+    public LandCoverChangeReader(RasterSet<ForcedLccItem> lccRaster) {
+        super(" +", MIN_COLS, lccRaster);
+    }
+
+    @Override
+    protected void setData(RasterKey key, ForcedLccItem item, Map<String, Double> rowValues) {
+        for (LandCoverType fromLc : LandCoverType.values()) {
+            for (LandCoverType toLc : LandCoverType.values()) {
+                String colName = fromLc.getName() + "->" + toLc.getName();
+                if (rowValues.containsKey(colName)) {
+                    double fract = getValueForCol(rowValues, colName);
+                    item.setFraction(fromLc, toLc, fract);
+                }
+            }
+        }
+    }
+}