@@ -6,7 +6,7 @@ |
import java.util.Calendar; |
|
/** |
-* Last Updated: 2-February-2015 |
+* Last Updated: 3-February-2015 |
* @author Tyler Wible |
* @since 16-December-2014 |
*/ |
@@ -106,7 +106,7 @@ |
double designFlow = Math.exp(U + K*S); |
|
//Call file writer for outputs fo flow statistics |
- designFlow = doubleMath.round(designFlow, 3); |
+ designFlow = doubleMath.round(designFlow, 2); |
|
return designFlow; |
} |
@@ -114,7 +114,7 @@ |
* Calculate the CDPHE "biologically-based" design flow (see DFLOW user manual) |
* which is an 'm'-day harmonic average low flow based on a certain excursion count (exceedance?), |
* performs this calculation for the entire flow record as well as each month of the year |
- * @param data_all a String[][] of flow data, column1 = dates (format yyyy-mm-dd), column2 = flow values |
+ * @param flowData a String[][] of flow data, column1 = dates (format yyyy-mm-dd), column2 = flow values |
* @param m the number of days to average for annual low flow analysis (m-day average) |
* @param R the desired return period of the m-day low flow (in years) |
* @param clusterLength the length of time for the definition of a 'cluster' of excursion |
@@ -126,7 +126,7 @@ |
* @throws IOException |
* @throws ParseException |
*/ |
- public double[] CDPHE_Biological(String[][] data_all, |
+ public double[] CDPHE_Biological(String[][] flowData, |
int m, |
int R, |
int clusterLength, |
@@ -134,38 +134,58 @@ |
DoubleArray doubleArray = new DoubleArray(); |
DoubleMath doubleMath = new DoubleMath(); |
|
- //Pull data |
- String[][] data_jan = doubleArray.getSeasonalData(data_all, "01-01", "01-31"); |
- String[][] data_feb = doubleArray.getSeasonalData(data_all, "02-01", "02-28"); |
- if(m == 30){ |
- data_feb = doubleArray.getSeasonalData(data_all, "02-01", "03-03"); |
+ //Calculate annual design low flow |
+ double DFLOW_annual = CDPHE_Biological_calcs(flowData, m, R, clusterLength, clusterCountMax); |
+ |
+ //Calculate monthly design low flows |
+ double DFLOW_jan = -9999, DFLOW_feb = -9999, DFLOW_mar = -9999, DFLOW_apr = -9999, DFLOW_may = -9999, DFLOW_jun = -9999; |
+ double DFLOW_jul = -9999, DFLOW_aug = -9999, DFLOW_sep = -9999, DFLOW_oct = -9999, DFLOW_nov = -9999, DFLOW_dec = -9999; |
+ if(m == 30 && R == 3){ |
+ //If the design flow is 30E3, follow the special provisions set out by reg31 |
+ double[] monthlyDFLOWs = calc30E3(flowData, DFLOW_annual); |
+ DFLOW_jan = monthlyDFLOWs[0]; |
+ DFLOW_feb = monthlyDFLOWs[1]; |
+ DFLOW_mar = monthlyDFLOWs[2]; |
+ DFLOW_apr = monthlyDFLOWs[3]; |
+ DFLOW_may = monthlyDFLOWs[4]; |
+ DFLOW_jun = monthlyDFLOWs[5]; |
+ DFLOW_jul = monthlyDFLOWs[6]; |
+ DFLOW_aug = monthlyDFLOWs[7]; |
+ DFLOW_sep = monthlyDFLOWs[8]; |
+ DFLOW_oct = monthlyDFLOWs[9]; |
+ DFLOW_nov = monthlyDFLOWs[10]; |
+ DFLOW_dec = monthlyDFLOWs[11]; |
+ }else{ |
+ //Otherwise treat it as a normal biological flow |
+ DFLOW_jan = CDPHE_Biological_calcs(doubleArray.getSeasonalData(flowData, "01-01", "01-31"), m, R, clusterLength, clusterCountMax); |
+ DFLOW_feb = CDPHE_Biological_calcs(doubleArray.getSeasonalData(flowData, "02-01", "02-28"), m, R, clusterLength, clusterCountMax); |
+ DFLOW_mar = CDPHE_Biological_calcs(doubleArray.getSeasonalData(flowData, "03-01", "03-31"), m, R, clusterLength, clusterCountMax); |
+ DFLOW_apr = CDPHE_Biological_calcs(doubleArray.getSeasonalData(flowData, "04-01", "04-30"), m, R, clusterLength, clusterCountMax); |
+ DFLOW_may = CDPHE_Biological_calcs(doubleArray.getSeasonalData(flowData, "05-01", "05-31"), m, R, clusterLength, clusterCountMax); |
+ DFLOW_jun = CDPHE_Biological_calcs(doubleArray.getSeasonalData(flowData, "06-01", "06-30"), m, R, clusterLength, clusterCountMax); |
+ DFLOW_jul = CDPHE_Biological_calcs(doubleArray.getSeasonalData(flowData, "07-01", "07-31"), m, R, clusterLength, clusterCountMax); |
+ DFLOW_aug = CDPHE_Biological_calcs(doubleArray.getSeasonalData(flowData, "08-01", "08-31"), m, R, clusterLength, clusterCountMax); |
+ DFLOW_sep = CDPHE_Biological_calcs(doubleArray.getSeasonalData(flowData, "09-01", "09-30"), m, R, clusterLength, clusterCountMax); |
+ DFLOW_oct = CDPHE_Biological_calcs(doubleArray.getSeasonalData(flowData, "10-01", "10-31"), m, R, clusterLength, clusterCountMax); |
+ DFLOW_nov = CDPHE_Biological_calcs(doubleArray.getSeasonalData(flowData, "11-01", "11-30"), m, R, clusterLength, clusterCountMax); |
+ DFLOW_dec = CDPHE_Biological_calcs(doubleArray.getSeasonalData(flowData, "12-01", "12-31"), m, R, clusterLength, clusterCountMax); |
} |
- String[][] data_mar = doubleArray.getSeasonalData(data_all, "03-01", "03-31"); |
- String[][] data_apr = doubleArray.getSeasonalData(data_all, "04-01", "04-30"); |
- String[][] data_may = doubleArray.getSeasonalData(data_all, "05-01", "05-31"); |
- String[][] data_jun = doubleArray.getSeasonalData(data_all, "06-01", "06-30"); |
- String[][] data_jul = doubleArray.getSeasonalData(data_all, "07-01", "07-31"); |
- String[][] data_aug = doubleArray.getSeasonalData(data_all, "08-01", "08-31"); |
- String[][] data_sep = doubleArray.getSeasonalData(data_all, "09-01", "09-30"); |
- String[][] data_oct = doubleArray.getSeasonalData(data_all, "10-01", "10-31"); |
- String[][] data_nov = doubleArray.getSeasonalData(data_all, "11-01", "11-30"); |
- String[][] data_dec = doubleArray.getSeasonalData(data_all, "12-01", "12-31"); |
|
//Calculate design flows |
double[] designFlows = new double[13]; |
- designFlows[0] = doubleMath.round(CDPHE_Biological_calcs(data_all, m, R, clusterLength, clusterCountMax), 3); //entire record |
- designFlows[1] = doubleMath.round(CDPHE_Biological_calcs(data_jan, m, R, clusterLength, clusterCountMax), 3); //January |
- designFlows[2] = doubleMath.round(CDPHE_Biological_calcs(data_feb, m, R, clusterLength, clusterCountMax), 3); //February |
- designFlows[3] = doubleMath.round(CDPHE_Biological_calcs(data_mar, m, R, clusterLength, clusterCountMax), 3); //March |
- designFlows[4] = doubleMath.round(CDPHE_Biological_calcs(data_apr, m, R, clusterLength, clusterCountMax), 3); //April |
- designFlows[5] = doubleMath.round(CDPHE_Biological_calcs(data_may, m, R, clusterLength, clusterCountMax), 3); //May |
- designFlows[6] = doubleMath.round(CDPHE_Biological_calcs(data_jun, m, R, clusterLength, clusterCountMax), 3); //June |
- designFlows[7] = doubleMath.round(CDPHE_Biological_calcs(data_jul, m, R, clusterLength, clusterCountMax), 3); //July |
- designFlows[8] = doubleMath.round(CDPHE_Biological_calcs(data_aug, m, R, clusterLength, clusterCountMax), 3); //August |
- designFlows[9] = doubleMath.round(CDPHE_Biological_calcs(data_sep, m, R, clusterLength, clusterCountMax), 3); //September |
- designFlows[10] = doubleMath.round(CDPHE_Biological_calcs(data_oct, m, R, clusterLength, clusterCountMax), 3); //October |
- designFlows[11] = doubleMath.round(CDPHE_Biological_calcs(data_nov, m, R, clusterLength, clusterCountMax), 3); //November |
- designFlows[12] = doubleMath.round(CDPHE_Biological_calcs(data_dec, m, R, clusterLength, clusterCountMax), 3); //December |
+ designFlows[0] = doubleMath.round(DFLOW_annual, 2); //entire record |
+ designFlows[1] = doubleMath.round(DFLOW_jan, 2); //January |
+ designFlows[2] = doubleMath.round(DFLOW_feb, 2); //February |
+ designFlows[3] = doubleMath.round(DFLOW_mar, 2); //March |
+ designFlows[4] = doubleMath.round(DFLOW_apr, 2); //April |
+ designFlows[5] = doubleMath.round(DFLOW_may, 2); //May |
+ designFlows[6] = doubleMath.round(DFLOW_jun, 2); //June |
+ designFlows[7] = doubleMath.round(DFLOW_jul, 2); //July |
+ designFlows[8] = doubleMath.round(DFLOW_aug, 2); //August |
+ designFlows[9] = doubleMath.round(DFLOW_sep, 2); //September |
+ designFlows[10] = doubleMath.round(DFLOW_oct, 2); //October |
+ designFlows[11] = doubleMath.round(DFLOW_nov, 2); //November |
+ designFlows[12] = doubleMath.round(DFLOW_dec, 2); //December |
|
return designFlows; |
} |
@@ -208,6 +228,7 @@ |
double flow_lowerBound = 0, flow_upperBound = trialDFLOW, excursions_lowerBound = 0, excursions_upperBound = trialDFLOW_excursions; |
double designFlow = -1; |
boolean convergance = false; |
+ int ctr = 0; |
while(!convergance){ |
|
//Check for convergance |
@@ -220,6 +241,10 @@ |
}else if( Math.abs(A - excursions_upperBound) <= (0.005*A) ){ |
designFlow = flow_upperBound; |
convergance = true; |
+ }else if( ctr > 200 ){ |
+ designFlow = -9999; |
+ convergance = true; |
+ System.err.println("Did not converge to a solution after " + ctr + " iterations, current upper flow boundary: " + flow_upperBound+ ", current lower flow boundary: " + flow_lowerBound); |
}else{ |
//If convergance is not met, interpolate a new trial design flow and count it's excursions |
trialDFLOW = flow_lowerBound + ( ((flow_upperBound - flow_lowerBound) * (A - excursions_lowerBound)) / (excursions_upperBound - excursions_lowerBound) ); |
@@ -232,6 +257,7 @@ |
excursions_upperBound = trialDFLOW_excursions; |
} |
} |
+ ctr++; |
} |
|
//Call file writer for outputs fo flow statistics |
@@ -363,6 +389,84 @@ |
return excursionLength; |
} |
/** |
+ * Calculate the 30-day average low flow associated with a 3 year return period |
+ * using the special provisions set out in Regulation 31.9.3 "Streams with Rapid Flow Changes" |
+ * @param flowData flow data, column1 = dates (format yyyy-mm-dd), column2 = flow values |
+ * @param DFLOW_annual the biologically based 30E3 design flow for the period of record |
+ * @return a list of monthly low flows in order from January to December |
+ * @throws IOException |
+ */ |
+ private double[] calc30E3(String[][] flowData, double DFLOW_annual) throws IOException{ |
+ DoubleArray doubleArray = new DoubleArray(); |
+ DoubleMath doubleMath = new DoubleMath(); |
+ |
+ //Calculate m-day statistics |
+ Object[] resultArray = doubleArray.getMdayData(flowData, 30, "harmonic"); |
+ ArrayList<String> mDayAverage_dates = (ArrayList<String>) resultArray[0]; |
+ ArrayList<Double> mDayAverage = (ArrayList<Double>) resultArray[1]; |
+ |
+ //Determine the year and 'month' of each m-day flow |
+ ArrayList<String> mDayAverage_month = new ArrayList<String>(); |
+ for(int i=0; i<mDayAverage.size(); i++){ |
+ //Get the date for 14 days from the begin date, |
+ //aka a total of 15 days of data and check if this is still in the same month |
+ String beginDate = mDayAverage_dates.get(i).substring(0,10); |
+ String midDate = doubleArray.getDay(beginDate, 12); |
+ |
+ String beginMonth = beginDate.substring(5,7); |
+ String midMonth = midDate.substring(5,7); |
+ if(beginMonth.equalsIgnoreCase(midMonth)){ |
+ mDayAverage_month.add(convertMonth(Double.parseDouble(beginMonth))); |
+ }else{ |
+ mDayAverage_month.add(convertMonth(Double.parseDouble(midMonth))); |
+ } |
+ } |
+ |
+ //Determine monthly low flows |
+ String[] months = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}; |
+ double[] monthlyLowFlow = new double[12]; |
+ for(int j=0; j<12; j++){ |
+ //Get all flows for the current month |
+ ArrayList<Double> currentMonthFlows = new ArrayList<Double>(); |
+ for(int i=0; i<mDayAverage.size(); i++){ |
+ if(mDayAverage_month.get(i).equalsIgnoreCase(months[j])){ |
+ currentMonthFlows.add(mDayAverage.get(i)); |
+ } |
+ } |
+ |
+ //Determine m-day minimum flow for this month |
+ double mDayAveage_MonthlyMin = doubleMath.min(currentMonthFlows); |
+ |
+ //Check whether to return the annual 30E3 value or the monthly flow (Reg 31.9.3.e) |
+ if(currentMonthFlows.isEmpty() || DFLOW_annual > mDayAveage_MonthlyMin){ |
+ mDayAveage_MonthlyMin = DFLOW_annual; |
+ } |
+ monthlyLowFlow[j] = mDayAveage_MonthlyMin; |
+ } |
+ |
+ return monthlyLowFlow; |
+ } |
+ private String convertMonth(double monthDouble){ |
+ int monthInteger = (int) monthDouble; |
+ String monthString = "?"; |
+ switch(monthInteger){ |
+ case 1: monthString = "January"; break; |
+ case 2: monthString = "February"; break; |
+ case 3: monthString = "March"; break; |
+ case 4: monthString = "April"; break; |
+ case 5: monthString = "May"; break; |
+ case 6: monthString = "June"; break; |
+ case 7: monthString = "July"; break; |
+ case 8: monthString = "August"; break; |
+ case 9: monthString = "September"; break; |
+ case 10: monthString = "October"; break; |
+ case 11: monthString = "November"; break; |
+ case 12: monthString = "December"; break; |
+ default: monthString = "Not a valid month integer"; break; |
+ } |
+ return monthString; |
+ } |
+ /** |
* Calculate the CDPHE "human health" design flow (see DFLOW user manual) |
* which is the harmonic mean of the flows |
* @param flowData flow data, column1 = dates (format yyyy-mm-dd), column2 = flow values |
@@ -375,7 +479,7 @@ |
|
//Calculate design flows |
double[] flowOnlyData = convertSecondColumn(flowData); |
- double designFlow = doubleMath.round(doubleMath.meanHarmonic(flowOnlyData), 3); |
+ double designFlow = doubleMath.round(doubleMath.meanHarmonic(flowOnlyData), 2); |
|
return designFlow; |
} |
@@ -437,7 +541,7 @@ |
//Calculate annual median of data with a 5-year return period |
System.out.println("Calcualting Reg. 31 1E5 Annual Median of Daily Average Flows..."); |
double median_R_yearFlow = annualMedianReturnPeriod(flowData, 5); |
- median_R_yearFlow = doubleMath.round(median_R_yearFlow, 3); |
+ median_R_yearFlow = doubleMath.round(median_R_yearFlow, 2); |
|
//Format the results into a summary table |
String summaryTable = "Month\t1E3 Acute Monthly Low Flows\t7E3 Chronic Monthly Low Flows\t30E3 Chronic Monthly Low Flows"; |