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;
rhenry2
committed
import ac.ed.lurg.country.CountryPrice;
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);
Peter Alexander
committed
GAMSParameter prevFertIP = inDB.addParameter("previousFertIntensity", 2);
GAMSParameter prevIrrigIP = inDB.addParameter("previousIrrigIntensity", 2);
GAMSParameter prevOtherIP = inDB.addParameter("previousOtherIntensity", 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));
setGamsParamValueTruncate(landP.addRecord(locString), suitableLand, 3);
Peter Alexander
committed
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
for (CropType cropType : CropType.getNonMeatTypes()) {
Vector<String> v = new Vector<String>();
v.add(cropType.getGamsName());
v.add(locString);
double area;
if (CropType.PASTURE == cropType)
area = landUseItem.getLandCoverArea(LandCoverType.PASTURE);
else
area = landUseItem.getCropArea(cropType);
double prevFertI, prevIrrigI, prevOtherI;
Intensity intensity = landUseItem.getIntensity(cropType);
if (intensity==null) { // could be first time through or this crop not previously grown in this location, so give it some default values
double defaultI = CropType.PASTURE == cropType ? 0.01 : 0.5;
prevFertI = defaultI;
prevIrrigI = defaultI;
prevOtherI = defaultI;
}
else {
prevFertI = intensity.getFertiliserIntensity();
prevIrrigI = intensity.getIrrigationIntensity();
prevOtherI = intensity.getOtherIntensity();
}
if (DEBUG) LogWriter.println(String.format(" %d %15s,\t %.2f,\t %.3f,\t %.3f,\t %.3f", locationId, cropType.getGamsName(), area, prevFertI, prevIrrigI, prevOtherI));
setGamsParamValue(prevCropP.addRecord(v), area, 3);
Peter Alexander
committed
setGamsParamValue(prevFertIP.addRecord(v), prevFertI, 4);
setGamsParamValue(prevIrrigIP.addRecord(v), prevIrrigI, 4);
setGamsParamValue(prevOtherIP.addRecord(v), prevOtherI, 4);
totalAgriLand += area;
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));
Peter Alexander
committed
setGamsParamValue(irrigCostP.addRecord(Integer.toString(locationId)), irrigCost, 4);
setGamsParamValue(irrigConstraintP.addRecord(Integer.toString(locationId)), irrigConstraint, 3);
GamsCountryInput countryInput = inputData.getCountryInput();
Peter Alexander
committed
addCommodityMapParm(inDB.addParameter("demand", 1), countryInput.getProjectedDemand(), 4);
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));
Peter Alexander
committed
setGamsParamValue(yNoneP.addRecord(v), yresp.getYieldNone(crop), 4);
setGamsParamValue(y_fert.addRecord(v), yresp.getYieldFertOnly(crop), 4);
setGamsParamValue(y_irrig.addRecord(v), yresp.getYieldIrrigOnly(crop), 4);
setGamsParamValue(y_both.addRecord(v), yresp.getYieldMax(crop), 4);
setGamsParamValue(fert_p.addRecord(v), yresp.getFertParam(crop), 4);
setGamsParamValue(irrig_p.addRecord(v), yresp.getIrrigParam(crop), 4);
setGamsParamValue(irrigMaxP.addRecord(v), maxIrrig, 3);
if (DEBUG) LogWriter.println("\nImport-export, min net imports, max net imports, global import price, global export price");
GAMSParameter minImportP = inDB.addParameter("minNetImport", 1);
GAMSParameter maxImportP = inDB.addParameter("maxNetImport", 1);
GAMSParameter importPriceP = inDB.addParameter("importPrices", 1);
GAMSParameter exportPriceP = inDB.addParameter("exportPrices", 1);
for (CropType crop : CropType.getImportedTypes()) {
ImportExportConstraint iec = countryInput.getImportConstraints().get(crop);
CountryPrice gp = countryInput.getCountryPrices().get(crop);
double minNetImport = iec.getMinNetImport();
double maxNetImport = iec.getMaxNetImport();
double importPrice = gp.getImportPrice();
double exportPrice = gp.getExportPrice();
if (DEBUG) LogWriter.println(String.format(" %15s, \t %5.1f, \t %5.1f, \t %5.3f, \t %5.3f", crop.getGamsName(), minNetImport, maxNetImport, importPrice, exportPrice));
Peter Alexander
committed
setGamsParamValue(minImportP.addRecord(crop.getGamsName()), minNetImport, 3);
setGamsParamValue(maxImportP.addRecord(crop.getGamsName()), maxNetImport, 3);
setGamsParamValue(importPriceP.addRecord(crop.getGamsName()), importPrice, 3);
setGamsParamValue(exportPriceP.addRecord(crop.getGamsName()), exportPrice, 3);
Peter Alexander
committed
}
Peter Alexander
committed
addScalar(inDB, "meatEfficency", countryInput.getMeatEfficiency(), 3);
addScalar(inDB, "fertiliserUnitCost", ModelConfig.FERTILISER_MAX_COST, 3);
addScalar(inDB, "otherICost",ModelConfig.OTHER_INTENSITY_COST, 3);
addScalar(inDB, "otherIParam", ModelConfig.OTHER_INTENSITY_PARAM, 3);
addScalar(inDB, "landChangeCost", countryInput.getLandChangeCost(), 3);
addScalar(inDB, "minFeedRate", countryInput.getMinFeedRate(), 3);
addScalar(inDB, "unhandledCropArea", ModelConfig.UNHANDLED_CROP_AREA, 3);
addScalar(inDB, "domesticPriceMarkup", ModelConfig.DOMESTIC_PRICE_MARKUP, 3);
Peter Alexander
committed
private void addScalar(GAMSDatabase gamsDb, String recordName, double val, int places) {
GAMSParameter param = gamsDb.addParameter(recordName, 0);
Peter Alexander
committed
setGamsParamValue(param.addRecord(), val, places);
if (DEBUG) LogWriter.println(recordName + ": " + val);
Peter Alexander
committed
private void setGamsParamValue(GAMSParameterRecord param, double val, int places) {
double dOut = Math.round(val * Math.pow(10,places)) / Math.pow(10,places);
param.setValue(dOut);
Peter Alexander
committed
}
private void setGamsParamValueTruncate(GAMSParameterRecord param, double val, int places) {
double dOut = ((int)(val * Math.pow(10,places))) / Math.pow(10,places);
param.setValue(dOut);
Peter Alexander
committed
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;
Peter Alexander
committed
double area, fertIntensity, irrigIntensity, otherIntensity = Double.NaN, feedAmount, netImport, yield, unitCost, 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));
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 addCommodityMapParm(GAMSParameter parm, Map<CommodityType, Double> itemMap, int places) {
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));
Peter Alexander
committed
setGamsParamValue(parm.addRecord(entry.getKey().getGamsName()), d, places);
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) {