From d32c19ed21321654e9ce6137688d07bc2d6bf82b Mon Sep 17 00:00:00 2001
From: R0slyn <roslyn.henry.08@aberdeen.ac.uk>
Date: Thu, 15 Nov 2018 10:27:21 +0000
Subject: [PATCH] fix to incorporate seed and waste losses into production
 passed from GAMS to Java, incl change to fbs method. Outputting demand for
 Frances and hacky code for Trump stuff.

---
 GAMS/IntExtOpt.gms                            |  6 ++--
 GAMS/LUOpt.gms                                |  6 ++--
 data/subsidyrates.csv                         |  2 +-
 src/ac/ed/lurg/InternationalMarket.java       |  6 ++--
 src/ac/ed/lurg/ModelConfig.java               |  1 +
 src/ac/ed/lurg/ModelMain.java                 | 35 +++++++++++++++++--
 src/ac/ed/lurg/country/CountryAgent.java      | 16 +++++----
 .../country/gams/GamsLocationOptimiser.java   |  7 ++++
 src/ac/ed/lurg/landuse/CropUsageData.java     |  2 +-
 9 files changed, 62 insertions(+), 19 deletions(-)

diff --git a/GAMS/IntExtOpt.gms b/GAMS/IntExtOpt.gms
index c02f4ed5..6f0b2ac4 100644
--- a/GAMS/IntExtOpt.gms
+++ b/GAMS/IntExtOpt.gms
@@ -243,9 +243,9 @@ $gdxin
  parameter feedCostRate(feed_crop);
  
 * Production quantities based on smaller area (before unhandledCropArea adjustment applied)
- totalProd(crop) = sum(location, area.l(crop, location) * yield.l(crop, location));
- totalProd('ruminants') = meatEfficency*sum(feed_crop, ruminantFeed.l(feed_crop) * cropDM(feed_crop));
- totalProd('monogastrics') = meatEfficency*sum(feed_crop, monogastricFeed.l(feed_crop) * cropDM(feed_crop));
+ totalProd(crop) = sum(location, area.l(crop, location) * yield.l(crop, location))* (1 - seedAndWasteRate(crop));
+ totalProd('ruminants') = meatEfficency*(sum(feed_crop, ruminantFeed.l(feed_crop) * cropDM(feed_crop)) + ruminantOtherFeed) * (1 - seedAndWasteRate('ruminants'));
+ totalProd('monogastrics') = meatEfficency*(sum(feed_crop, monogastricFeed.l(feed_crop) * cropDM(feed_crop)) + monogastricOtherFeed)* (1 - seedAndWasteRate('monogastrics'));
  
 * Cost based on adjusted area
  area.l(crop_less_pasture, location) = area.l(crop_less_pasture, location) / (1.0 - unhandledCropRate);
diff --git a/GAMS/LUOpt.gms b/GAMS/LUOpt.gms
index ad188039..dfaf456a 100644
--- a/GAMS/LUOpt.gms
+++ b/GAMS/LUOpt.gms
@@ -19,6 +19,7 @@
  PARAMETER previousRuminantFeed(crop);
  PARAMETER previousMonogastricFeed(crop);
  PARAMETER previousImportAmount(all_types)   we still need imports and for feed that we is not grown domestically;
+ PARAMETER previousExportAmount(all_types)
  PARAMETER yieldNone(crop, location)         yield in t per ha;
  PARAMETER yieldFertOnly(crop, location)     yield in t per ha;
  PARAMETER yieldIrrigOnly(crop, location)    yield in t per ha;
@@ -56,7 +57,7 @@
 *$gdxin "/Users/peteralexander/Documents/R_Workspace/UNPLUM/output/GamsTmp/China2010.gdx"
 $gdxin %gdxincname% 
 $load location, suitableLandArea, demand, agriExpansionCost, cropIncCost, pastureIncCost, cropDecCost, pastureDecCost
-$load previousArea, previousFertIntensity, previousIrrigIntensity, previousOtherIntensity, previousRuminantFeed, previousMonogastricFeed, previousImportAmount
+$load previousArea, previousFertIntensity, previousIrrigIntensity, previousOtherIntensity, previousRuminantFeed, previousMonogastricFeed, previousImportAmount, previousExportAmount
 $load yieldNone, yieldFertOnly, yieldIrrigOnly, yieldBoth
 $load fertParam, irrigParam, otherIParam, exportPrices, importPrices, maxProduction, minProduction, unhandledCropRate, setAsideRate, maxLandExpansionRate, subsidyRate
 $load meatEfficency, otherICost, irrigCost, irrigMaxRate, irrigConstraint, fertiliserUnitCost, domesticPriceMarkup, minDemandPerCereal, seedAndWasteRate, animalFeedFromOtherSources
@@ -235,6 +236,7 @@ $gdxin
  ruminantFeed.L(feed_crop) = previousRuminantFeed(feed_crop);
  monogastricFeed.L(feed_crop) = previousMonogastricFeed(feed_crop);
  importForFeed.L(all_types) = 0;
+ export.L(traded_commodity) = previousExportAmount(traded_commodity);
   
  SOLVE LAND_USE USING NLP MAXIMIZING totalProfit;
        
@@ -252,7 +254,7 @@ $gdxin
  parameter netImportCost(all_types);
   
 * Need to copy to parameter for backward compatibility
- totalProd(all_types) = production.l(all_types);
+ totalProd(all_types) = production.l(all_types) * (1 - seedAndWasteRate(all_types));
  
 * Cost based on adjusted area
  area.l(crop_less_pasture, location) = area.l(crop_less_pasture, location) / (1.0 - unhandledCropRate);
diff --git a/data/subsidyrates.csv b/data/subsidyrates.csv
index 40012d0a..56ebb516 100644
--- a/data/subsidyrates.csv
+++ b/data/subsidyrates.csv
@@ -1 +1 @@
-country,crop,rate
+country,crop,rate
diff --git a/src/ac/ed/lurg/InternationalMarket.java b/src/ac/ed/lurg/InternationalMarket.java
index cd7b9b11..de86cf01 100644
--- a/src/ac/ed/lurg/InternationalMarket.java
+++ b/src/ac/ed/lurg/InternationalMarket.java
@@ -58,12 +58,14 @@ public class InternationalMarket {
 			for (Entry<CropType, CropUsageData> entry : cropUsage.entrySet()) {
 				CropType c = entry.getKey();
 				double countryNetImports = entry.getValue().getNetImports();
-
+				
 				if (countryNetImports > 0)
 					totalImportCommodities.incrementValue(c, countryNetImports);
 				else
 					totalExportCommodities.incrementValue(c, -countryNetImports);
 			}
+			
+			
 		}
 
 		// energycrops are a special case where demand in global and exogenously specified
@@ -71,10 +73,10 @@ public class InternationalMarket {
 
 		// Look at trade balance and adjust appropriately
 		for (CropType crop : CropType.getImportedTypes()) {
+		
 			GlobalPrice prevPrice = worldPrices.get(crop);
 			double imports = totalImportCommodities.containsKey(crop) ? totalImportCommodities.get(crop) : 0.0;
 			double exportsBeforeTransportLosses = totalExportCommodities.containsKey(crop) ? totalExportCommodities.get(crop) : 0.0;
-
 			double previousStockLevel = stockLevel.get(crop);
 			GlobalPrice adjustedPrice = prevPrice.createWithUpdatedMarketPrices(imports, exportsBeforeTransportLosses, exportsBeforeTransportLosses * ModelConfig.TRANSPORT_LOSSES, (ModelConfig.MARKET_ADJ_PRICE), timestep);
 			LogWriter.println( String.format("Price for %s updated from %s (imports amount %.0f, exports amount %.0f) to %s ",
diff --git a/src/ac/ed/lurg/ModelConfig.java b/src/ac/ed/lurg/ModelConfig.java
index a69e23a3..92fdc5d1 100644
--- a/src/ac/ed/lurg/ModelConfig.java
+++ b/src/ac/ed/lurg/ModelConfig.java
@@ -222,6 +222,7 @@ public class ModelConfig {
 	public static final String PRICES_OUTPUT_FILE = OUTPUT_DIR + File.separator + "prices.txt";
 	public static final String DEMAND_OUTPUT_FILE = OUTPUT_DIR + File.separator + "demand.txt";
 	public static final String DOMESTIC_OUTPUT_FILE = OUTPUT_DIR + File.separator + "domestic.txt";
+	public static final String COUNTRY_DEMAND_FILE = OUTPUT_DIR + File.separator + "countryDemand.txt";
 	public static final String FOOD_BALANCE_SHEET_FILE = OUTPUT_DIR + File.separator + "fbs.txt";
 	
 	public static final boolean OUTPUT_FOR_LPJG = getBooleanProperty("OUTPUT_FOR_LPJG", true);
diff --git a/src/ac/ed/lurg/ModelMain.java b/src/ac/ed/lurg/ModelMain.java
index 72a82e06..d18e7251 100644
--- a/src/ac/ed/lurg/ModelMain.java
+++ b/src/ac/ed/lurg/ModelMain.java
@@ -259,9 +259,9 @@ public class ModelMain {
 					}
 				}
 
-				double seedAndWaste = prod * crop.getSeedAndWasteRate();
+				double seedAndWaste = (prod * (1/(1-crop.getSeedAndWasteRate())))-prod;
 				double netSupply = prod - exportsBeforeTL + imports;
-				double foodAnd1stGen = netSupply - feedMonogastrics - feedRuminants - seedAndWaste;
+				double foodAnd1stGen = netSupply - feedMonogastrics - feedRuminants;
 				
 				if (!crop.equals(CropType.SETASIDE))
 					prodArea *= (1-ModelConfig.UNHANDLED_CROP_RATE);  // remove unhandled crop area
@@ -351,7 +351,7 @@ private void writeDomesticProductionFile(Timestep timestep) {
 	
 					StringBuffer sbData = new StringBuffer();
 					sbData.append(String.format("%d,%s,%s", timestep.getYear(), country.getCountry(), crop.getGamsName()));
-					sbData.append(String.format(",%.3f,%.3f,%.3f,%.10f,%.10f,%.3f,%.3f,%.3f", area, prod, prodCosts, importPrice, exportPrice, netImports, rumFeedAmount, monFeedAmount));
+					sbData.append(String.format(",%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f", area, prod, prodCosts, importPrice, exportPrice, netImports, rumFeedAmount, monFeedAmount));
 
 					outputFile.write(sbData.toString());
 					outputFile.newLine();
@@ -364,12 +364,41 @@ private void writeDomesticProductionFile(Timestep timestep) {
 		}
 	}
 
+	private void writeCountryDemandFile(Timestep timestep){
+	
+		try {
+			StringBuffer sbHeadings = new StringBuffer("Year, Country, Commodity, Demand");
+			BufferedWriter outputFile = getFileWriter(timestep, ModelConfig.COUNTRY_DEMAND_FILE, sbHeadings.toString());
+		
+			for (CountryAgent country : countryAgents) {
+				for (CommodityType commodity : CommodityType.getAllItems()) {
+					
+				double  demand =  country.getCurrentProjectedDemand().get(commodity);
+				
+				 StringBuffer sbData = new StringBuffer();
+				sbData.append(String.format("%d,%s,%s", timestep.getYear(), country.getCountry(), commodity.getGamsName()));
+				sbData.append(String.format(",%.3f", demand));
+
+				outputFile.write(sbData.toString());
+				outputFile.newLine();
+			}
+		}
+		outputFile.close();
+			
+		} catch (IOException e) {
+			LogWriter.print(e);
+		}
+		
+	}
+	
+
 	private void outputTimestepResults(Timestep timestep, RasterSet<LandUseItem> landUseRaster) {
 
 		writeLandCoverFile(timestep, landUseRaster);
 		writeGlobalMarketFile(timestep);
 		writeDemandFile(timestep);
 		writeDomesticProductionFile(timestep);
+		writeCountryDemandFile(timestep);
 		writeGlobalFoodBalanceSheet(timestep, landUseRaster);
 
 		if (ModelConfig.OUTPUT_FOR_LPJG) {
diff --git a/src/ac/ed/lurg/country/CountryAgent.java b/src/ac/ed/lurg/country/CountryAgent.java
index 142c5eb1..cb6926d2 100644
--- a/src/ac/ed/lurg/country/CountryAgent.java
+++ b/src/ac/ed/lurg/country/CountryAgent.java
@@ -174,24 +174,26 @@ public class CountryAgent {
 					else
 						totalExcessProd += netImportsFromMinDemand;
 				}
-				
 				double additionalNetImportsRequired = demand - totalProd - totalmportFromMD;
-		
 				for (CropType crop : commodity.getCropTypes()) {
 					double netImportsMD = netImportsFromMinDemands.get(crop);
 					double netImports=0;
 					if (additionalNetImportsRequired > 0) { // overall importing
 						if (minCerealFracts.containsKey(crop))
-							netImports = netImportsMD + minCerealFracts.get(crop) * additionalNetImportsRequired; // divide required imports by minCerealFracts
+							netImports = netImportsMD + minCerealFracts.get(crop) * additionalNetImportsRequired; // divide required imports by minCerealFracts		
 					}
 					else {  // overall exporting
 						if (netImportsMD > 0)
 							netImports = netImportsMD; // still import what we need for minimum fraction
-						else
+						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);
+					CropUsageData cropUsage = cropUsages.get(crop);	
 					LogWriter.println("Updating cereal " + crop + " to " + netImports);
 					cropUsage.updateNetImports(netImports);
 				}
@@ -245,6 +247,7 @@ public class CountryAgent {
 				
 				changeDown = changeUp = allowedImportChange * maxOfProdOrSupply;
 
+				
 			}
 			if (CropType.ENERGY_CROPS.equals(crop)) {
 				double croplandArea = LandUseItem.getTotalLandCover(previousGamsRasterOutput.getLandUses().values(), LandCoverType.CROPLAND);
@@ -262,7 +265,6 @@ public class CountryAgent {
 					baseTradeOrProd=0;
 			}
 
-
 			importConstraints.put(crop, new TradeOrProductionConstraint(baseTradeOrProd - changeDown, baseTradeOrProd + changeUp, ModelConfig.ORIG_LEAST_COST_MIN));
 		}
 
diff --git a/src/ac/ed/lurg/country/gams/GamsLocationOptimiser.java b/src/ac/ed/lurg/country/gams/GamsLocationOptimiser.java
index a90988a3..270c1181 100644
--- a/src/ac/ed/lurg/country/gams/GamsLocationOptimiser.java
+++ b/src/ac/ed/lurg/country/gams/GamsLocationOptimiser.java
@@ -261,6 +261,7 @@ public class GamsLocationOptimiser {
 		GAMSParameter exportPriceP = inDB.addParameter("exportPrices", 1);
 		
 		for (CropType crop : CropType.getImportedTypes()) {		
+			
 			TradeOrProductionConstraint iec = countryInput.getTradeOrProductionConstraints().get(crop);
 			CountryPrice gp = countryInput.getCountryPrices().get(crop);			
 			double minTradeOrProd = iec.getMinConstraint();
@@ -268,6 +269,12 @@ public class GamsLocationOptimiser {
 			double importPrice = gp.getImportPrice();
 			double exportPrice = gp.getExportPrice();
 			
+/*			if(ModelConfig.US_EXPORT_TARRIFF != 1.0 & inputData.getTimestep().getYear() >= 2018 & crop == CropType.OILCROPS &
+					countryInput.getCountry().getName().equals("United States of America")){
+			 exportPrice = gp.getExportPrice()* ModelConfig.US_EXPORT_TARRIFF;
+			}
+			else exportPrice = gp.getExportPrice();*/
+			
 			CropUsageData cu = countryInput.getPreviousCropUsageData().get(crop);
 			double netImports = cu.getNetImports();
 			double imports = netImports>0 ? netImports : 0;
diff --git a/src/ac/ed/lurg/landuse/CropUsageData.java b/src/ac/ed/lurg/landuse/CropUsageData.java
index 828a710d..dfe97349 100644
--- a/src/ac/ed/lurg/landuse/CropUsageData.java
+++ b/src/ac/ed/lurg/landuse/CropUsageData.java
@@ -39,7 +39,7 @@ public class CropUsageData {
 	public double getNetProduction() {
 		return prod - ruminantFeed - monogastricFeed;
 	}
-
+	
 	public double getProdCost() {
 		return prodCost;
 	}
-- 
GitLab