diff --git a/data/country_codes3.csv b/data/country_codes3.csv deleted file mode 100644 index 5c5f90384582f1f3895595c64bd3cdadb7e7fc3b..0000000000000000000000000000000000000000 --- a/data/country_codes3.csv +++ /dev/null @@ -1 +0,0 @@ -Country,CountryCode,Region,IncomeGroup,numCode Aruba,ABW,Latin America & Caribbean,High income: nonOECD,533 Afghanistan,AFG,South Asia,Low income,4 Angola,AGO,Sub-Saharan Africa,Upper middle income,24 Albania,ALB,Europe & Central Asia,Upper middle income,8 Andorra,AND,Europe & Central Asia,High income: nonOECD,20 United Arab Emirates,ARE,Middle East & North Africa,High income: nonOECD,784 Argentina,ARG,Latin America & Caribbean,Upper middle income,32 Armenia,ARM,Europe & Central Asia,Lower middle income,51 American Samoa,ASM,East Asia & Pacific,Upper middle income,16 Antigua and Barbuda,ATG,Latin America & Caribbean,High income: nonOECD,28 Australia,AUS,East Asia & Pacific,High income: OECD,36 Austria,AUT,Europe & Central Asia,High income: OECD,40 Azerbaijan,AZE,Europe & Central Asia,Upper middle income,31 Burundi,BDI,Sub-Saharan Africa,Low income,108 Belgium,BEL,Europe & Central Asia,High income: OECD,56 Benin,BEN,Sub-Saharan Africa,Low income,204 Burkina Faso,BFA,Sub-Saharan Africa,Low income,854 Bangladesh,BGD,South Asia,Low income,50 Bulgaria,BGR,Europe & Central Asia,Upper middle income,100 Bahrain,BHR,Middle East & North Africa,High income: nonOECD,48 Bahamas,BHS,Latin America & Caribbean,High income: nonOECD,44 Bosnia and Herzegovina,BIH,Europe & Central Asia,Upper middle income,70 Belarus,BLR,Europe & Central Asia,Upper middle income,112 Belize,BLZ,Latin America & Caribbean,Upper middle income,84 Bermuda,BMU,North America,High income: nonOECD,60 Bolivia (Plurinational State of),BOL,Latin America & Caribbean,Lower middle income,68 Brazil,BRA,Latin America & Caribbean,Upper middle income,76 Barbados,BRB,Latin America & Caribbean,High income: nonOECD,52 Brunei Darussalam,BRN,East Asia & Pacific,High income: nonOECD,96 Bhutan,BTN,South Asia,Lower middle income,64 Botswana,BWA,Sub-Saharan Africa,Upper middle income,72 Central African Republic,CAF,Sub-Saharan Africa,Low income,140 Canada,CAN,North America,High income: OECD,124 Switzerland,CHE,Europe & Central Asia,High income: OECD,756 Chile,CHL,Latin America & Caribbean,High income: OECD,152 China,CHN,East Asia & Pacific,Upper middle income,156 Cote d'Ivoire,CIV,Sub-Saharan Africa,Lower middle income,384 Cameroon,CMR,Sub-Saharan Africa,Lower middle income,120 Democratic Republic of the Congo,COD,Sub-Saharan Africa,Low income,180 Congo,COG,Sub-Saharan Africa,Lower middle income,178 Colombia,COL,Latin America & Caribbean,Upper middle income,170 Comoros,COM,Sub-Saharan Africa,Low income,174 Cabo Verde,CPV,Sub-Saharan Africa,Lower middle income,132 Costa Rica,CRI,Latin America & Caribbean,Upper middle income,188 Cuba,CUB,Latin America & Caribbean,Upper middle income,192 Cayman Islands,CYM,Latin America & Caribbean,High income: nonOECD,136 Cyprus,CYP,Europe & Central Asia,High income: nonOECD,196 Czech Republic,CZE,Europe & Central Asia,High income: OECD,203 Germany,DEU,Europe & Central Asia,High income: OECD,276 Djibouti,DJI,Middle East & North Africa,Lower middle income,262 Dominica,DMA,Latin America & Caribbean,Upper middle income,212 Denmark,DNK,Europe & Central Asia,High income: OECD,208 Dominican Republic,DOM,Latin America & Caribbean,Upper middle income,214 Algeria,DZA,Middle East & North Africa,Upper middle income,12 Ecuador,ECU,Latin America & Caribbean,Upper middle income,218 Egypt,EGY,Middle East & North Africa,Lower middle income,818 Eritrea,ERI,Sub-Saharan Africa,Low income,232 Spain,ESP,Europe & Central Asia,High income: OECD,724 Estonia,EST,Europe & Central Asia,High income: OECD,233 Ethiopia,ETH,Sub-Saharan Africa,Low income,231 Finland,FIN,Europe & Central Asia,High income: OECD,246 Fiji,FJI,East Asia & Pacific,Upper middle income,242 France,FRA,Europe & Central Asia,High income: OECD,250 Faroe Islands,FRO,Europe & Central Asia,High income: nonOECD,234 Micronesia (Federated States of),FSM,East Asia & Pacific,Lower middle income,583 Gabon,GAB,Sub-Saharan Africa,Upper middle income,266 United Kingdom,GBR,Europe & Central Asia,High income: OECD,826 Georgia,GEO,Europe & Central Asia,Lower middle income,268 Ghana,GHA,Sub-Saharan Africa,Lower middle income,288 Guinea,GIN,Sub-Saharan Africa,Low income,324 Gambia,GMB,Sub-Saharan Africa,Low income,270 Guinea-Bissau,GNB,Sub-Saharan Africa,Low income,624 Equatorial Guinea,GNQ,Sub-Saharan Africa,High income: nonOECD,226 Greece,GRC,Europe & Central Asia,High income: OECD,300 Grenada,GRD,Latin America & Caribbean,Upper middle income,308 Greenland,GRL,Europe & Central Asia,High income: nonOECD,304 Guatemala,GTM,Latin America & Caribbean,Lower middle income,320 Guam,GUM,East Asia & Pacific,High income: nonOECD,316 Guyana,GUY,Latin America & Caribbean,Lower middle income,328 Hong Kong,HKG,East Asia & Pacific,High income: nonOECD,344 Honduras,HND,Latin America & Caribbean,Lower middle income,340 Croatia,HRV,Europe & Central Asia,High income: nonOECD,191 Haiti,HTI,Latin America & Caribbean,Low income,332 Hungary,HUN,Europe & Central Asia,Upper middle income,348 Indonesia,IDN,East Asia & Pacific,Lower middle income,360 India,IND,South Asia,Lower middle income,356 Ireland,IRL,Europe & Central Asia,High income: OECD,372 Iran (Islamic Republic of),IRN,Middle East & North Africa,Upper middle income,364 Iraq,IRQ,Middle East & North Africa,Upper middle income,368 Iceland,ISL,Europe & Central Asia,High income: OECD,352 Israel,ISR,Middle East & North Africa,High income: OECD,376 Italy,ITA,Europe & Central Asia,High income: OECD,380 Jamaica,JAM,Latin America & Caribbean,Upper middle income,388 Jordan,JOR,Middle East & North Africa,Upper middle income,400 Japan,JPN,East Asia & Pacific,High income: OECD,392 Kazakhstan,KAZ,Europe & Central Asia,Upper middle income,398 Kenya,KEN,Sub-Saharan Africa,Low income,404 Kyrgyzstan,KGZ,Europe & Central Asia,Low income,417 Cambodia,KHM,East Asia & Pacific,Low income,116 Kiribati,KIR,East Asia & Pacific,Lower middle income,296 Saint Kitts and Nevis,KNA,Latin America & Caribbean,High income: nonOECD,659 Republic of Korea,KOR,East Asia & Pacific,High income: OECD,410 Kosovo,KSV,Europe & Central Asia,Lower middle income,410 Kuwait,KWT,Middle East & North Africa,High income: nonOECD,414 Lao People's Democratic Republic,LAO,East Asia & Pacific,Lower middle income,418 Lebanon,LBN,Middle East & North Africa,Upper middle income,422 Liberia,LBR,Sub-Saharan Africa,Low income,430 Libya,LBY,Middle East & North Africa,Upper middle income,434 Saint Lucia,LCA,Latin America & Caribbean,Upper middle income,662 Liechtenstein,LIE,Europe & Central Asia,High income: nonOECD,438 Sri Lanka,LKA,South Asia,Lower middle income,144 Lesotho,LSO,Sub-Saharan Africa,Lower middle income,426 Lithuania,LTU,Europe & Central Asia,High income: nonOECD,440 Luxembourg,LUX,Europe & Central Asia,High income: OECD,442 Latvia,LVA,Europe & Central Asia,High income: nonOECD,428 Macau,MAC,East Asia & Pacific,High income: nonOECD,446 Morocco,MAR,Middle East & North Africa,Lower middle income,504 Monaco,MCO,Europe & Central Asia,High income: nonOECD,492 Republic of Moldova,MDA,Europe & Central Asia,Lower middle income,498 Madagascar,MDG,Sub-Saharan Africa,Low income,450 Maldives,MDV,South Asia,Upper middle income,462 Mexico,MEX,Latin America & Caribbean,Upper middle income,484 Marshall Islands,MHL,East Asia & Pacific,Upper middle income,584 The former Yugoslav Republic of Macedonia,MKD,Europe & Central Asia,Upper middle income,807 Mali,MLI,Sub-Saharan Africa,Low income,466 Malta,MLT,Middle East & North Africa,High income: nonOECD,470 Myanmar,MMR,East Asia & Pacific,Low income,104 Montenegro,MNE,Europe & Central Asia,Upper middle income,499 Mongolia,MNG,East Asia & Pacific,Lower middle income,496 Northern Mariana Islands,MNP,East Asia & Pacific,High income: nonOECD,580 Mozambique,MOZ,Sub-Saharan Africa,Low income,508 Mauritania,MRT,Sub-Saharan Africa,Lower middle income,478 Mauritius,MUS,Sub-Saharan Africa,Upper middle income,480 Malawi,MWI,Sub-Saharan Africa,Low income,454 Malaysia,MYS,East Asia & Pacific,Upper middle income,458 Namibia,NAM,Sub-Saharan Africa,Upper middle income,516 New Caledonia,NCL,East Asia & Pacific,High income: OECD,540 Niger,NER,Sub-Saharan Africa,Low income,562 Nigeria,NGA,Sub-Saharan Africa,Lower middle income,566 Nicaragua,NIC,Latin America & Caribbean,Lower middle income,558 Netherlands,NLD,Europe & Central Asia,High income: OECD,528 Norway,NOR,Europe & Central Asia,High income: OECD,578 Nepal,NPL,South Asia,Low income,524 New Zealand,NZL,East Asia & Pacific,High income: OECD,554 Oman,OMN,Middle East & North Africa,High income: nonOECD,512 Pakistan,PAK,South Asia,Lower middle income,586 Panama,PAN,Latin America & Caribbean,Upper middle income,591 Peru,PER,Latin America & Caribbean,Upper middle income,604 Philippines,PHL,East Asia & Pacific,Lower middle income,608 Palau,PLW,East Asia & Pacific,Upper middle income,585 Papua New Guinea,PNG,East Asia & Pacific,Lower middle income,598 Poland,POL,Europe & Central Asia,High income: OECD,616 Puerto Rico,PRI,Latin America & Caribbean,High income: nonOECD,630 Democratic People's Republic of Korea,PRK,East Asia & Pacific,Low income,408 Portugal,PRT,Europe & Central Asia,High income: OECD,620 Paraguay,PRY,Latin America & Caribbean,Lower middle income,600 Occupied Palestinian Territory,PSE,Middle East & North Africa,Lower middle income,275 Pacific island small states,PSS,,,275 French Polynesia,PYF,East Asia & Pacific,High income: nonOECD,258 Qatar,QAT,Middle East & North Africa,High income: nonOECD,634 Romania,ROU,Europe & Central Asia,Upper middle income,642 Russian Federation,RUS,Europe & Central Asia,High income: nonOECD,643 Rwanda,RWA,Sub-Saharan Africa,Low income,646 Saudi Arabia,SAU,Middle East & North Africa,High income: nonOECD,682 Sudan,SDN,Sub-Saharan Africa,Lower middle income,729 Senegal,SEN,Sub-Saharan Africa,Lower middle income,686 Singapore,SGP,East Asia & Pacific,High income: nonOECD,702 Solomon Islands,SLB,East Asia & Pacific,Lower middle income,90 Sierra Leone,SLE,Sub-Saharan Africa,Low income,694 El Salvador,SLV,Latin America & Caribbean,Lower middle income,222 San Marino,SMR,Europe & Central Asia,High income: nonOECD,674 Somalia,SOM,Sub-Saharan Africa,Low income,706 Serbia,SRB,Europe & Central Asia,Upper middle income,688 Sao Tome and Principe,STP,Sub-Saharan Africa,Lower middle income,678 Suriname,SUR,Latin America & Caribbean,Upper middle income,740 Slovakia,SVK,Europe & Central Asia,High income: OECD,703 Slovenia,SVN,Europe & Central Asia,High income: OECD,705 Sweden,SWE,Europe & Central Asia,High income: OECD,752 Swaziland,SWZ,Sub-Saharan Africa,Lower middle income,748 Seychelles,SYC,Sub-Saharan Africa,Upper middle income,690 Syrian Arab Republic,SYR,Middle East & North Africa,Lower middle income,760 Turks and Caicos Islands,TCA,Latin America & Caribbean,High income: nonOECD,796 Chad,TCD,Sub-Saharan Africa,Low income,148 Togo,TGO,Sub-Saharan Africa,Low income,768 Thailand,THA,East Asia & Pacific,Upper middle income,764 Tajikistan,TJK,Europe & Central Asia,Low income,762 Turkmenistan,TKM,Europe & Central Asia,Upper middle income,795 Timor-Leste,TLS,East Asia & Pacific,Lower middle income,626 Tonga,TON,East Asia & Pacific,Upper middle income,776 Trinidad and Tobago,TTO,Latin America & Caribbean,High income: nonOECD,780 Tunisia,TUN,Middle East & North Africa,Upper middle income,788 Turkey,TUR,Europe & Central Asia,Upper middle income,792 Tuvalu,TUV,East Asia & Pacific,Upper middle income,798 United Republic of Tanzania,TZA,Sub-Saharan Africa,Low income,834 Uganda,UGA,Sub-Saharan Africa,Low income,800 Ukraine,UKR,Europe & Central Asia,Lower middle income,804 Uruguay,URY,Latin America & Caribbean,High income: nonOECD,858 United States of America,USA,North America,High income: OECD,840 Uzbekistan,UZB,Europe & Central Asia,Lower middle income,860 Saint Vincent and the Grenadines,VCT,Latin America & Caribbean,Upper middle income,670 Venezuela (Bolivarian Republic of),VEN,Latin America & Caribbean,Upper middle income,862 United States Virgin Islands,VIR,Latin America & Caribbean,High income: nonOECD,850 Viet Nam,VNM,East Asia & Pacific,Lower middle income,704 Vanuatu,VUT,East Asia & Pacific,Lower middle income,548 Samoa,WSM,East Asia & Pacific,Lower middle income,882 Yemen,YEM,Middle East & North Africa,Lower middle income,887 South Africa,ZAF,Sub-Saharan Africa,Upper middle income,710 Zambia,ZMB,Sub-Saharan Africa,Lower middle income,894 Zimbabwe,ZWE,Sub-Saharan Africa,Low income,716 Czechoslovakia,CZEF,Europe & Central Asia,High income: OECD,203 Ethiopia PDR,ETHF,Sub-Saharan Africa,Low income,231 Sudan (former),SDNF,Sub-Saharan Africa,Lower middle income,729 Western Sahara,WSAF,Sub-Saharan Africa,Lower middle income,876 Yugoslav SFR,YUGF,Europe & Central Asia,High income: OECD,887 Belgium-Luxembourg,BELF,Europe & Central Asia,High income: OECD,56 Serbia and Montenegro,SRBF,Europe & Central Asia,Upper middle income,688 Falkland Islands (Malvinas),FALF,Latin America & Caribbean,High income: nonOECD,231 South Sudan,SSUF,Sub-Saharan Africa,Lower middle income,728 USSR,USSR,Europe & Central Asia,High income: nonOECD,999 \ No newline at end of file diff --git a/src/ac/ed/lurg/InternationalMarket.java b/src/ac/ed/lurg/InternationalMarket.java index de86cf01f466c747989be0dd55f5a3db03c6d693..8e5a01a5c9c1455c5db2103dfd3a1003e7aebdb9 100644 --- a/src/ac/ed/lurg/InternationalMarket.java +++ b/src/ac/ed/lurg/InternationalMarket.java @@ -7,7 +7,7 @@ import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; -import ac.ed.lurg.country.CountryAgent; +import ac.ed.lurg.country.AbstractCountryAgent; import ac.ed.lurg.country.GlobalPrice; import ac.ed.lurg.country.StockReader; import ac.ed.lurg.landuse.CropUsageData; @@ -47,10 +47,10 @@ public class InternationalMarket { return initialStockLevels; } - void determineInternationalTrade(Collection<CountryAgent> countryAgents, double gen2EcDDemand, Timestep timestep) { + void determineInternationalTrade(Collection<AbstractCountryAgent> countryAgents, double gen2EcDDemand, Timestep timestep) { CropToDoubleMap totalImportCommodities = new CropToDoubleMap(); CropToDoubleMap totalExportCommodities = new CropToDoubleMap(); - for (CountryAgent ca : countryAgents) { + for (AbstractCountryAgent ca : countryAgents) { // Get values for world input costs Map<CropType, CropUsageData> cropUsage = ca.getCropUsageData(); diff --git a/src/ac/ed/lurg/ModelConfig.java b/src/ac/ed/lurg/ModelConfig.java index b40d449ba23cd12713225faee3f5ea247c4db75c..550878a61ad93dc6dc5b590546f63ed30d2967f6 100644 --- a/src/ac/ed/lurg/ModelConfig.java +++ b/src/ac/ed/lurg/ModelConfig.java @@ -272,7 +272,8 @@ public class ModelConfig { public static final double TOTAL_MAX_CEREAL_CHANGE = getDoubleProperty("TOTAL_MAX_CEREAL_CHANGE", 0.5); public static final double ANNUAL_MAX_CEREAL_CHANGE = getDoubleProperty("ANNUAL_MAX_CEREAL_CHANGE", 0.0); public static final boolean LIMIT_CEREAL_FRACTION = getBooleanProperty("LIMIT_CEREAL_FRACTION", true); - + public static final int CEREAL_CHANGE_START_STEP = getIntProperty("CEREAL_CHANGE_START_STEP", 0); + public static final double PASTURE_HARVEST_FRACTION = getDoubleProperty("PASTURE_HARVEST_FRACTION", 0.5); public static final double ANIMAL_FEED_FROM_OTHER_SOURCES_RATE = getDoubleProperty("ANIMAL_FEED_FROM_OTHER_SOURCES_RATE", 0.127); // animal nutrition coming from sources other crops modelled public static final double MEAT_EFFICIENCY = getDoubleProperty("MEAT_EFFICIENCY", 1.0); // 'meat' is includes feed conversion ratio already, this is tech. change or similar @@ -369,4 +370,7 @@ public class ModelConfig { public static final int FORCE_PROTECTED_AREAS_END_YEAR = getIntProperty("FORCE_PROTECTED_AREAS_END_YEAR", 2050); public static final double US_EXPORT_TARRIFF = getDoubleProperty("US_EXPORT_TARRIFF",1.0); + + public static final boolean USE_CRAFTY_COUNTRIES = getBooleanProperty("USE_CRAFTY_COUNTRIES", false); + public static final String CRAFTY_PRODUCTION_DIR = getProperty("CRAFTY_PRODUCTION_DIR", OUTPUT_DIR + File.separator + "crafty"); } diff --git a/src/ac/ed/lurg/ModelMain.java b/src/ac/ed/lurg/ModelMain.java index 0e3570057bf695d4b9e1bb9565f8515257617bf4..ceb4c58d404b4c858bd4f8b4ac5801797273572e 100644 --- a/src/ac/ed/lurg/ModelMain.java +++ b/src/ac/ed/lurg/ModelMain.java @@ -8,25 +8,19 @@ import java.io.FileWriter; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; -import java.nio.file.FileSystems; -import java.nio.file.Files; -import java.nio.file.StandardCopyOption; import java.util.Collection; -import java.util.HashSet; -import java.util.List; import java.util.Map; import java.util.Map.Entry; +import ac.ed.lurg.country.AbstractCountryAgent; import ac.ed.lurg.country.AnimalRateManager; import ac.ed.lurg.country.CompositeCountry; import ac.ed.lurg.country.CompositeCountryManager; -import ac.ed.lurg.country.CountryAgent; +import ac.ed.lurg.country.CountryAgentManager; import ac.ed.lurg.country.CountryBoundaryRaster; import ac.ed.lurg.country.CountryBoundaryReader; import ac.ed.lurg.country.CountryPrice; import ac.ed.lurg.country.GlobalPrice; -import ac.ed.lurg.country.SubsidyRateManager; -import ac.ed.lurg.country.TradeManager; import ac.ed.lurg.demand.AbstractDemandManager; import ac.ed.lurg.demand.BaseConsumpManager; import ac.ed.lurg.demand.DemandManagerFromFile; @@ -63,12 +57,10 @@ import ac.sac.raster.RasterSet; public class ModelMain { - private Collection<CountryAgent> countryAgents; + private CountryAgentManager countryAgents; private CountryBoundaryRaster countryBoundaryRaster; private AbstractDemandManager demandManager; - private SubsidyRateManager subsidyRateManager; private AnimalRateManager animalRateManager; - private TradeManager tradeManager; private CompositeCountryManager compositeCountryManager; LPJYieldResponseMapReader lpjYieldReader; private RasterHeaderDetails desiredProjection; @@ -91,7 +83,6 @@ public class ModelMain { BaseConsumpManager baseConsumpManager = new BaseConsumpManager(); compositeCountryManager = new CompositeCountryManager(baseConsumpManager); - subsidyRateManager = new SubsidyRateManager(compositeCountryManager); lpjYieldReader = new LPJYieldResponseMapReader(desiredProjection); animalRateManager = new AnimalRateManager(compositeCountryManager); @@ -102,14 +93,13 @@ public class ModelMain { if (ModelConfig.SHOCKS_POSSIBLE) ModelConfig.readInShocksFile(); - tradeManager = new TradeManager(compositeCountryManager); currentIrrigationData = getFixedIrrigationData(); countryBoundaryRaster = getCountryBoundaryRaster(); clusterIdRaster = ModelConfig.GENERATE_NEW_YIELD_CLUSTERS ? new RasterSet<IntegerRasterItem>(desiredProjection) : getClusterRaster(); - countryAgents = createCountryAgents(compositeCountryManager.getAll()); globalLandUseRaster = new RasterSet<LandUseItem>(desiredProjection); internationalMarket = new InternationalMarket(); + createCountryAgents(compositeCountryManager.getAll()); } /* run the model */ @@ -124,9 +114,9 @@ public class ModelMain { } } } - + private void doTimestep(Timestep timestep) { - LogWriter.println(timestep.toString()); + LogWriter.println("Timestep: " + timestep.toString()); YieldRaster yieldSurfaces = getYieldSurfaces(timestep); // this will wait for the marker file from LPJ if configured to do so getUpdateIrrigationData(timestep, yieldSurfaces); // updating currentIrrigationData @@ -134,48 +124,10 @@ public class ModelMain { double previousGen2EcDDemand = (timestep.isInitialTimestep() || ModelConfig.IS_CALIBRATION_RUN ) ? 0: demandManager.getSecondGenBioenergyDemand(timestep.getPreviousTimestep()); double gen2EcDDemand = demandManager.getSecondGenBioenergyDemand(ModelConfig.IS_CALIBRATION_RUN ? new Timestep(1) : timestep); double gen2Increase = (gen2EcDDemand>previousGen2EcDDemand) ? gen2EcDDemand - previousGen2EcDDemand : 0.0; - - for (CountryAgent ca : countryAgents) { - - LogWriter.println("Country " + ca.getCountry()); - Collection<RasterKey> countryKeys = countryBoundaryRaster.getKeysFor(ca.getCountry()); - YieldRaster countryYieldSurfaces = yieldSurfaces.createSubsetForKeys(countryKeys); - RasterSet<IrrigationItem> irrigData = currentIrrigationData.createSubsetForKeys(countryKeys); - - // do the optimization - try { - ca.determineProduction(timestep, countryYieldSurfaces, irrigData, internationalMarket.getWorldPrices(), gen2Increase); - } catch (Exception e) { - LogWriter.printlnError("Exception processing " + ca.getCountry() + " will continue with other countries"); - LogWriter.print(e); - continue; - } - - // some hacky code for debug purposes that keeps each gams gdx file - // for one country - if (ModelConfig.GAMS_COUNTRY_TO_SAVE != null && ca.getCountry().getName().equals(ModelConfig.GAMS_COUNTRY_TO_SAVE)) { - try { - Files.copy( - FileSystems.getDefault().getPath(ModelConfig.TEMP_DIR + File.separator + "_gams_java_gdb1.gdx"), - FileSystems.getDefault().getPath(ModelConfig.TEMP_DIR + File.separator + ModelConfig.GAMS_COUNTRY_TO_SAVE + timestep.getYear() + ".gdx"), - StandardCopyOption.REPLACE_EXISTING); - } catch (IOException e) { - LogWriter.print(e); - } - } - - // update global rasters - globalLandUseRaster.putAll(ca.getLandUses()); - - // if first timestep and calibration get the clustering info, which - // doesn't change through time - if (ModelConfig.GENERATE_NEW_YIELD_CLUSTERS && timestep.isInitialTimestep()) - clusterIdRaster.putAll(ca.getYieldClusters()); - - if (ca.getCountry().getName().equals("United Kingdom")) writeUKLandCoverFile(timestep, ca); - } - internationalMarket.determineInternationalTrade(countryAgents, gen2EcDDemand, timestep); + countryAgents.processTimestepForAll(timestep, yieldSurfaces, currentIrrigationData, gen2Increase); + + internationalMarket.determineInternationalTrade(countryAgents.getAll(), gen2EcDDemand, timestep); // output results outputTimestepResults(timestep, globalLandUseRaster); @@ -249,7 +201,7 @@ public class ModelMain { stockChange = priceQuantity.getStockChange(); } - for (CountryAgent ca : countryAgents) { + for (AbstractCountryAgent ca : countryAgents.getAll()) { Map<CropType, CropUsageData> allCropUsage = ca.getCropUsageData(); CropUsageData cropUsage = allCropUsage.get(crop); if (cropUsage != null) { @@ -298,7 +250,7 @@ public class ModelMain { for (CommodityType comm : CommodityType.getAllItems()) { double demandAmount = 0; - for (CountryAgent country : countryAgents) { + for (AbstractCountryAgent country : countryAgents.getAll()) { Double d = country.getCurrentProjectedDemand().get(comm); if (d != null) { demandAmount += d.doubleValue(); @@ -325,7 +277,7 @@ public class ModelMain { BufferedWriter outputFile = getFileWriter(timestep, ModelConfig.DOMESTIC_OUTPUT_FILE, sbHeadings.toString()); for (CropType crop : CropType.getAllItems()) { - for (CountryAgent country : countryAgents) { + for (AbstractCountryAgent country : countryAgents.getAll()) { Map<CropType, CropUsageData> cropUsageAllCrops = country.getCropUsageData(); CropUsageData cropUsage = cropUsageAllCrops.get(crop); @@ -367,44 +319,13 @@ public class ModelMain { } } - private void writeUKLandCoverFile(Timestep timestep, CountryAgent ca){ - - try { - StringBuffer sbHeadings = new StringBuffer("Year,Cropland,Pasture,ManForest,UnmanForest,Natural,AbPasture,EnergyCrop,FertCrop,IrrigCrop"); - BufferedWriter outputFile = getFileWriter(timestep, ModelConfig.UK_LAND_COVER_OUTPUT_FILE, sbHeadings.toString()); - - StringBuffer sbData = new StringBuffer(); - Collection<RasterKey> countryKeys = countryBoundaryRaster.getKeysFor(ca.getCountry()); - RasterSet<LandUseItem> ukLandUse = globalLandUseRaster.createSubsetForKeys(countryKeys); - - sbData.append(String.format("%d,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f", timestep.getYear(), - LandUseItem.getTotalLandCover(ukLandUse.values(), LandCoverType.CROPLAND), - LandUseItem.getTotalLandCover(ukLandUse.values(), LandCoverType.PASTURE), - LandUseItem.getTotalLandCover(ukLandUse.values(), LandCoverType.MANAGED_FOREST), - LandUseItem.getTotalLandCover(ukLandUse.values(), LandCoverType.UNMANAGED_FOREST), - LandUseItem.getTotalLandCover(ukLandUse.values(), LandCoverType.OTHER_NATURAL), - LandUseItem.getAbandonedPasture(ukLandUse.values())) - ); - - sbData.append(String.format(",%.1f", LandUseItem.getTotalCropArea(ukLandUse.values(), CropType.ENERGY_CROPS))); - sbData.append(String.format(",%.1f", LandUseItem.getFertiliserTotal(ukLandUse.values(), CropType.getCropsLessPasture()) / 1000)); - sbData.append(String.format(",%.1f", LandUseItem.getIrrigationTotal(ukLandUse.values(), CropType.getCropsLessPasture()))); - - outputFile.write(sbData.toString()); - outputFile.newLine(); - outputFile.close(); - } catch (IOException e) { - LogWriter.print(e); - } - } - private void writeCountryDemandFile(Timestep timestep){ try { StringBuffer sbHeadings = new StringBuffer("Year, Country, Commodity, Demand"); BufferedWriter outputFile = getFileWriter(timestep, ModelConfig.COUNTRY_DEMAND_FILE, sbHeadings.toString()); - for (CountryAgent country : countryAgents) { + for (AbstractCountryAgent country : countryAgents.getAll()) { for (CommodityType commodity : CommodityType.getAllItems()) { double demand = country.getCurrentProjectedDemand().get(commodity); @@ -429,10 +350,13 @@ public class ModelMain { StringBuffer sbHeadings = new StringBuffer("Year,Country,FAOItem,Heads(M)"); BufferedWriter outputFile = getFileWriter(timestep, ModelConfig.ANIMAL_NUMBERS_OUTPUT_FILE, sbHeadings.toString()); - for (CountryAgent country : countryAgents) { + for (AbstractCountryAgent country : countryAgents.getAll()) { Map<CropType, CropUsageData> cropUsageAllCrops = country.getCropUsageData(); for (CropType crop : CropType.getMeatTypes()) { - double prod = cropUsageAllCrops.get(crop).getProduction(); + CropUsageData cropusage = cropUsageAllCrops.get(crop); + if (cropusage == null) + continue; + double prod = cropusage.getProduction(); Map<String, Double> animalRates = animalRateManager.getAnimalRates(country.getCountry(), crop); for (Entry<String, Double> entry : animalRates.entrySet()) { @@ -492,7 +416,7 @@ public class ModelMain { serializeLandUse(landUseRaster); if (timestep.isInitialTimestep() && ModelConfig.GENERATE_NEW_YIELD_CLUSTERS) - outputClusters(clusterIdRaster); + outputClusters(clusterIdRaster); // Output LandUses to tabular file, for analysis (perhaps) LogWriter.println("Outputing land uses Year: " + timestep.getYear()); @@ -552,43 +476,14 @@ public class ModelMain { return countryBoundaries; } - public Collection<CountryAgent> createCountryAgents(Collection<CompositeCountry> countryGrouping) { - Collection<CountryAgent> countryAgents = new HashSet<CountryAgent>(); + public void createCountryAgents(Collection<CompositeCountry> countryGrouping) { + countryAgents = new CountryAgentManager(compositeCountryManager, demandManager, countryBoundaryRaster, internationalMarket, clusterIdRaster, globalLandUseRaster); Map<CompositeCountry, Map<CropType, CropUsageData>> cropUsageDataMap = new CropUsageReader(compositeCountryManager).getCommodityData(); RasterSet<LandUseItem> initLU = getInitialLandUse(); for (CompositeCountry cc : countryGrouping) { - - // DEBUG code - if (ModelConfig.DEBUG_LIMIT_COUNTRIES) { - if (!(cc.getName().equals(ModelConfig.DEBUG_COUNTRY_NAME))) - continue; - } - - List<RasterKey> keys = countryBoundaryRaster.getKeysFor(cc); - Map<CropType, CropUsageData> countryCommodityData = cropUsageDataMap.get(cc); - Map<CropType, Double> countryTradeBarriers = tradeManager.getTradeBarriers(cc); - - if (countryCommodityData == null) { - LogWriter.printlnError("No commodities data for " + cc + ", so skipping"); - } else { - RasterSet<LandUseItem> initCountryLandUse = initLU.createSubsetForKeys(keys); - RasterSet<IntegerRasterItem> yieldClusters = ModelConfig.GENERATE_NEW_YIELD_CLUSTERS ? null : clusterIdRaster.createSubsetForKeys(keys); - - if (initCountryLandUse.size() == 0) { - LogWriter.printlnError("No initial land use for " + cc + ", so skipping"); - continue; - } - - Map<CropType, Double> subsidyRates = subsidyRateManager.getSubsidyRates(cc); - - CountryAgent ca = new CountryAgent(demandManager, cc, initCountryLandUse, countryCommodityData, countryTradeBarriers, yieldClusters, subsidyRates); - countryAgents.add(ca); - LogWriter.println("Creating country agent for: " + cc); - } + countryAgents.addForCountry(cc, cropUsageDataMap, initLU); } - - return countryAgents; } private RasterSet<LandUseItem> getInitialLandUse() { diff --git a/src/ac/ed/lurg/country/AbstractCountryAgent.java b/src/ac/ed/lurg/country/AbstractCountryAgent.java new file mode 100644 index 0000000000000000000000000000000000000000..c6480482084527222d5967d56418deb6d522962d --- /dev/null +++ b/src/ac/ed/lurg/country/AbstractCountryAgent.java @@ -0,0 +1,131 @@ +package ac.ed.lurg.country; + +import java.util.HashMap; +import java.util.Map; + +import ac.ed.lurg.ModelConfig; +import ac.ed.lurg.Timestep; +import ac.ed.lurg.demand.AbstractDemandManager; +import ac.ed.lurg.landuse.CropUsageData; +import ac.ed.lurg.types.CommodityType; +import ac.ed.lurg.types.CropType; +import ac.ed.lurg.utils.LogWriter; + +public abstract class AbstractCountryAgent { + + protected AbstractDemandManager demandManager; + protected CompositeCountry country; + protected Map<CropType, Double> tradeBarriers; + protected Map<CommodityType, Double> currentProjectedDemand; + private Map<CropType, CountryPrice> currentCountryPrices; + + public AbstractCountryAgent(AbstractDemandManager demandManager,CompositeCountry country, Map<CropType, Double> tradeBarriers) { + + this.demandManager = demandManager; + this.country = country; + this.tradeBarriers = tradeBarriers; + } + + public CompositeCountry getCountry() { + return country; + } + + protected Map<CropType, CountryPrice> calculateCountryPrices(Map<CropType, GlobalPrice> worldPrices, Timestep timestep){ + Map<CropType, CountryPrice> countryPrices = new HashMap <CropType, CountryPrice>(); + + for (CropType c : CropType.getImportedTypes()) { + GlobalPrice worldPrice = worldPrices.get(c); + CountryPrice prices = new CountryPrice(worldPrice.getCountryImportPrice(tradeBarriers.get(c), timestep), worldPrice.getExportPrice()); + countryPrices.put(c, prices); + } + + currentCountryPrices = countryPrices; + return currentCountryPrices; + } + + protected Map<CommodityType, Double> calculateDemand(Timestep timestep) { + currentProjectedDemand = demandManager.getDemand(country, timestep.getYear()); + return currentProjectedDemand; + } + + public Map<CommodityType, Double> getCurrentProjectedDemand() { + return currentProjectedDemand; + } + + public Map<CropType, CountryPrice> getCurrentCountryPrices() { + return currentCountryPrices; + } + + protected Map<CropType, Double> getMinCerealFraction(Timestep timestep) { + Map<CropType, Double> minCerealFraction = new HashMap<CropType, Double>(); + + int yearsOfChange = ModelConfig.IS_CALIBRATION_RUN ? 0 : (timestep.getTimestep() - ModelConfig.CEREAL_CHANGE_START_STEP) * ModelConfig.TIMESTEP_SIZE; + + for (Map.Entry<CropType, Double> entry : demandManager.getBaseCerealFraction(country).entrySet()) { + minCerealFraction.put(entry.getKey(), entry.getValue() * Math.max(ModelConfig.TOTAL_MAX_CEREAL_CHANGE, (1- ModelConfig.ANNUAL_MAX_CEREAL_CHANGE * yearsOfChange))); + } + return minCerealFraction; + } + + protected void updateNetImportsFromProdAndDemand(Map<CommodityType, Double> demands, Map<CropType, Double> minCerealFracts, Map<CropType, CropUsageData> cropUsages) { + + for (CommodityType commodity : CommodityType.getAllItems()) { + if (commodity != CommodityType.CEREALS && commodity.getCropTypes().size() != 1) + throw new RuntimeException("Not cereal and not 1 to 1 mapping for commodity to crop: " + commodity); // skips cereals which is a special case and handled separately below + + double demand = demands.get(commodity); + if (commodity == CommodityType.CEREALS) { + Map<CropType, Double> netImportsFromMinDemands = new HashMap<CropType, Double>(); + double totalProd = 0, totalmportFromMD = 0, totalExcessProd = 0; + + for (CropType crop : commodity.getCropTypes()) { + CropUsageData cropUsage = cropUsages.get(crop); + double prod = cropUsage.getProduction() *(1-crop.getSeedAndWasteRate()) - cropUsage.getMonogastricFeed() - cropUsage.getRuminantFeed(); + totalProd += prod; + double minFract = minCerealFracts.containsKey(crop) ? minCerealFracts.get(crop) : 0.0; + double netImportsFromMinDemand = minFract * demand - prod; + LogWriter.println("netImportsFromMinDemand " + crop + " to " + netImportsFromMinDemand); + netImportsFromMinDemands.put(crop, netImportsFromMinDemand); + + if (netImportsFromMinDemand > 0) + totalmportFromMD += netImportsFromMinDemand; + else + totalExcessProd += netImportsFromMinDemand; + } + double additionalNetImportsRequired = demand - totalProd - totalmportFromMD; + LogWriter.println("additionalNetImportsRequired is " + additionalNetImportsRequired); + + for (CropType crop : commodity.getCropTypes()) { + double netImportsMD = netImportsFromMinDemands.get(crop); + double netImports=0; + if (additionalNetImportsRequired > 0) { // overall need to import more + if (minCerealFracts.containsKey(crop)) + netImports = netImportsMD + minCerealFracts.get(crop) * additionalNetImportsRequired; // divide required additional imports by minCerealFracts + } + else { // overall need to export more + if (netImportsMD > 0) + netImports = netImportsMD; // still import what we need for minimum fraction + else if(netImportsMD < 0) + netImports = netImportsMD / totalExcessProd * additionalNetImportsRequired; // divide exports by production in excess of minimum demand + } + + CropUsageData cropUsage = cropUsages.get(crop); + LogWriter.println("Updating cereal net imports " + crop + " to " + netImports); + cropUsage.updateNetImports(netImports); + } + } + else { + // simple 1-1 commodity to cereal mappings + for (CropType crop : commodity.getCropTypes()) { + CropUsageData cropUsage = cropUsages.get(crop); + double prod = cropUsage.getProduction() *(1-crop.getSeedAndWasteRate()) - cropUsage.getMonogastricFeed() - cropUsage.getRuminantFeed(); + double netImports = demand - prod; + LogWriter.println("Updating net imports " + crop + " to " + netImports); + cropUsage.updateNetImports(netImports); + } + } + } + } + + abstract public Map<CropType, CropUsageData> getCropUsageData(); +} diff --git a/src/ac/ed/lurg/country/CompositeCountry.java b/src/ac/ed/lurg/country/CompositeCountry.java index 16286ba51ad3f4e9d58ebf23ff697512ded54c7a..ac0f42a31e05dbd38de77fce41070a8bd27fdd5e 100644 --- a/src/ac/ed/lurg/country/CompositeCountry.java +++ b/src/ac/ed/lurg/country/CompositeCountry.java @@ -24,5 +24,29 @@ public class CompositeCountry { public String toString() { return name; } - + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + CompositeCountry other = (CompositeCountry) obj; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } } diff --git a/src/ac/ed/lurg/country/CountryAgent.java b/src/ac/ed/lurg/country/CountryAgent.java index f2c40d678e2a79b24d6c30c7c2065c9cafd22839..7d044667f3f513668b785aa3b7c65502081e642b 100644 --- a/src/ac/ed/lurg/country/CountryAgent.java +++ b/src/ac/ed/lurg/country/CountryAgent.java @@ -1,5 +1,10 @@ package ac.ed.lurg.country; +import java.io.File; +import java.io.IOException; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; @@ -30,36 +35,27 @@ import ac.sac.raster.IntegerRasterItem; import ac.sac.raster.RasterKey; import ac.sac.raster.RasterSet; -public class CountryAgent { - - private AbstractDemandManager demandManager; - private CompositeCountry country; +public class CountryAgent extends AbstractCountryAgent { private GamsRasterOutput previousGamsRasterOutput; private Timestep currentTimestep; - private Map<CommodityType, Double> currentProjectedDemand; - private Map<CropType, CountryPrice> currentCountryPrices; - private Map<CropType, Double> tradeBarriers; private RasterSet<IntegerRasterItem> yieldClusters; private double animalFeedFromOtherSources; private Map<CropType, Double> subsidyRates; + private boolean saveGamsGdxFiles; public CountryAgent(AbstractDemandManager demandManager,CompositeCountry country, RasterSet<LandUseItem> cropAreaRaster, Map<CropType, CropUsageData> cropUsageData, Map<CropType, Double> tradeBarriers, RasterSet<IntegerRasterItem> yieldClusters, Map<CropType, Double> subsidyRates) { - this.demandManager = demandManager; - this.country = country; - this.tradeBarriers = tradeBarriers; + super(demandManager, country, tradeBarriers); this.yieldClusters = yieldClusters; this.subsidyRates = subsidyRates; GamsRasterOutput initialData = new GamsRasterOutput(cropAreaRaster, cropUsageData); previousGamsRasterOutput = initialData; - } - - public CompositeCountry getCountry() { - return country; + + saveGamsGdxFiles = (ModelConfig.GAMS_COUNTRY_TO_SAVE != null && country.getName().equals(ModelConfig.GAMS_COUNTRY_TO_SAVE)); } public RasterSet<IntegerRasterItem> getYieldClusters() { @@ -110,15 +106,15 @@ public class CountryAgent { currentTimestep = timestep; // get projected demand - currentProjectedDemand = demandManager.getDemand(country, timestep.getYear()); + Map<CommodityType, Double> projectedDemand = calculateDemand(timestep); if (currentTimestep.isInitialTimestep()) { - double totalAnimalProductDemand = currentProjectedDemand.get(CommodityType.MONOGASTRICS) + currentProjectedDemand.get(CommodityType.RUMINANTS); + double totalAnimalProductDemand = projectedDemand.get(CommodityType.MONOGASTRICS) + projectedDemand.get(CommodityType.RUMINANTS); animalFeedFromOtherSources = totalAnimalProductDemand * ModelConfig.ANIMAL_FEED_FROM_OTHER_SOURCES_RATE; } - currentCountryPrices = calculateCountryPrices(worldPrices); + calculateCountryPrices(worldPrices, currentTimestep); - if (currentProjectedDemand.size() == 0) { + if (projectedDemand.size() == 0) { LogWriter.printlnError("No demand for country " + country + " so skipping it"); } else if (countryYieldSurfaces.size() == 0 ) { @@ -142,79 +138,25 @@ public class CountryAgent { updateNetImportsFromProdAndDemand(countryInput.getProjectedDemand(), countryInput.getMinCerealFraction(), result.getCropUsageData()); } + if (saveGamsGdxFiles) saveGDXFile(); + previousGamsRasterOutput = result; return result; } throw new RuntimeException("Skipping optimisation of country " + country); } - - private void updateNetImportsFromProdAndDemand(Map<CommodityType, Double> demands, Map<CropType, Double> minCerealFracts, Map<CropType, CropUsageData> cropUsages) { - - for (CommodityType commodity : CommodityType.getAllItems()) { - if (commodity != CommodityType.CEREALS && commodity.getCropTypes().size() != 1) - throw new RuntimeException("Not cereal and not 1 to 1 mapping for commodity to crop: " + commodity); // skips cereals which is a special case and handled separately below - - double demand = demands.get(commodity); - if (commodity == CommodityType.CEREALS) { - Map<CropType, Double> netImportsFromMinDemands = new HashMap<CropType, Double>(); - double totalProd = 0, totalmportFromMD = 0, totalExcessProd = 0; - - for (CropType crop : commodity.getCropTypes()) { - CropUsageData cropUsage = cropUsages.get(crop); - double prod = cropUsage.getProduction() *(1-crop.getSeedAndWasteRate()) - cropUsage.getMonogastricFeed() - cropUsage.getRuminantFeed(); - totalProd += prod; - double minFract = minCerealFracts.containsKey(crop) ? minCerealFracts.get(crop) : 0.0; - double netImportsFromMinDemand = minFract * demand - prod; - LogWriter.println("netImportsFromMinDemand " + crop + " to " + netImportsFromMinDemand); - netImportsFromMinDemands.put(crop, netImportsFromMinDemand); - - if (netImportsFromMinDemand > 0) - totalmportFromMD += netImportsFromMinDemand; - else - totalExcessProd += netImportsFromMinDemand; - } - double additionalNetImportsRequired = demand - totalProd - totalmportFromMD; - LogWriter.println("additionalNetImportsRequired is " + additionalNetImportsRequired); - - for (CropType crop : commodity.getCropTypes()) { - double netImportsMD = netImportsFromMinDemands.get(crop); - double netImports=0; - if (additionalNetImportsRequired > 0) { // overall need to import more - if (minCerealFracts.containsKey(crop)) - netImports = netImportsMD + minCerealFracts.get(crop) * additionalNetImportsRequired; // divide required additional imports by minCerealFracts - } - else { // overall need to export more - if (netImportsMD > 0) - netImports = netImportsMD; // still import what we need for minimum fraction - else if(netImportsMD < 0) - netImports = netImportsMD / totalExcessProd * additionalNetImportsRequired; // divide exports by production in excess of minimum demand - } - - CropUsageData cropUsage = cropUsages.get(crop); - LogWriter.println("Updating cereal net imports " + crop + " to " + netImports); - cropUsage.updateNetImports(netImports); - } - } - else { - // simple 1-1 commodity to cereal mappings - for (CropType crop : commodity.getCropTypes()) { - CropUsageData cropUsage = cropUsages.get(crop); - double prod = cropUsage.getProduction() *(1-crop.getSeedAndWasteRate()) - cropUsage.getMonogastricFeed() - cropUsage.getRuminantFeed(); - double netImports = demand - prod; - LogWriter.println("Updating net imports " + crop + " to " + netImports); - cropUsage.updateNetImports(netImports); - } - } - } - } - - public Map<CommodityType, Double> getCurrentProjectedDemand() { - return currentProjectedDemand; - } - public Map<CropType, CountryPrice> getCurrentCountryPrices() { - return currentCountryPrices; + private void saveGDXFile() { + // some hacky code for debug purposes that keeps each gams gdx file + try { + Files.copy( + FileSystems.getDefault().getPath(ModelConfig.TEMP_DIR + File.separator + "_gams_java_gdb1.gdx"), + FileSystems.getDefault().getPath(ModelConfig.TEMP_DIR + File.separator + ModelConfig.GAMS_COUNTRY_TO_SAVE + currentTimestep.getYear() + ".gdx"), + StandardCopyOption.REPLACE_EXISTING); + } catch (IOException e) { + LogWriter.print(e); + } } private GamsRasterInput getGamsRasterInput(RasterSet<IrrigationItem> irrigData, YieldRaster countryYieldSurfaces, double gen2EcIncrease) { @@ -269,36 +211,13 @@ public class CountryAgent { Map<CropType, Double> minCerealFract = getMinCerealFraction(currentTimestep); - GamsCountryInput countryLevelInputs = new GamsCountryInput(country, currentProjectedDemand, currentCountryPrices, importConstraints, + GamsCountryInput countryLevelInputs = new GamsCountryInput(country, getCurrentProjectedDemand(), getCurrentCountryPrices(), importConstraints, previousGamsRasterOutput.getCropUsageData(), minCerealFract, animalFeedFromOtherSources, subsidyRates); GamsRasterInput input = new GamsRasterInput(currentTimestep, countryYieldSurfaces, previousGamsRasterOutput.getLandUses(), irrigData, countryLevelInputs); return input; } - private Map<CropType, Double> getMinCerealFraction(Timestep timestep) { - Map<CropType, Double> minCerealFraction = new HashMap<CropType, Double>(); - - int yearsOfChange = ModelConfig.IS_CALIBRATION_RUN ? 0 : (timestep.getTimestep() - ModelConfig.TECHNOLOGY_CHANGE_START_STEP) * ModelConfig.TIMESTEP_SIZE; - - for (Map.Entry<CropType, Double> entry : demandManager.getBaseCerealFraction(country).entrySet()) { - minCerealFraction.put(entry.getKey(), entry.getValue() * Math.max(ModelConfig.TOTAL_MAX_CEREAL_CHANGE, (1- ModelConfig.ANNUAL_MAX_CEREAL_CHANGE * yearsOfChange))); - } - return minCerealFraction; - } - - private Map<CropType, CountryPrice> calculateCountryPrices(Map<CropType, GlobalPrice> worldPrices){ - Map<CropType, CountryPrice> countryPrices = new HashMap <CropType, CountryPrice>(); - - for (CropType c : CropType.getImportedTypes()) { - GlobalPrice worldPrice = worldPrices.get(c); - CountryPrice prices = new CountryPrice(worldPrice.getCountryImportPrice(tradeBarriers.get(c), currentTimestep), worldPrice.getExportPrice()); - countryPrices.put(c, prices); - } - - return countryPrices; - } - public RasterSet<LandUseItem> getLandUses() { return previousGamsRasterOutput.getLandUses(); } @@ -306,4 +225,4 @@ public class CountryAgent { public Map<CropType, CropUsageData> getCropUsageData() { return previousGamsRasterOutput.getCropUsageData(); } -} +} \ No newline at end of file diff --git a/src/ac/ed/lurg/country/CountryAgentManager.java b/src/ac/ed/lurg/country/CountryAgentManager.java new file mode 100644 index 0000000000000000000000000000000000000000..3c59266712c3800427b72d0b7068906098dee646 --- /dev/null +++ b/src/ac/ed/lurg/country/CountryAgentManager.java @@ -0,0 +1,128 @@ +package ac.ed.lurg.country; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import ac.ed.lurg.InternationalMarket; +import ac.ed.lurg.ModelConfig; +import ac.ed.lurg.Timestep; +import ac.ed.lurg.country.crafty.CraftyCountryAgent; +import ac.ed.lurg.country.crafty.CraftyProdManager; +import ac.ed.lurg.demand.AbstractDemandManager; +import ac.ed.lurg.landuse.CropUsageData; +import ac.ed.lurg.landuse.IrrigationItem; +import ac.ed.lurg.landuse.IrrigationRasterSet; +import ac.ed.lurg.landuse.LandUseItem; +import ac.ed.lurg.types.CropType; +import ac.ed.lurg.utils.LogWriter; +import ac.ed.lurg.yield.YieldRaster; +import ac.sac.raster.IntegerRasterItem; +import ac.sac.raster.RasterKey; +import ac.sac.raster.RasterSet; + +public class CountryAgentManager { + private AbstractDemandManager demandManager; + private TradeManager tradeBarrierManager; + private SubsidyRateManager subsidyRateManager; + private InternationalMarket internationalMarket; + private CountryBoundaryRaster countryBoundaryRaster; + private RasterSet<IntegerRasterItem> clusterIdRaster; + private RasterSet<LandUseItem> globalLandUseRaster; + + private Collection<AbstractCountryAgent> countryAgents = new ArrayList<AbstractCountryAgent>(); + private Collection<CountryAgent> gamsCountryAgents = new ArrayList<CountryAgent>(); + private Collection<CraftyCountryAgent> craftyCountryAgents = new ArrayList<CraftyCountryAgent>(); + private CraftyProdManager craftyManager; + + public CountryAgentManager (CompositeCountryManager compositeCountryManager, AbstractDemandManager demandManager, + CountryBoundaryRaster countryBoundaryRaster, InternationalMarket internationalMarket, + RasterSet<IntegerRasterItem> clusterIdRaster, RasterSet<LandUseItem> globalLandUseRaster) { + this.demandManager = demandManager; + this.countryBoundaryRaster = countryBoundaryRaster; + this.clusterIdRaster = clusterIdRaster; + this.internationalMarket = internationalMarket; + this.globalLandUseRaster = globalLandUseRaster; + tradeBarrierManager = new TradeManager(compositeCountryManager); + subsidyRateManager = new SubsidyRateManager(compositeCountryManager); + craftyManager = new CraftyProdManager(); + } + + public void addForCountry(CompositeCountry cc, Map<CompositeCountry, Map<CropType, CropUsageData>> cropUsageDataMap, RasterSet<LandUseItem> initLU) { + if (ModelConfig.DEBUG_LIMIT_COUNTRIES) { // DEBUG code + if (!(cc.getName().equals(ModelConfig.DEBUG_COUNTRY_NAME))) + return; + } + + Map<CropType, Double> tradeBarriers = tradeBarrierManager.getTradeBarriers(cc); + + if (ModelConfig.USE_CRAFTY_COUNTRIES && craftyManager.getCraftyCountries().contains(cc)) { + LogWriter.println("Creating CRAFTY agent for: " + cc); + CraftyCountryAgent cca = new CraftyCountryAgent(demandManager, cc, tradeBarriers); + craftyCountryAgents.add(cca); + countryAgents.add(cca); + } + else { //GAMS + LogWriter.println("Creating GAMS agent for: " + cc); + List<RasterKey> keys = countryBoundaryRaster.getKeysFor(cc); + Map<CropType, CropUsageData> countryCommodityData = cropUsageDataMap.get(cc); + + if (countryCommodityData == null) { + LogWriter.printlnError("No commodities data for " + cc + ", so skipping"); + } else { + RasterSet<LandUseItem> initCountryLandUse = initLU.createSubsetForKeys(keys); + RasterSet<IntegerRasterItem> yieldClusters = ModelConfig.GENERATE_NEW_YIELD_CLUSTERS ? null : clusterIdRaster.createSubsetForKeys(keys); + + if (initCountryLandUse.size() == 0) { + LogWriter.printlnError("No initial land use for " + cc + ", so skipping"); + } + else { + Map<CropType, Double> subsidyRates = subsidyRateManager.getSubsidyRates(cc); + + CountryAgent ca = new CountryAgent(demandManager, cc, initCountryLandUse, countryCommodityData, tradeBarriers, yieldClusters, subsidyRates); + gamsCountryAgents.add(ca); + countryAgents.add(ca); + } + } + } + } + + public Collection<AbstractCountryAgent> getAll() { + return countryAgents; + } + + public void processTimestepForAll(Timestep timestep, YieldRaster yieldSurfaces, IrrigationRasterSet currentIrrigationData, double gen2Increase) { + + for (CountryAgent ca : gamsCountryAgents) { + LogWriter.println("Country " + ca.getCountry()); + doGamsAgentTimestep(timestep, ca, yieldSurfaces, currentIrrigationData, gen2Increase); + } + + if (craftyCountryAgents.size() > 0) { + craftyManager.updateWithCraftyData(craftyCountryAgents, timestep, internationalMarket.getWorldPrices()); // this will wait for the marker file from CRAFTY + } + } + + private void doGamsAgentTimestep(Timestep timestep, CountryAgent ca, YieldRaster yieldSurfaces, IrrigationRasterSet currentIrrigationData, double gen2Increase) { + Collection<RasterKey> countryKeys = countryBoundaryRaster.getKeysFor(ca.getCountry()); + YieldRaster countryYieldSurfaces = yieldSurfaces.createSubsetForKeys(countryKeys); + RasterSet<IrrigationItem> irrigData = currentIrrigationData.createSubsetForKeys(countryKeys); + + // do the optimization + try { + ca.determineProduction(timestep, countryYieldSurfaces, irrigData, internationalMarket.getWorldPrices(), gen2Increase); + + // update global rasters + globalLandUseRaster.putAll(ca.getLandUses()); + + // if first timestep and calibration get the clustering info, which doesn't change through time + if (ModelConfig.GENERATE_NEW_YIELD_CLUSTERS && timestep.isInitialTimestep()) + clusterIdRaster.putAll(ca.getYieldClusters()); + + } catch (Exception e) { + LogWriter.printlnError("Exception processing " + ca.getCountry() + " will continue with other countries"); + LogWriter.print(e); + } + } +} \ No newline at end of file diff --git a/src/ac/ed/lurg/country/crafty/CraftyCountryAgent.java b/src/ac/ed/lurg/country/crafty/CraftyCountryAgent.java new file mode 100644 index 0000000000000000000000000000000000000000..24a99c2b750abc2debc6bb110c3d3d3032cc53c9 --- /dev/null +++ b/src/ac/ed/lurg/country/crafty/CraftyCountryAgent.java @@ -0,0 +1,43 @@ +package ac.ed.lurg.country.crafty; + +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +import ac.ed.lurg.Timestep; +import ac.ed.lurg.country.AbstractCountryAgent; +import ac.ed.lurg.country.CompositeCountry; +import ac.ed.lurg.country.GlobalPrice; +import ac.ed.lurg.demand.AbstractDemandManager; +import ac.ed.lurg.landuse.CropUsageData; +import ac.ed.lurg.types.CropType; + +/** + * Country agent that is interface over data transferred to and from CRAFTY. + * Need to configure country mapping to that there is + * */ +public class CraftyCountryAgent extends AbstractCountryAgent { + + private Map<CropType, CropUsageData> cropUsageData; + + public CraftyCountryAgent(AbstractDemandManager demandManager,CompositeCountry country, Map<CropType, Double> tradeBarriers) { + super(demandManager, country, tradeBarriers); + } + + public Map<CropType, CropUsageData> getCropUsageData() { + return cropUsageData; + } + + public void updateProduction(Timestep timestep, Map<CropType, Double> cropProduction, Map<CropType, GlobalPrice> worldPrices) { + calculateDemand(timestep); + calculateCountryPrices(worldPrices, timestep); + + cropUsageData = new HashMap<CropType, CropUsageData>(); + for (Entry<CropType, Double> entry : cropProduction.entrySet()) { + CropUsageData cropusage = new CropUsageData(entry.getValue()); + cropUsageData.put(entry.getKey(), cropusage); + } + + updateNetImportsFromProdAndDemand(currentProjectedDemand, getMinCerealFraction(timestep), cropUsageData); + } +} \ No newline at end of file diff --git a/src/ac/ed/lurg/country/crafty/CraftyProdManager.java b/src/ac/ed/lurg/country/crafty/CraftyProdManager.java new file mode 100644 index 0000000000000000000000000000000000000000..af3cf49422d19e3da306e3b5f2f37a0cff707fe8 --- /dev/null +++ b/src/ac/ed/lurg/country/crafty/CraftyProdManager.java @@ -0,0 +1,76 @@ +package ac.ed.lurg.country.crafty; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import ac.ed.lurg.ModelConfig; +import ac.ed.lurg.Timestep; +import ac.ed.lurg.country.CompositeCountry; +import ac.ed.lurg.country.GlobalPrice; +import ac.ed.lurg.types.CropType; +import ac.ed.lurg.utils.LogWriter; +import ac.ed.lurg.utils.StringTabularReader; +import ac.ed.lurg.utils.WatchForFile; + +public class CraftyProdManager { + + private Collection<CompositeCountry> craftyCountries; + + public synchronized Collection<CompositeCountry> getCraftyCountries() { + if (craftyCountries == null) { + craftyCountries = new ArrayList<CompositeCountry>(); + StringTabularReader tabularReader = new StringTabularReader(",", new String[]{"Country"}); + List<Map<String, String>> rows = tabularReader.read(ModelConfig.CRAFTY_PRODUCTION_DIR + File.separator + "craftyCountries.csv"); + for (Map<String, String> row : rows) { + craftyCountries.add(new CompositeCountry(row.get("Country"), "craftycountry")); + } + } + return craftyCountries; + } + + public void updateWithCraftyData(Collection<CraftyCountryAgent> craftyCountryAgents, Timestep timestep, Map<CropType, GlobalPrice> worldPrices) { + String rootDir = ModelConfig.CRAFTY_PRODUCTION_DIR + File.separator + timestep.getYear(); + long startTime = System.currentTimeMillis(); + + WatchForFile fileWatcher = new WatchForFile(new File(rootDir + File.separator + "done")); + boolean foundFile = fileWatcher.await(ModelConfig.LPJG_MONITOR_TIMEOUT_SEC); + if (!foundFile) { + LogWriter.printlnError("Not able to find marker file. May have timed out."); + throw new RuntimeException("Not able to find marker file. May have timed out."); + } + LogWriter.println("Found marker file in " + (System.currentTimeMillis() - startTime) + " ms"); + + StringTabularReader tabularReader = new StringTabularReader(",", new String[]{"Country","Crop","Production"}); + tabularReader.read(rootDir + File.separator + "production.csv"); + + + for (CraftyCountryAgent cca : craftyCountryAgents) { + Map<CropType, Double> cropProduction = new HashMap<CropType, Double>(); + + Map<String, String> queryMap = new HashMap<String, String>(); + queryMap.put("Country", cca.getCountry().getName()); + + try { + List<Map<String, String>> rows = tabularReader.query(queryMap); + for (Map<String, String> row : rows) { + String cropS = row.get("Crop"); + CropType crop = CropType.getForGamsName(cropS); + String prodS = row.get("Production"); + Double prod = Double.valueOf(prodS); + cropProduction.put(crop, prod); + } + if (cropProduction.size() < CropType.getImportedTypes().size()) { // Don't need setaside or pasture, which aren't imported either + LogWriter.printlnError("Not all crops present in Crafty production for country: " + cca.getCountry() + " only " + cropProduction.size()); + } + cca.updateProduction(timestep, cropProduction, worldPrices); + } + catch (Exception e) { + LogWriter.println("Problem getting Crafty data for: " + cca.getCountry()); + } + } + } +} \ No newline at end of file diff --git a/src/ac/ed/lurg/landuse/CropUsageData.java b/src/ac/ed/lurg/landuse/CropUsageData.java index a7640fccbe16f27ca45010c59ff146f7e86cc7f8..aaa9019951914c05c7fe3f5848a38db7648eb9c0 100644 --- a/src/ac/ed/lurg/landuse/CropUsageData.java +++ b/src/ac/ed/lurg/landuse/CropUsageData.java @@ -10,8 +10,11 @@ public class CropUsageData { private double prodCost; private double area; + public CropUsageData(double prod) { + this.prod = prod; + } + public CropUsageData(double ruminantFeed, double monogastricFeed, double netImports, double netImportCost, double prod, double prodCost, double area) { - super(); this.ruminantFeed = ruminantFeed; this.monogastricFeed = monogastricFeed; this.netImports = netImports;