From c3eaa31e4c2f9c5779ae9e1e7bd00291ef9db066 Mon Sep 17 00:00:00 2001
From: Roslyn Henry <roslyn.henry@ed.ac.uk>
Date: Mon, 7 Jun 2021 16:06:24 +0100
Subject: [PATCH] Honour spatial arrangement of protected areas throughout
 simulation, not only when forced.

---
 .../country/gams/GamsRasterOptimiser.java     | 87 +++++++++----------
 1 file changed, 42 insertions(+), 45 deletions(-)

diff --git a/src/ac/ed/lurg/country/gams/GamsRasterOptimiser.java b/src/ac/ed/lurg/country/gams/GamsRasterOptimiser.java
index d75c384e..5fe27e05 100644
--- a/src/ac/ed/lurg/country/gams/GamsRasterOptimiser.java
+++ b/src/ac/ed/lurg/country/gams/GamsRasterOptimiser.java
@@ -110,7 +110,7 @@ public class GamsRasterOptimiser {
 			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);
-			
+
 			if (DEBUG) {
 				checkedTotalAreas(landUseItemsForLocation, locId + " before");
 				LogWriter.println("pastureChange " + gamsPastureChange);
@@ -128,58 +128,55 @@ public class GamsRasterOptimiser {
 			double prevForestTotal = prevManagedForest + prevUnmanagedForest;
 			double prevForestToNaturalFraction = (prevNatural > 0) ? prevForestTotal / prevNatural : 0;
 			double prevForestManagedFraction = (prevForestTotal > 0) ? prevManagedForest / prevForestTotal : 0;
-			
+
 			if(prevForestToNaturalFraction > 1.0) prevForestToNaturalFraction = 1.0;
 			if(prevForestManagedFraction > 1.0) prevForestManagedFraction = 1.0;
-			
-			//this tries to honour spatial distribution of protected areas, force removal of pasture and cropland from protected areas 
-			if (ModelConfig.FORCE_PROTECTED_AREAS && year >= ModelConfig.FORCE_PROTECTED_AREAS_START_YEAR) {
-				double protectedLandShortfall = 0;
-
-				for (LandUseItem luItem: landUseItemsForLocation.values()) {
-
-					double suitableLand = luItem.getSuitableArea();
-					double prevCropland = luItem.getLandCoverArea(LandCoverType.CROPLAND);
-					double prevPasture = luItem.getLandCoverArea(LandCoverType.PASTURE);
-
-					//if we have more agricultural land in this cell than we should, remove it and add it to land needing reallocated 
-					if (suitableLand < (prevCropland + prevPasture)) {
-
-						double excessAgriculture = prevCropland + prevPasture - suitableLand;
-						double prevPastureFract = prevPasture / (prevCropland + prevPasture);
-						double pastureShortfall = excessAgriculture * prevPastureFract;
-						double croplandShortfall = excessAgriculture * (1 - prevPastureFract);
-
-						protectedLandShortfall += luItem.moveAreas(LandCoverType.MANAGED_FOREST, LandCoverType.PASTURE,
-								pastureShortfall * prevForestToNaturalFraction * prevForestManagedFraction);
-						protectedLandShortfall += luItem.moveAreas(LandCoverType.UNMANAGED_FOREST, LandCoverType.PASTURE,
-								pastureShortfall * prevForestToNaturalFraction * (1 - prevForestManagedFraction));
-						protectedLandShortfall += luItem.moveAreas(LandCoverType.OTHER_NATURAL, LandCoverType.PASTURE,
-								pastureShortfall * (1 - prevForestToNaturalFraction));
-						protectedLandShortfall += luItem.moveAreas(LandCoverType.MANAGED_FOREST, LandCoverType.CROPLAND,
-								croplandShortfall * prevForestToNaturalFraction * prevForestManagedFraction);
-						protectedLandShortfall += luItem.moveAreas(LandCoverType.UNMANAGED_FOREST, LandCoverType.CROPLAND,
-								croplandShortfall * prevForestToNaturalFraction * (1 - prevForestManagedFraction));
-						protectedLandShortfall += luItem.moveAreas(LandCoverType.OTHER_NATURAL, LandCoverType.CROPLAND,
-								croplandShortfall * (1 - prevForestToNaturalFraction));
-
-						protectedAreasPastureChange+= pastureShortfall;
-						protectedAreasCroplandChange+= croplandShortfall;
-					}
 
-				}
+			//this tries to honour spatial distribution of protected areas, force removal of pasture and cropland from protected areas and reallocate within cluster location
+			double protectedLandShortfall = 0;
 
-				if(protectedLandShortfall > 0.00001) {
-					LogWriter.printlnWarning("locID " + locId + " Not able to incorporate all protected area changes " + protectedLandShortfall + " remains unprotected.");
-				}
+			for (LandUseItem luItem: landUseItemsForLocation.values()) {
 
-				if (DEBUG) {
-					LogWriter.println("protectedAreasPastureChange " + protectedAreasPastureChange + " protectedAreasCroplandChange " + protectedAreasCroplandChange);
+				double suitableLand = luItem.getSuitableArea();
+				double prevCropland = luItem.getLandCoverArea(LandCoverType.CROPLAND);
+				double prevPasture = luItem.getLandCoverArea(LandCoverType.PASTURE);
+
+				//if we have more agricultural land in this cell than we should, remove it and add it to land needing reallocated 
+				if (suitableLand < (prevCropland + prevPasture)) {
+
+					double excessAgriculture = prevCropland + prevPasture - suitableLand;
+					double prevPastureFract = prevPasture / (prevCropland + prevPasture);
+					double pastureShortfall = excessAgriculture * prevPastureFract;
+					double croplandShortfall = excessAgriculture * (1 - prevPastureFract);
+
+					protectedLandShortfall += luItem.moveAreas(LandCoverType.MANAGED_FOREST, LandCoverType.PASTURE,
+							pastureShortfall * prevForestToNaturalFraction * prevForestManagedFraction);
+					protectedLandShortfall += luItem.moveAreas(LandCoverType.UNMANAGED_FOREST, LandCoverType.PASTURE,
+							pastureShortfall * prevForestToNaturalFraction * (1 - prevForestManagedFraction));
+					protectedLandShortfall += luItem.moveAreas(LandCoverType.OTHER_NATURAL, LandCoverType.PASTURE,
+							pastureShortfall * (1 - prevForestToNaturalFraction));
+					protectedLandShortfall += luItem.moveAreas(LandCoverType.MANAGED_FOREST, LandCoverType.CROPLAND,
+							croplandShortfall * prevForestToNaturalFraction * prevForestManagedFraction);
+					protectedLandShortfall += luItem.moveAreas(LandCoverType.UNMANAGED_FOREST, LandCoverType.CROPLAND,
+							croplandShortfall * prevForestToNaturalFraction * (1 - prevForestManagedFraction));
+					protectedLandShortfall += luItem.moveAreas(LandCoverType.OTHER_NATURAL, LandCoverType.CROPLAND,
+							croplandShortfall * (1 - prevForestToNaturalFraction));
+
+					protectedAreasPastureChange+= pastureShortfall;
+					protectedAreasCroplandChange+= croplandShortfall;
 				}
 
+			}
 
+			if(protectedLandShortfall > 0.00001) {
+				LogWriter.printlnWarning("locID " + locId + " Not able to incorporate all protected area changes " + protectedLandShortfall + " remains unprotected.");
 			}
 
+			if (DEBUG) {
+				LogWriter.println("protectedAreasPastureChange " + protectedAreasPastureChange + " protectedAreasCroplandChange " + protectedAreasCroplandChange);
+			}
+
+
 			double totalPastureChange = protectedAreasPastureChange + gamsPastureChange;
 			double totalCroplandChange = protectedAreasCroplandChange + gamsCroplandChange;
 
@@ -235,7 +232,7 @@ public class GamsRasterOptimiser {
 				}
 			}
 		}
-		
+
 		return newLandUseRaster;
 	}
 
@@ -265,7 +262,7 @@ public class GamsRasterOptimiser {
 		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);
-- 
GitLab