Newer
Older
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import ac.ed.lurg.country.CompositeCountry;
import ac.ed.lurg.country.CompositeCountryManager;
import ac.ed.lurg.country.CountryAgent;
import ac.ed.lurg.country.CountryBoundaryRaster;
import ac.ed.lurg.country.CountryBoundaryReader;
import ac.ed.lurg.demand.BaseConsumpManager;
import ac.ed.lurg.demand.DemandManager;
import ac.ed.lurg.landuse.CropUsageData;
import ac.ed.lurg.landuse.IrrigationConstraintReader;
import ac.ed.lurg.landuse.IrrigationItem;
import ac.ed.lurg.landuse.IrrigationMaxAmountReader;
import ac.ed.lurg.landuse.IrrigiationCostReader;
import ac.ed.lurg.landuse.LandCoverItem;
import ac.ed.lurg.landuse.LandCoverReader;
import ac.ed.lurg.landuse.LandUseItem;
import ac.ed.lurg.output.LpjgOutputer;
import ac.ed.lurg.types.LandCoverType;
import ac.ed.lurg.types.ModelFitType;
import ac.ed.lurg.utils.LogWriter;
import ac.ed.lurg.yield.LPJYieldResponseMapReader;
import ac.ed.lurg.yield.YieldRaster;
import ac.ed.lurg.yield.YieldResponsesItem;
import ac.sac.raster.RasterKey;
import ac.sac.raster.RasterOutputer;
public class ModelMain {
private Collection<CountryAgent> countryAgents;
private CountryBoundaryRaster countryBoundaryRaster;
private CompositeCountryManager compositeCountryManager;
private Map<CropType, Double> prevWorldPrices;
private RasterSet<LandUseItem> prevLandUseRaster;
public static void main(String[] args) {
ModelMain theModel = new ModelMain();
theModel.setup();
theModel.run();
}
/* setup models, reading inputs, etc. */
private void setup() {
desiredProjection = RasterHeaderDetails.getGlobalHeaderFromCellSize(ModelConfig.CELL_SIZE_X, ModelConfig.CELL_SIZE_Y, "999");
BaseConsumpManager baseConsumpManager = new BaseConsumpManager();
compositeCountryManager = new CompositeCountryManager(baseConsumpManager);
demandManager = new DemandManager(ModelFitType.LOGISTIC, ModelConfig.SSP_SCENARIO, baseConsumpManager, compositeCountryManager);
countryBoundaryRaster = getCountryBoundaryRaster();
countryAgents = createCountryAgents(compositeCountryManager.getAll());
// in first timestep we don't have this info, but ok as constrained to import/export specified amount
prevWorldPrices = new HashMap<CropType, Double>();
prevWorldPrices.put(CropType.STARCHY_ROOTS, 1.4);
for (int i = ModelConfig.START_TIMESTEP; i <= ModelConfig.END_TIMESTEP; i++) {
Timestep timestep = new Timestep(i);
LpjgOutputer.writeMarkerFile(timestep.getYear(), true);
private void doTimestep(Timestep timestep) {
LogWriter.println(timestep.toString());
YieldRaster yieldSurfaces = getYieldSurfaces(timestep); // this will wait for the marker file from LPJ if configured to do so
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();
RasterSet<LandUseItem> globalLandUseRaster = new RasterSet<LandUseItem>(desiredProjection);
RasterSet<IntegerRasterItem> globalLocationIdRaster = new RasterSet<IntegerRasterItem>(desiredProjection);
Collection<RasterKey> countryKeys = countryBoundaryRaster.getKeysFor(ca.getCountry());
YieldRaster countryYieldSurfaces = yieldSurfaces.createSubsetForKeys(countryKeys);
try {
result = ca.determineProduction(timestep, countryYieldSurfaces, prevWorldPrices);
}
catch (Exception e) {
LogWriter.printlnError("Exception processing " + ca.getCountry() + " will continue with other countries");
e.printStackTrace();
}
if (result == null) {
LogWriter.printlnError("No results for " + ca.getCountry());
continue;
}
globalLandUseRaster.putAll(result.getLandUses());
globalLocationIdRaster.putAll(result.getLocationIdRaster());
// Get values for world input costs
Map<CropType, CropUsageData> cropUsage = result.getCropUsageData();
for (Entry<CropType, CropUsageData> entry : cropUsage.entrySet()) {
CropType c = entry.getKey();
double countryNetImports = entry.getValue().getNetImports();
if (countryNetImports > 0)
totalImportCommodities.incrementValue(c, countryNetImports);
else
totalExportCommodities.incrementValue(c, -countryNetImports);
// Look at trade balance and adjust appropriately
for (CropType crop : CropType.getImportedTypes()) {
double prevPrice = prevWorldPrices.get(crop);
if (!totalImportCommodities.containsKey(crop) || !totalExportCommodities.containsKey(crop)) {
LogWriter.printlnError(String.format("Price for %s not updated (still %.3f), as no imports or no exports for it", crop.getGamsName(), prevPrice));
continue;
}
double imports = totalImportCommodities.get(crop);
double exports = totalExportCommodities.get(crop) * (1.0-ModelConfig.TRANSPORT_LOSSES);
double adjustedPrice = updateMarketPrices(prevPrice, imports, exports);
LogWriter.println(String.format("Price for %s updated from %.3f (imports %.0f, exports %.0f) to %.3f ", crop.getGamsName(), prevPrice, imports, exports, adjustedPrice));
prevWorldPrices.put(crop, adjustedPrice);
}
outputTimestepResults(timestep, globalLandUseRaster, globalLocationIdRaster, yieldSurfaces);
prevLandUseRaster = globalLandUseRaster;
public double updateMarketPrices(double previousPrice, double demand, double supply) {
if (demand > 0 || supply > 0) {
double ratio;
if (demand > supply)
ratio = (demand-supply)/demand;
else
ratio = (demand-supply)/supply;
double adjustment = Math.exp(ratio * ModelConfig.MARKET_LAMBA);
return previousPrice * adjustment;
}
else {
return previousPrice;
}
}
private BufferedWriter getFileWriter(Timestep timestep, String file, String columnHeadings) throws IOException {
if (timestep.isInitialTimestep()) {
FileWriter fstream = new FileWriter(file,false);
BufferedWriter outputFile = new BufferedWriter(fstream);
outputFile.write(columnHeadings);
outputFile.newLine();
return outputFile;
}
else {
FileWriter fstream = new FileWriter(file,true);
return new BufferedWriter(fstream);
}
}
private void writeMarketFile(Timestep timestep, RasterSet<LandUseItem> landUseRaster) {
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)");
// for (CropType crop : CropType.getImportedTypes())
// sbHeadings.append(",Px_" + crop.getGamsName());
BufferedWriter outputFile = getFileWriter(timestep, ModelConfig.TOTAL_LAND_COVER_FILE, sbHeadings.toString());
StringBuffer sbData = new StringBuffer();
sbData.append(String.format("%d, %.1f, %.1f, %.1f",
timestep.getYear(),
LandUseItem.getTotalLandCover(landUseRaster.values(), LandCoverType.CROPLAND),
LandUseItem.getTotalLandCover(landUseRaster.values(), LandCoverType.PASTURE),
LandUseItem.getTotalLandCover(landUseRaster.values(), LandCoverType.OTHER_NATURAL)));
sbData.append(String.format(", %.1f", LandUseItem.getFertiliserTotal(landUseRaster.values(), CropType.getCropsLessPasture())/1000));
// double f = LandUseItem.getFertiliserTotal(landUseRaster.values(), CropType.MAIZE)/1000;
// double c = LandUseItem.getTotalCropArea(landUseRaster.values(), CropType.MAIZE);
sbData.append(String.format(", %.1f", LandUseItem.getFertiliserTotal(landUseRaster.values(), CropType.PASTURE)/1000));
sbData.append(String.format(", %.1f", LandUseItem.getIrrigationTotal(landUseRaster.values(), CropType.getCropsLessPasture())));
sbData.append(String.format(", %.1f", LandUseItem.getIrrigationTotal(landUseRaster.values(), CropType.PASTURE)));
// for (CropType crop : CropType.getImportedTypes() )
// sbData.append(String.format(", %.3f", prevWorldPrices.get(crop)));
outputFile.write(sbData.toString());
outputFile.newLine();
outputFile.close();
}
catch (IOException e) {
e.printStackTrace();
}
private void outputTimestepResults(Timestep timestep, RasterSet<LandUseItem> landUseRaster, RasterSet<IntegerRasterItem> locationIdRaster, YieldRaster yieldSurfaces) {
writeMarketFile(timestep, landUseRaster);
if (ModelConfig.OUTPUT_FOR_LPJG) {
for (int outputYear : timestep.getYearsFromLast()) {
LogWriter.printlnError("Outputing Year: " + outputYear);
RasterSet<LandUseItem> landUseToOutput;
landUseToOutput = landUseRaster;
InterpolatingRasterSet<LandUseItem> intermediateLandUse = new InterpolatingRasterSet<LandUseItem>(landUseRaster.getHeaderDetails()) {
private static final long serialVersionUID = 1306045141011047760L;
protected LandUseItem createRasterData() {
return new LandUseItem();
intermediateLandUse.setup(prevLandUseRaster, landUseRaster, timestep.getPreviousTimestep().getYear(), timestep.getYear(), outputYear);
landUseToOutput = intermediateLandUse;
LpjgOutputer lpjOutputer = new LpjgOutputer(outputYear, landUseToOutput, yieldSurfaces);
outputLandCover(timestep.getYear(), landUseRaster, LandCoverType.CROPLAND);
outputLandCover(timestep.getYear(), landUseRaster, LandCoverType.PASTURE);
private void outputLandCover(int year, RasterSet<LandUseItem> landUseRaster, final LandCoverType lcType) {
new RasterOutputer<LandUseItem>(landUseRaster, lcType.getName() + "Area" + year) {
@Override
public Double getValue(RasterKey location) {
LandUseItem item = results.get(location);
if (item == null)
return item.getLandCoverArea(lcType);
}.writeOutput();
public CountryBoundaryRaster getCountryBoundaryRaster() {
CountryBoundaryRaster countryBoundaries = new CountryBoundaryRaster(desiredProjection, compositeCountryManager);
CountryBoundaryReader countryReader = new CountryBoundaryReader(countryBoundaries);
countryReader.getRasterDataFromFile(ModelConfig.COUNTRY_BOUNDARY_FILE);
public Collection<CountryAgent> createCountryAgents(Collection<CompositeCountry> countryGrouping) {
Collection<CountryAgent> countryAgents = new HashSet<CountryAgent>();
RasterSet<LandCoverItem> initLC = getInitialLandCover();
RasterSet<IrrigationItem> allIrrigationCosts = getIrrigationData();
Map<CompositeCountry, Map<CropType, CropUsageData>> cropUsageDataMap = new CropUsageReader(compositeCountryManager).getCommodityData();
for (CompositeCountry cc : countryGrouping) {
if (ModelConfig.DEBUG_LIMIT_COUNTRIES) {
if (!(cc.getName().equals("United States of America") || cc.getName().equals("Russian Federationxx") || cc.getName().equals("South Asia_otherxx")) ) {
continue;
}
List<RasterKey> keys = countryBoundaryRaster.getKeysFor(cc);
RasterSet<LandCoverItem> initCountryLC = initLC.createSubsetForKeys(keys);
RasterSet<IrrigationItem> irrigationCosts = allIrrigationCosts.createSubsetForKeys(keys);
Map<CropType, CropUsageData> countryCommodityData = cropUsageDataMap.get(cc);
LogWriter.printlnError("No commodities data for " + cc + ", so skipping");
LogWriter.printlnError("No initial land cover for " +cc + ", so skipping");
CountryAgent ca = new CountryAgent(demandManager, cc, initCountryLC, irrigationCosts, countryCommodityData);
LogWriter.println("Creating country agent for: " + cc );
LandCoverReader lcReader = new LandCoverReader(desiredProjection);
RasterSet<LandCoverItem> initLC = lcReader.getRasterDataFromFile(ModelConfig.INITAL_LAND_COVER_FILE);
private YieldRaster getYieldSurfaces(Timestep timestep) {
LPJYieldResponseMapReader yieldReader = new LPJYieldResponseMapReader(desiredProjection);
return yieldReader.getRasterData(timestep);
private RasterSet<IrrigationItem> getIrrigationData() {
RasterSet<IrrigationItem> irigData = new RasterSet<IrrigationItem>(desiredProjection) {
private static final long serialVersionUID = 8393130687550888654L;
protected IrrigationItem createRasterData() {
return new IrrigationItem();
new IrrigiationCostReader(irigData).getRasterDataFromFile(ModelConfig.IRRIGATION_COST_FILE);
new IrrigationConstraintReader(irigData).getRasterDataFromFile(ModelConfig.IRRIGATION_CONSTRAINT_FILE);
new IrrigationMaxAmountReader(irigData).getRasterDataFromFile(ModelConfig.IRRIG_MAX_WATER_FILE);
return irigData;