From 1a46184bae1052d38bcd9b439aee9cc4cedf80d0 Mon Sep 17 00:00:00 2001
From: Peter Alexander <peter@blackhillock.co.uk>
Date: Thu, 22 Nov 2018 20:35:17 +0000
Subject: [PATCH] Fix issue with ruminants going to zero for profit max
 constrained by production (rather than net prod)

---
 GAMS/LUOpt.gms                                | 10 ++++++----
 src/ac/ed/lurg/country/CountryAgent.java      | 20 +++++++++----------
 .../country/gams/GamsLocationOptimiser.java   |  2 +-
 3 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/GAMS/LUOpt.gms b/GAMS/LUOpt.gms
index 2feb7c0c..8cdc449b 100644
--- a/GAMS/LUOpt.gms
+++ b/GAMS/LUOpt.gms
@@ -143,8 +143,8 @@ $gdxin
        MAX_OTHER_INTENSITY_CONSTRAINT(crop, location)
        SETASIDE_AREA_CALC(location)
        TOTAL_LAND_CHANGE_CONSTRAINT(location)           constraint on suitable land use 
-       CROP_MAX_PROD_CONSTRAINT(crop)                   constraint on max production for crops
-       CROP_MIN_PROD_CONSTRAINT(crop)                   constraint on min production for crops
+       CROP_MAX_PROD_CONSTRAINT(crop_less_pasture)      constraint on max production for crops
+       CROP_MIN_PROD_CONSTRAINT(crop_less_pasture)      constraint on min production for crops
        ANIMAL_MAX_PROD_CONSTRAINT(animal_product)       constraint on max production for animal product
        ANIMAL_MIN_PROD_CONSTRAINT(animal_product)       constraint on min production for animal products
        IRRIGATION_CONSTRAINT(location)                  constraint no water usage
@@ -155,6 +155,7 @@ $gdxin
        PASTURE_DECREASE_CONV_CALC(location)          
        PASTURE_TOTAL_CHANGE_CONSTRAINT(location)   
        LAND_RATE_CHANGE_CONSTRAINT_INCREASE
+       PASTURE_FEED_CONSTRAINT
        PROFIT_EQ                                        total profit objective function;
  
  UNIT_COST_EQ(crop, location) .. unitCost(crop, location) =E=  (     baseCost(crop) +           
@@ -193,8 +194,9 @@ $gdxin
  TOTAL_LAND_CHANGE_CONSTRAINT(location) .. suitableLandArea(location) =G= sum(crop_less_pasture, area(crop_less_pasture, location)) / (1.0 - unhandledCropRate) + area('pasture', location);
  SETASIDE_AREA_CALC(location) .. area('setaside', location) =E= sum(crop_less_pasture, area(crop_less_pasture, location)) * setAsideRate;
   
- CROP_MAX_PROD_CONSTRAINT(crop) .. production(crop) =L= maxProduction(crop);
- CROP_MIN_PROD_CONSTRAINT(crop) .. production(crop) =G= minProduction(crop);
+ CROP_MAX_PROD_CONSTRAINT(crop_less_pasture) .. production(crop_less_pasture) =L= maxProduction(crop_less_pasture);
+ CROP_MIN_PROD_CONSTRAINT(crop_less_pasture) .. production(crop_less_pasture) =G= minProduction(crop_less_pasture);
+ PASTURE_FEED_CONSTRAINT .. production('pasture') =E= ruminantFeed('pasture');
  ANIMAL_MAX_PROD_CONSTRAINT(animal_product) .. production(animal_product) =L= maxProduction(animal_product);
  ANIMAL_MIN_PROD_CONSTRAINT(animal_product) .. production(animal_product) =G= minProduction(animal_product);
    
diff --git a/src/ac/ed/lurg/country/CountryAgent.java b/src/ac/ed/lurg/country/CountryAgent.java
index b1003a56..f2c40d67 100644
--- a/src/ac/ed/lurg/country/CountryAgent.java
+++ b/src/ac/ed/lurg/country/CountryAgent.java
@@ -175,26 +175,24 @@ public class CountryAgent {
 						totalExcessProd += netImportsFromMinDemand;
 				}
 				double additionalNetImportsRequired = demand - totalProd - totalmportFromMD;
+				LogWriter.println("additionalNetImportsRequired is " + additionalNetImportsRequired);
+
 				for (CropType crop : commodity.getCropTypes()) {
 					double netImportsMD = netImportsFromMinDemands.get(crop);
 					double netImports=0;
-					if (additionalNetImportsRequired > 0) { // overall importing
+					if (additionalNetImportsRequired > 0) { // overall need to import more
 						if (minCerealFracts.containsKey(crop))
-							netImports = netImportsMD + minCerealFracts.get(crop) * additionalNetImportsRequired; // divide required imports by minCerealFracts		
+							netImports = netImportsMD + minCerealFracts.get(crop) * additionalNetImportsRequired; // divide required additional imports by minCerealFracts		
 					}
-					else {  // overall exporting
+					else {  // overall need to export more
 						if (netImportsMD > 0)
 							netImports = netImportsMD; // still import what we need for minimum fraction
-						else{
-							if(netImportsMD != 0)
+						else if(netImportsMD < 0)
 							netImports = netImportsMD / totalExcessProd * additionalNetImportsRequired; // divide exports by production in excess of minimum demand
-							else
-								netImports = 0;
-						}
-						}
+					}
 					
 					CropUsageData cropUsage = cropUsages.get(crop);	
-					LogWriter.println("Updating cereal " + crop + " to " + netImports);
+					LogWriter.println("Updating cereal net imports " + crop + " to " + netImports);
 					cropUsage.updateNetImports(netImports);
 				}
 			}
@@ -204,7 +202,7 @@ public class CountryAgent {
 					CropUsageData cropUsage = cropUsages.get(crop);
 					double prod =  cropUsage.getProduction() *(1-crop.getSeedAndWasteRate()) - cropUsage.getMonogastricFeed() - cropUsage.getRuminantFeed();
 					double netImports = demand - prod;
-					LogWriter.println("Updating net imports single commodity/crop" + commodity + "/" + crop + " to " + netImports);
+					LogWriter.println("Updating net imports " + crop + " to " + netImports);
 					cropUsage.updateNetImports(netImports);
 				}
 			} 
diff --git a/src/ac/ed/lurg/country/gams/GamsLocationOptimiser.java b/src/ac/ed/lurg/country/gams/GamsLocationOptimiser.java
index 74ef446a..1e081894 100644
--- a/src/ac/ed/lurg/country/gams/GamsLocationOptimiser.java
+++ b/src/ac/ed/lurg/country/gams/GamsLocationOptimiser.java
@@ -440,7 +440,7 @@ public class GamsLocationOptimiser {
 			prodCost = getParmValue(parmProdCost, meatTypes.getGamsName());
 
 			cropUsageData.put(meatTypes, new CropUsageData(0.0, 0.0, netImport, netImportCost, prod, prodCost, Double.NaN));
-			if (DEBUG) LogWriter.println(String.format("\n%s:\t\t\t\t\tnetImports= %.3f,tnetImportCost= %.3f,\tprod= %.3f,\tprodCost= %.3f", meatTypes.getGamsName(), netImport, netImportCost, prod, prodCost)); 
+			if (DEBUG) LogWriter.println(String.format("\n%s:\t\t\t\t\tnetImports= %.3f,\tnetImportCost= %.3f,\tprod= %.3f,\tprodCost= %.3f", meatTypes.getGamsName(), netImport, netImportCost, prod, prodCost)); 
 		}
 		LogWriter.println(String.format("\n%s %s: Total area= %.1f (crop=%.1f, pasture %.1f)", 
 				inputData.getCountryInput().getCountry(), inputData.getTimestep().getYear(), 
-- 
GitLab