## Wave transmission through a Breakwater # Author: AJMR # December 14, 2021 # %% Setup Project from mikeio import Dfs0, Dfs1 from mikeio.eum import ItemInfo, EUMUnit, EUMType import pandas as pd import pathlib as pl import numpy as np import geopandas as gp import math import matplotlib.pyplot as plt import contextily as ctx # %% Read Model Log pth = pl.Path("//srv-mad3.baird.com/", "Projects", "13632.101 South Shore Breakwater", "06_Models", "13632.101.W.AJMR.Rev0_ModelLog.xlsx") runLog = pd.read_excel(pth.as_posix(), "ModelLog") # %% Read in Point Sh breakwaterPTS = gp.read_file("//srv-mad3.baird.com/Projects/" "13632.101 South Shore Breakwater/08_CADD/Outgoing/" "20211211_Toe Extents (to Alexander)/" "20211211_Toe_Extents_NAD83_WISStatePlaneSZn_USFt_Lines_OffshoreClipSimple_10m_vertexUTM.shp") # %% Read in Breakwater crest breakCrest = pd.read_csv( '//srv-mad3.baird.com/Projects/13632.101 South Shore Breakwater/08_CADD/Outgoing/20211214_Crest Points (to Alexander)/20211214_Crest_Points_m.csv', header=None, names=['x', 'y', 'z']) breakCrest_gdf = gp.GeoDataFrame(breakCrest, crs='EPSG:32154', geometry=gp.points_from_xy(breakCrest.x, breakCrest.y)) breakCrest_gdf.to_crs('EPSG:32616', inplace=True) breakwaterPTS_Crest = breakwaterPTS.sjoin_nearest(breakCrest_gdf) breakwaterPTS_Crest.rename(columns={'x': 'breakCrest_x', 'y': 'breakCrest_y', 'z': 'Crest'}, inplace=True) # Add in Default width and slope breakwaterPTS_Crest['Width'] = 5.0 breakwaterPTS_Crest['Slope'] = 2.6 # %% Modify Breakwater Crest to new elevation # From email # X, Y, Crest, Slope, Cotangent breakSegments = np.zeros((4, 5)) breakSegments[0, :] = [2534702.7417, 372246.1099, 0, 0, 0] # 6+85 breakSegments[1, :] = [2535059.6902, 371628.1622, 180.5, 5.5, 2.6] # 14+00 breakSegments[2, :] = [2535910.4820, 370655.9834, 181.1, 6.7, 2.6] # 27+00 breakSegments[3, :] = [2536821.5682, 369722.4850, 180.5, 5.5, 2.6] # 40+05 breakSegments_gdf = gp.GeoDataFrame(breakSegments, geometry=gp.points_from_xy(breakSegments[:, 0], breakSegments[:, 1]), crs='EPSG:8796') breakSegments_gdf.to_crs('EPSG:32616', inplace=True) for idx in range(0, breakwaterPTS_Crest.shape[0]): # Check where point is (based on x coordinate) and assign new crest elevation if breakSegments_gdf.geometry.x[0] <= breakwaterPTS_Crest.geometry.x[idx] <= breakSegments_gdf.geometry.x[1]: breakwaterPTS_Crest.loc[idx, 'Crest'] = breakSegments[1, 2] breakwaterPTS_Crest.loc[idx, 'Width'] = breakSegments[1, 3] breakwaterPTS_Crest.loc[idx, 'Slope'] = breakSegments[1, 4] elif breakSegments_gdf.geometry.x[1] <= breakwaterPTS_Crest.geometry.x[idx] <= breakSegments_gdf.geometry.x[2]: breakwaterPTS_Crest.loc[idx, 'Crest'] = breakSegments[2, 2] breakwaterPTS_Crest.loc[idx, 'Width'] = breakSegments[2, 3] breakwaterPTS_Crest.loc[idx, 'Slope'] = breakSegments[2, 4] elif breakSegments_gdf.geometry.x[2] <= breakwaterPTS_Crest.geometry.x[idx] <= breakSegments_gdf.geometry.x[3]: breakwaterPTS_Crest.loc[idx, 'Crest'] = breakSegments[3, 2] breakwaterPTS_Crest.loc[idx, 'Width'] = breakSegments[3, 3] breakwaterPTS_Crest.loc[idx, 'Slope'] = breakSegments[3, 4] # %% Read Model Results modelPlot = range(33, 40) for m in modelPlot: dfsIN = Dfs0(pl.Path(runLog['Run Location'][m], str(runLog['Number'][m]) + '_' + runLog['Run Name'][m] + '.sw - Result Files', 'BreakPts.dfs0').as_posix()) dfsIN_read = dfsIN.read() MIKEds = dfsIN_read.to_dataframe() # %% Merge with dataframe breakwaterPTS_times = None for t in range(0, MIKEds.shape[0]): breakwaterPTS_merge = None breakwaterPTS_merge = breakwaterPTS_Crest for i in range(0, MIKEds.shape[1]): paramName = MIKEds.columns.values[i][MIKEds.columns.values[i].find('"', 5, -1) + 3:] if paramName not in breakwaterPTS_merge.columns: breakwaterPTS_merge[paramName] = np.full([breakwaterPTS_merge.shape[0], 1], np.nan) # MIKEds_dict[paramName] = [] # MIKEid_dict[paramName] = [] tmpFID = int(MIKEds.columns.values[i][1:MIKEds.columns.values[i].find('"', 1)]) tmpIND = int(MIKEds.columns.values[i][5:MIKEds.columns.values[i].find('"', 5)]) breakwaterPTS_merge.loc[((breakwaterPTS_merge.FID == tmpFID) & (breakwaterPTS_merge.vertex_ind == tmpIND)), paramName] = MIKEds.iloc[t, i] breakwaterPTS_merge['Time'] = MIKEds.index[t] breakwaterPTS_times = pd.concat([breakwaterPTS_times, breakwaterPTS_merge], ignore_index=True) breakwaterPTS_times.rename(columns={'index_right': 'index_right_old'}, inplace=True) # %% Conversion breakwaterPTS_times['transmitted'] = np.full([breakwaterPTS_times.shape[0], 1], np.nan) # Identify different overtopping regimes breakMask_A = breakwaterPTS_times['Sign. Wave Height'] < 0 breakMask_B = (breakwaterPTS_times['Width'] / breakwaterPTS_times['Sign. Wave Height']) <=8 breakMask_C = (breakwaterPTS_times['Width'] / breakwaterPTS_times['Sign. Wave Height']) >=12 breakMask_Da = (breakwaterPTS_times['Width'] / breakwaterPTS_times['Sign. Wave Height']) >8 breakMask_Db = (breakwaterPTS_times['Width'] / breakwaterPTS_times['Sign. Wave Height']) <12 breakMask_D = breakMask_Da & breakMask_Db # Updated approach breakwaterPTS_times.loc[breakMask_A, 'transmitted'] = 0 breakwaterPTS_times.loc[breakMask_B, 'transmitted'] = breakwaterPTS_times.loc[breakMask_B, 'Sign. Wave Height']*\ np.maximum(0, np.minimum(0.8, (-0.4 * (breakwaterPTS_times.loc[breakMask_B, 'Crest'] - breakwaterPTS_times.loc[breakMask_B, 'Surface elevation']) / breakwaterPTS_times.loc[breakMask_B, 'Sign. Wave Height'] + 0.64 * (breakwaterPTS_times.loc[breakMask_B, 'Width'] / breakwaterPTS_times.loc[breakMask_B, 'Sign. Wave Height']) ** (-0.31) * (1 - np.exp(-0.5 * (1 / breakwaterPTS_times.loc[breakMask_B, 'Slope'] / np.sqrt(2 * math.pi * breakwaterPTS_times.loc[breakMask_B, 'Sign. Wave Height'] / 9.81 / breakwaterPTS_times.loc[breakMask_B, 'Peak Wave Period'] ** 2))))))) breakwaterPTS_times.loc[breakMask_C, 'transmitted'] = breakwaterPTS_times.loc[breakMask_C, 'Sign. Wave Height'] * \ np.maximum(0.05, np.minimum(np.maximum(0, -0.006 * breakwaterPTS_times.loc[breakMask_C, 'Width'] / breakwaterPTS_times.loc[breakMask_C, 'Sign. Wave Height'] + 0.93), (-0.35 * (breakwaterPTS_times.loc[breakMask_C, 'Crest'] - breakwaterPTS_times.loc[breakMask_C, 'Surface elevation']) / breakwaterPTS_times.loc[breakMask_C, 'Sign. Wave Height'] + 0.51 * (breakwaterPTS_times.loc[breakMask_C, 'Width'] / breakwaterPTS_times.loc[breakMask_C, 'Sign. Wave Height']) ** (-0.65) * (1 - np.exp(-0.41 * (1 / breakwaterPTS_times.loc[breakMask_C, 'Slope'] / np.sqrt(2 * math.pi * breakwaterPTS_times.loc[breakMask_C, 'Sign. Wave Height'] / 9.81 / breakwaterPTS_times.loc[breakMask_C, 'Peak Wave Period'] ** 2))))))) breakwaterPTS_times.loc[breakMask_D, 'transmitted'] = breakwaterPTS_times.loc[breakMask_D, 'Sign. Wave Height'] * \ ((np.maximum(0.05, np.minimum(np.maximum(0, -0.006 * breakwaterPTS_times.loc[breakMask_D, 'Width'] / breakwaterPTS_times.loc[breakMask_D, 'Sign. Wave Height'] + 0.93), (-0.35 * (breakwaterPTS_times.loc[breakMask_D, 'Crest'] - breakwaterPTS_times.loc[breakMask_D, 'Surface elevation']) / breakwaterPTS_times.loc[breakMask_D, 'Sign. Wave Height'] + 0.51 * (breakwaterPTS_times.loc[breakMask_D, 'Width'] / breakwaterPTS_times.loc[breakMask_D, 'Sign. Wave Height']) ** (-0.65) * (1 - np.exp(-0.41 * (1 / breakwaterPTS_times.loc[breakMask_D, 'Slope'] / np.sqrt(2 * math.pi * breakwaterPTS_times.loc[breakMask_D, 'Sign. Wave Height'] / 9.81 / breakwaterPTS_times.loc[breakMask_D, 'Peak Wave Period'] ** 2))))))) - np.maximum(0, np.minimum(0.8, (-0.4 * (breakwaterPTS_times.loc[breakMask_D, 'Crest'] - breakwaterPTS_times.loc[breakMask_D, 'Surface elevation']) / breakwaterPTS_times.loc[breakMask_D, 'Sign. Wave Height'] + 0.64 * (breakwaterPTS_times.loc[breakMask_D, 'Width'] / breakwaterPTS_times.loc[breakMask_D, 'Sign. Wave Height']) ** (-0.31) * (1 - np.exp(-0.5 * (1 / breakwaterPTS_times.loc[breakMask_D,'Slope'] / np.sqrt(2 * math.pi * breakwaterPTS_times.loc[breakMask_D, 'Sign. Wave Height'] / 9.81 / breakwaterPTS_times.loc[breakMask_D,'Peak Wave Period'] ** 2)))))))) * (breakwaterPTS_times.loc[breakMask_D,'Width'] / breakwaterPTS_times.loc[breakMask_D, 'Sign. Wave Height'] - 8) / (12 - 8) +\ np.maximum(0, np.minimum(0.8, (-0.4 * (breakwaterPTS_times.loc[breakMask_D, 'Crest'] - breakwaterPTS_times.loc[breakMask_D, 'Surface elevation']) / breakwaterPTS_times.loc[breakMask_D, 'Sign. Wave Height'] + 0.64 * (breakwaterPTS_times.loc[breakMask_D, 'Width'] / breakwaterPTS_times.loc[breakMask_D, 'Sign. Wave Height']) ** (-0.31) * (1 - np.exp(-0.5 * (1 / breakwaterPTS_times.loc[breakMask_D, 'Slope'] / np.sqrt(2 * math.pi * breakwaterPTS_times.loc[breakMask_D, 'Sign. Wave Height'] / 9.81 / breakwaterPTS_times.loc[breakMask_D, 'Peak Wave Period'] ** 2)))))))) # %% Merge with breakwater transformed waves breakwaterPTS_end = breakwaterPTS_times['Time'] == breakwaterPTS_times['Time'].max() # %% Read Inner Boundary Points North innerBoundNorth = pd.read_csv( '//srv-mad3.baird.com/Projects/13632.101 South Shore Breakwater/06_Models/02_Mike21SW/InnerBound_Mesh2_North.txt', delimiter='\s+', header=None, names=['node', 'val', 'x', 'y']) innerBoundNorth.sort_values(by=['x'], inplace=True) innerBoundNorth_gdf = gp.GeoDataFrame(innerBoundNorth, crs='EPSG:32616', geometry=gp.points_from_xy(innerBoundNorth.x, innerBoundNorth.y)) innerBoundNorth_gdf = innerBoundNorth_gdf.sjoin_nearest(breakwaterPTS_times.loc[breakwaterPTS_end, :]) # %% Read Inner Boundary Points Mid # innerBoundMid = pd.read_csv( # '//srv-mad3.baird.com/Projects/13632.101 South Shore Breakwater/06_Models/02_Mike21SW/InnerBound_Mid.txt', # delimiter='\s+', header=None, names=['x', 'y']) innerBoundMid = pd.read_csv( '//srv-mad3.baird.com/Projects/13632.101 South Shore Breakwater/06_Models/02_Mike21SW/InnerBound_Mesh2_Mid.txt', delimiter='\s+', header=None, names=['node', 'val', 'x', 'y']) innerBoundMid.sort_values(by=['x'], inplace=True) innerBoundMid_gdf = gp.GeoDataFrame(innerBoundMid, crs='EPSG:32616', geometry=gp.points_from_xy(innerBoundMid.x, innerBoundMid.y)) innerBoundMid_gdf = innerBoundMid_gdf.sjoin_nearest(breakwaterPTS_times.loc[breakwaterPTS_end, :]) # %% Read Inner Boundary Points South innerBoundSouth = pd.read_csv( '//srv-mad3.baird.com/Projects/13632.101 South Shore Breakwater/06_Models/02_Mike21SW/InnerBound_South.txt', delimiter='\s+', header=None, names=['x', 'y']) innerBoundSouth.sort_values(by=['x'], inplace=True) innerBoundSouth_gdf = gp.GeoDataFrame(innerBoundSouth, crs='EPSG:32616', geometry=gp.points_from_xy(innerBoundSouth.x, innerBoundSouth.y)) innerBoundSouth_gdf = innerBoundSouth_gdf.sjoin_nearest(breakwaterPTS_times.loc[breakwaterPTS_end, :]) # %% Save as DFS1 boundDataNorth = pd.DataFrame( innerBoundNorth_gdf.loc[:, ['Time', 'transmitted', 'Peak Wave Period', 'Mean Wave Direction']]) boundDataNorth.set_index('Time', inplace=True) boundDataNorth.rename(columns={'transmitted': 'Significant wave height', 'Peak Wave Period': 'Peak wave period', 'Mean Wave Direction': 'Mean wave direction'}, inplace=True) dfsfilename = '//oak-spillway.baird.com/F/13632.101 South Shore Breakwater/SetupFiles/InnerBounds/' + \ runLog['Run Name'][m] + 'TestInnerNorth_RevB.dfs1' items = [ItemInfo("Significant wave height", EUMType.Significant_wave_height, EUMUnit.meter), ItemInfo("Peak wave period", EUMType.Wave_period, EUMUnit.second), ItemInfo("Mean wave direction", EUMType.Mean_Wave_Direction, EUMUnit.degree), ItemInfo("Directional Standard Deviation, n", EUMType.Directional_Standard_Deviation, EUMUnit.degree)] dfs = Dfs1() dfs.write(filename=dfsfilename, data=[np.array((boundDataNorth['Significant wave height'], boundDataNorth['Significant wave height'])), np.array((boundDataNorth['Peak wave period'], boundDataNorth['Peak wave period'])), np.array((boundDataNorth['Mean wave direction'], boundDataNorth['Mean wave direction'])), np.ones((2, boundDataNorth.shape[0])) * 23.28], start_time=breakwaterPTS_times['Time'].min(), dt=86400, datetimes=None, items=items, title=None) # %% Save as DFS1- Mid boundDataMid = pd.DataFrame( innerBoundMid_gdf.loc[:, ['Time', 'transmitted', 'Peak Wave Period', 'Mean Wave Direction']]) boundDataMid.set_index('Time', inplace=True) boundDataMid.rename(columns={'transmitted': 'Significant wave height', 'Peak Wave Period': 'Peak wave period', 'Mean Wave Direction': 'Mean wave direction'}, inplace=True) dfsfilename = '//oak-spillway.baird.com/F/13632.101 South Shore Breakwater/SetupFiles/InnerBounds/' + \ runLog['Run Name'][m] + 'TestInnerMid_RevB.dfs1' items = [ItemInfo("Significant wave height", EUMType.Significant_wave_height, EUMUnit.meter), ItemInfo("Peak wave period", EUMType.Wave_period, EUMUnit.second), ItemInfo("Mean wave direction", EUMType.Mean_Wave_Direction, EUMUnit.degree), ItemInfo("Directional Standard Deviation, n", EUMType.Directional_Standard_Deviation, EUMUnit.degree)] dfs = Dfs1() dfs.write(filename=dfsfilename, data=[np.array((boundDataMid['Significant wave height'], boundDataMid['Significant wave height'])), np.array((boundDataMid['Peak wave period'], boundDataMid['Peak wave period'])), np.array((boundDataMid['Mean wave direction'], boundDataMid['Mean wave direction'])), np.ones((2, boundDataMid.shape[0])) * 23.28], start_time=breakwaterPTS_times['Time'].min(), dt=86400, items=items) # %% Save as DFS1- South boundDataSouth = pd.DataFrame( innerBoundSouth_gdf.loc[:, ['Time', 'transmitted', 'Peak Wave Period', 'Mean Wave Direction']]) boundDataSouth.set_index('Time', inplace=True) boundDataSouth.rename(columns={'transmitted': 'Significant wave height', 'Peak Wave Period': 'Peak wave period', 'Mean Wave Direction': 'Mean wave direction'}, inplace=True) dfsfilename = '//oak-spillway.baird.com/F/13632.101 South Shore Breakwater/SetupFiles/InnerBounds/' + \ runLog['Run Name'][m] + 'ProdInnerSouth.dfs1' items = [ItemInfo("Significant wave height", EUMType.Significant_wave_height, EUMUnit.meter), ItemInfo("Peak wave period", EUMType.Wave_period, EUMUnit.second), ItemInfo("Mean wave direction", EUMType.Mean_Wave_Direction, EUMUnit.degree), ItemInfo("Directional Standard Deviation, n", EUMType.Directional_Standard_Deviation, EUMUnit.degree)] dfs = Dfs1() dfs.write(filename=dfsfilename, data=[np.array((boundDataSouth['Significant wave height'], boundDataSouth['Significant wave height'])), np.array((boundDataSouth['Peak wave period'], boundDataSouth['Peak wave period'])), np.array((boundDataSouth['Mean wave direction'], boundDataSouth['Mean wave direction'])), np.ones((2, boundDataSouth.shape[0])) * 23.28], start_time=breakwaterPTS_times['Time'].min(), dt=86400, items=items) # %% Test Plot mapbox = 'https://api.mapbox.com/styles/v1/alexander0042/ckemxgtk51fgp19nybfmdcb1e/tiles/256/{z}/{x}/{y}@2x?access_token=pk.eyJ1IjoiYWxleGFuZGVyMDA0MiIsImEiOiJjazVmdG4zbncwMHY4M2VrcThwZGUzZDFhIn0.w6oDHoo1eCeRlSBpwzwVtw' fig, axes = plt.subplots(nrows=1, ncols=1, figsize=(9, 9), constrained_layout=True) breakwaterPTS_merge.plot(ax=axes, column='Sign. Wave Height', cmap='viridis') # breakwaterPTS_merge.plot(ax=axes, column='Crest', cmap='viridis', legend=True) innerBound_gdf.plot(ax=axes, column='transmitted', cmap='viridis') ctx.add_basemap(axes, source=mapbox, crs='EPSG:32616') plt.show()