Newer
Older
import com.gams.api.GAMSDatabase;
import com.gams.api.GAMSException;
import com.gams.api.GAMSGlobals;
import com.gams.api.GAMSJob;
import com.gams.api.GAMSOptions;
import com.gams.api.GAMSParameter;
import com.gams.api.GAMSParameterRecord;
import com.gams.api.GAMSSet;
import com.gams.api.GAMSVariable;
import com.gams.api.GAMSVariableRecord;
import com.gams.api.GAMSWorkspace;
import com.gams.api.GAMSWorkspaceInfo;
import ac.ed.lurg.country.GlobalPrice;
import ac.ed.lurg.country.ImportExportConstraint;
import ac.ed.lurg.landuse.CropUsageData;
import ac.ed.lurg.landuse.IrrigationItem;
import ac.ed.lurg.landuse.LandUseItem;
import ac.ed.lurg.types.CommodityType;
import ac.ed.lurg.types.LandCoverType;
import ac.ed.lurg.utils.LazyHashMap;
public class GamsLocationOptimiser {
private GamsLocationInput inputData;
public GamsLocationOptimiser(GamsLocationInput inputData) {
public GamsLocationOutput run() {
File workingDirectory = new File(ModelConfig.TEMP_DIR, "GamsTmp");
workingDirectory.mkdir();
GAMSWorkspaceInfo wsInfo = new GAMSWorkspaceInfo();
wsInfo.setWorkingDirectory(workingDirectory.getAbsolutePath());
GAMSDatabase inDB = ws.addDatabase();
setupInDB(inDB);
GAMSJob gamsJob = ws.addJobFromFile(ModelConfig.GAMS_MODEL);
GAMSOptions opt = ws.addOptions();
opt.setAllModelTypes("conopt");
opt.defines("gdxincname", inDB.getName());
long startTime = System.currentTimeMillis();
gamsJob.run(opt, inDB);
if (ModelConfig.CLEANUP_GAMS_DIR)
cleanup(ws.workingDirectory());
LogWriter.println("Took " + (System.currentTimeMillis() - startTime) + " ms to run");
return handleResults(gamsJob.OutDB());
}
private void setupInDB(GAMSDatabase inDB) {
//if (DEBUG) LogWriter.println("\nLocation set");
GAMSSet locationSet = inDB.addSet("location", 1);
for (Integer locId : inputData.getPreviousLandUse().keySet()) {
//if (DEBUG) LogWriter.println(" " + locId);
locationSet.addRecord(locId.toString());
}
if (DEBUG) LogWriter.println("\nPrevious crop and land areas");
GAMSParameter prevCropP = inDB.addParameter("previousArea", 2);
GAMSParameter landP = inDB.addParameter("suitableLandArea", 1);
for (Map.Entry<Integer, ? extends LandUseItem> entry : inputData.getPreviousLandUse().entrySet()) {
LandUseItem landUseItem = entry.getValue();
double suitableLand = landUseItem.getSuitableLand();
if (DEBUG) LogWriter.println(String.format(" %d %15s,\t %.1f", locationId, "suitableLand", suitableLand));
landP.addRecord(locString).setValue(suitableLand);
double pastureArea = landUseItem.getLandCoverArea(LandCoverType.PASTURE);
if (DEBUG) LogWriter.println(String.format(" %d %15s,\t %.1f", locationId, "pastureArea", pastureArea));
setPreviousArea(prevCropP, locString, CropType.PASTURE.getGamsName(), pastureArea);
totalAgriLand += pastureArea;
for (CropType cropType : CropType.getCropsLessPasture()) {
double d = landUseItem.getCropArea(cropType);
if (DEBUG && d != 0) LogWriter.println(String.format(" %d %15s,\t %.1f", locationId, cropType.getGamsName(), d));
setPreviousArea(prevCropP, locString, cropType.getGamsName(), d);
if (DEBUG) LogWriter.println(String.format(" Total agricultural\t %.1f", totalAgriLand));
if (DEBUG) LogWriter.println("\nIrrigation data (cost, constraint)");
GAMSParameter irrigCostP = inDB.addParameter("irrigCost", 1);
GAMSParameter irrigConstraintP = inDB.addParameter("irrigConstraint", 1);
Map<Integer, ? extends IrrigationItem> irrigationData = inputData.getIrrigationCosts();
for (Entry<Integer, ? extends IrrigationItem> entry : irrigationData.entrySet()) {
IrrigationItem irrigCostItem = entry.getValue();
double irrigCost = irrigCostItem.getIrrigCost();
double irrigConstraint = irrigCostItem.getIrrigConstraint();
if (DEBUG) LogWriter.println(String.format(" %d \t %.3f,\t %.1f", locationId, irrigCost, irrigConstraint));
irrigCostP.addRecord(Integer.toString(locationId)).setValue(irrigCost);
irrigConstraintP.addRecord(Integer.toString(locationId)).setValue(irrigConstraint);
GamsCountryInput countryInput = inputData.getCountryInput();
addCommodityMapParm(inDB.addParameter("demand", 1), countryInput.getProjectedDemand());
if (DEBUG) LogWriter.println("\nYield (fert/irrig) None/None, Max/None, None/Max, Max/Max,\t [fert p],\t [irrig p],\t {max irrig}");
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);
GAMSParameter irrigMaxP = inDB.addParameter("irrigMaxRate", 2);
for (Entry<Integer, ? extends YieldResponsesItem> entry : inputData.getYields().entrySet()) {
Integer locationId = entry.getKey();
IrrigationItem irrigationItem = irrigationData.get(locationId);
for (CropType crop : CropType.getNonMeatTypes()) {
double maxIrrig = irrigationItem.getMaxIrrigAmount(crop);
if (DEBUG) LogWriter.println(String.format("%d %15s,\t %.1f,\t %.1f, \t %.1f,\t %.1f,\t\t [%.2f],\t [%.2f],\t {%.2f}",
locationId, crop.getGamsName(), yresp.getYieldNone(crop), yresp.getYieldFertOnly(crop), yresp.getYieldIrrigOnly(crop), yresp.getYieldMax(crop),
yresp.getFertParam(crop), yresp.getIrrigParam(crop), maxIrrig));
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
committed
if (DEBUG) {
LogWriter.println("\nImport-export, min net imports, max net imports, global import price, global export price");
Peter Alexander
committed
for (CropType crop : CropType.getImportedTypes()) {
ImportExportConstraint iec = countryInput.getImportConstraints().get(crop);
double minNetImport = 0, maxNetImport = 0;
if (iec != null) {
minNetImport = iec.getMinNetImport();
maxNetImport = iec.getMaxNetImport();
}
GlobalPrice gp = countryInput.getWorldPrices().get(crop);
Peter Alexander
committed
LogWriter.println(String.format(" %15s, \t %5.1f, \t %5.1f, \t %5.3f, \t %5.3f",
crop.getGamsName(), minNetImport, maxNetImport, gp.getImportPrice(), gp.getExportPrice()));
Peter Alexander
committed
}
}
addItemMapParm(inDB.addParameter("minNetImport", 1), countryInput.getMinNetImport(), false);
addItemMapParm(inDB.addParameter("maxNetImport", 1), countryInput.getMaxNetImport(), false);
addItemMapParm(inDB.addParameter("countryImportPrices", 1), countryInput.getCountryImportPrices(), false);
addItemMapParm(inDB.addParameter("worldExportPrices", 1), countryInput.getWorldExportPrices(), false);
//the above is not really world export price because it is scaled by country tradeBarriers, might want to change
//parameter name in GAMS i.e. countryExportPrices
addScalar(inDB, "meatEfficency", countryInput.getMeatEfficiency());
addScalar(inDB, "fertiliserUnitCost", ModelConfig.FERTILISER_MAX_COST);
addScalar(inDB, "otherICost",ModelConfig.OTHER_INTENSITY_COST);
addScalar(inDB, "otherIParam", ModelConfig.OTHER_INTENSITY_PARAM);
addScalar(inDB, "landChangeCost", countryInput.getLandChangeCost());
addScalar(inDB, "minFeedRate", countryInput.getMinFeedRate());
addScalar(inDB, "unhandledCropArea", ModelConfig.UNHANDLED_CROP_AREA);
addScalar(inDB, "domesticPriceMarkup", ModelConfig.DOMESTIC_PRICE_MARKUP);
private void addScalar(GAMSDatabase gamsDb, String recordName, double val) {
GAMSParameter param = gamsDb.addParameter(recordName, 0);
param.addRecord().setValue(val);
if (DEBUG) LogWriter.println(recordName + ": " + val);
private void setPreviousArea(GAMSParameter prevCropP, String locString, String cropTypeString, double d) {
Vector<String> v = new Vector<String>();
v.add(cropTypeString);
v.add(locString);
prevCropP.addRecord(v).setValue(d);
}
@SuppressWarnings("serial")
private GamsLocationOutput handleResults(GAMSDatabase outDB) {
int modelStatus = (int) outDB.getParameter("ms").findRecord().getValue();
LogWriter.println(String.format("\n%s %s: Modelstatus %s, Solvestatus %s",
inputData.getCountryInput().getCountry(),
inputData.getTimestep().getYear(),
GAMSGlobals.ModelStat.lookup( modelStatus ),
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");
Peter Alexander
committed
GAMSParameter parmNetImports = outDB.getParameter("netImportAmount");
GAMSVariable varUnitEnergies = outDB.getVariable("unitCost");
// GAMSParameter parmCropAdj = outDB.getParameter("cropAdj");
GAMSParameter parmProd = outDB.getParameter("totalProd");
GAMSParameter parmProdCost = outDB.getParameter("totalProdCost");
GAMSParameter parmCroplandArea = outDB.getParameter("totalCropland");
double totalCropArea = 0;
double totalPastureArea = 0;
double area, fertIntensity, irrigIntensity, otherIntensity = Double.NaN, feedAmount, netImport, yield, unitCost, cropAdj, prod, prodCost;
final LazyHashMap<Integer, LandUseItem> landUses = new LazyHashMap<Integer, LandUseItem>() {
protected LandUseItem createValue() { return new LandUseItem(); }
};
Map<Integer, ? extends IrrigationItem> allIrrigationRefData = inputData.getIrrigationCosts();
Map<CropType, CropUsageData> cropUsageData = new HashMap<CropType, CropUsageData>();
Map<CropType, Double> cropAdjs = new HashMap<CropType, Double>();
String locationName = rec.getKeys()[1];
fertIntensity = varFertIntensities.findRecord(itemName, locationName).getLevel();
irrigIntensity = varIrrigIntensities.findRecord(itemName, locationName).getLevel();
otherIntensity = varOtherIntensities.findRecord(itemName, locationName).getLevel();
yield = varYields.findRecord(itemName, locationName).getLevel();
unitCost = varUnitEnergies.findRecord(itemName, locationName).getLevel();
int locId = Integer.parseInt(locationName);
CropType cropType = CropType.getForGamsName(itemName);
if (!cropUsageData.containsKey(cropType)) { // then we must not have seen this crop type before, so need to do all non location specific stuff
feedAmount = varFeedAmount.findRecord(itemName).getLevel();
Peter Alexander
committed
netImport = cropType.isImportedCrop() ? getParmValue(parmNetImports, itemName) : 0;
prod = getParmValue(parmProd, itemName);
prodCost = getParmValue(parmProdCost, itemName);
cropUsageData.put(cropType, new CropUsageData(feedAmount, netImport, prod, prodCost));
// cropAdjs.put(cropType, cropAdj);
if (DEBUG) LogWriter.println(String.format("\n%s:\tfeedAmount= %.1f,\tnetImports= %.3f,\tprod= %.3f,\tprodCost= %.3f,\tcropAdj= %.3f", itemName, feedAmount, netImport, prod, prodCost, Double.NaN));
LandUseItem landUseItem = landUses.lazyGet(locId);
if (DEBUG) LogWriter.println(String.format("\t location %s, %s:\tarea= %.1f,\tfert= %.3f,\tirrg= %.3f,\tintensity= %.3f", locationName, itemName, area, fertIntensity, irrigIntensity, otherIntensity));
IrrigationItem irrigRefData = allIrrigationRefData.get(locId);
landUseItem.setIntensity(cropType, new Intensity(fertIntensity, irrigIntensity, otherIntensity, yield, unitCost, irrigRefData.getMaxIrrigAmount(cropType)));
double croplandArea = getParmValue(parmCroplandArea, locationName);
landUseItem.setLandCoverArea(LandCoverType.PASTURE, area);
landUseItem.setLandCoverArea(LandCoverType.CROPLAND, croplandArea); // will set this multiple times, once for each arable crop, but doesn't really matter
landUseItem.setCropFraction(cropType, croplandArea > 0 ? area/croplandArea : 0);
Peter Alexander
committed
netImport = getParmValue(parmNetImports, CropType.MEAT.getGamsName());
prod = getParmValue(parmProd, CropType.MEAT.getGamsName());
prodCost = getParmValue(parmProdCost, CropType.MEAT.getGamsName());
cropUsageData.put(CropType.MEAT, new CropUsageData(0.0, netImport, prod, prodCost));
LogWriter.println(String.format("\n%s:\t\t\t\t\tnetImports= %.3f,\tprod= %.3f,\tprodCost= %.3f", CropType.MEAT.getGamsName(), netImport, prod, prodCost));
LogWriter.println(String.format("\nTotal area= %.1f (crop=%.1f, pasture %.1f)", totalCropArea+totalPastureArea, totalCropArea, totalPastureArea));
GamsLocationOutput results = new GamsLocationOutput(modelStatus, landUses, cropUsageData, cropAdjs);
private double getParmValue(GAMSParameter aParm, String itemName) {
try {
GAMSParameterRecord record = aParm.findRecord(itemName);
double d = record.getValue();
return d;
}
catch (GAMSException gamsEx) {
//LogWriter.println("GAMSException thrown for " + itemName);
return 0;
}
}
Peter Alexander
committed
private void addItemMapParm(GAMSParameter parm, Map<CropType, Double> itemMap, boolean printOutput) {
for (Map.Entry<CropType, Double> entry : itemMap.entrySet()) {
Peter Alexander
committed
if (printOutput) LogWriter.println(String.format(" %15s,\t %.3f", entry.getKey().getGamsName(), d));
if (!Double.isNaN(d))
parm.addRecord(entry.getKey().getGamsName()).setValue(d);
private void addCommodityMapParm(GAMSParameter parm, Map<CommodityType, Double> itemMap) {
for (Map.Entry<CommodityType, Double> entry : itemMap.entrySet()) {
double d = entry.getValue();
if (DEBUG) LogWriter.println(String.format(" %15s,\t %.1f", entry.getKey().getGamsName(), d));
parm.addRecord(entry.getKey().getGamsName()).setValue(d);
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){
}
}
try {
directoryToDelete.delete();
} catch(Exception e) {