StandardStepMethod.java [src/java/hydraulics] Revision: b1a7e551b0536e3210dc7b1b7211cca8080fd9f2 Date: Tue Aug 04 11:33:25 MDT 2015
package hydraulics;
import java.awt.Color;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.io.IOException;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.chart.title.LegendTitle;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
public class StandardStepMethod {
boolean irregularGeometry =false;
//Downstream x-section characteristics
double bottomWidth = 10;
double sideSlope = 2;
double measuredDownstreamDepth = 7;
double discharge_DS = 200;
//Reach Characteristics
double manning_n = .035;
double bedSlope = 0.0004;
double seepage = 0;
boolean downstream = true; //Designates whether the water surface profile
//is being calculated up or downstream from the original sample location
//(designated x-section 0). True if downstream/False if upstream.
double channelLength = 20000; //Distance between sample x-sections
double reachLength = 100; //Length between calculated x-section
String subFolder = "Test2";
//String subFolder = "ChinExample4_11";
String mainFolder = "C:/Users/Chris/My Documents/StandardStepMethod" + File.separator + subFolder ;
//Sets
public void setBottomWidth(double bottomWidth){
this.bottomWidth = bottomWidth;
}
public void setSideSlope(double sideSlope){
this.sideSlope = sideSlope;
}
public void setDepth_DS(double measuredDownstreamDepth){
this.measuredDownstreamDepth = measuredDownstreamDepth;
}
public void setdischarge_DS(double discharge_DS){
this.discharge_DS = discharge_DS;
}
public void setManningRoughness(double manning_n){
this.manning_n = manning_n;
}
public void setBedSlope(double bedSlope){
this.bedSlope = bedSlope;
}
public void setSeepage(double seepage){
this.seepage = seepage;
}
public void setChannelLength(double channelLength){
this.channelLength = channelLength;
}
public void setReachLength(double reachLength){
this.reachLength = reachLength;
}
public void setMainFolder(String mainFolder){
this.mainFolder = mainFolder;
}
public void setSubFolder(String subFolder){
this.subFolder = subFolder;
}
public void setStreamDirection(boolean downstream){
this.downstream = downstream;
}
//gets
public String getElevationGraphTitle(){
return "Longitudinal Elevation Profile";
}
public String getDepthGraphTitle(){
return "Longitudinal Depth Profile";
}
public String getElevationGraphOutputName(){
if (downstream){
return subFolder + " Downstream Longitudinal Elevation Profile.png";
}
else{
return subFolder + " Upstream Longitudinal Elevation Profile.png";
}
}
public String getDepthGraphOutputName(){
if (downstream){
return subFolder + " Downstream Longitudinal Depth Profile.png";
}
else{
return subFolder + " Upstream Longitudinal Depth Profile.png";
}
}
public String getSummaryTitle(){
if (downstream){
return subFolder + " Downstream Summary Data.txt";
}
else{
return subFolder + " Upstream Summary Data.txt";
}
}
public String getSummaryOuputName(){
if (downstream){
return subFolder + " Downstream Summary Data.txt";
}
else{
return subFolder + " Upstream Summary Data.txt";
}
}
public static void main(String[] args) throws IOException {
StandardStepMethod model = new StandardStepMethod();
model.run();
}
public void run() throws IOException {
calcStandardStepMethod();
} //end of run
public void calcStandardStepMethod() throws IOException {
int numberOfReaches;
if (irregularGeometry) {
numberOfReaches = readLines(mainFolder + File.separator + "reaches.txt");
} else {
double numReach = channelLength / reachLength;
if (numReach == Math.floor(numReach) && !Double.isInfinite(numReach)) {
numberOfReaches = (int) numReach;
} else {
System.out.println("Variable reachLength must be factor of channelLength");
numberOfReaches = 1;
}
}
double[][][] elevationArray = new double[numberOfReaches + 1][2][4];
double[][][] depthArray = new double[numberOfReaches + 1][2][4];
double downstreamDistance = 0;
double bedElevation = 0;
double depth_DS = measuredDownstreamDepth;
for (int currentReach = 0; currentReach < numberOfReaches; currentReach++) {
double length;
if (irregularGeometry) {
double[][] reachProperties = setReachProperties();
length = reachProperties[currentReach][0];
} else {
length = reachLength;
}
double reachSlope;
if (irregularGeometry) {
double[][] reachProperties = setReachProperties();
reachSlope = reachProperties[currentReach][1];
} else {
reachSlope = bedSlope;
}
if (downstream == false){
length = -length;
}
ChannelGeometry DSValues = setDSValues(currentReach,depth_DS);
double velocity_DS = calcVelocity(DSValues);
double frictionSlope_DS = calcFrictionSlope(DSValues);
double critDepth_DS = DSValues.calcCriticalDepth();
double normDepth_DS = DSValues.calcNormalDepth();
ChannelGeometry USValues = setUSValues(currentReach,depth_DS);
double critDepth_US = USValues.calcCriticalDepth();
double normDepth_US = USValues.calcNormalDepth();
double[] bounds = calcBoundaryConditions(depth_DS, critDepth_US, normDepth_US);
double lower = bounds[0];
double upper = bounds[1];
USValues = setUSValues(currentReach,lower);
double velocity_US = calcVelocity(USValues);
double frictionSlope_US = calcFrictionSlope(USValues);
double err_lower = standardStepEquation(velocity_DS,
velocity_US,
frictionSlope_DS,
frictionSlope_US,
depth_DS,
lower,
reachSlope,
length);
USValues = setUSValues(currentReach,upper);
velocity_US = calcVelocity(USValues);
frictionSlope_US = calcFrictionSlope(USValues);
double err_upper = standardStepEquation(velocity_DS,
velocity_US,
frictionSlope_DS,
frictionSlope_US,
depth_DS,
upper,
reachSlope,
length);
double error = 1000;
double guessDepth_US = (lower + upper) / 2;
int ctr = 0;
if (err_lower > 0 && err_upper < 0) {
while (Math.abs(error) > .0001 && ctr < 100) {
guessDepth_US = (lower + upper) / 2;
USValues = setUSValues(currentReach,guessDepth_US);
velocity_US = calcVelocity(USValues);
frictionSlope_US = calcFrictionSlope(USValues);
error = standardStepEquation(velocity_DS, velocity_US,
frictionSlope_DS, frictionSlope_US,
depth_DS, guessDepth_US,
reachSlope,
length);
if (error <= 0) {
upper = guessDepth_US;
} else {
lower = guessDepth_US;
}
ctr = ctr + 1;
}
} else if (err_lower < 0 && err_upper > 0) {
while (Math.abs(error) > .0001 && ctr < 100) {
guessDepth_US = (lower + upper) / 2;
USValues = setUSValues(currentReach,guessDepth_US);
velocity_US = calcVelocity(USValues);
frictionSlope_US = calcFrictionSlope(USValues);
error = standardStepEquation(velocity_DS, velocity_US,
frictionSlope_DS, frictionSlope_US,
depth_DS, guessDepth_US,
reachSlope,
length);
if (error >= 0) {
upper = guessDepth_US;
} else {
lower = guessDepth_US;
}
ctr = ctr + 1;
}
} else {
guessDepth_US = (lower + upper) / 2;
System.out.println("****Could not solve standard step equation****");
}
boolean append_to_file;
if (currentReach == 0) {
elevationArray[currentReach] = writeElevationArray(depth_DS,
critDepth_DS,
normDepth_DS,
downstreamDistance,
bedElevation);
depthArray[currentReach] = writeDepthArray(depth_DS,
critDepth_DS,
normDepth_DS,
downstreamDistance,
bedElevation);
append_to_file = false;
String summaryOutputName = getSummaryOuputName();
String summaryTitle = getSummaryTitle();
writeToFile(summaryTitle,append_to_file,summaryOutputName);
append_to_file = true;
writeToFile("",append_to_file,summaryOutputName);
writeToFile("Cross Section " + currentReach + ": " + downstreamDistance + " m downstream",append_to_file,summaryOutputName);
writeToFile(" Depth: " + depth_DS,append_to_file,summaryOutputName);
writeToFile(" Critical Depth: " + critDepth_DS,append_to_file,summaryOutputName);
writeToFile(" Normal Depth: " + normDepth_DS,append_to_file,summaryOutputName);
writeToFile(" Bed Elevation: " + bedElevation,append_to_file,summaryOutputName);
writeToFile(" Water Surface Elevation: " + (depth_DS + bedElevation),append_to_file,summaryOutputName);
writeToFile("",append_to_file,summaryOutputName);
downstreamDistance = downstreamDistance + length;
bedElevation = bedElevation - (reachSlope * length);
elevationArray[currentReach + 1] = writeElevationArray(guessDepth_US,
critDepth_US,
normDepth_US,
downstreamDistance,
bedElevation);
depthArray[currentReach + 1] = writeDepthArray(guessDepth_US,
critDepth_US,
normDepth_US,
downstreamDistance,
bedElevation);
writeToFile("Cross Section " + (currentReach + 1) + ": " + downstreamDistance + " m downstream",append_to_file,summaryOutputName);
writeToFile(" Depth: " + guessDepth_US,append_to_file,summaryOutputName);
writeToFile(" Critical Depth: " + critDepth_US,append_to_file,summaryOutputName);
writeToFile(" Normal Depth: " + normDepth_US,append_to_file,summaryOutputName);
writeToFile(" Bed Elevation: " + bedElevation,append_to_file,summaryOutputName);
writeToFile(" Water Surface Elevation: " + (guessDepth_US + bedElevation),append_to_file,summaryOutputName);
writeToFile("",append_to_file,summaryOutputName);
} else {
downstreamDistance = downstreamDistance + length;
bedElevation = bedElevation - (reachSlope * length);
elevationArray[currentReach + 1] = writeElevationArray(guessDepth_US,
critDepth_US,
normDepth_US,
downstreamDistance,
bedElevation);
depthArray[currentReach + 1] = writeDepthArray(guessDepth_US,
critDepth_US,
normDepth_US,
downstreamDistance,
bedElevation);
append_to_file = true;
String summaryOutputName = getSummaryOuputName();
writeToFile("Cross Section " + (currentReach + 1) + ": " + downstreamDistance + " m downstream",append_to_file,summaryOutputName);
writeToFile(" Depth: " + guessDepth_US,append_to_file,summaryOutputName);
writeToFile(" Critical Depth: " + critDepth_US,append_to_file,summaryOutputName);
writeToFile(" Normal Depth: " + normDepth_US,append_to_file,summaryOutputName);
writeToFile(" Bed Elevation: " + bedElevation,append_to_file,summaryOutputName);
writeToFile(" Water Surface Elevation: " + (guessDepth_US + bedElevation),append_to_file,summaryOutputName);
writeToFile("",append_to_file,summaryOutputName);
}
depth_DS = guessDepth_US;
} //end for statement
graphLongitudinalProfile(elevationArray,
numberOfReaches,
getElevationGraphTitle(),
getElevationGraphOutputName(),
mainFolder,
"Water Surface Elevation",
"Critical Depth",
"Normal Depth",
"Channel Bed Elevation",
"Elevation (m)");
graphLongitudinalProfile(depthArray,
numberOfReaches,
getDepthGraphTitle(),
getDepthGraphOutputName(),
mainFolder,
"Water Surface Depth",
"Critical Depth",
"Normal Depth",
"Channel Bed (x-axis)",
"Depth (m)");
} //end calcStandardStepMethod
public double[] calcBoundaryConditions(double depth_DS,
double criticalDepth,
double normalDepth) throws IOException {
String waterSurfaceProfile;
double a = .01;
double b = 999;
if (normalDepth > criticalDepth && normalDepth < 900) { //test if slope is mild
if (depth_DS < criticalDepth) {
waterSurfaceProfile = "M3";
a = 0.01;
b = criticalDepth;
} else if (depth_DS > normalDepth) {
waterSurfaceProfile = "M1";
a = normalDepth;
b = (2.0 * depth_DS);
} else {
waterSurfaceProfile = "M2";
a = criticalDepth;
b = normalDepth;
}
} else if (normalDepth < criticalDepth) {//test if slope is steep
if (depth_DS < normalDepth) {
waterSurfaceProfile = "S3";
a = .01;
b = normalDepth;
} else if (depth_DS > criticalDepth) {
waterSurfaceProfile = "S1";
a = criticalDepth;
b = (2.0 * depth_DS);
} else {
waterSurfaceProfile = "S2";
a = normalDepth;
b = criticalDepth;
}
} else if (Math.abs(normalDepth - criticalDepth) < .001) {//test if slope is critical
if (depth_DS < criticalDepth) {
waterSurfaceProfile = "C3";
a = .01;
b = criticalDepth;
} else {
waterSurfaceProfile = "C1";
a = criticalDepth;
b = (2.0 * depth_DS);
}
} else if (normalDepth > 100 * depth_DS) { //test if slope is horizontal
if (depth_DS < criticalDepth) {
waterSurfaceProfile = "H3";
a = .01;
b = criticalDepth;
} else {
waterSurfaceProfile = "H2";
a = criticalDepth;
b = normalDepth;
}
} else {
waterSurfaceProfile = "undefined";
} //end if
double[] boundaries = new double[2];
boundaries[0] = a;
boundaries[1] = b;
return boundaries;
} //end calcBoundaryConditions
public double[][] writeElevationArray(double waterDepth,
double critDepth,
double normDepth,
double distance_DS,
double bedElevation) {
double[][] results = new double[2][4];
results[0][0] = distance_DS;
results[1][0] = waterDepth + bedElevation;
results[1][1] = critDepth + bedElevation;
results[1][2] = normDepth + bedElevation;
results[1][3] = bedElevation;
return results;
}
public double[][] writeDepthArray(double waterDepth,
double critDepth,
double normDepth,
double distance_DS,
double bedElevation){
double[][] results = new double[2][4];
results[0][0] = distance_DS;
results[1][0] = waterDepth;
results[1][1] = critDepth;
results[1][2] = normDepth;
return results;
}
public int readLines(String file_path) throws IOException { //determine number of lines in text file to find how many cross sections there are.
FileReader fr = new FileReader(file_path);
BufferedReader bf = new BufferedReader(fr);
String aLine;
int numberOfLines = 0;
while ((aLine = bf.readLine()) != null) {
numberOfLines++;
}
bf.close();
return numberOfLines;
}
public String[] transferTXTFile(String file_path) throws IOException { //read text file and add entries to single dimension array.
FileReader fr = new FileReader(file_path);
BufferedReader textReader = new BufferedReader(fr);
int numberOfLines = readLines(file_path);
String[] crossSections = new String[numberOfLines];
int i;
for (i = 0; i < numberOfLines; i++) {
crossSections[i] = textReader.readLine();
}
textReader.close();
return crossSections;
}
public int calcLargestCrossSection() throws IOException { //determine the longest cross section to determine the length of the new array.
String[] sections = transferTXTFile(mainFolder + File.separator + "crossSections.txt");
int numberOfLines = readLines(mainFolder + File.separator + "crossSections.txt");
int i;
int n;
int m = 0;
for (i = 0; i < numberOfLines; i++) {
String[] xypoints = sections[i].split("\\(");
n = xypoints.length;
if (n > m) {
m = n;
}
}
m = m - 1;
return m;
}
public double[][][] setCrossSectionArray() throws IOException {
int numberOfSections = readLines(mainFolder + File.separator + "crossSections.txt");
String[] sections = transferTXTFile(mainFolder + File.separator + "crossSections.txt");
int length = calcLargestCrossSection();
String[][] xypointlist;
int i;
double[][][] dimensionalArray = new double[numberOfSections][2][length];
for (i = 0; i < numberOfSections; i++) {
String crossSection = sections[i];
String newCrossSection = crossSection.replaceAll("\\)", "");
String[] xypoints = newCrossSection.split("\\(");
double[][] xyPoints_new = new double[length][2];
int j;
for (j = 1; j < xypoints.length; j++) {
String[] xy = xypoints[j].split("\\|");
xyPoints_new[j - 1][0] = Double.parseDouble(xy[0]);
xyPoints_new[j - 1][1] = Double.parseDouble(xy[1]);
}
dimensionalArray[i] = xyPoints_new;
}
return dimensionalArray;
}
public double[][] setReachProperties() throws IOException {
int numberOfSections = readLines(mainFolder + File.separator + "reaches.txt");
String[] reaches = transferTXTFile(mainFolder + File.separator + "reaches.txt");
double[][] properties = new double[numberOfSections][4];
int i;
for (i = 0; i < numberOfSections; i++) {
String reach = reaches[i];
String[] new_reach = reach.split("\\|");
for (int j = 0; j < 4; j++) {
properties[i][j] = Double.parseDouble(new_reach[j]);
}
}
return properties;
}
/*public void testEGLChange(int currentReach) throws IOException {
setDSValues(currentReach);
double EGL1 = calcFrictionSlope();
this.setUSValues(currentReach);
double EGL2 = calcFrictionSlope();
System.out.println(EGL1 + ":" + EGL2);
} //end testEGLChange
*/
public double calcVelocity(ChannelGeometry values) { //Need to move to ChannelGeomety Class?
if (irregularGeometry) {
double area = values.calcIrregularArea();
double velocity = values.discharge / area;
return velocity;
} else {
double area = values.calcTrapezoidalArea();
double velocity = values.discharge / area;
return velocity;
}
} //end of calcVelocity
public double calcFrictionSlope(ChannelGeometry values) { //Need to move to ChannelGeometry Class?
if (irregularGeometry) {
double area = values.calcIrregularArea();
double hydrRadius = values.calcIrregularHydraulicRadius();
double frictionSlope = Math.pow(((values.n * values.discharge)
/ (area * Math.pow(hydrRadius, 2. / 3.))), 2.);
return frictionSlope;
} else {
double area = values.calcTrapezoidalArea();
double hydrRadius = values.calcTrapezoidalHydraulicRadius();
double frictionSlope = Math.pow(((values.n * values.discharge)
/ (area * Math.pow(hydrRadius, 2. / 3.))), 2.);
return frictionSlope;
}
} //end of calcFrictionSlope
public ChannelGeometry setDSValues(int currentReach,
double depth) throws IOException {
ChannelGeometry DSValues = new ChannelGeometry();
DSValues.setGeometryType(irregularGeometry);
if (irregularGeometry) {
double[][][] geometries = setCrossSectionArray();
double[][] properties = setReachProperties();
DSValues.setXYPoints(geometries[currentReach]);
DSValues.setDepth(depth);
DSValues.setDischarge(discharge_DS);
DSValues.setManningRoughness(properties[currentReach][2]);
DSValues.setBedSlope(properties[currentReach][1]);
} else {
DSValues.setBottomWidth(bottomWidth);
DSValues.setSideSlope(sideSlope);
DSValues.setDepth(depth);
DSValues.setDischarge(discharge_DS);
DSValues.setManningRoughness(manning_n);
DSValues.setBedSlope(bedSlope);
}
return DSValues;
}//end setDSValues
public ChannelGeometry setUSValues(int currentReach,
double depth) throws IOException {
ChannelGeometry USValues = new ChannelGeometry();
USValues.setGeometryType(irregularGeometry);
if (irregularGeometry) {
double[][][] geometries = setCrossSectionArray();
double[][] properties = setReachProperties();
USValues.setXYPoints(geometries[currentReach + 1]);
USValues.setDepth(depth);
USValues.setDischarge(discharge_DS);
USValues.setManningRoughness(properties[currentReach][2]);
USValues.setBedSlope(properties[currentReach][1]);
} else {
USValues.setBottomWidth(bottomWidth);
USValues.setSideSlope(sideSlope);
USValues.setDepth(depth);
USValues.setDischarge(discharge_DS);
USValues.setManningRoughness(manning_n);
USValues.setBedSlope(bedSlope);
}
return USValues;
}//end of setUSValues
private double standardStepEquation(double velocity_DS,
double velocity_US,
double frictionSlope_DS,
double frictionSlope_US,
double measuredDownstreamDepth,
double depth_US,
double bedSlope,
double length) throws IOException {
double error = (((depth_US + (Math.pow(velocity_US, 2.) / (2 * 9.81)))
- (measuredDownstreamDepth + (Math.pow(velocity_DS, 2.) / (2. * 9.81))))
/ (((frictionSlope_US + frictionSlope_DS) / 2) - (Math.abs(bedSlope))))
+ length;
return error;
} //end standardStepEquation
public void graphLongitudinalProfile(double[][][] resultsArray,
int numberOfReaches,
String graphTitle,
String graphOutputName,
String mainFolder,
String series1_name,
String series2_name,
String series3_name,
String series4_name,
String yAxis_name) throws IOException {
GeneralFunctions general = new GeneralFunctions();
//Graph data
XYSeries series1 = new XYSeries(series1_name);
for (int i = 0; i < numberOfReaches + 1; i++) {
//Graph the rating curve
series1.add(resultsArray[i][0][0], resultsArray[i][1][0]);
}
XYSeries series2 = new XYSeries(series2_name);
for (int i = 0; i < numberOfReaches + 1; i++) {
//Graph the rating curve
series2.add(resultsArray[i][0][0], resultsArray[i][1][1]);
}
XYSeries series3 = new XYSeries(series3_name);
for (int i = 0; i < numberOfReaches + 1; i++) {
//Graph the rating curve
series3.add(resultsArray[i][0][0], resultsArray[i][1][2]);
}
XYSeries series4 = new XYSeries(series4_name);
for (int i = 0; i < numberOfReaches + 1; i++) {
//Graph the rating curve
series4.add(resultsArray[i][0][0], resultsArray[i][1][3]);
}
//Graph the effective discharge curve
XYPlot plot = new XYPlot();
XYDataset dataset1 = new XYSeriesCollection(series1);
XYItemRenderer currentRenderer = new XYLineAndShapeRenderer(true, false);
currentRenderer.setSeriesPaint(0, Color.blue);
plot.setDataset(2, dataset1);
plot.setRenderer(2, currentRenderer);
XYDataset dataset2 = new XYSeriesCollection(series2);
XYItemRenderer currentRenderer2 = new XYLineAndShapeRenderer(true, false);
currentRenderer2.setSeriesPaint(0, Color.red);
plot.setDataset(1, dataset2);
plot.setRenderer(1, currentRenderer2);
XYDataset dataset3 = new XYSeriesCollection(series3);
XYItemRenderer currentRenderer3 = new XYLineAndShapeRenderer(true, false);
currentRenderer3.setSeriesPaint(0, Color.green);
plot.setDataset(0, dataset3);
plot.setRenderer(0, currentRenderer3);
XYDataset dataset4 = new XYSeriesCollection(series4);
XYItemRenderer currentRenderer4 = new XYLineAndShapeRenderer(true, false);
currentRenderer4.setSeriesPaint(0, Color.black);
plot.setDataset(3, dataset4);
plot.setRenderer(3, currentRenderer4);
//Create the X Axis
ValueAxis xAxis = new NumberAxis("Downstream Distance (m)");
plot.setDomainAxis(0, xAxis);
//Create the Y Axis
ValueAxis yAxis = new NumberAxis(yAxis_name);
plot.setRangeAxis(0, yAxis);
//Set extra plot preferences
general.setAxisPreferences(plot);
//Create the chart with the plot
JFreeChart chart = new JFreeChart(graphTitle, general.titleFont, plot, true);
//Set legend Font
LegendTitle legendTitle = chart.getLegend();
legendTitle.setItemFont(general.masterFont);
try {
String path = mainFolder + File.separator + graphOutputName;
ChartUtilities.saveChartAsJPEG(new File(path), chart, 1280, 800);
System.out.println(path);
} catch (IOException e) {
System.err.println("A problem occurred while trying to create the chart.");
}
}// end graphRatingCurve
public void writeToFile(String textLine, boolean append_to_file, String summaryOutputName) throws IOException {
FileWriter write = new FileWriter(mainFolder + File.separator + summaryOutputName,append_to_file);
PrintWriter print_line = new PrintWriter(write);
print_line.printf("%s" + "%n", textLine);
print_line.close();
}
} //end of StandardStepMethd