1 module libs.openchannel;
2 
3 import std.math;
4 import std.algorithm;
5 
6 /++
7     Open Channel
8 
9     The base class for all open channels.
10 +/
11 class OpenChannel
12 {
13     /** ****************************************
14     * Constants
15     ***************************************** */
16     protected const double GRAVITY_METRIC = 9.81;
17     protected const ERROR = 0.0001;            // Trial error max to 1%
18 
19     /** ****************************************
20     * Properties
21     ***************************************** */
22     /**
23         Flow types. These are the categories in which the calculated froude number
24         is compared to.
25     */
26     public enum FlowType
27     {
28         CRITICAL,
29         SUBCRITICAL,
30         SUPERCRITICAL
31     }
32 
33     /// General available unknowns for open channel.
34     public enum Unknown
35     {
36         DISCHARGE,
37         BED_SLOPE,
38         WATER_DEPTH,
39         BASE_WIDTH,
40         PIPE_DIAMETER
41     }
42 
43     /// Discharge / Flow Rate
44     protected double discharge;
45 
46     /// Rise over run of the channel.
47     protected double bedSlope;
48 
49     /// Depth of water measured from the deepest point of the
50     /// channel.
51     protected double waterDepth;
52 
53     /// Manning's roughness coefficient.
54     protected float manningRoughness;
55 
56     /// Total length of the channel section covered with water.
57     protected double wettedPerimeter;
58 
59     /// Total area of the channel section covered with water.
60     protected double wettedArea;
61 
62     /// wettedArea / wettedPerimeter
63     protected double hydraulicRadius;
64 
65     /// Average velocity over the whole cross section of the channel.
66     protected double averageVelocity;
67 
68     /// Froude number.
69     protected float froudeNumber;
70 
71     /// Enum type. (e.g. DISCHARGE, WATER_DEPTH, etc.)
72     protected Unknown unknown;
73 
74     protected FlowType flowType;
75 
76     protected double hydraulicDepth;
77     protected double dischargeIntensity;
78     protected double criticalDepth;
79     protected double criticalSlope;
80     protected Unknown[] availableUnknowns = [Unknown.DISCHARGE];
81 
82     protected bool isCalculationSuccess;
83     public string errorMessage;
84 
85     /+++++++++++++++++++++++++++++++++++++++++++++++ 
86     +                  Getters                     +
87     +++++++++++++++++++++++++++++++++++++++++++++++/
88     
89     /** Returns the rate of flow. */
90     public double getDischarge()
91     {
92         return discharge;
93     }
94 
95     /** Returns the average velocity in the channel. */
96     public double getAverageVelocity()
97     {
98         return averageVelocity;
99     }
100 
101     public double getBedSlope()
102     {
103         return bedSlope;
104     }
105 
106     public double getWaterDepth()
107     {
108         return waterDepth;
109     }
110 
111     public double getWettedPerimeter()
112     {
113         return wettedPerimeter;
114     }
115 
116     public double getWettedArea()
117     {
118         return wettedArea;
119     }
120 
121     public double getHydraulicRadius()
122     {
123         return hydraulicRadius;
124     }
125 
126     public double getFroudeNumber()
127     {
128         return froudeNumber;
129     }
130 
131     public double getManningRoughness()
132     {
133         return manningRoughness;
134     }
135 
136     public FlowType getFlowType()
137     {
138         return flowType;
139     }
140 
141     public double getHydraulicDepth()
142     {
143         return hydraulicDepth;
144     }
145 
146     public double getDischargeIntensity()
147     {
148         return dischargeIntensity;
149     }
150 
151     public double getCriticalDepth()
152     {
153         return criticalDepth;
154     }
155 
156     public double getCriticalSlope()
157     {
158         return criticalSlope;
159     }
160 
161     /**
162     * Check if an error has occurred.
163     * @return isError
164     */
165     public bool isCalculationSuccessful()
166     {
167         return isCalculationSuccessful;
168     }
169 
170     /**
171     * Gets the error message.
172     * @return errMessage
173     */
174     public string getErrMessage()
175     {
176         return errorMessage;
177     }
178 
179     /+++++++++++++++++++++++++++++++++++++++++++++++ 
180     +                  Setters                     +
181     +++++++++++++++++++++++++++++++++++++++++++++++/
182     public void setBedSlope(double pBedSlope)
183     {
184         bedSlope = pBedSlope;
185     }
186 
187     public void setDischarge(double pDischarge)
188     {
189         discharge = pDischarge;
190     }
191 
192     public void setWaterDepth(double pWaterDepth)
193     {
194         waterDepth = pWaterDepth;
195     }
196 
197     public void setManningRoughness(double pManningRoughness)
198     {
199         manningRoughness = pManningRoughness;
200     }
201 
202     public void setUnknown(Unknown u) {
203         unknown = u;
204     }
205 
206     /+++++++++++++++++++++++++++++++++++++++++++++++
207     +                   Methods                    +
208     +++++++++++++++++++++++++++++++++++++++++++++++/
209     protected void calculateFlowType()
210     {
211         // Flow type
212         if (this.froudeNumber == 1)
213         {
214             flowType = FlowType.CRITICAL;
215         }
216         else if (this.froudeNumber < 1)
217         {
218             flowType = FlowType.SUBCRITICAL;
219         }
220         else
221         {
222             flowType = FlowType.SUPERCRITICAL;
223         }
224     }
225 
226     /+++++++++++++++++++++++++++++++++++++++++++++++
227     +               Error handling                 +
228     +++++++++++++++++++++++++++++++++++++++++++++++/
229 
230     /**
231     * Manning's roughness error checking
232     */
233     protected bool isValidManning()
234     {
235         if (manningRoughness <= 0.0)
236         {
237             errorMessage = "Manning\'s roughness must be set greater than zero.";
238             return false;
239         }
240 
241         if (isNaN(manningRoughness))
242         {
243             errorMessage = "Manning\'s roughness must be numeric.";
244             return false;
245         }
246 
247         // errorMessage = "Valid manning's rougness. Calculation successful.";
248         return true;
249     }
250 
251     /**
252     * Bed slope error checking
253     */
254     protected bool isValidBedSlope(Unknown u)
255     {
256         if (isNaN(bedSlope) && u != Unknown.BED_SLOPE)
257         {
258             errorMessage = "Bed slope must be numeric.";
259             return false;
260         }
261 
262         if (bedSlope <= 0.0 && u != Unknown.BED_SLOPE)
263         {
264             errorMessage = "Bed slope must be set greater than zero.";
265             return false;
266         }
267 
268         // errorMessage = "Valid bed slope. Calculation successful.";
269         return true;
270     }
271 
272     /**
273     *   Water depth error checking
274     */
275     protected bool isValidWaterDepth(Unknown u)
276     {
277         if (isNaN(waterDepth) && u != Unknown.WATER_DEPTH)
278         {
279             errorMessage = "Water depth must be set to numeric.";
280             return false;
281         }
282 
283         if (waterDepth <= 0.0 && u != Unknown.WATER_DEPTH)
284         {
285             errorMessage = "Water depth must be set greater than or equal to zero.";
286             return false;
287         }
288 
289         // errorMessage = "Valid water depth. Calculation successful.";
290         return true;
291     }
292 
293     protected bool isValidDischarge(Unknown u) {
294         if (isNaN(discharge) && u != Unknown.DISCHARGE) {
295             errorMessage = "Discharge must be numeric.";
296             return false;
297         }
298 
299         if (discharge < 0 && u != Unknown.DISCHARGE) {
300             errorMessage = "Discharge must be set greater than zero.";
301             return false;
302         }
303 
304         // errorMessage = "Valid discharge. Calculation successful.";
305         return true;
306     }
307 
308     /// Check if all conditions are true
309     protected bool isValidInputs(A...)(A a)
310     {
311         bool res = true;
312         foreach (b; a)
313         {
314             res = res && b;
315         }
316 
317         if (res) errorMessage = "Calculation successful.";
318         return res;
319     }
320 
321 }
322 
323 class InvalidInputException : Exception
324 {
325     this(string msg, string file = __FILE__, size_t line = __LINE__)
326     {
327         super(msg, file, line);
328     }
329 }