From 38f223e40f0bf34da3e39dc9021b646d8ed537c0 Mon Sep 17 00:00:00 2001
From: Peter Alexander <peter@blackhillock.co.uk>
Date: Tue, 13 Nov 2018 14:28:59 +0100
Subject: [PATCH] Fix allocation of land use change issue "This should never
 happen.. " error

---
 src/ac/ed/lurg/ModelMain.java                 | 22 +++++---------
 .../country/gams/GamsRasterOptimiser.java     | 29 ++++++++++---------
 src/ac/ed/lurg/utils/LogWriter.java           |  7 ++++-
 3 files changed, 30 insertions(+), 28 deletions(-)

diff --git a/src/ac/ed/lurg/ModelMain.java b/src/ac/ed/lurg/ModelMain.java
index 273e11ba..ed0e5abc 100644
--- a/src/ac/ed/lurg/ModelMain.java
+++ b/src/ac/ed/lurg/ModelMain.java
@@ -45,15 +45,12 @@ import ac.ed.lurg.landuse.ProtectedAreasReader;
 import ac.ed.lurg.landuse.RunOffReader;
 import ac.ed.lurg.output.LandUseOutputer;
 import ac.ed.lurg.output.LpjgOutputer;
-import ac.ed.lurg.shock.YieldShockReader;
-import ac.ed.lurg.shock.YieldShocks;
 import ac.ed.lurg.types.CommodityType;
 import ac.ed.lurg.types.CropType;
 import ac.ed.lurg.types.LandCoverType;
 import ac.ed.lurg.utils.LogWriter;
 import ac.ed.lurg.yield.LPJYieldResponseMapReader;
 import ac.ed.lurg.yield.YieldRaster;
-import ac.ed.lurg.yield.YieldResponsesItem;
 import ac.sac.raster.IntegerRasterItem;
 import ac.sac.raster.IntegerRasterReader;
 import ac.sac.raster.InterpolatingRasterSet;
@@ -128,10 +125,6 @@ public class ModelMain {
 		YieldRaster yieldSurfaces = getYieldSurfaces(timestep); // this will wait for the marker file from LPJ if configured to do so
 		getUpdateIrrigationData(timestep, yieldSurfaces); // updating currentIrrigationData
 
-		YieldResponsesItem yresp = yieldSurfaces.getFromCoordinates(-90.5, 45.5);
-		LogWriter.printlnError("Test key: " + yresp.getYieldMax(CropType.MAIZE) + ", " + yresp.getYieldFertOnly(CropType.MAIZE) + ", "
-						+ yresp.getYieldIrrigOnly(CropType.MAIZE) + ", " + yresp.getYieldNone(CropType.MAIZE));
-
 		double previousGen2EcDDemand = (timestep.isInitialTimestep() || ModelConfig.IS_CALIBRATION_RUN ) ? 0: demandManager.getSecondGenBioenergyDemand(timestep.getPreviousTimestep());
 		double gen2EcDDemand = demandManager.getSecondGenBioenergyDemand(ModelConfig.IS_CALIBRATION_RUN ? new Timestep(1) : timestep);
 		double gen2Increase = (gen2EcDDemand>previousGen2EcDDemand) ? gen2EcDDemand - previousGen2EcDDemand : 0.0;
@@ -374,7 +367,7 @@ private void writeDomesticProductionFile(Timestep timestep) {
 
 		if (ModelConfig.OUTPUT_FOR_LPJG) {
 			for (int outputYear : timestep.getYearsFromLast()) {
-				LogWriter.printlnError("Outputing Year: " + outputYear);
+				LogWriter.println("Outputing Year: " + outputYear);
 				RasterSet<LandUseItem> landUseToOutput = null;
 
 				if (outputYear == timestep.getYear()) {
@@ -579,10 +572,11 @@ private void writeDomesticProductionFile(Timestep timestep) {
 	private YieldRaster getYieldSurfaces(Timestep timestep) {
 		LPJYieldResponseMapReader yieldReader = new LPJYieldResponseMapReader(desiredProjection);
 		YieldRaster yieldRaster = yieldReader.getRasterData(timestep);
-		
+	
+		/*
 		YieldResponsesItem yresp = yieldRaster.getFromCoordinates(-90.5, 45.5);
-		LogWriter.printlnError("Test key: " + yresp.getYieldMax(CropType.MAIZE) + ", " + yresp.getYieldFertOnly(CropType.MAIZE) + ", "
-						+ yresp.getYieldIrrigOnly(CropType.MAIZE) + ", " + yresp.getYieldNone(CropType.MAIZE));
+	//	LogWriter.println("Test key: " + yresp.getYieldMax(CropType.MAIZE) + ", " + yresp.getYieldFertOnly(CropType.MAIZE) + ", "
+	//					+ yresp.getYieldIrrigOnly(CropType.MAIZE) + ", " + yresp.getYieldNone(CropType.MAIZE));
 
 		// read in shocks for timestep
 		// for each, get shock map and apply to yieldRaster
@@ -597,9 +591,9 @@ private void writeDomesticProductionFile(Timestep timestep) {
 		}
 		
 		yresp = yieldRaster.getFromCoordinates(-90.5, 45.5);
-		LogWriter.printlnError("Test key: " + yresp.getYieldMax(CropType.MAIZE) + ", " + yresp.getYieldFertOnly(CropType.MAIZE) + ", "
-						+ yresp.getYieldIrrigOnly(CropType.MAIZE) + ", " + yresp.getYieldNone(CropType.MAIZE));
-
+	//	LogWriter.println("Test key: " + yresp.getYieldMax(CropType.MAIZE) + ", " + yresp.getYieldFertOnly(CropType.MAIZE) + ", "
+	//					+ yresp.getYieldIrrigOnly(CropType.MAIZE) + ", " + yresp.getYieldNone(CropType.MAIZE));
+*/
 		return yieldRaster;
 	}
 
diff --git a/src/ac/ed/lurg/country/gams/GamsRasterOptimiser.java b/src/ac/ed/lurg/country/gams/GamsRasterOptimiser.java
index ca9f71d8..ce75a94e 100644
--- a/src/ac/ed/lurg/country/gams/GamsRasterOptimiser.java
+++ b/src/ac/ed/lurg/country/gams/GamsRasterOptimiser.java
@@ -40,7 +40,7 @@ public class GamsRasterOptimiser {
 		GamsLocationOutput gamsOutput = opti.run();
 
 		long last = System.currentTimeMillis();
-		LogWriter.printlnError("Took " + (last-start));
+		LogWriter.println("Took " + (last-start));
 
 		// map results back to raster
 		return convertToRaster(gamsInput, gamsOutput);
@@ -73,7 +73,7 @@ public class GamsRasterOptimiser {
 					total += a.getLandCoverArea(l);
 			}
 
-			LogWriter.printlnError("Total Area " + comment + ": " + l.getName() + ": " + total);
+			LogWriter.println("Total Area " + comment + ": " + l.getName() + ": " + total);
 		}
 		
 		double unprotectedNatural=0, suitableArea=0, protectedArea=0;
@@ -121,9 +121,9 @@ public class GamsRasterOptimiser {
 			double prevManagedForest = 0, prevUnmanagedForest = 0, prevNatural = 0;  
 			
 			for (LandUseItem luItem: landUseItemsForLocation.values()) {
-				prevManagedForest += luItem.getLandCoverArea(LandCoverType.MANAGED_FOREST);
-				prevUnmanagedForest += luItem.getLandCoverArea(LandCoverType.UNMANAGED_FOREST);
-				prevNatural += luItem.getTotalNatural();
+				prevManagedForest += luItem.getUnprotectedLandCoverArea(LandCoverType.MANAGED_FOREST);
+				prevUnmanagedForest += luItem.getUnprotectedLandCoverArea(LandCoverType.UNMANAGED_FOREST);
+				prevNatural += luItem.getUnprotectedNatural();
 			}
 			
 			double prevForestTotal = prevManagedForest + prevUnmanagedForest;
@@ -199,8 +199,10 @@ public class GamsRasterOptimiser {
 		
 		double shortfall = allocAllLandCrops(newLandUseRaster, keys, toType, fromType, change);
 		
-		if (shortfall > 0.00001)
+		if (shortfall > 0.00001) {
 			LogWriter.printlnError("This should never happen, due to GAMS constraint. Not able to incorporate all changes: from " + fromLC + " to " + toLC + " " + locId + ": " + shortfall);
+			System.exit(-123);
+		}
 	}
 
 	private double allocAllLandCrops(RasterSet<LandUseItem> newLandUseRaster, Set<RasterKey> keys, LandCoverType toType, LandCoverType fromType, double change) {
@@ -231,6 +233,7 @@ public class GamsRasterOptimiser {
 			}
 		}
 
+		// Now we check for unprotected areas, I think this is redundant.  However, it does cause a problem so leaving just in case it is needed.
 		if (totalShortfall > 0 & keysWithSpace.size() > 0) {  // more to allocate and some free areas to allocate into
 			if (DEBUG) LogWriter.println("A total land cover of " + totalShortfall + " is unallocated, so trying again with areas with space");
 			totalShortfall = allocAllLandCrops(newLandUseRaster, keysWithSpace, toType, fromType, totalShortfall);
@@ -289,7 +292,7 @@ public class GamsRasterOptimiser {
 			CropType crop = CropType.WHEAT;
 
 			if (yresp != null && (yresp.getYieldMax(crop) < yresp.getYieldFertOnly(crop) || yresp.getYieldMax(crop) < yresp.getYieldIrrigOnly(crop))) {
-				logErrorWithCoord("Inconsistency F only:" + yresp.getYieldFertOnly(crop) + ", I only" + yresp.getYieldIrrigOnly(crop) + ", max " + yresp.getYieldMax(crop) + " at ", key, yieldRaster);
+				logWarningWithCoord("Inconsistency F only:" + yresp.getYieldFertOnly(crop) + ", I only" + yresp.getYieldIrrigOnly(crop) + ", max " + yresp.getYieldMax(crop) + " at ", key, yieldRaster);
 			}
 		}
 		
@@ -349,7 +352,7 @@ public class GamsRasterOptimiser {
 							double irrigMax = irrigItem.getMaxIrrigAmount(crop);
 	
 							if (Double.isNaN(irrigMax))
-								logErrorWithCoord("Can't find irrig max amount for ", key, yieldRaster, crop);
+								logWarningWithCoord("Can't find irrig max amount for ", key, yieldRaster, crop);
 							else 
 								aggIrig.setMaxIrrigAmount(crop, aggregateMean(aggIrig.getMaxIrrigAmount(crop), suitableAreaSoFar, irrigMax, suitableAreaThisTime));
 						}
@@ -357,7 +360,7 @@ public class GamsRasterOptimiser {
 						for (YieldType yieldType : YieldType.values()) {
 							double y = yresp.getYield(yieldType, crop);
 							if (Double.isNaN(y))
-								logErrorWithCoord("Problem getting yield for type:" + yieldType + ", ", key, yieldRaster, crop);
+								logWarningWithCoord("Problem getting yield for type:" + yieldType + ", ", key, yieldRaster, crop);
 							else {
 								double yieldSoFar = aggYResp.getYield(yieldType, crop);
 								double updatedYield = aggregateMean(yieldSoFar, suitableAreaSoFar, y, suitableAreaThisTime);
@@ -420,12 +423,12 @@ public class GamsRasterOptimiser {
 		return new GamsLocationInput(rasterInputData.getTimestep(), aggregatedYields, aggregatedAreas, aggregatedIrrigCosts, rasterInputData.getCountryInput());
 	}
 	
-	private void logErrorWithCoord(String message, RasterKey key, YieldRaster yieldRaster, CropType crop) {
-		logErrorWithCoord(message + "crop:" + crop + ", ", key, yieldRaster);
+	private void logWarningWithCoord(String message, RasterKey key, YieldRaster yieldRaster, CropType crop) {
+		logWarningWithCoord(message + "crop:" + crop + ", ", key, yieldRaster);
 	}
 	
-	private void logErrorWithCoord(String message, RasterKey key, YieldRaster yieldRaster) {
-		LogWriter.printlnError(message + key + ", x:" + yieldRaster.getXCoordin(key) + ", y:" + yieldRaster.getYCoordin(key));
+	private void logWarningWithCoord(String message, RasterKey key, YieldRaster yieldRaster) {
+		LogWriter.printlnWarning(message + key + ", x:" + yieldRaster.getXCoordin(key) + ", y:" + yieldRaster.getYCoordin(key));
 	}
 	
 	private double aggregateMean(double aggV, double aggArea, double newV, double newArea) {
diff --git a/src/ac/ed/lurg/utils/LogWriter.java b/src/ac/ed/lurg/utils/LogWriter.java
index f0f4d173..59edf619 100644
--- a/src/ac/ed/lurg/utils/LogWriter.java
+++ b/src/ac/ed/lurg/utils/LogWriter.java
@@ -23,9 +23,14 @@ public class LogWriter {
 	}
 	
 	public static synchronized void printlnError(String s) {
-		getLogWriter().print(s, System.err, true);
+		getLogWriter().print("Error: " + s, System.err, true);
 	}
 	
+	public static synchronized void printlnWarning(String s) {
+		getLogWriter().print("Warning: " + s, System.err, true);
+	}
+
+	
 	public static synchronized void print(Exception e) {
 	    e.printStackTrace(getLogWriter().logFile);
 	    
-- 
GitLab