Mercurial > dive4elements > river
view artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/tkhcalculation/DischargeValuesFinder.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 | 5d5d482da3e9 |
children | 16df9f7a9815 |
line wrap: on
line source
/** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde * Software engineering by * Björnsen Beratende Ingenieure GmbH * Dr. Schumacher Ingenieurbüro für Wasser und Umwelt * * This file is Free Software under the GNU AGPL (>=v3) * and comes with ABSOLUTELY NO WARRANTY! Check out the * documentation coming with Dive4Elements River for details. */ package org.dive4elements.river.artifacts.sinfo.tkhcalculation; import org.apache.commons.lang.math.DoubleRange; import org.apache.commons.math.FunctionEvaluationException; import org.apache.commons.math.analysis.UnivariateRealFunction; import org.dive4elements.river.artifacts.model.QKms; import org.dive4elements.river.artifacts.model.WKms; import org.dive4elements.river.artifacts.model.WQKms; import org.dive4elements.river.utils.DoubleUtil; import gnu.trove.TDoubleDoubleHashMap; /** * @author Gernot Belger */ public final class DischargeValuesFinder { private final UnivariateRealFunction qInterpolator; private final TDoubleDoubleHashMap exactValues; private final QKms qKms; /** * Create an instance from a {@link WKms} object. If the given {@link WKms} is not a {@link WQKms}, a finder that always * returns {@link Double#NaN} is returned. */ public static DischargeValuesFinder fromKms(final WKms wstKms) { if (!(wstKms instanceof QKms)) { return new DischargeValuesFinder(null); } final QKms qKms = (QKms) wstKms; return new DischargeValuesFinder(qKms); } public DischargeValuesFinder(final QKms qKms) { this.qKms = qKms; if (qKms == null) { this.qInterpolator = null; this.exactValues = null; } else { this.qInterpolator = DoubleUtil.getLinearInterpolator(qKms.allKms(), qKms.allQs()); this.exactValues = new TDoubleDoubleHashMap(qKms.size()); for (int i = 0; i < qKms.size(); i++) { final double station = qKms.getKm(i); final double discharge = qKms.getQ(i); this.exactValues.put(station, discharge); } } } /** * If this provider may return valid data at all. */ public boolean isValid() { return this.qInterpolator != null; } public DoubleRange getRange() { return new DoubleRange(this.qKms.allQs().min(), this.qKms.allQs().max()); } public double getDischarge(final double station) { try { // FIXME: check: ich dachte wir interpolieren den abfluss nicht linear? // IMPORTANT: we first try to retrieve the exact value if it is present, to avoid rounding changes due to interpolation. // This is important because in the WaterlevelExporter code, these values are double-compared (with '==' ...) in order // to find the corresponding main-value. if (this.exactValues != null && this.exactValues.contains(station)) return this.exactValues.get(station); if (this.qInterpolator == null) return Double.NaN; return this.qInterpolator.value(station); } catch (final FunctionEvaluationException e) { e.printStackTrace(); return Double.NaN; } } }