diff --git a/src/ac/ed/lurg/InternationalMarket.java b/src/ac/ed/lurg/InternationalMarket.java index a3a4af7a8e8bdb960adeebdc404ff5a77cc08662..ac25b1f2639f67e1ca98ed252b11caa6c62669aa 100644 --- a/src/ac/ed/lurg/InternationalMarket.java +++ b/src/ac/ed/lurg/InternationalMarket.java @@ -152,6 +152,18 @@ public class InternationalMarket { } } + public boolean negativeStockLevelsExist() { + for (Map.Entry<CropType, GlobalPrice> entry : worldPrices.entrySet()) { + double stocklevel = entry.getValue().getStockLevel(); + if (stocklevel < 0) { + LogWriter.println(String.format("negativeStockLevelsExist: %s has negative stock %.3f", entry.getKey().getFaoName(), stocklevel)); + return true; + } + } + LogWriter.println(String.format("No negative stocks found")); + return false; + } + /* public double findMaxPriceDiff(Map<CropType, Double> previousExportPrices) { if (previousExportPrices == null) return Double.MAX_VALUE; diff --git a/src/ac/ed/lurg/ModelConfig.java b/src/ac/ed/lurg/ModelConfig.java index 97d12c6634395d0412bbab1a32728dfb32a6ac46..aba2b20c564415abbec68199f6f9e28ff830d3d2 100755 --- a/src/ac/ed/lurg/ModelConfig.java +++ b/src/ac/ed/lurg/ModelConfig.java @@ -267,8 +267,8 @@ public class ModelConfig { // Temporal configuration public static final int START_TIMESTEP = getIntProperty("START_TIMESTEP", 0); - public static final int END_TIMESTEP = getIntProperty("END_TIMESTEP", 18); - public static final int TIMESTEP_SIZE = getIntProperty("TIMESTEP_SIZE", 5); + public static final int END_TIMESTEP = getIntProperty("END_TIMESTEP", 90); + public static final int TIMESTEP_SIZE = getIntProperty("TIMESTEP_SIZE", 1); public static final int BASE_YEAR = getIntProperty("BASE_YEAR", 2010); // Import export limits @@ -338,6 +338,7 @@ public class ModelConfig { public static final double MAX_PRICE_INCREASE = getDoubleProperty("MAX_PRICE_INCREASE", 1.5); public static final double MAX_PRICE_DECREASE = getDoubleProperty("MAX_PRICE_DECREASE", .75); public static final int DEMAND_RECALC_MAX_ITERATIONS = IS_CALIBRATION_RUN ? 0 : getIntProperty("DEMAND_RECALC_MAX_ITERATIONS", 1); // 0 is original behaviour + public static final boolean DEMAND_RECALC_ON_NEGATIVE_STOCK = IS_CALIBRATION_RUN ? false : getBooleanProperty("DEMAND_RECALC_ON_NEGATIVE_STOCK", false); public static final double POPULATION_AGGREG_LIMIT = getDoubleProperty("POPULATION_AGGREG_LIMIT", 30.0); // in millions, smaller countries are aggregated on a regional basis public static final boolean PREDEFINED_COUNTRY_GROUPING = getBooleanProperty("PREDEFINED_COUNTRY_GROUPING", true); diff --git a/src/ac/ed/lurg/ModelMain.java b/src/ac/ed/lurg/ModelMain.java index f863419d2876475169095e08ba695da2c51d4bb9..108914d29e35e8c5bb3900b72796c6cfc3aac5bb 100644 --- a/src/ac/ed/lurg/ModelMain.java +++ b/src/ac/ed/lurg/ModelMain.java @@ -51,7 +51,6 @@ import ac.ed.lurg.yield.LPJYieldResponseMapReader; import ac.ed.lurg.yield.YieldRaster; import ac.sac.raster.IntegerRasterItem; import ac.sac.raster.IntegerRasterReader; -import ac.sac.raster.InterpolatingRasterSet; import ac.sac.raster.RasterHeaderDetails; import ac.sac.raster.RasterKey; import ac.sac.raster.RasterOutputer; @@ -133,16 +132,18 @@ public class ModelMain { countryAgents.determineProductionForAll(timestep, yieldSurfaces, currentIrrigationData); internationalMarket.determineInternationalTrade(countryAgents.getAll(), timestep); - // loop for iterations. Could check within a tolerance using internationalMarket.findMaxPriceDiff, not doing so as doesn't find a solution due to inelastic consumption - for (int i=0; i < ModelConfig.DEMAND_RECALC_MAX_ITERATIONS; i++) { - LogWriter.println("\n++ Re-estimating prices and demand " + i); + int i = 0; + while (i < ModelConfig.DEMAND_RECALC_MAX_ITERATIONS || + (ModelConfig.DEMAND_RECALC_ON_NEGATIVE_STOCK && internationalMarket.negativeStockLevelsExist() && i<10)) { // loop if negative stock have we haven't tried 10 times already + LogWriter.println("\n++ Re-estimating prices and demand: timestep " + timestep.getTimestep() + ": interation " + i); countryAgents.recalculateDemandAndNetImportsForAll(); // recalculate demand from new prices and calculate imports and exports internationalMarket.determineInternationalTrade(countryAgents.getAll(), timestep); // calculate prices + i++; } internationalMarket.applyPriceShocks(timestep); // output results - outputTimestepResults(timestep, globalLandUseRaster); + outputTimestepResults(timestep); checkAndSaveCheckpoint(timestep); } @@ -157,7 +158,7 @@ public class ModelMain { int year = Integer.parseInt(yearStr[i]); if (timestep.getYear() == year) { LogWriter.println("Saving checkpoint"); - serializeCheckpoint(globalLandUseRaster); + serializeCheckpoint(); } } } @@ -404,14 +405,14 @@ public class ModelMain { } } - private void outputTimestepResults(Timestep timestep, RasterSet<LandUseItem> landUseRaster) { + private void outputTimestepResults(Timestep timestep) { - writeLandCoverFile(timestep, landUseRaster); + writeLandCoverFile(timestep, globalLandUseRaster); writeGlobalMarketFile(timestep); writeDemandFile(timestep); writeDomesticProductionFile(timestep); writeCountryDemandFile(timestep); - writeGlobalFoodBalanceSheet(timestep, landUseRaster); + writeGlobalFoodBalanceSheet(timestep, globalLandUseRaster); writeAnimalNumber(timestep); if (ModelConfig.OUTPUT_FOR_LPJG) { @@ -420,17 +421,18 @@ public class ModelMain { RasterSet<LandUseItem> landUseToOutput = null; if (outputYear == timestep.getYear()) { - landUseToOutput = landUseRaster; + landUseToOutput = globalLandUseRaster; } else if (ModelConfig.INTERPOLATE_OUTPUT_YEARS) { - InterpolatingRasterSet<LandUseItem> intermediateLandUse = new InterpolatingRasterSet<LandUseItem>( landUseRaster.getHeaderDetails()) { + // we run with 1 year time steps these days so this code is redundant and flawed + /* InterpolatingRasterSet<LandUseItem> intermediateLandUse = new InterpolatingRasterSet<LandUseItem>( landUseRaster.getHeaderDetails()) { private static final long serialVersionUID = 1306045141011047760L; protected LandUseItem createRasterData() { return new LandUseItem(); } }; intermediateLandUse.setup(globalLandUseRaster, landUseRaster, timestep.getPreviousTimestep().getYear(), timestep.getYear(), outputYear); - landUseToOutput = intermediateLandUse; + landUseToOutput = intermediateLandUse; */ } if (landUseToOutput != null) { @@ -442,7 +444,7 @@ public class ModelMain { } if (ModelConfig.IS_CALIBRATION_RUN) { - serializeCheckpoint(landUseRaster); + serializeCheckpoint(); } if (timestep.isInitialTimestep() && ModelConfig.GENERATE_NEW_YIELD_CLUSTERS) @@ -450,7 +452,7 @@ public class ModelMain { // Output LandUses to tabular file, for analysis (perhaps) LogWriter.println("Outputing land uses Year: " + timestep.getYear()); - LandUseOutputer landuseOutputer = new LandUseOutputer(timestep.getYear(), landUseRaster); + LandUseOutputer landuseOutputer = new LandUseOutputer(timestep.getYear(), globalLandUseRaster); landuseOutputer.writeOutput(); // don't really need this a LPJ outputs have same data, although in a slightly different format @@ -646,8 +648,8 @@ public class ModelMain { } } - private void serializeCheckpoint(RasterSet<LandUseItem> landUseRaster) { - serializeLandUse(landUseRaster); + private void serializeCheckpoint() { + serializeLandUse(globalLandUseRaster); countryAgents.serializeCropUsageForAll(); internationalMarket.serializeGlobalPrices(); }