Mercurial > dive4elements > river
comparison artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineCalculator.java @ 9504:76c0665888a3
No rounding during calculation (Meilenstein-2 2.4.2 and 2.9), delta-w-cm as double (for historical scenario)
author | mschaefer |
---|---|
date | Fri, 28 Sep 2018 10:13:09 +0200 |
parents | 853f2dafc16e |
children | 8b7bf26b8782 |
comparison
equal
deleted
inserted
replaced
9503:83e6acdf8fc6 | 9504:76c0665888a3 |
---|---|
7 * and comes with ABSOLUTELY NO WARRANTY! Check out the | 7 * and comes with ABSOLUTELY NO WARRANTY! Check out the |
8 * documentation coming with Dive4Elements River for details. | 8 * documentation coming with Dive4Elements River for details. |
9 */ | 9 */ |
10 package org.dive4elements.river.artifacts.uinfo.salix; | 10 package org.dive4elements.river.artifacts.uinfo.salix; |
11 | 11 |
12 import java.math.BigDecimal; | |
13 import java.util.ArrayList; | 12 import java.util.ArrayList; |
14 import java.util.Collection; | 13 import java.util.Collection; |
15 import java.util.List; | 14 import java.util.List; |
16 import java.util.Map.Entry; | 15 import java.util.Map.Entry; |
17 import java.util.NavigableMap; | 16 import java.util.NavigableMap; |
18 | 17 |
19 import org.dive4elements.river.artifacts.WINFOArtifact; | 18 import org.dive4elements.river.artifacts.WINFOArtifact; |
20 import org.dive4elements.river.artifacts.access.ComputationRangeAccess; | 19 import org.dive4elements.river.artifacts.access.ComputationRangeAccess; |
21 import org.dive4elements.river.artifacts.common.AbstractResultType; | |
22 import org.dive4elements.river.artifacts.common.GeneralResultType; | 20 import org.dive4elements.river.artifacts.common.GeneralResultType; |
23 import org.dive4elements.river.artifacts.common.ResultRow; | 21 import org.dive4elements.river.artifacts.common.ResultRow; |
24 import org.dive4elements.river.artifacts.model.Calculation; | 22 import org.dive4elements.river.artifacts.model.Calculation; |
25 import org.dive4elements.river.artifacts.model.river.MainWstValuesCalculator; | 23 import org.dive4elements.river.artifacts.model.river.MainWstValuesCalculator; |
26 import org.dive4elements.river.artifacts.model.river.RiverInfoProvider; | 24 import org.dive4elements.river.artifacts.model.river.RiverInfoProvider; |
27 import org.dive4elements.river.artifacts.sinfo.tkhstate.WinfoArtifactWrapper; | 25 import org.dive4elements.river.artifacts.sinfo.tkhstate.WinfoArtifactWrapper; |
28 import org.dive4elements.river.artifacts.uinfo.UINFOArtifact; | 26 import org.dive4elements.river.artifacts.uinfo.UINFOArtifact; |
29 import org.dive4elements.river.artifacts.uinfo.common.UInfoResultType; | 27 import org.dive4elements.river.artifacts.uinfo.common.UInfoResultType; |
30 import org.dive4elements.river.artifacts.uinfo.salix.SalixLineAccess.ScenarioType; | 28 import org.dive4elements.river.artifacts.uinfo.salix.SalixLineAccess.ScenarioType; |
31 import org.dive4elements.river.artifacts.uinfo.vegetationzones.VegetationZoneServerClientXChange; | |
32 import org.dive4elements.river.utils.Formatter; | |
33 | 29 |
34 /** | 30 /** |
35 * Calculation of the result rows of the u-info salix line calc mode | 31 * Calculation of the result rows of the u-info salix line calc mode |
36 * | 32 * |
37 * @author Matthias Schäfer | 33 * @author Matthias Schäfer |
38 */ | 34 */ |
39 final class SalixLineCalculator { | 35 final class SalixLineCalculator { |
40 | 36 |
41 private static final String MAIN_VALUE_MNQ = "mnq"; | 37 private static final String MAIN_VALUE_MNQ = "MNQ"; |
42 | 38 |
43 private static final String MAIN_VALUE_MQ = "mq"; | 39 private static final String MAIN_VALUE_MQ = "MQ"; |
44 | 40 |
45 private static final String MAIN_VALUE_MHQ = "mhq"; | 41 private static final String MAIN_VALUE_MHQ = "MHQ"; |
46 | 42 |
47 private static final String MAIN_VALUE_HQ5 = "hq5"; | 43 private static final String MAIN_VALUE_HQ5 = "HQ5"; |
48 | 44 |
49 private static final BigDecimal SALIX_DISTANCE = new BigDecimal("2.31"); | 45 private static final double SALIX_DISTANCE = 2.31; |
50 private final List<ResultRow> rows = new ArrayList<>(); | 46 private final List<ResultRow> rows = new ArrayList<>(); |
51 | 47 |
52 private final RiverInfoProvider riverInfoProvider; | 48 private final RiverInfoProvider riverInfoProvider; |
53 | 49 |
50 | |
54 public SalixLineCalculator(final RiverInfoProvider riverInfoProvider) { | 51 public SalixLineCalculator(final RiverInfoProvider riverInfoProvider) { |
55 this.riverInfoProvider = riverInfoProvider; | 52 this.riverInfoProvider = riverInfoProvider; |
56 } | 53 } |
54 | |
57 | 55 |
58 /** | 56 /** |
59 * Calculate the salix line result rows | 57 * Calculate the salix line result rows |
60 */ | 58 */ |
61 public void execute(final Calculation problems, final UINFOArtifact uinfo, final NavigableMap<Double, List<Double>> rangeScenarios, | 59 public void execute(final Calculation problems, final UINFOArtifact uinfo, final NavigableMap<Double, List<Double>> rangeScenarios, |
96 return mainWstValues; | 94 return mainWstValues; |
97 } | 95 } |
98 | 96 |
99 /** | 97 /** |
100 * Create a result row for a station and its gauge, and add w-q-values as selected | 98 * Create a result row for a station and its gauge, and add w-q-values as selected |
101 * | |
102 * @param mainWstValues | |
103 */ | 99 */ |
104 private ResultRow createRow(final MainWstValuesCalculator mainWstValues, final double station, final NavigableMap<Double, List<Double>> rangeScenarios) { | 100 private ResultRow createRow(final MainWstValuesCalculator mainWstValues, final double station, final NavigableMap<Double, List<Double>> rangeScenarios) { |
105 | 101 |
106 final ResultRow row = ResultRow.create(); | 102 final ResultRow row = ResultRow.create(); |
107 row.putValue(GeneralResultType.station, station); | 103 row.putValue(GeneralResultType.station, station); |
121 row.putValue(UInfoResultType.waterlevelMH5, hw5); | 117 row.putValue(UInfoResultType.waterlevelMH5, hw5); |
122 | 118 |
123 // Calc salix-line and mw-mnw | 119 // Calc salix-line and mw-mnw |
124 row.putValue(UInfoResultType.salixline, calcSalix(mhw, mw, 0.0)); | 120 row.putValue(UInfoResultType.salixline, calcSalix(mhw, mw, 0.0)); |
125 row.putValue(UInfoResultType.salix_mw_mnw, calcMwmnw(mw, mnw)); | 121 row.putValue(UInfoResultType.salix_mw_mnw, calcMwmnw(mw, mnw)); |
126 final double salixw = Formatter.roundW(mhw).subtract(SALIX_DISTANCE).doubleValue(); | 122 final double salixw = mhw - SALIX_DISTANCE; |
127 row.putValue(UInfoResultType.salixw, salixw); | 123 row.putValue(UInfoResultType.salixw, salixw); |
128 // Calc scenario values (always all scenario types set, Result variant extracts the fields needed) | 124 // Calc scenario values (always all scenario types set, Result variant extracts the fields needed) |
129 final List<SalixScenario> scenarios = new ArrayList<>(); | 125 final List<SalixScenario> scenarios = new ArrayList<>(); |
130 final List<Double> deltaws = getDeltaWs(station, rangeScenarios); | 126 final List<Double> deltaws = getDeltaWs(station, rangeScenarios); |
131 for (final Double deltaw : deltaws) { | 127 for (final Double deltaw : deltaws) { |
132 if (deltaw != null) { | 128 if (deltaw != null) { |
133 final double salix = calcSalix(mhw, mw, deltaw.doubleValue()); | 129 final double salix = calcSalix(mhw, mw, deltaw.doubleValue()); |
134 final double scen = calcSalix(mhw, 0.0, deltaw.doubleValue()); | 130 final double scen = calcSalix(mhw, 0.0, deltaw.doubleValue()); |
135 scenarios.add(new SalixScenario((int) (deltaw * 100), salix, scen)); | 131 scenarios.add(new SalixScenario(deltaw * 100, salix, scen)); |
136 } else { | 132 } else { |
137 scenarios.add(null); | 133 scenarios.add(null); |
138 } | 134 } |
139 } | 135 } |
140 row.putValue(UInfoResultType.customMultiRowColSalixScenarios, scenarios); | 136 row.putValue(UInfoResultType.customMultiRowColSalixScenarios, scenarios); |
146 * Calculates the salix value | 142 * Calculates the salix value |
147 */ | 143 */ |
148 private double calcSalix(final double mhw, final double mw, final double deltamw) { | 144 private double calcSalix(final double mhw, final double mw, final double deltamw) { |
149 if (Double.isNaN(mw) || Double.isInfinite(mw) || Double.isNaN(mhw) || Double.isInfinite(mhw)) | 145 if (Double.isNaN(mw) || Double.isInfinite(mw) || Double.isNaN(mhw) || Double.isInfinite(mhw)) |
150 return mhw - mw; // preserving NaN or Infinity | 146 return mhw - mw; // preserving NaN or Infinity |
151 return Formatter.roundW(mhw).subtract(SALIX_DISTANCE).subtract(Formatter.roundW(mw).add(Formatter.roundW(deltamw))).doubleValue(); | 147 return mhw - SALIX_DISTANCE - mw - deltamw; |
152 } | 148 } |
153 | 149 |
154 /** | 150 /** |
155 * Calculates the inverse MW-MNW difference | 151 * Calculates the inverse MW-MNW difference |
156 */ | 152 */ |
157 private double calcMwmnw(final double mw, final double mnw) { | 153 private double calcMwmnw(final double mw, final double mnw) { |
158 if (Double.isNaN(mw) || Double.isInfinite(mw) || Double.isNaN(mnw) || Double.isInfinite(mnw)) | 154 if (Double.isNaN(mw) || Double.isInfinite(mw) || Double.isNaN(mnw) || Double.isInfinite(mnw)) |
159 return mnw - mw; // preserving NaN or Inifinity | 155 return mnw - mw; // preserving NaN or Inifinity |
160 return Formatter.roundW(mnw).subtract(Formatter.roundW(mw)).doubleValue(); | 156 return mnw - mw; |
161 } | 157 } |
162 | 158 |
163 /** | 159 /** |
164 * Gets the station-specific list of delta-ws of the active scenario, at least with one null item in any case | 160 * Gets the station-specific list of delta-ws of the active scenario, at least with one null item in any case |
165 */ | 161 */ |
172 noScen.add(null); | 168 noScen.add(null); |
173 return noScen; | 169 return noScen; |
174 } | 170 } |
175 | 171 |
176 /** | 172 /** |
177 * Find and return a height (iota, w main value) of a station in a previously calculated result | |
178 */ | |
179 public double fetchStationHeight(final Calculation problems, final double station, final AbstractResultType resultType, | |
180 final SalixLineCalculationResult result) { | |
181 | |
182 // Search the station in the previously calculated result rows | |
183 final ResultRow stationRow = searchStation(station, result.getRows()); | |
184 if (stationRow != null) | |
185 return stationRow.getDoubleValue(resultType); | |
186 return Double.NaN; | |
187 } | |
188 | |
189 /** | |
190 * Searches the row of a station in a result rows collection | 173 * Searches the row of a station in a result rows collection |
191 */ | 174 */ |
192 private ResultRow searchStation(final double station, final Collection<ResultRow> rows) { | 175 private ResultRow searchStation(final double station, final Collection<ResultRow> rows) { |
193 for (final ResultRow row : rows) { | 176 for (final ResultRow row : rows) { |
194 if (row.getDoubleValue(GeneralResultType.station) > station + 0.0001) | 177 if (row.getDoubleValue(GeneralResultType.station) > station + 0.0001) |
195 return row; | 178 return row; |
196 } | 179 } |
197 return null; | 180 return null; |
198 } | 181 } |
199 | |
200 /** | |
201 * Computes the height of a vegetation zone limit for a station and a previously computed salix line result | |
202 */ | |
203 public double computeVegetationZoneHeight(final Calculation problems, final double station, final int vegetationZoneType, | |
204 final SalixLineCalculationResult result) { | |
205 | |
206 // Search the station in the previously calculated result rows | |
207 final ResultRow stationRow = searchStation(station, result.getRows()); | |
208 if (stationRow == null) | |
209 return Double.NaN; | |
210 | |
211 // Compute height from overflow duration days | |
212 final List<VegetationZoneServerClientXChange> vzs = VegetationZoneServerClientXChange.getStandardList(null, null); // TODO river, context | |
213 if ((vegetationZoneType >= 1) && (vegetationZoneType <= vzs.size())) { | |
214 final int uefd = vzs.get(vegetationZoneType - 1).getMin_day_overflow(); | |
215 // Üfd = -70,559 ∗ ln((DGM - MW) + 0,5) + 80,711 | |
216 final double f1 = -70.559; | |
217 final double f2 = -88.711; | |
218 final double mw = stationRow.getDoubleValue(UInfoResultType.waterlevelMW); | |
219 final double dgm = Math.exp((uefd - f2) / f1) + mw - 0.5; | |
220 return dgm; | |
221 } | |
222 return Double.NaN; | |
223 } | |
224 } | 182 } |