1 /** 2 * openchannel module. 3 */ 4 module libs.openchannel; 5 6 import std.math; 7 import std.algorithm; 8 9 /++ 10 + The base class for all open channels. 11 +/ 12 class OpenChannel 13 { 14 //****************************************** 15 // Constants 16 //*************************************** */ 17 /// Gravitational acceleration in metric. 18 protected const GRAVITY_METRIC = 9.81; 19 /// Trial error max to 0.01% 20 protected const ERROR = 0.0001; 21 22 // **************************************** 23 // Properties 24 //*************************************** */ 25 /** 26 * Units options 27 */ 28 enum Units 29 { 30 METRIC, 31 ENGLISH 32 } 33 /** 34 * Flow types. These are the categories in which the calculated froude number 35 * is compared to. 36 */ 37 public enum FlowType 38 { 39 CRITICAL, 40 SUBCRITICAL, 41 SUPERCRITICAL 42 } 43 44 /// General available unknowns for open channel. 45 public enum Unknown 46 { 47 DISCHARGE, 48 BED_SLOPE, 49 WATER_DEPTH, 50 BASE_WIDTH, 51 PIPE_DIAMETER 52 } 53 /** Unit of measurement.\ 54 All calculations will be done in metric but both 55 metric and imperial system are supported. 56 */ 57 protected Units unit = Units.METRIC; 58 59 /// Discharge (Flow Rate) 60 protected double discharge; 61 62 /// Rise over run of the channel. 63 protected double bedSlope; 64 65 /// Depth of water measured from the deepest point of the 66 /// channel. 67 protected double waterDepth; 68 69 /// Manning's roughness coefficient. 70 protected float manningRoughness; 71 72 /// Total length of the channel section covered with water. 73 protected double wettedPerimeter; 74 75 /// Total area of the channel section covered with water. 76 protected double wettedArea; 77 78 /// wettedArea / wettedPerimeter 79 protected double hydraulicRadius; 80 81 /// Average velocity over the whole cross section of the channel. 82 protected double averageVelocity; 83 84 /// Froude number. 85 protected float froudeNumber; 86 87 /// Enum type. (e.g. DISCHARGE, WATER_DEPTH, etc.) 88 protected Unknown unknown; 89 90 /// Flow type reconned from the Enum type FlowType 91 protected FlowType flowType; 92 /// Hydraulic depth 93 protected double hydraulicDepth; 94 /// Discharge intensity. Discharge divided by the top channel width. 95 protected double dischargeIntensity; 96 /// Depth of flow that will give critical flow. 97 protected double criticalDepth; 98 /// Bed slope that will give critical flow. 99 protected double criticalSlope; 100 /// Available unknowns 101 protected Unknown[] availableUnknowns = [Unknown.DISCHARGE]; 102 /// Variable that tells if the calculation has no error. 103 protected bool isCalculationSuccess; 104 /// The error or warning message that helps debug or give 105 /// information about the calculation results. 106 public string errorMessage; 107 108 //++++++++++++++++++++++++++++++++++++++++++++++ 109 // Constructors + 110 //+++++++++++++++++++++++++++++++++++++++++++++/ 111 112 /** 113 * Empty constructor. 114 * The unit is automatically set to S.I. (Metric). 115 */ 116 this() 117 { 118 this.intialize(); 119 } 120 121 /** 122 Put all the initializations here. 123 */ 124 protected void intialize() 125 { 126 unknown = Unknown.DISCHARGE; 127 unit = Units.METRIC; 128 } 129 130 //++++++++++++++++++++++++++++++++++++++++++++++ 131 // Getters + 132 //+++++++++++++++++++++++++++++++++++++++++++++/ 133 134 /** 135 Returns the rate of flow in either cubic meter per second (metric) 136 or cubic feet per second (english). 137 */ 138 public double getDischarge() 139 { 140 if (unit == Units.ENGLISH) 141 { 142 return discharge * pow(3.28, 3); 143 } else { 144 return discharge; 145 } 146 } 147 148 /** 149 Returns the average velocity in the channel in either meter per second (metric) 150 or feet per second (english). 151 */ 152 public double getAverageVelocity() 153 { 154 if (unit == Units.ENGLISH) 155 { 156 return averageVelocity * 3.28; 157 } 158 return averageVelocity; 159 } 160 161 /** 162 Returns the bed (bottom) slope of the channel. 163 */ 164 public double getBedSlope() 165 { 166 return bedSlope; 167 } 168 169 /** 170 Returns the water depth in either meter 171 or feet. 172 */ 173 public double getWaterDepth() 174 { 175 if (unit == Units.ENGLISH) 176 { 177 return waterDepth * 3.28; 178 } 179 return waterDepth; 180 } 181 182 /** 183 Returns the wet perimeter in either meter of feet. 184 */ 185 public double getWettedPerimeter() 186 { 187 if (unit == Units.ENGLISH) 188 { 189 return wettedPerimeter * 3.28; 190 } 191 return wettedPerimeter; 192 } 193 194 /** 195 Returns the wet area in either square meter or 196 square foot. 197 */ 198 public double getWettedArea() 199 { 200 if (unit == Units.ENGLISH) 201 { 202 return wettedArea * pow(3.28, 2); 203 } 204 return wettedArea; 205 } 206 207 /** 208 Returns the hydraulic radius in either meters 209 or feet. 210 */ 211 public double getHydraulicRadius() 212 { 213 if (unit == Units.ENGLISH) 214 { 215 return hydraulicRadius * 3.28; 216 } 217 return hydraulicRadius; 218 } 219 220 /** 221 Returns the froude number 222 */ 223 public double getFroudeNumber() 224 { 225 return froudeNumber; 226 } 227 228 /** 229 Retuens the manning's roughness coefficient. 230 */ 231 public double getManningRoughness() 232 { 233 return manningRoughness; 234 } 235 236 /** 237 Returns the string representation of type of flow. 238 */ 239 public FlowType getFlowType() 240 { 241 return flowType; 242 } 243 244 /** 245 Returns the hydraulic depth in either meter 246 or foot. 247 */ 248 public double getHydraulicDepth() 249 { 250 if (unit == Units.ENGLISH) 251 { 252 return hydraulicDepth * 3.28; 253 } 254 return hydraulicDepth; 255 } 256 257 /** 258 Returns discharge intensity in either cubic meter per second per meter 259 or cubic foot per second per foot. 260 */ 261 public double getDischargeIntensity() 262 { 263 if (unit == Units.ENGLISH) 264 { 265 return dischargeIntensity * pow(3.28, 2); 266 } 267 return dischargeIntensity; 268 } 269 270 /** 271 Returns critical depth in either meters or feet. 272 */ 273 public double getCriticalDepth() 274 { 275 if (unit == Units.ENGLISH) 276 { 277 return criticalDepth * 3.28; 278 } 279 return criticalDepth; 280 } 281 282 /** 283 Returns the slope of the critical flow for the channel. 284 */ 285 public double getCriticalSlope() 286 { 287 return criticalSlope; 288 } 289 290 /** 291 * Check if an error has occurred. 292 * @return isError 293 */ 294 public bool isCalculationSuccessful() 295 { 296 return isCalculationSuccessful; 297 } 298 299 /** 300 * Gets the error message. 301 * @return errMessage 302 */ 303 public string getErrMessage() 304 { 305 return errorMessage; 306 } 307 308 //++++++++++++++++++++++++++++++++++++++++++++++ 309 // Setters + 310 //+++++++++++++++++++++++++++++++++++++++++++++/ 311 312 /** 313 Set the bed slope of the channel. 314 Params: 315 pBedSlope = Bed or bottom slope of the channel. 316 */ 317 public void setBedSlope(double pBedSlope) 318 { 319 bedSlope = pBedSlope; 320 } 321 322 /** 323 Sets the discharge. 324 Params: 325 pDeischarge = discharge in either cubic meter per second or 326 cubic foot per second. 327 */ 328 public void setDischarge(double pDischarge) 329 { 330 if (unit == Units.ENGLISH) 331 { 332 discharge = pDischarge * pow(1 / 3.28, 3); 333 } 334 else 335 { 336 discharge = pDischarge; 337 } 338 } 339 340 /** 341 Sets the water depth. 342 Params: 343 pWaterDepth = Water depth in either meter or foot. 344 */ 345 public void setWaterDepth(double pWaterDepth) 346 { 347 if (unit == Units.ENGLISH) 348 { 349 waterDepth = pWaterDepth / 3.28; 350 } 351 else 352 { 353 waterDepth = pWaterDepth; 354 } 355 } 356 357 /** 358 Sets the manning roughness coefficient. 359 Params: 360 pManningRoughness = Manning's roughness coefficient. 361 */ 362 public void setManningRoughness(double pManningRoughness) 363 { 364 manningRoughness = pManningRoughness; 365 } 366 367 /** 368 Sets the unknown based on the available unknowns of a specific channel type. 369 Params: 370 u = Unknown. 371 */ 372 public void setUnknown(Unknown u) 373 { 374 unknown = u; 375 } 376 377 /** 378 Sets the unit. 379 Params: 380 u = Unit 381 */ 382 public void setUnit(Units u) 383 { 384 unit = u; 385 } 386 387 //++++++++++++++++++++++++++++++++++++++++++++++ 388 // Methods + 389 //+++++++++++++++++++++++++++++++++++++++++++++/ 390 /** 391 Determines the flow type based on the froude number. 392 */ 393 protected void calculateFlowType() 394 { 395 // Flow type 396 if (this.froudeNumber == 1) 397 { 398 flowType = FlowType.CRITICAL; 399 } 400 else if (this.froudeNumber < 1) 401 { 402 flowType = FlowType.SUBCRITICAL; 403 } 404 else 405 { 406 flowType = FlowType.SUPERCRITICAL; 407 } 408 } 409 410 /+++++++++++++++++++++++++++++++++++++++++++++++ 411 + Error handling + 412 +++++++++++++++++++++++++++++++++++++++++++++++/ 413 414 /** 415 * Manning's roughness error checking 416 */ 417 protected bool isValidManning() 418 { 419 if (manningRoughness <= 0.0) 420 { 421 errorMessage = "Manning\'s roughness must be set greater than zero."; 422 return false; 423 } 424 425 if (isNaN(manningRoughness)) 426 { 427 errorMessage = "Manning\'s roughness must be numeric."; 428 return false; 429 } 430 431 // errorMessage = "Valid manning's rougness. Calculation successful."; 432 return true; 433 } 434 435 /** 436 * Bed slope error checking 437 */ 438 protected bool isValidBedSlope(Unknown u) 439 { 440 if (isNaN(bedSlope) && u != Unknown.BED_SLOPE) 441 { 442 errorMessage = "Bed slope must be numeric."; 443 return false; 444 } 445 446 if (bedSlope <= 0.0 && u != Unknown.BED_SLOPE) 447 { 448 errorMessage = "Bed slope must be set greater than zero."; 449 return false; 450 } 451 452 // errorMessage = "Valid bed slope. Calculation successful."; 453 return true; 454 } 455 456 /** 457 * Water depth error checking 458 */ 459 protected bool isValidWaterDepth(Unknown u) 460 { 461 if (isNaN(waterDepth) && u != Unknown.WATER_DEPTH) 462 { 463 errorMessage = "Water depth must be set to numeric."; 464 return false; 465 } 466 467 if (waterDepth <= 0.0 && u != Unknown.WATER_DEPTH) 468 { 469 errorMessage = "Water depth must be set greater than or equal to zero."; 470 return false; 471 } 472 473 // errorMessage = "Valid water depth. Calculation successful."; 474 return true; 475 } 476 477 /** 478 Discharge error checking. 479 */ 480 protected bool isValidDischarge(Unknown u) 481 { 482 if (isNaN(discharge) && u != Unknown.DISCHARGE) 483 { 484 errorMessage = "Discharge must be numeric."; 485 return false; 486 } 487 488 if (discharge < 0 && u != Unknown.DISCHARGE) 489 { 490 errorMessage = "Discharge must be set greater than zero."; 491 return false; 492 } 493 494 // errorMessage = "Valid discharge. Calculation successful."; 495 return true; 496 } 497 498 /// Check if all conditions are true 499 protected bool isValidInputs(A...)(A a) 500 { 501 bool res = true; 502 foreach (b; a) 503 { 504 res = res && b; 505 } 506 507 if (res) 508 errorMessage = "Calculation successful."; 509 return res; 510 } 511 512 }