Watershed.java [src/java/m/weppws] Revision: default Date:
package m.weppws;
import csip.Config;
import csip.api.server.Executable;
import csip.api.server.ServiceException;
import csip.SessionLogger;
import csip.utils.Parallel;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import org.apache.commons.io.FileUtils;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import util.Grid;
import util.WeppConstants;
/**
* Represents a WEPP watershed, holds channels, subcatchments
*
*/
public class Watershed {
List<Subcatchment> subcatchments;
List<Channel> channels;
List<Impoundment> impoundments;
SessionLogger LOG;
File sessionWorkDir;
float precip;
float dischargeVol;
float sedimentYld;
float sedimentYldArea;
float delRatio;
float precipVol;
float discharge;
String weppVersion;
String preVersion;
boolean isWatershed;
int cells;
double area;
V1_0 par;
boolean subarea;
double irrigation; // total over all representative hillslopes
double fieldErosion; // total over all representative hillslopes
double fieldNRCSErosion; // total over all representative hillslopes
double fieldSedYield; // total over all representative hillslopes
Watershed(SessionLogger log, File sessionWorkDir, boolean isWatershed, V1_0 par) {
this.LOG = log;
this.isWatershed = isWatershed;
channels = new ArrayList<>();
subcatchments = new ArrayList<>();
impoundments = new ArrayList<>();
this.sessionWorkDir = sessionWorkDir;
this.par = par;
subarea = false;
}
void setChannelFlowpaths() throws ServiceException {
for (int i = 0; i < channels.size(); i++) {
par.walkChannelFlowpath(channels.get(i));
}
}
void createFlowpathLossGrid(Grid lossGrid, Grid sedWeightGrid) throws ServiceException {
for (int i = 0; i < subcatchments.size(); i++) {
if (subcatchments.get(i).getInuse())
subcatchments.get(i).outputFlowpaths(lossGrid, sedWeightGrid);
}
}
void createSoilLossGrid(Grid lossGrid, Grid subs) throws ServiceException {
for (int i = 0; i < subcatchments.size(); i++) {
int key = subcatchments.get(i).id;
float val = subcatchments.get(i).getAvgSoilLoss();
if (subcatchments.get(i).getInuse())
lossGrid.update(subs, key, val);
}
}
void createSoilLossGridSubareas(Grid lossGrid, Grid subs) throws ServiceException {
int hills = 0;
for (int i = 0; i < subcatchments.size(); i++) {
Subcatchment s = subcatchments.get(i);
int key;
float val;
boolean found = false;
if (s.getInuse()) {
if (s.topsub != null) {
val = s.topsub.getAvgSoilLoss();
key = s.topsub.topazid;
lossGrid.update(subs, key, val);
hills++;
found = true;
}
if (s.leftsub != null) {
val = s.leftsub.getAvgSoilLoss();
key = s.leftsub.topazid;
lossGrid.update(subs, key, val);
hills++;
found = true;
}
if (s.rightsub != null) {
val = s.rightsub.getAvgSoilLoss();
key = s.rightsub.topazid;
lossGrid.update(subs, key, val);
hills++;
found = true;
}
if (found == false)
LOG.info(" ERROR: Could not update sub3 grid " + s.id);
}
}
}
void createSedYieldGrid(Grid sedGrid, Grid subs) throws ServiceException {
for (int i = 0; i < subcatchments.size(); i++) {
int key = subcatchments.get(i).id;
float val = subcatchments.get(i).getAvgSedYield();
if (subcatchments.get(i).getInuse())
sedGrid.update(subs, key, val);
}
}
void createSedYieldGridSubareas(Grid sedGrid, Grid subs) throws ServiceException {
int hills = 0;
for (int i = 0; i < subcatchments.size(); i++) {
Subcatchment s = subcatchments.get(i);
int key;
float val;
boolean found = false;
if (s.getInuse()) {
if (s.topsub != null) {
val = s.topsub.getAvgSedYield();
key = s.topsub.topazid;
sedGrid.update(subs, key, val);
hills++;
found = true;
}
if (s.leftsub != null) {
val = s.leftsub.getAvgSedYield();
key = s.leftsub.topazid;
sedGrid.update(subs, key, val);
hills++;
found = true;
}
if (s.rightsub != null) {
val = s.rightsub.getAvgSedYield();
key = s.rightsub.topazid;
sedGrid.update(subs, key, val);
hills++;
found = true;
}
if (found == false)
LOG.info(" ERROR: Could not update sub3 grid " + s.id);
}
}
}
void createRunoffGrid(Grid runoffGrid, Grid subs) throws ServiceException {
for (int i = 0; i < subcatchments.size(); i++) {
int key = subcatchments.get(i).id;
float val = subcatchments.get(i).getAvgRunoff();
if (subcatchments.get(i).getInuse()) {
runoffGrid.update(subs, key, val);
}
}
}
void createRunoffGridSubareas(Grid runoffGrid, Grid subs) throws ServiceException {
int hills = 0;
for (int i = 0; i < subcatchments.size(); i++) {
Subcatchment s = subcatchments.get(i);
int key;
float val;
boolean found = false;
if (s.getInuse()) {
if (s.topsub != null) {
val = s.topsub.getAvgRunoff();
key = s.topsub.topazid;
runoffGrid.update(subs, key, val);
hills++;
found = true;
}
if (s.leftsub != null) {
val = s.leftsub.getAvgRunoff();
key = s.leftsub.topazid;
runoffGrid.update(subs, key, val);
hills++;
found = true;
}
if (s.rightsub != null) {
val = s.rightsub.getAvgRunoff();
key = s.rightsub.topazid;
runoffGrid.update(subs, key, val);
hills++;
found = true;
}
if (found == false)
LOG.info(" ERROR: Could not update sub3 grid " + s.id);
}
}
}
Grid createsub3grid(Grid sub3) throws ServiceException {
for (int i = 0; i < subcatchments.size(); i++) {
LOG.info((">Processing subcatchment: " + subcatchments.get(i).id));
if (subcatchments.get(i).getInuse()) {
subcatchments.get(i).fillsub3grid(LOG,sub3);
} else {
LOG.info(">Unused subcatchment: " + subcatchments.get(i).id);
}
}
for (int i = 0; i < channels.size(); i++) {
channels.get(i).fillsub3grid(sub3);
}
return sub3;
}
void addChannel(Channel ch) {
channels.add(ch);
}
void addImpoundment(Impoundment imp) {
impoundments.add(imp);
linkImpoundmentToChannel(imp);
}
void addSubcatchment(Subcatchment s) {
s.weppid = subcatchments.size() + 1;
subcatchments.add(s);
}
void dumpChannels() {
for (int i = 0; i < channels.size(); i++) {
LOG.info("Channel: " + channels.get(i).id);
}
}
void dumpSubcatchments() throws ServiceException, JSONException {
try {
for (int i = 0; i < subcatchments.size(); i++) {
subcatchments.get(i).writeFlowpaths(sessionWorkDir);
}
} catch (IOException ex1) {
throw new ServiceException("Can not create flowpaths files.");
}
}
Subcatchment getSubcatchment(int id) {
for (int i = 0; i < subcatchments.size(); i++) {
if (subcatchments.get(i).id == id)
return subcatchments.get(i);
}
return null;
}
void removeFiles() {
for (int i = 0; i < subcatchments.size(); i++) {
new File(sessionWorkDir, "flowpaths_" + Integer.toString(subcatchments.get(i).id)).delete();
}
new File(sessionWorkDir, "slope_d8.asc").delete();
}
int runFlowpaths(Executable weppserv, Grid field, boolean statsOnly,
int subsetPercentage, boolean parallelRuns) throws ServiceException, Exception {
int total = 0;
LOG.info(">>> Flowpath runs starting now for subcatchments: " + subcatchments.size());
try {
for (int i = 0; i < subcatchments.size(); i++) {
LOG.info(">>> Subcatchment " + i);
if (parallelRuns) {
total += subcatchments.get(i).runFlowpaths0(LOG, sessionWorkDir, field, statsOnly);
} else {
//if (par.flowpathURL.length() > 0) {
// total += subcatchments.get(i).runFlowpaths(LOG, sessionWorkDir, weppserv, field, statsOnly, subsetPercentage);
//} else {
total += subcatchments.get(i).runFlowpathsLocal(LOG, sessionWorkDir, weppserv, field, statsOnly, subsetPercentage);
//}
}
}
} catch (IOException ex1) {
throw new ServiceException("Can not run flowpaths.", ex1);
}
LOG.info("<<< Flowpath runs ending now.");
return total;
}
int runFlowpathsSubset(Executable weppserv, Grid field, boolean statsOnly,
int subsetPercentage, boolean parallelRuns, int[] detailsubcatchments) throws ServiceException, Exception {
int total = 0;
if (detailsubcatchments.length == 0) {
LOG.info(">>> Flowpath runs starting now for subcatchments: " + subcatchments.size());
} else {
LOG.info(">>> Flowpath runs starting now for subcatchments: " + detailsubcatchments);
}
try {
for (int i = 0; i < detailsubcatchments.length; i++) {
for (int j = 0; j < subcatchments.size(); j++) {
if (detailsubcatchments[i] == subcatchments.get(j).id) {
LOG.info(">>> Subcatchment " + j);
if (parallelRuns) {
total += subcatchments.get(j).runFlowpaths0(LOG, sessionWorkDir, field, statsOnly);
} else {
total += subcatchments.get(j).runFlowpathsLocal(LOG, sessionWorkDir, weppserv, field, statsOnly, subsetPercentage);
}
break;
}
}
}
} catch (IOException ex1) {
throw new ServiceException("Can not run flowpaths.", ex1);
}
LOG.info("<<< Flowpath runs ending now.");
return total;
}
int runRepresentativeHillslopes(Executable weppserv, Grid field, boolean statsOnly, boolean parallelRuns, boolean splitSubcatchments, boolean usePassFiles) throws ServiceException, Exception {
int total = 0;
if (parallelRuns) {
LOG.info(">>> Representative hillslope parallel runs starting now." + " Stats Only " + statsOnly);
total = runRepresentativeHillslopes0(weppserv, field, statsOnly, splitSubcatchments, usePassFiles);
LOG.info("<<< Representative hillslope parallel runs ending now." + total);
return total;
} else {
String flowpathServiceURL = par.flowpathURL;
//if (flowpathServiceURL.length() == 0) {
LOG.info(">>> Representative hillslope single thread runs starting now.");
// } else {
// LOG.info(">>> Representative hillslope non-parallel runs starting now on URL: " + flowpathServiceURL);
//}
}
List<JSONObject> runningFlowpaths = new ArrayList<>();
List<Integer> runningIndex = new ArrayList<>();
try {
for (int i = 0; i < subcatchments.size(); i++) {
if (subcatchments.get(i).flowpaths.size() > 0) {
JSONObject resp = subcatchments.get(i).runRepresentativeHillslope(LOG, sessionWorkDir, weppserv, field, statsOnly, splitSubcatchments, usePassFiles);
if (resp != null) {
runningFlowpaths.add(resp);
runningIndex.add(i);
}
total++;
}
}
waitForRuns(runningFlowpaths, runningIndex);
} catch (IOException ex1) {
throw new ServiceException("Can not run representative hillslope.");
}
LOG.info("<<< Representative hillslope runs ending now.");
return total;
}
int runRepresentativeHillslopes0(Executable weppserv, Grid field, boolean statsOnly, boolean splitSubcatchments, boolean usePassFiles) throws Exception {
int total = 0;
AtomicInteger numRun = new AtomicInteger();
int nthreads = Config.getInt("weppws.fp.par", 16);
if (statsOnly) {
// no need to run parallel runs for this since it is only creating
// input files, not doing a model run
for (int i = 0; i < subcatchments.size(); i++) {
if (subcatchments.get(i).flowpaths.size() > 0) {
total += subcatchments.get(i).runRepresentativeHillslope0(sessionWorkDir, weppserv, field, statsOnly, splitSubcatchments, usePassFiles);
} else {
subcatchments.get(i).makeRepresentativeHillslopeNoData((float)field.getCellsize());
total++;
}
}
return total;
}
Parallel.run(nthreads, subcatchments.size(), new Function<Integer, Parallel.Run>() {
@Override
public Parallel.Run apply(Integer t) {
par.progress("Running " + 0 + "/" + t);
return () -> {
Subcatchment sub = subcatchments.get(t);
if (sub.flowpaths.size() > 0) {
sub.runRepresentativeHillslope0(sessionWorkDir, weppserv, field, statsOnly, splitSubcatchments, usePassFiles);
LOG.info(">>>>Representative flowpath run complete id=" + sub.repHillslopeFlowpath.id
+ " loss=" + sub.repHillslopeFlowpath.avgSoilLoss + " runoff=" + sub.repHillslopeFlowpath.avgRunoff
+ " sed=" + sub.repHillslopeFlowpath.avgSedYield);
numRun.incrementAndGet();
}
};
}
});
return numRun.get();
}
void waitForRuns(List<JSONObject> runningFlowpaths, List<Integer> runningIndex)
throws ServiceException, IOException, Exception {
int concount = runningFlowpaths.size();
while (concount > 0) {
Thread.sleep(2000);
// check the status of all running representative flowpaths
int removed = 0;
int curIdx = 0;
for (int j = 0; j < concount; j++) {
if (curIdx < runningFlowpaths.size()) {
if (runningFlowpaths.get(curIdx) != null) {
JSONObject resp = subcatchments.get(runningIndex.get(curIdx)).
checkProgress(LOG, runningFlowpaths.get(curIdx), sessionWorkDir);
if (resp == null) {
// run completed, remove from list
runningIndex.remove(curIdx);
runningFlowpaths.remove(curIdx);
removed++;
} else {
curIdx = curIdx + 1;
}
} else {
curIdx = curIdx + 1;
}
}
}
concount = concount - removed;
}
}
int runWatershed(Executable weppserv, boolean statsOnly, boolean usePassFiles) throws ServiceException, IOException {
File prjFile = new File(sessionWorkDir, "wepp.prw");
try {
buildProjectInput(prjFile, usePassFiles);
} catch (IOException | ServiceException | JSONException ex) {
throw new ServiceException("Can not build watershed project.");
}
if (statsOnly == false) {
int ret = weppserv.exec();
if (ret != 0) {
throw new ServiceException("WEPP watershed run error: " + ret);
} else {
parseOutputs(new File(sessionWorkDir, "output/weppout.txt"));
}
// if you reuse the weppservobject, you need to reinit the
// output streams, or call getRessourceExe again.
weppserv.redirectDefaults();
}
return 0;
}
int runWatershedSubarea(Executable weppserv, boolean statsOnly, int outletChannel, boolean usePassFiles) throws ServiceException, IOException {
File prjFile = new File(sessionWorkDir, "wepp.prw");
try {
buildProjectInput(prjFile, usePassFiles);
} catch (IOException | ServiceException | JSONException ex) {
throw new ServiceException("Can not build watershed project.");
}
if (statsOnly == false) {
int ret = weppserv.exec();
if (ret != 0) {
throw new ServiceException("WEPP watershed run error: " + ret);
} else {
parseOutputs(new File(sessionWorkDir, "output/weppout.txt"));
}
// if you reuse the weppservobject, you need to reinit the
// output streams, or call getRessourceExe again.
weppserv.redirectDefaults();
}
return 0;
}
int followTree(Channel chan, int lastid) {
chan.setWeppID(lastid);
lastid = lastid - 1;
if (chan.leftChannel != null)
lastid = followTree(chan.leftChannel, lastid);
if (chan.rightChannel != null)
lastid = followTree(chan.rightChannel, lastid);
if (chan.topChannel != null)
lastid = followTree(chan.topChannel, lastid);
return lastid;
}
void labelWEPPChannels() throws ServiceException {
int lastChannel = channels.size();
Channel outlet = null;
// find the outlet, this channel will have no downstream link
for (int i = 0; i < channels.size(); i++) {
if (channels.get(i).downstream == -1) {
outlet = channels.get(i);
break;
}
}
if (outlet != null) {
followTree(outlet, lastChannel);
// check that all nodes have a weppID
for (int i = 0; i < channels.size(); i++) {
if (channels.get(i).weppID <= 0) {
throw new ServiceException("Channel links incomplete.");
}
}
// Attached subcatchments to channels, for single subcatchment for
// each channel the numbers are the same.
for (int i = 0; i < channels.size(); i++) {
if (channels.get(i).weppID <= 0) {
throw new ServiceException("Channel links incomplete.");
}
for (int j = 0; j < subcatchments.size(); j++) {
if (subcatchments.get(j).id == channels.get(i).id) {
channels.get(i).setHillslope(subcatchments.get(j));
break;
}
}
}
}
}
void labelWEPPChannelsSubarea(int outletID) throws ServiceException {
int lastChannel = channels.size();
Channel outlet = null;
subarea = true;
for (int i = 0; i < channels.size(); i++) {
if (channels.get(i).id == outletID) {
outlet = channels.get(i);
break;
}
}
if (outlet != null) {
followTree(outlet, lastChannel);
relabelChannels();
// some of the channels will not have a weppID because they are not
// included in the subarea - this is ok.
// Attached subcatchments to channels, for single subcatchment for
// each channel the numbers are the same.
for (int i = 0; i < channels.size(); i++) {
// some of the channels will not have a weppID because they are not
// included in the subarea - this is ok.
if (channels.get(i).weppID > 0) {
LOG.info("*** Checking channel: " + channels.get(i).weppID + " real id: " + channels.get(i).id);
for (int j = 0; j < subcatchments.size(); j++) {
if (subcatchments.get(j).id == channels.get(i).id) {
channels.get(i).setHillslope(subcatchments.get(j));
LOG.info("Set hillslope for channel " + channels.get(i).id + " " + subcatchments.get(j).weppid);
break;
}
}
}
}
relabelHillslopes();
}
}
void relabelChannels() {
int numChannels = 0;
int minID = 9999;
for (int i = 0; i < channels.size(); i++) {
channels.get(i).setInuse(false);
if (channels.get(i).weppID > 0) {
numChannels++;
if (channels.get(i).weppID < minID) {
minID = channels.get(i).weppID;
numChannels++;
}
}
}
int adjust = minID - 1;
for (int i = 0; i < channels.size(); i++) {
if (channels.get(i).weppID > 0) {
channels.get(i).setWeppID(channels.get(i).weppID - adjust);
channels.get(i).setInuse(true);
}
}
}
void relabelHillslopes() {
int numHillslopes = 0;
int minID = 9999;
for (int i = 0; i < subcatchments.size(); i++) {
if (subcatchments.get(i).getInuse()) {
numHillslopes++;
} else {
subcatchments.get(i).weppid = -1;
}
}
int curHillslope = 1;
LOG.info(" *** Found " + numHillslopes + " subcatchments in use.");
for (int i = 0; i < subcatchments.size(); i++) {
if (subcatchments.get(i).getInuse()) {
LOG.info("Relabel subcatchment: " + subcatchments.get(i).weppid + " to " + curHillslope);
subcatchments.get(i).setWeppID(curHillslope);
curHillslope++;
}
}
}
void setInuseSubcatchments() {
for (int i = 0; i < subcatchments.size(); i++) {
subcatchments.get(i).setInuse(true);
}
}
void writeInputSummary(File f) throws IOException, ServiceException, JSONException {
JSONObject oneRot;
String elem;
double larea;
int numChannels = getNumChannels();
int numHillslopes = getNumHillslopes();
if (f.exists())
f.delete();
if (!f.createNewFile())
throw new ServiceException("Could not create Input summary file");
PrintStream o = new PrintStream(f);
JSONObject jo = new JSONObject();
jo.put("Field/Watershed Area (ac)", area * WeppConstants.CONV_HA_TO_AC);
jo.put("Number of subcatchments/representative hillslopes", numHillslopes);
jo.put("Number of channels", numChannels);
String header = jo.toString(2);
header = header.trim();
header = header.substring(0, header.length() - 1);
header = header + ",";
o.println(header);
o.println("\"Subcatchments\" : [");
int curHillslope = 0;
float percent = 0;
int scells = 0;
for (int i = 0; i < subcatchments.size(); i++) {
Subcatchment mysub = subcatchments.get(i);
if (mysub.getInuse()) {
if (!par.splitSubcatchments) {
// use TauDEM single area
elem = mysub.summarizeInput();
percent += mysub.getPercentageArea();
curHillslope++;
o.println(elem);
if (curHillslope < numHillslopes) {
o.println(",");
}
} else {
// use TOPAZ subareas TOP, LEFT, RIGHT
if (mysub.leftsub != null) {
elem = mysub.leftsub.summarizeInput(curHillslope);
percent += mysub.leftsub.getPercentageArea();
scells += mysub.leftsub.getCells();
curHillslope++;
o.println(elem);
if (curHillslope < numHillslopes) {
o.println(",");
}
}
if (mysub.rightsub != null) {
elem = mysub.rightsub.summarizeInput(curHillslope);
percent += mysub.rightsub.getPercentageArea();
scells += mysub.rightsub.getCells();
curHillslope++;
o.println(elem);
if (curHillslope < numHillslopes) {
o.println(",");
}
}
if (mysub.topsub != null) {
elem = mysub.topsub.summarizeInput(curHillslope);
percent += mysub.topsub.getPercentageArea();
scells += mysub.topsub.getCells();
curHillslope++;
o.println(elem);
if (curHillslope < numHillslopes) {
o.println(",");
}
}
}
}
}
o.println("],");
LOG.info("Check percentage of all subcatchments: " + percent);
LOG.info("Check cell count subcatchments: " + scells + " aoi cells: " + cells);
Channel mychan;
int curChan = 0;
o.println("\"Channels\" : [");
if ((isWatershed) || (par.usechannels.length > 0)) {
for (int i = 0; i < channels.size(); i++) {
mychan = null;
// for subareas the simulation will only use a fraction of the total
// number of channels, those channels with a valid weppID will be used,
// other channels outside the area are not used.
for (int j = 0; j < channels.size(); j++) {
if (channels.get(j).weppID == i) {
mychan = channels.get(j);
curChan = curChan + 1;
break;
}
}
if (mychan != null) {
elem = mychan.summarizeInput();
o.println(elem);
if (curChan < (numChannels - 1)) {
o.println(",");
}
}
}
}
o.println("],");
o.println("\"Impoundments\" : [");
if (isWatershed) {
Impoundment myimp;
for (int i = 0; i < impoundments.size(); i++) {
myimp = impoundments.get(i);
if (myimp != null) {
elem = myimp.summarizeInput();
o.println(elem);
if (i < (impoundments.size() - 1)) {
o.println(",");
}
}
}
}
o.println("],");
int numWritten = 0;
o.println("\"Landuse Summary\" : [");
for (int i = 0; i < par.managementDictAll.length(); i++) {
oneRot = par.managementDictAll.getJSONObject(i);
if (oneRot.getInt("cells") > 0) {
jo = new JSONObject();
jo.put("id", oneRot.getInt("id"));
jo.put("name", oneRot.getString("name"));
jo.put("grid cells", oneRot.getInt("cells"));
larea = (oneRot.getInt("cells") * (par.field_grid.getCellsize() * par.field_grid.getCellsize())) / 10000;
jo.put("Area (ac)", larea * WeppConstants.CONV_HA_TO_AC);
if (area > 0) {
jo.put("Percentage of total area", (larea / area) * 100);
}
if (numWritten > 0) {
o.println(",");
}
o.println(jo.toString(2));
numWritten++;
}
}
o.println("],");
o.println("\"Soils Summary\" : [");
numWritten = 0;
for (int i = 0; i < par.soilDictAll.length(); i++) {
oneRot = par.soilDictAll.getJSONObject(i);
if (oneRot.getInt("cells") > 0) {
jo = new JSONObject();
jo.put("id", oneRot.getInt("id"));
jo.put("cokey", oneRot.getString("cokey"));
jo.put("name", oneRot.getString("name"));
jo.put("grid cells", oneRot.getInt("cells"));
larea = (oneRot.getInt("cells") * (par.field_grid.getCellsize() * par.field_grid.getCellsize())) / 10000;
jo.put("Area (ac)", larea * WeppConstants.CONV_HA_TO_AC);
if (area > 0) {
jo.put("Percentage of total area", (larea / area) * 100);
}
if (numWritten > 0) {
o.println(",");
}
o.println(jo.toString(2));
numWritten++;
}
}
o.println("]");
o.println("}");
o.close();
}
void filterSubarea() {
subcatchments.removeIf(x -> (x.getInuse() == false));
channels.removeIf(x -> (x.getInuse() == false));
// recalculate watershed area
area = 0;
for (int i = 0; i < subcatchments.size(); i++) {
area += subcatchments.get(i).getAreasOfSubs();
LOG.config(" Area adding: " + i + " " + area);
}
}
void writeOutputSummary(File f) throws IOException, ServiceException, JSONException {
String elem;
if (f.exists())
f.delete();
if (!f.createNewFile())
throw new ServiceException("Could not create output summary file");
PrintStream o = new PrintStream(f);
int numChannels = getNumChannels();
int numHillslopes = getNumHillslopes();
JSONObject jo = new JSONObject();
jo.put("Field/Watershed Area (ac)", area * WeppConstants.CONV_HA_TO_AC);
jo.put("Number of subcatchments/representative hillslopes", numHillslopes);
jo.put("Number of channels", numChannels);
jo.put("Watershed discharge volume (ft^3/yr)", dischargeVol);
jo.put("Watershed sediment yield (ton/yr)", sedimentYld);
jo.put("Watershed sediment yield (ton/ac/yr)", sedimentYldArea);
jo.put("Watershed sediment delivery ratio", delRatio);
jo.put("Precipitation volume in watershed (ft^3/yr)", precipVol);
jo.put("Precipitation (in)", precip);
jo.put("Discharge at outlet (in/yr)", discharge);
int totalFlowpaths = 0;
int simFlowpaths = 0;
for (int i = 0; i < subcatchments.size(); i++) {
totalFlowpaths += subcatchments.get(i).flowpaths.size();
simFlowpaths += subcatchments.get(i).flowpathsRun;
}
jo.put("Total Number of Flowapths", totalFlowpaths);
jo.put("Flowpaths simulated", simFlowpaths);
String header = jo.toString(2);
header = header.trim();
header = header.substring(0, header.length() - 1);
header = header + ",";
o.println(header);
o.println("\"Representative hillslope subcatchment summary\" : [");
int curHillslope = 0;
for (int i = 0; i < subcatchments.size(); i++) {
Subcatchment mysub = subcatchments.get(i);
if (mysub.getInuse()) {
if (!par.splitSubcatchments) {
// use TauDEM single area
elem = mysub.summarizeOutput(LOG);
curHillslope++;
o.println(elem);
if (curHillslope < numHillslopes) {
o.println(",");
}
} else {
// use TOPAZ subareas TOP, LEFT, RIGHT
if (mysub.leftsub != null) {
elem = mysub.leftsub.summarizeOutput(LOG, curHillslope);
curHillslope++;
o.println(elem);
if (curHillslope < numHillslopes) {
o.println(",");
}
}
if (mysub.rightsub != null) {
elem = mysub.rightsub.summarizeOutput(LOG, curHillslope);
curHillslope++;
o.println(elem);
if (curHillslope < numHillslopes) {
o.println(",");
}
}
if (mysub.topsub != null) {
elem = mysub.topsub.summarizeOutput(LOG, curHillslope);
curHillslope++;
o.println(elem);
if (curHillslope < numHillslopes) {
o.println(",");
}
}
}
}
}
o.println("],");
Channel mychan;
int curChan = 0;
o.println("\"Channels\" : [");
if ((isWatershed) || (par.usechannels.length > 0)) {
for (int i = 0; i < channels.size(); i++) {
mychan = null;
// for subareas the simulation will only use a fraction of the total
// number of channels, those channels with a valid weppID will be used,
// other channels outside the area are not used.
for (int j = 0; j < channels.size(); j++) {
if (channels.get(j).weppID == i+1) {
mychan = channels.get(j);
curChan = curChan + 1;
break;
}
}
if (mychan != null) {
elem = mychan.summarizeOutput(LOG);
o.println(elem);
if (curChan < numChannels) {
o.println(",");
}
}
}
}
o.println("],");
o.println("\"Impoundments\" : [");
if (isWatershed) {
Impoundment myimp;
for (int i = 0; i < impoundments.size(); i++) {
myimp = impoundments.get(i);
if (myimp != null) {
elem = myimp.summarizeOutput(LOG);
o.println(elem);
if (i < (impoundments.size() - 1)) {
o.println(",");
}
}
}
}
o.println("]");
o.println("}");
o.close();
}
void findMajorComponents(Grid subgrid, Grid changrid, Grid soilgrid, Grid mangrid, Grid mask) throws ServiceException {
int val;
for (int i = 0; i < subcatchments.size(); i++) {
val = soilgrid.majorValue(subcatchments.get(i).id, subgrid);
if (val < 0) {
val = par.defaultSoil;
}
subcatchments.get(i).setMajorSoil(val);
val = mangrid.majorValue(subcatchments.get(i).id, subgrid);
if (val < 0) {
val = par.defaultManagement;
}
subcatchments.get(i).setMajorLanduse(val);
// count number of cells for this subcatchment which is the area
subcatchments.get(i).calcArea(subgrid, mask);
}
for (int i = 0; i < channels.size(); i++) {
val = soilgrid.majorValue(channels.get(i).id, changrid);
if (val < 0) {
val = par.defaultSoil;
}
channels.get(i).setMajorSoil(val);
val = mangrid.majorValue(channels.get(i).id, changrid);
if (val < 0) {
val = par.defaultManagement;
}
channels.get(i).setMajorLanduse(val);
// count number of cells for this channel which is the area
channels.get(i).calcArea();
}
}
void findMajorComponentsTopaz(Grid subgrid, Grid soilgrid, Grid mangrid, Grid mask) throws ServiceException {
int val;
for (int i = 0; i < subcatchments.size(); i++) {
Subcatchment mysub = subcatchments.get(i);
if (mysub != null) {
if (mysub.leftsub != null) {
val = soilgrid.majorValue(mysub.leftsub.topazid, subgrid);
if (val < 0) {
LOG.info("Failed to find soil for TOPAZ ID: " + mysub.leftsub.topazid + " " + mysub.id);
LOG.info("Deleting left subcatchment, can't determine flowpath orientations");
mysub.leftsub = null;
} else {
LOG.info("Found soil for TOPAZ ID: " + mysub.leftsub.topazid + " " + mysub.id);
}
if (mysub.leftsub != null) {
mysub.leftsub.setMajorSoil(val);
val = mangrid.majorValue(mysub.leftsub.topazid, subgrid);
if (val < 0) {
LOG.info("Failed to find management for TOPAZ ID: " + mysub.leftsub.topazid + " " + mysub.id);
LOG.info("Deleting left subcatchment, can't determine flowpath orientations");
mysub.leftsub = null;
} else {
LOG.info("Found management for TOPAZ ID: " + mysub.leftsub.topazid + " " + mysub.id);
}
if (mysub.leftsub != null) {
mysub.leftsub.setMajorLanduse(val);
mysub.leftsub.calcArea(subgrid, mask);
}
}
}
if (mysub.rightsub != null) {
val = soilgrid.majorValue(mysub.rightsub.topazid, subgrid);
if (val < 0) {
LOG.info("Failed to find soil for TOPAZ ID: " + mysub.rightsub.topazid + " " + mysub.id);
LOG.info("Deleting right subcatchment, can't determine flowpath orientations");
mysub.rightsub = null;
} else {
LOG.info("Found soil for TOPAZ ID: " + mysub.rightsub.topazid + " " + mysub.id);
}
if (mysub.rightsub != null) {
mysub.rightsub.setMajorSoil(val);
val = mangrid.majorValue(mysub.rightsub.topazid, subgrid);
if (val < 0) {
LOG.info("Failed to find management for TOPAZ ID: " + mysub.rightsub.topazid);
LOG.info("Deleting right subcatchment, can't determine flowpath orientations");
mysub.rightsub = null;
}
if (mysub.rightsub != null) {
mysub.rightsub.setMajorLanduse(val);
mysub.rightsub.calcArea(subgrid, mask);
}
}
}
if (mysub.topsub != null) {
val = soilgrid.majorValue(mysub.topsub.topazid, subgrid);
if (val < 0) {
LOG.info("Failed to find soil for TOPAZ ID: " + mysub.topsub.topazid);
LOG.info("Deleting top subcatchment, can't determine flowpath orientations");
mysub.topsub = null;
}
if (mysub.topsub != null) {
mysub.topsub.setMajorSoil(val);
val = mangrid.majorValue(mysub.topsub.topazid, subgrid);
if (val < 0) {
LOG.info("Failed to find management for TOPAZ ID: " + mysub.topsub.topazid);
LOG.info("Deleting top subcatchment, can't determine flowpath orientations");
mysub.topsub = null;
}
if (mysub.topsub != null) {
mysub.topsub.setMajorLanduse(val);
mysub.topsub.calcArea(subgrid, mask);
}
}
}
}
val = soilgrid.majorValue(subcatchments.get(i).id, subgrid);
if (val < 0)
val = par.defaultSoil;
subcatchments.get(i).setMajorSoil(val);
val = mangrid.majorValue(subcatchments.get(i).id, subgrid);
if (val < 0)
val = par.defaultManagement;
subcatchments.get(i).setMajorLanduse(val);
// count number of cells for this subcatchment which is the area
subcatchments.get(i).calcArea(subgrid, mask);
}
}
int calcArea(Grid mask) throws ServiceException {
cells = mask.cellCount(1);
area = (cells * (mask.getCellsize() * mask.getCellsize())) / 10000;
return cells;
}
int getArea() {
return cells;
}
void setChannelStart(int id, int row, int col) {
for (int i = 0; i < channels.size(); i++) {
Channel ch = channels.get(i);
if (ch.id == id)
ch.addStart(row, col);
}
}
void connectChannels() {
for (int i = 0; i < channels.size(); i++) {
Channel ch = channels.get(i);
if (ch.upstream1 != -1) {
for (int j = 0; j < channels.size(); j++) {
Channel ch1 = channels.get(j);
if (ch1.id == ch.upstream1) {
ch.topChannel = ch1;
break;
}
}
}
if (ch.upstream2 != -1) {
for (int j = 0; j < channels.size(); j++) {
Channel ch1 = channels.get(j);
if (ch1.id == ch.upstream2) {
ch.leftChannel = ch1;
break;
}
}
}
}
}
int sizeChannelsSubarea() {
int numChannels;
numChannels = 0;
for (int i = 0; i < channels.size(); i++) {
if (channels.get(i).weppID > 0) {
LOG.info(" >> Add channel: " + channels.get(i).weppID + " " + channels.get(i).id);
numChannels++;
}
}
return numChannels;
}
int sizeSubcatchmentsSubarea() {
int numSubcatchments;
numSubcatchments = 0;
for (int i = 0; i < subcatchments.size(); i++) {
if (subcatchments.get(i).getInuse()) {
LOG.info(" >> Add Subcatchment: " + subcatchments.get(i).weppid + " " + subcatchments.get(i).id);
numSubcatchments++;
}
}
return numSubcatchments;
}
int getNumImpoundments() {
int numImpoundments;
numImpoundments = impoundments.size();
return numImpoundments;
}
int getNumChannels() {
int numChannels;
if (subarea) {
numChannels = sizeChannelsSubarea();
} else {
numChannels = channels.size();
}
return numChannels;
}
int getNumHillslopes() {
int numHillslopes;
if (subarea) {
numHillslopes = sizeSubcatchmentsSubarea();
} else {
numHillslopes = subcatchments.size();
}
if (par.splitSubcatchments) {
// need to count portions of each subcatchment, may have top, left, right
// components
numHillslopes = 0;
for (int i = 0; i < subcatchments.size(); i++) {
if (subcatchments.get(i).getInuse()) {
numHillslopes += subcatchments.get(i).numTopazareas();
}
}
}
return numHillslopes;
}
protected void writeNetworkImpoundment(String id, StringBuilder output) throws ServiceException {
output.append(" " + id + " (");
int idx = Integer.parseInt(id.substring(1));
Impoundment myimp;
myimp = impoundments.get(idx - 1);
if (par.splitSubcatchments) {
output.append(myimp.getLeftHillslope()).append(", ");
output.append(myimp.getRightHillslope() + ", ");
output.append(myimp.getTopHillslope() + ", ");
} else {
output.append(myimp.getHillslope()).append(", ");
output.append("0, ");
output.append("0, ");
}
output.append(myimp.getLeftChannel() + ", ");
output.append(myimp.getRightChannel() + ", ");
output.append(myimp.getTopChannel() + ", ");
output.append(myimp.getLeftImpoundment() + ", ");
output.append(myimp.getRightImpoundment() + ", ");
output.append(myimp.getTopImpoundment() + ") # I" + myimp.id + "\n");
myimp.linked = true;
}
protected void buildProjectInput(File prjFile, boolean usePassFiles) throws IOException, ServiceException, JSONException {
int years = par.run_years;
StringBuilder output = new StringBuilder();
output.append("#\n# Watershed project from csip-weppws\n#\n");
output.append("Version = 99.1\n");
output.append("Name = csip-weppws\n");
int numChannels = getNumChannels();
int numHillslopes = getNumHillslopes();
int numImpoundments = getNumImpoundments();
output.append("Comments {\n Hillslopes=" + numHillslopes
+ " and channels=" + numChannels + " derived from TauDEM\n}\n");
output.append("Climate {\n");
output.append(" File = \"wepp.cli\"\n");
output.append("}\n");
output.append("Size = (1000,1000)\n");
output.append("Units = Meters\n");
output.append("Orientation = 0.0\n");
output.append("Scale = 1.0\n");
output.append("\nChannelDB {\n");
output.append(" File = \"channels.db\"\n");
par.writeWEPPFormatChannelData("channels.db");
//output.append(par.rawChannelDatabaseData);
output.append("\n}\n\n");
if (numImpoundments > 0) {
output.append("\nImpoundmentDB {\n");
output.append(" File = \"impoundments.db\"\n");
par.buildWEPPFormatImpoundmentData("impoundments.db");
output.append("\n}\n\n");
}
output.append("Channels {\n");
output.append(" Number = " + numChannels + "\n");
Channel mychan;
int curChan = 0;
for (int i = 1; i <= channels.size(); i++) {
mychan = null;
// for subareas the simulation will only use a fraction of the total
// number of channels, those channels with a valid weppID will be used,
// other channels outside the area are not used.
for (int j = 0; j < channels.size(); j++) {
if (channels.get(j).weppID == i) {
mychan = channels.get(j);
curChan = curChan + 1;
break;
}
}
if (mychan != null) {
output.append("C" + curChan + "{\n");
output.append(" Head = (1,1)\n");
output.append(" Tail = (1,1)\n");
if (mychan.flowpath != null) {
output.append(" Length = " + mychan.flowpath.totalLengthMeters + "\n");
} else {
output.append(" Length = 0.1\n");
}
double defaultWidth = par.getChannelWidth(mychan.order);
String defaultDef = par.getChannelName(mychan.order);
if (par.useLanduseManInChannels) {
// write default management, unless it is overridden in user
// params (which is set in the next if statement
if (mychan.userParameters != null) {
if (mychan.userParameters.optString("management", "").equals("")) {
output.append(" Management = \"" + par.manIndexToName(mychan.majorLanduse) + "\"\n");
}
} else {
output.append(" Management = \"" + par.manIndexToName(mychan.majorLanduse) + "\"\n");
}
}
if (mychan.userParameters == null) {
output.append(" Width = " + defaultWidth + "\n");
output.append(" Definition = \"" + defaultDef + "\"\n");
} else {
mychan.writeUserParameters(output, defaultWidth, defaultDef);
}
output.append(" Soil = \"");
if (!par.soilIndexToName(mychan.majorSoil).equals("")) {
output.append(par.soilIndexToName(mychan.majorSoil));
} else {
output.append("default.sol");
}
output.append("\"\n");
output.append(" Profile = {\n");
output.append(mychan.printProfile() + "\n");
output.append("}\n");
output.append(" Outlet = true\n");
output.append("}\n");
} else {
if (!subarea) {
LOG.info("Channel links incorrect, some are not set.");
throw new ServiceException("Channel links incorrect.");
}
}
}
output.append("}\n");
LOG.info("<<< Watershed project file - wrote channel section.");
output.append("Impoundments {\n");
output.append(" Number = " + impoundments.size() + "\n");
Impoundment myimp;
for (int i = 1; i <= impoundments.size(); i++) {
myimp = impoundments.get(i - 1);
output.append("I" + i + "{\n");
output.append(" Head = (1,1)\n");
output.append(" Tail = (1,1)\n");
output.append(" Height = 1\n");
output.append(" Base = 1\n");
output.append(" Direction = 0\n");
output.append(" Definition = " + "\"" + myimp.getName() + "\"\n");
output.append("}\n");
}
output.append("}\n");
LOG.info("<<< Watershed project file - wrote impoundment section.");
int curHillslope = 1;
int subs = 1;
output.append("Hillslopes {\n");
output.append(" Number = " + numHillslopes + "\n");
for (int i = 1; i <= subcatchments.size(); i++) {
Subcatchment mysub = null;
for (int j = 0; j < subcatchments.size(); j++) {
if (subcatchments.get(j).weppid == i) {
mysub = subcatchments.get(j);
if (par.splitSubcatchments) {
subs = mysub.numTopazareas();
}
mysub.setWeppAltID(curHillslope);
break;
}
}
if (mysub != null) {
if (!par.splitSubcatchments) {
// use TauDEM single area
writeOneHillslope(output, curHillslope++, mysub, null);
} else {
// use TOPAZ subareas TOP, LEFT, RIGHT
if (mysub.leftsub != null) {
LOG.info("< Writing Left Subcatchment: " + mysub.id + " " +mysub.leftsub.id);
mysub.leftsub.setWeppAltID(curHillslope);
writeOneHillslope(output, curHillslope++, mysub, mysub.leftsub);
}
if (mysub.rightsub != null) {
LOG.info("< Writing Right Subcatchment: " + mysub.id + " " +mysub.rightsub.id);
mysub.rightsub.setWeppAltID(curHillslope);
writeOneHillslope(output, curHillslope++, mysub, mysub.rightsub);
}
if (mysub.topsub != null) {
LOG.info("< Writing Top Subcatchment: " + mysub.id + " " + mysub.topsub.id);
mysub.topsub.setWeppAltID(curHillslope);
writeOneHillslope(output, curHillslope++, mysub, mysub.topsub);
}
}
}
}
output.append("}\n");
LOG.info("<<< Step 4 - Wrote hillslope section");
curChan = 0;
output.append("Network {\n");
// hillslopes (left,right,top) channels (left, right, top) impoundments (left,right, top)
int total = channels.size() + impoundments.size();
for (int i = 1; i <= channels.size(); i++) {
// a downstream element must have a higher number than what is flowing into it.
// The element number is implicit, it relys on the output order.
// The channels are already ordered correcly, need to merge in the impoundments.
mychan = null;
for (int j = 0; j < channels.size(); j++) {
if (channels.get(j).weppID == i) {
mychan = channels.get(j);
curChan = curChan + 1;
break;
}
}
if (mychan != null) {
// check if any impoundments need to come before this entry
if (!mychan.getLeftImpoundment().equals("0")) {
writeNetworkImpoundment(mychan.getLeftImpoundment(), output);
}
if (!mychan.getRightImpoundment().equals("0")) {
writeNetworkImpoundment(mychan.getRightImpoundment(), output);
}
if (!mychan.getTopImpoundment().equals("0")) {
writeNetworkImpoundment(mychan.getTopImpoundment(), output);
}
// It is now safe to write out the channel
output.append(" C" + curChan + " (");
if (par.splitSubcatchments) {
output.append(mychan.getLeftHillslope()).append(", ");
output.append(mychan.getRightHillslope() + ", ");
output.append(mychan.getTopHillslope() + ", ");
} else {
output.append(mychan.getHillslope()).append(", ");
output.append("0, ");
output.append("0, ");
}
output.append(mychan.getLeftChannel() + ", ");
output.append(mychan.getRightChannel() + ", ");
output.append(mychan.getTopChannel() + ", ");
output.append(mychan.getLeftImpoundment() + ", ");
output.append(mychan.getRightImpoundment() + ", ");
output.append(mychan.getTopImpoundment() + ") # C" + mychan.id + "\n");
} else {
if (!subarea) {
LOG.info("Channel links incorrect, setting network.");
throw new ServiceException("Channel links incorrect, network.");
}
}
}
// It is possible that there is an impoundment that does not have any channels
// flowing into it (it at the outlet. This would be the last line.
for (int i = 1; i <= impoundments.size(); i++) {
myimp = impoundments.get(i - 1);
if (!myimp.linked) {
writeNetworkImpoundment("I" + String.valueOf(i), output);
}
}
output.append("}\n");
LOG.info("<<< Step 5 - Wrote network section.");
output.append("RunOptions {\n");
output.append(" SoilLossOutputType = 1\n");
output.append(" SoilLossOutputFile = AutoName\n");
output.append(" EventFile = AutoName\n");
output.append(" PlotFile = AutoName\n");
output.append(" SimulationYears = " + years + "\n");
output.append(" CalcMethod = " + par.runoffCalculation + "\n");
output.append(" LenWidthRatio = 1.0\n");
output.append(" ChanErodFlag = " + par.chanErodFlag + "\n");
output.append("}\n");
FileUtils.writeStringToFile(prjFile, output.toString(), "UTF-8");
}
void writeOneHillslope(StringBuilder output, int curHillslope, Subcatchment mysub, SubcatchmentSubarea mysub2) throws ServiceException {
String msoils;
String mlanduse;
output.append(" H" + curHillslope + "{\n");
output.append(" File = \"ww2_H" + curHillslope + "\" {\n");
output.append(" Landuse = 1\n");
if (mysub2 == null) {
if (mysub.repHillslopeFlowpath == null) {
LOG.info("No Representative hillslope: " + curHillslope + " (" + mysub.id + ") need to check TauDEM grids for non contiguous cells.");
}
output.append(" Length = " + mysub.getRepHillslopeLength() + "\n");
} else {
output.append(" Length = " + mysub2.getRepHillslopeLength() + "\n");
}
output.append(" Profile {\n");
output.append(" Data {\n");
if (mysub2 == null) {
output.append(mysub.printProfile() + "\n");
} else {
output.append(mysub2.printProfile() + "\n");
}
output.append(" }\n");
output.append(" }\n");
output.append("Climate {\n");
output.append(" File = \"wepp.cli\"\n");
output.append("}\n");
output.append("Soil {\n");
output.append(" Breaks = 0\n");
output.append(" default {\n");
if (mysub2 == null) {
output.append(" Distance = " + mysub.getRepHillslopeLength() + "\n");
msoils = mysub.majorSoilName();
if (msoils != null) {
output.append(" File = \"" + msoils + "\"\n");
} else {
LOG.info("Can't get major soil (mysub) for hillslope " + curHillslope);
}
} else {
output.append(" Distance = " + mysub2.getRepHillslopeLength() + "\n");
msoils = mysub2.majorSoilName();
if (msoils != null) {
output.append(" File = \"" + msoils + "\"\n");
} else {
LOG.info("Can't get major soil (mysub2) for hillslope " + curHillslope);
}
}
output.append(" }\n");
output.append("}\n");
output.append("Management {\n");
output.append(" Breaks = 0\n");
output.append(" default {\n");
if (mysub2 == null) {
output.append(" Distance = " + mysub.getRepHillslopeLength() + "\n");
mlanduse = mysub.majorLanduseName();
if (mlanduse != null) {
output.append(" File = \"" + mlanduse + "\"\n");
} else {
LOG.info("Can't get major landuse (mysub) for hillslope " + curHillslope);
}
} else {
output.append(" Distance = " + mysub2.getRepHillslopeLength() + "\n");
mlanduse = mysub2.majorLanduseName();
if (mlanduse != null) {
output.append(" File = \"" + mlanduse + "\"\n");
} else {
LOG.info("Can't get major landuse (mysub2) for hillslope " + curHillslope);
}
}
output.append(" }\n");
output.append("}\n");
output.append("RunOptions {\n");
output.append(" Version = 1\n");
output.append(" SoilLossOutputType = 1\n");
output.append(" SoilLosOutputFile = AutoName\n");
output.append(" PlotFile = AutoName\n");
output.append(" SimulationYears = " + par.run_years + "\n");
output.append(" SmallEventByPass = 1\n");
output.append("}\n");
output.append("}\n");
output.append(" Head = (400,400)\n");
output.append(" Direction = 30\n");
output.append(" Angle = 90\n ");
if (mysub2 == null) {
output.append(" Base = " + mysub.getRepHillslopeWidth() + "\n");
output.append(" Height = " + mysub.getRepHillslopeLength() + "\n");
} else {
output.append(" Base = " + mysub2.getRepHillslopeWidth() + "\n");
output.append(" Height = " + mysub2.getRepHillslopeLength() + "\n");
}
output.append(" Polygon = 5 {\n");
output.append(" (408.0,577.0) (406.0,371.0) (287.0,373.0) (290.0,579.0) (408.0,577.0)\n");
output.append("}\n");
output.append("}\n");
}
void classifyFlowpaths() {
LOG.info(">>> Classify Flowpath runs starting now.");
for (int i = 0; i < subcatchments.size(); i++) {
subcatchments.get(i).classifyFlowpaths(LOG);
}
LOG.info("<<< Classify Flowpath ending now.");
}
protected int findPrevChannelCellDir(int chnEnd, int chnEndRow, int chnEndCol) {
int prev = -1;
for (int i = 0; i < channels.size(); i++) {
Channel ch = channels.get(i);
if (ch.id == chnEnd) {
prev = ch.getPrevDir(chnEndRow, chnEndCol);
}
}
return prev;
}
public void parseOutputs(File resultsFile) throws IOException {
float sedYield, runoff;
StringBuilder fileContents = new StringBuilder();
String cellOutputs;
try (BufferedReader reader = new BufferedReader(new FileReader(resultsFile))) {
String line = null;
while ((line = reader.readLine()) != null) {
fileContents.append(line);
}
reader.close();
JSONObject results = new JSONObject(fileContents.toString());
if (results == null || !results.has("RESULTS")) {
throw new IOException("The format of the results output file could not be read. Contents missing or \"RESULTS\" xml tag not found.");
}
results = results.optJSONObject("RESULTS");
precip = (float) results.optDouble("PRECIP_IN", -999);
dischargeVol = (float) results.optDouble("DISCHARGE_FT3", -999);
sedimentYld = (float) results.optDouble("SEDIMENT_YLD_TON", -999);
sedimentYldArea = (float) results.optDouble("SEDIMENT_UNIT_TONACYR", -999);
delRatio = (float) results.optDouble("DEL_RATIO", -999);
precipVol = (float) results.optDouble("PRECIP_FT3", -999);
discharge = (float) results.optDouble("DISCHARGE_IN", -999);
int id;
Channel tempChan;
JSONArray chns = results.getJSONArray("CHANNELS");
for (int i = 0; i < chns.length(); i++) {
JSONObject chan = chns.optJSONObject(i);
id = chan.getInt("ID");
for (int j = 0; j < channels.size(); j++) {
tempChan = channels.get(j);
if (tempChan.weppID == id) {
tempChan.length = chan.getDouble("LENGTH_FT");
tempChan.discharge = chan.getDouble("DISCHARGE_FT3");
tempChan.sedYield = chan.getDouble("SED_YIELD_TON");
}
}
}
Impoundment tempImpound;
JSONArray imps = results.getJSONArray("IMPOUNDMENTS");
for (int i = 0; i < imps.length(); i++) {
JSONObject onei = imps.optJSONObject(i);
id = onei.getInt("ID");
for (int j = 0; j < impoundments.size(); j++) {
tempImpound = impoundments.get(j);
if (tempImpound.weppID == id) {
tempImpound.discharge = onei.getDouble("DISCHARGE_FT3");
tempImpound.sedYield = onei.getDouble("SED_YIELD_TON");
}
}
}
JSONArray hills = results.getJSONArray("HILLSLOPES");
Subcatchment tempSub;
int validHills = 0;
for (int i = 0; i < hills.length(); i++) {
JSONObject hill = hills.optJSONObject(i);
id = hill.getInt("ID");
if (!par.splitSubcatchments) {
for (int j = 0; j < subcatchments.size(); j++) {
tempSub = subcatchments.get(j);
if (tempSub.weppid == id) {
//tempSub.length = hill.getDouble("LENGTH_FT");
tempSub.avgRunoff = (float) hill.getDouble("RUNOFF_IN");
tempSub.avgSedYield = (float) hill.getDouble("SED_YIELD_TONAC");
tempSub.avgSoilLoss = (float) hill.getDouble("SOIL_LOSS_TONAC");
}
}
} else {
boolean found = false;
for (int j = 0; j < subcatchments.size(); j++) {
tempSub = subcatchments.get(j);
if (tempSub.getInuse()) {
if (tempSub.leftsub != null) {
if (tempSub.leftsub.getWeppAltID() == id) {
tempSub.leftsub.avgRunoff = (float) hill.getDouble("RUNOFF_IN");
tempSub.leftsub.avgSedYield = (float) hill.getDouble("SED_YIELD_TONAC");
tempSub.leftsub.avgSoilLoss = (float) hill.getDouble("SOIL_LOSS_TONAC");
validHills++;
found = true;
}
}
if (tempSub.rightsub != null) {
if (tempSub.rightsub.getWeppAltID() == id) {
tempSub.rightsub.avgRunoff = (float) hill.getDouble("RUNOFF_IN");
tempSub.rightsub.avgSedYield = (float) hill.getDouble("SED_YIELD_TONAC");
tempSub.rightsub.avgSoilLoss = (float) hill.getDouble("SOIL_LOSS_TONAC");
validHills++;
found = true;
}
}
if (tempSub.topsub != null) {
if (tempSub.topsub.getWeppAltID() == id) {
tempSub.topsub.avgRunoff = (float) hill.getDouble("RUNOFF_IN");
tempSub.topsub.avgSedYield = (float) hill.getDouble("SED_YIELD_TONAC");
tempSub.topsub.avgSoilLoss = (float) hill.getDouble("SOIL_LOSS_TONAC");
validHills++;
found = true;
}
}
} else {
LOG.info("Omitted hillslope, not used: " + tempSub.id);
}
}
if (found == false)
LOG.info("**** ERROR: ID not found: " + id);
}
}
LOG.info("Parsed " + validHills + " hillslopes.");
/*
* avgSoilLoss = (float) results.optDouble("LOSS"); avgSedYield = (float)
* results.optDouble("SEDYIELD"); avgRunoff = (float)
* results.optDouble("RUNOFF"); wspar.weppVersion =
* results.getString("WEPP_VERSION"); wspar.preVersion =
* results.getString("PREPROCESSOR_VERSION"); * cellOutputs = new
* String(Files.readAllBytes(plotFile.toPath()));
* readLossPlotData(cellOutputs);
*/
} catch (Exception e) {
precip = (float) -999;
}
}
Grid createSubareaMask(Grid field_grid, Grid subcatch_grid) throws ServiceException, IOException {
List<Integer> chs = new ArrayList<>();
for (int i = 0; i < channels.size(); i++) {
if (channels.get(i).getInuse() == true)
chs.add(channels.get(i).id);
}
int[] vals = chs.stream().mapToInt(i -> i).toArray();
field_grid.clear();
String vstr = Arrays.toString(vals);
LOG.info("**** Setting createSubareaMask: " + vstr);
field_grid.maskSubareas(subcatch_grid, vals, 1);
field_grid.writeGrid(new File(sessionWorkDir, "fieldgrid2.asc"));
return field_grid;
}
void setTopazIDs() throws ServiceException {
int topazid = 14;
for (int i = 0; i < channels.size(); i++) {
if (channels.get(i).getInuse() == true) {
Channel ch = channels.get(i);
ch.setTopazID(LOG,topazid);
topazid += 10;
}
}
}
void modifySingleChannel(String id, JSONObject chdata) throws JSONException {
int myid = Integer.parseInt(id);
for (int i = 0; i < channels.size(); i++) {
Channel ch = channels.get(i);
if (ch.id == myid)
ch.updateParameters(chdata);
}
}
boolean usesChannelParms(String id) {
for (int i = 0; i < channels.size(); i++) {
Channel ch = channels.get(i);
if (ch.usesChannelParms(id))
return true;
}
return false;
}
boolean usesImpoundmentParms(String id) {
for (int i = 0; i < impoundments.size(); i++) {
Impoundment imp = impoundments.get(i);
if (imp.name.equals(id))
return true;
}
return false;
}
Channel getChannel(int id) {
for (int i = 0; i < channels.size(); i++) {
Channel ch = channels.get(i);
if (channels.get(i).id == id)
return ch;
}
return null;
}
int getImpoundmentBeforeChannel(int id) {
for (int i = 0; i < impoundments.size(); i++) {
Impoundment imp = impoundments.get(i);
if (impoundments.get(i).chanid == id) {
if (imp.position.equals("before-channel"))
return imp.id;
}
}
return 0;
}
void linkImpoundmentToChannel(Impoundment imp) {
for (int i = 0; i < channels.size(); i++) {
Channel ch = channels.get(i);
if (ch.id == imp.chanid) {
if (imp.position.equals("before-channel")) {
ch.setTopImpoundment(imp);
} else if (imp.position.equals("left-side")) {
ch.setLeftImpoundment(imp);
} else if (imp.position.equals("right-side")) {
ch.setRightImpoundment(imp);
}
}
}
}
int getImpoundmentAfterChannel(int id) {
for (int i = 0; i < impoundments.size(); i++) {
Impoundment imp = impoundments.get(i);
if (impoundments.get(i).chanid == id) {
if (imp.position.equals("after-channel"))
return imp.id;
}
}
return 0;
}
int getImpoundmentWeppIDAfterChannel(int id) {
for (int i = 0; i < impoundments.size(); i++) {
Impoundment imp = impoundments.get(i);
if (impoundments.get(i).chanid == id) {
if (imp.position.equals("after-channel"))
return imp.weppID;
}
}
return 0;
}
}