Skip to content
Snippets Groups Projects
GamsLandUseOptimiser.java 9.1 KiB
Newer Older
Peter Alexander's avatar
Peter Alexander committed
package ac.ed.lurg.country.gams;

import java.io.File;
Peter Alexander's avatar
Peter Alexander committed
import java.util.HashMap;
Peter Alexander's avatar
Peter Alexander committed
import java.util.Map;
Peter Alexander's avatar
Peter Alexander committed
import java.util.Map.Entry;
import java.util.Vector;
Peter Alexander's avatar
Peter Alexander committed

import ac.ed.lurg.ModelConfig;
Peter Alexander's avatar
Peter Alexander committed
import ac.ed.lurg.landuse.CropAreas;
import ac.ed.lurg.landuse.Intensities;
import ac.ed.lurg.landuse.Intensity;
Peter Alexander's avatar
Peter Alexander committed
import ac.ed.lurg.types.CropType;
Peter Alexander's avatar
Peter Alexander committed
import ac.ed.lurg.utils.LogWriter;
Peter Alexander's avatar
Peter Alexander committed
import ac.ed.lurg.yield.YieldResponses;
Peter Alexander's avatar
Peter Alexander committed

import com.gams.api.GAMSDatabase;
import com.gams.api.GAMSGlobals;
import com.gams.api.GAMSJob;
import com.gams.api.GAMSOptions;
import com.gams.api.GAMSParameter;
import com.gams.api.GAMSVariable;
import com.gams.api.GAMSVariableRecord;
import com.gams.api.GAMSWorkspace;
import com.gams.api.GAMSWorkspaceInfo;

public class GamsLandUseOptimiser {
Peter Alexander's avatar
Peter Alexander committed

Peter Alexander's avatar
Peter Alexander committed
	private GamsInput inputData;
Peter Alexander's avatar
Peter Alexander committed

Peter Alexander's avatar
Peter Alexander committed
	public GamsLandUseOptimiser(GamsInput inputData) {
Peter Alexander's avatar
Peter Alexander committed
		this.inputData = inputData;
	}
Peter Alexander's avatar
Peter Alexander committed

Peter Alexander's avatar
Peter Alexander committed
	public GamsOutput run() {
Peter Alexander's avatar
Peter Alexander committed

		File workingDirectory = new File(ModelConfig.TEMP_DIR, "GamsTest");
		workingDirectory.mkdir();

		GAMSWorkspaceInfo  wsInfo  = new GAMSWorkspaceInfo();
		wsInfo.setWorkingDirectory(workingDirectory.getAbsolutePath());
Peter Alexander's avatar
Peter Alexander committed
		//	wsInfo.setDebugLevel(DebugLevel.VERBOSE);

Peter Alexander's avatar
Peter Alexander committed
		GAMSWorkspace ws = new GAMSWorkspace(wsInfo);
Peter Alexander's avatar
Peter Alexander committed
		GAMSDatabase inDB = ws.addDatabase();

		setupInDB(inDB);

		GAMSJob gamsJob = ws.addJobFromFile(ModelConfig.GAMS_MODEL);
		GAMSOptions opt = ws.addOptions();
		opt.defines("gdxincname", inDB.getName());

		long startTime = System.currentTimeMillis();
		gamsJob.run(opt, inDB);
		LogWriter.println("Took " + (System.currentTimeMillis() - startTime) + " ms to run");

		return handleResults(gamsJob.OutDB());
	}

	private void setupInDB(GAMSDatabase inDB) {
Peter Alexander's avatar
Peter Alexander committed
		LogWriter.println("\nPrevious areas");
Peter Alexander's avatar
Peter Alexander committed
		GAMSParameter param = inDB.addParameter("previous_area", 2, "the previous area for each land use");
Peter Alexander's avatar
Peter Alexander committed
		addLocationMapParm(param, inputData.getPreviousCropArea());
Peter Alexander's avatar
Peter Alexander committed

		LogWriter.println("\nDemand");
Peter Alexander's avatar
Peter Alexander committed
		param = inDB.addParameter("demand", 1, "demand for crop");
Peter Alexander's avatar
Peter Alexander committed
		addItemMapParm(param, inputData.getCountryInput().getProjectedDemand());
Peter Alexander's avatar
Peter Alexander committed

Peter Alexander's avatar
Peter Alexander committed
		LogWriter.println("\nYieldNone");
Peter Alexander's avatar
Peter Alexander committed
		GAMSParameter yNoneP = inDB.addParameter("yieldNone", 2);
		GAMSParameter y_fert = inDB.addParameter("yieldFertOnly", 2);
		GAMSParameter y_irrig = inDB.addParameter("yieldIrrigOnly", 2);
		GAMSParameter y_both = inDB.addParameter("yieldBoth", 2);
		GAMSParameter fert_p = inDB.addParameter("fertParam", 2);
		GAMSParameter irrig_p = inDB.addParameter("irrigParam", 2);

Peter Alexander's avatar
Peter Alexander committed
		for (Entry<Integer, ? extends YieldResponses> cropsForALocation : inputData.getYields().entrySet()) {
Peter Alexander's avatar
Peter Alexander committed
			Integer locationId = cropsForALocation.getKey();
Peter Alexander's avatar
Peter Alexander committed
			YieldResponses yresp = cropsForALocation.getValue();
Peter Alexander's avatar
Peter Alexander committed
			for (CropType crop : CropType.values()) {
				LogWriter.println(String.format("     %15s,\t %.1f", crop.getGamsName(), yresp.getYieldNone(crop)));
				
Peter Alexander's avatar
Peter Alexander committed
				Vector<String> v = new Vector<String>();
Peter Alexander's avatar
Peter Alexander committed
				v.add(crop.getGamsName());
Peter Alexander's avatar
Peter Alexander committed
				v.add(Integer.toString(locationId));
Peter Alexander's avatar
Peter Alexander committed
				yNoneP.addRecord(v).setValue(yresp.getYieldNone(crop));
				y_fert.addRecord(v).setValue(yresp.getYieldFertOnly(crop));
				y_irrig.addRecord(v).setValue(yresp.getYieldIrrigOnly(crop));
				y_both.addRecord(v).setValue(yresp.getYieldMax(crop));
				fert_p.addRecord(v).setValue(yresp.getFertParam(crop));
				irrig_p.addRecord(v).setValue(yresp.getIrrigParam(crop));
Peter Alexander's avatar
Peter Alexander committed
			}
		}
Peter Alexander's avatar
Peter Alexander committed

		LogWriter.println("\nWorld input energy");
Peter Alexander's avatar
Peter Alexander committed
		param = inDB.addParameter("world_input_energy", 1, "average input energy from world exports used to determine if we should import or export energy per t");
Peter Alexander's avatar
Peter Alexander committed
		addItemMapParm(param, inputData.getCountryInput().getWorldInputEnergy());
Peter Alexander's avatar
Peter Alexander committed

Peter Alexander's avatar
Peter Alexander committed
		LogWriter.println("\nMax Net Import");
Peter Alexander's avatar
Peter Alexander committed
		param = inDB.addParameter("maxNetImport", 1, "max net imports for each crop based on world market");
Peter Alexander's avatar
Peter Alexander committed
		addItemMapParm(param, inputData.getCountryInput().getMaxNetImport());
Peter Alexander's avatar
Peter Alexander committed

Peter Alexander's avatar
Peter Alexander committed
		LogWriter.println("\nMin Net Import");
Peter Alexander's avatar
Peter Alexander committed
		param = inDB.addParameter("minNetImport", 1, "min net imports for each crop based on world market");
Peter Alexander's avatar
Peter Alexander committed
		addItemMapParm(param, inputData.getCountryInput().getMinNetImport());
Peter Alexander's avatar
Peter Alexander committed

Peter Alexander's avatar
Peter Alexander committed
		addScalar(inDB.addParameter("meatEfficency", 0, "efficency of converting feed and pasture into animal products"), inputData.getCountryInput().getMeatEfficiency());
		addScalar(inDB.addParameter("maxLandUseChange", 0, "max rate of land use change"), inputData.getCountryInput().getMaxLandUseChange());
		addScalar(inDB.addParameter("tradeBarrier", 0, "trade barrier which adjust energy cost of imports"), inputData.getCountryInput().getTradeBarrier());
		addScalar(inDB.addParameter("landChangeEnergy", 0, "energy required to add ha of agricultural land"), inputData.getCountryInput().getLandChangeEnergy());
		addScalar(inDB.addParameter("minFeedRate", 0, "minimum rate of feed for producing animal products"), inputData.getCountryInput().getMinFeedRate());
Peter Alexander's avatar
Peter Alexander committed
	}

Peter Alexander's avatar
Peter Alexander committed
	private GamsOutput handleResults(GAMSDatabase outDB) {
Peter Alexander's avatar
Peter Alexander committed
		int modelStatus = (int) outDB.getParameter("ms").findRecord().getValue();
		System.out.println(
				"\nModelstatus: " + GAMSGlobals.ModelStat.lookup( modelStatus ) +
				", Solvestatus: " + GAMSGlobals.SolveStat.lookup((int) outDB.getParameter("ss").findRecord().getValue()) );

		GAMSVariable varAreas = outDB.getVariable("area");
		GAMSVariable varFertIntensities = outDB.getVariable("fertI");
		GAMSVariable varIrrigIntensities = outDB.getVariable("irrigI");
		GAMSVariable varOtherIntensities = outDB.getVariable("otherIntensity");
		GAMSVariable varFeedAmount = outDB.getVariable("feedAmount");
		GAMSVariable varNetImports = outDB.getVariable("netImportAmount");
Peter Alexander's avatar
Peter Alexander committed

		double totalArea = 0;
Peter Alexander's avatar
Peter Alexander committed
		double area, fertIntensity, irrigIntensity, otherIntensity, feedAmount, netImport;

Peter Alexander's avatar
Peter Alexander committed
		Map<Integer, Intensities> intensities = new HashMap<Integer, Intensities>();
		Map<Integer, CropAreas> cropAreas = new HashMap<Integer, CropAreas>();
Peter Alexander's avatar
Peter Alexander committed
		Map<CropType, Double> feedAmounts = new HashMap<CropType, Double>();
		Map<CropType, Double> netImports = new HashMap<CropType, Double>();
Peter Alexander's avatar
Peter Alexander committed

Peter Alexander's avatar
Peter Alexander committed
		for (GAMSVariableRecord rec : varAreas) {
Peter Alexander's avatar
Peter Alexander committed
			String itemName = rec.getKeys()[0];
			String locationName = rec.getKeys()[1];
Peter Alexander's avatar
Peter Alexander committed
			area = rec.getLevel();
			fertIntensity = varFertIntensities.findRecord(itemName, locationName).getLevel();
			irrigIntensity = varIrrigIntensities.findRecord(itemName, locationName).getLevel();
			otherIntensity = varOtherIntensities.findRecord(itemName, locationName).getLevel();
Peter Alexander's avatar
Peter Alexander committed
			int locId = Integer.parseInt(locationName);
			CropType cropType = CropType.getForGamsName(itemName);
			
			if (locId == 1) {
				feedAmount = varFeedAmount.findRecord(itemName).getLevel();
				netImport = varNetImports.findRecord(itemName).getLevel();
				feedAmounts.put(cropType, feedAmount);
				netImports.put(cropType, netImport);
				LogWriter.println(String.format("\n%s:\tfeedAmount= %.1f,\tnetImports= %.3f", itemName, feedAmount, netImport)); 
			}

			if (area > 0) {
				LogWriter.println(String.format("\t location %s:\tarea= %.1f,\tfert= %.3f,\tirrg= %.3f,\tintensity= %.3f", 
						locationName, area, fertIntensity, irrigIntensity, otherIntensity)); 

Peter Alexander's avatar
Peter Alexander committed
				Intensities intensityItem = intensities.get(locId);
				if (intensityItem == null) {
					intensityItem = new Intensities();
					intensities.put(locId, intensityItem);
Peter Alexander's avatar
Peter Alexander committed
				}
Peter Alexander's avatar
Peter Alexander committed
				intensityItem.setIntensity(cropType, new Intensity(fertIntensity, irrigIntensity, otherIntensity));
Peter Alexander's avatar
Peter Alexander committed

Peter Alexander's avatar
Peter Alexander committed
				CropAreas areaItem = cropAreas.get(locId);
				if (areaItem == null) {
					areaItem = new CropAreas();
					cropAreas.put(locId, areaItem);
				}
				areaItem.setCropArea(cropType, area);
				
Peter Alexander's avatar
Peter Alexander committed
				totalArea += area;
			}
Peter Alexander's avatar
Peter Alexander committed
			
Peter Alexander's avatar
Peter Alexander committed
		}
Peter Alexander's avatar
Peter Alexander committed
		LogWriter.println(String.format("\nTotal area= %.1f", totalArea));
Peter Alexander's avatar
Peter Alexander committed
		//cleanup(ws.workingDirectory());
Peter Alexander's avatar
Peter Alexander committed
		
Peter Alexander's avatar
Peter Alexander committed
		GamsOutput results = new GamsOutput(modelStatus, intensities, cropAreas, feedAmounts, netImports);
Peter Alexander's avatar
Peter Alexander committed
		return results ;
Peter Alexander's avatar
Peter Alexander committed
	}

	private void addScalar(GAMSParameter param, double val) {
		param.addRecord().setValue(val);
	}

Peter Alexander's avatar
Peter Alexander committed
	private void addItemMapParm(GAMSParameter parm, Map<CropType, Double> itemMap) {
		for (Map.Entry<CropType, Double> entry : itemMap.entrySet()) {
Peter Alexander's avatar
Peter Alexander committed
			LogWriter.println(String.format("     %15s,\t %.1f", entry.getKey().getGamsName(), entry.getValue()));
Peter Alexander's avatar
Peter Alexander committed
			parm.addRecord(entry.getKey().getGamsName()).setValue(entry.getValue());
		}
	}
Peter Alexander's avatar
Peter Alexander committed

Peter Alexander's avatar
Peter Alexander committed
	private void addLocationMapParm(GAMSParameter parm, Map<Integer, ? extends CropAreas> locationItemMap) {
		for (Map.Entry<Integer, ? extends CropAreas> cropsForALocation : locationItemMap.entrySet()) {
Peter Alexander's avatar
Peter Alexander committed
			Integer locationId = cropsForALocation.getKey();
Peter Alexander's avatar
Peter Alexander committed
			CropAreas itemMap = cropsForALocation.getValue();
Peter Alexander's avatar
Peter Alexander committed

Peter Alexander's avatar
Peter Alexander committed
			for (CropType cropType : CropType.values()) {
				double d = itemMap.getCropArea(cropType);
				LogWriter.println(String.format("     %15s,\t %.1f", cropType.getGamsName(), d));
Peter Alexander's avatar
Peter Alexander committed
				Vector<String> v = new Vector<String>();
Peter Alexander's avatar
Peter Alexander committed
				v.add(cropType.getGamsName());
Peter Alexander's avatar
Peter Alexander committed
				v.add(Integer.toString(locationId));
Peter Alexander's avatar
Peter Alexander committed
				parm.addRecord(v).setValue(d);
Peter Alexander's avatar
Peter Alexander committed
			}
Peter Alexander's avatar
Peter Alexander committed

Peter Alexander's avatar
Peter Alexander committed
	@SuppressWarnings("unused")
	private void cleanup(String directory)  {
		File directoryToDelete = new File(directory);
		String files[] = directoryToDelete.list();
		for (String file : files) {
			File fileToDelete = new File(directoryToDelete, file);
			try {
				fileToDelete.delete();
			} catch(Exception e){
				e.printStackTrace();
			}
		}
		try {
			directoryToDelete.delete();
		} catch(Exception e) {
			e.printStackTrace();
		}
	}
Peter Alexander's avatar
Peter Alexander committed
}