From c137553c1cc21443609b73e0d962f997a3754fd8 Mon Sep 17 00:00:00 2001 From: s1924442 <b.arendarczyk@sms.ed.ac.uk> Date: Sat, 2 Apr 2022 21:05:23 +0100 Subject: [PATCH] Fixed ruminant overproduction bug. --- GAMS/IntExtOpt.gms | 38 +++++++++++-------- src/ac/ed/lurg/ModelConfig.java | 6 +-- src/ac/ed/lurg/ModelMain.java | 4 +- .../country/gams/GamsDemandOptimiser.java | 1 + src/ac/ed/lurg/landuse/LandTileReader.java | 4 +- src/ac/ed/lurg/landuse/WoodUsageReader.java | 4 +- src/ac/ed/lurg/types/WoodType.java | 2 +- 7 files changed, 34 insertions(+), 25 deletions(-) diff --git a/GAMS/IntExtOpt.gms b/GAMS/IntExtOpt.gms index eb9064de..306186cb 100644 --- a/GAMS/IntExtOpt.gms +++ b/GAMS/IntExtOpt.gms @@ -122,18 +122,19 @@ $gdxin * minNetImport(import_crop) = min(minNetImport(import_crop), demand(import_crop)); VARIABLES - cropArea(crop, location) total area for crops - Mha + unitCost(crop, location) cost per area for each crop - cost fertI(crop, location) fertilizer intensity for each crop - factor between 0 and 1 irrigI(crop, location) irrigation intensity for each crop - factor between 0 and 1 otherIntensity(crop, location) + yield(crop, location) yield per area for each crop - t per ha + cropArea(crop, location) total area for crops - Mha + netSupply(all_types) crop supply ruminantFeed(crop) amount of feed for ruminant animals - Mt monogastricFeed(crop) amount of feed for monogatric animals - Mt importAmount(all_types) imports of crops and meat - Mt exportAmount(all_types) exports of crops and meat - Mt - yield(crop, location) yield per area for each crop - t per ha - unitCost(crop, location) cost per area for each crop - cost + totalFeedDM total feed dry matter - supply(all_types) crop supply landCoverArea(land_cover, location) land cover area in Mha landCoverChange(land_cover_before, land_cover_after, location) land cover change in Mha totalConversionCost(location) land cover conversion cost - $1000 per ha @@ -163,12 +164,14 @@ $gdxin MAX_OTHER_INTENSITY_CONSTRAINT(crop, location) IRRIGATION_CONSTRAINT(location) constraint on water usage - SUPPLY_CALC(crop) - RUMINANTS_SUPPLY_CALC - MONOGASTRICS_SUPPLY_CALC + NET_SUPPLY_EQ(crop) calc net supply for crops + CROP_DEMAND_CONSTRAINT(crop) satisfy demand for individual crops + TOTAL_CEREAL_DEMAND_CONSTRAINT satisfy demand for combined cereals + TOTAL_OIL_PULSE_DEMAND_CONSTRAINT satisfy demand for combined oilcrops and pulses + RUMINANT_DEMAND_CONSTRAINT satisfy demand for ruminant products + MONOGASTRICS_DEMAND_CONSTRAINT satisfy demand for monogastric products TOTAL_NON_PASTURE_FEED_DM_CALC calc total feed dry matter not including pasture FEED_MIX_CONSTRAINT(feed_crop_less_pasture) limit amount of feed for each feed crop - SUPPLY_CONSTRAINT(import_crop) MAX_NET_IMPORT_CONSTRAINT(import_crop) constraint on max net imports MIN_NET_IMPORT_CONSTRAINT(import_crop) constraint on min net imports @@ -221,16 +224,21 @@ $gdxin *************** Commodity supply ************************* - SUPPLY_CALC(crop) .. supply(crop) =E= sum(location, cropArea(crop, location) * yield(crop, location)) * (1 - seedAndWasteRate(crop)) - ruminantFeed(crop) - monogastricFeed(crop); + NET_SUPPLY_EQ(crop) .. netSupply(crop) =E= sum(location, cropArea(crop, location) * yield(crop, location)) * (1 - seedAndWasteRate(crop)) - ruminantFeed(crop) - monogastricFeed(crop) + importAmount(crop) - exportAmount(crop); + + CROP_DEMAND_CONSTRAINT(crop) .. netSupply(crop) =G= demand(crop); + + TOTAL_CEREAL_DEMAND_CONSTRAINT .. sum(cereal_crop, netSupply(cereal_crop)) =G= demand('cereals'); - RUMINANTS_SUPPLY_CALC .. supply('ruminants') =E= meatEfficency * sum(feed_crop, ruminantFeed(feed_crop) * cropDM(feed_crop)) * (1 - seedAndWasteRate('ruminants')); + TOTAL_OIL_PULSE_DEMAND_CONSTRAINT .. sum(oilpulse_crop, netSupply(oilpulse_crop)) =G= demand('oilcropspulses'); + + RUMINANT_DEMAND_CONSTRAINT .. meatEfficency * sum(feed_crop, ruminantFeed(feed_crop) * cropDM(feed_crop)) * (1 - seedAndWasteRate('ruminants')) =G= (demand('ruminants') - importAmount('ruminants') + exportAmount('ruminants')); + + MONOGASTRICS_DEMAND_CONSTRAINT .. meatEfficency * sum(feed_crop_less_pasture, monogastricFeed(feed_crop_less_pasture) * cropDM(feed_crop_less_pasture)) * (1 - seedAndWasteRate('monogastrics')) =G= (demand('monogastrics') - importAmount('monogastrics') + exportAmount('monogastrics')); - MONOGASTRICS_SUPPLY_CALC .. supply('monogastrics') =E= meatEfficency * sum(feed_crop_less_pasture, monogastricFeed(feed_crop_less_pasture) * cropDM(feed_crop_less_pasture)) * (1 - seedAndWasteRate('monogastrics')); - TOTAL_NON_PASTURE_FEED_DM_CALC .. totalFeedDM =E= sum(feed_crop_less_pasture, (ruminantFeed(feed_crop_less_pasture) + monogastricFeed(feed_crop_less_pasture)) * cropDM(feed_crop_less_pasture)); FEED_MIX_CONSTRAINT(feed_crop_less_pasture) .. (ruminantFeed(feed_crop_less_pasture) + monogastricFeed(feed_crop_less_pasture)) * cropDM(feed_crop_less_pasture) =L= totalFeedDM * 0.7; - - SUPPLY_CONSTRAINT(import_crop) .. supply(import_crop) =E= demand(import_crop) + exportAmount(import_crop) - importAmount(import_crop); + *************** Exports ******************************* @@ -313,7 +321,7 @@ $gdxin SOLVE LAND_USE USING NLP MINIMIZING total_cost; display previousCropArea, irrigMaxRate, otherIntensity.L, fertI.L, irrigI.L, cropArea.L; - display supply.l, demand, ruminantFeed.l, monogastricFeed.l, exportAmount.l; + display netSupply.l, demand, ruminantFeed.l, monogastricFeed.l, exportAmount.l; * Calculate summary information used in Java process parameter totalProd(all_types); diff --git a/src/ac/ed/lurg/ModelConfig.java b/src/ac/ed/lurg/ModelConfig.java index 8c7d7116..8e274af0 100755 --- a/src/ac/ed/lurg/ModelConfig.java +++ b/src/ac/ed/lurg/ModelConfig.java @@ -462,9 +462,8 @@ public class ModelConfig { public static final String TIMBER_DEMAND_FILE = getProperty("TIMBER_DEMAND_FILE", DATA_DIR + File.separator + TIMBER_DEMAND_FILENAME); public static final double INIT_WOOD_STOCK = getDoubleProperty("INIT_WOOD_STOCK", 1000.0); // tC-eq - public static final double ROUNDWOOD_DEMAND_ELASTICITY = getDoubleProperty("ROUNDWOOD_DEMAND_ELASTICITY", -0.21956); - public static final double FUELWOOD_DEMAND_ELASTICITY = getDoubleProperty("FUELDWOOD_DEMAND_ELASTICITY", -0.22787); - public static final double FOREST_ESTABLISHMENT_COST = getDoubleProperty("FOREST_ESTABLISHMENT_COST", 2.0); // $1000/ha + public static final double IND_ROUNDWOOD_DEMAND_ELASTICITY = getDoubleProperty("IND_ROUNDWOOD_DEMAND_ELASTICITY", 0.3123881); + public static final double FUELWOOD_DEMAND_ELASTICITY = getDoubleProperty("FUELDWOOD_DEMAND_ELASTICITY", -0.3598551); public static final String WOOD_NET_IMPORTS_FILENAME = getProperty("WOOD_NET_IMPORTS_FILENAME", "wood_net_imports.csv"); public static final String WOOD_NET_IMPORTS_FILE = getProperty("WOOD_NET_IMPORTS_FILE", DATA_DIR + File.separator + WOOD_NET_IMPORTS_FILENAME); public static final double WOOD_BIOMASS_CONVERSION_FACTOR = getDoubleProperty("WOOD_BIOMASS_CONVERSION_FACTOR", 3e-7); // m3 to MtC-eq p.16 [https://doi.org/10.5194/gmd-13-5425-2020] @@ -473,6 +472,7 @@ public class ModelConfig { public static final boolean CONVERSION_COSTS_FROM_FILE = getBooleanProperty("CONVERSION_COSTS_FROM_FILE", false); public static final boolean IS_FORESTRY_ON = getBooleanProperty("IS_FORESTRY_ON", true); public static final boolean IS_CARBON_ON = getBooleanProperty("IS_CARBON_ON", true); + public static final double FOREST_ESTABLISHMENT_COST = IS_FORESTRY_ON ? getDoubleProperty("FOREST_ESTABLISHMENT_COST", 2.0) : 0.0; // $1000/ha public static final int CARBON_HORIZON = getIntProperty("CARBON_HORIZON", 30); public static final double WOOD_TRADE_BARRIER = getDoubleProperty("WOOD_TRADE_BARRIER", 0.05); //$1000/tC public static final double INIT_CARBON_PRICE = IS_CARBON_ON ? getDoubleProperty("INIT_CARBON_PRICE", 0.02) : 0.0; // $1000/tC-eq diff --git a/src/ac/ed/lurg/ModelMain.java b/src/ac/ed/lurg/ModelMain.java index 83dc5606..3a2f4a15 100644 --- a/src/ac/ed/lurg/ModelMain.java +++ b/src/ac/ed/lurg/ModelMain.java @@ -140,7 +140,7 @@ public class ModelMain { private void doTimestep(Timestep timestep) { System.gc(); LogWriter.println("Timestep: " + timestep.toString()); - LogWriter.println("Memory usage 1: " + (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())); + LogWriter.println("Memory usage 1: " + (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / (1024.0*1024.0*1024.0)); YieldRaster yieldSurfaces = getYieldSurfaces(timestep); // this will wait for the marker file from LPJ if configured to do so getUpdateIrrigationData(timestep, yieldSurfaces); // updating currentIrrigationData @@ -183,7 +183,7 @@ public class ModelMain { } internationalMarket.applyPriceShocks(timestep); - LogWriter.println("Memory usage: 2" + (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())); + LogWriter.println("Memory usage 2: " + (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / (1024.0*1024.0*1024.0)); // output results outputTimestepResults(timestep); diff --git a/src/ac/ed/lurg/country/gams/GamsDemandOptimiser.java b/src/ac/ed/lurg/country/gams/GamsDemandOptimiser.java index 798fa03d..febfca4c 100755 --- a/src/ac/ed/lurg/country/gams/GamsDemandOptimiser.java +++ b/src/ac/ed/lurg/country/gams/GamsDemandOptimiser.java @@ -58,6 +58,7 @@ public class GamsDemandOptimiser { opt.defines("gdx_parameters", new File(ModelConfig.DEMAND_PARAM_FILE).getAbsolutePath()); long startTime = System.currentTimeMillis(); + LogWriter.println("Memory usage: GAMS Demand " + (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / (1024.0*1024.0*1024.0)); gamsJob.run(opt, dbs.toArray(new GAMSDatabase[dbs.size()])); LogWriter.println("Took " + (System.currentTimeMillis() - startTime) + " ms to run"); diff --git a/src/ac/ed/lurg/landuse/LandTileReader.java b/src/ac/ed/lurg/landuse/LandTileReader.java index 4a3b3aae..f1772633 100644 --- a/src/ac/ed/lurg/landuse/LandTileReader.java +++ b/src/ac/ed/lurg/landuse/LandTileReader.java @@ -8,7 +8,7 @@ import ac.sac.raster.RasterKey; import ac.sac.raster.RasterSet; public class LandTileReader extends AbstractTabularRasterReader<LandCoverItem> { - private static final int MIN_COLS = 6; + private static final int MIN_COLS = 7; public LandTileReader(RasterSet<LandCoverItem> data) { super("[ |\t]+", MIN_COLS, data); @@ -21,6 +21,6 @@ public class LandTileReader extends AbstractTabularRasterReader<LandCoverItem> { item.setLandUseAgeDist(LandCoverType.PASTURE, getValueForCol(rowValues, "PASTURE"), ageGroup); item.setLandUseAgeDist(LandCoverType.TIMBER_FOREST, getValueForCol(rowValues, "FOREST"), ageGroup); item.setLandUseAgeDist(LandCoverType.CARBON_FOREST, getValueForCol(rowValues, "FOREST"), ageGroup); - item.setLandUseAgeDist(LandCoverType.NATURAL, getValueForCol(rowValues, "FOREST"), ageGroup); + item.setLandUseAgeDist(LandCoverType.NATURAL, getValueForCol(rowValues, "NATURAL"), ageGroup); } } diff --git a/src/ac/ed/lurg/landuse/WoodUsageReader.java b/src/ac/ed/lurg/landuse/WoodUsageReader.java index 0a3e50d7..add6e103 100644 --- a/src/ac/ed/lurg/landuse/WoodUsageReader.java +++ b/src/ac/ed/lurg/landuse/WoodUsageReader.java @@ -53,8 +53,8 @@ public class WoodUsageReader { countryName = tokens[COUNTRY_COL]; woodTypeName = tokens[WOOD_TYPE_COL]; - harvest = Double.parseDouble(tokens[HARVEST_COL]) * ModelConfig.WOOD_BIOMASS_CONVERSION_FACTOR; // m3 to MtC-eq - netImport = Double.parseDouble(tokens[NET_IMPORT_COL]) * ModelConfig.WOOD_BIOMASS_CONVERSION_FACTOR; // m3 to MtC-eq + harvest = ModelConfig.IS_FORESTRY_ON ? Double.parseDouble(tokens[HARVEST_COL]) * ModelConfig.WOOD_BIOMASS_CONVERSION_FACTOR : 0; // m3 to MtC-eq + netImport = ModelConfig.IS_FORESTRY_ON ? Double.parseDouble(tokens[NET_IMPORT_COL]) * ModelConfig.WOOD_BIOMASS_CONVERSION_FACTOR : 0; // m3 to MtC-eq SingleCountry country = CountryManager.getForName(countryName); WoodType woodType = WoodType.getForName(woodTypeName); diff --git a/src/ac/ed/lurg/types/WoodType.java b/src/ac/ed/lurg/types/WoodType.java index de4af65f..a8407076 100644 --- a/src/ac/ed/lurg/types/WoodType.java +++ b/src/ac/ed/lurg/types/WoodType.java @@ -5,7 +5,7 @@ import java.util.Map; import ac.ed.lurg.ModelConfig; public enum WoodType { - ROUNDWOOD("roundwood", ModelConfig.ROUNDWOOD_DEMAND_ELASTICITY), + ROUNDWOOD("roundwood", ModelConfig.IND_ROUNDWOOD_DEMAND_ELASTICITY), FUELWOOD("fuelwood", ModelConfig.FUELWOOD_DEMAND_ELASTICITY); private String name; -- GitLab