Mercurial > dive4elements > river
diff flys-artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixATWriter.java @ 5831:bd047b71ab37
Repaired internal references
author | Sascha L. Teichmann <teichmann@intevation.de> |
---|---|
date | Thu, 25 Apr 2013 12:06:39 +0200 |
parents | flys-artifacts/src/main/java/de/intevation/flys/exports/fixings/FixATWriter.java@8bbb9e173297 |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixATWriter.java Thu Apr 25 12:06:39 2013 +0200 @@ -0,0 +1,187 @@ +package org.dive4elements.river.exports.fixings; + +import org.dive4elements.artifacts.CallMeta; + +import org.dive4elements.river.artifacts.math.fitting.Function; + +import org.dive4elements.river.artifacts.model.Parameters; + +import org.dive4elements.river.artifacts.resources.Resources; + +import org.dive4elements.river.exports.ATWriter; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.Writer; + +import java.util.Locale; + +import org.apache.log4j.Logger; + +/** Export Fixation Analysis Results to AT. */ +public class FixATWriter +{ + /** Private logger. */ + private static Logger log = Logger.getLogger(FixATWriter.class); + + public static final String I18N_HEADER_KEY = + "fix.export.at.header"; + + public static final String I18N_HEADER_DEFAULT = + "Exported fixings discharge curve for {0} {0}-km: {1}"; + + public static final String [] Q_MAX_COLUMN = new String [] { "max_q" }; + + private static final int MAX_ITERATIONS = 10000; + private static final double EPSILON = 1e-8; + private static final double MIN_Q = 1e-4; + + protected Function function; + protected Parameters parameters; + + public FixATWriter() { + } + + public FixATWriter(Function function, Parameters parameters) { + this.function = function; + this.parameters = parameters; + } + + public void write( + Writer writer, + CallMeta meta, + String river, + double km + ) + throws IOException { + PrintWriter out = new PrintWriter(writer); + printHeader(out, meta, river, km); + + double [] coeffs = parameters.interpolate( + "km", km, function.getParameterNames()); + + double [] qMax = parameters.interpolate( + "km", km, Q_MAX_COLUMN); + + if (coeffs == null || qMax == null) { + log.debug("No data found at km " + km + "."); + return; + } + + org.dive4elements.river.artifacts.math.Function funcInst = + function.instantiate(coeffs); + + // Increase Q max about 5%. + qMax[0] += Math.abs(qMax[0])*0.05; + + double wMax = funcInst.value(qMax[0]); + + if (Double.isNaN(wMax) || wMax < 0d) { + log.debug("function '" + function.getName() + + "' eval failed at " + wMax); + return; + } + + Function inverse = function.getInverse(); + + org.dive4elements.river.artifacts.math.Function invInst = + inverse.instantiate(coeffs); + + double wMin = minW(invInst, wMax, qMax[0]); + + double wMinCM = wMin * 100d; + double wMaxCM = wMax * 100d; + + int wRow = ((int)wMinCM / 10) * 10; + + if ((wMinCM - (int)wMinCM) > 0d) { + wMinCM = (int)wMinCM + 1d; + } + + double w = wMinCM / 100.0; + + int wcm = ((int)wMinCM) % 10; + + if (log.isDebugEnabled()) { + log.debug("wMinCM: " + wMinCM); + log.debug("wMaxCM: " + wMaxCM); + log.debug("wcm: " + wcm); + } + + out.printf(Locale.US, "%8d", wRow); + + if (wcm > 0) { + int rest = 10 - wcm; + while (rest-- > 0) { + out.print(ATWriter.EMPTY); + } + } + + for (;;) { + while (wcm++ < 10) { + if (w > wMax) { + break; + } + double q = invInst.value(w); + if (Double.isNaN(w)) { + out.print(ATWriter.EMPTY); + } + else { + ATWriter.printQ(out, q); + } + w += 0.01d; + } + out.println(); + if (w > wMax) { + break; + } + out.printf(Locale.US, "%8d", wRow += 10); + wcm = 0; + } + + out.flush(); + } + + protected void printHeader( + PrintWriter out, + CallMeta meta, + String river, + double km + ) { + out.println(Resources.format( + meta, + I18N_HEADER_KEY, + I18N_HEADER_DEFAULT, + river, km)); + } + + private static double minW( + org.dive4elements.river.artifacts.math.Function function, + double maxW, + double maxQ + ) { + double stepWidth = 10d; + + double lastW = maxW; + double lastQ = maxQ; + + for (int i = 0; i < MAX_ITERATIONS; ++i) { + double w = lastW - stepWidth; + double q = function.value(w); + + if (Double.isNaN(q) || q > lastQ || q < MIN_Q) { + if (stepWidth < EPSILON) { + break; + } + stepWidth *= 0.5d; + continue; + } + + lastW = w; + lastQ = q; + } + + return lastW; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :