0% found this document useful (0 votes)
60 views7 pages

Irregular Section Channel (Java)

Source code for one of the classes in my library IrrigFlo. IrrigFlo is a java library that can be used by developer in developing softwares for hydraulic structures.

Uploaded by

Alex
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
60 views7 pages

Irregular Section Channel (Java)

Source code for one of the classes in my library IrrigFlo. IrrigFlo is a java library that can be used by developer in developing softwares for hydraulic structures.

Uploaded by

Alex
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 7

1 package com.alexiusacademia.

hydraulics;
2
3 import java.util.ArrayList;
4 import java.util.List;
5
6 /**
7 * Irregular section channel
8 * An extension of the class OpenChannel
9 * Used for irregular section channel, usually river channels.
10 */
11 public class IrregularSectionChannel extends OpenChannel {
12 /* **********************************
13 * Properties
14 ***********************************/
15
16 public enum Unknown { // Unknown class
17 DISCHARGE,
18 BED_SLOPE
19 }
20
21
22 private Unknown unknown; // Unknown
23 private List<Point> points; // List of points for the channel profile
24 private float maxWaterElevation;
25 private float waterElevation;
26 private double calculatedDischarge;
27 private double criticalWaterElevation;
28
29 /* **********************************
30 * Setters
31 ***********************************/
32
33 public void setUnknown(Unknown unknown) {
34 this.unknown = unknown;
35 }
36
37 public void setPoints(List<Point> points) {
38 this.points = points;
39 }
40
41 public void setWaterElevation(float waterElevation) {
42 this.waterElevation = waterElevation;
43 }
44
45 /* **********************************
46 * Getters
47 ***********************************/
48
49 public List<Point> getPoints() {
50 return points;
51 }
52
53 public float getMaxWaterElevation() {
54 return maxWaterElevation;
55 }
56
57 public float getWaterElevation() {
58 return waterElevation;
59 }
60
61 public double getCriticalWaterElevation() {
62 return criticalWaterElevation;
63 }
64
65 public Unknown getUnknown() {
66 return unknown;
67 }
68
69 /**
70 * Create an empty {@code IrregularSectionChannel}
71 */
72 public IrregularSectionChannel() {
73 this.unknown = Unknown.DISCHARGE;
74 }
75
76 /**
77 * Creates an {@code IrregularOpenChannel} with given unknown
78 * @param unknown Unknown
79 */
80 public IrregularSectionChannel(Unknown unknown) {
81 this.unknown = unknown;
82 }
83
84 /**
85 * Creates an {@code IrregularSectionChannel} with gicen unknown and points
86 * @param unknown Unknown
87 * @param pts List of Points
88 */
89 public IrregularSectionChannel(Unknown unknown, List<Point> pts) {
90 this.points = pts;
91 }
92
93 /* **********************************
94 * Methods
95 ***********************************/
96
97 public boolean analyze() {
98 if (isValidInputs()) {
99 switch (this.unknown) {
100 case DISCHARGE:
101 solveForDischarge();
102 break;
103 case BED_SLOPE:
104 solveForBedSlope();
105 break;
106 default:
107 try {
108 throw new InvalidValueException("Invalid unknown.");
109 } catch (InvalidValueException e) {
110 this.isCalculationSuccessful = false;
111 this.errMessage = e.getMessage();
112 }
113 }
114 solveForCriticalFlow();
115 return isCalculationSuccessful;
116 }
117 return false;
118 }
119
120 /**
121 * Solve for the unknown bed slope
122 */
123 private void solveForBedSlope() {
124 // Number of waterline intersections
125 int leftIntersections = 0, rightIntersections = 0;
126
127 // Remove points above the waterline intersection at the banks
128 List<Point> newPoints = new ArrayList<>();
129
130 float x1, x2, x3, y1, y2;
131
132 for (int i = 0; i < this.points.size(); i++) {
133 // float x = this.points.get(i).getX();
134 float y = this.points.get(i).getY();
135
136 // Look for the intersection at the left side of the channel
137 if (leftIntersections == 0) {
138 if (y <= this.waterElevation && i > 0) {
139 leftIntersections++;
140 // Solve for the intersection point using interpolation
141 x1 = this.points.get(i - 1).getX();
142 y1 = this.points.get(i - 1).getY();
143 x2 = this.points.get(i).getX();
144 y2 = this.points.get(i).getY();
145 x3 = (this.waterElevation - y1) * (x2 - x1) / (y2 - y1) + x1;
146 newPoints.add(new Point(x3, this.waterElevation));
147 }
148 }
149
150 // Look for the intersection at the right side of the channel
151 if (rightIntersections == 0) {
152 if (y >= this.waterElevation && i > 0) {
153 rightIntersections++;
154 x1 = this.points.get(i - 1).getX();
155 y1 = this.points.get(i - 1).getY();
156 x2 = this.points.get(i).getX();
157 y2 = this.points.get(i).getY();
158 x3 = (this.waterElevation - y1) * (x2 - x1) / (y2 - y1) + x1;
159 newPoints.add(new Point(x3, this.waterElevation));
160 }
161 }
162
163 if (leftIntersections == 1) {
164 if (rightIntersections == 0) {
165 newPoints.add(this.points.get(i));
166 }
167 }
168 }
169
170 double trialSlope = 0;
171 calculatedDischarge = 0;
172
173 while (calculatedDischarge < this.discharge) {
174 trialSlope += SLOPE_TRIAL_INCREMENT;
175 this.wettedArea = polygonArea(newPoints);
176 this.wettedPerimeter = polygonPerimeter(newPoints);
177 this.hydraulicRadius = this.wettedArea / this.wettedPerimeter;
178 this.averageVelocity = (1 / this.manningRoughness) * Math.sqrt(trialSlope) *
179 Math.pow(this.hydraulicRadius, (2.0/3.0));
180 calculatedDischarge = this.averageVelocity * this.wettedArea;
181 }
182
183 this.bedSlope = trialSlope;
184 this.isCalculationSuccessful = true;
185 }
186
187 /**
188 * Solve for the unknown discharge
189 */
190 private void solveForDischarge() {
191 // Number of waterline intersections
192 int leftIntersections = 0, rightIntersections = 0;
193
194 // Remove points above the waterline intersection at the banks
195 List<Point> newPoints = new ArrayList<>();
196
197 float x1, x2, x3, y1, y2;
198
199 for (int i = 0; i < this.points.size(); i++) {
200 // float x = this.points.get(i).getX();
201 float y = this.points.get(i).getY();
202
203 // Look for the intersection at the left side of the channel
204 if (leftIntersections == 0) {
205 if (y <= this.waterElevation && i > 0) {
206 leftIntersections++;
207 // Solve for the intersection point using interpolation
208 x1 = this.points.get(i - 1).getX();
209 y1 = this.points.get(i - 1).getY();
210 x2 = this.points.get(i).getX();
211 y2 = this.points.get(i).getY();
212 x3 = (this.waterElevation - y1) * (x2 - x1) / (y2 - y1) + x1;
213 newPoints.add(new Point(x3, this.waterElevation));
214 }
215 }
216
217 // Look for the intersection at the right side of the channel
218 if (rightIntersections == 0) {
219 if (y >= this.waterElevation && i > 0) {
220 rightIntersections++;
221 x1 = this.points.get(i - 1).getX();
222 y1 = this.points.get(i - 1).getY();
223 x2 = this.points.get(i).getX();
224 y2 = this.points.get(i).getY();
225 x3 = (this.waterElevation - y1) * (x2 - x1) / (y2 - y1) + x1;
226 newPoints.add(new Point(x3, this.waterElevation));
227 }
228 }
229
230 if (leftIntersections == 1) {
231 if (rightIntersections == 0) {
232 newPoints.add(this.points.get(i));
233 }
234 }
235 }
236
237 // Hydraulic elements
238 this.wettedArea = polygonArea(newPoints);
239 this.wettedPerimeter = polygonPerimeter(newPoints);
240 this.hydraulicRadius = this.wettedArea / this.wettedPerimeter;
241 this.averageVelocity = (1 / this.manningRoughness) * Math.sqrt(this.bedSlope) *
242 Math.pow(this.hydraulicRadius, (2.0/3.0));
243 this.discharge = this.averageVelocity * this.wettedArea;
244
245 this.isCalculationSuccessful = true;
246 }
247
248 /**
249 * Implementation of the shoelace formula in computing area of a polygon with
250 * given vertices.
251 * @param points The vertices covered by the cross sectional area.
252 * @return Double Polygon area
253 */
254 private double polygonArea(List<Point> points) {
255 // Number of vertices of the polygon
256 int n = points.size();
257
258 // Initialize area
259 double area = 0;
260 int j;
261
262 for (int i = 0; i < n; i++) {
263 j = (i + 1) % n;
264 area += points.get(i).getX() * points.get(j).getY();
265 area -= points.get(j).getX() * points.get(i).getY();
266 }
267
268 area = Math.abs(area) / 2;
269
270 return area;
271 }
272
273 /**
274 * Get the total distance covered by multiple points
275 * @param points The vertices covered by the cross sectional area.
276 * @return Double Polygon perimeter
277 */
278 private double polygonPerimeter(List<Point> points) {
279 // Initialize perimeter
280 double perimeter = 0;
281
282 // Number of vertices of the polygon
283 int n = points.size();
284
285 Point p1, p2;
286
287 for (int i = 0; i < (n-1); i++) {
288 p1 = points.get(i);
289 p2 = points.get(i + 1);
290 perimeter += distanceBetweenTwoPoints(p1, p2);
291 }
292
293 return perimeter;
294 }
295
296 /**
297 * Calculate the distance between two given points.
298 * @param p1 First point
299 * @param p2 Second point
300 * @return Double The distance between the 2 points
301 */
302 private double distanceBetweenTwoPoints(Point p1, Point p2) {
303 float x1, y1, x2, y2;
304 x1 = p1.getX();
305 y1 = p1.getY();
306 x2 = p2.getX();
307 y2 = p2.getY();
308 return Math.sqrt(Math.pow((y2 - y1), 2) + Math.pow((x2 - x1), 2));
309 }
310
311 /**
312 * Get the lowest point elevation from the list of poits.
313 * @return Double Lowest point
314 */
315 private float calculateLowestPoint() {
316 List<Float> elevations = new ArrayList<Float>();
317 float lowest = 0;
318
319 for (Point p : this.points) {
320 elevations.add(p.getY());
321 }
322
323 for (float el : elevations) {
324 if (lowest > el) {
325 lowest = el;
326 }
327 }
328
329 return lowest;
330 }
331
332 /**
333 * Check for invalid inputs
334 * @return Boolean True if all inputs are valid.
335 */
336 private boolean isValidInputs() {
337 // First, solve for the lowest bank
338 int numberOfPoints = this.points.size();
339 // Elevation of left and right bank
340 float leftBankElevation = this.points.get(0).getY();
341 float rightBankElevation = this.points.get(numberOfPoints - 1).getY();
342
343 // Get the lower of the 2 banks
344 if (leftBankElevation > rightBankElevation) {
345 this.maxWaterElevation = rightBankElevation;
346 } else {
347 this.maxWaterElevation = leftBankElevation;
348 }
349
350 try {
351 if (this.waterElevation > this.maxWaterElevation) {
352 throw new InvalidValueException("Water elevation is above the lowest bank.
Overflow!");
353 }
354
355 if (this.waterElevation < calculateLowestPoint()) {
356 throw new DimensionException("Water surface was set below the lowest
ground.");
357 }
358
359 if (this.points.size() < 3) {
360 throw new DimensionException("Invalid number of points. Minimum is three (3)
points.");
361 }
362
363 if (this.manningRoughness <= 0) {
364 throw new InvalidValueException("Manning's roughness must be greater than
zero.");
365 }
366
367 if (this.unknown != Unknown.DISCHARGE) {
368 if (this.discharge <= 0) {
369 throw new InvalidValueException("Discharge must be greater than zero.");
370 }
371 }
372
373 if (this.unknown != Unknown.BED_SLOPE) {
374 if (this.bedSlope <= 0) {
375 throw new InvalidValueException("Bed slope must not be flat or less than
zero.");
376 }
377 }
378
379 } catch (Exception e) {
380 this.isCalculationSuccessful = false;
381 this.errMessage = e.getMessage();
382 return false;
383 }
384 return true;
385 }
386
387 /**
388 * Solve for critical flow properties (e.g. critical depth, froude number, flow
type ...)
389 */
390 private void solveForCriticalFlow() {
391 double Q2g = Math.pow(this.discharge, 2) / this.GRAVITY_METRIC;
392
393 double tester = 0;
394
395 // Critical depth elevation
396 // Initially at the lowest elevation
397 double yc = this.calculateLowestPoint();
398
399 // Critical area, perimeter, hydraulic radius, critical slope
400 double Ac = 0, Pc, Rc, Sc;
401
402 // Top width
403 double T = 0;
404
405 // Remove points above the waterline intersection at the banks
406 List<Point> newPoints = new ArrayList<>();
407
408 while (tester < Q2g) {
409 yc += this.DEPTH_TRIAL_INCREMENT;
410
411 // Get the new points
412 // Number of waterline intersections
413 int leftIntersections = 0, rightIntersections = 0;
414
415 float x1, x2, x3, y1, y2;
416
417 for (int i = 0; i < this.points.size(); i++) {
418 // float x = this.points.get(i).getX();
419 float y = this.points.get(i).getY();
420
421 // Look for the intersection at the left side of the channel
422 if (leftIntersections == 0) {
423 if (y <= yc && i > 0) {
424 leftIntersections++;
425 // Solve for the intersection point using interpolation
426 x1 = this.points.get(i - 1).getX();
427 y1 = this.points.get(i - 1).getY();
428 x2 = this.points.get(i).getX();
429 y2 = this.points.get(i).getY();
430 x3 = (float) ((yc - y1) * (x2 - x1) / (y2 - y1) + x1);
431 newPoints.add(new Point(x3, (float) yc));
432 }
433 }
434
435 // Look for the intersection at the right side of the channel
436 if (rightIntersections == 0) {
437 if (y >= yc && i > 0) {
438 rightIntersections++;
439 x1 = this.points.get(i - 1).getX();
440 y1 = this.points.get(i - 1).getY();
441 x2 = this.points.get(i).getX();
442 y2 = this.points.get(i).getY();
443 x3 = (float) ((yc - y1) * (x2 - x1) / (y2 - y1) + x1);
444 newPoints.add(new Point(x3, (float) yc));
445 }
446 }
447
448 if (leftIntersections == 1) {
449 if (rightIntersections == 0) {
450 newPoints.add(this.points.get(i));
451 }
452 }
453 }
454
455 tester = Math.pow(Ac, 3) / T;
456 }
457
458 this.criticalWaterElevation = yc;
459 // Calculate the area covered
460 Ac = polygonArea(newPoints);
461 Pc = polygonPerimeter(newPoints);
462 Rc = Ac / Pc;
463 Sc = Math.pow(this.discharge / (Ac * Math.pow(Rc, (2.0/3.0))) *
this.manningRoughness, 2);
464 this.criticalSlope = Sc;
465 T = distanceBetweenTwoPoints(newPoints.get(0), newPoints.get(newPoints.size() -
1));
466 this.hydraulicDepth = this.wettedArea / T;
467 this.froudeNumber = this.averageVelocity / Math.sqrt(this.GRAVITY_METRIC *
this.hydraulicDepth);
468
469 // Select the flow type
470 this.flowType();
471 }
472 }
473

You might also like