comparison artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/tkhcalculation/FlowVelocityModelKmValueFinder.java @ 8964:45f1ad66560e

Code cleanup concerning calculations: improved error handling; improved interpolation; bed heights are now always used for spatial discretisation
author gernotbelger
date Thu, 29 Mar 2018 15:48:17 +0200
parents d9dbf0b74bc2
children 9b9f5f4ddb80
comparison
equal deleted inserted replaced
8963:b98fbd91f64a 8964:45f1ad66560e
15 15
16 import org.apache.commons.lang.math.DoubleRange; 16 import org.apache.commons.lang.math.DoubleRange;
17 import org.apache.log4j.Logger; 17 import org.apache.log4j.Logger;
18 import org.dive4elements.river.artifacts.math.Linear; 18 import org.dive4elements.river.artifacts.math.Linear;
19 import org.dive4elements.river.artifacts.math.Utils; 19 import org.dive4elements.river.artifacts.math.Utils;
20 import org.dive4elements.river.artifacts.model.Calculation;
20 import org.dive4elements.river.artifacts.sinfo.flowdepth.FlowVelocityKmModelValues; 21 import org.dive4elements.river.artifacts.sinfo.flowdepth.FlowVelocityKmModelValues;
21 import org.dive4elements.river.backend.SessionHolder; 22 import org.dive4elements.river.backend.SessionHolder;
22 import org.dive4elements.river.model.River; 23 import org.dive4elements.river.model.River;
23 import org.hibernate.SQLQuery; 24 import org.hibernate.SQLQuery;
24 import org.hibernate.Session; 25 import org.hibernate.Session;
35 * 36 *
36 * (Created based on a copy of FlowVelocityMeasurementFactory.) 37 * (Created based on a copy of FlowVelocityMeasurementFactory.)
37 * 38 *
38 * @author Matthias Schäfer 39 * @author Matthias Schäfer
39 */ 40 */
41 // TODO: noch mal prüfen, ob wir eine interpolationsschranke brauchen (max. km-abstand)
40 final class FlowVelocityModelKmValueFinder { 42 final class FlowVelocityModelKmValueFinder {
41 /***** FIELDS *****/ 43 /***** FIELDS *****/
42 44
43 /** 45 /**
44 * Private log to use here. 46 * Private log to use here.
113 /** 115 /**
114 * For each km in kms a list of q-v-tau-tupels 116 * For each km in kms a list of q-v-tau-tupels
115 */ 117 */
116 private final List<FlowVelocityKmModelValues> values = new ArrayList<>(); 118 private final List<FlowVelocityKmModelValues> values = new ArrayList<>();
117 119
120 private Calculation problems;
121
118 /** 122 /**
119 * Searched km of the last findKmValue 123 * Searched km of the last findKmValue
120 */ 124 */
121 private double findKm; 125 private double findKm;
122 126
132 136
133 /** 137 /**
134 * Q of the last findKmQValues 138 * Q of the last findKmQValues
135 */ 139 */
136 private double findQ; 140 private double findQ;
141
142 public FlowVelocityModelKmValueFinder(final Calculation problems) {
143 this.problems = problems;
144 }
137 145
138 /***** METHODS *****/ 146 /***** METHODS *****/
139 147
140 /** 148 /**
141 * Discharge of the last {@link findKmQValue} 149 * Discharge of the last {@link findKmQValue}
161 * Shear stress tau of the last {@link findKmQValues} 169 * Shear stress tau of the last {@link findKmQValues}
162 */ 170 */
163 public double getFindTauFound() { 171 public double getFindTauFound() {
164 if (this.leftIndexFound < 0) 172 if (this.leftIndexFound < 0)
165 return Double.NaN; 173 return Double.NaN;
166 else if (this.leftIndexFound == this.rightIndexFound) 174
175 if (this.leftIndexFound == this.rightIndexFound)
167 return getLeftValues().getTauFound(); 176 return getLeftValues().getTauFound();
168 else 177
169 return Linear.linear(this.findKm, getLeftValues().getKm(), getRightValues().getKm(), getLeftValues().getTauFound(), getRightValues().getTauFound()); 178 return Linear.linear(this.findKm, getLeftValues().getKm(), getRightValues().getKm(), getLeftValues().getTauFound(), getRightValues().getTauFound());
170 } 179 }
171 180
172 /** 181 /**
173 * Whether the discharge has been interpolated in the last {@link findKmQValues} 182 * Whether the discharge has been interpolated in the last {@link findKmQValues}
174 */ 183 */
177 } 186 }
178 187
179 /** 188 /**
180 * Static constructor: queries a range of a river's kms with all their q-v-tau values. 189 * Static constructor: queries a range of a river's kms with all their q-v-tau values.
181 * 190 *
191 * @param problems
192 *
182 * @return Whether the load has been successful the new instance, <code>null</code> otherwise. 193 * @return Whether the load has been successful the new instance, <code>null</code> otherwise.
183 */ 194 */
184 public static FlowVelocityModelKmValueFinder loadValues(final River river, final DoubleRange kmRange, final DoubleRange qRange) { 195 public static FlowVelocityModelKmValueFinder loadValues(final Calculation problems, final River river, final DoubleRange kmRange,
196 final DoubleRange qRange) {
185 // DB session 197 // DB session
186 log.debug(String.format("loadValues km %.3f - %.3f / q %.1f - %.1f", kmRange.getMinimumDouble(), kmRange.getMaximumDouble(), qRange.getMinimumDouble(), 198 log.debug(String.format("loadValues km %.3f - %.3f / q %.1f - %.1f", kmRange.getMinimumDouble(), kmRange.getMaximumDouble(), qRange.getMinimumDouble(),
187 qRange.getMaximumDouble())); 199 qRange.getMaximumDouble()));
188 200
189 final FlowVelocityModelKmValueFinder instance = new FlowVelocityModelKmValueFinder(); 201 final FlowVelocityModelKmValueFinder instance = new FlowVelocityModelKmValueFinder(problems);
190 202
191 final TDoubleArrayList kms = instance.kms; 203 final TDoubleArrayList kms = instance.kms;
192 final List<FlowVelocityKmModelValues> values = instance.values; 204 final List<FlowVelocityKmModelValues> values = instance.values;
193 205
194 final boolean isDemoValuesCorrection = river.getName().equalsIgnoreCase("beispielfluss"); 206 final boolean isDemoValuesCorrection = river.getName().equalsIgnoreCase("beispielfluss");
247 } 259 }
248 } 260 }
249 261
250 log.debug(String.format("loadValues %d kms, %d values loaded", kmcount, rowcount)); 262 log.debug(String.format("loadValues %d kms, %d values loaded", kmcount, rowcount));
251 263
252 if (kms.size() == 0) 264 if (kms.size() == 0) {
265 problems.addProblem("flowvelocitymodelkmvaluefinder.empty");
253 return null; 266 return null;
267 }
254 268
255 return instance; 269 return instance;
256 } 270 }
257 271
258 /** 272 /**
281 * 295 *
282 * @return Whether values have been found 296 * @return Whether values have been found
283 */ 297 */
284 public boolean findKmQValues(final double km, final double q) { 298 public boolean findKmQValues(final double km, final double q) {
285 this.findQ = q; 299 this.findQ = q;
300
301 final boolean found = doFindKmQValues(km, q);
302
303 if (this.problems != null) {
304
305 this.problems.addProblem(km, "flowvelocitymodelkmvaluefinder.missing");
306
307 // report only once
308 this.problems = null;
309 }
310
311 return found;
312 }
313
314 private boolean doFindKmQValues(final double km, final double q) {
286 if (!searchKm(km)) 315 if (!searchKm(km))
287 return false; 316 return false;
317
288 if (this.leftIndexFound == this.rightIndexFound) { 318 if (this.leftIndexFound == this.rightIndexFound) {
289 // Exact km match 319 // Exact km match
290 final double qfound = getLeftValues().findQ(q); 320 final double qfound = getLeftValues().findQ(q);
291 log.debug(String.format("findKmQValues km %.3f q %.0f = %.0f (%d)", km, q, qfound, this.leftIndexFound)); 321 log.debug(String.format("findKmQValues km %.3f q %.0f = %.0f (%d)", km, q, qfound, this.leftIndexFound));
292 return !Double.isNaN(qfound); 322 return !Double.isNaN(qfound);
293 } else { 323 }
294 final double[] qfound = { getLeftValues().findQ(q), getRightValues().findQ(q) }; 324
295 log.debug(String.format("findKmQValues km %.3f q %.0f = %.0f (%d, %.3f) - %.0f (%d, %.3f)", km, q, qfound[0], this.leftIndexFound, 325 final double[] qfound = { getLeftValues().findQ(q), getRightValues().findQ(q) };
296 getLeftValues().getKm(), qfound[1], this.rightIndexFound, getRightValues().getKm())); 326 log.debug(String.format("findKmQValues km %.3f q %.0f = %.0f (%d, %.3f) - %.0f (%d, %.3f)", km, q, qfound[0], this.leftIndexFound,
297 return !Double.isNaN(qfound[0]) && !Double.isNaN(qfound[1]); 327 getLeftValues().getKm(), qfound[1], this.rightIndexFound, getRightValues().getKm()));
298 } 328 return !Double.isNaN(qfound[0]) && !Double.isNaN(qfound[1]);
299 } 329 }
300 330
301 /** 331 /**
302 * Searches a km 332 * Searches a km
303 * 333 *
305 */ 335 */
306 private boolean searchKm(final double km) { 336 private boolean searchKm(final double km) {
307 this.findKm = km; 337 this.findKm = km;
308 this.leftIndexFound = -1; 338 this.leftIndexFound = -1;
309 this.rightIndexFound = -1; 339 this.rightIndexFound = -1;
310 if ((this.kms == null) || (this.kms.size() == 0)) 340
311 return false;
312 int i = this.kms.binarySearch(km); 341 int i = this.kms.binarySearch(km);
313 if (i >= 0) { 342 if (i >= 0) {
314 // Exact km match 343 // Exact km match
315 this.leftIndexFound = i; 344 this.leftIndexFound = i;
316 this.rightIndexFound = i; 345 this.rightIndexFound = i;
317 return true; 346 return true;
318 } else { 347 }
319 // Out of range or within km interval 348
320 if (i < 0) 349 // Out of range or within km interval
321 i = -i - 1; 350 if (i < 0)
322 if ((i <= 0) || (i >= this.kms.size())) 351 i = -i - 1;
323 return false; 352 if ((i <= 0) || (i >= this.kms.size()))
324 this.leftIndexFound = i - 1; 353 return false;
325 this.rightIndexFound = i; 354 this.leftIndexFound = i - 1;
326 return true; 355 this.rightIndexFound = i;
327 } 356 return true;
328 } 357 }
329 358
330 private FlowVelocityKmModelValues getLeftValues() { 359 private FlowVelocityKmModelValues getLeftValues() {
331 return this.values.get(this.leftIndexFound); 360 return this.values.get(this.leftIndexFound);
332 } 361 }

http://dive4elements.wald.intevation.org