Mercurial > dive4elements > river
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 } |