diff artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/tkhstate/TkhCalculation.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 5d5d0051723f
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/tkhstate/TkhCalculation.java	Wed Feb 28 17:27:15 2018 +0100
@@ -0,0 +1,152 @@
+/** 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.tkhstate;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.apache.commons.lang.math.DoubleRange;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.WINFOArtifact;
+import org.dive4elements.river.artifacts.model.Calculation;
+import org.dive4elements.river.artifacts.model.Calculation.Problem;
+import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.model.WQKms;
+import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.artifacts.sinfo.SINFOArtifact;
+import org.dive4elements.river.artifacts.sinfo.common.RiverInfoProvider;
+import org.dive4elements.river.artifacts.sinfo.tkhcalculation.DischargeValuesFinder;
+import org.dive4elements.river.artifacts.sinfo.tkhcalculation.Tkh;
+import org.dive4elements.river.artifacts.sinfo.tkhcalculation.TkhCalculator;
+import org.dive4elements.river.artifacts.sinfo.util.CalculationUtils;
+import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
+import org.dive4elements.river.artifacts.sinfo.util.WstInfo;
+import org.dive4elements.river.artifacts.states.WaterlevelData;
+import org.dive4elements.river.model.River;
+
+/**
+ * @author Gernot Belger
+ */
+final class TkhCalculation {
+
+    private final CallContext context;
+
+    public TkhCalculation(final CallContext context) {
+        this.context = context;
+    }
+
+    public CalculationResult calculate(final SINFOArtifact sinfo) {
+
+        /* access input data */
+        final TkhAccess access = new TkhAccess(sinfo);
+        final River river = access.getRiver();
+        final RiverInfo riverInfo = new RiverInfo(river);
+        final DoubleRange calcRange = access.getRange();
+
+        final Calculation problems = new Calculation();
+
+        /* find relevant bed-heights */
+        final Collection<BedHeightsFinder> bedHeights = BedHeightsFinder.createTkhBedHeights(river, problems, calcRange);
+
+        /* calculate waterlevels */
+        final WQKms[] kms = calculateWaterlevels(sinfo, problems);
+
+        final RiverInfoProvider infoProvider = RiverInfoProvider.forRange(this.context, river, calcRange);
+
+        final String user = CalculationUtils.findArtifactUser(this.context, sinfo);
+
+        final String calcModeLabel = Resources.getMsg(this.context.getMeta(), sinfo.getCalculationMode().name());
+
+        /* for each waterlevel, do a tkh calculation */
+        final TkhCalculationResults results = new TkhCalculationResults(calcModeLabel, user, riverInfo, calcRange);
+
+        for (final WQKms wqKms : kms) {
+
+            final TkhCalculationResult result = calculateResult(calcRange, infoProvider, wqKms, bedHeights, problems);
+            if (result != null)
+                // FIXME: must be sorted by station!
+                results.addResult(result);
+        }
+
+        return new CalculationResult(results, problems);
+    }
+
+    private WQKms[] calculateWaterlevels(final SINFOArtifact sinfo, final Calculation problems) {
+
+        /* misuse winfo-artifact to calculate waterlevels in the same way */
+        final WINFOArtifact winfo = new WinfoArtifactWrapper(sinfo);
+
+        final CalculationResult waterlevelData = winfo.getWaterlevelData(this.context);
+
+        /* copy all problems */
+        final Calculation winfoProblems = waterlevelData.getReport();
+        for (final Problem problem : winfoProblems.getProblems()) {
+            problems.addProblem(problem);
+        }
+
+        return (WQKms[]) waterlevelData.getData();
+    }
+
+    private TkhCalculationResult calculateResult(final DoubleRange calcRange, final RiverInfoProvider riverInfo, final WQKms wkms,
+            final Collection<BedHeightsFinder> bedHeights, final Calculation problems) {
+
+        // FIXME: wo kommt das her? via winfo kein jahr vorhanden, oder doch? aber soll in metadaten ausgegeben werden...
+        final int wspYear = -1;
+        // FIXME: richtig? vgl. WInfo?
+        final boolean showAllGauges = false;
+        final WaterlevelData waterlevel = new WaterlevelData(wkms, wspYear, showAllGauges);
+
+        final RiverInfoProvider riverInfoProvider = riverInfo.forWaterlevel(waterlevel);
+
+        final String label = waterlevel.getName();
+
+        final WstInfo wstInfo = new WstInfo(label, wspYear, riverInfoProvider.getReferenceGauge());
+
+        final Collection<TkhResultRow> rows = new ArrayList<>();
+
+        /*
+         * for each separate bed height dataset we do the calculation and put everything into one result, bed heights must not
+         * overlap accordingly
+         */
+        for (final BedHeightsFinder bedHeightsProvider : bedHeights) {
+
+            final DischargeValuesFinder dischargeProvider = DischargeValuesFinder.fromKms(wkms);
+
+            /* initialize tkh calculator */
+            final TkhCalculator tkhCalculator = TkhCalculator.buildTkhCalculator(true, this.context, problems, label, riverInfoProvider.getRiver(), calcRange,
+                    dischargeProvider, bedHeightsProvider);
+            if (tkhCalculator == null) {
+                /* just abort, problems have already been updated by buildTkhCalculator() */
+                return null;
+            }
+
+            /* using wst-kms as basis, because we know that they are generated wst's with a fixed km-step */
+
+            // FIXME: das führt dazu, das aktuell die Sohlhöhen beliebig linear interpolierrt werden. ist das immer richtig? z.b.
+            // bei großen abständen?
+
+            final int size = wkms.size();
+            for (int i = 0; i < size; i++) {
+
+                final double station = wkms.getKm(i);
+                final double wst = wkms.getW(i);
+
+                final Tkh tkh = tkhCalculator.getTkh(station, wst);
+
+                final String gaugeLabel = riverInfoProvider.findGauge(station);
+                final String location = riverInfoProvider.getLocation(station);
+
+                rows.add(new TkhResultRow(tkh, label, gaugeLabel, location));
+            }
+        }
+
+        return new TkhCalculationResult(label, wstInfo, true, rows);
+    }
+}
\ No newline at end of file

http://dive4elements.wald.intevation.org