V2_0.java [src/java/m/rhem/rhem01_runmodel] Revision: e405ebb4d28292bd49a17ecad3275e581e8223fb Date: Wed Jan 27 13:13:12 MST 2021
/*
* $Id$
*
* This file is part of the Cloud Services Integration Platform (CSIP),
* a Model-as-a-Service framework, API, and application suite.
*
* 2012-2020, OMSLab, Colorado State University.
*
* OMSLab licenses this file to you under the MIT license.
* See the LICENSE file in the project root for more information.
*/
package m.rhem.rhem01_runmodel;
import csip.Config;
import csip.Executable;
import csip.ModelDataService;
import csip.ModelDataServiceCall;
import csip.PayloadParameter;
import csip.ServiceException;
import csip.annotations.Polling;
import csip.annotations.Resource;
import java.io.IOException;
import java.sql.Connection;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.ws.rs.Path;
import m.rhem.model.AoA;
import m.rhem.model.Parameter;
import m.rhem.model.RhemModel;
import csip.annotations.Description;
import csip.annotations.Name;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import rhem.utils.DBResources;
import rhem.utils.RhemResources;
import static rhem.utils.RhemResources.RHEM4_INTL_EXE;
/**
* RHEM-01:Run RHEM Model
*
* @version 2.0
* @author <a href="mailto:shaun.case@colostate.edu">Shaun Case</a>
*/
@Name("RHEM-01:Run RHEM Model")
@Description("Run RHEM Model utilizing parameters including climate station, "
+ "surface soil texture class, slope percent and length, and vegetative "
+ "cover characteristics (bunchgrass, forbs/annual, shrub, and sodgrass "
+ "foliar cover; plant basal cover; rock cover; litter cover; and "
+ "cryptogam cover. This version uses PRISM/cligen")
@Path("m/rhem/runrhem/2.0")
@Polling(first = 10000, next = 2000)
@Resource(from = DBResources.class)
@Resource(from = RhemResources.class)
public class V2_0 extends ModelDataService {
private static final int DEFAULT_MOISTURE_CONTENT = 25;
private static final double DEFAULT_SLOPE_LENGTH_1 = 50.0;
private static final double DEFAULT_SLOPE_LENGTH_2 = 164.04;
private static final double DEFAULT_MINIMUM_SLOPE_STEEPNESS = 0.01;
private AoA aoa;
private String parameterFileName;
private String stormFileName;
private String summaryFileName;
private String runFileName;
private String detailedOutputFileName;
private Parameter parameter;
// String cligen_db = Config.getString("rhem.cligen_db",
// "file:/Users/rumpal/Documents/Work/csipDocuments/RHEM/cligen");
static String cligenUrl = Config.getString("rhem.cligen.url",
"http://csip.engr.colostate.edu:8083/csip-climate/m/cligen_prism/weps/1.0");
public static final String KEY_LATITUDE = "latitude";
public static final String KEY_LONGITUDE = "longitude";
RhemModel rhemModel;
int unit;
double lat;
double lon;
@Override
public void preProcess() throws ServiceException {
PayloadParameter parameters = parameter();
int aoaId = parameters.getInt("AoAID", 0);
int rhemSiteId = parameters.getInt("rhem_site_id", 0);
lat = parameter().getDouble(KEY_LATITUDE);
lon = parameter().getDouble(KEY_LONGITUDE);
String scenarioName = parameters.getString("scenarioname");
String scenarioDescription = parameters.getString("scenariodescription");
unit = parameters.getInt("units");
// will go away
String stateId = parameters.getString("stateid", "");
String climatestationId = parameters.getString("climatestationid", "");
String soilTexture = parameters.getString("soiltexture");
String slopeShape = parameters.getString("slopeshape");
double slopeSteepness = parameters.getDouble("slopesteepness", DEFAULT_MINIMUM_SLOPE_STEEPNESS);
double bunchGgrassCanopyCover = parameters.getDouble("bunchgrasscanopycover", 0.0);
double forbsCanopyCover = parameters.getDouble("forbscanopycover", 0.0);
double shrubsCanopyCover = parameters.getDouble("shrubscanopycover", 0.0);
double sodGrassCanopyCover = parameters.getDouble("sodgrasscanopycover", 0.0);
double basalCover = parameters.getDouble("basalcover", 0.0);
double rockCover = parameters.getDouble("rockcover", 0.0);
double litterCover = parameters.getDouble("littercover", 0.0);
double cryptogamsCover = parameters.getDouble("cryptogamscover", 0.0);
double sar = parameters.getDouble("sar", 0.0);
///////////////////////////////
// BEGIN Validations of input
//The values allowed for the field unit in the request are 1 and 2. 1 is for metric units and 2 is for English units
if (sar < 0.0 || sar > 50.0) {
throw new ServiceException("invalid sar (0.0 ... 50.0): " + sar);
}
double slopeLength;
switch (unit) {
case 1:
slopeLength = DEFAULT_SLOPE_LENGTH_1;
break;
case 2:
slopeLength = DEFAULT_SLOPE_LENGTH_2;
break;
default:
throw new ServiceException("Unit should be 1-metric or 2-English. The value, " + unit + ", is not valid.");
}
if (slopeSteepness <= 0.0) {
throw new ServiceException("The slopesteepness input parameter must be greater than 0.");
}
// END Validations
///////////////////////////////
aoa = new AoA(aoaId, rhemSiteId, scenarioName,
scenarioDescription, unit, stateId, climatestationId,
soilTexture, slopeLength, slopeShape, slopeSteepness,
bunchGgrassCanopyCover, forbsCanopyCover, shrubsCanopyCover,
sodGrassCanopyCover, basalCover, rockCover, litterCover,
cryptogamsCover, DEFAULT_MOISTURE_CONTENT, sar);
}
@Override
public void doProcess() throws Exception {
// Files.createSymbolicLink(
// workspace().getFile(stormFileName).toPath(),
// workspace().getFile("cli_gen.cli").toPath());
String now = new SimpleDateFormat("MMMM dd, YYYY, hh:mm a").format(new Date());
String fileName = aoa.getScenarioName();
if (fileName.length() > 15) {
fileName = fileName.substring(0, 15);
}
fileName = fileName.replace(' ', '_');
parameterFileName = "scenario_input_" + fileName + ".par";
stormFileName = "storm_input_" + fileName + ".pre";
summaryFileName = "scenario_output_summary_" + fileName + ".sum";
detailedOutputFileName = "scenario_output_summary_" + fileName + ".out";
runFileName = fileName + ".run";
parameter = new Parameter(aoa);
try (Connection connection = resources().getJDBC(DBResources.CRDB)) {
parameter.computeParameters(connection);
}
rhemModel = new RhemModel(aoa.getStateId(), aoa.getClimateStationId(),
aoa.getScenarioName(), now, workspace().getDir(), parameterFileName,
stormFileName, runFileName, summaryFileName);
rhemModel.generateParamFile(parameter);
// rhemModel.generateStormFile(cligen_db, Double.parseDouble(parameter.getKe()));
fetchClimate(stormFileName);
rhemModel.generateRunFile();
runModel();
//If the run is successful then edit the summary file.
// if (!rhemModel.isIntl()) {
//// avgYearlyPrecip = rhemModel.getYearlyPrecipIntl();
//// } else {
// double avgYearlyPrecip = 0.0;
// try (Connection connection = resources().getJDBC(DBResources.CRDB);
// Statement statement = connection.createStatement();) {
// try (ResultSet rs = statement.executeQuery(DBResources.RHEM01Query02(aoa.getClimateStationId()))) {
// while (rs.next()) {
// avgYearlyPrecip = rs.getDouble("avg_yearly_precip_mm");
// }
// }
// }
// rhemModel.appendToSumFile(avgYearlyPrecip);
// }
}
private void fetchClimate(String stormfileName) throws JSONException, Exception {
ModelDataServiceCall res = new ModelDataServiceCall()
.put("duration", 300)
.put("outputFile", "cli_gen.cli")
.put("usePRISM", true)
.put("input_zone_features", new JSONObject(
"{ 'type': 'FeatureCollection',"
+ " 'features': [{"
+ " 'type': 'Feature',"
+ " 'properties': {"
+ " 'name': 'pt one',"
+ " 'gid': 1"
+ " },"
+ " 'geometry': {"
+ " 'type': 'Point',"
+ " 'coordinates': ["
+ " " + lon + ","
+ " " + lat
+ " ]"
+ " }"
+ " }]"
+ " }"))
.url(cligenUrl)
.withDefaultLogger()
.call();
if (res.serviceFinished()) {
res.download("cli_gen.cli", workspace().getFile(stormfileName));
results().put("cli_state", res.getInt("state", 0));
results().put("cli_stationId", res.getInt("stationId", 0));
results().put("cli_station_name", res.getString("name", "?"));
// modelRun.setCliStationLong(res.getDouble("stationX", 0.0));
// modelRun.setCliStationLat(res.getDouble("stationY", 0.0));
// modelRun.setCliStationStateFips(res.getInt("state", 0));
// modelRun.setCliStationC1(res.getInt("stationId", 0));
// modelRun.setCliStationName(res.getString("name", "no name"));
// modelRun.setCliStationEleM(res.getDouble("elevation", 0.0));
} else {
throw new ServiceException("Climate service error: " + res.getError());
}
}
private void runModel() throws ServiceException, IOException {
// Executable rh = resources().getExe(rhemModel.isIntl() ? RHEM4_INTL_EXE : RHEM4_EXE);
Executable rh = resources().getExe(RHEM4_INTL_EXE);
rh.setArguments("-b", workspace().getFile(runFileName));
int run = rh.exec();
if (run != 0) {
throw new ServiceException("Error running rhem: " + run);
}
}
@Override
public void postProcess() {
results().put("AoAID", aoa.getAoaId(), "Area of Analysis Identifier");
results().put("rhem_site_id", aoa.getRhemSiteId(), "RHEM Evaluation Site Identifier");
results().put("CLEN", parameter.getClen(), "characteristic length of hillsope");
results().put("UNITS", (unit == 1) ? "metric" : "English", "unit of measure, metric or English");
results().put("DIAMS", parameter.getDiams(), "list of representative soil particle diameters for up to 5 particle classes");
results().put("DENSITY", parameter.getDensity(), "list of densities corresponding to the DIAMS particle classes");
results().put("CHEZY", parameter.getChezy(), "overland flow Chezy coefficient");
results().put("RCHEZY", parameter.getRchezy(), "concentrated flow Chezy coefficient");
results().put("SL", parameter.getSl(), "slope expressed as fractional rise/run");
results().put("SX", parameter.getSx(), "normalized distance");
results().put("KSS", parameter.getKss(), "splash and sheet erodibility coefficient");
results().put("KE", parameter.getKe(), "effective hydraulic conductivity");
results().put("G", parameter.getG(), "mean capillary drive");
results().put("DIST", parameter.getDist(), "pore size distribution index");
results().put("POR", parameter.getPor(), "porosity");
results().put("FRACT", parameter.getFract(), "list of particle class fractions");
results().put("TDS", rhemModel.getTDS(), "total dissolved solids");
results().put(workspace().getFile(parameterFileName), "Parameter input file");
results().put(workspace().getFile(stormFileName), "Storm input file");
results().put(workspace().getFile(summaryFileName), "Summary file");
results().put(workspace().getFile(detailedOutputFileName), "Detailed summary file");
// results().put(getWorkspaceFile("temp_" + summaryFileName), "Temp Summary file");
}
}