/* * 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.net; import static java.lang.Math.acos; import static java.lang.Math.ceil; import static java.lang.Math.cos; import static java.lang.Math.pow; import static java.lang.Math.sin; import static java.lang.Math.sqrt; import static org.jgrasstools.hortonmachine.modules.networktools.trento_p.utils.Constants.CUBICMETER2LITER; import static org.jgrasstools.hortonmachine.modules.networktools.trento_p.utils.Constants.DEFAULT_C; 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_TOLERANCE; import static org.jgrasstools.hortonmachine.modules.networktools.trento_p.utils.Constants.EIGHTOVERTHREE; import static org.jgrasstools.hortonmachine.modules.networktools.trento_p.utils.Constants.FIVEOVEREIGHT; import static org.jgrasstools.hortonmachine.modules.networktools.trento_p.utils.Constants.HOUR2MIN; import static org.jgrasstools.hortonmachine.modules.networktools.trento_p.utils.Constants.METER2CM; import static org.jgrasstools.hortonmachine.modules.networktools.trento_p.utils.Constants.METER2CMSQUARED; import static org.jgrasstools.hortonmachine.modules.networktools.trento_p.utils.Constants.ONEOVERFOUR; import static org.jgrasstools.hortonmachine.modules.networktools.trento_p.utils.Constants.ONEOVERSIX; import static org.jgrasstools.hortonmachine.modules.networktools.trento_p.utils.Constants.ONEOVERTHIRTEEN; import static org.jgrasstools.hortonmachine.modules.networktools.trento_p.utils.Constants.SEVENOVERTHIRTEEN; import static org.jgrasstools.hortonmachine.modules.networktools.trento_p.utils.Constants.SIXOVERTHIRTEEN; import static org.jgrasstools.hortonmachine.modules.networktools.trento_p.utils.Constants.THIRTHEENOVERSIX; import static org.jgrasstools.hortonmachine.modules.networktools.trento_p.utils.Constants.THREEOVEREIGHT; import static org.jgrasstools.hortonmachine.modules.networktools.trento_p.utils.Constants.TWOOVERTHREE; import static org.jgrasstools.hortonmachine.modules.networktools.trento_p.utils.Constants.TWO_TENOVERTHREE; import static org.jgrasstools.hortonmachine.modules.networktools.trento_p.utils.Constants.TWO_THIRTEENOVEREIGHT; import static org.jgrasstools.hortonmachine.modules.networktools.trento_p.utils.Constants.TWO_THIRTEENOVERTHREE; import static org.jgrasstools.hortonmachine.modules.networktools.trento_p.utils.Constants.TWO_TWENTYOVERTHIRTEEN; import static org.jgrasstools.hortonmachine.modules.networktools.trento_p.utils.Constants.WSPECIFICWEIGHT; import org.jgrasstools.gears.libs.monitor.IJGTProgressMonitor; import org.jgrasstools.hortonmachine.i18n.HortonMessageHandler; import org.jgrasstools.hortonmachine.modules.networktools.trento_p.OmsTrentoP; import org.jgrasstools.hortonmachine.modules.networktools.trento_p.utils.TrentoPFeatureType.PipesTrentoP; import org.jgrasstools.hortonmachine.modules.networktools.trento_p.utils.Utility; import org.opengis.feature.simple.SimpleFeature; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Geometry; /** * This is a class which represents a sewer pipe. * * <p> * It contains a collection of field which are a pipe features. Some of these * are private, and are used as input to calculate the others. * * There is two type of features: geometric and hydraulic. * * The depth are refereed to the ground and the elevation to the see level. * </p> * <p> * In this class there is some methods that are used to calculate feature that * can be calculate only with few external parameters. The other properties * need, to be calculate, to the whole network so they are put into other * classes ({@link NetworkBuilder, @}{@link OmsTrentoP}). * * </p> * * <p> * Some of the properties of a pipe are private and theirs fields are set at the * initializing time and the value is immutable (the initial value have to be * the same as the final) so there is only the getter method. Others fields are * set as a public and in the implementations of OmsTrentoP program are set * directly. This is done to obtain a more readable code, in fact in the code * there is some large equations that aren't useful to read in a setter method. * </p> * * * @author Daniele Andreis, Riccardo Rigon, David Tamanini. * @see {@link OmsTrentoP} * @version since 1.1 * */ public class Pipe { /** * Accuracy used with the bisection method. */ private double accuracy; /** * Minimum dig depth for the circular pipe. */ private double minimumDepth = DEFAULT_MINIMUM_DEPTH; /** * Max number of bisection to do in the solution of equationon. */ private int jMax = DEFAULT_J_MAX; /** * Minimum fill degree in the channel. */ private double minG = DEFAULT_MING; /** * Maximum Fill degree. */ private double maxTheta = DEFAULT_MAX_THETA; /** * Align mode, it can be 0 (so the free surface is aligned through a change * in the depth of the pipes) or 1 (aligned with bottom step). */ private int align; /** * Max number of pipes that can converge in a junction. */ private int maxJunction = DEFAULT_MAX_JUNCTION; /** * Minimum discharge in a pipe. * */ private double minDischarge = DEFAULT_MIN_DISCHARGE; /** * Tangential bottom stress, which ensure the self-cleaning of the network. */ private double tau; /** * Fill degree to use during the project. */ private double g; /** * Division base to height in the rectangular or trapezium section. * */ private double c = DEFAULT_C; /** * Tolerance used in the iteration method to calculate the radius. */ private double tolerance = DEFAULT_TOLERANCE; /** * It's the ID of this pipe. */ private int id; /** * It's the ID of the pipe where this drain. */ private Integer idPipeWhereDrain = null; /** * It's the ID of the pipe where this drain. */ private Integer indexPipeWhereDrain = null; /** * Is the contributed area. */ private double drainArea; /** * The pipe's length. */ private double lenght; /** * The elevation of the begin of the pipe. */ private double initialElevation; /** * The elevation of the end of the pipe. */ private double finalElevation; /** * The run of coefficient related to the area which drains in this pipe. */ private double runoffCoefficient; /** * The average residence time. */ private double averageResidenceTime; /** * The Strikler coefficient. */ private double ks; /** * Minimum pipe slope. * <p> * The slope calculate to the program have to be grater than this. * </p> */ private double minimumPipeSlope; /** * The height of the free surface at the begin of the pipe. */ public double initialFreesurface; /** * The height of the free surface at the end of the pipe. */ public double finalFreesurface; /** * Empty degree of the pipe. */ public double emptyDegree; /** * The type of pipe. * * <p> * It can be: * <ol> * <li>circular. * <li>rectangular. * <li>trapezium. * </ol> * </p> */ private int pipeSectionType; /** * The depth of the dig at the end of the pipe. */ public double depthFinalPipe; /** * The depth of the dig at the begin of the pipe. */ public double depthInitialPipe; /** * Diameter of the pipe. */ public double diameter; /** * The actually slope. */ public double pipeSlope; /** * Time at the maximum discharge. */ public double tQmax; /** * Discharge. */ public double discharge; /** * Udometric coefficient. */ public double coeffUdometrico; /** * Average slope of the pipes. */ private double averageSlope; /** * Average speed into the pipe. */ public double meanSpeed; /** * Residence time. */ public double tP; /** * The effective diameter in the verify mode. * */ public double residenceTime;; /** * Pipe slope used to verify the net in mode 1. */ public double verifyPipeSlope; /** * diameter of the pipe, used to verify the net in mode 1. */ public double diameterToVerify; public double k; /** * The coordinate of the pipes extreme. */ public Coordinate[] point = null; /** * The amount of the area which drain in this pipe, included all the upstream pipe. */ public double totalSubNetArea; /** * The amount of the length of the upstream pipes. */ public double totalSubNetLength; /** * Mean length of upstream net [ m ] */ public double meanLengthSubNet; /** * Variance of lengths of upstream net [ m ^ 2 ] */ public double varianceLengthSubNet; private static HortonMessageHandler msg = HortonMessageHandler.getInstance(); private IJGTProgressMonitor pm; public Pipe( SimpleFeature feature, int verify, boolean isAreaNotAllDry, IJGTProgressMonitor pm ) throws Exception { this.pm = pm; setKnowNetworkValue(feature, verify, isAreaNotAllDry); } public void setK( double defaultEsp1, double defaultExponent, double defaultGamma ) { this.k = (HOUR2MIN * averageResidenceTime * pow(drainArea / METER2CM, defaultExponent)) / (pow(runoffCoefficient, defaultEsp1) * pow(averageSlope, defaultGamma)); } public double getAverageSlope() { return averageSlope; } public void setAverageSlope( double averageSlope ) { this.averageSlope = averageSlope; } public double getAverageResidenceTime() { return averageResidenceTime; } public int getId() { return id; } public Integer getIdPipeWhereDrain() { return idPipeWhereDrain; } public void setIdPipeWhereDrain( int idPipeWhereDrain ) { this.idPipeWhereDrain = idPipeWhereDrain; } public double getDrainArea() { return drainArea; } public double getLenght() { return lenght; } public double getInitialElevation() { return initialElevation; } public double getFinalElevation() { return finalElevation; } public double getRunoffCoefficient() { return runoffCoefficient; } public double getKs() { return ks; } public double getMinimumPipeSlope() { return minimumPipeSlope; } public int getPipeSectionType() { return pipeSectionType; } public void setTolerance( double tolerance ) { this.tolerance = tolerance; } public double getTolerance() { return tolerance; } public void setAlign( int align ) { this.align = align; } public int getAlign() { return align; } public void setMaxJunction( int maxJunction ) { this.maxJunction = maxJunction; } public int getMaxJunction() { return maxJunction; } public void setMinDischarge( double minDischarge ) { this.minDischarge = minDischarge; } public double getMinDischarge() { return minDischarge; } public void setTau( double tau ) { this.tau = tau; } public double getTau() { return tau; } public void setG( double g ) { this.g = g; } public double getG() { return g; } public void setC( double c ) { this.c = c; } public double getC() { return c; } public double getMaxTheta() { return maxTheta; } public void setMaxTheta( double maxTheta ) { this.maxTheta = maxTheta; } public double getAccuracy() { return accuracy; } public int getjMax() { return jMax; } public double getMinG() { return minG; } public void setAccuracy( double accuracy ) { this.accuracy = accuracy; } public void setMinimumDepth( double minimumDepth ) { this.minimumDepth = minimumDepth; } public void setJMax( int jMax ) { this.jMax = jMax; } public void setMinG( double minG ) { this.minG = minG; } /** * Set the value of the network. * * <p> * Extract the needed value from a featureCollection. * </p> * * @param pipeFeature * the feature where the value are stored. * @param verify * if the mode is project or verify. * @param isAreaNotAllDry * @throws Exception * if the featureCollection doesn't contains the field */ private void setKnowNetworkValue( SimpleFeature pipeFeature, int verify, boolean isAreaNotAllDry ) throws Exception { try { /* * Verifiche su ID e idPipeWhereDrain sono fatte durante la verifica * di consistenza della rete. */ this.id = setFeatureField(pipeFeature, PipesTrentoP.ID.getAttributeName()).intValue(); double tmp = setFeatureField(pipeFeature, PipesTrentoP.DRAIN_AREA.getAttributeName()).doubleValue(); if (tmp >= 0.0) { if (!isAreaNotAllDry) { this.drainArea = tmp; } else { double tmpPerc = setFeatureField(pipeFeature, PipesTrentoP.PER_AREA.getAttributeName()).doubleValue(); if (tmpPerc >= 0 && tmpPerc <= 1) { this.drainArea = tmp * tmpPerc; } else { pm.errorMessage(msg.message("trentoP.error.fieldPerArea") + tmpPerc); throw new IllegalArgumentException(msg.message("trentoP.error.fieldPerArea" + tmpPerc)); } } } else { pm.errorMessage(msg.message("trentoP.error.fieldArea") + tmp); throw new IllegalArgumentException(msg.message("trentoP.error.fieldArea" + tmp)); } this.lenght = ((Geometry) pipeFeature.getDefaultGeometry()).getLength(); this.point = ((Geometry) pipeFeature.getDefaultGeometry()).getCoordinates(); this.initialElevation = setFeatureField(pipeFeature, PipesTrentoP.INITIAL_ELEVATION.getAttributeName()).doubleValue();; this.finalElevation = setFeatureField(pipeFeature, PipesTrentoP.FINAL_ELEVATION.getAttributeName()).doubleValue(); tmp = setFeatureField(pipeFeature, PipesTrentoP.RUNOFF_COEFFICIENT.getAttributeName()).doubleValue(); if (tmp >= 0) { this.runoffCoefficient = tmp; } else { pm.errorMessage(msg.message("trentoP.error.runO") + this.id); throw new IllegalArgumentException(msg.message("trentoP.error.runO" + this.id)); } tmp = setFeatureField(pipeFeature, PipesTrentoP.KS.getAttributeName()).doubleValue(); if (tmp >= 0) { this.ks = tmp; } else { pm.errorMessage(msg.message("trentoP.error.ks") + this.id); throw new IllegalArgumentException(msg.message("trentoP.error.ks" + this.id)); } this.averageSlope = setFeatureField(pipeFeature, PipesTrentoP.AVERAGE_SLOPE.getAttributeName()).intValue();; tmp = setFeatureField(pipeFeature, PipesTrentoP.AVERAGE_RESIDENCE_TIME.getAttributeName()).doubleValue();; if (tmp >= 0) { this.averageResidenceTime = tmp; } else { pm.errorMessage(msg.message("trentoP.error.averageTime") + this.id); throw new IllegalArgumentException(msg.message("trentoP.error.averageTime" + this.id)); } if (verify == 1) { /* Pipe diameter [cm] */ this.diameterToVerify = setFeatureField(pipeFeature, PipesTrentoP.DIAMETER.getAttributeName()).doubleValue(); /* Pipe slope [%] */ this.verifyPipeSlope = 100.0 * Math.abs(this.initialElevation - this.finalElevation) / this.lenght; } else if (verify == 0) { this.minimumPipeSlope = setFeatureField(pipeFeature, PipesTrentoP.MINIMUM_PIPE_SLOPE.getAttributeName()) .doubleValue(); int sectionTmp = setFeatureField(pipeFeature, PipesTrentoP.PIPE_SECTION_TYPE.getAttributeName()).intValue(); if (sectionTmp > 0 && sectionTmp < 4) { this.pipeSectionType = sectionTmp; } else { pm.errorMessage(msg.message("trentoP.error.section") + this.id); throw new IllegalArgumentException(msg.message("trentoP.error.section") + this.id); } } } catch (NullPointerException e) { pm.errorMessage(msg.message("trentop.inputMatrix")); throw new Exception(msg.message("trentop.inputMatrix")); } } /** * Check if there is the field in a SimpleFeature and if it's a Number. * * @param pipe * the feature. * @param key * the key string of the field. * @return the Number associated at this key. */ private Number setFeatureField( SimpleFeature pipe, String key ) { Number field = ((Number) pipe.getAttribute(key)); if (field == null) { pm.errorMessage(msg.message("trentoP.error.number") + key); throw new IllegalArgumentException(msg.message("trentoP.error.number") + key); } // return the Number return field; } /** * Calculate the dimension of the pipes. * * <p> * It switch between several section geometry. * </p> * * * @param diameters * matrix with the commercial diameters. * @param tau * tangential stress at the bottom of the pipe.. * @param g * fill degree. * @param maxd * maximum diameter. * @param c * is a geometric expression b/h where h is the height and b base * (only for rectangular or trapezium shape). */ public void designPipe( double[][] diameters, double tau, double g, double maxd, double c, StringBuilder strWarnings ) { switch( this.pipeSectionType ) { case 1: designCircularPipe(diameters, tau, g, maxd, strWarnings); break; case 2: designRectangularPipe(tau, g, maxd, c, strWarnings); break; case 3: designTrapeziumPipe(tau, g, maxd, c, strWarnings); break; default: designCircularPipe(diameters, tau, g, maxd, strWarnings); break; } } /** * Dimensiona la tubazione. * * <p> * Chiama altre subroutine per il dimensionamento del diametro del tubo * circolare e calcola alcune grandezze correlate. * <ol> * <li> * Inanzittuto dimensiona il tubo chiamando la diameters. Quest'ultimasi * basa sul criterio di autopulizia della rete, e determina, mediante * chiamatead ulteriori funuzioni, tutte le grandezze necessarie (grado di * riempimento,angolo, ecc..) * <li>Dopodiche riprogetta il tratto (chiamata a get_diameter_i) imponendo * unapendenza pari a quella del terreno, qualora questa fosse superioe a * quellaprecedentemete calcolata. * <li>Inoltre ogni volta che dimensiona il tubo, design_pipe (o le altre * funzionida essa chiamate) calcola tutte le grandezze secondarie, ma * alquantofondamentali (quota dello scavo, pelo libero ecc..) e le registra * nellamatrice networkPipes. * <ol> * </p> * * @param diameter * matrice dei possibili diametri. * @param tau * sforzo al fondo. * @param g * grado di riempimento. * @param maxd * massimo diametro * @param strWarnings * a string which collect all the warning messages. */ private void designCircularPipe( double[][] diameters, double tau, double g, double maxd, StringBuilder strWarnings ) { /* Angolo di riempimento */ double newtheta; /* * [%] Pendenza naturale, calcolata in funzione dei dati geometrici * della rete */ double naturalslope; /* [cm] Diametro tubo */ double D; /* [cm]Spessore tubo */ double[] dD = new double[1]; /* [%] Pendenza minima per il tratto che si sta dimensionando. */ double ms; /* * Dimensiona il diametro del tubo da adottare col criterio di * autopulizia, calcola altre grandezze correlate come la pendenza e il * grado di riempimento, e restituisce il riempimento effettivo nel * tratto progettato */ newtheta = getDiameter(diameters, tau, g, dD, maxd, strWarnings); /* [%] Pendenza del terreno */ naturalslope = METER2CM * (getInitialElevation() - getFinalElevation()) / getLenght(); /* [%] pendenza minima del tratto che si sta progettando. */ ms = getMinimumPipeSlope(); if (naturalslope < 0) { /* * Avvisa l'utente che il tratto che si sta progettando e in * contropendenza */ strWarnings.append(msg.message("trentoP.warning.slope") + id); } /* La pendenza del terreno deve essere superiore a quella minima ms */ if (naturalslope < ms) { naturalslope = ms; } /* * Se la pendenza del terreno e maggiore di quella del tubo, allora la * pendenza del tubo viene posta uguale a quella del terreno. */ if (naturalslope > pipeSlope) { pipeSlope = (naturalslope); /* * Progetta la condotta assegnado una pendenza pari a quella del * terreno, calcola altre grandezze correlate come la pendenza e il * grado di riempimento, e restituisce il riempimento effettivo nel * tratto progettato */ newtheta = getDiameterI(diameters, naturalslope, g, dD, maxd, strWarnings); } /* Diametro tubo [cm] */ D = diameter; /* Velocita media nella sezione [m/s] */ meanSpeed = ((8 * discharge) / (CUBICMETER2LITER * D * D * (newtheta - sin(newtheta)) / METER2CMSQUARED)); /* Quota scavo all'inizio del tubo [m s.l.m.] */ depthInitialPipe = (getInitialElevation() - minimumDepth - (D + 2 * dD[0]) / METER2CM); /* * Quota dello scavo alla fine del tubo calcolata considerando la * pendenza effettiva del tratto [m s.l.m.] */ depthFinalPipe = (depthInitialPipe - getLenght() * pipeSlope / METER2CM); /* Quota pelo libero all'inizio del tubo [m s.l.m.] */ initialFreesurface = depthInitialPipe + emptyDegree * D / METER2CM + dD[0] / METER2CM; /* Quota pelo libero all'inizio del tubo [m s.l.m.] */ finalFreesurface = depthFinalPipe + emptyDegree * D / METER2CM + dD[0] / METER2CM; } /** * Dimensiona il tubo, imponendo uno sforzo tangenziale al fondo. * * <p> * <ol> * <li>Calcola l'angolo theta in funzione di g. * <li>Nota la portata di progetto del tratto considerato, determina il * diametro oldD (adottando una pendenza che garantisca l'autopulizia). * <li>Successivamente oldD viene approssimato al diametro commerciale piu * vicino, letto dalla martice diametrs. Lo spessore adottato, anche esso * letto dalla matrice dei diametri, viene assegnato al puntatore dD. Mentre * la varabile maxd fa in modo che andando verso valle i diametri utilizzati * possano solo aumentare. * <li>A questo punto la get_diameter() ricalcola il nuovo valore * dell'angolo theta, chiamando la funzione this_bisection(), theta deve * risultare piu piccolo. * <li>Se invece oldD risulta maggiore del diametro commerciale piu grande * disponibile, allora si mantiene il suo valore. * <li>Infine calcola il grado di riempimento e pendenza del tratto a * partire dal raggio idraulico, e li registra nella matrice networkPipes. * <ol> * </p> * * @param diametrs * matrice che contiene i diametri e spessori commerciali. * @param tau * [Pa] Sforzo tangenziale al fondo che garantisca l'autopulizia * della rete * @param dD * @param g * Grado di riempimento da considerare nella progettazione della * rete * @param maxd * Diamtetro o altezza piu' grande adottato nei tratti piu' a * monte * @param strWarnings * a string which collect all the warning messages. */ private double getDiameter( double[][] diameters, double tau, double g, double[] dD, double maxd, StringBuilder strWarnings ) { /* Pari a A * ( Rh ^1/6 ) */ double B; /* Anglo formato dalla sezione bagnata */ double thta; /* Diametro calcolato imponendo il criterio di autopulizia della rete */ double oldD; /* [cm]Diametro commerciale */ double D = 0; /* Costane */ double known; /* * [rad]Angolo formato dalla sezione bagnata, adottando un diametro * commerciale */ double newtheta; /* * [cm] Nuovo raggio idraulico calcolato in funzione del diametro * commerciale */ double newrh; /* B=A(Rh^1/6) [m^13/6] */ B = (discharge * sqrt(WSPECIFICWEIGHT / tau)) / (CUBICMETER2LITER * getKs()); /* Angolo formato dalla sezione bagnata [rad] */ thta = 2 * acos(1 - 2 * g); /* Diametro tubo [cm] */ oldD = TWO_TWENTYOVERTHIRTEEN * pow(B, SIXOVERTHIRTEEN) / (pow((1 - sin(thta) / thta), ONEOVERTHIRTEEN) * pow(thta - sin(thta), SIXOVERTHIRTEEN)); /* * Se il diametro ottenuto e piu piccolo del diametro commerciale piu * grande, allora lo approssimo per eccesso col diametro commerciale piu * prossimo. */ if (oldD < diameters[diameters.length - 1][0]) { int j = 0; for( j = 0; j < diameters.length; j++ ) { /* Diametro commerciale [cm] */ D = diameters[j][0]; if (D >= oldD) break; } if (D < maxd) { /* * Scendendo verso valle i diametri usati non possono diventare * piu piccoli */ D = maxd; } diameter = (D); /* Spessore corrispondente al diametro commerciale scelto [cm] */ dD[0] = diameters[j][1]; known = (B * TWO_TENOVERTHREE) / pow(D / METER2CM, THIRTHEENOVERSIX); /* * Angolo formato dalla sezione bagnata considerando un diametro * commerciale [rad] */ newtheta = Utility.thisBisection(thta, known, ONEOVERSIX, minG, accuracy, jMax, pm, strWarnings); /* * E ovvio che adottando un diametro commerciale piu grande di * quello che sarebbe strettamente neccessario, il grado di * riempimento non puo aumentare */ if (newtheta > thta) { strWarnings.append(msg.message("trentoP.warning.bisection") + id); } } /* * se il diametro necessario e piu grande del massimo diametro * commerciale disponibile, allora mantengo il risultato ottenuto senza * nessuna approssimazione */ else { D = oldD; diameter = D; /* COSA SUCCEDE ALLO SPESSORE ??!! */ newtheta = thta; } /* Grado di riempimento del tubo */ emptyDegree = 0.5 * (1 - cos(newtheta / 2)); /* Rh [cm] */ newrh = 0.25 * D * (1 - sin(newtheta) / newtheta); /* pendenza del tratto progettato [%] */ pipeSlope = (tau / (WSPECIFICWEIGHT * newrh) * METER2CMSQUARED); return newtheta; } /** * * Dimensiona il tubo adottando una pendenza pari a quella del terreno/ * <p> * Sostanzialmente uguale alla get_diameter. L'unica differenza e che * dimensiona il tubo adottando una pendenza pari a quella del terreno. * </p> * * * @param diametrs * matrice che contiene i diametri e spessori commerciali. * @param slope * pendenza della tubazione. * @param dD * spessore del tubo commerciale. * @param g * Grado di riempimento da considerare nella progettazione della * rete * @param maxd * Diamtetro o altezza piu' grande adottato nei tratti piu' a * monte * @param strWarnings * a string which collect all the warning messages. */ private double getDiameterI( double[][] diameters, double slope, double g, double[] dD, double maxd, StringBuilder strWarnings ) { int j; /* \param */ /* Pari a A * ( Rh ^1/6 ) */ double B; /* Anglo formato dalla sezione bagnata */ double thta; /* Diametro calcolato imponendo il criterio di autopulizia della rete */ double oldD; /* [cm]Diametro commerciale */ double D = 0; /* Costane */ double known; /* * [rad]Angolo formato dalla sezione bagnata, adottando un diametro * commerciale */ double newtheta; /* * B = A ( Rh ^ 2 / 3 ) [ m ^ 8 / 3 ] */ B = (discharge) / (CUBICMETER2LITER * getKs() * sqrt(slope / METER2CM)); /* * Angolo formato dalla sezione bagnata [rad] */ thta = 2 * acos(1 - 2 * g); /* * Diametro tubo [ cm ] */ oldD = TWO_THIRTEENOVEREIGHT * pow(B, THREEOVEREIGHT) / (pow((1 - sin(thta) / thta), 0.25) * pow(thta - sin(thta), THREEOVEREIGHT)); if (oldD < diameters[diameters.length - 1][0]) { for( j = 0; j < diameters.length; j++ ) { D = diameters[j][0]; /* Diametro commerciale del tubo [cm] */ if (D >= oldD) break; } if (j == diameters.length + 1 || j == diameters.length) { strWarnings.append(msg.message("trentoP.warning.loop")); j = diameters.length - 1; } if (D < maxd) { /* * Il diametro adottando non puo decrescere procedendo verso * valle */ D = maxd; } diameter = D; /* Spessore tubo commerciale [cm] */ dD[0] = diameters[j][1]; /* * B=(networkPipes->element[l][10])/(CUBICMETER2LITER*networkPipes-> * element[l][ 9]*.sqrt(slope/METER2CM)); */ known = (B * TWO_THIRTEENOVERTHREE) / pow(D / METER2CM, EIGHTOVERTHREE); /* Riempimento effettivo considerando il diametro commerciale [rad] */ newtheta = Utility.thisBisection(thta, known, TWOOVERTHREE, minG, accuracy, jMax, pm, strWarnings); if (newtheta > thta) { strWarnings.append(msg.message("trentoP.warning.bisection") + id); } } else { D = oldD; diameter = D; newtheta = thta; } /* Grdao di riempimento */ emptyDegree = 0.5 * (1 - cos(newtheta / 2)); /* Pendenza tubo [%] */ pipeSlope = slope; return newtheta; } /** * Dimensiona una sezione di tipo 2, ossia rettangolare. * <p> * Inoltre calcola altre grndezze correlate. * <ol> * <li> * Inizialmente dimensiona il tubo chiamando la get_height_1() la quale * adotta il criterio dell'autopulizia e determina, mediante chiamate ad * ulteriori funuzioni tutte le grandezze necessarie (grado di riempimento, * pendenza, ecc..) * <li>Dopodiche riprogetta il tratto (chiamata a get_height_1_i) imponendo * una pendenza pari a quella del terreno, qualora questa fosse superioe a * quella ottenuta secondo il criterio di autopulizia. * <li>Inoltre ogni volta che dimensiona il tubo, design_pipe_2 (o le altre * funzioni da essa chiamate) calcola tutte le grandezze secondarie, ma * alquanto fondamentali (quota dello scavo, pelo libero ecc..) e le * registra nella matrice networkPipes. * </ol> * </p> * * @param diametrs * matrice che contiene i diametri e spessori commerciali. * @param tau * [Pa] Sforzo tangenziale al fondo che garantisca l'autopulizia * della rete * @param g * Grado di riempimento da considerare nella progettazione della * rete * @param maxd * Diamtetro o altezza piu' grande adottato nei tratti piu' a * monte * @param c * Rapporto base-altezza della sezione rettangolare. * @param strWarnings * a string which collect all the warning messages. */ private void designRectangularPipe( double tau, double g, double maxd, double c, StringBuilder strWarnings ) { /* [cm] base della sezione effettivamente adottata. */ double base; /* * [%] pendenza naturale, calcolata in funzione dei dati geometrici * della rete */ double naturalslope; /* D [cm] Altezza del canale a sezione rettangolare. */ double D; /* * [%] Pendenza minima da adottare per il tratto che si sta * dimensionando. */ double ms; /* * Dimensiona il diametro del tubo da adottare col criterio di * autopulizia, calcola altre grandezze correlate come la pendenza e il * grado di riempimento, e restituisce il riempimento effettivo nel * tratto progettato */ base = getHeight1(tau, g, maxd, c); /* [%] pendenza minima per il tratto che si sta dimensionando. */ ms = getMinimumPipeSlope(); /* [%] Pendenza del terreno */ naturalslope = METER2CM * (getInitialElevation() - getFinalElevation()) / getLenght(); /* * Avvisa l'utente che il tratto che si sta progettando e in * contropendenza */ if (naturalslope < 0) { strWarnings.append(msg.message("trentoP.warning.slope") + id); } /* La pendenza del terreno deve essere superiore a quella minima ms */ if (naturalslope < ms) { naturalslope = ms; } /* * Se la pendenza del terreno e maggiore di quella del tubo, allora la * pendenza del tubo viene posta uguale a quella del terreno. */ if (naturalslope > pipeSlope) { pipeSlope = naturalslope; /* * Progetta la condotta assegnado una pendenza pari a quella del * terreno, calcola altre grandezze correlate come la pendenza e il * grado di riempimento, e restituisce il riempimento effettivo nel * tratto progettato */ base = getHeight1I(naturalslope, g, maxd, c); } /* Diametro tubo [cm] */ D = diameter; /* Velocita media nella sezione [m/s] */ meanSpeed = (discharge / CUBICMETER2LITER) / (emptyDegree * D * base / METER2CMSQUARED); /* Quota scavo all'inizio del tubo [m s.l.m.] */ depthInitialPipe = initialElevation - diameter / METER2CM; /* * Quota dello scavo alla fine del tubo calcolata considerando la * pendenza effettiva del tratto [m s.l.m.] */ depthFinalPipe = depthInitialPipe - getLenght() * pipeSlope / METER2CM; /* Quota pelo libero all'inizio del tubo [m s.l.m.] */ initialFreesurface = depthInitialPipe + emptyDegree * D / METER2CM; /* Quota pelo libero all'inizio del tubo [m s.l.m.] */ finalFreesurface = depthFinalPipe + emptyDegree * D / METER2CM; } /** * * Dimensiona il canale a sezione rettangolare, imponendo uno sforzo * tangenziale al fondo. * * <p> * <ol> * <li>Calcola l'altezza oldD della sezione rettangolare in funzione del * grado di riempimento e del rapporto base-altezza assegnati; ovviamente * imponendo un certo valore dello sforzo tangenziale al fondo (criterio di * autopulizia della rete.) * <li>Calcola la base oldb. * <li>Calcola il raggio idraulico richiesto, e a partire da esso determina * sia il grado di riempimento nella sezione commerciale che la pendenza * della tubazione, e gli registra nella matrice networkPipes. * <li>Infine la get_height_1 restituisce il valore della base della sezione * rettangolare adottata. * * @param tau * [Pa] Sforzo tangenziale al fondo che garantisca l'autopulizia * della rete * @param g * Grado di riempimento da considerare nella progettazione della * rete * @param maxd * Diamtetro o altezza piu' grande adottato nei tratti piu' a * monte * @param c * Rapporto base-altezza della sezione rettangolare. */ private double getHeight1( double tau, double g, double maxd, double c ) { /* Pari a A * ( Rh ^1/6 ) */ double B; /* [cm] Altezza della sezione rettangolare effettivamente impiegata. */ double oldD; /* [cm] Altezza della sezione rettangolare effettivamente impiegata. */ double D = 0; /* [cm] la base della sezione rettangolare. */ double oldb; /* [cm] La base della sezione effettivamente usata. */ double b; /* [cm]il raggio idraulico. */ double rh; /* B=A(Rh^1/6) [m^13/6] */ B = (discharge * sqrt(WSPECIFICWEIGHT / tau)) / (CUBICMETER2LITER * ks); /* altezza sezione rettangolare */ oldD = METER2CM * pow(B, SIXOVERTHIRTEEN) * pow((2 * g + c), ONEOVERTHIRTEEN) / pow((g * c), SEVENOVERTHIRTEEN); /* [cm] base */ oldb = c * oldD; D = ceil(oldD); b = c * D; diameter = D; /* Rh [cm] raggio idraulico. */ rh = g * oldD * oldb / (2 * g * oldD + oldb); /* Grado di riempimento del tubo */ emptyDegree = b * rh / (D * (b - 2 * rh)); /* pendenza del tratto progettato [%] */ pipeSlope = (tau / (WSPECIFICWEIGHT * rh) * METER2CMSQUARED); return b; } /** * Dimensiona il tubo adottando una pendenza pari a quella del terreno * <p> * Sostanzialmente uguale alla get_height_1. L'unica differenza e che * dimensiona il tubo adottando una pendenza pari a quella del terreno. * <p> * * @param slope * , pendenza della tubazione. * @param g * Grado di riempimento da considerare nella progettazione della * rete * @param maxd * Diamtetro o altezza piu' grande adottato nei tratti piu' a * monte * @param c * Rapporto base-altezza della sezione rettangolare. */ private double getHeight1I( double slope, double g, double maxd, double c ) { /* B Pari a A * ( Rh^ 1/6) */ double B; /* * [cm] Diametro calcolato adottando una pendenza per i canali pari a * quella del terreno. */ double oldD; /* [cm] Altezza della sezione trapezoidale. */ double D; /* [cm] Base della sezione trapezoidale. */ double oldb; /* [cm] Base della sezione trapezoidale finale. */ double b; double rh; /* B=A(Rh^2/3) [m^13/6] */ B = (discharge) / (CUBICMETER2LITER * ks * sqrt(slope / METER2CM)); /* altezza sezione rettangolare */ oldD = METER2CM * pow(B, THREEOVEREIGHT) * pow(2 * g + c, ONEOVERFOUR) / pow((g * c), FIVEOVEREIGHT); /* [cm] base */ oldb = c * oldD; D = ceil(oldD); b = c * D; diameter = D; /* Rh [cm] raggio idraulico. */ rh = g * oldD * oldb / (2 * g * oldD + oldb); /* Grado di riempimento del tubo */ emptyDegree = b * rh / (D * (b - 2 * rh)); /* pendenza del tratto progettato [%] */ pipeSlope = slope; return b; } /** * Chiama altre subroutine per dimensionare una sezione di tipo 3, ossia * trapezioidale. * * <p> * Oltre al dimensionamento vero e proprio, calcola anche tutte le altre * grandezze correlate. * <ol> * <li>Inizialmente dimensiona il tubo chiamando la get_height_2() la quale * adotta il criterio dell'autopulizia e determina, mediante chiamate ad * ulteriori funuzioni tutte le grandezze necessarie (grado di riempimento, * pendenza, ecc..) * <li>Dopodiche riprogetta il tratto (chiamata a get_height_2_i) imponendo * una pendenza pari a quella del terreno, qualora questa fosse superioe a * quella ottenuta secondo il criterio di autopulizia. * <li>Inoltre ogni volta che dimensiona il tubo, design_pipe_3 (o le altre * funzioni da essa chiamate) calcola tutte le grandezze secondarie, ma * alquanto fondamentali (quota dello scavo, pelo libero ecc..) e le * registra nella matrice networkPipes. * </ol> * </p> * * @param tau * [Pa] Sforzo tangenziale al fondo che garantisca l'autopulizia * della rete * @param g * Grado di riempimento da considerare nella progettazione della * rete * @param maxd * Diamtetro o altezza piu' grande adottato nei tratti piu' a * monte * @param c * Rapporto base-altezza della sezione rettangolare. */ private void designTrapeziumPipe( double tau, double g, double maxd, double c, StringBuilder strWarnings ) { /* [cm] Base della sezione effettivamente adottata. */ double base; /* * [%] Pendenza naturale, calcolata in funzione dei dati geometrici * della rete */ double naturalSlope; /* [cm] Altezza del canale trapezoidale. */ double D; /* * [%] Pendenza minima da adottare per il tratto che si sta * dimensionando. */ double ms; /* DUE FORMULE */ /* * Dimensiona il diametro del tubo da adottare col criterio di * autopulizia, calcola altre grandezze correlate come la pendenza e il * grado di riempimento, e restituisce il riempimento effettivo nel * tratto progettato */ base = getHeight2(tau, g, maxd, c); /* [%] pendenza minima per il tratto che si sta dimensionando. */ ms = getMinimumPipeSlope(); /* [%] Pendenza del terreno */ naturalSlope = METER2CM * (initialElevation - finalElevation) / lenght; /* * Avvisa l'utente che il tratto che si sta progettando e in * contropendenza */ if (naturalSlope < 0) { strWarnings.append(msg.message("trentoP.warning.slope") + id); } /* La pendenza del terreno deve essere superiore a quella minima ms */ if (naturalSlope < ms) { naturalSlope = ms; } /* * Se la pendenza del terreno e maggiore di quella del tubo, allora la * pendenza del tubo viene posta uguale a quella del terreno. */ if (naturalSlope > pipeSlope) { pipeSlope = naturalSlope; /* * Progetta la condotta assegnado una pendenza pari a quella del * terreno, calcola altre grandezze correlate come la pendenza e il * grado di riempimento, e restituisce il riempimento effettivo nel * tratto progettato */ base = getHeight2I(naturalSlope, g, maxd, c); } /* Diametro tubo [cm] */ D = diameter; // Velocita media nella sezione [ m / s ] meanSpeed = (discharge / CUBICMETER2LITER) / (emptyDegree * D * base / METER2CMSQUARED); // Quota scavo all 'inizio del tubo [ m s . l . m . ] depthInitialPipe = getInitialElevation() - diameter / METER2CM; /* * Quota dello scavo alla fine del tubo calcolata considerando la * pendenza effettiva del tratto [ m s . l . m . ] */ depthFinalPipe = depthInitialPipe - getLenght() * pipeSlope / METER2CM; // Quota pelo libero all 'inizio del tubo [ m s . l . m . ] initialFreesurface = depthInitialPipe + emptyDegree * D / METER2CM; // Quota pelo libero all 'inizio del tubo [ m s . l . m . ] finalFreesurface = depthFinalPipe + emptyDegree * D / METER2CM; } /** * * Dimensiona i canali trapezioidale, imponendo un certo sforzo tangenziale * al fondo. * <p> * <ol> * <li>Calcola l'altezza oldD della sezione trapezoidale in funzione del * grado di riempimento e del rapporto base-altezza assegnati; ovviamente * imponendo un certo valore dello sforzo tangenziale al fondo (criterio di * autopulizia della rete.) * <li>Calcola la base oldb. * <li>Calcola il raggio idraulico richiesto, e a partire da esso determina * sia il grado di riempimento nella sezione commerciale che la pendenza * della tubazione, e gli registra nella matrice networkPipes. * <li>Infine la get_height_2 restituisce il valore della base della sezione * rettangolare adottata. * </ol> * </l> * * @param tau * [Pa] Sforzo tangenziale al fondo che garantisca l'autopulizia * della rete * @param g * Grado di riempimento da considerare nella progettazione della * rete * @param maxd * [cm] Diamtetro o altezza piu' grande adottati nei tratti piu' * a monte * @param c * Rapporto tra base e altezza nella sezione trapezoidale. */ private double getHeight2( double tau, double g, double maxd, double c ) { /* B Pari a A * ( Rh^ 1/6 ) */ double B; /* * oldD [cm] Diametro calcolato imponendo il criterio di autopulizia * della rete */ double oldD; /* D [cm] Altezza della sezione trapezoidale. */ double D; /* oldb [cm] Base della sezione tapezoidale. */ double oldb; /* b [cm] Base della sezione commerciale. */ double b; /* newrh [cm] Raggio idraulico. */ double rh; /* B=A(Rh^1/6) [m^13/6] */ B = (discharge * sqrt(WSPECIFICWEIGHT / tau)) / (CUBICMETER2LITER * ks); /* [cm] altezza sezione trapezia */ oldD = METER2CM * pow(B, SIXOVERTHIRTEEN) * pow((c + 2 * sqrt(2) * g), ONEOVERTHIRTEEN) / pow((g * (g + c)), SEVENOVERTHIRTEEN); /* [cm] base */ oldb = c * oldD; D = ceil(oldD); b = c * D; diameter = D; /* Rh [cm] raggio idraulico. */ rh = g * oldD * (g * oldD + oldb) / (oldb + 2 * sqrt(2) * g * oldD); /* Grado di riempimento del tubo */ emptyDegree = ((2 * sqrt(2) * rh * D - D * b) + sqrt(pow((D * b - 2 * sqrt(2) * rh * D), 2) + 4 * D * D * rh * b)) / (2 * D * D); /* pendenza del tratto progettato [%] */ pipeSlope = (tau / (WSPECIFICWEIGHT * rh) * METER2CMSQUARED); return b; } /** * Dimensiona il tubo adottando una pendenza pari a quella del terreno * <p> * Sostanzialmente uguale alla get_height_2. L'unica differenza e che * dimensiona iltubo adottando una pendenza pari a quella del terreno. * </p> * * @param slope * [%] Pendenza del tratto da dimensionare, che e' pari a quella * del terreno * @param g * Grado di riempimento da considerare nella progettazione della * rete * @param maxd * [cm]Diamtetro o altezza piu' grande adottati nei tratti piu' a * monte * @param c * Rapporto tra base e altezza nella sezione trapezoidale. */ private double getHeight2I( double slope, double g, double maxd, double c ) { /* B Pari a A * ( Rh^ 1/6 ). */ double B; /* * oldD [cm] Altezza della sezione trapezoidale calcolato imponendo una * pendenza pari a quella del terreno. */ double oldD; /* D [cm] Altezza della sezione trapezoidale. */ double D; /* oldb [cm]Base della sezione trapezoidale. */ double oldb; /* b [cm] la Base della sezione trapezoidale finale. */ double b; /* newrh [cm] Raggio idraulico. */ double rh; /* B=A(Rh^2/3) [m^13/6] */ B = (discharge) / (CUBICMETER2LITER * ks * sqrt(slope / METER2CM)); /* altezza sezione rettangolare */ oldD = METER2CM * pow(B, THREEOVEREIGHT) * pow((c + 2 * sqrt(2) * g), ONEOVERFOUR) / pow((g * (g + c)), FIVEOVEREIGHT); /* [cm] base */ oldb = c * oldD; D = ceil(oldD); b = c * D; diameter = D; /* Rh [cm] raggio idraulico. */ rh = g * oldD * (g * oldD + oldb) / (oldb + 2 * sqrt(2) * g * oldD); /* Grado di riempimento del tubo */ emptyDegree = ((2 * sqrt(2) * rh * D - D * b) + sqrt(pow((D * b - 2 * sqrt(2) * rh * D), 2) + 4 * D * D * rh * b)) / (2 * D * D); /* pendenza del tratto progettato [%] */ pipeSlope = slope; return b; } /** Verify if the empty degree is greather than the 0.8. * @param strWarnings * a string which collect all the warning messages. * @param q discharge in this pipe. */ public double verifyEmptyDegree( StringBuilder strWarnings, double q ) { /* Pari a A * ( Rh ^1/6 ) */ double B; /* Anglo formato dalla sezione bagnata */ double thta; /* Costante */ double known; /* * [rad]Angolo formato dalla sezione bagnata, adottando un diametro * commerciale */ double newtheta = 0; B = (q * sqrt(WSPECIFICWEIGHT / 2.8)) / (CUBICMETER2LITER * getKs()); /* Angolo formato dalla sezione bagnata [rad] */ thta = 2 * acos(1 - 2 * 0.8); known = (B * TWO_TENOVERTHREE) / pow(diameterToVerify / METER2CM, THIRTHEENOVERSIX); /* * Angolo formato dalla sezione bagnata considerando un diametro * commerciale [rad] */ newtheta = Utility.thisBisection(thta, known, ONEOVERSIX, minG, accuracy, jMax, pm, strWarnings); /* Grado di riempimento del tubo */ emptyDegree = 0.5 * (1 - cos(newtheta / 2)); return newtheta; } public void setIndexPipeWhereDrain( Integer indexPipeWhereDrain ) { this.indexPipeWhereDrain = indexPipeWhereDrain; } public Integer getIndexPipeWhereDrain() { return indexPipeWhereDrain; } }