Spaces:
Sleeping
Sleeping
| #!/usr/bin/env python | |
| # coding: utf-8 | |
| # In[5]: | |
| from scipy.optimize import fsolve | |
| import matplotlib.pyplot as plt | |
| import numpy as np | |
| from matplotlib.lines import Line2D | |
| import matplotlib.image as mpimg | |
| from matplotlib.offsetbox import AnchoredText | |
| import plotly.figure_factory as ff | |
| import pandas as pd | |
| from io import BytesIO | |
| import base64 | |
| # In[17]: | |
| def dispersion(T, h): | |
| """ Dispersion relationship | |
| uses fsolve to find the wave length | |
| Parameters | |
| ---------- | |
| T : float | |
| wave period [s] | |
| h : float | |
| water depth [m] | |
| Returns | |
| L : float | |
| the wave length [m] | |
| """ | |
| g=32 | |
| # deep water wave length | |
| L0 = g*T**2/(2*np.pi) | |
| # define dispersion relation with a lambda function to solve L | |
| dispersion = lambda L : L0 * np.tanh(2*np.pi*h/L) - L | |
| # solve for L | |
| L = fsolve(dispersion, L0)[0] | |
| print(L) | |
| return L | |
| # In[24]: | |
| def goda(Case, Hs, Hmax, h, d, h_acc, hc, T, beta, rho, slope_foreshore, B, lambda_, Still_Water_Level, Top_of_Wall_Height, Bottom_of_Wall, Pmin, s, p2_bottom): | |
| '''Parameters | |
| ---------- | |
| Hs : float | |
| mean of the highest 1/3 of the wave heights [m]. | |
| Hmax : float | |
| design wave height, equal to the mean of the highest 1/250 of | |
| the wave heights [m]. | |
| h : float | |
| water depth [m] | |
| d : float | |
| water depth in front of the caisson, on top of the foundation [m] | |
| h_acc : float | |
| submerged depth of the caisson [m] | |
| hc : float | |
| height of the caisson above the water line [m] | |
| Bm : float | |
| width of the berm [m] | |
| T : float | |
| wave period, Goda (2000) advises to use :math:`T_{1/3}` [s] | |
| beta : float | |
| angle between direction of wave approach and a line normal to | |
| the breakwater [rad] | |
| rho : float | |
| density of water [kg/m³] | |
| slope_foreshore : float | |
| slope of the foreshore [rad] | |
| lambda_ : list, optional, default: [1, 1, 1] | |
| modification factors of Takahasi (2002) for alternative | |
| monolithic breakwater. Input must be | |
| \\lambda_= [:math:`\\lambda_1, \\lambda_2, \\lambda_3`].''' | |
| # set dimensions as private variables | |
| h = h | |
| d = d | |
| h_acc = h_acc | |
| hc = hc | |
| rho = rho | |
| g=32 | |
| # water depth at a location of 5x H1/3 | |
| hb = Hs #h + 5 * np.tan(slope_foreshore) * Hs | |
| L = dispersion(T=T, h=h) | |
| # compute wave pressure coefficients (Goda, 2000) | |
| alpha_1 = (0.6 + 0.5*((4*np.pi*h/L)/ np.sinh(4*np.pi*h/L))**2) | |
| alpha_2_1 = ((hb-d)/(3*hb)*(Hmax/d)**2) | |
| alpha_2_2 = (2*d/Hmax) | |
| alpha_2 = min((alpha_2_1), (alpha_2_2)) | |
| alpha_3 = 1 - (h_acc/h) * (1-1/np.cosh(2*np.pi*h/L)) | |
| alpha_star = alpha_2 | |
| # Compute the elevation to which the wave pressure is exerted | |
| eta_star = 0.75*(1 + np.cos(beta))*lambda_[0]*Hmax | |
| # Compute the wave pressures | |
| p1 = (0.5*(1 + np.cos(beta))* (lambda_[0]*alpha_1 + lambda_[1]*alpha_star*np.cos(beta)**2)*rho*g*Hmax) | |
| p3 = alpha_3*p1 | |
| if eta_star > hc: | |
| p4 = p1*(1-hc/eta_star) | |
| else: | |
| p4 = 0 | |
| #Computes the Uplift wave forces | |
| pu = (0.5*(1 + np.cos(beta))* lambda_[2]*alpha_1*alpha_3*rho*g*Hmax) | |
| # Determine h_c_star | |
| h_c_star = min([eta_star, hc]) | |
| #Computes the Horizontal force due to the pressure | |
| P = (0.5*(p1+p3)*h_acc + 0.5*(p1+p4)*h_c_star)/1000 | |
| goda.p1 = p1 | |
| goda.p3 = p3 | |
| goda.hc = hc | |
| goda.eta_star = eta_star | |
| goda.h_acc = h_acc | |
| goda.pu = pu | |
| def distributed_load(loads, positions): | |
| # loads is a list of load values at different positions | |
| # positions is a list of positions corresponding to the load values | |
| x_centroid = 0 | |
| y_centroid = 0 | |
| total_load = 0 | |
| for i in range(len(loads)): | |
| x_centroid += loads[i] * positions[i] | |
| y_centroid += loads[i] | |
| total_load += loads[i] | |
| x_centroid /= y_centroid | |
| return (total_load, x_centroid) | |
| # Example usage | |
| loads = [goda.p1, p4, goda.p3] | |
| positions = [Still_Water_Level, Top_of_Wall_Height, Bottom_of_Wall] | |
| resultant, centroid = distributed_load(loads, positions) | |
| #Suction Loads (wave load under a wave trough) | |
| Steepness = Hs/L | |
| depth_to_wavelength = h/L | |
| print('Steepness(H/L) = ' + str(Steepness)) | |
| print('h/L = ' + str(depth_to_wavelength)) | |
| img = mpimg.imread('Goda_Suction.png') | |
| imgplot = plt.imshow(img) | |
| plt.axis('off') | |
| plt.show() | |
| Pmin = Pmin | |
| s = s | |
| p2_bottom = p2_bottom | |
| Suction_Load = Pmin*rho*g*h*Hs/1000 | |
| Load_Distance_from_Bottom = s*h | |
| Bottom_Pressure = p2_bottom*rho*g*Hs/1000 | |
| #Horizontal Loading Table Data | |
| data_matrix = [['Parameters', 'Units', 'Value'], | |
| [ 'Acceleration due to gravity', 'g[ft/s2]', g], | |
| [ 'Water Density', '[slug/ft3]', rho], | |
| ['Wave Period', 'T[s]', T], | |
| ['Significant Wave Height', 'Hs[ft]', Hs], | |
| ['Max. Wave Height', 'Hmax[ft]', round(Hmax,2)], | |
| ['Depth in front of scour protection', 'h[ft]', h], | |
| ['Water Depth 5Hs away', 'hb[ft]', h], | |
| ['Height of Seawall from bottom to SWL', 'h\'[ft]', h_acc], | |
| ['Height of Seawall above SWL', 'hc[ft]', hc], | |
| ['Depth in front of Seawall', 'd[ft]', d], | |
| ['Wavelength', 'L[ft]', round(L,2)], | |
| ['Angle of Incoming Waves', 'deg', beta], | |
| [ ], | |
| ['a1', '', round(alpha_1,2)], | |
| ['a2', '', round(alpha_star, 2)], | |
| ['a3', '', round(alpha_3,2)], | |
| ['Eta*', '[ft]', round(eta_star,2)], | |
| ['hc*', '[ft]', h_c_star], | |
| [ ], | |
| ['p1', '[ksf]', round(p1/1000,2)], | |
| ['p2', '[ksf]', round(p4/1000,2)], | |
| ['p3', '[ksf]', round(p3/1000,2)], | |
| [ ], | |
| ['Force on Breakwater', '[kip/ft]', round(P,2)]] | |
| #fig = ff.create_table(data_matrix) | |
| #fig.update_layout(width=1000) | |
| df = pd.DataFrame(data_matrix) | |
| # Generate a unique filename for each CSV file | |
| filename = f'goda_horizontal_load_{Case}.csv' | |
| # Create a buffer to hold the CSV data | |
| csv_buffer = BytesIO() | |
| df.to_csv(csv_buffer, header=None, index=None) | |
| # Reset the buffer position to the start | |
| csv_buffer.seek(0) | |
| # Create a download link for the generated CSV file | |
| b64 = base64.b64encode(csv_buffer.read()).decode() | |
| href = f'<a href="data:file/csv;base64,{b64}" download="{filename}">Download Horizontal Loading CSV</a>' | |
| st.markdown(href, unsafe_allow_html=True) | |
| #fig.write_image() | |
| # Suction Loads Data Table | |
| data_matrix = [['Parameters', 'Units', 'Value'], | |
| [ 'Acceleration due to gravity', 'g[ft/s2]', g], | |
| [ 'Water Density', '[slug/ft3]', rho], | |
| ['Wave Period', 'T[s]', T], | |
| ['Significant Wave Height', 'Hs[ft]', Hs], | |
| ['Max. Wave Height', 'Hmax[ft]', round(Hmax,2)], | |
| ['Depth in front of Seawall', 'd[ft]', d], | |
| ['Wavelength', 'L[ft]', round(L,2)], | |
| ['Seabed Bottom Elevation', '[ft]', Bottom_of_Wall], | |
| [ ], | |
| ['Wave Steepness', 'H/L', round(Steepness,2)], | |
| ['Depth to Wavelength Ratio', 'h/L', round(depth_to_wavelength, 2)], | |
| ['Nondimensional Value of Wave Thrust Load', 'Pmin/pgHh', round(Pmin,2)], | |
| ['Nondimensional Value of Wave Thrust Arm', 's/d', round(s,2)], | |
| ['Suction Load', '[kip/ft]', round(Suction_Load,2)], | |
| ['Load Distance from Seabed Bottom', 's[ft]', round(Load_Distance_from_Bottom,2)], | |
| ['Load Elevation', '[ft] MSL', round(Bottom_of_Wall + Load_Distance_from_Bottom,2)]] | |
| df = pd.DataFrame(data_matrix) | |
| # Generate a unique filename for each CSV file | |
| filename = f'goda_suction_load_{Case}.csv' | |
| # Create a buffer to hold the CSV data | |
| csv_buffer = BytesIO() | |
| df.to_csv(csv_buffer, header=None, index=None) | |
| # Reset the buffer position to the start | |
| csv_buffer.seek(0) | |
| # Create a download link for the generated CSV file | |
| b64 = base64.b64encode(csv_buffer.read()).decode() | |
| href = f'<a href="data:file/csv;base64,{b64}" download="{filename}">Download Suction Loading CSV</a>' | |
| st.markdown(href, unsafe_allow_html=True) | |
| # get the width | |
| B = B | |
| p = np.array([goda.p3, | |
| goda.p1, | |
| goda.p1-goda.p1*goda.hc/goda.eta_star])/1000 | |
| y = np.array([Bottom_of_Wall, Still_Water_Level, Top_of_Wall_Height]) | |
| x = np.array([0, B]) | |
| pu = np.array([goda.pu, 0])/1000 | |
| # scale the size of the caisson with the pressure | |
| scale = np.max(p)/np.max(y) | |
| scale_1 = np.max(y)/np.max(p) | |
| y = y | |
| x = x | |
| pu_1 = pu*scale_1*0.25 | |
| B = B*scale | |
| p_s = np.array([Bottom_Pressure, 1.5*Bottom_Pressure, 0]) | |
| y_s = np.array([Bottom_of_Wall, Bottom_of_Wall+Load_Distance_from_Bottom, Still_Water_Level]) | |
| x_s = np.array([0, B]) | |
| # scale the size of the caisson with the pressure | |
| scale_s = np.max(y_s)/np.max(p) | |
| x_s = x | |
| #y_s = y_s[0:2] | |
| custom_lines = [Line2D([0], [0], color='k', lw=4), Line2D([0], [0], color='b', lw=4), Line2D([0], [0], color='g', lw=4), | |
| Line2D([0], [0], color='r', lw=4) | |
| ] | |
| fig, ax = plt.subplots() | |
| # plot the caisson and wlev | |
| plt.vlines(x=0, ymin=((Bottom_of_Wall)), ymax=Top_of_Wall_Height, linewidth=2, color='k') | |
| plt.vlines(x=-B, ymin=((Bottom_of_Wall)), ymax=Top_of_Wall_Height, linewidth=2, color = 'k') | |
| plt.hlines(y=-(abs(Bottom_of_Wall)), xmin=0, xmax=-B, linewidth=2, color = 'k') | |
| plt.hlines(y=Top_of_Wall_Height, xmin=0, xmax=-B, linewidth=2, color='k') | |
| plt.hlines(y=(Still_Water_Level), xmin=0, xmax=np.max(p)*1.3, color='b') | |
| # plot pressure distributions | |
| plt.hlines(y=Bottom_of_Wall, xmin=0, xmax=p[0], color='g') | |
| plt.hlines(y=Top_of_Wall_Height, xmin=0, xmax=p[2], color='g') | |
| plt.plot(p, y, color='g') | |
| #plt.vlines(x=0, ymin=Bottom_of_Wall, ymax=Bottom_of_Wall - pu_1[0], color='purple') | |
| #plt.plot([0,-B], Bottom_of_Wall-pu_1, color='purple') | |
| # plot suction load distributions | |
| plt.hlines(y=Bottom_of_Wall, xmin=-p_s[0], xmax=0, color='r') | |
| #plt.hlines(y=-y_s[1], xmin=-p_s[1], xmax=0, color='r') | |
| plt.plot(-p_s, y_s, color='r') | |
| # red arrow | |
| plt.arrow(-p_s[1], Bottom_of_Wall+Load_Distance_from_Bottom , p_s[1], 0, head_width=0.15*Load_Distance_from_Bottom, head_length=0.03, linewidth=4, color='r', length_includes_head=True) | |
| # green arrow | |
| plt.arrow(resultant, centroid , -resultant, 0, head_width=0.15*Load_Distance_from_Bottom, head_length=0.03, linewidth=4, color='g', length_includes_head=True) | |
| # Dimensions Annotation Suction | |
| plt.arrow(-0.025, Bottom_of_Wall, 0, (Load_Distance_from_Bottom), color='k', head_length = 0.15*Load_Distance_from_Bottom, head_width = 0.01, length_includes_head = True) | |
| plt.arrow(-0.025, Bottom_of_Wall+Load_Distance_from_Bottom, 0, -Load_Distance_from_Bottom, color='k', head_length = 0.15*Load_Distance_from_Bottom, head_width = 0.01, length_includes_head = True) | |
| plt.annotate(str(round(Load_Distance_from_Bottom, 2)) + ' ft', xy=(0, 0), | |
| xytext=(-0.03, (Bottom_of_Wall+Load_Distance_from_Bottom)/.45), rotation=90 ) | |
| # Dimensions Annotation Horizontal | |
| plt.arrow(0.025, Bottom_of_Wall, 0, -(Bottom_of_Wall-centroid), color='k', head_length = 0.15*Load_Distance_from_Bottom, head_width = 0.01, length_includes_head = True) | |
| plt.arrow(0.025, Bottom_of_Wall+Load_Distance_from_Bottom, 0, -Load_Distance_from_Bottom, color='k', head_length = 0.15*Load_Distance_from_Bottom, head_width = 0.01, length_includes_head = True) | |
| plt.annotate(str(round(-Bottom_of_Wall+centroid, 1)) + ' ft', xy=(0, 0), | |
| xytext=(0.05, -(-Bottom_of_Wall+centroid)/1.5), rotation=90 ) | |
| #invert axes | |
| plt.xlim(np.max(p)*1.3, -np.max(p_s)) | |
| #plt.ylim(Bottom_of_Wall*1.6, np.max(y)*2) | |
| #plt.ylim(np.max(pu_1)+10, (-np.max(y)-5)) | |
| HL = 'Horizontal Load (kip/ft) = ' + str(round(P,2)) | |
| #UL = 'Uplift Load (ksf/ft) = ' + str(round(pu[0],2)) | |
| SL = 'Suction Load (kip/ft) = ' + str(round(Suction_Load, 2)) | |
| VW = 'Seawall' | |
| SW = 'Still Water Level' | |
| # add title and label | |
| plt.title('Pressure distributions computed with Goda (2000)') | |
| plt.xlabel('Pressure [ksf/ft]') | |
| plt.ylabel('Surface Elevation [ft], NGVD 29') | |
| plt.legend(custom_lines, [VW, SW, HL, SL], loc ='lower left') | |
| # add grid and show plot | |
| plt.grid() | |
| plt.savefig('Case_Number_' + str(Case) + '.png', dpi = 300) | |
| st.pyplot(fig) | |
| return goda.p1, p4, goda.p3, P, pu[0], Suction_Load, Bottom_Pressure, Load_Distance_from_Bottom | |
| # In[29]: | |
| import streamlit as st | |
| #def main(): | |
| # st.title("Goda Horizontal Loading Calculator") | |
| # # Display the image | |
| # img = mpimg.imread('Goda_Suction.png') | |
| # st.image(img, use_column_width=True) | |
| # User Inputs | |
| # Case_number = st.number_input("Case Number", value=3, min_value=1, step=1) | |
| # B = st.number_input("Width of Wall", value=2.0, min_value=0.0) | |
| # Bottom_of_Wall = st.number_input("Bottom of Wall", value=-11.92) | |
| # Still_Water_Level = st.number_input("Stillwater Level", value=0.0) | |
| # Top_of_Wall_Height = st.number_input("Top of Wall Height", value=7.27) | |
| # Hs = st.number_input("Hs", value=4.5) | |
| # T = st.number_input("T", value=7.0) | |
| # beta = st.number_input("Beta", value=0.0) | |
| # rho = st.number_input("Rho", value=2.0) | |
| # Pmin = st.number_input("Non-Dimensional Pmin (For Suction Loads - from Graphs Above)", value=0.4) | |
| # s = st.number_input("Non-Dimensional s (For Suction Loads - from Graphs Above)", value=0.5) | |
| # p2_bottom = st.number_input("Non-Dimensional p2 (For Suction Loads - from Graphs Above)", value=0.55) | |
| # Hmax = Hs*1.8 #design wave height, equal to the mean of the highest 1/250 of the wave heights [m]. | |
| # h = Still_Water_Level - Bottom_of_Wall #water depth [m] | |
| # d = h #water depth in front of the caisson, on top of the foundation [m] | |
| # h_acc = h #submerged depth of the caisson [m] | |
| # hc = Top_of_Wall_Height - Still_Water_Level #height of the caisson above the water line [m] | |
| # slope_foreshore = [1,100] #slope of the foreshore [rad] | |
| # lambda_=[1,1,1] | |
| # if st.button("Calculate"): | |
| # result = goda(Case = Case_number, Hs=Hs, Hmax=Hmax, h=h, d=d, h_acc=h_acc, hc=hc, T=T, | |
| # beta=beta, rho=rho, slope_foreshore=slope_foreshore, B = B, lambda_=lambda_, | |
| # Still_Water_Level = Still_Water_Level, Top_of_Wall_Height= Top_of_Wall_Height, | |
| # Bottom_of_Wall=Bottom_of_Wall, Pmin=Pmin, s=s, p2_bottom=p2_bottom ) | |
| def main(): | |
| st.title("Goda Horizontal Loading Calculator") | |
| # Display the image | |
| img = mpimg.imread('Goda_Suction.png') | |
| st.image(img, use_column_width=True) | |
| # User Inputs | |
| Case_number = st.number_input("Case Number", value=3, min_value=1, step=1) | |
| Hs = st.number_input("Wave Height, Hs [ft]", value=4.5) | |
| T = st.number_input("Period, T [s]", value=7.0) | |
| h = st.number_input("Depth, h [ft]", value=11.0) | |
| if st.button("Run Dispersion"): | |
| dispersion_result = dispersion(T=T, h=h) | |
| st.write("Suction Load Parameters:") | |
| st.write("Wavelength:", dispersion_result) | |
| st.write("Wave Steepness:", Hs/dispersion_result) | |
| st.write("h/L:", h/dispersion_result) | |
| B = 2.0 #st.number_input("Width of Wall [ft]", value=2.0, min_value=0.0) | |
| Bottom_of_Wall = st.number_input("Bottom of Wall [ft]", value=-11.92) | |
| Still_Water_Level = st.number_input("Stillwater Level [ft]", value=0.0) | |
| Top_of_Wall_Height = st.number_input("Top of Wall Height [ft]", value=7.27) | |
| beta = st.number_input("Beta [deg]", value=0.0) | |
| rho = 2 #st.number_input("Rho", value=2.0) | |
| Pmin = st.number_input("Non-Dimensional Pmin (For Suction Loads - from Graphs Above)", value=0.4) | |
| s = st.number_input("Non-Dimensional s (For Suction Loads - from Graphs Above)", value=0.5) | |
| p2_bottom = st.number_input("Non-Dimensional p2 (For Suction Loads - from Graphs Above)", value=0.55) | |
| Hmax = Hs*1.8 #design wave height, equal to the mean of the highest 1/250 of the wave heights [m]. | |
| h = Still_Water_Level - Bottom_of_Wall #water depth [m] | |
| d = h #water depth in front of the caisson, on top of the foundation [m] | |
| h_acc = h #submerged depth of the caisson [m] | |
| hc = Top_of_Wall_Height - Still_Water_Level #height of the caisson above the water line [m] | |
| slope_foreshore = [1,100] #slope of the foreshore [rad] | |
| lambda_=[1,1,1] | |
| if st.button("Run Goda"): | |
| goda_result = goda(Case=Case_number, Hs=Hs, Hmax=Hmax, h=h, d=d, h_acc=h_acc, hc=hc, T=T, | |
| beta=beta, rho=rho, slope_foreshore=slope_foreshore, B=B, lambda_=lambda_, | |
| Still_Water_Level=Still_Water_Level, Top_of_Wall_Height=Top_of_Wall_Height, | |
| Bottom_of_Wall=Bottom_of_Wall, Pmin=Pmin, s=s, p2_bottom=p2_bottom) | |
| #st.write("Goda Result:") | |
| #st.write("Output:", goda_result) | |
| if __name__ == "__main__": | |
| main() | |