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 }