diff artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineCalculator.java @ 9295:385b52ccde23

Work on U-Info salix line calculation and chart (no scenario case)
author mschaefer
date Tue, 24 Jul 2018 18:51:47 +0200
parents
children 9a9f076d5716
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineCalculator.java	Tue Jul 24 18:51:47 2018 +0200
@@ -0,0 +1,153 @@
+/** 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.uinfo.salix;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.WINFOArtifact;
+import org.dive4elements.river.artifacts.access.ComputationRangeAccess;
+import org.dive4elements.river.artifacts.common.GeneralResultType;
+import org.dive4elements.river.artifacts.common.ResultRow;
+import org.dive4elements.river.artifacts.model.Calculation;
+import org.dive4elements.river.artifacts.model.WstValueTable;
+import org.dive4elements.river.artifacts.model.WstValueTable.QPosition;
+import org.dive4elements.river.artifacts.model.WstValueTableFactory;
+import org.dive4elements.river.artifacts.sinfo.common.GaugeDischargeValuesFinder;
+import org.dive4elements.river.artifacts.sinfo.common.RiverInfoProvider;
+import org.dive4elements.river.artifacts.sinfo.common.SInfoResultType;
+import org.dive4elements.river.artifacts.sinfo.tkhstate.WinfoArtifactWrapper;
+import org.dive4elements.river.artifacts.uinfo.UINFOArtifact;
+import org.dive4elements.river.artifacts.uinfo.commons.UInfoResultType;
+import org.dive4elements.river.model.Gauge;
+import org.dive4elements.river.model.MainValue;
+import org.dive4elements.river.model.MainValueType.MainValueTypeKey;
+
+/**
+ * Calculation of the result rows of the u-info salix line calc mode
+ *
+ * @author Matthias Schäfer
+ */
+public class SalixLineCalculator {
+
+    private final List<ResultRow> rows = new ArrayList<>();
+
+    private final RiverInfoProvider riverInfoProvider;
+
+    private final CallContext context;
+
+    private final Map<Gauge, QPosition> gaugeMwPos;
+    private final Map<Gauge, QPosition> gaugeMnwPos;
+    private final Map<Gauge, QPosition> gaugeMhwPos;
+
+    private Calculation problems;
+
+    private WstValueTable wst;
+
+    public SalixLineCalculator(final CallContext context, final RiverInfoProvider riverInfoProvider) {
+        this.context = context;
+        this.riverInfoProvider = riverInfoProvider;
+        this.gaugeMwPos = new HashMap<>();
+        this.gaugeMnwPos = new HashMap<>();
+        this.gaugeMhwPos = new HashMap<>();
+    }
+
+
+    /**
+     * Calculate the salix line result rows
+     */
+    public void execute(final Calculation problems, final UINFOArtifact uinfo, final SalixLineCalculationResults results) {
+
+        this.problems = problems;
+        this.wst = WstValueTableFactory.getTable(this.riverInfoProvider.getRiver());
+
+        fetchGaugeMainValuePositions();
+
+        final WINFOArtifact winfo = new WinfoArtifactWrapper(uinfo);
+        winfo.addStringData("ld_mode", "distance");
+        winfo.addStringData("ld_step", "100");
+        for (final double station : new ComputationRangeAccess(winfo).getKms()) {
+            this.rows.add(createRow(station));
+        }
+        results.addResult(new SalixLineCalculationNoScenarioResult("Salix", null, this.rows), problems);
+    }
+
+    /**
+     * Fetch MW, MNW and MHW of all gauges and determine the wst QPosition for each one
+     */
+    private void fetchGaugeMainValuePositions() {
+        this.gaugeMwPos.clear();
+        this.gaugeMnwPos.clear();
+        this.gaugeMhwPos.clear();
+        for (final Gauge gauge : this.riverInfoProvider.getGauges()) {
+            this.gaugeMwPos.put(gauge, null);
+            this.gaugeMnwPos.put(gauge, null);
+            this.gaugeMhwPos.put(gauge, null);
+            final GaugeDischargeValuesFinder finder = GaugeDischargeValuesFinder.loadValues(gauge, this.problems);
+            if (finder == null)
+                continue;
+            final double gaugeKm = gauge.getStation().doubleValue();
+            for (final MainValue mv : MainValue.getValuesOfGaugeAndType(gauge, MainValueTypeKey.W)) {
+                if (mv.getMainValue().getName().equalsIgnoreCase("mw"))
+                    this.gaugeMwPos.put(gauge, this.wst.getQPosition(gaugeKm, finder.getDischarge(mv.getValue().doubleValue())));
+                else if (mv.getMainValue().getName().equalsIgnoreCase("mnw"))
+                    this.gaugeMnwPos.put(gauge, this.wst.getQPosition(gaugeKm, finder.getDischarge(mv.getValue().doubleValue())));
+                else if (mv.getMainValue().getName().equalsIgnoreCase("mhw"))
+                    this.gaugeMhwPos.put(gauge, this.wst.getQPosition(gaugeKm, finder.getDischarge(mv.getValue().doubleValue())));
+            }
+        }
+    }
+
+    /**
+     * Create a result row for a station and its gauge, and add w-q-values as selected
+     */
+    private ResultRow createRow(final double station) {
+
+        final ResultRow row = ResultRow.create();
+        final Gauge gauge = this.riverInfoProvider.getGauge(station, true);
+        row.putValue(GeneralResultType.station, station);
+        final double mnw = interpolateW(station, this.gaugeMnwPos.get(gauge));
+        final double mw = interpolateW(station, this.gaugeMwPos.get(gauge));
+        final double mhw = interpolateW(station, this.gaugeMhwPos.get(gauge));
+        row.putValue(SInfoResultType.waterlevel, mnw);
+        row.putValue(SInfoResultType.waterlevel1, mw);
+        row.putValue(SInfoResultType.waterlevel2, mhw);
+        row.putValue(UInfoResultType.salixline, calcSalix(mhw, mw));
+        row.putValue(UInfoResultType.salix_delta_mw, calcMwmnw(mw, mnw));
+        return row;
+    }
+
+    /**
+     * Interpolates the W for a station with a fixed (virtual) wst column position
+     */
+    private double interpolateW(final double station, final QPosition qPosition) {
+        if (qPosition != null)
+            return this.wst.interpolateW(station, qPosition, this.problems);
+        else
+            return Double.NaN;
+    }
+
+    /**
+     * Calculates the salix value
+     */
+    private double calcSalix(final double mhw, final double mw) {
+        return mhw - 2.31 - mw;
+    }
+
+    /**
+     * Calculates the inverse MW-MNW difference
+     */
+    private double calcMwmnw(final double mw, final double mnw) {
+        return mnw - mw;
+    }
+}

http://dive4elements.wald.intevation.org