diff --git a/GAMS/IntExtOpt.gms b/GAMS/IntExtOpt.gms index c02f4ed56996eea1ee960107bd7ae680bc4d2302..6f0b2ac413a10c1ef994fdfc879c28b9700600f2 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 ad18803980df09b8edd4e06cdefacd95f0a087be..dfaf456aee952b68127603a1908b43210688b0ad 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 40012d0a9c9b2792f273f57c4c54e298a8b914bd..56ebb51656a39ef7ef431232ebfc81047e0a0fc1 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 cd7b9b11bc5be9374446674071a27d21947d5f42..de86cf01f466c747989be0dd55f5a3db03c6d693 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 a69e23a391d4ba087b518975e15f7ade1ffc878c..92fdc5d16085b1badac2b10a71779b41c82fa8a1 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 72a82e06f548c0e7a9468785bd0939adaa3626be..d18e7251de8cdbae32e0c6e1d0a5481d17081bf7 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 142c5eb1f4c387d7e20e590ec03b13dd0305f8ac..cb6926d2b29dba67393e4dad426df1d47bf452e7 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 a90988a3114568dee21a784f256072c496525eda..270c11815664ab8f9ad727c58e2af02ad078a884 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 828a710d11b3a810225fe301154f76ad15d7a6c1..dfe97349c474bb9e6d5a8a14f8a64b626992e236 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; }