From 320026059644aee8f2cf64ded14a62974f02e7f6 Mon Sep 17 00:00:00 2001 From: s1924442 <b.arendarczyk@sms.ed.ac.uk> Date: Mon, 8 Feb 2021 14:47:31 +0000 Subject: [PATCH] Initial changes to include wood yields and carbon fluxes. --- GAMS/IntExtOpt.gms | 275 ++++++++++-------- .../lurg/country/gams/GamsLocationInput.java | 17 +- .../ed/lurg/country/gams/GamsRasterInput.java | 18 +- src/ac/ed/lurg/landuse/CarbonFluxItem.java | 22 ++ .../ed/lurg/landuse/CarbonFluxRasterSet.java | 28 ++ src/ac/ed/lurg/landuse/WoodYieldItem.java | 21 ++ src/ac/ed/lurg/types/NonCropType.java | 53 ++++ 7 files changed, 316 insertions(+), 118 deletions(-) create mode 100644 src/ac/ed/lurg/landuse/CarbonFluxItem.java create mode 100644 src/ac/ed/lurg/landuse/CarbonFluxRasterSet.java create mode 100644 src/ac/ed/lurg/landuse/WoodYieldItem.java create mode 100644 src/ac/ed/lurg/types/NonCropType.java diff --git a/GAMS/IntExtOpt.gms b/GAMS/IntExtOpt.gms index 6b558131..33495b6e 100644 --- a/GAMS/IntExtOpt.gms +++ b/GAMS/IntExtOpt.gms @@ -1,18 +1,24 @@ - SET all_types / monogastrics, ruminants, cereals, oilcropspulses, wheat, maize, rice, oilcrops, pulses, starchyRoots, fruitveg, sugar, energycrops, pasture, setaside /; - - SET crop(all_types) / wheat, maize, rice, oilcrops, pulses, starchyRoots, fruitveg, sugar, energycrops, pasture, setaside /; - SET crop_less_pasture(crop) / wheat, maize, rice, oilcrops, pulses, starchyRoots, fruitveg, sugar, energycrops, setaside/; - SET cereal_crop(crop) / wheat, maize, rice /; - SET oilpulse_crop(crop) / oilcrops, pulses /; - SET feed_crop(crop) / wheat, maize, rice, oilcrops, pulses, starchyRoots, fruitveg, pasture/; - SET feed_crop_less_pasture(feed_crop) / wheat, maize, rice, oilcrops, pulses, starchyRoots, fruitveg /; - SET import_crop(all_types) / monogastrics, ruminants, wheat, maize, rice, oilcrops, pulses, starchyRoots, fruitveg, sugar, energycrops /; - + + SET all_types / monogastrics, ruminants, cereals, oilcropspulses, wheat, maize, rice, oilcrops, pulses, starchyRoots, fruitveg, sugar, energycrops, pasture, setaside, carbonForest, timberForest, natural /; + + SET crop(all_types) / wheat, maize, rice, oilcrops, pulses, starchyRoots, fruitveg, sugar, energycrops, pasture, setaside /; + SET crop_less_pasture(crop) / wheat, maize, rice, oilcrops, pulses, starchyRoots, fruitveg, sugar, energycrops, setaside/; + SET cereal_crop(crop) / wheat, maize, rice /; + SET oilpulse_crop(crop) / oilcrops, pulses /; + SET feed_crop(crop) / wheat, maize, rice, oilcrops, pulses, starchyRoots, fruitveg, pasture/; + SET feed_crop_less_pasture(feed_crop) / wheat, maize, rice, oilcrops, pulses, starchyRoots, fruitveg /; + SET import_crop(all_types) / monogastrics, ruminants, wheat, maize, rice, oilcrops, pulses, starchyRoots, fruitveg, sugar, energycrops/; + SET wood_producing(all_types) / timberForest, carbonForest, natural/; +* SET forest(all_types) / timberForest, carbonForest /; + + ALIAS (all_types, lu_type_previous); + SET location; PARAMETER suitableLandArea(location) areas of land in Mha; - PARAMETER previousArea(crop, location) areas for previous timestep in Mha; + PARAMETER previousCropArea(crop, location) areas for previous timestep in Mha; + PARAMETER previousNonCropArea(wood_producing, location); PARAMETER previousFertIntensity(crop, location); - PARAMETER previousIrrigIntensity(crop, location); + PARAMETER previousIrrigIntensity(crop, location); PARAMETER previousOtherIntensity(crop, location); PARAMETER previousRuminantFeed(crop); PARAMETER previousMonogastricFeed(crop); @@ -25,7 +31,7 @@ PARAMETER yieldShock(crop, location) rate of yield shock; PARAMETER fertParam(crop, location) yield response to fertilizer parameter; PARAMETER irrigParam(crop, location) yield response to irrigation parameter; - PARAMETER demand(all_types) in t; + PARAMETER demand(all_types) in t; PARAMETER exportPrices(import_crop) prices for exports; PARAMETER importPrices(import_crop) prices for imports; PARAMETER maxNetImport(import_crop) maximum net import for each crop based on world market; @@ -37,13 +43,13 @@ PARAMETER minDemandPerOilcrop(oilpulse_crop) min demand for oilcrop pulses as factor of total; PARAMETER seedAndWasteRate(all_types) rate of use for seed and waste combined; PARAMETER subsidyRate(crop) rates of subsidy compared to costs; - + PARAMETER agriExpansionCost(location) price for increase agricultural area varies based on amount of managed or unmanaged forest; SCALAR pastureIncCost price for increasing pasture area; SCALAR cropIncCost price for increasing crop; SCALAR cropDecCost price for decreasing crop; SCALAR pastureDecCost price for decreasing pasture; - + SCALAR meatEfficency efficiency of converting feed and pasture into animal products; SCALAR fertiliserUnitCost fert cost at max fert rate; SCALAR otherIParam yield response to other intensity; @@ -51,44 +57,50 @@ SCALAR unhandledCropRate rate of fruit veg and other crops not modelled; SCALAR setAsideRate rate of set aside and failed crop; SCALAR domesticPriceMarkup factor price increased from cost of production; - SCALAR maxLandExpansionRate max rate of country land expansion; + SCALAR maxLandExpansionRate max rate of country land expansion; + + PARAMETER carbonFluxRate(all_types, location) carbon flux; + PARAMETER woodYield(wood_producing, location) wood yield; + SCALAR carbonPrice price of carbon; + SCALAR woodPrice price of wood and timber; *$gdxin "/Users/peteralexander/Documents/R_Workspace/UNPLUM/temp/GamsTmp/t1.gdx" -$gdxin %gdxincname% +$gdxin %gdxincname% $load location, suitableLandArea, demand, agriExpansionCost, cropIncCost, pastureIncCost, cropDecCost, pastureDecCost -$load previousArea, previousFertIntensity, previousIrrigIntensity, previousOtherIntensity, previousRuminantFeed, previousMonogastricFeed, previousImportAmount, previousExportAmount +$load previousCropArea, previousFertIntensity, previousIrrigIntensity, previousOtherIntensity, previousRuminantFeed, previousMonogastricFeed, previousImportAmount, previousExportAmount $load yieldNone, yieldFertOnly, yieldIrrigOnly, yieldBoth, yieldShock $load fertParam, irrigParam, otherIParam, exportPrices, importPrices, maxNetImport, minNetImport, unhandledCropRate, setAsideRate, maxLandExpansionRate, subsidyRate $load meatEfficency, otherICost, irrigCost, irrigMaxRate, irrigConstraint, fertiliserUnitCost, domesticPriceMarkup, minDemandPerCereal, minDemandPerOilcrop, seedAndWasteRate -$gdxin - +$load carbonFluxRate, woodYield, carbonPrice, woodPrice +$gdxin + SCALAR delta use to smooth power function see 7.5 www.gams.com dd docs solversconopt.pdf / 0.00000000001 /; - + demand(cereal_crop) = demand('cereals') * minDemandPerCereal(cereal_crop); demand(oilpulse_crop) = demand('oilcropspulses') * minDemandPerOilcrop(oilpulse_crop); - - previousArea(crop_less_pasture, location) = previousArea(crop_less_pasture, location) * (1.0 - unhandledCropRate); - + + previousCropArea(crop_less_pasture, location) = previousCropArea(crop_less_pasture, location) * (1.0 - unhandledCropRate); + PARAMETER cropDM(crop) kg DM per kg of feed the conversion from feed to meat is done in the R animal product index. Pasture is in DM terms already - / wheat 0.87 - maize 0.86 + / wheat 0.87 + maize 0.86 rice 0.89 - oilcrops 0.96 + oilcrops 0.96 pulses 0.31 starchyRoots 0.25 fruitveg 0.1 sugar 1 - pasture 1 / ; - + pasture 1 / ; + PARAMETER prodCost(crop) cost per ha before intensity values not including fertiliser or irrigation i.e. seed spray and other. In 1000 $ per ha - / wheat 0.32 - maize 0.31 + / wheat 0.32 + maize 0.31 rice 0.36 oilcrops 0.2 pulses 0.31 - starchyRoots 3.14 + starchyRoots 3.14 fruitveg 4.0 - sugar 3.0 + sugar 3.0 energyCrops 0.34 / ; PARAMETER baseCost(crop); @@ -97,9 +109,13 @@ $gdxin otherIntCost(crop) = baseCost(crop)*0.7 + otherICost; baseCost('pasture') = 0.04; otherIntCost('pasture') = 0.8 + otherICost; - + +*PARAMETER lcTransitionCost(lc_type_previous, lc_type, location) cost of land transitions including carbon cost and conversion cost; +*lcTransitionCost(lc_type_previous, lc_type, location) = carbonFluxRate(lc_type_previous, lc_type, location) * carbonPrice + agriExpansionCost(location); + VARIABLES - area(crop, location) total area for each crop - Mha + cropArea(crop, location) total area for crops - Mha + nonCropArea(wood_producing, location) forest and natural area fertI(crop, location) fertilizer intensity for each crop - factor between 0 and 1 irrigI(crop, location) irrigation intensity for each crop - factor between 0 and 1 otherIntensity(crop, location) @@ -111,18 +127,21 @@ $gdxin unitCost(crop, location) cost per area for each crop - cost net_supply(crop) supply after exports and feed agriLandExpansion(location) addition agricultural land needed as it must be positive it deliberately does not account for abandonment - cropIncrease(location) - cropDecrease(location) - pastureIncrease(location) - pastureDecrease(location) - totalFeedDM + cropIncrease(location) + cropDecrease(location) + pastureIncrease(location) + pastureDecrease(location) + woodHarvest(location) total wood harvested + carbonFlux(location) total carbon flux + totalFeedDM total_cost total cost of domestic supply including net imports; - - POSITIVE VARIABLE area, fertI, irrigI, otherIntensity, ruminantFeed, monogastricFeed, importAmount, exportAmount, - agriLandExpansion, cropIncrease, cropDecrease, pastureDecrease, pastureIncrease, totalFeedDM; - + + POSITIVE VARIABLE cropArea, nonCropArea, fertI, irrigI, otherIntensity, ruminantFeed, monogastricFeed, importAmount, exportAmount, + agriLandExpansion, cropIncrease, cropDecrease, pastureDecrease, pastureIncrease, totalFeedDM, + woodHarvest, carbonFlux; + EQUATIONS - UNIT_COST_EQ(crop, location) cost per area + UNIT_COST_EQ(crop, location) cost per area YIELD_EQ(crop, location) yield given chosen intensity CROP_DEMAND_CONSTRAINT(crop) satisfy demand for individual crops TOTAL_CEREAL_DEMAND_CONSTRAINT satisfy demand for combined cereals @@ -135,108 +154,134 @@ $gdxin MAX_IRRIG_INTENSITY_CONSTRAINT(crop, location) constraint on maximum irrigation intensity MAX_OTHER_INTENSITY_CONSTRAINT(crop, location) SETASIDE_AREA_CALC(location) - TOTAL_LAND_CHANGE_CONSTRAINT(location) constraint on suitable land use + TOTAL_LAND_CHANGE_CONSTRAINT(location) constraint on suitable land use MAX_NET_IMPORT_CONSTRAINT(import_crop) constraint on max net imports MIN_NET_IMPORT_CONSTRAINT(import_crop) constraint on min net imports PASTURE_IMPORT_CONSTRAINT constraint to not import pasture PASTURE_EXPORT_CONSTRAINT + TIMBER_IMPORT_CONSTRAINT constraint to not import timber (for now) + TIMBER_EXPORT_CONSTRAINT + CARBON_IMPORT_CONSTRAINT constraint to not import carbon + CARBON_EXPORT_CONSTRAINT + NATURAL_IMPORT_CONSTRAINT constraint to not import natural + NATURAL_EXPORT_CONSTRAINT IRRIGATION_CONSTRAINT(location) constraint no water usage NET_SUPPLY_EQ(crop) calc net supply for crops AGRI_LAND_EXPANSION_CALC(location) calc agriLandExpansion - CROP_INCREASE_CALC(location) - CROP_DECREASE_CALC(location) - PASTURE_INCREASE_CONV_CALC(location) - PASTURE_DECREASE_CONV_CALC(location) - PASTURE_TOTAL_CHANGE_CONSTRAINT(location) + CROP_INCREASE_CALC(location) + CROP_DECREASE_CALC(location) + PASTURE_INCREASE_CONV_CALC(location) + PASTURE_DECREASE_CONV_CALC(location) + PASTURE_TOTAL_CHANGE_CONSTRAINT(location) + WOOD_HARVEST_CALC(location) calc wood harvested + CARBON_FLUX_CALC(location) calc carbon flux COST_EQ total cost objective function; - - UNIT_COST_EQ(crop, location) .. unitCost(crop, location) =E= ( baseCost(crop) + - fertiliserUnitCost * fertI(crop, location) + + + UNIT_COST_EQ(crop, location) .. unitCost(crop, location) =E= ( baseCost(crop) + + fertiliserUnitCost * fertI(crop, location) + irrigCost(location) * irrigMaxRate(crop, location) * irrigI(crop, location) + otherIntCost(crop) * otherIntensity(crop, location) ) ; - + YIELD_EQ(crop, location) .. yield(crop, location) =E= ( - yieldNone(crop, location) + + yieldNone(crop, location) + (yieldFertOnly(crop, location) - yieldNone(crop, location)) * (1 - exp(-fertParam(crop, location)*fertI(crop, location))) + (yieldIrrigOnly(crop, location) - yieldNone(crop, location)) * (1 - exp(-irrigParam(crop, location)*irrigI(crop, location))) + (yieldBoth(crop, location) + yieldNone(crop, location) - yieldFertOnly(crop, location) - yieldIrrigOnly(crop, location)) * (1 - exp(-fertParam(crop, location)*fertI(crop, location))) * (1 - exp(-irrigParam(crop, location)*irrigI(crop, location))) ) * (1 - exp(-otherIntensity(crop, location)*otherIParam)); - - NET_SUPPLY_EQ(crop) .. net_supply(crop) =E= sum(location, area(crop, location) * yield(crop, location)) * (1 - seedAndWasteRate(crop)) - ruminantFeed(crop) - monogastricFeed(crop) + importAmount(crop) - exportAmount(crop); - + + NET_SUPPLY_EQ(crop) .. net_supply(crop) =E= sum(location, cropArea(crop, location) * yield(crop, location)) * (1 - seedAndWasteRate(crop)) - ruminantFeed(crop) - monogastricFeed(crop) + importAmount(crop) - exportAmount(crop); + CROP_DEMAND_CONSTRAINT(crop) .. net_supply(crop) =G= demand(crop); - + TOTAL_CEREAL_DEMAND_CONSTRAINT .. sum(cereal_crop, net_supply(cereal_crop)) =G= demand('cereals'); - + TOTAL_OIL_PULSE_DEMAND_CONSTRAINT .. sum(oilpulse_crop, net_supply(oilpulse_crop)) =G= demand('oilcropspulses'); - + RUMINANT_DEMAND_CONSTRAINT .. meatEfficency * sum(feed_crop, ruminantFeed(feed_crop) * cropDM(feed_crop)) * (1 - seedAndWasteRate('ruminants')) =G= (demand('ruminants') - importAmount('ruminants') + exportAmount('ruminants')); - + MONOGASTRICS_DEMAND_CONSTRAINT .. meatEfficency * sum(feed_crop_less_pasture, monogastricFeed(feed_crop_less_pasture) * cropDM(feed_crop_less_pasture)) * (1 - seedAndWasteRate('monogastrics')) =G= (demand('monogastrics') - importAmount('monogastrics') + exportAmount('monogastrics')); - + TOTAL_NON_PASTURE_FEED_DM_CALC .. totalFeedDM =E= sum(feed_crop_less_pasture, (ruminantFeed(feed_crop_less_pasture) + monogastricFeed(feed_crop_less_pasture)) * cropDM(feed_crop_less_pasture)); FEED_MIX_CONSTRAINT(feed_crop_less_pasture) .. (ruminantFeed(feed_crop_less_pasture) + monogastricFeed(feed_crop_less_pasture)) * cropDM(feed_crop_less_pasture) =L= totalFeedDM * 0.7; - + MAX_FERT_INTENSITY_CONSTRAINT(crop, location) .. fertI(crop, location) =L= 1; MAX_IRRIG_INTENSITY_CONSTRAINT(crop, location) .. irrigI(crop, location) =L= 1; MAX_OTHER_INTENSITY_CONSTRAINT(crop, location) .. otherIntensity(crop, location) =L= 1; - - SETASIDE_AREA_CALC(location) .. area('setaside', location) =E= sum(crop_less_pasture, area(crop_less_pasture, location)) * setAsideRate; - - TOTAL_LAND_CHANGE_CONSTRAINT(location) .. suitableLandArea(location) =G= sum(crop_less_pasture, area(crop_less_pasture, location)) / (1.0 - unhandledCropRate) + area('pasture', location); - + + SETASIDE_AREA_CALC(location) .. cropArea('setaside', location) =E= sum(crop_less_pasture, cropArea(crop_less_pasture, location)) * setAsideRate; + + TOTAL_LAND_CHANGE_CONSTRAINT(location) .. suitableLandArea(location) =G= sum(crop_less_pasture, cropArea(crop_less_pasture, location)) / (1.0 - unhandledCropRate) + cropArea('pasture', location) + + sum(wood_producing, nonCropArea(wood_producing, location)); + MAX_NET_IMPORT_CONSTRAINT(import_crop) .. importAmount(import_crop) - exportAmount(import_crop) =L= maxNetImport(import_crop); MIN_NET_IMPORT_CONSTRAINT(import_crop) .. importAmount(import_crop) - exportAmount(import_crop) =G= minNetImport(import_crop); PASTURE_IMPORT_CONSTRAINT .. importAmount('pasture') =E= 0; PASTURE_EXPORT_CONSTRAINT .. exportAmount('pasture') =E= 0; - - IRRIGATION_CONSTRAINT(location) .. irrigConstraint(location) * suitableLandArea(location) * (1.0 - unhandledCropRate) =G= sum(crop, irrigMaxRate(crop, location) * irrigI(crop, location) * area(crop, location)); - - AGRI_LAND_EXPANSION_CALC(location) .. agriLandExpansion(location) =G= sum(crop, area(crop, location) - previousArea(crop, location)); - - CROP_INCREASE_CALC(location) .. cropIncrease(location) =G= sum(crop_less_pasture, area(crop_less_pasture, location) - previousArea(crop_less_pasture, location)); - CROP_DECREASE_CALC(location) .. cropDecrease(location) =G= -sum(crop_less_pasture, area(crop_less_pasture, location) - previousArea(crop_less_pasture, location)); - PASTURE_INCREASE_CONV_CALC(location) .. pastureIncrease(location) =G= area('pasture', location) - previousArea('pasture', location); - PASTURE_DECREASE_CONV_CALC(location) .. pastureDecrease(location) =G= -(area('pasture', location) - previousArea('pasture', location)); - PASTURE_TOTAL_CHANGE_CONSTRAINT(location) .. pastureIncrease(location) -pastureDecrease(location) =G= area('pasture', location) - previousArea('pasture', location); - -* CROPLAND_INCREASE_CONSTRAINT(location) .. cropIncrease(location)/(1.0 - unhandledCropRate) =L= maxLandChangeRate * ( suitableLandArea(location) -sum(crop_less_pasture, previousArea(crop_less_pasture, location))/*(1.0 - unhandledCropRate) - previousArea('pasture', location) ); -* PASTURE_DECREASE_CONSTRAINT(location) .. pastureDecrease(location) =L= maxLandChangeRate * previousArea('pasture', location); - - COST_EQ .. total_cost =E= - ( - ( SUM((crop, location), area(crop, location) * unitCost(crop, location) * (1-subsidyRate(crop))) + - - SUM(location, + + MAX_NET_IMPORT_CONSTRAINT(import_crop) .. importAmount(import_crop) - exportAmount(import_crop) =L= maxNetImport(import_crop); + MIN_NET_IMPORT_CONSTRAINT(import_crop) .. importAmount(import_crop) - exportAmount(import_crop) =G= minNetImport(import_crop); + + TIMBER_IMPORT_CONSTRAINT .. importAmount('timberForest') =E= 0; + TIMBER_EXPORT_CONSTRAINT .. exportAmount('timberForest') =E= 0; + CARBON_IMPORT_CONSTRAINT .. importAmount('carbonForest') =E= 0; + CARBON_EXPORT_CONSTRAINT .. exportAmount('carbonForest') =E= 0; + NATURAL_IMPORT_CONSTRAINT .. importAmount('natural') =E= 0; + NATURAL_EXPORT_CONSTRAINT .. exportAmount('natural') =E= 0; + + IRRIGATION_CONSTRAINT(location) .. irrigConstraint(location) * suitableLandArea(location) * (1.0 - unhandledCropRate) =G= sum(crop, irrigMaxRate(crop, location) * irrigI(crop, location) * cropArea(crop, location)); + + AGRI_LAND_EXPANSION_CALC(location) .. agriLandExpansion(location) =G= sum(crop, cropArea(crop, location) - previousCropArea(crop, location)); + + CROP_INCREASE_CALC(location) .. cropIncrease(location) =G= sum(crop_less_pasture, cropArea(crop_less_pasture, location) - previousCropArea(crop_less_pasture, location)); + CROP_DECREASE_CALC(location) .. cropDecrease(location) =G= -sum(crop_less_pasture, cropArea(crop_less_pasture, location) - previousCropArea(crop_less_pasture, location)); + PASTURE_INCREASE_CONV_CALC(location) .. pastureIncrease(location) =G= cropArea('pasture', location) - previousCropArea('pasture', location); + PASTURE_DECREASE_CONV_CALC(location) .. pastureDecrease(location) =G= -(cropArea('pasture', location) - previousCropArea('pasture', location)); + PASTURE_TOTAL_CHANGE_CONSTRAINT(location) .. pastureIncrease(location) -pastureDecrease(location) =G= cropArea('pasture', location) - previousCropArea('pasture', location); + + WOOD_HARVEST_CALC(location) .. woodHarvest(location) =E= sum(wood_producing, nonCropArea(wood_producing, location) * woodYield(wood_producing, location)); + + CARBON_FLUX_CALC(location) .. carbonFlux(location) =E= sum(wood_producing, nonCropArea(wood_producing, location) * carbonFluxRate(wood_producing, location)); + +* CROPLAND_INCREASE_CONSTRAINT(location) .. cropIncrease(location)/(1.0 - unhandledCropRate) =L= maxLandChangeRate * ( suitableLandArea(location) -sum(crop_less_pasture, previousCropArea(crop_less_pasture, location))/*(1.0 - unhandledCropRate) - previousCropArea('pasture', location) ); +* PASTURE_DECREASE_CONSTRAINT(location) .. pastureDecrease(location) =L= maxLandChangeRate * previousCropArea('pasture', location); + + COST_EQ .. total_cost =E= + ( + ( SUM((crop, location), cropArea(crop, location) * unitCost(crop, location) * (1-subsidyRate(crop))) + + + SUM(location, agriExpansionCost(location) * agriLandExpansion(location) + - cropIncCost * cropIncrease(location) + - pastureIncCost * pastureIncrease(location) + - cropDecCost * cropDecrease(location) + + cropIncCost * cropIncrease(location) + + pastureIncCost * pastureIncrease(location) + + cropDecCost * cropDecrease(location) + pastureDecCost * pastureDecrease(location) ) - ) * domesticPriceMarkup + + ) * domesticPriceMarkup + + + SUM(location, carbonFlux(location) * carbonPrice) - SUM(location, woodHarvest(location) * woodPrice) + - SUM(import_crop, importAmount(import_crop) * importPrices(import_crop) - exportAmount(import_crop) * exportPrices(import_crop)) + SUM(import_crop, importAmount(import_crop) * importPrices(import_crop) - exportAmount(import_crop) * exportPrices(import_crop)) ); - + MODEL LAND_USE /ALL/ ; fertI.L(crop, location) = previousFertIntensity(crop, location); irrigI.L(crop, location) = previousIrrigIntensity(crop, location); otherIntensity.L(crop, location) = previousOtherIntensity(crop, location); - area.L(crop, location) = previousArea(crop, location); + cropArea.L(crop, location) = previousCropArea(crop, location); + nonCropArea.L(wood_producing, location) = previousNonCropArea(wood_producing, location); ruminantFeed.L(feed_crop) = previousRuminantFeed(feed_crop); monogastricFeed.L(feed_crop) = previousMonogastricFeed(feed_crop); importAmount.L(all_types) = previousImportAmount(all_types); exportAmount.L(all_types) = previousExportAmount(all_types); - + SOLVE LAND_USE USING NLP MINIMIZING total_cost; - - display agriLandExpansion.L, previousArea, irrigMaxRate, otherIntensity.L, fertI.L, irrigI.L, area.L, cropIncrease.L, cropDecrease.L, pastureIncrease.L, pastureDecrease.L; + + display agriLandExpansion.L, previousCropArea, irrigMaxRate, otherIntensity.L, fertI.L, irrigI.L, cropArea.L, cropIncrease.L, cropDecrease.L, pastureIncrease.L, pastureDecrease.L; display net_supply.l, demand, ruminantFeed.l, monogastricFeed.l, importAmount.l, exportAmount.l; -* Calculate summary information used in Java process +* Calculate summary information used in Java process parameter totalProd(all_types); parameter totalProdCost(all_types); parameter totalArea(crop); @@ -245,32 +290,32 @@ $gdxin parameter netImportCost(all_types); parameter feedCostRate(feed_crop); parameter productionShock(all_types); - + * Production quantities based on smaller area (before unhandledCropArea adjustment applied) - totalProd(crop) = sum(location, area.l(crop, location) * yield.l(crop, location)); - productionShock(crop) = sum(location, area.l(crop, location) * yield.l(crop, location) * yieldShock(crop, location)); + totalProd(crop) = sum(location, cropArea.l(crop, location) * yield.l(crop, location)); + productionShock(crop) = sum(location, cropArea.l(crop, location) * yield.l(crop, location) * yieldShock(crop, location)); totalProd('ruminants') = meatEfficency*(sum(feed_crop, ruminantFeed.l(feed_crop) * cropDM(feed_crop))); totalProd('monogastrics') = meatEfficency*(sum(feed_crop, monogastricFeed.l(feed_crop) * cropDM(feed_crop))); - + * Cost based on adjusted area - area.l(crop_less_pasture, location) = area.l(crop_less_pasture, location) / (1.0 - unhandledCropRate); - totalProdCost(crop) = sum(location, unitCost.l(crop, location) * area.l(crop, location)); - totalCropland(location) = sum(crop_less_pasture, area.l(crop_less_pasture, location)); - totalArea(crop) = sum(location, area.l(crop, location)); - + cropArea.l(crop_less_pasture, location) = cropArea.l(crop_less_pasture, location) / (1.0 - unhandledCropRate); + totalProdCost(crop) = sum(location, unitCost.l(crop, location) * cropArea.l(crop, location)); + totalCropland(location) = sum(crop_less_pasture, cropArea.l(crop_less_pasture, location)); + totalArea(crop) = sum(location, cropArea.l(crop, location)); + feedCostRate(feed_crop)$[totalProd(feed_crop) <> 0] = totalProdCost(feed_crop) / totalProd(feed_crop); totalProdCost('ruminants') = sum(feed_crop, ruminantFeed.l(feed_crop) * feedCostRate(feed_crop)); totalProdCost('monogastrics') = sum(feed_crop, monogastricFeed.l(feed_crop) * feedCostRate(feed_crop)); - + netImportCost(import_crop) = importAmount.l(import_crop) * importPrices(import_crop) - exportAmount.l(import_crop) * exportPrices(import_crop); netImportAmount(import_crop) = importAmount.l(import_crop) - exportAmount.l(import_crop); - + Scalar totalCostsLessLU; - + totalCostsLessLU = sum(crop,totalProdCost(crop))+ sum(import_crop,netImportCost(import_crop)); - - Scalar ms 'model status', ss 'solve status'; + + Scalar ms 'model status', ss 'solve status'; ms=LAND_USE.modelstat; ss=LAND_USE.solvestat; - \ No newline at end of file + diff --git a/src/ac/ed/lurg/country/gams/GamsLocationInput.java b/src/ac/ed/lurg/country/gams/GamsLocationInput.java index 218d6086..d00a90bf 100644 --- a/src/ac/ed/lurg/country/gams/GamsLocationInput.java +++ b/src/ac/ed/lurg/country/gams/GamsLocationInput.java @@ -3,8 +3,10 @@ package ac.ed.lurg.country.gams; import java.util.Map; import ac.ed.lurg.Timestep; +import ac.ed.lurg.landuse.CarbonFluxItem; import ac.ed.lurg.landuse.IrrigationItem; import ac.ed.lurg.landuse.LandUseItem; +import ac.ed.lurg.landuse.WoodYieldItem; import ac.ed.lurg.yield.YieldResponsesItem; public class GamsLocationInput { @@ -13,15 +15,20 @@ public class GamsLocationInput { private Map<Integer, ? extends YieldResponsesItem> yields; private Map<Integer, ? extends LandUseItem> previousLandUse; private Map<Integer, ? extends IrrigationItem> irrigationCosts; + private Map<Integer, ? extends CarbonFluxItem> carbonFluxes; + private Map<Integer, ? extends WoodYieldItem> woodYields; private GamsCountryInput countryInput; public GamsLocationInput(Timestep timestep, Map<Integer, ? extends YieldResponsesItem> yields, Map<Integer, ? extends LandUseItem> previousLandUse, - Map<Integer, ? extends IrrigationItem> irrigationCosts, GamsCountryInput countryInput) { + Map<Integer, ? extends IrrigationItem> irrigationCosts, Map<Integer, ? extends CarbonFluxItem> carbonFluxes, + Map<Integer, ? extends WoodYieldItem> woodYields, GamsCountryInput countryInput) { super(); this.timestep = timestep; this.yields = yields; this.previousLandUse = previousLandUse; this.irrigationCosts = irrigationCosts; + this.carbonFluxes = carbonFluxes; + this.woodYields = woodYields; this.countryInput = countryInput; } @@ -37,6 +44,14 @@ public class GamsLocationInput { return irrigationCosts; } + public Map<Integer, ? extends CarbonFluxItem> getCarbonFluxes() { + return carbonFluxes; + } + + public Map<Integer, ? extends WoodYieldItem> getWoodYields() { + return woodYields; + } + public GamsCountryInput getCountryInput() { return countryInput; } diff --git a/src/ac/ed/lurg/country/gams/GamsRasterInput.java b/src/ac/ed/lurg/country/gams/GamsRasterInput.java index 072d0754..f6ef7f85 100644 --- a/src/ac/ed/lurg/country/gams/GamsRasterInput.java +++ b/src/ac/ed/lurg/country/gams/GamsRasterInput.java @@ -2,6 +2,8 @@ package ac.ed.lurg.country.gams; import ac.ed.lurg.Timestep; import ac.ed.lurg.landuse.LandUseItem; +import ac.ed.lurg.landuse.WoodYieldItem; +import ac.ed.lurg.landuse.CarbonFluxItem; import ac.ed.lurg.landuse.IrrigationItem; import ac.ed.lurg.yield.YieldRaster; import ac.sac.raster.RasterSet; @@ -12,15 +14,19 @@ public class GamsRasterInput { private YieldRaster yields; private RasterSet<LandUseItem> previousLandsUses; private RasterSet<IrrigationItem> irrigationCost; + private RasterSet<CarbonFluxItem> carbonFluxes; + private RasterSet<WoodYieldItem> woodYields; private GamsCountryInput countryInput; - public GamsRasterInput(Timestep timestep, YieldRaster yields, RasterSet<LandUseItem> previousLandsUses, - RasterSet<IrrigationItem> irrigationCost, GamsCountryInput countryInput) { + public GamsRasterInput(Timestep timestep, YieldRaster yields, RasterSet<LandUseItem> previousLandsUses, RasterSet<IrrigationItem> irrigationCost, + RasterSet<CarbonFluxItem> carbonFluxes, RasterSet<WoodYieldItem> woodYields, GamsCountryInput countryInput) { super(); this.timestep = timestep; this.yields = yields; this.previousLandsUses = previousLandsUses; this.irrigationCost = irrigationCost; + this.carbonFluxes = carbonFluxes; + this.woodYields = woodYields; this.countryInput = countryInput; } @@ -36,6 +42,14 @@ public class GamsRasterInput { return irrigationCost; } + public RasterSet<CarbonFluxItem> getCarbonFluxes() { + return carbonFluxes; + } + + public RasterSet<WoodYieldItem> getWoodYields() { + return woodYields; + } + public GamsCountryInput getCountryInput() { return countryInput; } diff --git a/src/ac/ed/lurg/landuse/CarbonFluxItem.java b/src/ac/ed/lurg/landuse/CarbonFluxItem.java new file mode 100644 index 00000000..e83ebf77 --- /dev/null +++ b/src/ac/ed/lurg/landuse/CarbonFluxItem.java @@ -0,0 +1,22 @@ +package ac.ed.lurg.landuse; + +import ac.sac.raster.RasterItem; +import java.util.HashMap; +import java.util.Map; + +import ac.ed.lurg.types.LandCoverType; + +public class CarbonFluxItem implements RasterItem { + Map<LandCoverType, Map<LandCoverType, Double>> carbonFluxes = new HashMap<LandCoverType, Map<LandCoverType, Double>>(); + + public void setCarbonFlux(LandCoverType previousLandCover, LandCoverType newLandCover, Double carbonFlux) { + Map<LandCoverType, Double> cfMap = new HashMap<LandCoverType, Double>(); + cfMap.put(newLandCover, carbonFlux); + carbonFluxes.put(previousLandCover, cfMap); + } + + public Double getCarbonFlux(LandCoverType previousLandCover, LandCoverType newLandCover) { + return carbonFluxes.get(previousLandCover).get(newLandCover); + } + +} diff --git a/src/ac/ed/lurg/landuse/CarbonFluxRasterSet.java b/src/ac/ed/lurg/landuse/CarbonFluxRasterSet.java new file mode 100644 index 00000000..059bfac4 --- /dev/null +++ b/src/ac/ed/lurg/landuse/CarbonFluxRasterSet.java @@ -0,0 +1,28 @@ +package ac.ed.lurg.landuse; + +import java.util.Collection; + +import ac.sac.raster.RasterHeaderDetails; +import ac.sac.raster.RasterKey; +import ac.sac.raster.RasterSet; + +public class CarbonFluxRasterSet extends RasterSet<CarbonFluxItem> { + + private static final long serialVersionUID = 4986837799421955684L; + + public CarbonFluxRasterSet(RasterHeaderDetails header) { + super(header); + } + + protected CarbonFluxItem createRasterData() { + return new CarbonFluxItem(); + } + + // not very efficient, we could keep the mapping of country to area somewhere. + @Override + public CarbonFluxRasterSet createSubsetForKeys(Collection<RasterKey> keys) { + CarbonFluxRasterSet subsetCarbonFluxRaster = new CarbonFluxRasterSet(getHeaderDetails()); + popSubsetForKeys(subsetCarbonFluxRaster, keys); + return subsetCarbonFluxRaster; + } +} diff --git a/src/ac/ed/lurg/landuse/WoodYieldItem.java b/src/ac/ed/lurg/landuse/WoodYieldItem.java new file mode 100644 index 00000000..ff7c23ae --- /dev/null +++ b/src/ac/ed/lurg/landuse/WoodYieldItem.java @@ -0,0 +1,21 @@ +package ac.ed.lurg.landuse; + +import java.util.HashMap; +import java.util.Map; + +import ac.ed.lurg.types.LandCoverType; +import ac.sac.raster.RasterItem; + +public class WoodYieldItem implements RasterItem { + Map<LandCoverType, Map<LandCoverType, Double>> woodYields = new HashMap<LandCoverType, Map<LandCoverType, Double>>(); + + public void setWoodYield(LandCoverType previousLandCover, LandCoverType newLandCover, Double woodYield) { + Map<LandCoverType, Double> cfMap = new HashMap<LandCoverType, Double>(); + cfMap.put(newLandCover, woodYield); + woodYields.put(previousLandCover, cfMap); + } + + public Double getWoodYield(LandCoverType previousLandCover, LandCoverType newLandCover) { + return woodYields.get(previousLandCover).get(newLandCover); + } +} diff --git a/src/ac/ed/lurg/types/NonCropType.java b/src/ac/ed/lurg/types/NonCropType.java new file mode 100644 index 00000000..ad5f9a6d --- /dev/null +++ b/src/ac/ed/lurg/types/NonCropType.java @@ -0,0 +1,53 @@ +package ac.ed.lurg.types; + +import java.util.Collection; +import java.util.HashSet; + +public enum NonCropType { + TIMBER_FOREST("timberForest", true, true), + CARBON_FOREST("carbonForest", true, true), + NATURAL("natural", true, false); + + private String gamsName; + private boolean isWoodProducing; + private boolean isManagedForest; + + private NonCropType (String gamsName, boolean isWoodProducing, boolean isManagedForest) { + this.gamsName = gamsName; + this.isWoodProducing = isWoodProducing; + this.isManagedForest = isManagedForest; + } + + public String getGamsName() { + return gamsName; + } + + public boolean isWoodProducing() { + return isWoodProducing; + } + + public boolean isManagedForest() { + return isManagedForest; + } + + public static Collection<NonCropType> getWoodProducingTypes() { + Collection<NonCropType> lu = new HashSet<NonCropType>(); + + for (NonCropType c : values()) + if (c.isWoodProducing) + lu.add(c); + + return lu; + } + + public static Collection<NonCropType> getManagedForestTypes() { + Collection<NonCropType> lu = new HashSet<NonCropType>(); + + for (NonCropType c : values()) + if (c.isManagedForest) + lu.add(c); + + return lu; + } + +} -- GitLab