diff --git a/GAMS/IntExtOpt.gms b/GAMS/IntExtOpt.gms
index d20564f6df0649777126c12084ccaf41b56e4c11..0ac433f0baa40f170d978c1bc4db30b19063c6e3 100644
--- a/GAMS/IntExtOpt.gms
+++ b/GAMS/IntExtOpt.gms
@@ -23,6 +23,8 @@
  PARAMETER maxNetImport(import_crop)         maximum net import for each crop based on world market;
  PARAMETER minNetImport(import_crop)         minimum net import for each crop based on world market;
  PARAMETER irrigCost(location)               irrigation cost;
+ PARAMETER irrigMaxRate(crop, location)      max water application rate irrigation in mm;
+ PARAMETER irrigConstraint(location)         max water available for irrigation in mm;
  PARAMETER cropAdj(crop)                     this is the fudge factor that allows the model to fit the observed data
  
  SCALAR meatEfficency                        efficiency of converting feed and pasture into animal products;
@@ -36,7 +38,7 @@ $gdxin %gdxincname%
 $load location, suitableLandArea, previousArea, demand, landChangeEnergy
 $load yieldNone, yieldFertOnly, yieldIrrigOnly, yieldBoth
 $load fertParam, irrigParam, worldInputPrices, maxNetImport, minNetImport
-$load meatEfficency, minFeedRate, irrigCost
+$load meatEfficency, minFeedRate, irrigCost, irrigMaxRate, irrigConstraint
 $load cropAdj, fitToPreviousAreas
 $gdxin
     
@@ -100,6 +102,7 @@ $gdxin
        MIN_NET_IMPORT_CONSTRAINT(import_crop)           constraint on min net imports
        PASTURE_IMPORT_CONSTRAINT                        constraint to not import pasture
        MIN_FEED_CONSTRAINT                              constraint on min feed rate
+       IRRIGATION_CONSTRAINT(location)                  constraint no water usage
        NET_SUPPLY_EQ(crop)                              calc net supply for crops
        AGRI_LAND_EXPANSION_CALC(location)               calc agriLandExpansion
        CROP_INCREASE_CALC(location)                     
@@ -146,6 +149,8 @@ $gdxin
  
  MIN_FEED_CONSTRAINT .. sum(feed_crop_less_pasture, feedDM(feed_crop_less_pasture) * feedAmount(feed_crop_less_pasture)) =G= minFeedRate * (demand('meat') - netImportAmount('meat'));
  
+ IRRIGATION_CONSTRAINT(location) .. irrigConstraint(location) =G= sum(crop, irrigMaxRate(crop, location) * irrigI(crop, location) * area(crop, location));
+ 
  AGRI_LAND_EXPANSION_CALC(location) .. agriLandExpansion(location) =G= sum(crop, area(crop, location) - previousArea(crop, location)); 
  
  CROP_INCREASE_CALC(location) .. cropIncrease(location) =G= sum(crop_less_pasture, area(crop_less_pasture, location) - previousArea(crop_less_pasture, location));
diff --git a/src/ac/ed/lurg/country/gams/GamsLocationOptimiser.java b/src/ac/ed/lurg/country/gams/GamsLocationOptimiser.java
index c56267a0b374b82ecd9fbdaf6a2fecef4df408b3..3f28357ffb1b9f497b0fb824e5218f1162c165ad 100644
--- a/src/ac/ed/lurg/country/gams/GamsLocationOptimiser.java
+++ b/src/ac/ed/lurg/country/gams/GamsLocationOptimiser.java
@@ -32,12 +32,6 @@ import com.gams.api.GAMSWorkspaceInfo;
 
 public class GamsLocationOptimiser {
 
-	// DM kg / kg
-	// cereals 0.86
-	// oilcrops 0.90
-	// soy 0.89
-	// potatoes 0.21
-
 	private static final boolean DEBUG = true;
 
 	private GamsLocationInput inputData;
@@ -89,7 +83,7 @@ public class GamsLocationOptimiser {
 		if (DEBUG) LogWriter.println("\nPrevious crop and land areas");	
 		GAMSParameter prevCropP = inDB.addParameter("previousArea", 2);
 		GAMSParameter landP = inDB.addParameter("suitableLandArea", 1);
-
+		
 		double totalAgriLand = 0;
 
 		for (Map.Entry<Integer, ? extends LandUseItem> entry : inputData.getPreviousLandUse().entrySet()) {
@@ -115,36 +109,46 @@ public class GamsLocationOptimiser {
 		}
 		if (DEBUG) LogWriter.println(String.format("  Total agricultural\t %.1f", totalAgriLand));
 
-		if (DEBUG) LogWriter.println("\nIrrigation cost");
-		GAMSParameter irrigCostP = inDB.addParameter("irrigCost", 1);
-		for (Entry<Integer, ? extends IrrigationItem> entry : inputData.getIrrigationCosts().entrySet()) {
+		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()) {
 			Integer locationId = entry.getKey();
 			IrrigationItem irrigCostItem = entry.getValue();
 			double irrigCost = irrigCostItem.getIrrigCost();
-			if (DEBUG) LogWriter.println(String.format("  %d   %15s,\t %.1f", locationId, "irrigCost", irrigCost));
+			double irrigConstraint = irrigCostItem.getIrrigConstraint();
+			if (DEBUG) LogWriter.println(String.format("  %d  \t %.1f,\t %.1f", locationId, irrigCost, irrigConstraint));
 			irrigCostP.addRecord(Integer.toString(locationId)).setValue(irrigCost);
+			irrigConstraintP.addRecord(Integer.toString(locationId)).setValue(irrigCost);
 		}
 
 		if (DEBUG) LogWriter.println("\nDemand");
 		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]");
+		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();
 			String locString = Integer.toString(locationId);
 			YieldResponsesItem yresp = entry.getValue();
+			IrrigationItem irrigationItem = irrigationData.get(locationId);
 
 			for (CropType crop : CropType.getNonMeatTypes()) {
-				if (DEBUG) LogWriter.println(String.format("%d     %15s,\t %.1f,\t %.1f, \t %.1f,\t %.1f,\t\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)));
+				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 {%.1f}", 
+						locationId, crop.getGamsName(), yresp.getYieldNone(crop), yresp.getYieldFertOnly(crop), yresp.getYieldIrrigOnly(crop), yresp.getYieldMax(crop), 
+						yresp.getFertParam(crop), yresp.getIrrigParam(crop), maxIrrig));
 
 				Vector<String> v = new Vector<String>();
 				v.add(crop.getGamsName());
@@ -156,6 +160,7 @@ public class GamsLocationOptimiser {
 				y_both.addRecord(v).setValue(yresp.getYieldMax(crop));
 				fert_p.addRecord(v).setValue(yresp.getFertParam(crop));
 				irrig_p.addRecord(v).setValue(yresp.getIrrigParam(crop));
+				irrigMaxP.addRecord(v).setValue(maxIrrig);
 			}
 		}
 
diff --git a/src/ac/ed/lurg/landuse/IrrigationItem.java b/src/ac/ed/lurg/landuse/IrrigationItem.java
index 5ebcfb9d72892124e28c812b32b35b9915cfd508..1a2d873e14756cfec7eebfd5f0ec91ae3e0013d5 100644
--- a/src/ac/ed/lurg/landuse/IrrigationItem.java
+++ b/src/ac/ed/lurg/landuse/IrrigationItem.java
@@ -25,7 +25,7 @@ public class IrrigationItem implements RasterItem {
 	
 	public double getMaxIrrigAmount(CropType crop) {
 		Double d = maxIrrigAmounts.get(crop);
-		return d==null ? Double.NaN : d.doubleValue();
+		return d==null ? 0.0 : d.doubleValue();
 	}
 	
 	public void setMaxIrrigAmount(CropType crop, double maxIrrig) {