1 /** 2 libs.weirs.sharpcrested module 3 Module for hydraulic analysis of sharp crested weirs used in diversion dams. 4 */ 5 module libs.weirs.broadcrested; 6 7 import libs.weirs.weir; 8 import libs.utils.constants; 9 import libs.utils.hydraulics; 10 import libs.utils.geometry_calculators; 11 12 import std.math: abs, pow, sqrt, isNaN; 13 import std.stdio; 14 15 /** 16 SharpCrestedWeir class. 17 Contains fields and methods for hydraulic calculations 18 of sharp crested weirs. 19 */ 20 class BroadCrestedWeir : Weir 21 { 22 /////////////////////////////////////// 23 // Properties // 24 /////////////////////////////////////// 25 26 double dA, // Depth at approach 27 vA, // Velocity at approach 28 hA, // Height at approach 29 eE, // Energy elevation 30 ho, 31 h1, 32 h2, 33 h2_h1, 34 co, 35 correction, 36 cs; 37 38 /** 39 Empty constructor. 40 */ 41 this() 42 { 43 44 } 45 46 //++++++++++++++++++++++++++++++++++++++++++++++ 47 // Methods + 48 //+++++++++++++++++++++++++++++++++++++++++++++/ 49 50 /** 51 Performs the hydraulic analysis for sharp-crested (gated) weirs/diversion dams. 52 */ 53 bool analysis() 54 { 55 if (!isValidInputs) 56 { 57 return false; 58 } 59 60 // Reset values 61 TRIAL_INCREMENT = 0.0001; 62 calculatedDischargeIntensity = 0; 63 64 dischargeIntensity = discharge / crestLength; 65 66 // Afflux elevation initial assumption 67 affluxElevation = crestElev > tailwaterElev ? crestElev : tailwaterElev; 68 69 // Accuracy closure 70 const allowedDiff = discharge * ERROR; 71 72 // Calculation for the afflux elevation 73 while (abs(dischargeIntensity - calculatedDischargeIntensity) > allowedDiff) 74 { 75 affluxElevation += TRIAL_INCREMENT; 76 dA = affluxElevation - usApronElev; 77 vA = dischargeIntensity / dA; 78 hA = velocityHead(vA); 79 eE = affluxElevation + hA; 80 ho = eE - crestElev; 81 co = 3.087; 82 h1 = affluxElevation - crestElev; 83 h2 = tailwaterElev - crestElev; 84 h2_h1 = h2 / h1; 85 if (h2 <= 0) 86 { 87 correction = 1; 88 } 89 else 90 { 91 // correction = pow((1 - pow(h2_h1, (3.0/2.0))), 0.385); 92 // APply correction for broad crested weirs 93 correction = broadCrestedWeirCorrection(h2_h1); 94 } 95 cs = co * correction; 96 calculatedDischargeIntensity = cs / 1.811 * pow(ho, (3.0 / 2.0)); 97 98 // My root-finding acceleration 99 if (calculatedDischargeIntensity < dischargeIntensity) 100 { 101 TRIAL_INCREMENT *= 2.1; 102 } 103 else 104 { 105 affluxElevation -= TRIAL_INCREMENT; 106 TRIAL_INCREMENT *= 0.75; 107 } 108 // End of root finding acceleration 109 } 110 111 // Calculation for the hydraulic jump 112 double d1, // Pre-jump height 113 d2, // Hydraulic jump height 114 he, 115 he2 = 0, // Pre-jump height to energy grade elevation 116 v1, 117 hv1; 118 float f; // Froude number 119 120 TRIAL_INCREMENT = 0.0001; // Reset 121 d1 = 0; 122 he = eE - dsApronElev; 123 124 // Froude number calculation 125 // Hydraulic jump calculation 126 while (abs(he - he2) > ERROR) 127 { 128 d1 += TRIAL_INCREMENT; 129 v1 = dischargeIntensity / d1; 130 hv1 = velocityHead(v1); 131 he2 = d1 + hv1; 132 d2 = (-1 * d1 / 2) + sqrt((pow(d1, 2) / 4.0) + (2 * pow(v1, 2) * d1 / GRAVITY)); 133 f = v1 / sqrt(d1 * GRAVITY); 134 } 135 136 // Length of hydraulic jump 137 if (f < 1.6) 138 { 139 lengthOfHydraulicJump = 4 * d2; 140 } else { 141 lengthOfHydraulicJump = hydraulicJump(f); 142 } 143 144 preJumpElev = dsApronElev + d1; 145 jumpElev = dsApronElev + d2; 146 147 errorMessage = "Calculation successful."; 148 return true; 149 } 150 151 private bool isValidInputs() 152 { 153 // Check for each input 154 if (isNaN(discharge)) 155 { 156 errorMessage = "Discharge must be set."; 157 return false; 158 } 159 160 if (isNaN(crestElev)) 161 { 162 errorMessage = "Crest elevation must be set."; 163 return false; 164 } 165 166 if (isNaN(crestLength)) 167 { 168 errorMessage = "Crest length must be set."; 169 return false; 170 } 171 172 if (isNaN(usApronElev)) 173 { 174 errorMessage = "Elevation of upstream apron must be set."; 175 return false; 176 } 177 178 if (isNaN(dsApronElev)) 179 { 180 errorMessage = "Elevation of downstream apron must be set."; 181 return false; 182 } 183 184 if (isNaN(tailwaterElev)) 185 { 186 errorMessage = "Elevation of tail water must be set."; 187 return false; 188 } 189 190 // Check if tailwater if lower than downstream apron 191 if (tailwaterElev < dsApronElev) 192 { 193 errorMessage = "Tailwater elevation must be set higher or the same as downstream apron."; 194 return false; 195 } 196 197 // Check crest is lower than upstream apron 198 if (crestElev < usApronElev) 199 { 200 errorMessage = "Crest elevation must be the same or higher then upstream apron."; 201 return false; 202 } 203 204 return true; 205 } 206 207 private double broadCrestedWeirCorrection(double h2_h1) 208 { 209 // hs/hc = [] 210 // Cs/C = [] 211 double correction = 0; 212 const double[11][2] cs_c = [ 213 [ 214 0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1 215 ], 216 [ 217 1, 0.991, 0.983, 0.972, 0.956, 0.937, 0.907, 0.856, 0.778, 0.621, 0 218 ] 219 ]; 220 221 for (int i = 0; i < (cs_c.length - 1); i++) 222 { 223 if (h2_h1 >= cs_c[0][i] && h2_h1 < cs_c[0][i+1]) 224 { 225 correction = interpolate(cs_c[1][i], 226 cs_c[1][i + 1], 227 cs_c[0][i], 228 h2_h1, 229 cs_c[0][i + 1]); 230 } 231 } 232 233 return correction; 234 } 235 }