[4777] | 1 | """Validation of the AnuGA implementation of the shallow water wave equation. |
---|
| 2 | |
---|
| 3 | This script sets up 2D circular island..... |
---|
| 4 | |
---|
[5038] | 5 | use 'res' parameter of 1 to make run fast. |
---|
| 6 | |
---|
[4777] | 7 | """ |
---|
| 8 | |
---|
| 9 | # Module imports |
---|
| 10 | from anuga.shallow_water import Domain |
---|
| 11 | from anuga.shallow_water import Reflective_boundary |
---|
| 12 | from anuga.shallow_water import Transmissive_Momentum_Set_Stage_boundary |
---|
| 13 | from anuga.shallow_water import Dirichlet_boundary, Time_boundary |
---|
[5065] | 14 | from anuga.shallow_water.data_manager import get_maximum_inundation_data, start_screen_catcher, copy_code_files |
---|
| 15 | from anuga.abstract_2d_finite_volumes.util import file_function, sww2csv_gauges,csv2timeseries_graphs |
---|
[4777] | 16 | from anuga.pmesh.mesh_interface import create_mesh_from_regions |
---|
[4987] | 17 | from anuga.utilities.polygon import read_polygon#, plot_polygons |
---|
[5123] | 18 | from math import cos,pi,sin,tan#,sqrt |
---|
| 19 | from Numeric import array, zeros, Float, allclose,resize,sqrt |
---|
[4980] | 20 | from anuga.shallow_water.data_manager import csv2dict |
---|
[5065] | 21 | from time import localtime, strftime, gmtime |
---|
| 22 | from anuga.utilities.system_tools import get_user_name, get_host_name |
---|
| 23 | from os import sep, environ, getenv |
---|
[4777] | 24 | #------------------------- |
---|
| 25 | # Create Domain from mesh |
---|
| 26 | #------------------------- |
---|
| 27 | |
---|
[5065] | 28 | user = get_user_name() |
---|
| 29 | home = getenv('INUNDATIONHOME') + sep +'data'+sep #Sandpit's parent dir |
---|
| 30 | time = strftime('%Y%m%d_%H%M%S',localtime()) |
---|
[5031] | 31 | |
---|
[5147] | 32 | res=0.05 |
---|
[5065] | 33 | |
---|
| 34 | dir_comment = time+'_res_'+str(res)+'_'+str(user) |
---|
| 35 | |
---|
| 36 | anuga_dir = home+'anuga_validation'+sep+'circular_island_tsunami_benchmark'+sep+'anuga'+sep |
---|
| 37 | output_dir = anuga_dir+'outputs'+sep+dir_comment+sep |
---|
[5123] | 38 | #output_dir = anuga_dir+'outputs'+sep+'20080222_062917_res_0.0025_nbartzis'+sep |
---|
[5065] | 39 | copy_code_files(output_dir,__file__) |
---|
| 40 | |
---|
| 41 | start_screen_catcher(output_dir) |
---|
| 42 | |
---|
[4797] | 43 | def get_xy(x=0,y=0,r=1,angle=1): |
---|
[5031] | 44 | #return x and y co-ordinates |
---|
[4797] | 45 | x1 = x + cos(angle)*r |
---|
| 46 | y1 = y + sin(-angle)*r |
---|
| 47 | # print "get",x,y,r,x1,y1,"angle",angle, cos(angle),sin(angle) |
---|
| 48 | return x1,y1, |
---|
[4777] | 49 | |
---|
| 50 | def prepare_timeboundary(filename): |
---|
| 51 | """Converting benchmark 2 time series to NetCDF tms file. |
---|
| 52 | This is a 'throw-away' code taylor made for files like |
---|
| 53 | 'Benchmark_2_input.txt' from the LWRU2 benchmark |
---|
| 54 | """ |
---|
| 55 | |
---|
| 56 | textversion = filename[:-4] + '.txt' |
---|
| 57 | |
---|
| 58 | print 'Preparing time boundary from %s' %textversion |
---|
| 59 | from Numeric import array |
---|
| 60 | |
---|
| 61 | fid = open(textversion) |
---|
| 62 | |
---|
| 63 | #Skip first line |
---|
| 64 | line = fid.readline() |
---|
| 65 | |
---|
| 66 | #Read remaining lines |
---|
| 67 | lines = fid.readlines() |
---|
| 68 | fid.close() |
---|
| 69 | |
---|
| 70 | |
---|
| 71 | N = len(lines) |
---|
| 72 | T = zeros(N, Float) #Time |
---|
| 73 | Q = zeros(N, Float) #Values |
---|
| 74 | |
---|
| 75 | for i, line in enumerate(lines): |
---|
| 76 | fields = line.split() |
---|
[4797] | 77 | # print 'fields',i,line |
---|
[4777] | 78 | |
---|
| 79 | T[i] = float(fields[0]) |
---|
| 80 | Q[i] = float(fields[1]) |
---|
| 81 | |
---|
| 82 | |
---|
| 83 | #Create tms file |
---|
| 84 | from Scientific.IO.NetCDF import NetCDFFile |
---|
| 85 | |
---|
| 86 | print 'Writing to', filename |
---|
| 87 | fid = NetCDFFile(filename[:-4] + '.tms', 'w') |
---|
| 88 | |
---|
| 89 | fid.institution = 'Geoscience Australia' |
---|
| 90 | fid.description = 'Input wave for Benchmark 2' |
---|
| 91 | fid.starttime = 0.0 |
---|
| 92 | fid.createDimension('number_of_timesteps', len(T)) |
---|
| 93 | fid.createVariable('time', Float, ('number_of_timesteps',)) |
---|
| 94 | fid.variables['time'][:] = T |
---|
| 95 | |
---|
| 96 | fid.createVariable('stage', Float, ('number_of_timesteps',)) |
---|
| 97 | fid.variables['stage'][:] = Q[:] |
---|
| 98 | |
---|
| 99 | fid.createVariable('xmomentum', Float, ('number_of_timesteps',)) |
---|
| 100 | fid.variables['xmomentum'][:] = 0.0 |
---|
| 101 | |
---|
| 102 | fid.createVariable('ymomentum', Float, ('number_of_timesteps',)) |
---|
| 103 | fid.variables['ymomentum'][:] = 0.0 |
---|
| 104 | |
---|
| 105 | fid.close() |
---|
| 106 | |
---|
| 107 | |
---|
[5065] | 108 | # angle to make circular interior polygons |
---|
[4797] | 109 | angles1 = (0.0, 22.5, 45.0, 67.5, 90.0, 112.5, 135.0, 157.5, 180.0, 202.5, 225.0, |
---|
| 110 | 247.5, 270.0, 292.5, 315.0, 337.5) |
---|
[4777] | 111 | |
---|
[5031] | 112 | center_x = 12.96 |
---|
| 113 | center_y = 13.80 |
---|
| 114 | |
---|
[5038] | 115 | #L=3.6 and therefore the gauges 1,2,3 and 4 are located 1.8 from the toe of the island |
---|
| 116 | # 13.8 - 3.6(radii of island) - 1.8 = 8.4 |
---|
| 117 | L=8.4 |
---|
[4797] | 118 | |
---|
[4979] | 119 | #create polygons (circles) to have higher resolution |
---|
[4797] | 120 | poly = [] |
---|
[4799] | 121 | poly1 = [] |
---|
[4797] | 122 | internal_poly=[] |
---|
[4799] | 123 | for i,angle in enumerate(angles1): |
---|
| 124 | #convert Degs to Rads |
---|
[4797] | 125 | angle = ((angle-180)/180.0)*pi |
---|
| 126 | |
---|
[5147] | 127 | p = get_xy(center_x,center_y,4.5,angle) |
---|
[4799] | 128 | poly1.append([p[0],p[1]]) |
---|
[4797] | 129 | |
---|
[4799] | 130 | poly.append(poly1) |
---|
[4877] | 131 | internal_poly.append([poly1,.1*res]) |
---|
[4799] | 132 | |
---|
| 133 | poly2 = [] |
---|
| 134 | for i,angle in enumerate(angles1): |
---|
| 135 | #convert Degs to Rads |
---|
[4797] | 136 | angle = ((angle-180)/180.0)*pi |
---|
[5147] | 137 | p = get_xy(center_x,center_y,3.2,angle) |
---|
[4799] | 138 | poly2.append([p[0],p[1]]) |
---|
[4797] | 139 | |
---|
[4799] | 140 | poly.append(poly2) |
---|
[4877] | 141 | internal_poly.append([poly2,.01*res]) |
---|
[4797] | 142 | |
---|
[4799] | 143 | poly3 = [] |
---|
| 144 | for i,angle in enumerate(angles1): |
---|
| 145 | #convert Degs to Rads |
---|
[4797] | 146 | angle = ((angle-180)/180.0)*pi |
---|
[5038] | 147 | # p = get_xy(center_x,center_y,1.6,angle) |
---|
| 148 | p = get_xy(center_x,center_y,1.5,angle) |
---|
[4799] | 149 | poly3.append([p[0],p[1]]) |
---|
[4797] | 150 | |
---|
[4799] | 151 | poly.append(poly3) |
---|
[4877] | 152 | internal_poly.append([poly3,1*res]) |
---|
[4797] | 153 | |
---|
[4987] | 154 | #plot_polygons(poly,'poly.png') |
---|
[4797] | 155 | |
---|
[5031] | 156 | poly_all= [[0,L],[0,25],[30,25],[30,L]] |
---|
[4777] | 157 | create_mesh_from_regions(poly_all, |
---|
[4797] | 158 | boundary_tags={'wall': [0,2],'wave': [3], 'buffer':[1]}, |
---|
[5038] | 159 | maximum_triangle_area=1*res, |
---|
[4777] | 160 | interior_regions=internal_poly, |
---|
| 161 | filename='temp.msh', |
---|
| 162 | use_cache=False, |
---|
| 163 | verbose=True) |
---|
| 164 | |
---|
| 165 | domain = Domain('temp.msh', use_cache=True, verbose=True) |
---|
| 166 | print domain.statistics() |
---|
| 167 | |
---|
| 168 | #------------------------- |
---|
| 169 | # Initial Conditions |
---|
| 170 | #------------------------- |
---|
[5123] | 171 | #domain.set_quantity('friction', 0.0) |
---|
| 172 | domain.set_quantity('friction', 0.01)#for concrete |
---|
| 173 | #water_height = 0.322 |
---|
| 174 | water_height = 0.0 |
---|
| 175 | |
---|
[4777] | 176 | domain.set_quantity('stage', water_height) |
---|
| 177 | |
---|
[5031] | 178 | |
---|
[5123] | 179 | #attribute_dic, title_index_dic = csv2dict('sqrt_table.csv') |
---|
[4777] | 180 | |
---|
[5038] | 181 | def circular_island_elevation(x,y): |
---|
[5123] | 182 | water_depth = 0.32 |
---|
| 183 | list_xy = sqrt((center_x-x)**2+(center_y-L-y)**2) |
---|
[5035] | 184 | print 'x',min(x),max(x) |
---|
| 185 | print 'y',min(y),max(y) |
---|
[5038] | 186 | list_z=[] |
---|
[5123] | 187 | # for xy in list_xy_square: |
---|
| 188 | for distance in list_xy: |
---|
| 189 | |
---|
[5147] | 190 | # The cone has a 1/4 slope and a 7.2 diameter this make the height 0.9m |
---|
| 191 | # to get the stage at 0 elevation + cone height and - water depth |
---|
[5123] | 192 | z = -distance*.25+0.9-water_depth |
---|
[5031] | 193 | |
---|
[5123] | 194 | if z <0-water_depth: |
---|
| 195 | z=0-water_depth |
---|
| 196 | if z > .625-water_depth: |
---|
| 197 | z=0.625-water_depth |
---|
[5038] | 198 | list_z.append(z) |
---|
| 199 | return list_z |
---|
[4980] | 200 | |
---|
[5038] | 201 | domain.set_quantity('elevation', circular_island_elevation, verbose=True) |
---|
[4980] | 202 | |
---|
| 203 | |
---|
[5123] | 204 | ##------------------------- |
---|
| 205 | ## Set simulation parameters |
---|
| 206 | ##------------------------- |
---|
[5031] | 207 | model_name='wavetank_model' |
---|
| 208 | domain.set_name(model_name) # Name of output sww file |
---|
[5065] | 209 | domain.set_datadir(output_dir) |
---|
[5123] | 210 | domain.set_default_order(2) # Apply second order scheme |
---|
[4985] | 211 | #domain.set_all_limiters(0.9) # Max second order scheme (old lim) |
---|
| 212 | domain.set_minimum_storable_height(0.001) # Don't store w < 0.001m |
---|
[5123] | 213 | #domain.set_maximum_allowed_speed(0.1) # Allow a little runoff (0.1 is OK) |
---|
[4777] | 214 | domain.tight_slope_limiters = 1 |
---|
| 215 | domain.beta_h = 0.0 |
---|
[5123] | 216 | |
---|
[5065] | 217 | sww_file=output_dir+sep+model_name+'.sww' |
---|
[4777] | 218 | |
---|
| 219 | |
---|
| 220 | #------------------------- |
---|
| 221 | # Boundary Conditions |
---|
| 222 | #------------------------- |
---|
| 223 | |
---|
| 224 | # Create boundary function from timeseries provided in file |
---|
| 225 | |
---|
[5123] | 226 | boundary_filename="ts2cnew1_input_20_80sec_new" |
---|
[4777] | 227 | prepare_timeboundary(boundary_filename+'.txt') |
---|
| 228 | |
---|
| 229 | function = file_function(boundary_filename+'.tms', |
---|
| 230 | domain, verbose=True) |
---|
| 231 | |
---|
| 232 | # Create and assign boundary objects |
---|
| 233 | Bts = Transmissive_Momentum_Set_Stage_boundary(domain, function) |
---|
| 234 | |
---|
| 235 | Br = Reflective_boundary(domain) |
---|
| 236 | Bd = Dirichlet_boundary([water_height,0,0]) |
---|
[5123] | 237 | #domain.set_boundary({'wave': Bts, 'wall': Br, 'buffer':Bd}) |
---|
| 238 | domain.set_boundary({'wave': Bts, 'wall': Bd, 'buffer':Bd}) |
---|
[5038] | 239 | #domain.set_time(20.0) |
---|
[4777] | 240 | #------------------------- |
---|
| 241 | # Evolve through time |
---|
| 242 | #------------------------- |
---|
| 243 | import time |
---|
| 244 | t0 = time.time() |
---|
| 245 | |
---|
[5123] | 246 | for t in domain.evolve(yieldstep = 1, finaltime = 28): |
---|
[4777] | 247 | domain.write_time() |
---|
| 248 | # domain.write_time(track_speeds=False) |
---|
| 249 | |
---|
[4980] | 250 | for t in domain.evolve(yieldstep = 0.1, finaltime = 36 |
---|
| 251 | #for t in domain.evolve(yieldstep = 0.5, finaltime = 36 |
---|
[4797] | 252 | ,skip_initial_step = True): |
---|
| 253 | domain.write_time() |
---|
| 254 | |
---|
[4985] | 255 | for t in domain.evolve(yieldstep = 1, finaltime = 45 |
---|
[4797] | 256 | ,skip_initial_step = True): |
---|
| 257 | domain.write_time() |
---|
| 258 | |
---|
[4777] | 259 | print 'That took %.2f seconds' %(time.time()-t0) |
---|
[4797] | 260 | |
---|
| 261 | |
---|
| 262 | |
---|
[4979] | 263 | #define the segments to find the run-up height to compare to wave tank study |
---|
| 264 | angles = (0.0, 22.5, 45.0, 67.5, 75.0, 80.0, 85.0, 87.5, 90.0, 92.5, |
---|
| 265 | 95.0, 100.0, 105.0, 112.5, 135.0, 157.5, 180.0, 202.5, 225.0, |
---|
| 266 | 247.5, 270.0, 292.5, 315.0, 337.5) |
---|
[5038] | 267 | r1 = 1.5 |
---|
| 268 | r2 = 2.6 |
---|
| 269 | #degrees to check |
---|
[5065] | 270 | d=1 |
---|
[4877] | 271 | |
---|
[4979] | 272 | poly_segment = [] |
---|
| 273 | |
---|
[4797] | 274 | for i,angle in enumerate(angles): |
---|
[4979] | 275 | angle = ((angle-180)/180.0)*pi |
---|
[5031] | 276 | p1 = get_xy(center_x,center_y,r1,angle-0.01745*d) |
---|
| 277 | p2 = get_xy(center_x,center_y,r2,angle-0.01745*d) |
---|
| 278 | p3 = get_xy(center_x,center_y,r2,angle+0.01745*d) |
---|
| 279 | p4 = get_xy(center_x,center_y,r1,angle+0.01745*d) |
---|
[4979] | 280 | # print p1,p2,p3,p4,angle |
---|
| 281 | poly_segment =[[p1[0],p1[1]],[p2[0],p2[1]],[p3[0],p3[1]],[p4[0],p4[1]]] |
---|
[4797] | 282 | |
---|
[5065] | 283 | run_up, location = get_maximum_inundation_data(filename=sww_file,polygon=poly_segment, verbose=False) |
---|
[4979] | 284 | |
---|
[5038] | 285 | print 'maxd %.3f, %.6f, %.6f, %.5s, %.5s '%(((angle/pi)*180)+180, run_up*100, (run_up-water_height)*100, location[0],location[1]) |
---|
[4797] | 286 | |
---|
[5123] | 287 | #sww_file=anuga_dir+'outputs'+sep+'20080220_010628_res_0.05_nbartzis'+sep+'wavetank_model.sww' |
---|
| 288 | #sww_file=anuga_dir+'outputs'+sep+'20080219_233611_res_0.05_nbartzis'+sep+'wavetank_model.sww' |
---|
[5065] | 289 | sww2csv_gauges(sww_file=sww_file, |
---|
[5123] | 290 | gauge_file=anuga_dir+'gauges'+sep+'gauges.csv', |
---|
[5147] | 291 | # gauge_file='gauges.csv', |
---|
[5065] | 292 | quantities = ['stage','depth', 'elevation', 'xmomentum', 'ymomentum'], |
---|
| 293 | verbose=True, |
---|
| 294 | use_cache = True) |
---|
[4797] | 295 | |
---|
| 296 | |
---|
| 297 | |
---|
| 298 | |
---|
[4877] | 299 | |
---|