diff --git a/debug_config.properties b/debug_config.properties index e6da74b99e8efdc8a2505774bad805d5e7755406..5832c87e8362045f9a2903318de3b83af7844465 100644 --- a/debug_config.properties +++ b/debug_config.properties @@ -10,6 +10,8 @@ YIELD_DIR=/Users/peteralexander/Documents/LURG/LPJ/IPSL/LPJG_PLUM_expt1.2_rcp45_ #MAX_IMPORT_CHANGE=0.0 #MARKET_ADJ_PRICE=false +SSP_SCENARIO=SSP5_v9_130325 +LAND_CHANGE_COST=0.6 IS_CALIBRATION_RUN = false diff --git a/src/ac/ed/lurg/ModelConfig.java b/src/ac/ed/lurg/ModelConfig.java index ea6252de20e886a940199c9b6ec78b7afd09030b..6294c30ebf4944813b06242cc7b6d0ba3cbff369 100644 --- a/src/ac/ed/lurg/ModelConfig.java +++ b/src/ac/ed/lurg/ModelConfig.java @@ -156,6 +156,7 @@ public class ModelConfig { public static final String SERIALIZED_LAND_USE_FILE = getProperty("SERIALIZED_LAND_USE_FILE", OUTPUT_DIR + File.separator + "landUseRaster.ser"); public static final boolean MARKET_ADJ_PRICE = IS_CALIBRATION_RUN ? false : getBooleanProperty("MARKET_ADJ_PRICE", true); public static final boolean CHANGE_YIELD_DATA_YEAR = IS_CALIBRATION_RUN ? false : getBooleanProperty("CHANGE_YIELD_DATA_YEAR", true); + public static final String CLUSTERED_YIELD_FILE = getProperty("CLUSTERED_YIELD_FILE", OUTPUT_DIR + File.separator + "cluster.asc"); // Temporal configuration public static final int START_TIMESTEP = getIntProperty("START_TIMESTEP", 0); diff --git a/src/ac/ed/lurg/ModelMain.java b/src/ac/ed/lurg/ModelMain.java index 19abc477ea705b6edac4228ab702aceadfa73c53..f20eafa8bb923a90e56971ab1f6e3b2d9b217768 100644 --- a/src/ac/ed/lurg/ModelMain.java +++ b/src/ac/ed/lurg/ModelMain.java @@ -47,6 +47,7 @@ import ac.ed.lurg.yield.LPJYieldResponseMapReader; import ac.ed.lurg.yield.YieldRaster; import ac.ed.lurg.yield.YieldResponsesItem; 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; @@ -67,8 +68,8 @@ public class ModelMain { private RasterSet<LandUseItem> prevLandUseRaster; private RasterSet<IrrigationItem> currentIrrigationData; private RasterSet<LandUseItem> globalLandUseRaster; - private RasterSet<IntegerRasterItem> globalLocationIdRaster; - + private RasterSet<IntegerRasterItem> clusterIdRaster; + public static void main(String[] args) { ModelMain theModel = new ModelMain(); theModel.setup(); @@ -84,8 +85,9 @@ public class ModelMain { demandManager = new DemandManager(ModelConfig.SSP_SCENARIO, baseConsumpManager, compositeCountryManager); tradeManager = new TradeManager(compositeCountryManager); currentIrrigationData = getFixedIrrigationData(); - countryBoundaryRaster = getCountryBoundaryRaster(); + clusterIdRaster = (ModelConfig.IS_CALIBRATION_RUN) ? new RasterSet<IntegerRasterItem>(desiredProjection) : getClusterRaster(); + countryAgents = createCountryAgents(compositeCountryManager.getAll()); globalLandUseRaster = new RasterSet<LandUseItem>(desiredProjection); @@ -95,7 +97,7 @@ public class ModelMain { prevWorldPrices.put(CropType.MAIZE, GlobalPrice.createInitial(0.152)); prevWorldPrices.put(CropType.RICE, GlobalPrice.createInitial(0.282)); prevWorldPrices.put(CropType.OILCROPS, GlobalPrice.createInitial((0.820 * .4 + 0.314 * .6))); - + prevWorldPrices.put(CropType.PULSES, GlobalPrice.createInitial(0.4)); prevWorldPrices.put(CropType.STARCHY_ROOTS, GlobalPrice.createInitial(0.1)); prevWorldPrices.put(CropType.MONOGASTRICS, GlobalPrice.createInitial(0.4 * 0.5)); // quantities is in feed equivalent term (0.4 is weighted average price per feed, and 0.5 accounts for mark-up for additional processing) @@ -122,22 +124,20 @@ public class ModelMain { YieldRaster yieldSurfaces = getYieldSurfaces(timestep); // this will wait for the marker file from LPJ if configured to do so RasterSet<IrrigationItem> allIrrigData = getUpdateIrrigationData(timestep, yieldSurfaces); - + YieldResponsesItem yresp = yieldSurfaces.getFromCoordinates(-90.5, 45.5); LogWriter.printlnError("Test key: " + yresp.getYieldMax(CropType.MAIZE) + ", " + yresp.getYieldFertOnly(CropType.MAIZE) + ", " + yresp.getYieldIrrigOnly(CropType.MAIZE) + ", " + yresp.getYieldNone(CropType.MAIZE)); CropToDoubleMap totalImportCommodities = new CropToDoubleMap(); CropToDoubleMap totalExportCommodities = new CropToDoubleMap(); - globalLocationIdRaster = new RasterSet<IntegerRasterItem>(desiredProjection); - for (CountryAgent ca : countryAgents) { LogWriter.println("Country " + ca.getCountry()); Collection<RasterKey> countryKeys = countryBoundaryRaster.getKeysFor(ca.getCountry()); YieldRaster countryYieldSurfaces = yieldSurfaces.createSubsetForKeys(countryKeys); RasterSet<IrrigationItem> irrigData = allIrrigData.createSubsetForKeys(countryKeys); - + GamsRasterOutput result = null; // do the optimization @@ -153,9 +153,9 @@ public class ModelMain { LogWriter.printlnError("No results for " + ca.getCountry()); continue; } - + // some hacky code for debug purposes that keeps each gams gdx file -/* if (ca.getCountry().getName().equals("Spain")) { + /* if (ca.getCountry().getName().equals("Spain")) { try { Files.copy( FileSystems.getDefault().getPath("/Users/peteralexander/Documents/R_Workspace/UNPLUM/temp/GamsTmp/_gams_java_gdb1.gdx"), @@ -168,10 +168,10 @@ public class ModelMain { // update global rasters globalLandUseRaster.putAll(result.getLandUses()); - - // if first timestep get the clustering info, which doesn't change through time - if (timestep.isInitialTimestep()) - globalLocationIdRaster.putAll(ca.getYieldClusters()); + + // if first timestep and calibration get the clustering info, which doesn't change through time + if (ModelConfig.IS_CALIBRATION_RUN && timestep.isInitialTimestep()) + clusterIdRaster.putAll(ca.getYieldClusters()); // Get values for world input costs Map<CropType, CropUsageData> cropUsage = result.getCropUsageData(); @@ -257,7 +257,7 @@ public class ModelMain { LogWriter.print(e); } } - + private void writeGlobalMarketFile(Timestep timestep) { try { StringBuffer sbHeadings = new StringBuffer("Year,Crop,Imports (Mt),Exports (Mt),New export price, Stock Levels (Mt)"); @@ -268,27 +268,27 @@ public class ModelMain { sbData.append(String.format("%d,%s", timestep.getYear(), crop.getGamsName())); sbData.append(String.format(",%.1f,%.1f", prevWorldPrices.get(crop).getImportAmount(), prevWorldPrices.get(crop).getExportAmount())); sbData.append(String.format(",%.3f,%.3f", prevWorldPrices.get(crop).getExportPrice(), prevStockLevel.get(crop))); - - + + outputFile.write(sbData.toString()); outputFile.newLine(); } - + outputFile.close(); } catch (IOException e) { LogWriter.print(e); } } - + private void writeDemandFile(Timestep timestep) { try { StringBuffer sbHeadings = new StringBuffer("Year,Commodity,Amount (Mt)"); BufferedWriter outputFile = getFileWriter(timestep, ModelConfig.DEMAND_OUTPUT_FILE, sbHeadings.toString()); - + for (CommodityType comm : CommodityType.getAllItems() ) { double demandAmount = 0; - + for (CountryAgent country : countryAgents) { Double d = country.getCurrentProjectedDemand().get(comm); if (d != null) @@ -297,7 +297,7 @@ public class ModelMain { StringBuffer sbData = new StringBuffer(); sbData.append(String.format("%d,%s", timestep.getYear(), comm.getGamsName())); sbData.append(String.format(",%.1f", demandAmount)); - + outputFile.write(sbData.toString()); outputFile.newLine(); } @@ -343,52 +343,52 @@ public class ModelMain { if (ModelConfig.IS_CALIBRATION_RUN) { serializeLandUse(landUseRaster); + + if (timestep.isInitialTimestep()) + outputClusters(clusterIdRaster); } - + // Output LandUses to tabular file, for analysis (perhaps) LogWriter.println("Outputing land uses Year: " + timestep.getYear()); LandUseOutputer landuseOutputer = new LandUseOutputer(timestep.getYear(), landUseRaster); landuseOutputer.writeOutput(); // don't really need this a LPJ outputs have same data, although in a slightly different format -// outputLandCover(timestep.getYear(), landUseRaster, LandCoverType.CROPLAND); -// outputLandCover(timestep.getYear(), landUseRaster, LandCoverType.PASTURE); - - if (timestep.isInitialTimestep()) - outputClusters(globalLocationIdRaster); + // outputLandCover(timestep.getYear(), landUseRaster, LandCoverType.CROPLAND); + // outputLandCover(timestep.getYear(), landUseRaster, LandCoverType.PASTURE); } private void outputClusters(RasterSet<IntegerRasterItem> landUseRaster) { - new RasterOutputer<IntegerRasterItem>(landUseRaster, "clusters") { - @Override - public Double getValue(RasterKey location) { - IntegerRasterItem item = results.get(location); - if (item == null) - return null; - - return (double)item.getInt(); - } - }.writeOutput(); -} - -/* private void outputLandCover(int year, RasterSet<LandUseItem> landUseRaster, final LandCoverType lcType) { - new RasterOutputer<LandUseItem>(landUseRaster, lcType.getName() + "Area" + year) { + new RasterOutputer<Integer, IntegerRasterItem>(landUseRaster, ModelConfig.CLUSTERED_YIELD_FILE) { @Override - public Double getValue(RasterKey location) { - LandUseItem item = results.get(location); + public Integer getValue(RasterKey location) { + IntegerRasterItem item = results.get(location); if (item == null) return null; - return item.getLandCoverFract(lcType); + return item.getInt(); } }.writeOutput(); - } */ + } + + public RasterSet<IntegerRasterItem> getClusterRaster() { + RasterSet<IntegerRasterItem> clusters = new RasterSet<IntegerRasterItem>(desiredProjection) { + private static final long serialVersionUID = 2467452274591854417L; + @Override + protected IntegerRasterItem createRasterData() { + return new IntegerRasterItem(0); + } + }; + + IntegerRasterReader clusterReader = new IntegerRasterReader(clusters); + clusterReader.getRasterDataFromFile(ModelConfig.CLUSTERED_YIELD_FILE); + return clusters; + } public CountryBoundaryRaster getCountryBoundaryRaster() { CountryBoundaryRaster countryBoundaries = new CountryBoundaryRaster(desiredProjection, compositeCountryManager); CountryBoundaryReader countryReader = new CountryBoundaryReader(countryBoundaries); countryReader.getRasterDataFromFile(ModelConfig.COUNTRY_BOUNDARY_FILE); - return countryBoundaries; } @@ -408,19 +408,20 @@ public class ModelMain { List<RasterKey> keys = countryBoundaryRaster.getKeysFor(cc); Map<CropType, CropUsageData> countryCommodityData = cropUsageDataMap.get(cc); Map<CropType, Double> countryTradeBarriers = tradeManager.getTradeBarriers(cc); - + if (countryCommodityData == null) { LogWriter.printlnError("No commodities data for " + cc + ", so skipping"); } else { RasterSet<LandUseItem> initCountryLandUse = initLU.createSubsetForKeys(keys); - + RasterSet<IntegerRasterItem> yieldClusters = (ModelConfig.IS_CALIBRATION_RUN) ? null : clusterIdRaster.createSubsetForKeys(keys); + if (initCountryLandUse.size() == 0) { LogWriter.printlnError("No initial land use for " +cc + ", so skipping"); continue; } - CountryAgent ca = new CountryAgent(demandManager, cc, initCountryLandUse, countryCommodityData, countryTradeBarriers); + CountryAgent ca = new CountryAgent(demandManager, cc, initCountryLandUse, countryCommodityData, countryTradeBarriers, yieldClusters); countryAgents.add(ca); LogWriter.println("Creating country agent for: " + cc ); } @@ -428,14 +429,14 @@ public class ModelMain { return countryAgents; } - + private RasterSet<LandUseItem> getInitialLandUse() { if (ModelConfig.IS_CALIBRATION_RUN) return getLandUseFromBaseline(); else return deserializeLandUse(); } - + private void serializeLandUse(RasterSet<LandUseItem> landUseRaster) { try { LogWriter.println("Starting serializing LandUse to " + ModelConfig.SERIALIZED_LAND_USE_FILE); @@ -450,7 +451,7 @@ public class ModelMain { i.printStackTrace(); } } - + @SuppressWarnings("unchecked") private RasterSet<LandUseItem> deserializeLandUse() { try { @@ -475,7 +476,7 @@ public class ModelMain { } // alternative to deserialization is to use tabular data - /* RasterSet<LandUseItem> initLU = new RasterSet<LandUseItem>(desiredProjection) { + /* RasterSet<LandUseItem> initLU = new RasterSet<LandUseItem>(desiredProjection) { private static final long serialVersionUID = 1317102740312961042L; protected LandUseItem createRasterData() { return new LandUseItem(); @@ -493,10 +494,10 @@ public class ModelMain { return new LandCoverItem(); } }; - + new ProtectedAreasReader(initialLC).getRasterDataFromFile(ModelConfig.PROTECTED_AREAS_FILE); new LandCoverReader(initialLC).getRasterDataFromFile(ModelConfig.INITAL_LAND_COVER_FILE); - + /* new RasterOutputer<LandCoverItem>(initLC, "InitialCropland") { @Override public Double getValue(RasterKey location) { @@ -508,7 +509,7 @@ public class ModelMain { }.writeOutput(); */ RasterSet<LandUseItem> landUseRaster = new RasterSet<LandUseItem>(initialLC.getHeaderDetails()); - + for (Map.Entry<RasterKey, LandCoverItem> entry : initialLC.entrySet()) { LandUseItem areasItem = new LandUseItem(); RasterKey key = entry.getKey(); @@ -519,7 +520,7 @@ public class ModelMain { areasItem.setProtectedArea(landCover.getProtectedArea()); landUseRaster.put(key, areasItem); } - + return landUseRaster; } @@ -527,7 +528,7 @@ public class ModelMain { LPJYieldResponseMapReader yieldReader = new LPJYieldResponseMapReader(desiredProjection); return yieldReader.getRasterData(timestep); } - + /** Get irrigation data components that don't change over time */ private RasterSet<IrrigationItem> getFixedIrrigationData() { RasterSet<IrrigationItem> irigData = new RasterSet<IrrigationItem>(desiredProjection) { @@ -541,7 +542,7 @@ public class ModelMain { new IrrigationConstraintReader(irigData).getRasterDataFromFile(ModelConfig.IRRIGATION_CONSTRAINT_FILE); return irigData; } - + private RasterSet<IrrigationItem> getUpdateIrrigationData(Timestep timestep, YieldRaster yieldSurfaces) { String rootDir = timestep.getYearSubDir(ModelConfig.YIELD_DIR); new IrrigationMaxAmountReader(currentIrrigationData, yieldSurfaces).getRasterDataFromFile(rootDir + File.separator + ModelConfig.IRRIG_MAX_WATER_FILENAME); @@ -550,8 +551,8 @@ public class ModelMain { private Map<CropType,Double> getInitialStockLevels(){ Map<CropType, Double> initialStockLevels = new HashMap<CropType, Double>(); new StockReader(initialStockLevels).read(); - + return initialStockLevels; - + } } diff --git a/src/ac/ed/lurg/country/CountryAgent.java b/src/ac/ed/lurg/country/CountryAgent.java index f9cf2d5bb9acbc3728cfabf8582a56eaa630b521..a9f94b23b4d0567985f6c10849e7ef301a083065 100644 --- a/src/ac/ed/lurg/country/CountryAgent.java +++ b/src/ac/ed/lurg/country/CountryAgent.java @@ -42,11 +42,12 @@ public class CountryAgent { private RasterSet<IntegerRasterItem> yieldClusters; public CountryAgent(DemandManager demandManager,CompositeCountry country, RasterSet<LandUseItem> cropAreaRaster, - Map<CropType, CropUsageData> cropUsageData, Map<CropType, Double> tradeBarriers) { + Map<CropType, CropUsageData> cropUsageData, Map<CropType, Double> tradeBarriers, RasterSet<IntegerRasterItem> yieldClusters) { this.demandManager = demandManager; this.country = country; this.tradeBarriers = tradeBarriers; + this.yieldClusters = yieldClusters; GamsRasterOutput initialData = new GamsRasterOutput(cropAreaRaster, cropUsageData); previousGamsRasterOutput = initialData; diff --git a/src/ac/ed/lurg/country/gams/GamsRasterOptimiser.java b/src/ac/ed/lurg/country/gams/GamsRasterOptimiser.java index 76ca08522f5aa3e1e75563c68a087f44a1538cdb..8ce7de1c5b24edfb4a2edd83551d0c7ae0e25d96 100644 --- a/src/ac/ed/lurg/country/gams/GamsRasterOptimiser.java +++ b/src/ac/ed/lurg/country/gams/GamsRasterOptimiser.java @@ -89,7 +89,9 @@ public class GamsRasterOptimiser { Set<RasterKey> keys = new HashSet<RasterKey>(); for (Entry<RasterKey, IntegerRasterItem> mapEntry : mapping.entrySet()) { - if (locId == mapEntry.getValue().getInt()) + IntegerRasterItem iri = mapEntry.getValue(); + + if (iri != null && locId == iri.getInt()) keys.add(mapEntry.getKey()); } diff --git a/src/ac/sac/raster/IntegerRasterItem.java b/src/ac/sac/raster/IntegerRasterItem.java index c4c3fd2212e27bea90fd53ccdee97cdbce8411a8..1a63f03bdfcdb070bf455dad8b499b34f0d8d779 100644 --- a/src/ac/sac/raster/IntegerRasterItem.java +++ b/src/ac/sac/raster/IntegerRasterItem.java @@ -10,4 +10,8 @@ public class IntegerRasterItem implements RasterItem { public int getInt() { return theInteger; } + + public void setInt(int i) { + theInteger = i; + } } diff --git a/src/ac/sac/raster/IntegerRasterReader.java b/src/ac/sac/raster/IntegerRasterReader.java new file mode 100644 index 0000000000000000000000000000000000000000..f8937b153f94e053580165c44978b9f79ff6ab90 --- /dev/null +++ b/src/ac/sac/raster/IntegerRasterReader.java @@ -0,0 +1,16 @@ +package ac.sac.raster; + +public class IntegerRasterReader extends AbstractRasterReader<IntegerRasterItem> { + + public IntegerRasterReader (RasterSet<IntegerRasterItem> dataset) { + super(dataset); + } + + @Override + public void setData(IntegerRasterItem item, String token) { + if (!"nan".equals(token)) { + int i = Integer.parseInt(token); + item.setInt(i); + } + } +} diff --git a/src/ac/sac/raster/RasterOutputer.java b/src/ac/sac/raster/RasterOutputer.java index 02c21ceb0b59caa5a89c8df7063970ef80abbd3a..b9910f3247210a40e1afc605ef7e9a04d24304c7 100644 --- a/src/ac/sac/raster/RasterOutputer.java +++ b/src/ac/sac/raster/RasterOutputer.java @@ -18,10 +18,9 @@ import java.io.IOException; import javax.imageio.ImageIO; -import ac.ed.lurg.ModelConfig; import ac.ed.lurg.utils.LogWriter; -public abstract class RasterOutputer<D extends RasterItem> { +public abstract class RasterOutputer<T, D extends RasterItem> { protected RasterSet<D> results; private String fileName; @@ -30,9 +29,9 @@ public abstract class RasterOutputer<D extends RasterItem> { this.fileName = fileName; } - abstract public Double getValue(RasterKey location); + abstract public T getValue(RasterKey location); - public int convertToPixelValue(double value) { + public int convertToPixelValue(T value) { throw new RuntimeException("RasterOutputer: if outputing image, need to override this method. "); } @@ -45,8 +44,7 @@ public abstract class RasterOutputer<D extends RasterItem> { BufferedWriter fileWriter = null; try { - String fullPathFileName = ModelConfig.OUTPUT_DIR + File.separator + fileName + ".asc"; - fileWriter = new BufferedWriter(new FileWriter(fullPathFileName,false)); + fileWriter = new BufferedWriter(new FileWriter(fileName,false)); String nullDataString = results.getHeaderDetails().getNodataString(); writeHeader(fileWriter); @@ -56,7 +54,7 @@ public abstract class RasterOutputer<D extends RasterItem> { RasterKey location = new RasterKey(col, row); - Double d = getValue(location); + T d = getValue(location); if (d == null) fileWriter.write(nullDataString + " "); @@ -112,7 +110,7 @@ public abstract class RasterOutputer<D extends RasterItem> { RasterKey key = new RasterKey(col, row); - Double v = getValue(key); + T v = getValue(key); if (v == null) continue; @@ -169,10 +167,8 @@ public abstract class RasterOutputer<D extends RasterItem> { } private void writeImage() { - File outputfile = new File(ModelConfig.OUTPUT_DIR + File.separator + fileName + ".jpeg"); try { - ImageIO.write((RenderedImage) createImage(results), "jpeg", outputfile); - + ImageIO.write((RenderedImage) createImage(results), "jpeg", new File(fileName + ".jpeg")); } catch (Exception e) { System.out.println("Problems saving image to " +fileName);