diff artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flowdepth/FlowDepthCalculator.java @ 8915:d9dbf0b74bc2

Refaktoring of flow depth calculation, extracting tkh part. First implementation of tkh calculation.
author gernotbelger
date Wed, 28 Feb 2018 17:27:15 +0100
parents
children 82998242ba84
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flowdepth/FlowDepthCalculator.java	Wed Feb 28 17:27:15 2018 +0100
@@ -0,0 +1,129 @@
+/** 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.flowdepth;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.apache.commons.lang.math.DoubleRange;
+import org.apache.commons.math.FunctionEvaluationException;
+import org.apache.commons.math.analysis.polynomials.PolynomialSplineFunction;
+import org.dive4elements.river.artifacts.model.WKms;
+import org.dive4elements.river.artifacts.sinfo.common.RiverInfoProvider;
+import org.dive4elements.river.artifacts.sinfo.tkhcalculation.DischargeValuesFinder;
+import org.dive4elements.river.artifacts.sinfo.tkhcalculation.SoilKind;
+import org.dive4elements.river.artifacts.sinfo.tkhcalculation.Tkh;
+import org.dive4elements.river.artifacts.sinfo.tkhcalculation.TkhCalculator;
+import org.dive4elements.river.artifacts.sinfo.tkhstate.BedHeightsFinder;
+import org.dive4elements.river.artifacts.sinfo.util.WstInfo;
+import org.dive4elements.river.utils.DoubleUtil;
+
+/**
+ * @author Gernot Belger
+ */
+final class FlowDepthCalculator {
+
+    private final Collection<FlowDepthRow> rows = new ArrayList<>();
+
+    private final DischargeValuesFinder dischargeProvider;
+
+    private final BedHeightsFinder bedHeight;
+
+    private final TkhCalculator tkhCalculator;
+
+    private final PolynomialSplineFunction wstInterpolator;
+
+    private final RiverInfoProvider riverInfoProvider;
+
+    private final String bedHeightLabel;
+
+    private final String wstLabel;
+
+    public FlowDepthCalculator(final RiverInfoProvider riverInfoProvider, final WKms wstKms,
+            final DischargeValuesFinder dischargeProvider, final BedHeightsFinder bedHeight, final TkhCalculator tkhCalculator) {
+
+        this.riverInfoProvider = riverInfoProvider;
+
+        this.dischargeProvider = dischargeProvider;
+        this.bedHeight = bedHeight;
+        this.tkhCalculator = tkhCalculator;
+
+        this.wstInterpolator = DoubleUtil.getLinearInterpolator(wstKms.allKms(), wstKms.allWs());
+
+        this.bedHeightLabel = bedHeight.getInfo().getDescription();
+        this.wstLabel = wstKms.getName();
+    }
+
+    public FlowDepthCalculationResult execute(final String label, final WstInfo wstInfo, final DoubleRange calcRange) {
+
+        final Collection<Double> stations = this.bedHeight.getStations();
+        for (final Double station : stations) {
+            if (calcRange.containsDouble(station))
+                calculateResultRow(station);
+        }
+
+        return new FlowDepthCalculationResult(label, wstInfo, this.bedHeight.getInfo(), this.tkhCalculator != null, this.rows);
+    }
+
+    private void calculateResultRow(final double station) {
+
+        try {
+            // FIXME: check out of range of waterlevel?
+            final double wst = this.wstInterpolator.value(station);
+
+            final Tkh tkh = calculateTkh(station, wst);
+
+            final double meanBedHeight = tkh.getMeanBedHeight();
+
+            final double flowDepth = wst - meanBedHeight;
+            final double flowDepthTkh = calculateFlowDepthTkh(tkh, wst, meanBedHeight);
+
+            // REMARK: access the location once only during calculation
+            final String location = this.riverInfoProvider.getLocation(station);
+
+            // REMARK: access the gauge once only during calculation
+            final String gaugeLabel = this.riverInfoProvider.findGauge(station);
+
+            this.rows.add(new FlowDepthRow(flowDepth, flowDepthTkh, tkh, this.wstLabel, gaugeLabel, this.bedHeightLabel, location));
+        }
+        catch (final FunctionEvaluationException e) {
+            /* should only happen if out of range */
+            e.printStackTrace();
+            /* simply ignore */
+        }
+    }
+
+    private Tkh calculateTkh(final double station, final double wst) throws FunctionEvaluationException {
+        if (this.tkhCalculator == null) {
+            final double discharge = this.dischargeProvider.getDischarge(station);
+            final double meanBedHeight = this.bedHeight.getMeanBedHeight(station);
+            return new Tkh(station, wst, meanBedHeight, discharge);
+        }
+
+        return this.tkhCalculator.getTkh(station, wst);
+    }
+
+    private double calculateFlowDepthTkh(final Tkh tkh, final double wst, final double meanBedHeight) {
+        final double tkhValue = tkh.getTkh();
+        final SoilKind tkhKind = tkh.getKind();
+
+        if (Double.isNaN(tkhValue) || tkhKind == null)
+            return Double.NaN;
+
+        switch (tkhKind) {
+        case starr:
+            return wst - (meanBedHeight + tkhValue / 100);
+
+        case mobil:
+        default:
+            return wst - (meanBedHeight + tkhValue / 200);
+        }
+    }
+}
\ No newline at end of file

http://dive4elements.wald.intevation.org