From 0658b14fd0faa538f204e9364fb314ae56a9cb53 Mon Sep 17 00:00:00 2001 From: Peter Alexander <peter@blackhillock.co.uk> Date: Thu, 17 Sep 2015 13:07:20 +0100 Subject: [PATCH] Calc irrigation usage more correctly --- GAMS/IntExtOpt.gms | 20 ++++++++++--------- src/ac/ed/lurg/ModelConfig.java | 3 ++- src/ac/ed/lurg/ModelMain.java | 4 ++-- .../country/gams/GamsRasterOptimiser.java | 9 ++++++++- src/ac/ed/lurg/landuse/Intensity.java | 1 + src/ac/ed/lurg/landuse/IrrigationItem.java | 2 +- src/ac/ed/lurg/landuse/LandUseItem.java | 15 ++++++++------ src/ac/ed/lurg/utils/LogWriter.java | 2 +- 8 files changed, 35 insertions(+), 21 deletions(-) diff --git a/GAMS/IntExtOpt.gms b/GAMS/IntExtOpt.gms index db113c5c..4defc99f 100644 --- a/GAMS/IntExtOpt.gms +++ b/GAMS/IntExtOpt.gms @@ -23,9 +23,9 @@ PARAMETER worldImportPrices(import_crop) prices for imports; PARAMETER maxNetImport(import_crop) maximum net import for each crop based on world market; PARAMETER minNetImport(import_crop) minimum net import for each crop based on world market; - PARAMETER irrigCost(location) irrigation cost; - PARAMETER irrigMaxRate(crop, location) max water application rate irrigation in mm; - PARAMETER irrigConstraint(location) max water available for irrigation in mm; + PARAMETER irrigCost(location) irrigation cost in energy per 1000 Mlitre or Mha for each litre per m2; + PARAMETER irrigMaxRate(crop, location) max water application rate irrigation in litre per m2; + PARAMETER irrigConstraint(location) max water available for irrigation in litre per m2; PARAMETER cropAdj(crop) this is the fudge factor that allows the model to fit the observed data SCALAR meatEfficency efficiency of converting feed and pasture into animal products; @@ -112,7 +112,7 @@ $gdxin UNIT_ENERGY_EQ(crop, location) .. unitEnergy(crop, location) =E= ( baseCost(crop) + fertiliserUnitCost * fertI(crop, location) + - irrigCost(location) * irrigI(crop, location) + + irrigCost(location) * irrigMaxRate(crop, location) * irrigI(crop, location) + SQR(otherIntensity(crop, location)) * 1 ) ; @@ -166,11 +166,13 @@ $gdxin ENERGY_EQ .. energy =E= ( SUM((crop, location), area(crop, location) * unitEnergy(crop, location)) + - sum(location, agriLandExpansion(location) * landChangeEnergy) + - sum(location, (SQR(cropIncrease(location) + cropDecrease(location)) / (suitableLandArea(location) * 0.01 + sum(crop_less_pasture, previousArea(crop_less_pasture, location))) - + (cropIncrease(location) + cropDecrease(location)) * 0.1) * landChangeEnergy) + - sum(location, (SQR(pastureIncrease(location) + pastureDecrease(location)) / (suitableLandArea(location) * 0.01 + previousArea('pasture', location)) - + (pastureIncrease(location) + pastureDecrease(location)) * 0.1) * landChangeEnergy) + + sum(location, + agriLandExpansion(location) + + 0.45 * SQR(cropIncrease(location) + cropDecrease(location)) / (suitableLandArea(location) * 0.01 + sum(crop_less_pasture, previousArea(crop_less_pasture, location))) + + 0.05 * (cropIncrease(location) + cropDecrease(location)) + + 0.45 * SQR(pastureIncrease(location) + pastureDecrease(location)) / (suitableLandArea(location) * 0.01 + previousArea('pasture', location)) + + 0.05 * (pastureIncrease(location) + pastureDecrease(location)) + ) * landChangeEnergy + sum(import_crop, importAmount(import_crop) * worldImportPrices(import_crop) - exportAmount(import_crop) * worldExportPrices(import_crop)) ) / 1000000; diff --git a/src/ac/ed/lurg/ModelConfig.java b/src/ac/ed/lurg/ModelConfig.java index c507777c..59019ffa 100644 --- a/src/ac/ed/lurg/ModelConfig.java +++ b/src/ac/ed/lurg/ModelConfig.java @@ -148,7 +148,7 @@ public class ModelConfig { public static final double MARKET_LAMBA = getDoubleProperty("MARKET_LAMBA", 0.3); // controls international market price adjustment rate public static final double POPULATION_AGGREG_LIMIT = getDoubleProperty("POPULATION_AGGREG_LIMIT", 40.0); // in millions, smaller countries are aggregated on a regional basis - public static final double IRRIG_COST_SCALE_FACTOR = getDoubleProperty("IRRIG_COST_SCALE_FACTOR", 2.0); + public static final double IRRIG_COST_SCALE_FACTOR = getDoubleProperty("IRRIG_COST_SCALE_FACTOR", 0.1); public static final double FERTILISER_MAX_COST = getDoubleProperty("FERTILISER_MAX_COST", 2.5); public static final double TRANSPORT_LOSSES = getDoubleProperty("TRANSPORT_LOSSES", 0.15); // in international trade public static final double TRADE_BARRIER_FACTOR = getDoubleProperty("TRADE_BARRIER_FACTOR", 1.2); // price factor in international trade, transport cost and real trade barriers @@ -157,4 +157,5 @@ public class ModelConfig { public static final int NUM_PASTURE_CATEGORIES = getIntProperty("NUM_PASTURE_CATEGORIES", 1); public static final boolean DEBUG_LIMIT_COUNTRIES = getBooleanProperty("DEBUG_LIMIT_COUNTRIES", false); + public static final double DEFAULT_MAX_IRRIGATION_RATE = getDoubleProperty("DEFAULT_MAX_IRRIGATION_RATE", 50.0); // should need this but some areas crops don't have a value, but was causing them to be selected } \ No newline at end of file diff --git a/src/ac/ed/lurg/ModelMain.java b/src/ac/ed/lurg/ModelMain.java index 5f9982f5..2f25d8d8 100644 --- a/src/ac/ed/lurg/ModelMain.java +++ b/src/ac/ed/lurg/ModelMain.java @@ -190,7 +190,7 @@ public class ModelMain { private void writeLandCoverFile(Timestep timestep, RasterSet<LandUseItem> landUseRaster) { try { - StringBuffer sbHeadings = new StringBuffer("Year, Cropland (Mha), Pasture (Mha), Natural (Mha), Fert crop (Mt), Fert pasture (Mt), Irrig crop (M litre), Irrig pasture (M litre)"); + StringBuffer sbHeadings = new StringBuffer("Year, Cropland (Mha), Pasture (Mha), Natural (Mha), Fert crop (Mt), Fert pasture (Mt), Irrig crop (km3), Irrig pasture (km3)"); BufferedWriter outputFile = getFileWriter(timestep, ModelConfig.LAND_COVER_OUTPUT_FILE, sbHeadings.toString()); StringBuffer sbData = new StringBuffer(); @@ -303,7 +303,7 @@ public class ModelMain { // DEBUG code if (ModelConfig.DEBUG_LIMIT_COUNTRIES) { - if (!(cc.getName().equals("United States of America") || cc.getName().equals("Russian Federationxx") || cc.getName().equals("South Asia_otherxx")) ) { + if (!(cc.getName().equals("United States of Americaxx") || cc.getName().equals("India") || cc.getName().equals("Russian Federationxx") || cc.getName().equals("South Asia_otherxx")) ) { continue; } } diff --git a/src/ac/ed/lurg/country/gams/GamsRasterOptimiser.java b/src/ac/ed/lurg/country/gams/GamsRasterOptimiser.java index 105e2978..fea86a05 100644 --- a/src/ac/ed/lurg/country/gams/GamsRasterOptimiser.java +++ b/src/ac/ed/lurg/country/gams/GamsRasterOptimiser.java @@ -355,7 +355,14 @@ public class GamsRasterOptimiser { // Crops yields and area fractions for (CropType crop : CropType.getNonMeatTypes()) { if (irrigItem!= null) { - aggIrig.setMaxIrrigAmount(crop, aggregateMean(aggIrig.getMaxIrrigAmount(crop), suitableAreaSoFar, irrigItem.getMaxIrrigAmount(crop), suitableAreaThisTime)); + double irrigMax = irrigItem.getMaxIrrigAmount(crop); + + if (irrigMax == 0.0) { + LogWriter.printlnError("Can't find irrig max amount for col:" + key.getCol() + ", row:" + key.getRow() + ", x:" + yieldRaster.getXCoordin(key) + ", y:" + yieldRaster.getYCoordin(key) + ", crop:" + crop); + irrigMax = ModelConfig.DEFAULT_MAX_IRRIGATION_RATE; + } + + aggIrig.setMaxIrrigAmount(crop, aggregateMean(aggIrig.getMaxIrrigAmount(crop), suitableAreaSoFar, irrigMax, suitableAreaThisTime)); } double areaSoFar = aggLandUse.getCropArea(crop); diff --git a/src/ac/ed/lurg/landuse/Intensity.java b/src/ac/ed/lurg/landuse/Intensity.java index 23f62525..79bdedf5 100644 --- a/src/ac/ed/lurg/landuse/Intensity.java +++ b/src/ac/ed/lurg/landuse/Intensity.java @@ -45,6 +45,7 @@ public class Intensity { return unitEnergy; } + /** irrigation rate in litre/m2 */ public double getIrrigationRate() { return maxIrrigRate * irrigationIntensity; } diff --git a/src/ac/ed/lurg/landuse/IrrigationItem.java b/src/ac/ed/lurg/landuse/IrrigationItem.java index b209ed0f..fa266640 100644 --- a/src/ac/ed/lurg/landuse/IrrigationItem.java +++ b/src/ac/ed/lurg/landuse/IrrigationItem.java @@ -11,7 +11,7 @@ public class IrrigationItem implements RasterItem { // when is the limited to be >= 0 (only Greenland had negative values) // this gives a value from 1 to 0, with 1 being the most costly and 0 the least. - private double irrigationCost; // cost per ? of irrigation + private double irrigationCost; // cost per 10000 Mlitre or 10^10 l or 10^7 m3 or 10^-2 km3, when multipled by rates from areas in Mha makes sense to have it in this apparently odd unit private double irrigConstraint; // mm or litre/m2 (they are the same) of water available private Map<CropType, Double> maxIrrigAmounts = new HashMap<CropType, Double>(); // amount of water (litres/m2) used at maximum irrigation, i.e. to achieve no water stress diff --git a/src/ac/ed/lurg/landuse/LandUseItem.java b/src/ac/ed/lurg/landuse/LandUseItem.java index 7838ff59..94c2d60d 100644 --- a/src/ac/ed/lurg/landuse/LandUseItem.java +++ b/src/ac/ed/lurg/landuse/LandUseItem.java @@ -69,32 +69,35 @@ public class LandUseItem implements InterpolatingRasterItem<LandUseItem> { return getFertiliserTotal(items, crops.toArray(new CropType[crops.size()])); } - /** Irrigation rate in litre/ha */ + /** Irrigation rate in litre/m2 */ public double getIrrigationRate(CropType crop) { Intensity i = getIntensity(crop); return (i == null) ? 0 : i.getIrrigationRate(); } - /** Irrigation amount in M litres, for this location */ - public double getIrrigationAmount(CropType c) { + /** Irrigation amount in km3 or 10^9 m3, for this location */ + private double getIrrigationAmount(CropType c) { double rate = getIrrigationRate(c); double area = getCropArea(c); - return rate * area; + return rate * area * 0.01; // rate(10^-3m or mm or l/m2) * area(10^6ha) = 10^3 m.ha = 10^7 m3 = 1/100 km3 } + /** Irrigation rate in litre/m2 */ public double getIrrigationAverageRate(CropType... crops) { double irrigTotal = 0; double areaTotal = 0; for (CropType c : crops) { - irrigTotal += getIrrigationAmount(c); - areaTotal = getCropArea(c); + double area = getCropArea(c); + irrigTotal += getIrrigationRate(c) * area; + areaTotal += area; } return areaTotal > 0 ? irrigTotal / areaTotal : 0; } + /** Irrigation amount in km3, for this location */ public static double getIrrigationTotal(Collection<? extends LandUseItem> items, CropType... crops) { double total = 0; for (LandUseItem a : items) { diff --git a/src/ac/ed/lurg/utils/LogWriter.java b/src/ac/ed/lurg/utils/LogWriter.java index 27ca8df9..32b5da0c 100644 --- a/src/ac/ed/lurg/utils/LogWriter.java +++ b/src/ac/ed/lurg/utils/LogWriter.java @@ -52,7 +52,7 @@ public class LogWriter { private void print(String s, PrintStream stream, boolean newLine) { logFile.write(s); if (newLine) logFile.write(System.lineSeparator()); - // logFile.flush(); + logFile.flush(); if (!ModelConfig.SUPPRESS_STD_OUTPUT) { stream.print(s); -- GitLab