Mercurial > dive4elements > river
view artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/common/GaugeDischargeValuesFinder.java @ 9613:f2473dc34535
Nachtrag Pos. 19: Q calculation with historical discharge tables instead of master discharge table
author | mschaefer |
---|---|
date | Tue, 08 Oct 2019 15:03:24 +0200 |
parents | d9fda7af24ca |
children |
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.common; import java.util.Date; import org.apache.commons.lang.math.DoubleRange; import org.apache.commons.math.FunctionEvaluationException; import org.apache.commons.math.analysis.UnivariateRealFunction; import org.apache.commons.math.analysis.interpolation.LinearInterpolator; import org.dive4elements.river.artifacts.model.Calculation; import org.dive4elements.river.model.DischargeTable; import org.dive4elements.river.model.DischargeTableValue; import org.dive4elements.river.model.Gauge; import org.dive4elements.river.model.River; import gnu.trove.TDoubleArrayList; /** * Loading and search/interpolation of a gauge's discharge table (.at) * * @author Matthias Schäfer * */ public final class GaugeDischargeValuesFinder { /***** FIELDS *****/ // private static Logger log = Logger.getLogger(GaugeDischargeValuesFinder.class); private final Gauge gauge; private Calculation problems; private final UnivariateRealFunction wInterpolator; private final DoubleRange wRange; private final Date startTime; private final Date endTime; /***** CONSTRUCTORS *****/ private GaugeDischargeValuesFinder(final Gauge gauge, final Calculation problems, final DischargeTable dischargeTable) { // Load W-Q-values from database this.gauge = gauge; this.problems = problems; this.startTime = dischargeTable.getTimeInterval().getStartTime(); this.endTime = dischargeTable.getTimeInterval().getStopTime(); final TDoubleArrayList ws = new TDoubleArrayList(); final TDoubleArrayList qs = new TDoubleArrayList(); for (final DischargeTableValue v : DischargeTable.fetchValuesSortedByW(dischargeTable)) { ws.add(v.getW().doubleValue()); qs.add(v.getQ().doubleValue()); } // Build interpolator if (ws.size() >= 2) { this.wInterpolator = new LinearInterpolator().interpolate(ws.toNativeArray(), qs.toNativeArray()); this.wRange = new DoubleRange(ws.get(0), ws.get(ws.size() - 1)); } else { this.wInterpolator = null; this.wRange = null; } if ((this.wInterpolator == null) && (this.problems != null)) { this.problems.addProblem("gauge_discharge_table.missing", gauge.getName()); // Report only once this.problems = null; } } /***** METHODS *****/ /** * Loads the main discharge table of a gauge ({gauge}.at) * * @return The discharge table values finder of the gauge, or null */ public static GaugeDischargeValuesFinder loadValues(final Gauge gauge, final Calculation problems) { return loadValues(gauge, gauge.getName(), problems); } /** * Loads the main discharge table of a river's gauge ({gauge}.at) * * @return The discharge table values finder of the gauge, or null */ public static GaugeDischargeValuesFinder loadValues(final River river, final String gaugeName, final Calculation problems) { final Gauge gauge = river.determineGaugeByName(gaugeName); return loadValues(gauge, gaugeName, problems); } /** * Loads a discharge table of a river's gauge (*.at) * * @return The discharge table values finder, or null */ public static GaugeDischargeValuesFinder loadValues(final DischargeTable table, final River river, final String gaugeName, final Calculation problems) { final Gauge gauge = river.determineGaugeByName(gaugeName); return loadValues(table, gauge, gaugeName, problems); } private static GaugeDischargeValuesFinder loadValues(final Gauge gauge, final String gaugeName, final Calculation problems) { return loadValues((gauge != null) ? gauge.fetchMasterDischargeTable() : null, gauge, gaugeName, problems); } private static GaugeDischargeValuesFinder loadValues(final DischargeTable table, final Gauge gauge, final String gaugeName, final Calculation problems) { if ((table == null) || (table.getDischargeTableValues().size() == 0)) { problems.addProblem("gauge_discharge_table.missing", gaugeName); return null; } else return new GaugeDischargeValuesFinder(gauge, problems, table); } /** * If this provider may return valid data at all. */ public boolean isValid() { return (this.wInterpolator != null); } /** * Discharge for a W * * @param w * W in cm above gauge datum * @return Q, or NegInf for w less than all, or PosInf for w greater then all, or NaN in case of exception */ public double getDischarge(final double w) { try { if (!this.isValid()) return Double.NaN; else if (w < this.wRange.getMinimumDouble()) return Double.NEGATIVE_INFINITY; else if (w > this.wRange.getMaximumDouble()) return Double.POSITIVE_INFINITY; else return this.wInterpolator.value(w); } catch (@SuppressWarnings("unused") final FunctionEvaluationException e) { // ignore exception because this can/will happen regularly return Double.NaN; } } /** * Start of the discharge table's time interval. * * @return */ public Date getStartTime() { return this.startTime; } /** * End of the discharge table's time interval. * * @return */ public Date getEndTime() { return this.endTime; } }