aboutsummaryrefslogtreecommitdiff
path: root/makeBoundary.py
diff options
context:
space:
mode:
Diffstat (limited to 'makeBoundary.py')
-rwxr-xr-xmakeBoundary.py331
1 files changed, 0 insertions, 331 deletions
diff --git a/makeBoundary.py b/makeBoundary.py
deleted file mode 100755
index 3d0d8c2..0000000
--- a/makeBoundary.py
+++ /dev/null
@@ -1,331 +0,0 @@
-#!/usr/bin/env python3
-
-import matplotlib.pyplot as plt
-import numpy as np
-import bisect
-import ast
-import math
-import argparse
-
-#TODO: use YAML/ruamel.yaml for configuration file.
-def read_definition(filename):
- ddict = {}
- with open(filename, "r") as f:
- for line in f:
- items = line.split(': ', 1)
- if len(items) == 2:
- ddict[items[0]] = ast.literal_eval(items[1])
- return ddict
-
-def conveyance(numH, n_co, xregion, zregion, zmin, zmax):
- p_i = [] # wetted perimeter
- A_i = [] # area
- r_h = [] # hydraulic radius
- h_i = [] # list of heights
- K_i = [] # conveyance
- Q_i = [] # discharge
- x_sub = [[] for i in range(numH)] # list of x values in subregion
- z_sub = [[] for i in range(numH)] # list of z values in subregion
- for i in range(numH):
- h_i.append(zmin + (i+1)*(zmax-zmin)/numH)
- #print(zregion[zregion < h_i[i]])
- booleanArray = zregion < h_i[i]
- #print(booleanArray[i])
- x_sub[i] += list(xregion[booleanArray])
- z_sub[i] += list(zregion[booleanArray])
- for interval in range(len(xregion)-1):
- if booleanArray[interval+1] != booleanArray[interval]:
- x_extra = xregion[interval] \
- + (h_i[i] - zregion[interval])\
- *(xregion[interval+1] - xregion[interval])\
- /(zregion[interval+1] - zregion[interval])
- bisect.insort(x_sub[i], x_extra) # add intercept value
- ind_x = x_sub[i].index(x_extra)
- z_sub[i].insert(ind_x, h_i[i]) # add height value
- #print(z_sub[i])
-
- dp = 0
- dA = 0
- eps = 1e-06
- for j in range(len(x_sub[i])-1):
- if (abs(z_sub[i][j+1] - h_i[i]) > eps
- or abs(z_sub[i][j] - h_i[i]) > eps):
- dp += np.hypot(x_sub[i][j+1] - x_sub[i][j],
- abs(z_sub[i][j+1] - z_sub[i][j]))
- #print(dp)
- # calculate area using trapezium rule
- dA += (h_i[i]
- - (z_sub[i][j+1] + z_sub[i][j])/2)\
- *(x_sub[i][j+1] - x_sub[i][j])
- #print('Area =', dA)
-
- p_i.append(dp)
- A_i.append(dA)
-
- r_h.append(A_i[i]/p_i[i]) # ratio of area and wetted perimeter
- #print('hydraulic radius =', r_h[i])
- K_i.append(A_i[i]*(1/n_co)*r_h[i]**(2/3)) # conveyance
- Q_i.append(K_i[i]*slope**0.5) # discharge
-
- return p_i, A_i, r_h, h_i, K_i, Q_i
-
-def plot_region(xdata, labelx,
- ydata1, labely1,
- ydata2, labely2,
- ydata3, labely3, titlep):
- plt.xlabel(labelx)
- plt.ylabel(labely1)
- plt.title(titlep)
- plt.plot(xdata, ydata1)
- plt.show()
-
- plt.xlabel(labelx)
- plt.ylabel(labely2)
- plt.title(titlep)
- plt.plot(xdata, ydata2)
- plt.show()
-
- plt.xlabel(labelx)
- plt.ylabel(labely3)
- plt.title(titlep)
- plt.plot(xdata, ydata3)
- plt.show()
-
-def save_bc():
- with open(outputFilename, 'w') as f:
- f.write('{:6} {:>2} {:>2} {:>10}\n'.format('#x', 'c', 'q', 'h'))
- for ind_z, (xitem, zitem) in enumerate(zip(xin, zin)):
- panel_x = bisect.bisect(markers, xitem)
- if csa[ind_z] == 0:
- # wall boundary condition
- f.write('{:6.2f} {:>2}\n'.format(xitem, 2))
- elif panel_x == panel[ind_p]:
- # imposed discharge within part-filled panel
- f.write('{:6.2f} {:>2} {:10.6f} {:9.6f}\n'.format(
- xitem, 5,
- -csa[ind_z]*panel_target_flow/csa_p[panel_x],
- h_extra-zitem))
- else:
- # imposed discharge within filled panels
- f.write('{:6.2f} {:>2} {:10.6f} {:9.6f}\n'.format(
- xitem, 5,
- -csa[ind_z]*Q_i[panel_x][-1]/csa_p[panel_x],
- zmax-zitem))
-
-# read command line argument:
-parser = argparse.ArgumentParser(
- description="generate FullSWOF boundary files")
-parser.add_argument("location", help="boundary location")
-args = parser.parse_args()
-
-# read boundary definition file:
-definition_dict = read_definition('boundaryDefinition.txt')
-#for dd in definition_dict:
-# print(definition_dict[dd])
-slope = abs(definition_dict["slope"]) # slope at top boundary
-target_flow = definition_dict["target_flow"] # imposed discharge
-plotting = definition_dict["plotting"] # enable or disable plotting
-n_co = definition_dict["n_co"] # Manning's 'n' coefficients
-# TODO: use weighted mean 'n' values. See
-# http://help.floodmodeller.com/isis/ISIS/River_Section.htm (Eq. 4)
-# Note: weighted mean calculation requires roughness map.
-height_data = definition_dict["height_data"] # topography
-markers = definition_dict["markers"] # distances from corner point
-panel = definition_dict["panel"] # panel fill order
-ztol = definition_dict["ztol"] # tolerance in overtopping height
-numH = definition_dict["numH"] # number of height intervals
-
-
-# print(len(markers))
-
-# with open('./1D_top.txt', "r") as data:
-# xch, ych, zch = np.loadtxt(data, delimiter=' ', unpack=True)
-
-# Fit with polyfit
-# m, c = np.polyfit(ych, zch, 1)
-# print('gradient =', m, 'intercept =', c)
-
-with open(height_data, "r") as topo:
- xtp, ytp, ztp = np.loadtxt(topo, delimiter=' ', unpack=True)
-
-
-xmax = (xtp[0]+xtp[-1]) # domain extent in x-direction
-ymax = (ytp[0]+ytp[-1]) # domain extent in y-direction
-ncols = int(math.sqrt(len(xtp)*xmax/ymax)) # number of cells in x-direction
-nrows = int(len(xtp)/ncols) # number of cells in y-direction
-dX = xmax/ncols # cell size
-print('dX =', dX)
-
-#print(ncols, nrows)
-
-# extract slices from height data array. Note: xyz format uses ncols
-# blocks, with nrows lines per block.
-if args.location == 'top':
- xin = xtp[nrows-1:len(xtp):nrows]
- yin = ytp[nrows-1:len(xtp):nrows]
- zin = ztp[nrows-1:len(xtp):nrows]
- outputFilename = "BCTop.txt"
-elif args.location == 'bottom':
- xin = xtp[0:len(xtp):nrows]
- yin = ytp[0:len(xtp):nrows]
- zin = ztp[0:len(xtp):nrows]
- outputFilename = "BCBottom.txt"
-elif args.location == 'left':
- xin = xtp[:nrows]
- yin = ytp[:nrows]
- zin = ztp[:nrows]
- outputFilename = "BCLeft.txt"
-elif args.location == 'right':
- xin = xtp[nrows*(ncols-1):]
- yin = ytp[nrows*(ncols-1):]
- zin = ztp[nrows*(ncols-1):]
- outputFilename = "BCRight.txt"
-
-
-# print(xin)
-
-num_panels = len(panel) # number of panels across boundary
-
-# convert marker co-ordinates to array indices:
-marker_ind = [0]
-for i in range(len(markers)):
- marker_ind.append(int(markers[i]/dX))
-if args.location == 'left' or args.location == 'right':
- marker_ind.append(nrows)
-elif args.location == 'top' or args.location == 'bottom':
- marker_ind.append(ncols)
-
-
-# print(marker_ind)
-
-xregion = []
-zregion = []
-zmin = []
-for p in range(num_panels):
- # identify regions:
- xregion.append(xin[marker_ind[p]:marker_ind[p+1]])
- zregion.append(zin[marker_ind[p]:marker_ind[p+1]])
- # identify minimum heights within each panel:
- zmin.append(zregion[p].min())
-
-# xregion_west = xin[100:281]
-# zregion_west = zin[100:281]
-
-# xregion_east = xin[300:408]
-# zregion_east = zin[300:408]
-
-# print(zregion)
-# print(xin[12:20])
-
-print('zmin[3] =', zmin[3])
-
-# channel overtopping height (minimum of left bank and right bank heights):
-zmax = min(zregion[panel[0]][0], zregion[panel[0]][-1]) - ztol
-
-print('zmax =', zmax)
-
-#print(h_i)
-
-
-
-p_i = [[] for _ in range(num_panels)]
-A_i = [[] for _ in range(num_panels)]
-r_h = [[] for _ in range(num_panels)]
-h_i = [[] for _ in range(num_panels)]
-K_i = [[] for _ in range(num_panels)]
-Q_i = [[] for _ in range(num_panels)]
-for p in range(num_panels):
- if p == panel[0]-1 and zregion[p][-1] < zmax:
- # ensure end node in region to the left of channel is dry:
- xregion[p] = np.append(xregion[p], xin[marker_ind[p]])
- zregion[p] = np.append(zregion[p], zin[marker_ind[p]])
- if p == panel[0]+1 and zregion[p][0] < zmax:
- # ensure start node in region to the right of channel is dry:
- xregion[p] = np.insert(xregion[p], 0, xin[marker_ind[p]-1])
- zregion[p] = np.insert(zregion[p], 0, zin[marker_ind[p]-1])
- if zmax > zmin[p]:
- p_i[p], A_i[p], r_h[p], h_i[p], K_i[p], Q_i[p] = conveyance(
- numH,
- n_co[p],
- xregion[p],
- zregion[p],
- zmin[p],
- zmax)
- if plotting:
- plot_region(
- h_i[p]-zmin[p], 'maximum depth / m',
- r_h[p], 'hydraulic radius / m',
- K_i[p], r'conveyance / $m^3/s$',
- Q_i[p], r'discharge / $m^3/s$',
- 'Panel {}'.format(p))
- else:
- p_i[p], A_i[p], r_h[p], h_i[p], K_i[p], Q_i[p] = [
- [0] * numH for _ in range(6)]
-
-# sort list of discharge lists according to panel fill order:
-sortedQ = [Q_i[i] for i in panel]
-# create cumulative discharge list:
-total_flow = np.cumsum([item[-1] for item in sortedQ])
-print('total_flow = ', total_flow)
-# target_flow_west = target_flow - Q_i[-1] - Q_i_east[-1]
-# calculate velocity: note dependence on hydraulic radius
-velocity_channel = Q_i[panel[0]][-1]/A_i[panel[0]][-1]
-# velocity_east = Q_i_east[-1]/A_i_east[-1]
-
-# print(target_flow_west)
-# find part-filled panel:
-ind_p = bisect.bisect(total_flow, target_flow)
-print('index of part-filled panel:', ind_p)
-
-# calculate target flow in part-filled panel:
-panel_target_flow = target_flow - total_flow[ind_p-1]
-
-# find insertion point for target flow value:
-ind_q = bisect.bisect(Q_i[panel[ind_p]], panel_target_flow)
-print('insertion point =', ind_q)
-
-# find height at target flow by linear interpolation
-h_extra = h_i[panel[ind_p]][ind_q-1] \
- + (h_i[panel[ind_p]][ind_q] - h_i[panel[ind_p]][ind_q-1])\
- *(panel_target_flow - Q_i[panel[ind_p]][ind_q-1])\
- /(Q_i[panel[ind_p]][ind_q] - Q_i[panel[ind_p]][ind_q-1])
-print('heights:', h_i[panel[ind_p]][ind_q-1], h_extra, h_i[panel[ind_p]][ind_q])
-# find area at target flow by linear interpolation
-A_extra = A_i[panel[ind_p]][ind_q-1] \
- + (h_extra-h_i[panel[ind_p]][ind_q-1])\
- *(A_i[panel[ind_p]][ind_q] - A_i[panel[ind_p]][ind_q-1])\
- /(h_i[panel[ind_p]][ind_q] - h_i[panel[ind_p]][ind_q-1])
-print('hydraulic radii:', r_h[panel[ind_p]][ind_q-1], r_h[panel[ind_p]][ind_q])
-
-velocity_panel = panel_target_flow/A_extra
-print('velocities:', velocity_channel, velocity_panel)
-
-csa = np.zeros(len(xin)) # cross-sectional area of element
-csa_p = np.zeros(num_panels) # cross-sectional area of panel
-for i, p in enumerate(panel):
- if i < ind_p:
- # panels are filled
- area_sum = 0
- for m in range(marker_ind[p], marker_ind[p+1]):
- csa[m] = max(0, (zmax - zin[m])*dX)
- area_sum += csa[m]
- csa_p[p] = area_sum
- elif i == ind_p:
- # panel is part-filled
- area_sum = 0
- for m in range(marker_ind[p], marker_ind[p+1]):
- csa[m] = max(0, (h_extra - zin[m])*dX)
- area_sum += csa[m]
- csa_p[p] = area_sum
- else:
- # panel is empty
- for m in range(marker_ind[p], marker_ind[p+1]):
- csa[m] = 0
- csa_p[p] = 0
-
-
-#print('csa_p[0] = {} csa_p[1] = {}'.format(csa_p[0], csa_p[1]))
-#print('A_i_west = {} A_i = {} A_i_east = {}'.format(A_extra, A_i[-1], A_i_east[-1]))
-
-
-save_bc()