From 38a0cc11c066f93fad38f2f399d3dc88fde066aa Mon Sep 17 00:00:00 2001 From: s1924442 <b.arendarczyk@sms.ed.ac.uk> Date: Wed, 1 Sep 2021 13:35:31 +0100 Subject: [PATCH] Changes to carbon flux data read-in. Wood yields and C flux bug fixes. --- GAMS/IntExtOpt.gms | 3 +- src/ac/ed/lurg/ModelMain.java | 34 +---- src/ac/ed/lurg/carbon/CarbonFluxItem.java | 100 +++++++------- src/ac/ed/lurg/carbon/CarbonFluxReader.java | 122 ++++++++++++------ .../country/gams/GamsLocationOptimiser.java | 28 ++-- .../country/gams/GamsRasterOptimiser.java | 46 +++---- src/ac/ed/lurg/forestry/WoodYieldItem.java | 5 +- src/ac/ed/lurg/forestry/WoodYieldReader.java | 8 +- 8 files changed, 194 insertions(+), 152 deletions(-) diff --git a/GAMS/IntExtOpt.gms b/GAMS/IntExtOpt.gms index f1fbb16c..2d7b2a04 100644 --- a/GAMS/IntExtOpt.gms +++ b/GAMS/IntExtOpt.gms @@ -52,6 +52,7 @@ PARAMETER previousLandCoverArea(land_cover, location) land cover area in Mha; PARAMETER carbonFluxRate(land_cover_before, land_cover_after, location) carbon flux - MtC-eq per Mha; + PARAMETER carbonFluxRateNEE(land_cover, location); PARAMETER woodYieldLuc(land_cover_before, land_cover_after, location) wood yield - MtC-eq per Mha; PARAMETER woodYieldRota(land_cover_before, land_cover_after, location); @@ -89,7 +90,7 @@ $load fertParam, irrigParam, otherIParam, exportPrices, importPrices, maxNetImpo $load meatEfficency, otherICost, irrigCost, irrigMaxRate, irrigConstraint, fertiliserUnitCost, domesticPriceMarkup, minDemandPerCereal, minDemandPerOilcrop, seedAndWasteRate $load previousLandCoverArea, carbonFluxRate, woodYieldLuc, carbonPrice, woodPrice $load conversionCost, woodYieldRota, infrastructureCost, forestRotationPeriod, woodMaxNetImport, woodMinNetImport, managedForestAreaMaxChangeRate, woodDemand -$load forestEstablishmentCost, naturalAreaValue, woodFromRotation, vegClearingCost, discountRate +$load forestEstablishmentCost, naturalAreaValue, woodFromRotation, vegClearingCost, discountRate, carbonFluxRateNEE $gdxin SCALAR delta "use to smooth power function see 7.5 www.gams.com dd docs solversconopt.pdf" / 0.00000000001 /; diff --git a/src/ac/ed/lurg/ModelMain.java b/src/ac/ed/lurg/ModelMain.java index 112f2cdd..f2a1adce 100644 --- a/src/ac/ed/lurg/ModelMain.java +++ b/src/ac/ed/lurg/ModelMain.java @@ -86,6 +86,7 @@ public class ModelMain { private RasterSet<LandUseItem> globalLandUseRaster; private RasterSet<IntegerRasterItem> clusterIdRaster; WoodYieldReader woodYieldReader; + CarbonFluxReader carbonFluxReader; public static void main(String[] args) { @@ -122,6 +123,7 @@ public class ModelMain { internationalMarket = new InternationalMarket(); woodYieldReader = new WoodYieldReader(desiredProjection); + carbonFluxReader = new CarbonFluxReader(desiredProjection); createCountryAgents(compositeCountryManager.getAll()); } @@ -145,7 +147,6 @@ public class ModelMain { YieldRaster yieldSurfaces = getYieldSurfaces(timestep); // this will wait for the marker file from LPJ if configured to do so getUpdateIrrigationData(timestep, yieldSurfaces); // updating currentIrrigationData - WoodYieldRasterSet woodYieldData = getWoodYieldData(timestep); // When running half earth we can to alter protected areas data at a point in time if(ModelConfig.HALFEARTH && ModelConfig.FORCE_PROTECTED_AREAS_START_YEAR == timestep.getYear() && !ModelConfig.IS_CALIBRATION_RUN) { @@ -161,13 +162,13 @@ public class ModelMain { double carbonDemand = demandManager.getCarbonDemand(ModelConfig.IS_CALIBRATION_RUN ? new Timestep(1) : timestep); double carbonDemandIncrease = (carbonDemand > previousCarbonDemand) ? carbonDemand - previousCarbonDemand: 0; - CarbonFluxRasterSet currentCarbonFluxData = getCarbonFluxData(timestep); - WoodYieldRasterSet currentWoodYieldData = getInterpolatedWoodYieldData(timestep); + CarbonFluxRasterSet carbonFluxData = getCarbonFluxData(timestep); + WoodYieldRasterSet woodYieldData = getWoodYieldData(timestep); Map<LccKey, Double> conversionCosts; conversionCosts = (ModelConfig.CONVERSION_COSTS_FROM_FILE) ? new ConversionCostReader().read() : new ConversionCostReader().calcFromConfig(); - countryAgents.determineProductionForAll(timestep, yieldSurfaces, currentIrrigationData, gen2Increase, currentCarbonFluxData, woodYieldData, + countryAgents.determineProductionForAll(timestep, yieldSurfaces, currentIrrigationData, gen2Increase, carbonFluxData, woodYieldData, conversionCosts, carbonDemandIncrease); internationalMarket.determineInternationalTrade(countryAgents.getAll(), gen2EcDDemand, carbonDemand, timestep); @@ -691,9 +692,6 @@ public class ModelMain { RasterSet<LandUseItem> landUseRaster = new RasterSet<LandUseItem>(initialLC.getHeaderDetails()); for (Map.Entry<RasterKey, LandCoverItem> entry : initialLC.entrySet()) { - if (entry.getKey().getCol() == 177 && entry.getKey().getRow() == 145) { - int foo = 1; - } landUseRaster.put(entry.getKey(), new LandUseItem(entry.getValue())); } @@ -719,33 +717,13 @@ public class ModelMain { /** Get carbon flux data */ private CarbonFluxRasterSet getCarbonFluxData(Timestep timestep) { - CarbonFluxRasterSet carbonFluxData = new CarbonFluxRasterSet(desiredProjection); - LogWriter.println("Reading carbon flux data"); - new CarbonFluxReader(carbonFluxData).getRasterDataFromFile(timestep.getYearSubDir(ModelConfig.FOREST_DIR) + File.separator + "cflux_net.out"); - return carbonFluxData; + return carbonFluxReader.getCarbonFluxes(globalLandUseRaster, timestep); } /** Get wood yield data */ private WoodYieldRasterSet getWoodYieldData(Timestep timestep) { return woodYieldReader.getWoodYields(globalLandUseRaster, timestep, internationalMarket.getWoodPrice().getExportPrice()); } - - - private WoodYieldRasterSet getInterpolatedWoodYieldData(Timestep timestep) { - WoodYieldRasterSet woodYieldData = new WoodYieldRasterSet(desiredProjection); - /*int yearCurrent = timestep.getYear(); - int yearLower = Math.floorDiv(yearCurrent, WoodYieldItem.YEAR_INTERVAL) * WoodYieldItem.YEAR_INTERVAL + WoodYieldItem.YEAR_OFFSET; - int yearUpper = yearLower + WoodYieldItem.YEAR_INTERVAL; - int age = - getWoodYieldData(woodYieldData, yearLower); - getWoodYieldData(woodYieldData, yearUpper); - for (WoodYieldItem wyItem : woodYieldData.values()) { - wyItem.interpolateAllForYear(yearCurrent); - wyItem.removeDataForYear(yearLower); - wyItem.removeDataForYear(yearUpper); - }*/ - return woodYieldData; - } /** Ugly in situ update of currentIrrigationData, better if IrrigationRasterSets were handled more immutably */ private void getUpdateIrrigationData(Timestep timestep, YieldRaster yieldSurfaces) { diff --git a/src/ac/ed/lurg/carbon/CarbonFluxItem.java b/src/ac/ed/lurg/carbon/CarbonFluxItem.java index 044782d5..e3ccfabd 100644 --- a/src/ac/ed/lurg/carbon/CarbonFluxItem.java +++ b/src/ac/ed/lurg/carbon/CarbonFluxItem.java @@ -3,75 +3,85 @@ package ac.ed.lurg.carbon; import ac.sac.raster.RasterItem; import java.io.Serializable; +import java.util.ArrayList; import java.util.HashMap; import java.util.Map; +import ac.ed.lurg.Timestep; +import ac.ed.lurg.landuse.LandUseTile; import ac.ed.lurg.landuse.LccKey; import ac.ed.lurg.types.LandCoverType; public class CarbonFluxItem implements RasterItem, Serializable { private static final long serialVersionUID = 440720456140537815L; - Map<LandCoverType, Map<LandCoverType, Double>> carbonFluxes = new HashMap<LandCoverType, Map<LandCoverType, Double>>(); - Map<LccKey, AgeFunction> conversionCarbonFlux = new HashMap<LccKey, AgeFunction>(); - Map<LandCoverType, AgeFunction> ecosystemCarbonFlux = new HashMap<LandCoverType, AgeFunction>(); + Map<LccKey, Double> conversionCarbonFlux = new HashMap<LccKey, Double>(); + Map<LandCoverType, Double> ecosystemCarbonFlux = new HashMap<LandCoverType, Double>(); - public void setConversionCarbonFlux(LandCoverType fromLc, LandCoverType toLc, int year, int age, double cFlux) { - LccKey key = new LccKey(fromLc, toLc); - AgeFunction ageFunc = conversionCarbonFlux.get(key); - if (ageFunc == null) { - ageFunc = new AgeFunction(); - conversionCarbonFlux.put(key, ageFunc); - } - ageFunc.setData(year, age, cFlux); + public void setConversionCarbonFlux(LccKey key, double cFlux) { + conversionCarbonFlux.put(key, cFlux); } - public void setEcosystemCarbonFlux(LandCoverType lcType, int year, int age, double cFlux) { - AgeFunction ageFunc = ecosystemCarbonFlux.get(lcType); - if (ageFunc == null) { - ageFunc = new AgeFunction(); - ecosystemCarbonFlux.put(lcType, ageFunc); - } - ageFunc.setData(year, age, cFlux); - } - - public double getConversionCarbonFlux(LccKey key, int year, int age) { - return conversionCarbonFlux.get(key).getValue(year, age); + public void calcConversionCarbonFlux(LccKey key, Double[] cFluxes, Map<LandCoverType, ArrayList<LandUseTile>> landUseTiles, Timestep timestep) { + + ArrayList<LandUseTile> tiles = landUseTiles.get(key.getFromLc()); + + if (tiles.size() == 0) { + this.conversionCarbonFlux.put(key, 0.0); + } else { + double totalFlux = 0; + double totalArea = 0; + for (LandUseTile tile : tiles) { + if (tile.isProtected()) + continue; + int age = tile.getAge(timestep); + totalFlux += cFluxes[age] * tile.getArea(); + totalArea += tile.getArea(); + } + double meanFlux = totalFlux / totalArea; + this.conversionCarbonFlux.put(key, meanFlux); + } } - public double getEcosystemCarbonFlux(LandCoverType lcType, int year, int age) { - return ecosystemCarbonFlux.get(lcType).getValue(year, age); + public void setEcosystemCarbonFlux(LandCoverType lcType, double cFlux) { + ecosystemCarbonFlux.put(lcType, cFlux); } - public void setCarbonFlux(LandCoverType previousLandCover, LandCoverType newLandCover, double carbonFlux) { + public void calcEcosystemCarbonFlux(LandCoverType lcType, Double[] cFluxes, Map<LandCoverType, ArrayList<LandUseTile>> landUseTiles, Timestep timestep) { - if (carbonFluxes.containsKey(previousLandCover)) { - carbonFluxes.get(previousLandCover).put(newLandCover, carbonFlux); - } else { - Map<LandCoverType, Double> cfMap = new HashMap<LandCoverType, Double>(); - cfMap.put(newLandCover, carbonFlux); - carbonFluxes.put(previousLandCover, cfMap); + ArrayList<LandUseTile> tiles = landUseTiles.get(lcType); + + if (tiles.size() == 0) { + this.ecosystemCarbonFlux.put(lcType, 0.0); + } else { + double totalFlux = 0; + double totalArea = 0; + for (LandUseTile tile : tiles) { + if (tile.isProtected()) + continue; + int age = tile.getAge(timestep); + totalFlux += cFluxes[age] * tile.getArea(); + totalArea += tile.getArea(); + } + double meanFlux = totalFlux / totalArea; + this.ecosystemCarbonFlux.put(lcType, meanFlux); } } + + public double getConversionCarbonFlux(LccKey key) { + return conversionCarbonFlux.getOrDefault(key, Double.NaN); + } - public double getCarbonFlux(LandCoverType previousLandCover, LandCoverType newLandCover) { - return carbonFluxes.get(previousLandCover).get(newLandCover); + public double getEcosystemCarbonFlux(LandCoverType lcType) { + return ecosystemCarbonFlux.getOrDefault(lcType, Double.NaN); } - public boolean checkForKeys(LandCoverType previousLandCover, LandCoverType newLandCover) { - if (carbonFluxes.containsKey(previousLandCover)) { - if (carbonFluxes.get(previousLandCover).containsKey(newLandCover)) { - return true; - } else { - return false; - } - } else { - return false; - } + public Map<LccKey, Double> getConversionCarbonFluxMap() { + return conversionCarbonFlux; } - public Map<LandCoverType, Map<LandCoverType, Double>> getCarbonFluxes() { - return carbonFluxes; + public Map<LandCoverType, Double> getEcosystemCarbonFluxMap() { + return ecosystemCarbonFlux; } } diff --git a/src/ac/ed/lurg/carbon/CarbonFluxReader.java b/src/ac/ed/lurg/carbon/CarbonFluxReader.java index 9b712557..79f40500 100644 --- a/src/ac/ed/lurg/carbon/CarbonFluxReader.java +++ b/src/ac/ed/lurg/carbon/CarbonFluxReader.java @@ -1,53 +1,103 @@ package ac.ed.lurg.carbon; +import java.io.File; import java.util.Map; +import ac.ed.lurg.ModelConfig; +import ac.ed.lurg.Timestep; +import ac.ed.lurg.landuse.LandUseItem; +import ac.ed.lurg.landuse.LccKey; import ac.ed.lurg.types.LandCoverType; import ac.sac.raster.AbstractTabularRasterReader; +import ac.sac.raster.RasterHeaderDetails; import ac.sac.raster.RasterKey; import ac.sac.raster.RasterSet; -public class CarbonFluxReader extends AbstractTabularRasterReader<CarbonFluxItem> { - - private static final int MIN_COLS = 27; - private static final double CONVERSION_FACTOR = 10; // convert kgC/m2 to tC/ha +public class CarbonFluxReader { + private static final int MIN_COLS = 263; + private static final String DELIMITER = "[ |\t]+"; + private static final double CONVERSION_FACTOR = 10.0; // convert kgC/m2 to tC/ha + private RasterHeaderDetails rasterProj; - public CarbonFluxReader(RasterSet<CarbonFluxItem> carbonFluxes) { - super("[ |\t]+", MIN_COLS, carbonFluxes); + public CarbonFluxReader(RasterHeaderDetails rasterProj) { + this.rasterProj = rasterProj; } - @Override - protected void setData(RasterKey key, CarbonFluxItem item, Map<String, Double> rowValues) { - item.setCarbonFlux(LandCoverType.CROPLAND, LandCoverType.NATURAL, getValueForCol(rowValues, "crop_to_ntrl") * CONVERSION_FACTOR); - item.setCarbonFlux(LandCoverType.CROPLAND, LandCoverType.TIMBER_FOREST, getValueForCol(rowValues, "crop_to_forT") * CONVERSION_FACTOR); - item.setCarbonFlux(LandCoverType.CROPLAND, LandCoverType.CARBON_FOREST, getValueForCol(rowValues, "crop_to_forC") * CONVERSION_FACTOR); - item.setCarbonFlux(LandCoverType.CROPLAND, LandCoverType.PASTURE, getValueForCol(rowValues, "crop_to_past") * CONVERSION_FACTOR); - item.setCarbonFlux(LandCoverType.CROPLAND, LandCoverType.CROPLAND, getValueForCol(rowValues, "crop_to_crop") * CONVERSION_FACTOR); - - item.setCarbonFlux(LandCoverType.PASTURE, LandCoverType.NATURAL, getValueForCol(rowValues, "past_to_ntrl") * CONVERSION_FACTOR); - item.setCarbonFlux(LandCoverType.PASTURE, LandCoverType.TIMBER_FOREST, getValueForCol(rowValues, "past_to_forT") * CONVERSION_FACTOR); - item.setCarbonFlux(LandCoverType.PASTURE, LandCoverType.CARBON_FOREST, getValueForCol(rowValues, "past_to_forC") * CONVERSION_FACTOR); - item.setCarbonFlux(LandCoverType.PASTURE, LandCoverType.CROPLAND, getValueForCol(rowValues, "past_to_crop") * CONVERSION_FACTOR); - item.setCarbonFlux(LandCoverType.PASTURE, LandCoverType.PASTURE, getValueForCol(rowValues, "past_to_past") * CONVERSION_FACTOR); + public CarbonFluxRasterSet getCarbonFluxes(RasterSet<LandUseItem> landUseRaster, Timestep timestep) { + CarbonFluxRasterSet cFluxData = new CarbonFluxRasterSet(rasterProj); + + getCarbonFluxesConversion("cflux_conv_ntrl_to_past.out", cFluxData, landUseRaster, timestep, new LccKey(LandCoverType.NATURAL, LandCoverType.PASTURE)); + getCarbonFluxesConversion("cflux_conv_ntrl_to_forC.out", cFluxData, landUseRaster, timestep, new LccKey(LandCoverType.NATURAL, LandCoverType.CARBON_FOREST)); + getCarbonFluxesConversion("cflux_conv_ntrl_to_forT.out", cFluxData, landUseRaster, timestep, new LccKey(LandCoverType.NATURAL, LandCoverType.TIMBER_FOREST)); + getCarbonFluxesConversion("cflux_conv_ntrl_to_crop.out", cFluxData, landUseRaster, timestep, new LccKey(LandCoverType.NATURAL, LandCoverType.CROPLAND)); + + getCarbonFluxesConversion("cflux_conv_past_to_ntrl.out", cFluxData, landUseRaster, timestep, new LccKey(LandCoverType.PASTURE, LandCoverType.NATURAL)); + getCarbonFluxesConversion("cflux_conv_past_to_forC.out", cFluxData, landUseRaster, timestep, new LccKey(LandCoverType.PASTURE, LandCoverType.CARBON_FOREST)); + getCarbonFluxesConversion("cflux_conv_past_to_forT.out", cFluxData, landUseRaster, timestep, new LccKey(LandCoverType.PASTURE, LandCoverType.TIMBER_FOREST)); + getCarbonFluxesConversion("cflux_conv_past_to_crop.out", cFluxData, landUseRaster, timestep, new LccKey(LandCoverType.PASTURE, LandCoverType.CROPLAND)); + + getCarbonFluxesConversion("cflux_conv_forC_to_ntrl.out", cFluxData, landUseRaster, timestep, new LccKey(LandCoverType.CARBON_FOREST, LandCoverType.NATURAL)); + getCarbonFluxesConversion("cflux_conv_forC_to_past.out", cFluxData, landUseRaster, timestep, new LccKey(LandCoverType.CARBON_FOREST, LandCoverType.PASTURE)); + getCarbonFluxesConversion("cflux_conv_forC_to_forT.out", cFluxData, landUseRaster, timestep, new LccKey(LandCoverType.CARBON_FOREST, LandCoverType.TIMBER_FOREST)); + getCarbonFluxesConversion("cflux_conv_forC_to_crop.out", cFluxData, landUseRaster, timestep, new LccKey(LandCoverType.CARBON_FOREST, LandCoverType.CROPLAND)); + + getCarbonFluxesConversion("cflux_conv_forT_to_ntrl.out", cFluxData, landUseRaster, timestep, new LccKey(LandCoverType.TIMBER_FOREST, LandCoverType.NATURAL)); + getCarbonFluxesConversion("cflux_conv_forT_to_past.out", cFluxData, landUseRaster, timestep, new LccKey(LandCoverType.TIMBER_FOREST, LandCoverType.PASTURE)); + getCarbonFluxesConversion("cflux_conv_forT_to_forC.out", cFluxData, landUseRaster, timestep, new LccKey(LandCoverType.TIMBER_FOREST, LandCoverType.CARBON_FOREST)); + getCarbonFluxesConversion("cflux_conv_forT_to_forT.out", cFluxData, landUseRaster, timestep, new LccKey(LandCoverType.TIMBER_FOREST, LandCoverType.TIMBER_FOREST)); + getCarbonFluxesConversion("cflux_conv_forT_to_crop.out", cFluxData, landUseRaster, timestep, new LccKey(LandCoverType.TIMBER_FOREST, LandCoverType.CROPLAND)); - item.setCarbonFlux(LandCoverType.NATURAL, LandCoverType.PASTURE, getValueForCol(rowValues, "ntrl_to_past") * CONVERSION_FACTOR); - item.setCarbonFlux(LandCoverType.NATURAL, LandCoverType.TIMBER_FOREST, getValueForCol(rowValues, "ntrl_to_forT") * CONVERSION_FACTOR); - item.setCarbonFlux(LandCoverType.NATURAL, LandCoverType.CARBON_FOREST, getValueForCol(rowValues, "ntrl_to_forC") * CONVERSION_FACTOR); - item.setCarbonFlux(LandCoverType.NATURAL, LandCoverType.CROPLAND, getValueForCol(rowValues, "ntrl_to_crop") * CONVERSION_FACTOR); - item.setCarbonFlux(LandCoverType.NATURAL, LandCoverType.NATURAL, getValueForCol(rowValues, "ntrl_to_ntrl") * CONVERSION_FACTOR); + getCarbonFluxesConversion("cflux_conv_crop_to_ntrl.out", cFluxData, landUseRaster, timestep, new LccKey(LandCoverType.CROPLAND, LandCoverType.NATURAL)); + getCarbonFluxesConversion("cflux_conv_crop_to_past.out", cFluxData, landUseRaster, timestep, new LccKey(LandCoverType.CROPLAND, LandCoverType.PASTURE)); + getCarbonFluxesConversion("cflux_conv_crop_to_forC.out", cFluxData, landUseRaster, timestep, new LccKey(LandCoverType.CROPLAND, LandCoverType.CARBON_FOREST)); + getCarbonFluxesConversion("cflux_conv_crop_to_forT.out", cFluxData, landUseRaster, timestep, new LccKey(LandCoverType.CROPLAND, LandCoverType.TIMBER_FOREST)); - item.setCarbonFlux(LandCoverType.TIMBER_FOREST, LandCoverType.PASTURE, getValueForCol(rowValues, "forT_to_past") * CONVERSION_FACTOR); - item.setCarbonFlux(LandCoverType.TIMBER_FOREST, LandCoverType.NATURAL, getValueForCol(rowValues, "forT_to_ntrl") * CONVERSION_FACTOR); - item.setCarbonFlux(LandCoverType.TIMBER_FOREST, LandCoverType.CARBON_FOREST, getValueForCol(rowValues, "forT_to_forC") * CONVERSION_FACTOR); - item.setCarbonFlux(LandCoverType.TIMBER_FOREST, LandCoverType.CROPLAND, getValueForCol(rowValues, "forT_to_crop") * CONVERSION_FACTOR); - item.setCarbonFlux(LandCoverType.TIMBER_FOREST, LandCoverType.TIMBER_FOREST, getValueForCol(rowValues, "forT_to_forT") * CONVERSION_FACTOR); - - item.setCarbonFlux(LandCoverType.CARBON_FOREST, LandCoverType.PASTURE, getValueForCol(rowValues, "forC_to_past") * CONVERSION_FACTOR); - item.setCarbonFlux(LandCoverType.CARBON_FOREST, LandCoverType.NATURAL, getValueForCol(rowValues, "forC_to_ntrl") * CONVERSION_FACTOR); - item.setCarbonFlux(LandCoverType.CARBON_FOREST, LandCoverType.TIMBER_FOREST, getValueForCol(rowValues, "forC_to_forT") * CONVERSION_FACTOR); - item.setCarbonFlux(LandCoverType.CARBON_FOREST, LandCoverType.CROPLAND, getValueForCol(rowValues, "forC_to_crop") * CONVERSION_FACTOR); - item.setCarbonFlux(LandCoverType.CARBON_FOREST, LandCoverType.CARBON_FOREST, getValueForCol(rowValues, "forC_to_forC") * CONVERSION_FACTOR); + getCarbonFluxesEcosystem("cflux_sts_ntrl.out", cFluxData, landUseRaster, timestep, LandCoverType.NATURAL); + getCarbonFluxesEcosystem("cflux_sts_past.out", cFluxData, landUseRaster, timestep, LandCoverType.PASTURE); + getCarbonFluxesEcosystem("cflux_sts_forC.out", cFluxData, landUseRaster, timestep, LandCoverType.CARBON_FOREST); + getCarbonFluxesEcosystem("cflux_sts_forT.out", cFluxData, landUseRaster, timestep, LandCoverType.TIMBER_FOREST); + getCarbonFluxesEcosystem("cflux_sts_crop.out", cFluxData, landUseRaster, timestep, LandCoverType.CROPLAND); - + return cFluxData; + + } + + public void getCarbonFluxesConversion(String filename, CarbonFluxRasterSet cFluxData, RasterSet<LandUseItem> landUseRaster, Timestep timestep, LccKey lccKey) { + + AbstractTabularRasterReader<CarbonFluxItem> cFluxReader = new AbstractTabularRasterReader<CarbonFluxItem>(DELIMITER, MIN_COLS, cFluxData) { + protected void setData(RasterKey key, CarbonFluxItem item, Map<String, Double> rowValues) { + + Double[] fluxes = getArrayFromRowValues(rowValues); + item.calcConversionCarbonFlux(lccKey, fluxes, landUseRaster.get(key).getLandUseTiles(), timestep); + } + }; + + cFluxReader.getRasterDataFromFile(getDataDir(filename, timestep)); + } + + public void getCarbonFluxesEcosystem(String filename, CarbonFluxRasterSet cFluxData, RasterSet<LandUseItem> landUseRaster, Timestep timestep, LandCoverType lcType) { + + AbstractTabularRasterReader<CarbonFluxItem> cFluxReader = new AbstractTabularRasterReader<CarbonFluxItem>(DELIMITER, MIN_COLS, cFluxData) { + protected void setData(RasterKey key, CarbonFluxItem item, Map<String, Double> rowValues) { + + Double[] fluxes = getArrayFromRowValues(rowValues); + item.calcEcosystemCarbonFlux(lcType, fluxes, landUseRaster.get(key).getLandUseTiles(), timestep); + } + }; + + cFluxReader.getRasterDataFromFile(getDataDir(filename, timestep)); + } + + private Double[] getArrayFromRowValues(Map<String, Double> rowValues) { + int arrSize = rowValues.size(); + Double[] arr = new Double[arrSize]; + for (int i=0; i<arrSize; i++) { + arr[i] = rowValues.get(Integer.toString(i)) * CONVERSION_FACTOR; + } + return arr; + } + + private String getDataDir(String filename, Timestep timestep) { + return timestep.getWoodAndCarbonYearSubDir(ModelConfig.WOOD_AND_CARBON_DIR) + File.separator + filename; } } diff --git a/src/ac/ed/lurg/country/gams/GamsLocationOptimiser.java b/src/ac/ed/lurg/country/gams/GamsLocationOptimiser.java index 082106bf..0569bf7d 100644 --- a/src/ac/ed/lurg/country/gams/GamsLocationOptimiser.java +++ b/src/ac/ed/lurg/country/gams/GamsLocationOptimiser.java @@ -361,24 +361,28 @@ public class GamsLocationOptimiser { // Carbon fluxes GAMSParameter cFluxRateP = inDB.addParameter("carbonFluxRate", 3); + GAMSParameter cFluxRateNeeP = inDB.addParameter("carbonFluxRateNEE", 2); for (Entry<Integer, ? extends CarbonFluxItem> entry : inputData.getCarbonFluxes().entrySet()) { Integer locationId = entry.getKey(); String locString = Integer.toString(locationId); CarbonFluxItem cFlux = entry.getValue(); - - for (LandCoverType prevLC : LandCoverType.getConvertibleTypes()) { - for (LandCoverType newLC : LandCoverType.getConvertibleTypes()) { - Vector<String> v = new Vector<String>(); - v.add(prevLC.getName()); - v.add(newLC.getName()); - v.add(locString); - // TODO Need a better way to deal with missing values - if (cFlux.checkForKeys(prevLC, newLC)) - setGamsParamValue(cFluxRateP.addRecord(v), cFlux.getCarbonFlux(prevLC, newLC), 3); - } - } + for (Map.Entry<LccKey, Double> cfEntry : cFlux.getConversionCarbonFluxMap().entrySet()) { + LccKey key = cfEntry.getKey(); + Vector<String> v = new Vector<String>(); + v.add(key.getFromLc().getName()); + v.add(key.getToLc().getName()); + v.add(locString); + setGamsParamValue(cFluxRateP.addRecord(v), cfEntry.getValue(), 2); + } + + for (Map.Entry<LandCoverType, Double> cfEntry : cFlux.getEcosystemCarbonFluxMap().entrySet()) { + Vector<String> v = new Vector<String>(); + v.add(cfEntry.getKey().getName()); + v.add(locString); + setGamsParamValue(cFluxRateNeeP.addRecord(v), cfEntry.getValue(), 3); + } } // Wood yields diff --git a/src/ac/ed/lurg/country/gams/GamsRasterOptimiser.java b/src/ac/ed/lurg/country/gams/GamsRasterOptimiser.java index 4c80bbc5..1f675e9a 100644 --- a/src/ac/ed/lurg/country/gams/GamsRasterOptimiser.java +++ b/src/ac/ed/lurg/country/gams/GamsRasterOptimiser.java @@ -249,8 +249,6 @@ public class GamsRasterOptimiser { protected WoodYieldData createValue() { return new WoodYieldData(); } }; Map<Integer, Double> aggregatedForestRotation = new HashMap<Integer, Double>(); - - int currentYear = rasterInputData.getTimestep().getYear(); int countFound = 0, countMissing = 0; @@ -304,32 +302,36 @@ public class GamsRasterOptimiser { } // Aggregate carbon fluxes and wood yields - for (LandCoverType prevLC : LandCoverType.getConvertibleTypes()) { - for (LandCoverType newLC : LandCoverType.getConvertibleTypes()) { - // Carbon flux - double carbonFlux; - if (carbonFluxItem != null) { - carbonFlux = carbonFluxItem.getCarbonFlux(prevLC, newLC); - } else { - carbonFlux = 0.0; // if missing data assume 0 TODO is this right? - } - - if (!aggCFlux.checkForKeys(prevLC, newLC)) { // if not seen yet - aggCFlux.setCarbonFlux(prevLC, newLC, carbonFlux); - } else { - aggCFlux.setCarbonFlux(prevLC, newLC, aggregateMean(aggCFlux.getCarbonFlux(prevLC, newLC), suitableAreaSoFar, - carbonFlux, suitableAreaThisTime)); - } + if (carbonFluxItem != null) { + for (Map.Entry<LccKey, Double> cfEntry : carbonFluxItem.getConversionCarbonFluxMap().entrySet()) { + LccKey lccKey = cfEntry.getKey(); + double cFluxThisTime = cfEntry.getValue(); + double cFluxSoFar = aggCFlux.getConversionCarbonFlux(lccKey); + double areaThisTime = landUseItem.getLandCoverArea(lccKey.getFromLc()); + double areaSoFar = aggLandUse.getLandCoverArea(lccKey.getFromLc()); + double cFluxAgg = aggregateMean(cFluxSoFar, areaSoFar, cFluxThisTime, areaThisTime); + aggCFlux.setConversionCarbonFlux(lccKey, cFluxAgg); } - } + + for (Map.Entry<LandCoverType, Double> cfEntry : carbonFluxItem.getEcosystemCarbonFluxMap().entrySet()) { + LandCoverType lcType = cfEntry.getKey(); + double cFluxThisTime = cfEntry.getValue(); + double cFluxSoFar = aggCFlux.getEcosystemCarbonFlux(lcType); + double areaThisTime = landUseItem.getLandCoverArea(lcType); + double areaSoFar = aggLandUse.getLandCoverArea(lcType); + double cFluxAgg = aggregateMean(cFluxSoFar, areaSoFar, cFluxThisTime, areaThisTime); + aggCFlux.setEcosystemCarbonFlux(lcType, cFluxAgg); + } + } if (woodYieldItem != null) { // TODO Fix for (Map.Entry<LccKey, Double> wyEntry : woodYieldItem.getYieldMap().entrySet()) { LccKey lccKey = wyEntry.getKey(); - double yield = wyEntry.getValue(); - double wYieldThisTime = woodYieldItem.getYield(lccKey); + double wYieldThisTime = wyEntry.getValue(); double wYieldSoFar = aggWYield.getYieldLuc(lccKey); - double wYieldAgg = aggregateMean(wYieldSoFar, suitableAreaSoFar, wYieldThisTime, suitableAreaThisTime); + double areaThisTime = landUseItem.getLandCoverArea(lccKey.getFromLc()); + double areaSoFar = aggLandUse.getLandCoverArea(lccKey.getFromLc()); + double wYieldAgg = aggregateMean(wYieldSoFar, areaSoFar, wYieldThisTime, areaThisTime); aggWYield.setYieldLuc(lccKey, wYieldAgg); } diff --git a/src/ac/ed/lurg/forestry/WoodYieldItem.java b/src/ac/ed/lurg/forestry/WoodYieldItem.java index c04c4b23..608ee0aa 100644 --- a/src/ac/ed/lurg/forestry/WoodYieldItem.java +++ b/src/ac/ed/lurg/forestry/WoodYieldItem.java @@ -37,11 +37,11 @@ public class WoodYieldItem implements RasterItem { ArrayList<LandUseTile> tiles = landUseTiles.get(key.getFromLc()); - if (tiles.size() == 0) { + double totalArea = tiles.stream().filter(o -> !o.isProtected()).mapToDouble(o -> o.getArea()).sum(); + if (tiles.size() == 0 || totalArea == 0) { this.yield.put(key, 0.0) ; } else { double totalYield = 0; - double totalArea = 0; for (LandUseTile tile : tiles) { if (tile.isProtected()) continue; @@ -50,6 +50,7 @@ public class WoodYieldItem implements RasterItem { totalArea += tile.getArea(); } double meanYield = totalYield / totalArea; + this.yield.put(key, meanYield); } } diff --git a/src/ac/ed/lurg/forestry/WoodYieldReader.java b/src/ac/ed/lurg/forestry/WoodYieldReader.java index d1d1557c..3f7076e4 100644 --- a/src/ac/ed/lurg/forestry/WoodYieldReader.java +++ b/src/ac/ed/lurg/forestry/WoodYieldReader.java @@ -31,7 +31,7 @@ public class WoodYieldReader { return woodYieldData; } - public WoodYieldRasterSet getWoodYieldsForest(WoodYieldRasterSet woodYieldData, RasterSet<LandUseItem> landUseRaster, Timestep timestep, double woodPrice) { + public void getWoodYieldsForest(WoodYieldRasterSet woodYieldData, RasterSet<LandUseItem> landUseRaster, Timestep timestep, double woodPrice) { AbstractTabularRasterReader<WoodYieldItem> yieldReader = new AbstractTabularRasterReader<WoodYieldItem>(DELIMITER, MIN_COLS, woodYieldData) { protected void setData(RasterKey key, WoodYieldItem item, Map<String, Double> rowValues) { @@ -53,11 +53,9 @@ public class WoodYieldReader { String filename = getDataDir(ModelConfig.WOOD_YIELD_FRST_FILENAME, timestep); yieldReader.getRasterDataFromFile(filename); - - return woodYieldData; } - public WoodYieldRasterSet getWoodYieldsAgri(WoodYieldRasterSet woodYieldData, RasterSet<LandUseItem> landUseRaster, Timestep timestep, double woodPrice) { + public void getWoodYieldsAgri(WoodYieldRasterSet woodYieldData, RasterSet<LandUseItem> landUseRaster, Timestep timestep, double woodPrice) { AbstractTabularRasterReader<WoodYieldItem> yieldReader = new AbstractTabularRasterReader<WoodYieldItem>(DELIMITER, MIN_COLS, woodYieldData) { protected void setData(RasterKey key, WoodYieldItem item, Map<String, Double> rowValues) { @@ -78,8 +76,6 @@ public class WoodYieldReader { String filename = getDataDir(ModelConfig.WOOD_YIELD_AGRI_FILENAME, timestep); yieldReader.getRasterDataFromFile(filename); - - return woodYieldData; } private String getDataDir(String filename, Timestep timestep) { -- GitLab