Skip to content
Snippets Groups Projects
CountryAgent.java 9.63 KiB
Newer Older
package ac.ed.lurg.country;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import ac.ed.lurg.ModelConfig;
import ac.ed.lurg.Timestep;
Peter Alexander's avatar
Peter Alexander committed
import ac.ed.lurg.country.gams.GamsCountryInput;
import ac.ed.lurg.country.gams.GamsRasterInput;
import ac.ed.lurg.country.gams.GamsRasterOptimiser;
import ac.ed.lurg.country.gams.GamsRasterOutput;
import ac.ed.lurg.demand.AbstractDemandManager;
import ac.ed.lurg.landuse.CropUsageData;
import ac.ed.lurg.landuse.IrrigationItem;
import ac.ed.lurg.landuse.LandUseItem;
import ac.ed.lurg.types.CommodityType;
Peter Alexander's avatar
Peter Alexander committed
import ac.ed.lurg.types.CropType;
Peter Alexander's avatar
Peter Alexander committed
import ac.ed.lurg.types.LandCoverType;
import ac.ed.lurg.types.YieldType;
import ac.ed.lurg.utils.LogWriter;
import ac.ed.lurg.utils.cluster.Cluster;
import ac.ed.lurg.utils.cluster.KMeans;
import ac.ed.lurg.yield.YieldClusterPoint;
import ac.ed.lurg.yield.YieldRaster;
import ac.ed.lurg.yield.YieldResponsesItem;
import ac.sac.raster.IntegerRasterItem;
import ac.sac.raster.RasterKey;
Peter Alexander's avatar
Peter Alexander committed
import ac.sac.raster.RasterSet;
Peter Alexander's avatar
Peter Alexander committed
public class CountryAgent {
	private AbstractDemandManager demandManager;
	private CompositeCountry country;
Peter Alexander's avatar
Peter Alexander committed
	
	private GamsRasterOutput previousGamsRasterOutput;
	private Timestep currentTimestep;
Peter Alexander's avatar
Peter Alexander committed
	private Map<CommodityType, Double> currentProjectedDemand;
	private Map<CropType, CountryPrice> currentCountryPrices;
	private Map<CropType, Double> tradeBarriers;
	private RasterSet<IntegerRasterItem> yieldClusters;
	public CountryAgent(AbstractDemandManager demandManager,CompositeCountry country, RasterSet<LandUseItem> cropAreaRaster,
			Map<CropType, CropUsageData> cropUsageData, Map<CropType, Double> tradeBarriers, RasterSet<IntegerRasterItem> yieldClusters) {
Peter Alexander's avatar
Peter Alexander committed
		
Peter Alexander's avatar
Peter Alexander committed
		this.demandManager = demandManager;
		this.country = country;
		this.tradeBarriers = tradeBarriers;
		this.yieldClusters = yieldClusters;
Peter Alexander's avatar
Peter Alexander committed
		
		GamsRasterOutput initialData = new GamsRasterOutput(cropAreaRaster, cropUsageData);
		previousGamsRasterOutput = initialData;
R0slyn's avatar
R0slyn committed
	
Peter Alexander's avatar
Peter Alexander committed
	}
	public CompositeCountry getCountry() {
		return country;
	}
	
	public RasterSet<IntegerRasterItem> getYieldClusters() {
		return yieldClusters;
	}
	
	private RasterSet<IntegerRasterItem> calcYieldClusters(RasterSet<IrrigationItem> irrigData, YieldRaster countryYieldSurfaces) {
		
		LogWriter.println("calcYieldClusters: for " + ModelConfig.NUM_YIELD_CLUSTERS + " clusters");	
		
		// create collection of ClusteringPoints from countryYieldSurfaces, these have the RasterKey and data for yield (or access to them)
		Collection<YieldClusterPoint> clusteringPoints = new HashSet<YieldClusterPoint>();
		for (Entry<RasterKey, YieldResponsesItem> entry : countryYieldSurfaces.entrySet()) {
			YieldResponsesItem yieldresp = entry.getValue();
			if (yieldresp != null) {
				RasterKey key = entry.getKey();
				IrrigationItem irrigItem = irrigData.get(key);
				clusteringPoints.add(new YieldClusterPoint(key, yieldresp, irrigItem));
			}
		}
				
		// do the clustering
		KMeans<String, YieldClusterPoint> kmeans = new KMeans<String, YieldClusterPoint>(clusteringPoints, ModelConfig.NUM_YIELD_CLUSTERS);
		kmeans.calculateClusters(100, 0.1);
		kmeans.printClusters();
		// reformat output
		List<Cluster<String, YieldClusterPoint>> yieldClusters = kmeans.getClusters();
		RasterSet<IntegerRasterItem> mapping = new RasterSet<IntegerRasterItem>(countryYieldSurfaces.getHeaderDetails());
		
		int id = 1;
		for (Cluster<String, YieldClusterPoint> c : yieldClusters) {
			for (YieldClusterPoint p : c.getPoints())
				mapping.put(p.getRasterKey(), new IntegerRasterItem(id));
			
			if (c.getPoints().size()>0)
				id++;
		}

		return mapping;
	}
	
Peter Alexander's avatar
Peter Alexander committed
	public GamsRasterOutput determineProduction(Timestep timestep, YieldRaster countryYieldSurfaces, RasterSet<IrrigationItem> irrigData, 
			Map<CropType, GlobalPrice> worldPrices, double globalGen2EcIncrease) {
Peter Alexander's avatar
Peter Alexander committed
		currentTimestep = timestep;
Peter Alexander's avatar
Peter Alexander committed
		
		// get projected demand
Peter Alexander's avatar
Peter Alexander committed
		currentProjectedDemand = demandManager.getDemand(country, timestep.getYear());
		currentCountryPrices = calculateCountryPrices(worldPrices, timestep.getYear());
		if(ModelConfig.LIMIT_MAIZE_YIELD_SAMERICA & country.getRegion().equals("Latin America & Caribbean")){
			 for (Entry<RasterKey, YieldResponsesItem> entry : countryYieldSurfaces.entrySet()) {
				 YieldResponsesItem yresp = entry.getValue();
				 if (yresp != null){
					 for (YieldType yt : YieldType.values()) {
						 double prevYield = yresp.getYield(yt, CropType.MAIZE);
						 yresp.setYield(yt,CropType.MAIZE, prevYield*(1-ModelConfig.LIMIT_YIELD_BY));
					 }
				 }
			 }
		}
		
Peter Alexander's avatar
Peter Alexander committed
		if (currentProjectedDemand.size() == 0) {
Peter Alexander's avatar
Peter Alexander committed
			LogWriter.printlnError("No demand for country " + country + " so skipping it");
		}
		else if (countryYieldSurfaces.size() == 0 ) {
			LogWriter.printlnError("No yield values for " + country + " so skipping it");
		}
		else if (ModelConfig.DEBUG_JUST_DEMAND_OUTPUT) { // if this debug flag is set we don't do the optimisation
		}
		else {			
			if (yieldClusters==null)
				yieldClusters = calcYieldClusters(irrigData, countryYieldSurfaces);  // this should only be on the first timestep
Peter Alexander's avatar
Peter Alexander committed
			// optimize areas and intensity 
			GamsRasterInput input = getGamsRasterInput(irrigData, countryYieldSurfaces, globalGen2EcIncrease);
			GamsRasterOptimiser opti = new GamsRasterOptimiser(input, yieldClusters);
			LogWriter.println("Running " + country.getName() + ", currentTimestep " + currentTimestep);
Peter Alexander's avatar
Peter Alexander committed
			
			GamsRasterOutput result = opti.run();
R0slyn's avatar
R0slyn committed
			
			previousGamsRasterOutput = result;
R0slyn's avatar
R0slyn committed
			
Peter Alexander's avatar
Peter Alexander committed
			return result;
		}
Peter Alexander's avatar
Peter Alexander committed
		
Peter Alexander's avatar
Peter Alexander committed
		return null;
Peter Alexander's avatar
Peter Alexander committed
	}
Peter Alexander's avatar
Peter Alexander committed
	
	public Map<CommodityType, Double> getCurrentProjectedDemand() {
		return currentProjectedDemand;
	}
R0slyn's avatar
R0slyn committed
	
	public Map<CropType, CountryPrice> getCurrentCountryPrices() {
		return currentCountryPrices;
	}
Peter Alexander's avatar
Peter Alexander committed

	private GamsRasterInput getGamsRasterInput(RasterSet<IrrigationItem> irrigData, YieldRaster countryYieldSurfaces,
			double gen2EcIncrease) {
Peter Alexander's avatar
Peter Alexander committed
		double allowedImportChange;
		if (currentTimestep.isInitialTimestep()) { // initialisation time-step
Peter Alexander's avatar
Peter Alexander committed
			allowedImportChange = 0.0;
		} else { // normal (not the initial) time-step
			allowedImportChange = ModelConfig.MAX_IMPORT_CHANGE; // when running
																	// is
																	// calibration
																	// model
																	// calibrate
																	// (ModelConfig.IS_CALIBRATION_RUN==true)
																	// MAX_IMPORT_CHANGE
																	// is
																	// already
																	// 0.
Peter Alexander's avatar
Peter Alexander committed
		}
		Map<CropType, ImportExportConstraint> importConstraints = new HashMap<CropType, ImportExportConstraint>();
		for (Map.Entry<CropType, CropUsageData> entry : previousGamsRasterOutput.getCropUsageData().entrySet()) {
			CropUsageData cropUsage = entry.getValue();
			CropType crop = entry.getKey();
			double baseNetImport = cropUsage.getNetImports();
			double changeUp = 0.0;
			double changeDown = 0.0;

			if (allowedImportChange > 0.0) {
				double maxOfProdOrSupply = cropUsage.getProduction() + Math.max(baseNetImport, 0);
				changeDown = changeUp = allowedImportChange * maxOfProdOrSupply;
			if (CropType.ENERGY_CROPS.equals(crop)) {
				double croplandArea = LandUseItem.getTotalLandCover(previousGamsRasterOutput.getLandUses().values(),
						LandCoverType.CROPLAND);
				double ecMaxExport = gen2EcIncrease * croplandArea / 1500.0 * 2;
				if (ModelConfig.IS_CALIBRATION_RUN) {
					baseNetImport = 0.0;
					ecMaxExport = 0.0;
				}
				changeDown = ecMaxExport;
			}
			if (crop.isCereal()) {
				demand = ((demand = currentProjectedDemand.get(CommodityType.CEREALS)) != null) ? demand : 0.0;
				if(allowedImportChange > 0.0 & baseNetImport - changeDown > demand){
				changeDown = baseNetImport-demand;
				}
			}
			if (!CropType.ENERGY_CROPS.equals(crop) & !crop.isCereal() & !CropType.PASTURE.equals(crop)) {
				demand = ((demand = currentProjectedDemand.get(CommodityType.getForFaoName(crop.getFaoName()))) != null) ? demand : 0.0;
				if(allowedImportChange > 0.0 & baseNetImport - changeDown > demand){
					changeDown = baseNetImport-demand;
			importConstraints.put(crop,
					new ImportExportConstraint(baseNetImport - changeDown, baseNetImport + changeUp));
Peter Alexander's avatar
Peter Alexander committed
		}
		Map<CropType, Double> minCerealFract = getMinCerealFraction(currentTimestep);
		
		GamsCountryInput countryLevelInputs = new GamsCountryInput(country, currentProjectedDemand, currentCountryPrices, importConstraints, 
				previousGamsRasterOutput.getCropUsageData(), minCerealFract);	
		GamsRasterInput input = new GamsRasterInput(currentTimestep, countryYieldSurfaces, previousGamsRasterOutput.getLandUses(), irrigData, countryLevelInputs);
Peter Alexander's avatar
Peter Alexander committed

Peter Alexander's avatar
Peter Alexander committed
	}
	
	private Map<CropType, Double> getMinCerealFraction(Timestep timestep) {
		Map<CropType, Double> minCerealFraction = new HashMap<CropType, Double>();
		
		int yearsOfChange = (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;
	}
	Map<CropType, CountryPrice> calculateCountryPrices(Map<CropType, GlobalPrice> worldPrices, int year){
		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),year), worldPrice.getExportPrice());
Peter Alexander's avatar
Peter Alexander committed
		return countryPrices;
R0slyn's avatar
R0slyn committed
	
	 public GamsRasterOutput getGamsOutput(){
		 
		 return previousGamsRasterOutput;
	 }