e2fae694 by Nathan Lighthart

Update UPGM Connection

- Rename PotentialCropGrowth to PotentialCropGrowthSWAT
- Create PotentialCropGrowthUPGM which removes calculations for UPGM calculated variables
- Update PotentialCropGrowthAdapter to execute the appropriate calculations based on flagUPGM
- Rename PlantGrowthStress to PlantGrowthStressSWAT
- Create PlantGrowthStressUPGM which removes calculations for UPGM calculated variabes
- Update PlantGrowthStressAdapter to execute the appropriate calculations based on flagUPGM
- Make water stress an optional variable for UPGM
- Move UPGM calculations to before PotentialCropGrowth
1 parent 253d0972
......@@ -697,8 +697,8 @@ public class AgESModel {
StatementBlock routingBlock = new StatementBlock(true, routing, sedRouting, routingN);
StatementBlock root = new StatementBlock(routingBlock, soilParams,
soilWater, drain, dorm, et, cropExist, fertilization, pcg, soilTemp,
soiln, gw, musle, gwn, pgs, upgm);
soilWater, drain, dorm, et, cropExist, fertilization, upgm, pcg,
soilTemp, soiln, gw, musle, gwn, pgs);
return new Program(root);
}
......
......@@ -25,7 +25,6 @@ import ages.types.HRU;
import annotations.Author;
import annotations.Bibliography;
import annotations.Documentation;
import annotations.Execute;
import annotations.Keywords;
import annotations.License;
import annotations.SourceInfo;
......@@ -33,6 +32,7 @@ import annotations.Status;
import annotations.VersionInfo;
import gov.usda.jcf.annotations.Description;
import gov.usda.jcf.annotations.Input;
import gov.usda.jcf.annotations.Optional;
import gov.usda.jcf.annotations.Output;
import gov.usda.jcf.annotations.Units;
import gov.usda.jcf.core.Context;
......@@ -48,6 +48,9 @@ import gov.usda.jcf.core.adapters.AnnotatedAdapter;
@Status(Status.TESTED)
@Documentation("src/crop/PlantGrowthStress.xml")
public class PlantGrowthStressAdapter extends AnnotatedAdapter {
@Description("UPGM flag")
@Input public boolean flagUPGM;
@Description("Actual HRU Transpiration")
@Units("mm")
@Input public double aTransp;
......@@ -92,10 +95,16 @@ public class PlantGrowthStressAdapter extends AnnotatedAdapter {
@Description("Actual Crop Biomass")
@Units("kg/ha")
@Optional
@Input @Output public double BioAct;
@Description("Temperature Growth Stress Factor")
@Output public double tstrs;
@Optional
@Input @Output public double tstrs;
@Description("delta biomass increase per day")
@Optional
@Input @Output public double deltabiomass;
@Description("N Growth Stress Factor")
@Output public double nstrs;
......@@ -103,12 +112,17 @@ public class PlantGrowthStressAdapter extends AnnotatedAdapter {
@Description("Water Growth Stress Factor")
@Output public double wstrs;
@Description("delta biomass increase per day")
@Output public double deltabiomass;
@Override
protected void run(Context context) {
PlantGrowthStress component = new PlantGrowthStress();
if (flagUPGM) {
executeUPGM();
} else {
executeSWAT();
}
}
private void executeSWAT() {
PlantGrowthStressSWAT component = new PlantGrowthStressSWAT();
component.aTransp = aTransp;
component.pTransp = pTransp;
......@@ -131,11 +145,17 @@ public class PlantGrowthStressAdapter extends AnnotatedAdapter {
deltabiomass = component.deltabiomass;
}
/**
* OMS execute statement for testing before JCF
*/
@Execute
public void execute() {
run(null);
private void executeUPGM() {
PlantGrowthStressUPGM component = new PlantGrowthStressUPGM();
component.aTransp = aTransp;
component.pTransp = pTransp;
component.BioNOpt = BioNOpt;
component.BioNAct = BioNAct;
component.execute();
nstrs = component.nstrs;
wstrs = component.wstrs;
}
}
......
......@@ -21,7 +21,7 @@
package crop;
public class PlantGrowthStress {
public class PlantGrowthStressSWAT {
public double aTransp;
public double pTransp;
public double BioNOpt;
......
/*
* This file is part of the AgroEcoSystem-Watershed (AgES-W) model component
* collection. AgES-W components are derived from multiple agroecosystem models
* including J2K and J2K-SN (FSU-Jena, DGHM, Germany), SWAT (USDA-ARS, USA),
* WEPP (USDA-ARS, USA), RZWQM2 (USDA-ARS, USA), and others.
*
* The AgES-W model is free software; you can redistribute the model and/or
* modify the components under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package crop;
public class PlantGrowthStressUPGM {
public double aTransp;
public double pTransp;
public double BioNOpt;
public double BioNAct;
public double nstrs;
public double wstrs;
public void execute() {
// calculate water stress
if (pTransp > 0) {
wstrs = 1 - ((aTransp) / (pTransp));
} else {
wstrs = 0;
}
// calculate N stress
double phi_nit = 0;
if (((BioNAct + 0.01) / (BioNOpt + 0.01)) >= 0.319) {
phi_nit = 200 * (((BioNAct + 0.01) / (BioNOpt + 0.01)) - 0.319);
}
nstrs = 1 - (phi_nit / (phi_nit + Math.exp(3.535 - (0.02597 * phi_nit))));
nstrs = (nstrs > 1.0) ? 1.0 : nstrs;
}
}
......@@ -25,7 +25,6 @@ import ages.types.HRU;
import annotations.Author;
import annotations.Bibliography;
import annotations.Documentation;
import annotations.Execute;
import annotations.Keywords;
import annotations.License;
import annotations.Range;
......@@ -44,7 +43,6 @@ import gov.usda.jcf.core.adapters.AnnotatedAdapter;
import java.time.LocalDate;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger;
import management.HarvestOperation;
@Description("Add PotentialCropGrowth module definition here")
......@@ -57,9 +55,6 @@ import management.HarvestOperation;
@Status(Status.TESTED)
@Documentation("src/crop/PotentialCropGrowth.xml")
public class PotentialCropGrowthAdapter extends AnnotatedAdapter {
private static final Logger log
= Logger.getLogger("oms3.model." + PotentialCropGrowthAdapter.class.getSimpleName());
@Description("light extinction coefficient")
@Role(PARAMETER)
@Range(min = -1.0, max = 0.0)
......@@ -181,16 +176,18 @@ public class PotentialCropGrowthAdapter extends AnnotatedAdapter {
@Description("Biomass Added to Residue Pool After Harvesting")
@Units("kg/ha")
@Output public double Addresidue_pool;
@Optional
@Input @Output public double Addresidue_pool;
@Description("Yield Biomass")
@Units("kg/ha")
@Optional
@Input @Output public double BioYield;
@Description("Amount N Added to Residue Pool After Harvesting")
@Units("kgN/ha")
@Output public double Addresidue_pooln;
@Description("Yield Biomass")
@Units("kg/ha")
@Output public double BioYield;
@Description("Amount of N in Yield")
@Units("absolut")
@Output public double NYield;
......@@ -213,14 +210,29 @@ public class PotentialCropGrowthAdapter extends AnnotatedAdapter {
@Description("DLAI (Senescence)")
@Output public double dlai;
private Map<HRU, PotentialCropGrowth> componentMap = new ConcurrentHashMap<>();
private Map<HRU, PotentialCropGrowthSWAT> swatComponentMap = new ConcurrentHashMap<>();
@Override
protected void run(Context context) {
PotentialCropGrowth component = componentMap.get(hru);
if (flagUPGM) {
executeUPGM();
} else {
executeSWAT();
}
}
private boolean doHarvest() {
if (nextHarvestingDate == null || nextHarvestingOperation == null) {
return false;
}
return time.plusDays(1L).equals(nextHarvestingDate);
}
private void executeSWAT() {
PotentialCropGrowthSWAT component = swatComponentMap.get(hru);
if (component == null) {
component = new PotentialCropGrowth();
componentMap.put(hru, component);
component = new PotentialCropGrowthSWAT();
swatComponentMap.put(hru, component);
}
component.LExCoef = LExCoef;
......@@ -306,18 +318,38 @@ public class PotentialCropGrowthAdapter extends AnnotatedAdapter {
dlai = component.dlai;
}
private boolean doHarvest() {
if (nextHarvestingDate == null || nextHarvestingOperation == null) {
return false;
private void executeUPGM() {
PotentialCropGrowthUPGM component = new PotentialCropGrowthUPGM();
component.area = hru.area;
component.plantExisting = cropExists;
component.doHarvest = doHarvest();
if (component.doHarvest) {
component.harvesttype = nextHarvestingOperation.getHarvestType();
}
return time.plusDays(1L).equals(nextHarvestingDate);
}
if (crop != null) {
component.idc = crop.idc;
component.cnyld = crop.cnyld;
component.bn1 = crop.bn1;
component.bn2 = crop.bn2;
component.bn3 = crop.bn3;
}
component.plantStateReset = plantStateReset;
component.BioNOpt = BioNOpt;
component.BioAct = BioAct;
component.FNPlant = FNPlant;
component.BioNAct = BioNAct;
component.FPHUact = FPHUact;
component.BioYield = BioYield;
/**
* OMS execute statement for testing before JCF
*/
@Execute
public void execute() {
run(null);
component.execute();
plantStateReset = component.plantStateReset;
BioNOpt = component.BioNOpt;
FNPlant = component.FNPlant;
BioNAct = component.BioNAct;
Addresidue_pooln = component.Addresidue_pooln;
NYield = component.NYield;
NYield_ha = component.NYield_ha;
}
}
......
......@@ -23,9 +23,9 @@ package crop;
import java.util.logging.Logger;
public class PotentialCropGrowth {
public class PotentialCropGrowthSWAT {
private static final Logger log
= Logger.getLogger("oms3.model." + PotentialCropGrowth.class.getSimpleName());
= Logger.getLogger("oms3.model." + PotentialCropGrowthSWAT.class.getSimpleName());
public double LExCoef;
public double rootfactor;
......
/*
* This file is part of the AgroEcoSystem-Watershed (AgES-W) model component
* collection. AgES-W components are derived from multiple agroecosystem models
* including J2K and J2K-SN (FSU-Jena, DGHM, Germany), SWAT (USDA-ARS, USA),
* WEPP (USDA-ARS, USA), RZWQM2 (USDA-ARS, USA), and others.
*
* The AgES-W model is free software; you can redistribute the model and/or
* modify the components under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package crop;
public class PotentialCropGrowthUPGM {
public double area;
public int harvesttype;
public boolean plantExisting;
public boolean doHarvest;
public double bn1;
public double bn2;
public double bn3;
public int idc;
public double cnyld;
public boolean plantStateReset;
public double BioNOpt;
public double BioAct;
public double FNPlant;
public double BioNAct;
public double FPHUact;
public double Addresidue_pooln;
public double BioYield;
public double NYield;
public double NYield_ha;
public void execute() {
NYield = 0;
if (plantExisting) {
// check to see if this is the first step where crop is calculated
if (BioNAct == 0) {
BioNAct = bn1; // initial N content using optimal N content at emergence
}
calc_nuptake();
Addresidue_pooln = 0;
if (doHarvest) {
calc_cropyield();
calc_cropyield_ha();
calc_residues();
doHarvest = false;
}
} else if (plantStateReset) { // called if there is no crop grown on HRU
FNPlant = 0;
BioNOpt = 0;
BioNAct = 0;
Addresidue_pooln = 0;
plantStateReset = false;
}
/*
* Don't reset if plant is clover (IDC = 3), hay/pasture/wetlands (IDC = 6), or orchard/forest (IDC = 7).
* Reset all other crops the next time step.
*/
plantStateReset = (idc == 3 || idc == 6 || idc == 7) ? false : true;
}
/* Calculates optimal biomass N content, not actual N uptake.
* Maturity is reached when fphu_act = 1, and then no further calculation is needed.
* Nutrients, water uptake, and transpiration should stop depending on the condition fphu = 1.
* Need to calculate water uptake by plants, potential water uptake, and nutrient uptake by plants.
*/
private boolean calc_nuptake() {
// fraction of N in plant biomass as a function of growth stage given optimal conditions
if (bn1 > bn2 && bn2 > bn3 && bn3 > 0) {
double s1 = Math.log((0.5 / (1 - ((bn2 - bn3) / (bn1 - bn3)))) - 0.5);
double s2 = Math.log((1 / (1 - ((0.0001) / (bn1 - bn3)))) - 1);
double n2 = (s1 - s2) / 0.5;
double n1 = Math.log((0.5 / (1 - ((bn2 - bn3) / (bn1 - bn3)))) - 0.5) + (n2 * 0.5);
FNPlant = ((bn1 - bn3) * (1 - (FPHUact / (FPHUact + Math.exp(n1 - n2 * FPHUact))))) + bn3;
FNPlant = (harvesttype == 2) ? bn3 : FNPlant;
} else {
FNPlant = 0.01;
}
BioNOpt = FNPlant * BioAct;
return true;
}
/* N fixation occurs when NO3-N levels in the root zone are insufficient to meet demand.
* Note: need to calculate phosphorus uptake.
*/
private boolean calc_cropyield() {
if (idc == 3 || idc == 6 || idc == 7 || (idc == 8)) {
// amount of nitrogen (kg N/ha) to be removed from the HRU
NYield = BioNAct * (BioYield / BioAct);
NYield = (NYield < 0) ? 0 : NYield;
BioNAct -= NYield;
BioNAct = (BioNAct < 0) ? 0 : BioNAct; // crop N is always present
} else {
/*
* For harvesting, four codes are implemented:
* 1 --> assumes harvesting with main crop and a cover crop; plant growth stopped
* 2 --> assumes harvesting with main crop; the cover crop remains on the field, plant growth stopped (former kill op)
* 3 --> assumes harvesting with main crop and a cover crop; plant growth continues (may not be suitable for meadows)
* 4 --> assumes harvesting with main crop; plant growth continues
*
* If harvest is determined by code 1, the above-ground plant biomass is removed as dry economic yield.
* For majority of crops, harvest index is between 0 and 1; however, for plants whose roots are harvested
* the harvest index may be > 1. Harvest index is calculated for each day of growing season.
*/
NYield = cnyld * BioYield;
if (NYield > BioNAct * (NYield / (NYield + ((BioAct - BioYield) * (bn3 / 2.0))))) {
NYield = BioNAct * (NYield / (NYield + ((BioAct - BioYield) * (bn3 / 2.0))));
}
}
return true;
}
private void calc_cropyield_ha() {
NYield_ha = NYield * (area / 10000) / 10000;
}
private boolean calc_residues() {
if (idc == 7) {
Addresidue_pooln = NYield;
} else if (idc == 1 || idc == 2 || idc == 4 || idc == 5) {
Addresidue_pooln = BioNAct - NYield;
} else if (idc == 6 || idc == 3) {
Addresidue_pooln = NYield * 0.1;
Addresidue_pooln = Math.min(Addresidue_pooln, BioNAct);
BioNAct -= Addresidue_pooln;
} else if (idc == 8) {
Addresidue_pooln = NYield * 0.1;
Addresidue_pooln = Math.min(Addresidue_pooln, BioNAct);
BioNAct -= Addresidue_pooln;
}
return true;
}
}
......@@ -87,6 +87,7 @@ public class UpgmAdapter extends AnnotatedAdapter {
@Input public double precip;
@Description("water stress")
@Optional
@Input public double wstrs;
@Optional
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!