From 2b5e9e64c32a29c83162ceb007d36af14898fcdd Mon Sep 17 00:00:00 2001
From: Peter Alexander <peter@blackhillock.co.uk>
Date: Wed, 11 Jan 2017 12:23:47 +0000
Subject: [PATCH] Changes for new LPJ data version.  Also, some demand work.

---
 GAMS/IntExtOpt.gms                            |   4 +-
 GAMS/demand.gms                               |  64 ++++----
 debug_config.properties                       |  14 +-
 src/ac/ed/lurg/ModelConfig.java               |   6 +-
 src/ac/ed/lurg/Timestep.java                  |   2 +-
 .../country/gams/GamsDemandOptimiser.java     | 143 ++++++++++++++++++
 6 files changed, 193 insertions(+), 40 deletions(-)
 create mode 100644 src/ac/ed/lurg/country/gams/GamsDemandOptimiser.java

diff --git a/GAMS/IntExtOpt.gms b/GAMS/IntExtOpt.gms
index ee3f1546..46da5614 100644
--- a/GAMS/IntExtOpt.gms
+++ b/GAMS/IntExtOpt.gms
@@ -119,7 +119,8 @@ $gdxin
        CROP_INCREASE_CALC(location)                     
        CROP_DECREASE_CALC(location)                     
        PASTURE_INCREASE_CONV_CALC(location)             
-       PASTURE_DECREASE_CONV_CALC(location)             
+       PASTURE_DECREASE_CONV_CALC(location)          
+       PASTURE_TOTAL_CHANGE_CONSTRAINT(location)   
        COST_EQ                                        total cost objective function;
  
  UNIT_COST_EQ(crop, location) .. unitCost(crop, location) =E=  (     baseCost(crop) * 0.5 +           
@@ -177,6 +178,7 @@ $gdxin
  CROP_DECREASE_CALC(location) .. cropDecrease(location) =G= -sum(crop_less_pasture, area(crop_less_pasture, location) - previousArea(crop_less_pasture, location));
  PASTURE_INCREASE_CONV_CALC(location) .. pastureIncrease(location) =G= area('pasture', location) - previousArea('pasture', location);
  PASTURE_DECREASE_CONV_CALC(location) .. pastureDecrease(location) =G= -(area('pasture', location) - previousArea('pasture', location));
+ PASTURE_TOTAL_CHANGE_CONSTRAINT(location) .. pastureIncrease(location) -pastureDecrease(location) =G= area('pasture', location) - previousArea('pasture', location);
   
  COST_EQ .. total_cost =E= 
          ( 
diff --git a/GAMS/demand.gms b/GAMS/demand.gms
index 5f5f83f1..16580822 100644
--- a/GAMS/demand.gms
+++ b/GAMS/demand.gms
@@ -3,49 +3,53 @@
  ALIAS (com, com2);
  ALIAS (com, com3);
       
- SCALAR income / 100 /;
+      
+ SCALAR income;
+      
+$gdxin %demandgdx% 
+$load income
+$gdxin    
       
  TABLE subElasticities(com, com2)
                      ruminants  wheat   maize    rice  oilcrops  pulses  starchyRoots
      monogastrics          0.7   0.15     0.1     0.1      0.1      0.1          0.1
      ruminants                    0.1     0.1     0.1      0.1      0.1          0.1
-     wheat                                0.6     0.6      0.4      0.4          0.4
-     maize                                        0.6      0.4      0.4          0.4
-     rice                                                  0.4      0.4          0.4
+     wheat                                0.6     0.6      0.3      0.3          0.3
+     maize                                        0.6      0.3      0.3          0.3
+     rice                                                  0.3      0.3          0.3
      oilcrops                                                       0.5          0.5
      pulses                                                                      0.5 ;
      
  subElasticities(com, com2)$subElasticities(com2, com) = subElasticities(com2, com);     
  
  PARAMETER calories(com)
-   / monogastrics          3,
-     ruminants             5,
-     wheat                 1,
-     maize                 1,
+   / monogastrics          1.5,
+     ruminants             1.7,
+     wheat                 1.02,
+     maize                 0.95,
      rice                  1,
-     oilcrops              2,
-     pulses                1,
-     starchyRoots          1  / ;
- calories(com) = 1;
+     oilcrops              1.3,
+     pulses                1.05,
+     starchyRoots          0.9  / ;
  
  PARAMETER idealDiet(com)
-   / monogastrics          1,
+   / monogastrics          1.1,
      ruminants             1,
-     wheat                 1,
-     maize                 1,
-     rice                  1,
-     oilcrops              1,
-     pulses                1,
-     starchyRoots          1  / ;
+     wheat                 0.9,
+     maize                 0.4,
+     rice                  0.5,
+     oilcrops              0.6,
+     pulses                0.5,
+     starchyRoots          0.8  / ;
       
  PARAMETER price(com)
-   / monogastrics          4,
-     ruminants             5,
-     wheat                 2,
-     maize                 2,
-     rice                  2,
-     oilcrops              2,
-     pulses                1,
+   / monogastrics          5,
+     ruminants             7.7,
+     wheat                 1.4,
+     maize                 1.25,
+     rice                  1.5,
+     oilcrops              3,
+     pulses                1.5,
      starchyRoots          1  / ;
        
  PARAMETER comUtility(com);
@@ -105,7 +109,7 @@
  
  total_cost_calc ..  totalCost =e= sum(com, consumption(com) * price(com));
  
- net_utility_calc ..  netUtility =e=   ((totalCost/income)) * 25 + foodUtility;
+ net_utility_calc ..  netUtility =e=   ((totalCost/income)) * 30 + foodUtility;
 
  MODEL DEMAND /ALL/ ;
  
@@ -121,4 +125,8 @@
   
  PARAMETER check(com);
  check(com) = 0;
-*display check;
\ No newline at end of file
+*display check;
+
+ Scalar ms 'model status', ss 'solve status'; 
+ ms=DEMAND.modelstat;
+ ss=DEMAND.solvestat;
\ No newline at end of file
diff --git a/debug_config.properties b/debug_config.properties
index 394a0d91..1e41da7c 100644
--- a/debug_config.properties
+++ b/debug_config.properties
@@ -1,12 +1,12 @@
 BASE_DIR=/Users/peteralexander/Documents/R_Workspace/UNPLUM
 #YIELD_DIR=/Users/peteralexander/Documents/LURG/LPJ/yield_anpp_rcps-2016-01-29/rcp8p5_past_fert/output-2016-01-29
 
-YIELD_DIR=/Users/peteralexander/Documents/LURG/LPJ/sam-03Nov2016
+YIELD_DIR=/Users/peteralexander/Documents/LURG/LPJ/10Jan2017/combined
 SPATIAL_DIR_NAME=halfdeg
 CELL_SIZE_X=0.5
-ANPP_FILENAME=anpp.out.2011-2015
-YIELD_FILENAME=yield.out.2011-2015
-IRRIG_MAX_WATER_FILENAME=gsirrigation.out.2011-2015
+#ANPP_FILENAME=anpp.out
+#YIELD_FILENAME=yield.out
+#IRRIG_MAX_WATER_FILENAME=gsirrigation.out
 MIN_FERT_AMOUNT=0
 MID_FERT_AMOUNT=200
 MAX_FERT_AMOUNT=1000
@@ -16,7 +16,7 @@ PASTURE_FERT_RESPONSE_FROM_LPJ=false
 CLEANUP_GAMS_DIR=false
 
 # Properties for testing
-CHANGE_YIELD_DATA_YEAR=false
+CHANGE_YIELD_DATA_YEAR=true
 CHANGE_DEMAND_YEAR=false
 DEBUG_LIMIT_COUNTRIES=false
 DEBUG_COUNTRY_NAME=Spain
@@ -25,7 +25,7 @@ SSP_SCENARIO=SSP2_v9_130325
 MAX_IMPORT_CHANGE=0.0
 MARKET_ADJ_PRICE=false
 
-IS_CALIBRATION_RUN = true
+IS_CALIBRATION_RUN = false
 
 #LAND_CHANGE_COST=.6
 
@@ -36,7 +36,7 @@ IS_CALIBRATION_RUN = true
 #NUM_CEREAL_CATEGORIES = 10
 #NUM_PASTURE_CATEGORIES = 3
 
-END_TIMESTEP=28
+END_TIMESTEP=18
 TIMESTEP_SIZE=5
 
 INTERPOLATE_OUTPUT_YEARS = false
\ No newline at end of file
diff --git a/src/ac/ed/lurg/ModelConfig.java b/src/ac/ed/lurg/ModelConfig.java
index 43766901..e81c70d8 100644
--- a/src/ac/ed/lurg/ModelConfig.java
+++ b/src/ac/ed/lurg/ModelConfig.java
@@ -102,8 +102,8 @@ public class ModelConfig {
 	// yield data
 	public static final String YIELD_DIR = getProperty("YIELD_DIR");
 	public static final int LPJG_MONITOR_TIMEOUT_SEC = getIntProperty("LPJG_MONITOR_TIMEOUT", 60*60*2);
-	public static final String ANPP_FILENAME = getProperty("ANPP_FILENAME", "anpp_plum.out");
-	public static final String YIELD_FILENAME = getProperty("YIELD_FILENAME", "yield_plum.out");
+	public static final String ANPP_FILENAME = getProperty("ANPP_FILENAME", "anpp.out");
+	public static final String YIELD_FILENAME = getProperty("YIELD_FILENAME", "yield.out");
 	public static final boolean PASTURE_FERT_RESPONSE_FROM_LPJ = getBooleanProperty("PASTURE_FERT_RESPONSE_FROM_LPJ", true);;
 
 	public static final double CALIB_FACTOR_WHEAT = getDoubleProperty("CALIB_FACTOR_WHEAT", 0.966);
@@ -122,7 +122,7 @@ public class ModelConfig {
 	public static final String COUNTRY_BOUNDARY_FILE = SPATIAL_DATA_DIR + File.separator + "country_boundaries.asc";
 	public static final String IRRIGATION_COST_FILE = SPATIAL_DATA_DIR + File.separator + "irrigation_cost.asc";
 	public static final String IRRIGATION_CONSTRAINT_FILE = SPATIAL_DATA_DIR + File.separator + "blue_water_available_pseudoCRU_rcp8p5_2004_2013_grid_allhdyro_mm.txt";
-	public static final String IRRIG_MAX_WATER_FILENAME = getProperty("IRRIG_MAX_WATER_FILENAME", "gsirrigation_plum.out");
+	public static final String IRRIG_MAX_WATER_FILENAME = getProperty("IRRIG_MAX_WATER_FILENAME", "gsirrigation.out");
 	public static final String PROTECTED_AREAS_FILE = SPATIAL_DATA_DIR + File.separator + "protected_areas.txt";
 	
 	// Output
diff --git a/src/ac/ed/lurg/Timestep.java b/src/ac/ed/lurg/Timestep.java
index 496697c7..50274b6c 100644
--- a/src/ac/ed/lurg/Timestep.java
+++ b/src/ac/ed/lurg/Timestep.java
@@ -88,6 +88,6 @@ public class Timestep {
 		if (ModelConfig.CHANGE_YIELD_DATA_YEAR)
 			return rootDir + File.separator + getYieldYear();
 		else
-			return rootDir;
+			return rootDir + File.separator + ModelConfig.BASE_YEAR;
 	}
 }
diff --git a/src/ac/ed/lurg/country/gams/GamsDemandOptimiser.java b/src/ac/ed/lurg/country/gams/GamsDemandOptimiser.java
new file mode 100644
index 00000000..967b3ecf
--- /dev/null
+++ b/src/ac/ed/lurg/country/gams/GamsDemandOptimiser.java
@@ -0,0 +1,143 @@
+package ac.ed.lurg.country.gams;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.gams.api.GAMSDatabase;
+import com.gams.api.GAMSGlobals;
+import com.gams.api.GAMSJob;
+import com.gams.api.GAMSOptions;
+import com.gams.api.GAMSParameter;
+import com.gams.api.GAMSParameterRecord;
+import com.gams.api.GAMSVariable;
+import com.gams.api.GAMSVariableRecord;
+import com.gams.api.GAMSWorkspace;
+import com.gams.api.GAMSWorkspaceInfo;
+
+import ac.ed.lurg.ModelConfig;
+import ac.ed.lurg.types.CropType;
+import ac.ed.lurg.utils.LogWriter;
+
+public class GamsDemandOptimiser {
+	private static final boolean DEBUG = true;
+
+	private double income;
+
+
+	public static void main(String[] args)  {
+		BufferedWriter demandWriter = null;
+
+		try {
+			demandWriter = new BufferedWriter(new FileWriter(ModelConfig.OUTPUT_DIR + "/demand.out", false));
+
+			StringBuffer sbHeader = new StringBuffer("income");
+			for (CropType crop : CropType.getImportedTypes())
+				sbHeader.append("," + crop.getGamsName());
+
+			demandWriter.write(sbHeader.toString());
+			demandWriter.newLine();
+
+			for (int i=0; i<50; i++) {
+				double income = 20.0 + i * 2.0;
+				GamsDemandOptimiser theModel = new GamsDemandOptimiser(income);
+				Map<CropType, Double> results = theModel.run();
+
+				StringBuffer sbData = new StringBuffer(String.format("%.6f", income));
+				for (CropType crop : CropType.getImportedTypes()) {
+					Double d = results.get(crop);
+					sbData.append(String.format(",%.6f", d));
+				}
+
+				demandWriter.write(sbData.toString());
+				demandWriter.newLine();
+			}
+		}
+		catch (IOException e) {
+			LogWriter.print(e);
+		}
+		finally {
+			if (demandWriter != null) {
+				try {
+					demandWriter.close();
+				} 
+				catch (IOException e) {
+					LogWriter.print(e);
+				}
+			}
+
+		}
+	}
+
+
+	public GamsDemandOptimiser(double income) {
+		this.income = income;
+	}
+
+	public Map<CropType, Double> run() {
+		File workingDirectory = new File(ModelConfig.TEMP_DIR, "GamsTmp");
+		workingDirectory.mkdir();
+
+		GAMSWorkspaceInfo  wsInfo  = new GAMSWorkspaceInfo();
+		wsInfo.setWorkingDirectory(workingDirectory.getAbsolutePath());
+		//	wsInfo.setDebugLevel(DebugLevel.VERBOSE);
+
+		GAMSWorkspace ws = new GAMSWorkspace(wsInfo);
+		GAMSDatabase inDB = ws.addDatabase();
+
+		setupInDB(inDB);
+
+		GAMSJob gamsJob = ws.addJobFromFile(ModelConfig.BASE_DIR + File.separator + "GAMS/demand.gms");
+		GAMSOptions opt = ws.addOptions();
+		//		opt.setAllModelTypes("conopt");
+		opt.defines("demandgdx", inDB.getName());
+
+		long startTime = System.currentTimeMillis();
+		gamsJob.run(opt, inDB);		
+		LogWriter.println("Took " + (System.currentTimeMillis() - startTime) + " ms to run");
+
+		return handleResults(gamsJob.OutDB());
+	}
+
+	private void setupInDB(GAMSDatabase inDB) {
+		addScalar(inDB, "income", income, 3);
+	}
+
+	private void addScalar(GAMSDatabase gamsDb, String recordName, double val, int places) {
+		GAMSParameter param = gamsDb.addParameter(recordName, 0);
+		setGamsParamValue(param.addRecord(), val, places);
+		if (DEBUG) LogWriter.println(recordName + ": " + val);
+	}
+
+	private void setGamsParamValue(GAMSParameterRecord param, double val, int places) {
+		double dOut = Math.round(val * Math.pow(10,places)) / Math.pow(10,places);
+		param.setValue(dOut);
+	}
+
+	private Map<CropType, Double> handleResults(GAMSDatabase outDB) {
+		int modelStatus = (int) outDB.getParameter("ms").findRecord().getValue();
+		LogWriter.println(String.format("\nModelstatus %s, Solvestatus %s", 
+				GAMSGlobals.ModelStat.lookup( modelStatus ),
+				GAMSGlobals.SolveStat.lookup((int) outDB.getParameter("ss").findRecord().getValue()) ));
+
+		GAMSVariable varConsump = outDB.getVariable("consumption");
+
+		double consumpValue;
+		Map<CropType, Double> consumptionData = new HashMap<CropType, Double>();
+
+		for (GAMSVariableRecord rec : varConsump) {
+			String itemName = rec.getKeys()[0];
+			consumpValue = rec.getLevel();
+
+			CropType cropType = CropType.getForGamsName(itemName);
+
+			consumptionData.put(cropType, consumpValue);
+			if (DEBUG) LogWriter.println(String.format("\n%s:\tconsumption= %.3f", itemName, consumpValue)); 
+		}
+
+		return consumptionData;
+	}
+}
-- 
GitLab