/*
* This file is part of JGrasstools (http://www.jgrasstools.org)
* (C) HydroloGIS - www.hydrologis.com
*
* JGrasstools is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.jgrasstools.hortonmachine.modules.networktools.trento_p;
import static java.lang.Math.pow;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSTRENTOP_AUTHORCONTACTS;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSTRENTOP_AUTHORNAMES;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSTRENTOP_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSTRENTOP_KEYWORDS;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSTRENTOP_LABEL;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSTRENTOP_LICENSE;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSTRENTOP_NAME;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSTRENTOP_STATUS;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSTRENTOP_dt_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSTRENTOP_inDiameters_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSTRENTOP_inPipes_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSTRENTOP_inRain_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSTRENTOP_outDischarge_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSTRENTOP_outFillDegree_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSTRENTOP_outPipes_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSTRENTOP_outTpMax_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSTRENTOP_pA_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSTRENTOP_pAccuracy_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSTRENTOP_pAlign_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSTRENTOP_pC_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSTRENTOP_pCelerityFactor_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSTRENTOP_pEpsilon_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSTRENTOP_pEspInflux_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSTRENTOP_pExponent_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSTRENTOP_pFranco_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSTRENTOP_pG_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSTRENTOP_pGamma_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSTRENTOP_pJMax_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSTRENTOP_pMaxJunction_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSTRENTOP_pMaxTheta_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSTRENTOP_pMinDischarge_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSTRENTOP_pMinG_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSTRENTOP_pMinimumDepth_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSTRENTOP_pMode_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSTRENTOP_pN_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSTRENTOP_pOutPipe_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSTRENTOP_pTau_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSTRENTOP_pTolerance_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSTRENTOP_tDTp_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSTRENTOP_tMax_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSTRENTOP_tpMaxCalibration_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSTRENTOP_tpMax_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSTRENTOP_tpMin_DESCRIPTION;
import static org.jgrasstools.hortonmachine.modules.networktools.trento_p.utils.Constants.DEFAULT_ACCURACY;
import static org.jgrasstools.hortonmachine.modules.networktools.trento_p.utils.Constants.DEFAULT_CELERITY_FACTOR;
import static org.jgrasstools.hortonmachine.modules.networktools.trento_p.utils.Constants.DEFAULT_EPSILON;
import static org.jgrasstools.hortonmachine.modules.networktools.trento_p.utils.Constants.DEFAULT_ESP1;
import static org.jgrasstools.hortonmachine.modules.networktools.trento_p.utils.Constants.DEFAULT_EXPONENT;
import static org.jgrasstools.hortonmachine.modules.networktools.trento_p.utils.Constants.DEFAULT_FRANCO;
import static org.jgrasstools.hortonmachine.modules.networktools.trento_p.utils.Constants.DEFAULT_GAMMA;
import static org.jgrasstools.hortonmachine.modules.networktools.trento_p.utils.Constants.DEFAULT_J_MAX;
import static org.jgrasstools.hortonmachine.modules.networktools.trento_p.utils.Constants.DEFAULT_MAX_JUNCTION;
import static org.jgrasstools.hortonmachine.modules.networktools.trento_p.utils.Constants.DEFAULT_MAX_THETA;
import static org.jgrasstools.hortonmachine.modules.networktools.trento_p.utils.Constants.DEFAULT_MING;
import static org.jgrasstools.hortonmachine.modules.networktools.trento_p.utils.Constants.DEFAULT_MINIMUM_DEPTH;
import static org.jgrasstools.hortonmachine.modules.networktools.trento_p.utils.Constants.DEFAULT_MIN_DISCHARGE;
import static org.jgrasstools.hortonmachine.modules.networktools.trento_p.utils.Constants.DEFAULT_TDTP;
import static org.jgrasstools.hortonmachine.modules.networktools.trento_p.utils.Constants.DEFAULT_TMAX;
import static org.jgrasstools.hortonmachine.modules.networktools.trento_p.utils.Constants.DEFAULT_TOLERANCE;
import static org.jgrasstools.hortonmachine.modules.networktools.trento_p.utils.Constants.DEFAULT_TPMIN;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import oms3.annotations.Author;
import oms3.annotations.Description;
import oms3.annotations.Execute;
import oms3.annotations.In;
import oms3.annotations.Keywords;
import oms3.annotations.Label;
import oms3.annotations.License;
import oms3.annotations.Name;
import oms3.annotations.Out;
import oms3.annotations.Range;
import oms3.annotations.Status;
import oms3.annotations.UI;
import oms3.annotations.Unit;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.jgrasstools.gears.libs.modules.JGTModel;
import org.jgrasstools.gears.libs.modules.ModelsEngine;
import org.jgrasstools.gears.libs.monitor.IJGTProgressMonitor;
import org.jgrasstools.gears.utils.sorting.QuickSortAlgorithm;
import org.jgrasstools.hortonmachine.i18n.HortonMessageHandler;
import org.jgrasstools.hortonmachine.modules.networktools.trento_p.net.Network;
import org.jgrasstools.hortonmachine.modules.networktools.trento_p.net.NetworkBuilder;
import org.jgrasstools.hortonmachine.modules.networktools.trento_p.net.NetworkCalibration;
import org.jgrasstools.hortonmachine.modules.networktools.trento_p.net.Pipe;
import org.jgrasstools.hortonmachine.modules.networktools.trento_p.utils.Constants;
import org.jgrasstools.hortonmachine.modules.networktools.trento_p.utils.TrentoPFeatureType;
import org.jgrasstools.hortonmachine.modules.networktools.trento_p.utils.Utility;
import org.joda.time.DateTime;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import com.vividsolutions.jts.geom.Coordinate;
@Description(OMSTRENTOP_DESCRIPTION)
@Author(name = OMSTRENTOP_AUTHORNAMES, contact = OMSTRENTOP_AUTHORCONTACTS)
@Keywords(OMSTRENTOP_KEYWORDS)
@Label(OMSTRENTOP_LABEL)
@Name(OMSTRENTOP_NAME)
@Status(OMSTRENTOP_STATUS)
@License(OMSTRENTOP_LICENSE)
public class OmsTrentoP extends JGTModel {
@Description(OMSTRENTOP_pMode_DESCRIPTION)
@In
public int pMode;
@Description(OMSTRENTOP_pMinimumDepth_DESCRIPTION)
@Unit("m")
@In
public double pMinimumDepth = DEFAULT_MINIMUM_DEPTH;
@Description(OMSTRENTOP_pMaxJunction_DESCRIPTION)
@Unit("-")
@Range(max = 6, min = 0)
@In
public int pMaxJunction = DEFAULT_MAX_JUNCTION;
@Description(OMSTRENTOP_pJMax_DESCRIPTION)
@Unit("-")
@Range(max = 1000, min = 3)
@In
public int pJMax = DEFAULT_J_MAX;
@Description(OMSTRENTOP_pAccuracy_DESCRIPTION)
@Unit("-")
@Range(min = 0)
@In
public Double pAccuracy = DEFAULT_ACCURACY;
@Description(OMSTRENTOP_pEpsilon_DESCRIPTION)
@Unit("-")
@Range(max = 1, min = 0)
@In
public double pEpsilon = DEFAULT_EPSILON;
@Description(OMSTRENTOP_pMinG_DESCRIPTION)
@Unit("-")
@Range(max = 0.1, min = 0)
@In
public double pMinG = DEFAULT_MING;
@Description(OMSTRENTOP_pMinDischarge_DESCRIPTION)
@Unit("m3/s")
@Range(min = 0)
@In
public double pMinDischarge = DEFAULT_MIN_DISCHARGE;
@Description(OMSTRENTOP_pMaxTheta_DESCRIPTION)
@Unit("-")
@Range(min = Math.PI)
@In
public double pMaxTheta = DEFAULT_MAX_THETA;
@Description(OMSTRENTOP_pCelerityFactor_DESCRIPTION)
@Unit("-")
@Range(min = 1, max = 1.6)
@In
public double pCelerityFactor = DEFAULT_CELERITY_FACTOR;
@Description(OMSTRENTOP_pExponent_DESCRIPTION)
@Unit("-")
@Range(min = 0)
@In
public double pExponent = DEFAULT_EXPONENT;
@Description(OMSTRENTOP_pTolerance_DESCRIPTION)
@Unit("-")
@Range(min = 0)
@In
public double pTolerance = DEFAULT_TOLERANCE;
@Description(OMSTRENTOP_pC_DESCRIPTION)
@Unit("-")
@Range(min = 0)
@In
public double pC = 1;
@Description(OMSTRENTOP_pGamma_DESCRIPTION)
@Unit("-")
@Range(min = 0)
@In
public double pGamma = DEFAULT_GAMMA;
@Description(OMSTRENTOP_pEspInflux_DESCRIPTION)
@Unit("-")
@Range(min = 0)
@In
public double pEspInflux = DEFAULT_ESP1;
@Description(OMSTRENTOP_pFranco_DESCRIPTION)
@Unit("m")
@Range(min = 0)
@In
public double pFranco = DEFAULT_FRANCO;
@Description(OMSTRENTOP_pA_DESCRIPTION)
@Unit("-")
@Range(min = 0)
@In
public Double pA;
@Description(OMSTRENTOP_pN_DESCRIPTION)
@Unit("-")
@Range(min = 0.05, max = 0.95)
@In
public Double pN;
@Description(OMSTRENTOP_pTau_DESCRIPTION)
@Unit("N/m2")
@Range(min = 0)
@In
public Double pTau;
@Description(OMSTRENTOP_pG_DESCRIPTION)
@Unit("-")
@Range(min = 0, max = 0.99)
@In
public Double pG;
@Description(OMSTRENTOP_pAlign_DESCRIPTION)
@In
public Integer pAlign;
@Description(OMSTRENTOP_inDiameters_DESCRIPTION)
@UI("infile")
@In
public List<double[]> inDiameters;
@Description(OMSTRENTOP_pOutPipe_DESCRIPTION)
@Unit("-")
@In
public Integer pOutPipe = null;
@Description(OMSTRENTOP_tDTp_DESCRIPTION)
@Unit("-")
@Range(min = 0.015)
@In
public double tDTp = DEFAULT_TDTP;
@Description(OMSTRENTOP_tpMin_DESCRIPTION)
@Unit("-")
@Range(min = 5)
@In
public double tpMin = DEFAULT_TPMIN;
@Description(OMSTRENTOP_tpMax_DESCRIPTION)
@Unit("minutes")
@Range(min = 30)
@In
public double tpMax = DEFAULT_TMAX;
@Description(OMSTRENTOP_tMax_DESCRIPTION)
@Unit("-")
@In
public int tMax = (int) DEFAULT_TMAX;
@Description(OMSTRENTOP_tpMaxCalibration_DESCRIPTION)
@Unit("minutes")
@In
public Integer tpMaxCalibration = null;
@Description(OMSTRENTOP_dt_DESCRIPTION)
@Unit("minutes")
@In
public Integer dt;
@Description(OMSTRENTOP_inRain_DESCRIPTION)
@UI("infile")
@In
public HashMap<DateTime, double[]> inRain = null;
@Description(OMSTRENTOP_inPipes_DESCRIPTION)
@In
public SimpleFeatureCollection inPipes = null;
@Description(OMSTRENTOP_outPipes_DESCRIPTION)
@Out
public SimpleFeatureCollection outPipes = null;
@Description(OMSTRENTOP_outDischarge_DESCRIPTION)
@UI("outfile")
@Out
public HashMap<DateTime, HashMap<Integer, double[]>> outDischarge;
@Description(OMSTRENTOP_outFillDegree_DESCRIPTION)
@UI("outfile")
@Out
public HashMap<DateTime, HashMap<Integer, double[]>> outFillDegree;
@Description(OMSTRENTOP_outTpMax_DESCRIPTION)
@Unit("minutes")
@Out
public Integer outTpMax = null;
/**
* Message handler.
*/
private final HortonMessageHandler msg = HortonMessageHandler.getInstance();
/**
* Is an array with all the pipe of the net.
*/
private Pipe[] networkPipes;
/*
* string which collected all the warnings. the warnings are printed at the
* end of the processes.
*/
private String warnings = "warnings";
public StringBuilder warningBuilder = new StringBuilder(warnings);
/**
* Used in calibration mode if use the generation of the rain.
*/
private boolean foundTp = false;
/**
*
* Elaboration on the net.
*
* <p>
*
* <ol>
* <li>Verify the net throughout the method verify.
* <li>Call the geosewer method which calculate the pipes diameter or the
* discharge.
* </ol>
* </p>
*
* @throws Exception
*
*
* @throw {@link IllegalArgumentException} this is throw to the verify
* methods, if some parameters isn't correct.
* @see {@link NetworkBuilder}
*
*/
@Execute
public void process() throws Exception {
/*
* verify the parameter in input (these method, when the OMS annotation
* work well, can be deleted).
*/
// begin the process.
pm.message(msg.message("trentoP.firstMessage"));
/*
* verify the parameter in input (these method, when the OMS annotation
* work well, can be deleted) andcreate the net as an array of pipes. .
*/
setNetworkPipes(verifyParameter());
/*
* create a network object. It can be a NetworkCalibration if the mode
* (pTest==1) verify otherwise is a NetworkBuilder.
*/
Network network = null;
if (pMode == 1) {
// set other common parameters for the verification.
if (inPipes != null) {
for( int t = 0; t < networkPipes.length; t++ ) {
networkPipes[t].setAccuracy(pAccuracy);
networkPipes[t].setJMax(pJMax);
networkPipes[t].setMaxTheta(pMaxTheta);
networkPipes[t].setTolerance(pTolerance);
networkPipes[t].setK(pEspInflux, pExponent, pGamma);
}
}
outDischarge = new LinkedHashMap<DateTime, HashMap<Integer, double[]>>();
outFillDegree = new LinkedHashMap<DateTime, HashMap<Integer, double[]>>();
// initialize the NetworkCalibration.
network = new NetworkCalibration.Builder(pm, networkPipes, dt, inRain, outDischarge, outFillDegree, warningBuilder,
tpMaxCalibration, foundTp).celerityFactor(pCelerityFactor).tMax(tMax).build();
network.geoSewer();
outTpMax = ((NetworkCalibration) network).getTpMax();
} else {
// set other common parameters for the project.
if (inPipes != null) {
for( int t = 0; t < networkPipes.length; t++ ) {
networkPipes[t].setAccuracy(pAccuracy);
networkPipes[t].setMinimumDepth(pMinimumDepth);
networkPipes[t].setMinG(pMinG);
networkPipes[t].setJMax(pJMax);
networkPipes[t].setMaxJunction(pMaxJunction);
networkPipes[t].setAlign(pAlign);
networkPipes[t].setC(pC);
networkPipes[t].setG(pG);
networkPipes[t].setTau(pTau);
networkPipes[t].setMinDischarge(pMinDischarge);
}
}
pA = pA / pow(60, pN); /* [mm/hour^n] -> [mm/min^n] */
// initialize the NetworkCalibration.
NetworkBuilder.Builder builder = new NetworkBuilder.Builder(pm, networkPipes, pN, pA, inDiameters, inPipes,
warningBuilder);
network = builder.celerityFactor(pCelerityFactor).pEpsilon(pEpsilon).pEsp1(pEspInflux).pExponent(pExponent)
.pGamma(pGamma).tDTp(tDTp).tpMax(tpMax).tpMin(tpMin).build();
network.geoSewer();
outPipes = Utility.createFeatureCollections(inPipes, networkPipes);
}
// elaborate.
String w = warningBuilder.toString();
if (!w.equals(warnings)) {
pm.message(w);
}
pm.message(msg.message("trentoP.end"));
}
/*
* Verifica la validità dei dati, OSSERVAZIONE con OMS non necessaria,
* vedere dichiarazione variabili per il range.
*
* @throw IllegalArgumentException se un parametro non rispetta certe
* condizioni (in OMS3 fatto dalle annotation)
*
* @return true if there is the percentage area.
*/
private boolean verifyParameter() {
// checkNull(inPipes,pAccuracy);
boolean isAreaAllDry;
if (pMode < 0 || pMode > 1) {
pm.errorMessage(msg.message("trentoP.error.mode"));
throw new IllegalArgumentException(msg.message("trentoP.error.mode"));
}
if (inPipes == null) {
pm.errorMessage(msg.message("trentoP.error.inputMatrix") + " geometry file");
throw new IllegalArgumentException(msg.message("trentoP.error.inputMatrix") + " geometry file");
}
/* Il numero di giunzioni in un nodo non puo' superiore a 7 */
if (pMaxJunction <= 0 || pMaxJunction > 6) {
pm.errorMessage(msg.message("trentoP.error.maxJunction"));
throw new IllegalArgumentException();
}
/*
* Il numero di iterazioni ammesso non puo' essere troppo piccolo ne'
* eccessivamente grande
*/
if (pJMax < 3 || pJMax > 1000) {
pm.errorMessage(msg.message("trentoP.error.jMax"));
throw new IllegalArgumentException(msg.message("trentoP.error.jMax"));
}
/*
* La precisione con cui si cercano alcune soluzioni non puo' essere
* negativa
*/
if (pAccuracy == null || pAccuracy <= 0) {
pm.errorMessage(msg.message("trentoP.error.accuracy"));
throw new IllegalArgumentException();
}
/* Intervallo in cui puo variare il riempimento minimo */
if (pMinG <= 0 || pMinG > 0.1) {
pm.errorMessage(msg.message("trentoP.error.minG"));
throw new IllegalArgumentException();
}
/* Non sono ammesse portate minime negative nei tubi */
if (pMinDischarge <= 0) {
pm.errorMessage(msg.message("trentoP.error.minDischarge"));
throw new IllegalArgumentException();
}
/* Il fattore di celerita' deve essere compreso tra 1 e 1.6 */
if (pCelerityFactor < 1 || pCelerityFactor > 1.6) {
pm.errorMessage(msg.message("trentoP.error.celerity"));
throw new IllegalArgumentException();
}
/* EXPONENT non puo' essere negativo */
if (pExponent <= 0) {
pm.errorMessage(msg.message("trentoP.error.exponent"));
throw new IllegalArgumentException();
}
/* La tolleranza non puo' essere nulla tantomeno negativa */
if (pTolerance <= 0) {
pm.errorMessage(msg.message("trentoP.error.tolerance"));
throw new IllegalArgumentException();
}
if (pGamma <= 0) {
pm.errorMessage(msg.message("trentoP.error.gamma"));
throw new IllegalArgumentException();
}
if (pEspInflux <= 0) {
pm.errorMessage(msg.message("trentoP.error.eps1"));
throw new IllegalArgumentException();
}
SimpleFeatureType schema = inPipes.getSchema();
if (pMode == 0) {
// checkNull(pA,pN,pTau,inDiameters);
isAreaAllDry = Utility.verifyProjectType(schema, pm);
if (pA == null || pA <= 0) {
pm.errorMessage(msg.message("trentoP.error.a"));
throw new IllegalArgumentException(msg.message("trentoP.error.a"));
}
if (pN == null || pN < 0.05 || pN > 0.95) {
pm.errorMessage(msg.message("trentoP.error.n"));
throw new IllegalArgumentException(msg.message("trentoP.error.n"));
}
if (pTau == null || pTau <= 0) {
pm.errorMessage(msg.message("trentoP.error.tau"));
throw new IllegalArgumentException(msg.message("trentoP.error.tau"));
}
if (pG == null || pG <= 0 || pG > 0.99) {
pm.errorMessage(msg.message("trentoP.error.g"));
throw new IllegalArgumentException(msg.message("trentoP.error.g"));
}
if (pAlign != 0 && pAlign != 1) {
pm.errorMessage(msg.message("trentoP.error.align"));
throw new IllegalArgumentException(msg.message("trentoP.error.align"));
}
/* Lo scavo minimo non puo' essere uguale o inferiore a 0 */
if (pMinimumDepth <= 0) {
pm.errorMessage(msg.message("trentoP.error.scavomin"));
throw new IllegalArgumentException();
}
/* Pecisione con cui si ricerca la portata nelle aree non di testa. */
if (pEpsilon <= 0 || pEpsilon > 1) {
pm.errorMessage(msg.message("trentoP.error.epsilon"));
throw new IllegalArgumentException();
}
/*
* L'angolo di riempimento minimo non puo' essere inferiore a 3.14
* [rad]
*/
if (pMaxTheta < 3.14) {
pm.errorMessage(msg.message("trentoP.error.maxtheta"));
throw new IllegalArgumentException();
}
if (pC <= 0) {
pm.errorMessage(msg.message("trentoP.error.c"));
throw new IllegalArgumentException();
}
if (inDiameters == null) {
throw new IllegalArgumentException();
}
/*
* Il passo temporale con cui valutare le portate non puo' essere
* inferiore a 0.015 [min]
*/
if (tDTp < 0.015) {
pm.errorMessage(msg.message("trentoP.error.dtp"));
throw new IllegalArgumentException();
}
/*
* Tempo di pioggia minimo da considerare nella massimizzazione
* delle portate non puo' essere superiore a 5 [min]
*/
if (tpMin > 5) {
pm.errorMessage(msg.message("trentoP.error.tpmin"));
throw new IllegalArgumentException();
}
/*
* Tempo di pioggia massimo da adottare nella ricerca della portata
* massima non puo' essere inferiore a 5 [min]
*/
if (tpMax < 30) {
pm.errorMessage(msg.message("trentoP.error.tpmax"));
throw new IllegalArgumentException();
}
} else {
// checkNull(inRain);
isAreaAllDry = Utility.verifyCalibrationType(schema, pm);
/*
* If the inRain is null and the users set the a and n parameters then create the rain data.
*/
if (pA != null && pN != null) {
// set it to true in order to search the time at max discharge.
if (tpMaxCalibration != null) {
foundTp = true;
} else {
tpMaxCalibration = tMax;
}
if (dt == null) {
pm.errorMessage(msg.message("trentoP.error.dtp"));
throw new IllegalArgumentException();
}
if (tMax < tpMaxCalibration) {
tpMaxCalibration = tMax;
}
double tMaxApproximate = ModelsEngine.approximate2Multiple(tMax, dt);
// initialize the output.
int iMax = (int) (tMaxApproximate / dt);
int iRainMax = (int) (Math.floor((double) tpMaxCalibration / (double) dt));
DateTime startTime = new DateTime(System.currentTimeMillis());
inRain = new LinkedHashMap<DateTime, double[]>();
double tp = ((double) dt) / 2;
DateTime newDate = startTime;
for( int i = 0; i <= iMax; i++ ) {
newDate = newDate.plusMinutes(dt);
double hourTime = tp / Constants.HOUR2MIN;
double value;
if (i < iRainMax) {
value = pA * pow(hourTime, pN - 1) / Constants.HOUR2MIN;
} else {
value = 0.0;
}
inRain.put(newDate, new double[]{value});
tp = tp + dt;
}
} else {
// force the time steep to null in order to read it to the file.
dt = null;
}
if (inRain == null) {
pm.errorMessage(msg.message("trentoP.error.inputRainMatrix") + " rain file");
throw new IllegalArgumentException(msg.message("trentoP.error.inputRainMatrix") + " rain file");
}
// verificy if the field exist.
}
return isAreaAllDry;
}
/**
* Initializating the array.
*
* <p>
* The array is the net. If there is a FeatureCollection extract values from
* it. The Array is order following the ID.
* </p>
* oss: if the FeatureCillection is null a IllegalArgumentException is throw
* in {@link OmsTrentoP#verifyParameter()}.
*
* @param isAreaNotAllDry it is true if there is only a percentage of the input area dry.
* @throws IllegalArgumentException
* if the FeatureCollection hasn't the correct parameters.
*/
private void setNetworkPipes( boolean isAreaNotAllDry ) throws Exception {
int length = inPipes.size();
networkPipes = new Pipe[length];
SimpleFeatureIterator stationsIter = inPipes.features();
boolean existOut = false;
int tmpOutIndex = 0;
try {
int t = 0;
while( stationsIter.hasNext() ) {
SimpleFeature feature = stationsIter.next();
try {
/*
* extract the value of the ID which is the position (minus
* 1) in the array.
*/
Number field = ((Number) feature.getAttribute(TrentoPFeatureType.ID_STR));
if (field == null) {
pm.errorMessage(msg.message("trentoP.error.number") + TrentoPFeatureType.ID_STR);
throw new IllegalArgumentException(msg.message("trentoP.error.number") + TrentoPFeatureType.ID_STR);
}
if (field.equals(pOutPipe)) {
tmpOutIndex = t;
existOut = true;
}
networkPipes[t] = new Pipe(feature, pMode, isAreaNotAllDry, pm);
t++;
} catch (NullPointerException e) {
pm.errorMessage(msg.message("trentop.illegalNet"));
throw new IllegalArgumentException(msg.message("trentop.illegalNet"));
}
}
} finally {
stationsIter.close();
}
if (!existOut) {
}
// set the id where drain of the outlet.
networkPipes[tmpOutIndex].setIdPipeWhereDrain(0);
networkPipes[tmpOutIndex].setIndexPipeWhereDrain(-1);
// start to construct the net.
int numberOfPoint = networkPipes[tmpOutIndex].point.length - 1;
findIdThatDrainsIntoIndex(tmpOutIndex, networkPipes[tmpOutIndex].point[0]);
findIdThatDrainsIntoIndex(tmpOutIndex, networkPipes[tmpOutIndex].point[numberOfPoint]);
List<Integer> missingId = new ArrayList<Integer>();
for( Pipe pipe : networkPipes ) {
if (pipe.getIdPipeWhereDrain() == null && pipe.getId() != pOutPipe) {
missingId.add(pipe.getId());
}
}
if (missingId.size() > 0) {
String errorMsg = "One of the following pipes doesn't have a connected pipe towards the outlet: "
+ Arrays.toString(missingId.toArray(new Integer[0]));
pm.errorMessage(msg.message(errorMsg));
throw new IllegalArgumentException(errorMsg);
}
verifyNet(networkPipes, pm);
}
/**
* Find the pipes that are draining in this pipe (defined by the index parameter).
*
* @param index
* the ID of this pipe.
* @param cord
* the Coordinate of the link where drain.
*/
private void findIdThatDrainsIntoIndex( int index, Coordinate cord ) {
int t = 0;
double toll = 0.1;
for( int i = 0; i < networkPipes.length; i++ ) {
// if it is this pipe then go haead.
if (index == i) {
continue;
}
// there isn-t other pipe that can drain in this.
else if (t == pMaxJunction) {
break;
}
// the id is already set.
else if (networkPipes[i].getIdPipeWhereDrain() != null) {
continue;
}
// extract the coordinate of the point of the linee of the new pipe.
Coordinate[] coords = networkPipes[i].point;
// if one of the coordinates are near of coord then the 2 pipe are
// linked.
int lastIndex = coords.length - 1;
if (cord.distance(coords[0]) < toll) {
networkPipes[i].setIdPipeWhereDrain(networkPipes[index].getId());
networkPipes[i].setIndexPipeWhereDrain(index);
findIdThatDrainsIntoIndex(i, coords[lastIndex]);
t++;
} else if (cord.distance(coords[lastIndex]) < toll) {
networkPipes[i].setIdPipeWhereDrain(networkPipes[index].getId());
networkPipes[i].setIndexPipeWhereDrain(index);
findIdThatDrainsIntoIndex(i, coords[0]);
t++;
}
}
}
/**
* Verify if the network is consistent.
*
* <p>
* <ol>
* <li>Verify that the <i>ID</i> of a pipe is a value less than the number
* of pipe.
* <li>Verify that the pipe where, the current pipe drain, have an <i>ID</i>
* less than the number of pipes.
* <li>Verify that there is an <b>outlet<b> in the net.
* </ol>
* </p>
*
* @param networkPipes
* the array which rappresent the net.
* @param pm
* the progerss monitor.
* @throws IllegalArgumentException
* if the net is unconsistent.
*/
public void verifyNet( Pipe[] networkPipes, IJGTProgressMonitor pm ) {
/*
* serve per verificare che ci sia almeno un'uscita. True= esiste
* un'uscita
*/
boolean isOut = false;
if (networkPipes != null) {
/* VERIFICA DATI GEOMETRICI DELLA RETE */
// Per ogni stato
int length = networkPipes.length;
int kj;
for( int i = 0; i < length; i++ )
{
// verifica che la rete abbia almeno un-uscita.
if (networkPipes[i].getIdPipeWhereDrain() == 0) {
isOut = true;
}
/*
* Controlla che non ci siano errori nei dati geometrici della
* rete, numero ID pipe in cui drena i >del numero consentito
* (la numerazione va da 1 a length
*/
if (networkPipes[i].getIndexPipeWhereDrain() > length) {
pm.errorMessage(msg.message("trentoP.error.pipe"));
throw new IllegalArgumentException(msg.message("trentoP.error.pipe"));
}
/*
* Da quanto si puo leggere nel file di input fossolo.geo in
* Fluide Turtle, ogni stato o sottobacino e contraddistinto da
* un numero crescente che va da 1 a n=numero di stati; n e
* anche pari a data->nrh. Inoltre si apprende che la prima
* colonna della matrice in fossolo.geo riporta l'elenco degli
* stati, mentre la seconda colonna ci dice dove ciascun stato
* va a drenare.(NON E AMMESSO CHE LO STESSO STATO DRENI SU PIU
* DI UNO!!) Questa if serve per verificare che non siano
* presenti condotte non dichiarate, ovvero piu realisticamente
* che non ci sia un'errore di numerazione o battitura. In altri
* termini lo stato analizzato non puo drenare in uno stato al
* di fuori di quelli esplicitamente dichiarati o dell'uscita,
* contradistinta con ID 0
*/
kj = i;
/*
* Terra conto degli stati attraversati dall'acqua che inizia a
* scorrere a partire dallo stato analizzato
*/
int count = 0;
/*
* Seguo il percorso dell'acqua a partire dallo stato corrente
*/
while( networkPipes[kj].getIdPipeWhereDrain() != 0 ) {
kj = networkPipes[kj].getIndexPipeWhereDrain();
/*
* L'acqua non puo finire in uno stato che con sia tra
* quelli esplicitamente definiti, in altre parole il
* percorso dell'acqua non puo essere al di fuori
* dell'inseme dei dercorsi possibili
*/
if (kj > length) {
pm.errorMessage(msg.message("trentoP.error.drainPipe") + kj);
throw new IllegalArgumentException(msg.message("trentoP.error.drainPipe") + kj);
}
count++;
if (count > length) {
pm.errorMessage(msg.message("trentoP.error.pipe"));
throw new IllegalArgumentException(msg.message("trentoP.error.pipe"));
}
/*
* La variabile count mi consente di uscire dal ciclo while,
* nel caso non ci fosse [kj][2]=0, ossia un'uscita. Infatti
* partendo da uno stato qualsiasi il numero degli stati
* attraversati prima di raggiungere l'uscita non puo essere
* superiore al numero degli stati effettivamente presenti.
* Quando questo accade vuol dire che l'acqua e in un loop
* chiuso
*/
}
}
/*
* Non si e trovato neanche un uscita, quindi Trento_p da errore di
* esecuzione, perchè almeno una colonna deve essere l'uscita
*/
if (isOut == false) {
pm.errorMessage(msg.message("trentoP.error.noout"));
throw new IllegalArgumentException(msg.message("trentoP.error.noout"));
}
} else {
throw new IllegalArgumentException(msg.message("trentoP.error.incorrectmatrix"));
}
}
/**
* Temporaneo per i test, ritorna i dati sotto forma di matrice.
*
* @return
*/
public double[][] getResults() {
double[][] results = new double[networkPipes.length][28];
double[] one = new double[networkPipes.length];
double[] two = new double[networkPipes.length];
for( int i = 0; i < networkPipes.length; i++ ) {
one[i] = i;
two[i] = networkPipes[i].getId();
}
QuickSortAlgorithm t = new QuickSortAlgorithm(pm);
t.sort(two, one);
for( int i = 0; i < networkPipes.length; i++ ) {
int index = (int) one[i];
results[i][0] = networkPipes[index].getId();
results[i][1] = networkPipes[index].getIdPipeWhereDrain();
results[i][2] = networkPipes[index].getDrainArea();
results[i][3] = networkPipes[index].getLenght();
results[i][4] = networkPipes[index].getInitialElevation();
results[i][5] = networkPipes[index].getFinalElevation();
results[i][6] = networkPipes[index].getRunoffCoefficient();
results[i][7] = networkPipes[index].getAverageResidenceTime();
results[i][8] = networkPipes[index].getKs();
results[i][9] = networkPipes[index].getMinimumPipeSlope();
results[i][10] = networkPipes[index].getPipeSectionType();
results[i][11] = networkPipes[index].getAverageSlope();
results[i][12] = networkPipes[index].discharge;
results[i][13] = networkPipes[index].coeffUdometrico;
results[i][14] = networkPipes[index].residenceTime;
results[i][15] = networkPipes[index].tP;
results[i][16] = networkPipes[index].tQmax;
results[i][17] = networkPipes[index].meanSpeed;
results[i][18] = networkPipes[index].pipeSlope;
results[i][19] = networkPipes[index].diameter;
results[i][20] = networkPipes[index].emptyDegree;
results[i][21] = networkPipes[index].depthInitialPipe;
results[i][22] = networkPipes[index].depthFinalPipe;
results[i][23] = networkPipes[index].initialFreesurface;
results[i][24] = networkPipes[index].finalFreesurface;
results[i][25] = networkPipes[index].totalSubNetArea;
results[i][26] = networkPipes[index].meanLengthSubNet;
results[i][27] = networkPipes[index].varianceLengthSubNet;
}
return results;
}
}