Changeset 849
- Timestamp:
- Feb 8, 2005, 2:55:56 PM (20 years ago)
- Location:
- inundation/ga/storm_surge/pyvolution
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
inundation/ga/storm_surge/pyvolution/data_manager.py
r848 r849 229 229 fid.createVariable('x', self.precision, ('number_of_points',)) 230 230 fid.createVariable('y', self.precision, ('number_of_points',)) 231 fid.createVariable('z', self.precision, ('number_of_points',)) 231 fid.createVariable('elevation', self.precision, ('number_of_points',)) 232 233 #FIXME: Backwards compatibility 234 fid.createVariable('z', self.precision, ('number_of_points',)) 235 ################################# 232 236 233 237 fid.createVariable('volumes', Int, ('number_of_volumes', … … 272 276 x = fid.variables['x'] 273 277 y = fid.variables['y'] 274 z = fid.variables[' z']278 z = fid.variables['elevation'] 275 279 276 280 volumes = fid.variables['volumes'] … … 286 290 y[:] = Y.astype(self.precision) 287 291 z[:] = Z.astype(self.precision) 292 293 #FIXME: Backwards compatibility 294 z = fid.variables['z'] 295 z[:] = Z.astype(self.precision) 296 ################################ 288 297 289 298 volumes[:] = V.astype(volumes.typecode()) … … 403 412 fid.createVariable('x', self.precision, ('number_of_points',)) 404 413 fid.createVariable('y', self.precision, ('number_of_points',)) 405 #fid.createVariable('z', self.precision, ('number_of_points',)) 414 406 415 407 416 fid.createVariable('volumes', Int, ('number_of_volumes', … … 648 657 x = fid.variables['x'] 649 658 y = fid.variables['y'] 650 z = fid.variables[' z']659 z = fid.variables['elevation'] 651 660 time = fid.variables['time'] 652 661 stage = fid.variables['stage'] -
inundation/ga/storm_surge/pyvolution/general_mesh.py
r715 r849 37 37 38 38 #creates two triangles: bac and bce 39 39 40 Other: 41 42 In addition mesh computes an Nx6 array called vertex_coordinates. 43 This structure is derived from coordinates and contains for each 44 triangle the three x,y coordinates at the vertices. 45 40 46 41 47 This is a cut down version of mesh from pyvolution\mesh.py -
inundation/ga/storm_surge/pyvolution/generic_boundary_conditions.py
r844 r849 175 175 from Numeric import array 176 176 from config import time_format 177 from util import File_function178 179 Boundary.__init__(self) 180 181 self.F = File_function(filename, domain)177 from util import file_function 178 179 Boundary.__init__(self) 180 181 self.F = file_function(filename, domain) 182 182 self.domain = domain 183 183 … … 205 205 206 206 d = len(domain.conserved_quantities) 207 msg = 'Values specified in file must be a list or an array of length %d' %d207 msg = 'Values specified in file %s must be a list or an array of length %d' %(filename, d) 208 208 assert len(q) == d, msg 209 209 -
inundation/ga/storm_surge/pyvolution/interpolate_sww.py
r754 r849 106 106 try: 107 107 if quantity_name == 'height': 108 z = fid.variables[' z'][:]108 z = fid.variables['elevation'][:] 109 109 stage = fid.variables['stage'][:,:] 110 110 quantity = stage - z # 2D, using broadcasting -
inundation/ga/storm_surge/pyvolution/mesh.py
r655 r849 409 409 break 410 410 411 #Should this warning be an exception?412 #assert v is not None, msg413 411 414 412 … … 453 451 #for id, edge in self.boundary: 454 452 # assert self.neighbours[id,edge] < 0 455 456 453 # 454 #NOTE (Ole): I reckon this was resolved late 2004? 455 # 456 #See domain.set_boundary 457 457 458 458 -
inundation/ga/storm_surge/pyvolution/shallow_water.py
r845 r849 22 22 23 23 symbol variable name explanation 24 z elevation elevation of bed on which flow is modelled 25 h height water height above z 26 w stage water level, w = z+h 27 u speed in the x direction 28 v speed in the y direction 29 uh xmomentum momentum in the x direction 30 vh ymomentum momentum in the y direction 31 32 eta mannings friction coefficient 33 nu wind stress coefficient 24 x x horizontal distance from origin [m] 25 y y vertical distance from origin [m] 26 z elevation elevation of bed on which flow is modelled [m] 27 h height water height above z [m] 28 w stage water level, w = z+h [m] 29 u speed in the x direction [m/s] 30 v speed in the y direction [m/s] 31 uh xmomentum momentum in the x direction [m^2/s] 32 vh ymomentum momentum in the y direction [m^2/s] 33 34 eta mannings friction coefficient [] 35 nu wind stress coefficient [] 34 36 35 37 The conserved quantities are w, uh, vh … … 111 113 assert self.conserved_quantities[2] == 'ymomentum', msg 112 114 113 114 #Check that stages are >= bed elevation115 from Numeric import alltrue, greater_equal116 117 stage = self.quantities['stage']118 bed = self.quantities['elevation']119 120 115 121 116 def compute_fluxes(self): … … 766 761 767 762 768 class Spatio_temporal_boundary(Boundary): 769 """The spatio-temporal boundary, reads values for the conserved 770 quantities from an sww NetCDF file, and returns interpolated values 771 at the midpoints of each associated boundaty segment. 772 Time dependency is interpolated linearly as in util.File_function. 773 774 """ 775 776 pass 763 #class Spatio_temporal_boundary(Boundary): 764 # """The spatio-temporal boundary, reads values for the conserved 765 # quantities from an sww NetCDF file, and returns interpolated values 766 # at the midpoints of each associated boundaty segment. 767 # Time dependency is interpolated linearly as in util.File_function.# 768 # 769 # Example: 770 # Bf = Spatio_temporal_boundary('source_file.sww', domain) 771 # 772 # """ 773 Spatio_temporal_boundary = File_boundary 774 775 777 776 778 777 -
inundation/ga/storm_surge/pyvolution/test_data_manager.py
r839 r849 149 149 x = fid.variables['x'] 150 150 y = fid.variables['y'] 151 z = fid.variables[' z']151 z = fid.variables['elevation'] 152 152 153 153 volumes = fid.variables['volumes'] … … 196 196 x = fid.variables['x'] 197 197 y = fid.variables['y'] 198 z = fid.variables[' z']198 z = fid.variables['elevation'] 199 199 200 200 volumes = fid.variables['volumes'] … … 256 256 x = fid.variables['x'] 257 257 y = fid.variables['y'] 258 z = fid.variables[' z']258 z = fid.variables['elevation'] 259 259 time = fid.variables['time'] 260 260 stage = fid.variables['stage'] … … 314 314 x = fid.variables['x'] 315 315 y = fid.variables['y'] 316 z = fid.variables[' z']316 z = fid.variables['elevation'] 317 317 time = fid.variables['time'] 318 318 stage = fid.variables['stage'] … … 374 374 x = fid.variables['x'] 375 375 y = fid.variables['y'] 376 z = fid.variables[' z']376 z = fid.variables['elevation'] 377 377 time = fid.variables['time'] 378 378 stage = fid.variables['stage'] … … 459 459 x = fid.variables['x'] 460 460 y = fid.variables['y'] 461 z = fid.variables[' z']461 z = fid.variables['elevation'] 462 462 463 463 volumes = fid.variables['volumes'] -
inundation/ga/storm_surge/pyvolution/test_interpolate_sww.py
r773 r849 98 98 x = fid.variables['x'] 99 99 y = fid.variables['y'] 100 z = fid.variables[' z']100 z = fid.variables['elevation'] 101 101 102 102 volumes = fid.variables['volumes'] … … 218 218 # look at error catching 219 219 try: 220 interp = Interpolate_sww(sww.filename, ' z')220 interp = Interpolate_sww(sww.filename, 'elevation') 221 221 except KeyError: 222 222 pass -
inundation/ga/storm_surge/pyvolution/test_shallow_water.py
r845 r849 5 5 6 6 from config import g, epsilon 7 from Numeric import allclose, array, zeros, ones, Float 7 from Numeric import allclose, array, zeros, ones, Float, take 8 8 from shallow_water import * 9 9 … … 949 949 from math import pi, cos, sin, sqrt 950 950 from config import time_format 951 from util import File_function951 from util import file_function 952 952 import time 953 953 … … 995 995 996 996 #Setup wind stress 997 F = File_function(filename)997 F = file_function(filename) 998 998 W = Wind_stress(F) 999 999 domain.forcing_terms = [] … … 2380 2380 2381 2381 #Create sww file of simple propagation from left to right 2382 #through rectangular domain : domain12382 #through rectangular domain 2383 2383 2384 2384 from mesh_factory import rectangular … … 2388 2388 2389 2389 #Create shallow water domain 2390 domain = Domain(points, vertices, boundary) 2391 domain.smooth = False 2392 2393 domain.visualise = False 2394 domain.default_order = 2 2395 2396 domain.set_datadir('.') 2397 domain.store = True 2398 domain.set_name('test_spatio_temporal_boundary_' + str(time.time())) 2399 2390 domain1 = Domain(points, vertices, boundary) 2391 2392 from util import mean 2393 domain1.reduction = mean 2394 domain1.smooth = True #FIXME: This may be a requirement for the 2395 #interpolation process 2396 2397 #domain1.visualise = True 2398 domain1.default_order = 2 2399 2400 domain1.store = True 2401 domain1.set_datadir('.') 2402 domain1.set_name('spatio_temporal_boundary_source' + str(time.time())) 2403 2404 2400 2405 #Bed-slope and friction at vertices (and interpolated elsewhere) 2401 domain .set_quantity('elevation', 0)2402 domain .set_quantity('friction', 0)2406 domain1.set_quantity('elevation', 0) 2407 domain1.set_quantity('friction', 0) 2403 2408 2404 2409 # Boundary conditions 2405 Br = Reflective_boundary(domain )2410 Br = Reflective_boundary(domain1) 2406 2411 Bd = Dirichlet_boundary([0.3,0,0]) 2407 Bt = Transmissive_boundary(domain )2408 domain .set_boundary({'left': Bd, 'right': Bt, 'top': Br, 'bottom': Br})2412 Bt = Transmissive_boundary(domain1) 2413 domain1.set_boundary({'left': Bd, 'right': Bt, 'top': Br, 'bottom': Br}) 2409 2414 2410 2415 #Initial condition 2411 domain .set_quantity('stage', 0)2412 domain .check_integrity()2416 domain1.set_quantity('stage', 0) 2417 domain1.check_integrity() 2413 2418 2414 2419 #Evolution 2415 for t in domain.evolve(yieldstep = 0.05, finaltime = 4): 2416 import time 2417 #time.sleep(0.01) 2418 #domain.write_time() 2419 2420 2421 2422 2423 2424 #Create an triangle shaped domain, formed from the 2425 #lower and right hand boundaries and the sw-ne diagonal 2426 #from domain 1. Called it domain2 2420 for t in domain1.evolve(yieldstep = 0.05, finaltime = 4): 2421 pass 2422 2423 cv1 = domain1.quantities['stage'].centroid_values 2424 2425 #print take(cv1, (12,14,16)) #Right 2426 #print take(cv1, (0,6,12)) #Bottom 2427 2428 2429 #Create an triangle shaped domain (reusing coordinates from domain 1), 2430 #formed from the lower and right hand boundaries and 2431 #the sw-ne diagonal 2432 #from domain 1. Call it domain2 2433 2434 points = [ [0,0], [1.0/3,0], [1.0/3,1.0/3], 2435 [2.0/3,0], [2.0/3,1.0/3], [2.0/3,2.0/3], 2436 [1,0], [1,1.0/3], [1,2.0/3], [1,1]] 2437 2438 vertices = [ [1,2,0], 2439 [3,4,1], [2,1,4], [4,5,2], 2440 [6,7,3], [4,3,7], [7,8,4], [5,4,8], [8,9,5]] 2441 2442 boundary = { (0,1):'bottom', (1,1):'bottom', (4,1): 'bottom', 2443 (4,2):'right', (6,2):'right', (8,2):'right', 2444 (0,0):'diagonal', (3,0):'diagonal', (8,0):'diagonal'} 2445 2446 domain2 = Domain(points, vertices, boundary) 2447 2448 domain2.reduction = domain1.reduction 2449 domain2.smooth = False 2450 domain2.visualise = True 2451 domain2.default_order = 2 2452 2453 #Bed-slope and friction at vertices (and interpolated elsewhere) 2454 domain2.set_quantity('elevation', 0) 2455 domain2.set_quantity('friction', 0) 2456 2457 # Boundary conditions 2458 Br = Reflective_boundary(domain2) 2459 #Bd = Dirichlet_boundary([0.3,0,0]) 2460 Bt = Transmissive_boundary(domain2) 2461 2462 return 2463 2464 Bf = Spatio_temporal_boundary(domain1.filename + '.' + domain1.format, 2465 domain2) 2466 domain2.set_boundary({'right':Bt, 'bottom':Br, 'diagonal':Bf}) 2467 2468 #Initial condition 2469 domain2.set_quantity('stage', 0) 2470 domain2.check_integrity() 2471 2472 #Evolution 2473 for t in domain2.evolve(yieldstep = 0.05, finaltime = 4): 2474 pass 2475 2427 2476 2428 2477 #Use output from domain1 as spatio-temporal boundary for domain2 2429 2478 #and verify that results at right hand side are close. 2430 2479 2431 2432 2480 cv2 = domain2.quantities['stage'].centroid_values 2481 2482 print take(cv1, (12,14,16)) #Right 2483 print take(cv2, (4,6,8)) 2484 2485 #print take(cv1, (0,6,12)) #Bottom 2486 2487 assert allclose( take(cv1, (12,14,16)), take(cv2, (4,6,8))) #RHS 2488 assert allclose( take(cv1, (0,6,12)), take(cv2, (0,1,4))) #Bottom 2489 2490 #Cleanup 2491 os.remove(domain1.filename + '.' + domain1.format) 2433 2492 2434 2493 #------------------------------------------------------------- 2435 2494 if __name__ == "__main__": 2436 suite = unittest.makeSuite(TestCase,'test')2437 #suite = unittest.makeSuite(TestCase,'test_boundary_conditionsII')2495 #suite = unittest.makeSuite(TestCase,'test') 2496 suite = unittest.makeSuite(TestCase,'test_spatio_temporal_boundary') 2438 2497 runner = unittest.TextTestRunner() 2439 2498 runner.run(suite) -
inundation/ga/storm_surge/pyvolution/test_util.py
r841 r849 166 166 fid.close() 167 167 168 F = File_function(filename)168 F = file_function(filename) 169 169 170 170 #Now try interpolation … … 229 229 230 230 #Check that domain.starttime is updated if non-existing 231 F = File_function(filename, domain)231 F = file_function(filename, domain) 232 232 assert allclose(domain.starttime, start) 233 233 234 234 #Check that domain.starttime is updated if too early 235 235 domain.starttime = start - 1 236 F = File_function(filename, domain)236 F = file_function(filename, domain) 237 237 assert allclose(domain.starttime, start) 238 238 239 239 #Check that domain.starttime isn't updated if later 240 240 #domain.starttime = start + 1 241 #F = File_function(filename, domain)241 #F = file_function(filename, domain) 242 242 #assert allclose(domain.starttime, start+1) 243 243 … … 307 307 delta = 23 308 308 domain.starttime = start + delta 309 F = File_function(filename, domain)309 F = file_function(filename, domain) 310 310 assert allclose(domain.starttime, start+delta) 311 311 -
inundation/ga/storm_surge/pyvolution/util.py
r844 r849 80 80 return False 81 81 82 83 class File_function: 82 83 def file_function(filename, domain=None): 84 assert type(filename) == type(''),\ 85 'First argument to File_function must be a string' 86 87 try: 88 fid = open(filename) 89 except Exception, e: 90 msg = 'File "%s" could not be opened: Error="%s"'\ 91 %(filename, e) 92 raise msg 93 94 line = fid.readline() 95 fid.close() 96 97 #Choose format 98 #FIXME: Maybe these can be merged later on 99 if line[:3] == 'CDF': 100 return File_function_NetCDF(filename, domain) 101 else: 102 return File_function_ASCII(filename, domain) 103 104 105 class File_function_NetCDF: 106 """Read time history of spatial data from NetCDF sww file and 107 return a callable object f(t,x,y) 108 which will return interpolated values based on the input file. 109 110 x, y may be either scalars or vectors 111 112 #FIXME: More about format, interpolation and order of quantities 113 """ 114 115 def __init__(self, filename, domain=None): 116 """Initialise callable object from a file. 117 See docstring for class File_function_NetCDF 118 119 If domain is specified, model time (domain.starttime) 120 will be checked and possibly modified 121 122 All times are assumed to be in UTC 123 """ 124 125 import time, calendar 126 from Numeric import array 127 from config import time_format 128 from Scientific.IO.NetCDF import NetCDFFile 129 130 #Open NetCDF file 131 fid = NetCDFFile(filename, 'r') 132 133 print fid.variables.keys() 134 135 fields = line.split(',') 136 msg = 'File %s must have the format date, value0 value1 value2 ...' 137 msg += ' or date, x, y, value0 value1 value2 ...' 138 mode = len(fields) 139 assert mode in [2,4], msg 140 141 try: 142 starttime = calendar.timegm(time.strptime(fields[0], time_format)) 143 except ValueError: 144 msg = 'First field in file %s must be' %filename 145 msg += ' date-time with format %s.\n' %time_format 146 msg += 'I got %s instead.' %fields[0] 147 raise msg 148 149 150 #Split values 151 values = [] 152 for value in fields[mode-1].split(): 153 values.append(float(value)) 154 155 q = array(values) 156 157 msg = 'ERROR: File must contain at least one independent value' 158 assert len(q.shape) == 1, msg 159 160 self.number_of_values = len(q) 161 162 self.filename = filename 163 self.starttime = starttime 164 self.domain = domain 165 166 if domain is not None: 167 if domain.starttime is None: 168 domain.starttime = self.starttime 169 else: 170 msg = 'WARNING: Start time as specified in domain (%s)'\ 171 %domain.starttime 172 msg += ' is earlier than the starttime of file %s: %s.'\ 173 %(self.filename, self.starttime) 174 msg += 'Modifying starttime accordingly.' 175 if self.starttime > domain.starttime: 176 #FIXME: Print depending on some verbosity setting 177 #print msg 178 domain.starttime = self.starttime #Modifying model time 179 180 if mode == 2: 181 self.read_times() #Now read all times in. 182 else: 183 raise 'x,y dependency not yet implemented' 184 185 186 187 class File_function_ASCII: 188 """Read time series from file and return a callable object: 189 f(t,x,y) 190 which will return interpolated values based on the input file. 191 192 The file format is assumed to be either two fields separated by a comma: 193 194 time [DD/MM/YY hh:mm:ss], value0 value1 value2 ... 195 196 or four comma separated fields 197 198 time [DD/MM/YY hh:mm:ss], x, y, value0 value1 value2 ... 199 200 In either case, the callable object will return a tuple of 201 interpolated values, one each value stated in the file. 202 203 204 E.g 205 206 31/08/04 00:00:00, 1.328223 0 0 207 31/08/04 00:15:00, 1.292912 0 0 208 209 will provide a time dependent function f(t,x=None,y=None), 210 ignoring x and y, which returns three values per call. 211 212 213 NOTE: At this stage the function is assumed to depend on 214 time only, i.e no spatial dependency!!!!! 215 When that is needed we can use the least_squares interpolation. 216 217 #FIXME: This should work with netcdf (e.g. sww) and thus render the 218 #spatio-temporal boundary condition in shallow water fully general 219 """ 220 221 222 def __init__(self, filename, domain=None): 223 """Initialise callable object from a file. 224 See docstring for class File_function 225 226 If domain is specified, model time (domain,starttime) 227 will be checked and possibly modified 228 229 All times are assumed to be in UTC 230 """ 231 232 import time, calendar 233 from Numeric import array 234 from config import time_format 235 236 fid = open(filename) 237 line = fid.readline() 238 fid.close() 239 240 fields = line.split(',') 241 msg = 'File %s must have the format date, value0 value1 value2 ...' 242 msg += ' or date, x, y, value0 value1 value2 ...' 243 mode = len(fields) 244 assert mode in [2,4], msg 245 246 try: 247 starttime = calendar.timegm(time.strptime(fields[0], time_format)) 248 except ValueError: 249 msg = 'First field in file %s must be' %filename 250 msg += ' date-time with format %s.\n' %time_format 251 msg += 'I got %s instead.' %fields[0] 252 raise msg 253 254 255 #Split values 256 values = [] 257 for value in fields[mode-1].split(): 258 values.append(float(value)) 259 260 q = array(values) 261 262 msg = 'ERROR: File must contain at least one independent value' 263 assert len(q.shape) == 1, msg 264 265 self.number_of_values = len(q) 266 267 self.filename = filename 268 self.starttime = starttime 269 self.domain = domain 270 271 if domain is not None: 272 if domain.starttime is None: 273 domain.starttime = self.starttime 274 else: 275 msg = 'WARNING: Start time as specified in domain (%s)'\ 276 %domain.starttime 277 msg += ' is earlier than the starttime of file %s: %s.'\ 278 %(self.filename, self.starttime) 279 msg += 'Modifying starttime accordingly.' 280 if self.starttime > domain.starttime: 281 #FIXME: Print depending on some verbosity setting 282 #print msg 283 domain.starttime = self.starttime #Modifying model time 284 285 if mode == 2: 286 self.read_times() #Now read all times in. 287 else: 288 raise 'x,y dependency not yet implemented' 289 290 291 def read_times(self): 292 """Read time and values 293 """ 294 from Numeric import zeros, Float, alltrue 295 from config import time_format 296 import time, calendar 297 298 fid = open(self.filename) 299 lines = fid.readlines() 300 fid.close() 301 302 N = len(lines) 303 d = self.number_of_values 304 305 T = zeros(N, Float) #Time 306 Q = zeros((N, d), Float) #Values 307 308 for i, line in enumerate(lines): 309 fields = line.split(',') 310 realtime = calendar.timegm(time.strptime(fields[0], time_format)) 311 312 T[i] = realtime - self.starttime 313 314 for j, value in enumerate(fields[1].split()): 315 Q[i, j] = float(value) 316 317 msg = 'File %s must list time as a monotonuosly ' %self.filename 318 msg += 'increasing sequence' 319 assert alltrue( T[1:] - T[:-1] > 0 ), msg 320 321 self.T = T #Time 322 self.Q = Q #Values 323 self.index = 0 #Initial index 324 325 326 def __repr__(self): 327 return 'File function' 328 329 330 331 def __call__(self, t, x=None, y=None): 332 """Evaluate f(t,x,y) 333 334 FIXME: x, y dependency not yet implemented except that 335 result is a vector of same length as x and y 336 FIXME: Naaaa 337 """ 338 339 from math import pi, cos, sin, sqrt 340 341 342 #Find time tau such that 343 # 344 # domain.starttime + t == self.starttime + tau 345 346 if self.domain is not None: 347 tau = self.domain.starttime-self.starttime+t 348 else: 349 tau = t 350 351 352 msg = 'Time interval derived from file %s (%s:%s) does not match model time: %s'\ 353 %(self.filename, self.T[0], self.T[1], tau) 354 if tau < self.T[0]: raise msg 355 if tau > self.T[-1]: raise msg 356 357 oldindex = self.index 358 359 #Find slot 360 while tau > self.T[self.index]: self.index += 1 361 while tau < self.T[self.index]: self.index -= 1 362 363 #t is now between index and index+1 364 ratio = (tau - self.T[self.index])/\ 365 (self.T[self.index+1] - self.T[self.index]) 366 367 #Compute interpolated values 368 q = self.Q[self.index,:] +\ 369 ratio*(self.Q[self.index+1,:] - self.Q[self.index,:]) 370 371 #Return vector of interpolated values 372 if x == None and y == None: 373 return q 374 else: 375 try: 376 N = len(x) 377 except: 378 return q 379 else: 380 from Numeric import ones, Float 381 #x is a vector - Create one constant column for each value 382 N = len(x) 383 assert len(y) == N, 'x and y must have same length' 384 385 res = [] 386 for col in q: 387 res.append(col*ones(N, Float)) 388 389 return res 390 391 392 #FIXME: TEMP 393 class File_function_copy: 84 394 """Read time series from file and return a callable object: 85 395 f(t,x,y)
Note: See TracChangeset
for help on using the changeset viewer.