[659] | 1 | """Example of the inundationmodel. |
---|
| 2 | |
---|
| 3 | A wave of water is washed up ontp a hypothetical beach. |
---|
| 4 | |
---|
| 5 | To run: |
---|
| 6 | |
---|
| 7 | python beach.py |
---|
| 8 | """ |
---|
| 9 | |
---|
| 10 | ###################### |
---|
| 11 | # Module imports |
---|
| 12 | # |
---|
| 13 | |
---|
| 14 | import sys |
---|
| 15 | from os import sep, path |
---|
[1977] | 16 | #sys.path.append('..'+sep+'pyvolution') |
---|
[659] | 17 | |
---|
| 18 | from shallow_water import Domain, Reflective_boundary, Dirichlet_boundary,\ |
---|
[668] | 19 | Transmissive_boundary, Time_boundary, Wind_stress |
---|
[659] | 20 | |
---|
| 21 | from pmesh2domain import pmesh_to_domain_instance |
---|
| 22 | from util import read_polygon, Polygon_function |
---|
[667] | 23 | from math import pi |
---|
[672] | 24 | from Numeric import choose, greater, ones, sin, exp |
---|
| 25 | import time |
---|
[659] | 26 | |
---|
| 27 | ###################### |
---|
| 28 | # Domain |
---|
| 29 | name = 'beach' |
---|
| 30 | print 'Creating domain from %s.tsh' %name |
---|
| 31 | domain = pmesh_to_domain_instance(name + '.tsh', Domain) |
---|
| 32 | |
---|
| 33 | domain.store = True |
---|
[694] | 34 | domain.set_name(name + '6') |
---|
[673] | 35 | domain.default_order = 2 |
---|
[901] | 36 | print "Output being written to " + domain.get_datadir() + sep + \ |
---|
[667] | 37 | domain.filename + "_size%d." %len(domain) + domain.format |
---|
[659] | 38 | |
---|
| 39 | |
---|
[667] | 40 | def bathymetry(x, y): |
---|
| 41 | cut = 75 |
---|
[659] | 42 | |
---|
[688] | 43 | res = choose( greater(x, cut), ( -(x - 55)/5, -4*ones(x.shape) )) |
---|
| 44 | res == (100-y)/50 + 1 |
---|
| 45 | #res += (100-y)/130 #Lift up southern bathymetry |
---|
| 46 | #res -= y/1500 #Pull down northern bathymetry |
---|
| 47 | |
---|
[672] | 48 | return res |
---|
| 49 | |
---|
[659] | 50 | |
---|
[667] | 51 | def topography(x, y): |
---|
[659] | 52 | |
---|
[672] | 53 | import RandomArray |
---|
| 54 | #z = 4*sin(pi*x/50) + (100-y)/50 + 1 #Ridge |
---|
| 55 | |
---|
| 56 | z = -4.0*x/25 + 8 + (100-y)/50 #Beach |
---|
| 57 | |
---|
| 58 | #z += sin(pi*x/5)/4 |
---|
| 59 | #z += RandomArray.normal(0, 1, x.shape)/4 |
---|
| 60 | |
---|
| 61 | z += 6*exp( -((x-30)/10)**2 ) * exp( -((y-50)/8)**2 ) #Mound |
---|
| 62 | z += 4*exp( -((x-30)/4)**2 ) * exp( -((y-26)/10)**2 ) #extra ridge |
---|
[688] | 63 | z += 4*exp( -((x-30)/5)**2 ) * exp( -((y-10)/8)**2 ) #extra ridge |
---|
| 64 | z -= 4*exp( -((x-15)/6)**2 ) * exp( -((y-20)/12)**2 ) #depression |
---|
| 65 | |
---|
| 66 | z += 1.2*exp( -((x-88)/7)**2 ) + exp( -((y-20)/25)**2 ) #Seafloor |
---|
[672] | 67 | return z |
---|
| 68 | |
---|
[667] | 69 | def riverbed(x, y): |
---|
[672] | 70 | return (y-100)/70 - 4.0*x/25 + 8 |
---|
[667] | 71 | |
---|
[659] | 72 | |
---|
[667] | 73 | shoreline = [[40,0], [100,0], [100,100], [65,100], |
---|
| 74 | [55,90], [55,70], [56,50], [50,25], [40,0]] |
---|
[659] | 75 | |
---|
[667] | 76 | land = [[65,100], [55,90], [55,70], [56,50], [50,25], [40,0], |
---|
[688] | 77 | [0,0], [0,100]] |
---|
| 78 | |
---|
| 79 | |
---|
| 80 | water = [[55,0], [100,0], [100,100], [55,100]] |
---|
| 81 | all = [[0,0], [0,100], [100,100], [100,0]] |
---|
| 82 | |
---|
[672] | 83 | |
---|
[667] | 84 | |
---|
[672] | 85 | building1 = [[45,80], [49,78], [52,83], [46,83]] |
---|
[667] | 86 | building2 = [[35,75], [40,75], [40,80], [35,80]] |
---|
[672] | 87 | building3 = [[42,63], [46,61], [48,65], [44,67]] |
---|
| 88 | building4 = [[28,56], [28,51], [33,51], [33,56]] |
---|
| 89 | building5 = [[10,70], [10,65], [15,65], [15,70]] |
---|
| 90 | building6 = [[10,50], [10,45], [15,45], [15,50]] |
---|
[667] | 91 | |
---|
| 92 | river = [[20,100], [18,90], [20,80], [20,60], [15,40], [11,20], [2,0], [10,0], |
---|
[668] | 93 | [14,10], [20,30], [24,45], [27,80], [27,85], [35,90], [39,100]] |
---|
[667] | 94 | |
---|
| 95 | print 'Set elevation' |
---|
[672] | 96 | t0 = time.time() |
---|
[667] | 97 | domain.set_quantity('elevation', |
---|
[688] | 98 | Polygon_function( [(all, topography), |
---|
| 99 | #(shoreline, bathymetry), (land, topography), |
---|
| 100 | (building1, 7), (building2, 8), |
---|
| 101 | (building3, 7), (building4, 13), |
---|
| 102 | (building5, 10), (building6, 11)])) |
---|
| 103 | #(river, riverbed)])) |
---|
[667] | 104 | |
---|
[672] | 105 | print 'That took %.2f seconds' %(time.time()-t0) |
---|
| 106 | |
---|
[774] | 107 | print 'Set stage' |
---|
| 108 | domain.set_quantity('stage', |
---|
[688] | 109 | Polygon_function( [(water, -1.5), |
---|
[667] | 110 | (land, -10)] )) |
---|
| 111 | |
---|
| 112 | print 'Set friction' |
---|
[673] | 113 | domain.set_quantity('friction', 0.08) |
---|
[659] | 114 | |
---|
| 115 | print domain.get_extent() |
---|
| 116 | |
---|
[668] | 117 | |
---|
| 118 | |
---|
| 119 | #Add lateral wind gusts bearing 135 degrees |
---|
| 120 | def gust(t,x,y): |
---|
| 121 | from math import sin, pi |
---|
| 122 | from Numeric import zeros, ones, Float |
---|
| 123 | |
---|
| 124 | N = len(x) |
---|
| 125 | |
---|
| 126 | tt = sin(2*pi*t/50) |
---|
| 127 | |
---|
[688] | 128 | if tt > 0.98: |
---|
[690] | 129 | return 26000*tt*ones(N, Float) |
---|
[668] | 130 | else: |
---|
| 131 | return zeros(N, Float) |
---|
| 132 | |
---|
| 133 | domain.forcing_terms.append(Wind_stress(gust, 135)) |
---|
| 134 | |
---|
| 135 | |
---|
[688] | 136 | #Add lateral wind gusts bearing 90 degrees |
---|
| 137 | def gust2(t,x,y): |
---|
| 138 | from math import sin, pi |
---|
| 139 | from Numeric import zeros, ones, Float |
---|
| 140 | |
---|
| 141 | N = len(x) |
---|
| 142 | |
---|
[694] | 143 | tt = sin(2*pi*t/100) |
---|
[688] | 144 | |
---|
| 145 | if tt > 0.95: |
---|
[690] | 146 | return 22000*tt*ones(N, Float) |
---|
[688] | 147 | else: |
---|
| 148 | return zeros(N, Float) |
---|
| 149 | |
---|
| 150 | domain.forcing_terms.append(Wind_stress(gust2, 90)) |
---|
| 151 | |
---|
[694] | 152 | #Add lateral wind gusts bearing 255 degrees |
---|
| 153 | def gust3(t,x,y): |
---|
| 154 | from math import sin, pi |
---|
| 155 | from Numeric import zeros, ones, Float |
---|
[688] | 156 | |
---|
[694] | 157 | N = len(x) |
---|
| 158 | |
---|
| 159 | tt = sin(2*pi*(t-30)/55) |
---|
| 160 | |
---|
| 161 | if tt > 0.96: |
---|
| 162 | return 24000*tt*ones(N, Float) |
---|
| 163 | else: |
---|
| 164 | return zeros(N, Float) |
---|
| 165 | |
---|
| 166 | domain.forcing_terms.append(Wind_stress(gust3, 255)) |
---|
| 167 | |
---|
| 168 | |
---|
[659] | 169 | ###################### |
---|
| 170 | # Boundary conditions |
---|
| 171 | |
---|
| 172 | print 'Boundaries' |
---|
| 173 | Br = Reflective_boundary(domain) |
---|
[668] | 174 | Bo = Transmissive_boundary(domain) |
---|
[659] | 175 | |
---|
[672] | 176 | #Constant outflow |
---|
| 177 | Bd = Dirichlet_boundary([-10, 0.0, 0.0]) |
---|
[690] | 178 | Bt = Time_boundary(domain, lambda t: [ 3.0*(1+sin(2*pi*t/100)), 0.0, 0.0]) |
---|
[659] | 179 | |
---|
| 180 | print 'Available boundary tags are', domain.get_boundary_tags() |
---|
| 181 | |
---|
| 182 | #Set boundary conditions |
---|
| 183 | tags = {} |
---|
[667] | 184 | tags['ocean'] = Bt |
---|
[659] | 185 | tags['wall'] = Br |
---|
[672] | 186 | tags['wall1'] = Br |
---|
| 187 | tags['outflow'] = Bd |
---|
[659] | 188 | tags['exterior'] = Br |
---|
[672] | 189 | tags['external'] = Br |
---|
[673] | 190 | #tags['land'] = Bo |
---|
| 191 | tags['land'] = Bd |
---|
[672] | 192 | tags['westbank'] = None #Riverbank |
---|
| 193 | tags['eastbank'] = None #Riverbank |
---|
| 194 | tags['eastbankN'] = None #Riverbank |
---|
[659] | 195 | domain.set_boundary(tags) |
---|
| 196 | |
---|
| 197 | |
---|
| 198 | domain.check_integrity() |
---|
| 199 | |
---|
| 200 | ###################### |
---|
| 201 | #Evolution |
---|
[688] | 202 | t0 = time.time() |
---|
[672] | 203 | for t in domain.evolve(yieldstep = 0.2, finaltime = 300): |
---|
[659] | 204 | domain.write_time() |
---|
[688] | 205 | print 'Simulation took %.2f seconds' %(time.time()-t0) |
---|
[659] | 206 | |
---|