Mercurial > dive4elements > river
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