diff --git a/src/ac/ed/lurg/country/CountryAgent.java b/src/ac/ed/lurg/country/CountryAgent.java index d1308e998bc4209cfffb7dcc7b79da78972c107c..84d7fbe92fd81f141f52a9656f1987c6c8954266 100644 --- a/src/ac/ed/lurg/country/CountryAgent.java +++ b/src/ac/ed/lurg/country/CountryAgent.java @@ -46,7 +46,7 @@ public class CountryAgent extends AbstractCountryAgent { private RasterSet<IntegerRasterItem> yieldClusters; private Map<CropType, Double> subsidyRates; private boolean saveGamsGdxFiles; - private TripleMap<Integer, Integer, LandCoverType, Double> minimumLandCover; //<Year, Location, LandCoverType, Area> + private ForestManager forestManager; public CountryAgent(AbstractDemandManager demandManager,CompositeCountry country, RasterSet<LandUseItem> cropAreaRaster, Map<CropType, CropUsageData> cropUsageData, Map<CropType, Double> tradeBarriers, RasterSet<IntegerRasterItem> yieldClusters, @@ -61,7 +61,7 @@ public class CountryAgent extends AbstractCountryAgent { saveGamsGdxFiles = (ModelConfig.GAMS_COUNTRY_TO_SAVE != null && country.getName().equals(ModelConfig.GAMS_COUNTRY_TO_SAVE)); - initialiseMinimumLandCover(yieldClusters); + initialiseForestManager(yieldClusters); } @@ -146,7 +146,7 @@ public class CountryAgent extends AbstractCountryAgent { saveGDXFile("landuse"); previousGamsRasterOutput = result; - updateMinimumLandCover(); + forestManager.updateForestHistory(result.getNewForest(), result.getReservedDeforested(), currentTimestep);; return result; } @@ -229,17 +229,7 @@ public class CountryAgent extends AbstractCountryAgent { TradeConstraint carbonTradeConstraint = new TradeConstraint(0, baseTrade + changeUp); // Aggregate minimum land cover for current timestep - DoubleMap<Integer, LandCoverType, Double> minimumLandCoverForTimestep = new DoubleMap<Integer, LandCoverType, Double>(); //<Location, LandCoverType, Area> - - for (Entry<Integer, DoubleMap<Integer, LandCoverType, Double>> yearMap : minimumLandCover.getMap().entrySet()) { - if (yearMap.getKey() > currentTimestep.getYear()) { - for (Entry<Integer, Map<LandCoverType, Double>> locMap : yearMap.getValue().getMap().entrySet()) { - for (Entry<LandCoverType, Double> coverMap : locMap.getValue().entrySet()) { - minimumLandCoverForTimestep.addTo(locMap.getKey(), coverMap.getKey(), coverMap.getValue()); - } - } - } - } + DoubleMap<Integer, LandCoverType, Double> minimumLandCoverForTimestep = forestManager.getReservedAreaForTimestep(currentTimestep); //<Location, LandCoverType, Area> GamsCountryInput countryLevelInputs = new GamsCountryInput(country, currentProjectedDemand, currentCountryPrices, importConstraints, previousGamsRasterOutput.getCropUsageData(), currentMinDemandFract, subsidyRates, currentCarbonPrice, carbonTradeConstraint); @@ -332,76 +322,20 @@ public class CountryAgent extends AbstractCountryAgent { } - private void initialiseMinimumLandCover(RasterSet<IntegerRasterItem> yieldClusters) { - minimumLandCover = new TripleMap<Integer, Integer, LandCoverType, Double>(); + private void initialiseForestManager(RasterSet<IntegerRasterItem> yieldClusters) { + forestManager = new ForestManager(); + + /* int maxYear = Integer.MAX_VALUE; for (LandCoverType lc : LandCoverType.getConvertibleTypes()) { for (IntegerRasterItem iri : yieldClusters.values()) { // inefficient, better to store somewhere the total number of clusters if (iri != null) // TODO Why? - minimumLandCover.put(maxYear, iri.getInt(), lc, 0.0); + forestManager.put(maxYear, iri.getInt(), lc, 0.0); } - - /* - for (Entry<RasterKey, IntegerRasterItem> iri : yieldClusters.entrySet()) { - // inefficient, better to store somewhere the total number of clusters - LogWriter.println("" + iri.getKey().toString()); - LogWriter.println("" + iri.getValue().getInt()); - minimumLandCover.put(maxYear, iri.getValue().getInt(), lc, 0.0); - } - */ } - } - - private void updateMinimumLandCover() { - DoubleMap<Integer, LandCoverType, Double> minimumLandCoverAdditions = previousGamsRasterOutput.getMinimumLandCoverAdditions(); - int expiryYear = currentTimestep.getYear() + ModelConfig.FOREST_LOCKIN_PERIOD; - for (Entry<Integer, Map<LandCoverType, Double>> locMap : minimumLandCoverAdditions.getMap().entrySet()) { - int locId = locMap.getKey(); - Map<LandCoverType, Double> changeMap = locMap.getValue(); - for (Entry<LandCoverType, Double> lcChange: changeMap.entrySet()) { - minimumLandCover.put(expiryYear, locId, lcChange.getKey(), lcChange.getValue()); - } - } - // Remove deforested area from minimum area requirement - DoubleMap<Integer, LandCoverType, Double> reservedDeforested = previousGamsRasterOutput.getReservedDeforested(); - if (!reservedDeforested.getMap().isEmpty()) { - for (Entry<Integer, Map<LandCoverType, Double>> locMap : reservedDeforested.getMap().entrySet()) { - int locId = locMap.getKey(); - - for (Entry<LandCoverType, Double> coverMap : locMap.getValue().entrySet()) { - LandCoverType forestType = coverMap.getKey(); - double deforestedArea = coverMap.getValue(); - List<Integer> expiryYearsFound = new ArrayList<Integer>(minimumLandCover.getMap().keySet()) ; - Collections.sort(expiryYearsFound); // ascending order, remove area from most mature forest - - for (int year : expiryYearsFound) { - if (year > currentTimestep.getYear()) { - double currentMinimumArea = minimumLandCover.get(year, locId, forestType); - if (currentMinimumArea < 0.0) - LogWriter.printlnError("CountryAgent.updateMinimumLandCover(): currentMinimumArea is <=0"); - else if (currentMinimumArea == 0.0) { - continue; - } - - double areaToSubtract = Math.min(currentMinimumArea, deforestedArea); - if (currentMinimumArea - areaToSubtract < 0.0) { // floating point errors - areaToSubtract = currentMinimumArea; - } - - minimumLandCover.put(year, locId, forestType, currentMinimumArea - areaToSubtract); - deforestedArea -= areaToSubtract; - if (deforestedArea < 1E-6) - break; - } - } - - if (deforestedArea >= 1E-6) - LogWriter.printlnError("CountryAgent.updateMinimumLandCover(): unable to subtract all deforested area"); - } - } - } + */ } public double getNetCarbonFlux() { diff --git a/src/ac/ed/lurg/country/ForestManager.java b/src/ac/ed/lurg/country/ForestManager.java index da57601d72c7716c8da8b660e04d8a17a9d4f9e6..5ebf504ab12ea68b6a304da17a633511b3585195 100644 --- a/src/ac/ed/lurg/country/ForestManager.java +++ b/src/ac/ed/lurg/country/ForestManager.java @@ -20,22 +20,22 @@ public class ForestManager { forestHistory = new ArrayList<ForestRecord>(); } - public List<ForestRecord> getReservedAreaForTimestep(Timestep timestep) { - List<ForestRecord> minimumLandCoverForTimestep = new ArrayList<ForestRecord>(); + public DoubleMap<Integer, LandCoverType, Double> getReservedAreaForTimestep(Timestep timestep) { + DoubleMap<Integer, LandCoverType, Double> minimumLandCoverForTimestep = new DoubleMap<Integer, LandCoverType, Double>(); double minYear = timestep.getYear() - ModelConfig.FOREST_LOCKIN_PERIOD; - for (ForestRecord forestRecord : forestHistory) { - if (forestRecord.getYearPlanted() > minYear) { - minimumLandCoverForTimestep.add(forestRecord); + for (ForestRecord record : forestHistory) { + if (record.getYearPlanted() > minYear) { + minimumLandCoverForTimestep.addTo(record.getLocation(), record.getForestType(), record.getArea()); } } - + return minimumLandCoverForTimestep; } public double getForestPlantedArea(int year, int location, LandCoverType forestType) { List<ForestRecord> recordsFound = forestHistory .stream() - .filter(r -> r.getYearPlanted() == year && r.getLocation() == location) + .filter(r -> r.getYearPlanted() == year && r.getLocation() == location && r.getForestType() == forestType) .collect(Collectors.toList()); if (recordsFound.size() > 1) @@ -44,13 +44,13 @@ public class ForestManager { if (recordsFound.isEmpty()) return 0.0; - return recordsFound.get(0).getArea(forestType); + return recordsFound.get(0).getArea(); } public void setForestPlantedArea(int year, int location, LandCoverType forestType, double area) { List<ForestRecord> recordsFound = forestHistory .stream() - .filter(r -> r.getYearPlanted() == year && r.getLocation() == location) + .filter(r -> r.getYearPlanted() == year && r.getLocation() == location && r.getForestType() == forestType) .collect(Collectors.toList()); if (recordsFound.size() > 1) @@ -59,13 +59,13 @@ public class ForestManager { if (recordsFound.isEmpty()) LogWriter.printlnError("ForestManager.getForestPlantedArea(): no records found."); - recordsFound.get(0).setArea(forestType, area); + recordsFound.get(0).setArea(area); } public double getPotentialYield(int year, int location, LandCoverType forestType) { List<ForestRecord> recordsFound = forestHistory .stream() - .filter(r -> r.getYearPlanted() == year && r.getLocation() == location) + .filter(r -> r.getYearPlanted() == year && r.getLocation() == location && r.getForestType() == forestType) .collect(Collectors.toList()); if (recordsFound.size() > 1) @@ -74,7 +74,7 @@ public class ForestManager { if (recordsFound.isEmpty()) LogWriter.printlnError("ForestManager.getPotentialYield(): no records found."); - return recordsFound.get(0).getPotentialYield(forestType); + return recordsFound.get(0).getPotentialYield(); } public void updateForestHistory(List<ForestRecord> newForest, DoubleMap<Integer, LandCoverType, Double> reservedDeforested, Timestep timestep) { diff --git a/src/ac/ed/lurg/country/ForestRecord.java b/src/ac/ed/lurg/country/ForestRecord.java index f298c595b03564c628957a714a1a9b1cd751819b..a699db55bca0a4f5c22c7f6b59a5fb3d3105e312 100644 --- a/src/ac/ed/lurg/country/ForestRecord.java +++ b/src/ac/ed/lurg/country/ForestRecord.java @@ -7,30 +7,34 @@ import ac.ed.lurg.types.LandCoverType; public class ForestRecord { private int yearPlanted; private int location; - private Map<LandCoverType, Double> area; - private Map<LandCoverType, Double> potentialYield; + private LandCoverType forestType; + private double area; + private double potentialYield; public ForestRecord() {} - public ForestRecord(int yearPlanted, int location, LandCoverType forestType, Map<LandCoverType, Double> area, Map<LandCoverType, Double> potentialYield) { + public ForestRecord(int yearPlanted, int location, LandCoverType forestType, double area, double potentialYield) { this.yearPlanted = yearPlanted; this.location = location; + this.forestType = forestType; this.area = area; this.potentialYield = potentialYield; } - public ForestRecord(int location, Map<LandCoverType, Double> area, Map<LandCoverType, Double> potentialYield) { + public ForestRecord(int location, LandCoverType forestType, double area, double potentialYield) { this.location = location; + this.forestType = forestType; this.area = area; this.potentialYield = potentialYield; } public ForestRecord(int yearPlanted, ForestRecord forestRecordToCopy) { this(); - this.yearPlanted = yearPlanted; - location = (forestRecordToCopy.location); - area.putAll(forestRecordToCopy.area); - potentialYield.putAll(forestRecordToCopy.potentialYield); + this.yearPlanted = (yearPlanted); + location = (forestRecordToCopy.getLocation()); + forestType = (forestRecordToCopy.getForestType()); + area = (forestRecordToCopy.getArea()); + potentialYield = (forestRecordToCopy.potentialYield); } public int getYearPlanted() { @@ -45,16 +49,19 @@ public class ForestRecord { return location; } - public double getArea(LandCoverType forestType) { - return area.get(forestType); + public LandCoverType getForestType() { + return forestType; } - - public void setArea(LandCoverType forestType, double area) { - this.area.put(forestType, area); + public double getArea() { + return area; + } + + public void setArea(double area) { + this.area = area; } - public double getPotentialYield(LandCoverType forestType) { - return potentialYield.get(forestType); + public double getPotentialYield() { + return potentialYield; } }