comparison 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
comparison
equal deleted inserted replaced
8914:e3519c3e7a0a 8915:d9dbf0b74bc2
1 /** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde
2 * Software engineering by
3 * Björnsen Beratende Ingenieure GmbH
4 * Dr. Schumacher Ingenieurbüro für Wasser und Umwelt
5 *
6 * This file is Free Software under the GNU AGPL (>=v3)
7 * and comes with ABSOLUTELY NO WARRANTY! Check out the
8 * documentation coming with Dive4Elements River for details.
9 */
10 package org.dive4elements.river.artifacts.sinfo.tkhstate;
11
12 import java.util.ArrayList;
13 import java.util.Collection;
14
15 import org.apache.commons.lang.math.DoubleRange;
16 import org.dive4elements.artifacts.CallContext;
17 import org.dive4elements.river.artifacts.WINFOArtifact;
18 import org.dive4elements.river.artifacts.model.Calculation;
19 import org.dive4elements.river.artifacts.model.Calculation.Problem;
20 import org.dive4elements.river.artifacts.model.CalculationResult;
21 import org.dive4elements.river.artifacts.model.WQKms;
22 import org.dive4elements.river.artifacts.resources.Resources;
23 import org.dive4elements.river.artifacts.sinfo.SINFOArtifact;
24 import org.dive4elements.river.artifacts.sinfo.common.RiverInfoProvider;
25 import org.dive4elements.river.artifacts.sinfo.tkhcalculation.DischargeValuesFinder;
26 import org.dive4elements.river.artifacts.sinfo.tkhcalculation.Tkh;
27 import org.dive4elements.river.artifacts.sinfo.tkhcalculation.TkhCalculator;
28 import org.dive4elements.river.artifacts.sinfo.util.CalculationUtils;
29 import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
30 import org.dive4elements.river.artifacts.sinfo.util.WstInfo;
31 import org.dive4elements.river.artifacts.states.WaterlevelData;
32 import org.dive4elements.river.model.River;
33
34 /**
35 * @author Gernot Belger
36 */
37 final class TkhCalculation {
38
39 private final CallContext context;
40
41 public TkhCalculation(final CallContext context) {
42 this.context = context;
43 }
44
45 public CalculationResult calculate(final SINFOArtifact sinfo) {
46
47 /* access input data */
48 final TkhAccess access = new TkhAccess(sinfo);
49 final River river = access.getRiver();
50 final RiverInfo riverInfo = new RiverInfo(river);
51 final DoubleRange calcRange = access.getRange();
52
53 final Calculation problems = new Calculation();
54
55 /* find relevant bed-heights */
56 final Collection<BedHeightsFinder> bedHeights = BedHeightsFinder.createTkhBedHeights(river, problems, calcRange);
57
58 /* calculate waterlevels */
59 final WQKms[] kms = calculateWaterlevels(sinfo, problems);
60
61 final RiverInfoProvider infoProvider = RiverInfoProvider.forRange(this.context, river, calcRange);
62
63 final String user = CalculationUtils.findArtifactUser(this.context, sinfo);
64
65 final String calcModeLabel = Resources.getMsg(this.context.getMeta(), sinfo.getCalculationMode().name());
66
67 /* for each waterlevel, do a tkh calculation */
68 final TkhCalculationResults results = new TkhCalculationResults(calcModeLabel, user, riverInfo, calcRange);
69
70 for (final WQKms wqKms : kms) {
71
72 final TkhCalculationResult result = calculateResult(calcRange, infoProvider, wqKms, bedHeights, problems);
73 if (result != null)
74 // FIXME: must be sorted by station!
75 results.addResult(result);
76 }
77
78 return new CalculationResult(results, problems);
79 }
80
81 private WQKms[] calculateWaterlevels(final SINFOArtifact sinfo, final Calculation problems) {
82
83 /* misuse winfo-artifact to calculate waterlevels in the same way */
84 final WINFOArtifact winfo = new WinfoArtifactWrapper(sinfo);
85
86 final CalculationResult waterlevelData = winfo.getWaterlevelData(this.context);
87
88 /* copy all problems */
89 final Calculation winfoProblems = waterlevelData.getReport();
90 for (final Problem problem : winfoProblems.getProblems()) {
91 problems.addProblem(problem);
92 }
93
94 return (WQKms[]) waterlevelData.getData();
95 }
96
97 private TkhCalculationResult calculateResult(final DoubleRange calcRange, final RiverInfoProvider riverInfo, final WQKms wkms,
98 final Collection<BedHeightsFinder> bedHeights, final Calculation problems) {
99
100 // FIXME: wo kommt das her? via winfo kein jahr vorhanden, oder doch? aber soll in metadaten ausgegeben werden...
101 final int wspYear = -1;
102 // FIXME: richtig? vgl. WInfo?
103 final boolean showAllGauges = false;
104 final WaterlevelData waterlevel = new WaterlevelData(wkms, wspYear, showAllGauges);
105
106 final RiverInfoProvider riverInfoProvider = riverInfo.forWaterlevel(waterlevel);
107
108 final String label = waterlevel.getName();
109
110 final WstInfo wstInfo = new WstInfo(label, wspYear, riverInfoProvider.getReferenceGauge());
111
112 final Collection<TkhResultRow> rows = new ArrayList<>();
113
114 /*
115 * for each separate bed height dataset we do the calculation and put everything into one result, bed heights must not
116 * overlap accordingly
117 */
118 for (final BedHeightsFinder bedHeightsProvider : bedHeights) {
119
120 final DischargeValuesFinder dischargeProvider = DischargeValuesFinder.fromKms(wkms);
121
122 /* initialize tkh calculator */
123 final TkhCalculator tkhCalculator = TkhCalculator.buildTkhCalculator(true, this.context, problems, label, riverInfoProvider.getRiver(), calcRange,
124 dischargeProvider, bedHeightsProvider);
125 if (tkhCalculator == null) {
126 /* just abort, problems have already been updated by buildTkhCalculator() */
127 return null;
128 }
129
130 /* using wst-kms as basis, because we know that they are generated wst's with a fixed km-step */
131
132 // FIXME: das führt dazu, das aktuell die Sohlhöhen beliebig linear interpolierrt werden. ist das immer richtig? z.b.
133 // bei großen abständen?
134
135 final int size = wkms.size();
136 for (int i = 0; i < size; i++) {
137
138 final double station = wkms.getKm(i);
139 final double wst = wkms.getW(i);
140
141 final Tkh tkh = tkhCalculator.getTkh(station, wst);
142
143 final String gaugeLabel = riverInfoProvider.findGauge(station);
144 final String location = riverInfoProvider.getLocation(station);
145
146 rows.add(new TkhResultRow(tkh, label, gaugeLabel, location));
147 }
148 }
149
150 return new TkhCalculationResult(label, wstInfo, true, rows);
151 }
152 }

http://dive4elements.wald.intevation.org