2 A collection of functions for streamlines and related shennanigans.
7 Functions for creating and analysing streamlines.
9 These functions work on cartesian and spherical polar grids - other grids, such as cubed sphere, are not supported.
11 Streamlines are defined to be the path that a parcel of fluid would follow when advected by an unchanging velocity field - the velocities are constant in time.
13 Streaklines are defined as the path that a parcel of fluid would follow in the actual flow - the velocity fields change with time.
22 import scipy.interpolate
23 from .
import functions
28 t_max=2592000,delta_t=3600,
29 u_grid_loc=
'U',v_grid_loc='V'):
30 """!A two-dimensional streamline solver. The velocity fields *must* be two dimensional and not vary in time.
31 X_grid_loc variables specify where the field "X" is located on the C-grid. Possibles options are, U, V, T and Zeta.
35 x_u = grid_object['Xp1'][:]
36 y_u = grid_object[
'Y'][:]
37 elif u_grid_loc ==
'V':
38 x_u = grid_object[
'X'][:]
39 y_u = grid_object[
'Yp1'][:]
40 elif u_grid_loc ==
'T':
41 x_u = grid_object[
'X'][:]
42 y_u = grid_object[
'Y'][:]
43 elif u_grid_loc ==
'Zeta':
44 x_u = grid_object[
'Xp1'][:]
45 y_u = grid_object[
'Yp1'][:]
47 print 'u_grid_loc not set correctly. Possible options are: U,V,T, Zeta'
51 x_v = grid_object['Xp1'][:]
52 y_v = grid_object[
'Y'][:]
53 elif v_grid_loc ==
'V':
54 x_v = grid_object[
'X'][:]
55 y_v = grid_object[
'Yp1'][:]
56 elif v_grid_loc ==
'T':
57 x_v = grid_object[
'X'][:]
58 y_v = grid_object[
'Y'][:]
59 elif v_grid_loc ==
'Zeta':
60 x_v = grid_object[
'Xp1'][:]
61 y_v = grid_object[
'Yp1'][:]
63 print 'v_grid_loc not set correctly. Possible options are: U,V,T, Zeta'
76 x_stream = np.ones((int(t_max/delta_t)+2))*startx
77 y_stream = np.ones((int(t_max/delta_t)+2))*starty
78 t_stream = np.zeros((int(t_max/delta_t)+2))
83 deg_per_m = np.array([1,1])
87 if grid_object[
'grid_type']==
'polar':
89 deg_per_m = np.array([1./(1852.*60.),np.cos(starty*np.pi/180.)/(1852.*60.)])
94 u_loc = u_loc*deg_per_m[1]
95 v_loc = v_loc*deg_per_m[0]
99 u_loc1 =
bilinear_interp(startx + 0.5*dx1,starty + 0.5*dy1,u,x_u,y_u,len_x_u,len_y_u)
100 v_loc1 =
bilinear_interp(startx + 0.5*dx1,starty + 0.5*dy1,v,x_v,y_v,len_x_v,len_y_v)
101 u_loc1 = u_loc1*deg_per_m[1]
102 v_loc1 = v_loc1*deg_per_m[0]
106 u_loc2 =
bilinear_interp(startx + 0.5*dx2,starty + 0.5*dy2,u,x_u,y_u,len_x_u,len_y_u)
107 v_loc2 =
bilinear_interp(startx + 0.5*dx2,starty + 0.5*dy2,v,x_v,y_v,len_x_v,len_y_v)
108 u_loc2 = u_loc2*deg_per_m[1]
109 v_loc2 = v_loc2*deg_per_m[0]
113 u_loc3 =
bilinear_interp(startx + dx3,starty + dy3,u,x_u,y_u,len_x_u,len_y_u)
114 v_loc3 =
bilinear_interp(startx + dx3,starty + dy3,v,x_v,y_v,len_x_v,len_y_v)
115 u_loc3 = u_loc3*deg_per_m[1]
116 v_loc3 = v_loc3*deg_per_m[0]
120 startx = startx + (dx1 + 2*dx2 + 2*dx3 + dx4)/6
121 starty = starty + (dy1 + 2*dy2 + 2*dy3 + dy4)/6
135 return x_stream,y_stream,t_stream
139 startx,starty,startz,
141 x_v=
'None',y_v=
'None',z_v=
'None',
142 x_w=
'None',y_w=
'None',z_w=
'None',
143 t_max=2592000,delta_t=3600,
144 u_grid_loc=
'U',v_grid_loc='V',w_grid_loc='W'):
145 """!A three-dimensional streamline solver. The velocity fields must be three dimensional and not vary in time.
146 X_grid_loc variables specify where the field "X" is located on the C-grid. Possibles options are, U, V, W, T and Zeta.
149 if u_grid_loc ==
'U':
150 x_u = copy.deepcopy(grid_object['Xp1'][:])
151 y_u = copy.deepcopy(grid_object[
'Y'][:])
152 z_u = copy.deepcopy(grid_object[
'Z'][:])
153 elif u_grid_loc ==
'V':
154 x_u = copy.deepcopy(grid_object[
'X'][:])
155 y_u = copy.deepcopy(grid_object[
'Yp1'][:])
156 z_u = copy.deepcopy(grid_object[
'Z'][:])
157 elif u_grid_loc ==
'W':
158 x_u = copy.deepcopy(grid_object[
'X'][:])
159 y_u = copy.deepcopy(grid_object[
'Y'][:])
160 z_u = copy.deepcopy(grid_object[
'Zl'][:])
161 elif u_grid_loc ==
'T':
162 x_u = copy.deepcopy(grid_object[
'X'][:])
163 y_u = copy.deepcopy(grid_object[
'Y'][:])
164 z_u = copy.deepcopy(grid_object[
'Z'][:])
165 elif u_grid_loc ==
'Zeta':
166 x_u = copy.deepcopy(grid_object[
'Xp1'][:])
167 y_u = copy.deepcopy(grid_object[
'Yp1'][:])
168 z_u = copy.deepcopy(grid_object[
'Z'][:])
170 print 'u_grid_loc not set correctly. Possible options are: U,V,W,T, and Zeta'
173 if v_grid_loc ==
'U':
174 x_v = copy.deepcopy(grid_object['Xp1'][:])
175 y_v = copy.deepcopy(grid_object[
'Y'][:])
176 z_v = copy.deepcopy(grid_object[
'Z'][:])
177 elif v_grid_loc ==
'V':
178 x_v = copy.deepcopy(grid_object[
'X'][:])
179 y_v = copy.deepcopy(grid_object[
'Yp1'][:])
180 z_v = copy.deepcopy(grid_object[
'Z'][:])
181 elif v_grid_loc ==
'W':
182 x_v = copy.deepcopy(grid_object[
'X'][:])
183 y_v = copy.deepcopy(grid_object[
'Y'][:])
184 z_v = copy.deepcopy(grid_object[
'Zl'][:])
185 elif v_grid_loc ==
'T':
186 x_v = copy.deepcopy(grid_object[
'X'][:])
187 y_v = copy.deepcopy(grid_object[
'Y'][:])
188 z_v = copy.deepcopy(grid_object[
'Z'][:])
189 elif v_grid_loc ==
'Zeta':
190 x_v = copy.deepcopy(grid_object[
'Xp1'][:])
191 y_v = copy.deepcopy(grid_object[
'Yp1'][:])
192 z_v = copy.deepcopy(grid_object[
'Z'][:])
194 print 'v_grid_loc not set correctly. Possible options are: U,V,W,T, and Zeta'
197 if w_grid_loc ==
'U':
198 x_w = copy.deepcopy(grid_object['Xp1'][:])
199 y_w = copy.deepcopy(grid_object[
'Y'][:])
200 z_w = copy.deepcopy(grid_object[
'Z'][:])
201 elif w_grid_loc ==
'V':
202 x_w = copy.deepcopy(grid_object[
'X'][:])
203 y_w = copy.deepcopy(grid_object[
'Yp1'][:])
204 z_w = copy.deepcopy(grid_object[
'Z'][:])
205 elif w_grid_loc ==
'W':
206 x_w = copy.deepcopy(grid_object[
'X'][:])
207 y_w = copy.deepcopy(grid_object[
'Y'][:])
208 z_w = copy.deepcopy(grid_object[
'Zl'][:])
209 elif w_grid_loc ==
'T':
210 x_w = copy.deepcopy(grid_object[
'X'][:])
211 y_w = copy.deepcopy(grid_object[
'Y'][:])
212 z_w = copy.deepcopy(grid_object[
'Z'][:])
213 elif w_grid_loc ==
'Zeta':
214 x_w = copy.deepcopy(grid_object[
'Xp1'][:])
215 y_w = copy.deepcopy(grid_object[
'Yp1'][:])
216 z_w = copy.deepcopy(grid_object[
'Z'][:])
218 print 'w_grid_loc not set correctly. Possible options are: U,V,W,T, and Zeta'
234 x_stream = np.ones((int(np.fabs(t_max/delta_t))+2))*startx
235 y_stream = np.ones((int(np.fabs(t_max/delta_t))+2))*starty
236 z_stream = np.ones((int(np.fabs(t_max/delta_t))+2))*startz
237 t_stream = np.zeros((int(np.fabs(t_max/delta_t))+2))
242 deg_per_m = np.array([1,1])
246 while i < np.fabs(t_max/delta_t):
248 if grid_object[
'grid_type']==
'polar':
250 deg_per_m = np.array([1./(1852.*60.),np.cos(starty*np.pi/180.)/(1852.*60.)])
253 u_loc =
trilinear_interp(startx,starty,startz,u,x_u,y_u,z_u,len_x_u,len_y_u,len_z_u)
254 v_loc =
trilinear_interp(startx,starty,startz,v,x_v,y_v,z_v,len_x_v,len_y_v,len_z_v)
255 w_loc =
trilinear_interp(startx,starty,startz,w,x_w,y_w,z_w,len_x_w,len_y_w,len_z_w)
256 u_loc = u_loc*deg_per_m[1]
257 v_loc = v_loc*deg_per_m[0]
262 u_loc1 =
trilinear_interp(startx + 0.5*dx1,starty + 0.5*dy1,startz + 0.5*dz1,u,x_u,y_u,z_u,len_x_u,len_y_u,len_z_u)
263 v_loc1 =
trilinear_interp(startx + 0.5*dx1,starty + 0.5*dy1,startz + 0.5*dz1,v,x_v,y_v,z_v,len_x_v,len_y_v,len_z_v)
264 w_loc1 =
trilinear_interp(startx + 0.5*dx1,starty + 0.5*dy1,startz + 0.5*dz1,w,x_w,y_w,z_w,len_x_w,len_y_w,len_z_w)
265 u_loc1 = u_loc1*deg_per_m[1]
266 v_loc1 = v_loc1*deg_per_m[0]
271 u_loc2 =
trilinear_interp(startx + 0.5*dx2,starty + 0.5*dy2,startz + 0.5*dz2,u,x_u,y_u,z_u,len_x_u,len_y_u,len_z_u)
272 v_loc2 =
trilinear_interp(startx + 0.5*dx2,starty + 0.5*dy2,startz + 0.5*dz2,v,x_v,y_v,z_v,len_x_v,len_y_v,len_z_v)
273 w_loc2 =
trilinear_interp(startx + 0.5*dx2,starty + 0.5*dy2,startz + 0.5*dz2,w,x_w,y_w,z_w,len_x_w,len_y_w,len_z_w)
274 u_loc2 = u_loc2*deg_per_m[1]
275 v_loc2 = v_loc2*deg_per_m[0]
280 u_loc3 =
trilinear_interp(startx + dx3,starty + dy3,startz + dz3,u,x_u,y_u,z_u,len_x_u,len_y_u,len_z_u)
281 v_loc3 =
trilinear_interp(startx + dx3,starty + dy3,startz + dz3,v,x_v,y_v,z_v,len_x_v,len_y_v,len_z_v)
282 w_loc3 =
trilinear_interp(startx + dx3,starty + dy3,startz + dz3,w,x_w,y_w,z_w,len_x_w,len_y_w,len_z_w)
283 u_loc3 = u_loc3*deg_per_m[1]
284 v_loc3 = v_loc3*deg_per_m[0]
290 startx = startx + (dx1 + 2*dx2 + 2*dx3 + dx4)/6
291 starty = starty + (dy1 + 2*dy2 + 2*dy3 + dy4)/6
292 startz = startz + (dz1 + 2*dz2 + 2*dz3 + dz4)/6
302 return x_stream,y_stream,z_stream,t_stream
306 startx,starty,startz,
308 x_v=
'None',y_v=
'None',z_v=
'None',
309 x_w=
'None',y_w=
'None',z_w=
'None',
310 t_max=2592000,delta_t=3600,
311 u_grid_loc=
'U',v_grid_loc='V',w_grid_loc='W'):
312 """!A three-dimensional streamline solver. The velocity fields must be three dimensional and not vary in time.
313 X_grid_loc variables specify where the field "X" is located on the C-grid. Possibles options are, U, V, W, T and Zeta.
316 * x_stream, y_stream, z_stream - all with dimensions (particle,time_level)
317 * t_stream - with dimensions (time_level)
320 if u_grid_loc ==
'U':
321 x_u = copy.deepcopy(grid_object['Xp1'][:])
322 y_u = copy.deepcopy(grid_object[
'Y'][:])
323 z_u = copy.deepcopy(grid_object[
'Z'][:])
324 elif u_grid_loc ==
'V':
325 x_u = copy.deepcopy(grid_object[
'X'][:])
326 y_u = copy.deepcopy(grid_object[
'Yp1'][:])
327 z_u = copy.deepcopy(grid_object[
'Z'][:])
328 elif u_grid_loc ==
'W':
329 x_u = copy.deepcopy(grid_object[
'X'][:])
330 y_u = copy.deepcopy(grid_object[
'Y'][:])
331 z_u = copy.deepcopy(grid_object[
'Zl'][:])
332 elif u_grid_loc ==
'T':
333 x_u = copy.deepcopy(grid_object[
'X'][:])
334 y_u = copy.deepcopy(grid_object[
'Y'][:])
335 z_u = copy.deepcopy(grid_object[
'Z'][:])
336 elif u_grid_loc ==
'Zeta':
337 x_u = copy.deepcopy(grid_object[
'Xp1'][:])
338 y_u = copy.deepcopy(grid_object[
'Yp1'][:])
339 z_u = copy.deepcopy(grid_object[
'Z'][:])
341 print 'u_grid_loc not set correctly. Possible options are: U,V,W,T, and Zeta'
344 if v_grid_loc ==
'U':
345 x_v = copy.deepcopy(grid_object['Xp1'][:])
346 y_v = copy.deepcopy(grid_object[
'Y'][:])
347 z_v = copy.deepcopy(grid_object[
'Z'][:])
348 elif v_grid_loc ==
'V':
349 x_v = copy.deepcopy(grid_object[
'X'][:])
350 y_v = copy.deepcopy(grid_object[
'Yp1'][:])
351 z_v = copy.deepcopy(grid_object[
'Z'][:])
352 elif v_grid_loc ==
'W':
353 x_v = copy.deepcopy(grid_object[
'X'][:])
354 y_v = copy.deepcopy(grid_object[
'Y'][:])
355 z_v = copy.deepcopy(grid_object[
'Zl'][:])
356 elif v_grid_loc ==
'T':
357 x_v = copy.deepcopy(grid_object[
'X'][:])
358 y_v = copy.deepcopy(grid_object[
'Y'][:])
359 z_v = copy.deepcopy(grid_object[
'Z'][:])
360 elif v_grid_loc ==
'Zeta':
361 x_v = copy.deepcopy(grid_object[
'Xp1'][:])
362 y_v = copy.deepcopy(grid_object[
'Yp1'][:])
363 z_v = copy.deepcopy(grid_object[
'Z'][:])
365 print 'v_grid_loc not set correctly. Possible options are: U,V,W,T, and Zeta'
368 if w_grid_loc ==
'U':
369 x_w = copy.deepcopy(grid_object['Xp1'][:])
370 y_w = copy.deepcopy(grid_object[
'Y'][:])
371 z_w = copy.deepcopy(grid_object[
'Z'][:])
372 elif w_grid_loc ==
'V':
373 x_w = copy.deepcopy(grid_object[
'X'][:])
374 y_w = copy.deepcopy(grid_object[
'Yp1'][:])
375 z_w = copy.deepcopy(grid_object[
'Z'][:])
376 elif w_grid_loc ==
'W':
377 x_w = copy.deepcopy(grid_object[
'X'][:])
378 y_w = copy.deepcopy(grid_object[
'Y'][:])
379 z_w = copy.deepcopy(grid_object[
'Zl'][:])
380 elif w_grid_loc ==
'T':
381 x_w = copy.deepcopy(grid_object[
'X'][:])
382 y_w = copy.deepcopy(grid_object[
'Y'][:])
383 z_w = copy.deepcopy(grid_object[
'Z'][:])
384 elif w_grid_loc ==
'Zeta':
385 x_w = copy.deepcopy(grid_object[
'Xp1'][:])
386 y_w = copy.deepcopy(grid_object[
'Yp1'][:])
387 z_w = copy.deepcopy(grid_object[
'Z'][:])
389 print 'w_grid_loc not set correctly. Possible options are: U,V,W,T, and Zeta'
405 x_stream = np.ones((len(startx),int(np.fabs(t_max/delta_t))+2))*startx[:,np.newaxis]
406 y_stream = np.ones((len(startx),int(np.fabs(t_max/delta_t))+2))*starty[:,np.newaxis]
407 z_stream = np.ones((len(startx),int(np.fabs(t_max/delta_t))+2))*startz[:,np.newaxis]
408 t_stream = np.zeros((int(np.fabs(t_max/delta_t))+2))
414 deg_per_m = np.ones((len(startx),2),dtype=float)
415 if grid_object[
'grid_type']==
'polar':
416 deg_per_m[:,0] = np.ones_like(startx)/(1852.*60.)
419 while i < np.fabs(t_max/delta_t):
421 if grid_object[
'grid_type']==
'polar':
423 deg_per_m[:,1] = np.cos(starty*np.pi/180.)/(1852.*60.)
429 u_loc = u_loc*deg_per_m[:,1]
430 v_loc = v_loc*deg_per_m[:,0]
435 u_loc1 =
trilinear_interp_arrays(startx + 0.5*dx1,starty + 0.5*dy1,startz + 0.5*dz1,u,x_u,y_u,z_u,len_x_u,len_y_u,len_z_u)
436 v_loc1 =
trilinear_interp_arrays(startx + 0.5*dx1,starty + 0.5*dy1,startz + 0.5*dz1,v,x_v,y_v,z_v,len_x_v,len_y_v,len_z_v)
437 w_loc1 =
trilinear_interp_arrays(startx + 0.5*dx1,starty + 0.5*dy1,startz + 0.5*dz1,w,x_w,y_w,z_w,len_x_w,len_y_w,len_z_w)
438 u_loc1 = u_loc1*deg_per_m[:,1]
439 v_loc1 = v_loc1*deg_per_m[:,0]
444 u_loc2 =
trilinear_interp_arrays(startx + 0.5*dx2,starty + 0.5*dy2,startz + 0.5*dz2,u,x_u,y_u,z_u,len_x_u,len_y_u,len_z_u)
445 v_loc2 =
trilinear_interp_arrays(startx + 0.5*dx2,starty + 0.5*dy2,startz + 0.5*dz2,v,x_v,y_v,z_v,len_x_v,len_y_v,len_z_v)
446 w_loc2 =
trilinear_interp_arrays(startx + 0.5*dx2,starty + 0.5*dy2,startz + 0.5*dz2,w,x_w,y_w,z_w,len_x_w,len_y_w,len_z_w)
447 u_loc2 = u_loc2*deg_per_m[:,1]
448 v_loc2 = v_loc2*deg_per_m[:,0]
456 u_loc3 = u_loc3*deg_per_m[:,1]
457 v_loc3 = v_loc3*deg_per_m[:,0]
463 startx = startx + (dx1 + 2*dx2 + 2*dx3 + dx4)/6
464 starty = starty + (dy1 + 2*dy2 + 2*dy3 + dy4)/6
465 startz = startz + (dz1 + 2*dz2 + 2*dz3 + dz4)/6
469 x_stream[:,i] = startx
470 y_stream[:,i] = starty
471 z_stream[:,i] = startz
475 return x_stream,y_stream,z_stream,t_stream
479 def pathlines(u_netcdf_filename,v_netcdf_filename,w_netcdf_filename,
480 startx,starty,startz,startt,
484 u_netcdf_variable=
'UVEL',
485 v_netcdf_variable=
'VVEL',
486 w_netcdf_variable=
'WVEL',
487 u_grid_loc=
'U',v_grid_loc='V',w_grid_loc='W',
491 """!A three-dimensional lagrangian particle tracker. The velocity fields must be four dimensional (three spatial, one temporal) and have units of m/s.
492 It should work to track particles forwards or backwards in time (set delta_t <0 for backwards in time). But, be warned, backwards in time hasn't been thoroughly tested yet.
494 Because this is a very large amount of data, the fields are passed as netcdffile handles.
497 * ?_netcdf_filename = name of the netcdf file with ?'s data in it.
498 * start? = intial value for x, y, z, or t.
499 * t = vector of time levels that are contained in the velocity data.
500 * grid_object is m.grid if you followed the standard naming conventions.
501 * ?_netcdf_variable = name of the "?" variable field in the netcdf file.
502 * t_max = length of time to track particles for, in seconds. This is always positive
503 * delta_t = timestep for particle tracking algorithm, in seconds. This can be positive or negative.
504 * ?_grid_loc = where the field "?" is located on the C-grid. Possibles options are, U, V, W, T and Zeta.
505 * ?_bias_field = bias to add to that velocity field omponent. If set to -mean(velocity component), then only the time varying portion of that field will be used.
508 if u_grid_loc ==
'U':
509 x_u = grid_object['Xp1'][:]
510 y_u = grid_object[
'Y'][:]
511 z_u = grid_object[
'Z'][:]
512 elif u_grid_loc ==
'V':
513 x_u = grid_object[
'X'][:]
514 y_u = grid_object[
'Yp1'][:]
515 z_u = grid_object[
'Z'][:]
516 elif u_grid_loc ==
'W':
517 x_u = grid_object[
'X'][:]
518 y_u = grid_object[
'Y'][:]
519 z_u = grid_object[
'Zl'][:]
520 elif u_grid_loc ==
'T':
521 x_u = grid_object[
'X'][:]
522 y_u = grid_object[
'Y'][:]
523 z_u = grid_object[
'Z'][:]
524 elif u_grid_loc ==
'Zeta':
525 x_u = grid_object[
'Xp1'][:]
526 y_u = grid_object[
'Yp1'][:]
527 z_u = grid_object[
'Z'][:]
529 print 'u_grid_loc not set correctly. Possible options are: U,V,W,T, and Zeta'
532 if v_grid_loc ==
'U':
533 x_v = grid_object['Xp1'][:]
534 y_v = grid_object[
'Y'][:]
535 z_v = grid_object[
'Z'][:]
536 elif v_grid_loc ==
'V':
537 x_v = grid_object[
'X'][:]
538 y_v = grid_object[
'Yp1'][:]
539 z_v = grid_object[
'Z'][:]
540 elif v_grid_loc ==
'W':
541 x_v = grid_object[
'X'][:]
542 y_v = grid_object[
'Y'][:]
543 z_v = grid_object[
'Zl'][:]
544 elif v_grid_loc ==
'T':
545 x_v = grid_object[
'X'][:]
546 y_v = grid_object[
'Y'][:]
547 z_v = grid_object[
'Z'][:]
548 elif v_grid_loc ==
'Zeta':
549 x_v = grid_object[
'Xp1'][:]
550 y_v = grid_object[
'Yp1'][:]
551 z_v = grid_object[
'Z'][:]
553 print 'v_grid_loc not set correctly. Possible options are: U,V,W,T, and Zeta'
556 if w_grid_loc ==
'U':
557 x_w = grid_object['Xp1'][:]
558 y_w = grid_object[
'Y'][:]
559 z_w = grid_object[
'Z'][:]
560 elif w_grid_loc ==
'V':
561 x_w = grid_object[
'X'][:]
562 y_w = grid_object[
'Yp1'][:]
563 z_w = grid_object[
'Z'][:]
564 elif w_grid_loc ==
'W':
565 x_w = grid_object[
'X'][:]
566 y_w = grid_object[
'Y'][:]
567 z_w = grid_object[
'Zl'][:]
568 elif w_grid_loc ==
'T':
569 x_w = grid_object[
'X'][:]
570 y_w = grid_object[
'Y'][:]
571 z_w = grid_object[
'Z'][:]
572 elif w_grid_loc ==
'Zeta':
573 x_w = grid_object[
'Xp1'][:]
574 y_w = grid_object[
'Yp1'][:]
575 z_w = grid_object[
'Z'][:]
577 print 'w_grid_loc not set correctly. Possible options are: U,V,W,T, and Zeta'
594 if u_bias_field
is None:
595 u_bias_field = np.zeros_like(grid_object[
'wet_mask_U'][:])
596 if v_bias_field
is None:
597 v_bias_field = np.zeros_like(grid_object[
'wet_mask_V'][:])
598 if w_bias_field
is None:
599 w_bias_field = np.zeros_like(grid_object[
'wet_mask_W'][:])
601 x_stream = np.ones((int(np.fabs(t_max/delta_t))+2))*startx
602 y_stream = np.ones((int(np.fabs(t_max/delta_t))+2))*starty
603 z_stream = np.ones((int(np.fabs(t_max/delta_t))+2))*startz
604 t_stream = np.ones((int(np.fabs(t_max/delta_t))+2))*startt
613 u_netcdf_filehandle = netCDF4.Dataset(u_netcdf_filename)
614 v_netcdf_filehandle = netCDF4.Dataset(v_netcdf_filename)
615 w_netcdf_filehandle = netCDF4.Dataset(w_netcdf_filename)
617 t_index = np.searchsorted(t,t_RK)
618 t_index_new = np.searchsorted(t,t_RK)
620 raise ValueError(
'Given time value is outside the given velocity fields - too small')
621 elif t_index == len_t:
622 raise ValueError(
'Given time value is outside the given velocity fields - too big')
628 x_RK,y_RK,z_RK,t_index,
629 len_x_u,len_y_u,len_z_u,len_t,
630 u_netcdf_filehandle,u_netcdf_variable,u_bias_field)
631 u_field,x_index_u_new,y_index_u_new,z_index_u_new =
indices_and_field(x_u,y_u,z_u,
632 x_RK,y_RK,z_RK,t_index,
633 len_x_u,len_y_u,len_z_u,len_t,
634 u_netcdf_filehandle,u_netcdf_variable,u_bias_field)
637 x_RK,y_RK,z_RK,t_index,
638 len_x_v,len_y_v,len_z_v,len_t,
639 v_netcdf_filehandle,v_netcdf_variable,v_bias_field)
640 v_field,x_index_v_new,y_index_v_new,z_index_v_new =
indices_and_field(x_v,y_v,z_v,
641 x_RK,y_RK,z_RK,t_index,
642 len_x_v,len_y_v,len_z_v,len_t,
643 v_netcdf_filehandle,v_netcdf_variable,v_bias_field)
647 x_RK,y_RK,z_RK,t_index,
648 len_x_w,len_y_w,len_z_w,len_t,
649 w_netcdf_filehandle,w_netcdf_variable,w_bias_field)
650 w_field,x_index_w_new,y_index_w_new,z_index_w_new =
indices_and_field(x_w,y_w,z_w,
651 x_RK,y_RK,z_RK,t_index,
652 len_x_w,len_y_w,len_z_w,len_t,
653 w_netcdf_filehandle,w_netcdf_variable,w_bias_field)
657 deg_per_m = np.array([1,1])
660 while i < np.fabs(t_max/delta_t):
663 if grid_object[
'grid_type']==
'polar':
665 deg_per_m = np.array([1./(1852.*60.),np.cos(starty*np.pi/180.)/(1852.*60.)])
668 if (y_index_u_new==y_index_u
and
669 x_index_u_new==x_index_u
and
670 z_index_u_new==z_index_u
and
672 y_index_v_new==y_index_v
and
673 x_index_v_new==x_index_v
and
674 z_index_v_new==z_index_v
and
676 y_index_w_new==y_index_w
and
677 x_index_w_new==x_index_w
and
678 z_index_w_new==z_index_w
and
680 t_index_new == t_index):
685 t_index = np.searchsorted(t,t_RK)
687 raise ValueError(
'Given time value is outside the given velocity fields - too small')
688 elif t_index == len_t:
689 raise ValueError(
'Given time value is outside the given velocity fields - too big')
695 x_RK,y_RK,z_RK,t_index,
696 len_x_u,len_y_u,len_z_u,len_t,
697 u_netcdf_filehandle,u_netcdf_variable,u_bias_field)
700 x_RK,y_RK,z_RK,t_index,
701 len_x_v,len_y_v,len_z_v,len_t,
702 v_netcdf_filehandle,v_netcdf_variable,v_bias_field)
706 x_RK,y_RK,z_RK,t_index,
707 len_x_w,len_y_w,len_z_w,len_t,
708 w_netcdf_filehandle,w_netcdf_variable,w_bias_field)
716 len_x_u,len_y_u,len_z_u,len_t,
717 x_index_u,y_index_u,z_index_u,t_index)
720 x_v,y_v,z_v,t,len_x_v,len_y_v,len_z_v,len_t,
721 x_index_v,y_index_v,z_index_v,t_index)
724 x_w,y_w,z_w,t,len_x_w,len_y_w,len_z_w,len_t,
725 x_index_w,y_index_w,z_index_w,t_index)
726 u_loc = u_loc*deg_per_m[1]
727 v_loc = v_loc*deg_per_m[0]
732 u_loc1 =
quadralinear_interp(x_RK + 0.5*dx1,y_RK + 0.5*dy1,z_RK + 0.5*dz1,t_RK + 0.5*delta_t,
734 x_u,y_u,z_u,t,len_x_u,len_y_u,len_z_u,len_t,
735 x_index_u,y_index_u,z_index_u,t_index)
736 v_loc1 =
quadralinear_interp(x_RK + 0.5*dx1,y_RK + 0.5*dy1,z_RK + 0.5*dz1,t_RK + 0.5*delta_t,
738 x_v,y_v,z_v,t,len_x_v,len_y_v,len_z_v,len_t,
739 x_index_v,y_index_v,z_index_v,t_index)
740 w_loc1 =
quadralinear_interp(x_RK + 0.5*dx1,y_RK + 0.5*dy1,z_RK + 0.5*dz1,t_RK + 0.5*delta_t,
742 x_w,y_w,z_w,t,len_x_w,len_y_w,len_z_w,len_t,
743 x_index_w,y_index_w,z_index_w,t_index)
744 u_loc1 = u_loc1*deg_per_m[1]
745 v_loc1 = v_loc1*deg_per_m[0]
750 u_loc2 =
quadralinear_interp(x_RK + 0.5*dx2,y_RK + 0.5*dy2,z_RK + 0.5*dz2,t_RK + 0.5*delta_t,
752 x_u,y_u,z_u,t,len_x_u,len_y_u,len_z_u,len_t,
753 x_index_u,y_index_u,z_index_u,t_index)
754 v_loc2 =
quadralinear_interp(x_RK + 0.5*dx2,y_RK + 0.5*dy2,z_RK + 0.5*dz2,t_RK + 0.5*delta_t,
756 x_v,y_v,z_v,t,len_x_v,len_y_v,len_z_v,len_t,
757 x_index_v,y_index_v,z_index_v,t_index)
758 w_loc2 =
quadralinear_interp(x_RK + 0.5*dx2,y_RK + 0.5*dy2,z_RK + 0.5*dz2,t_RK + 0.5*delta_t,
760 x_w,y_w,z_w,t,len_x_w,len_y_w,len_z_w,len_t,
761 x_index_w,y_index_w,z_index_w,t_index)
762 u_loc2 = u_loc2*deg_per_m[1]
763 v_loc2 = v_loc2*deg_per_m[0]
770 x_u,y_u,z_u,t,len_x_u,len_y_u,len_z_u,len_t,
771 x_index_u,y_index_u,z_index_u,t_index)
774 x_v,y_v,z_v,t,len_x_v,len_y_v,len_z_v,len_t,
775 x_index_v,y_index_v,z_index_v,t_index)
778 x_w,y_w,z_w,t,len_x_w,len_y_w,len_z_w,len_t,
779 x_index_w,y_index_w,z_index_w,t_index)
780 u_loc3 = u_loc3*deg_per_m[1]
781 v_loc3 = v_loc3*deg_per_m[0]
787 x_RK = x_RK + (dx1 + 2*dx2 + 2*dx3 + dx4)/6
788 y_RK = y_RK + (dy1 + 2*dy2 + 2*dy3 + dy4)/6
789 z_RK = z_RK + (dz1 + 2*dz2 + 2*dz3 + dz4)/6
798 t_index_new = np.searchsorted(t,t_RK)
799 x_index_w_new = np.searchsorted(x_w,x_RK)
800 y_index_w_new = np.searchsorted(y_w,y_RK)
802 z_index_w_new = np.searchsorted(-z_w,-z_RK)
804 z_index_w_new = np.searchsorted(z_w,z_RK)
806 x_index_v_new = np.searchsorted(x_v,x_RK)
807 y_index_v_new = np.searchsorted(y_v,y_RK)
809 z_index_v_new = np.searchsorted(-z_v,-z_RK)
811 z_index_v_new = np.searchsorted(z_v,z_RK)
813 x_index_u_new = np.searchsorted(x_u,x_RK)
814 y_index_u_new = np.searchsorted(y_u,y_RK)
816 z_index_u_new = np.searchsorted(-z_u,-z_RK)
818 z_index_u_new = np.searchsorted(z_u,z_RK)
821 u_netcdf_filehandle.close()
822 v_netcdf_filehandle.close()
823 w_netcdf_filehandle.close()
825 return x_stream,y_stream,z_stream,t_stream
830 def pathlines_many(u_netcdf_filename,v_netcdf_filename,w_netcdf_filename,
831 startx,starty,startz,startt,
835 u_netcdf_variable=
'UVEL',
836 v_netcdf_variable=
'VVEL',
837 w_netcdf_variable=
'WVEL',
838 u_grid_loc=
'U',v_grid_loc='V',w_grid_loc='W',
842 """!A three-dimensional lagrangian particle tracker designed for tracking many particles at once. If you're tracking fewer than O(10) - use the pathlines function.
844 The velocity fields must be four dimensional (three spatial, one temporal) and have units of m/s.
845 It should work to track particles forwards or backwards in time (set delta_t <0 for backwards in time). But, be warned, backwards in time hasn't been thoroughly tested yet.
847 Because this is a very large amount of data, the fields are passed as netcdffile handles.
851 * x_stream, y_stream, z_stream - all with dimensions (particle,time_level)
852 * t_stream - with dimensions (time_level)
854 ## The variables are:
855 * ?_netcdf_filename = name of the netcdf file with ?'s data in it.
856 * start? = (nx1) arrays of initial values for x, y, or z.
857 * startt = start time
858 * t = vector of time levels that are contained in the velocity data.
859 * grid_object is m.grid if you followed the standard naming conventions.
860 * ?_netcdf_variable = name of the "?" variable field in the netcdf file.
861 * t_max = length of time to track particles for, in seconds. This is always positive
862 * delta_t = timestep for particle tracking algorithm, in seconds. This can be positive or negative.
863 * ?_grid_loc = where the field "?" is located on the C-grid. Possibles options are, U, V, W, T and Zeta.
864 * ?_bias_field = bias to add to that velocity field component. If set to -mean(velocity component), then only the time varying portion of that field will be used.
867 if u_grid_loc ==
'U':
868 x_u = grid_object['Xp1'][:]
869 y_u = grid_object[
'Y'][:]
870 z_u = grid_object[
'Z'][:]
871 elif u_grid_loc ==
'V':
872 x_u = grid_object[
'X'][:]
873 y_u = grid_object[
'Yp1'][:]
874 z_u = grid_object[
'Z'][:]
875 elif u_grid_loc ==
'W':
876 x_u = grid_object[
'X'][:]
877 y_u = grid_object[
'Y'][:]
878 z_u = grid_object[
'Zl'][:]
879 elif u_grid_loc ==
'T':
880 x_u = grid_object[
'X'][:]
881 y_u = grid_object[
'Y'][:]
882 z_u = grid_object[
'Z'][:]
883 elif u_grid_loc ==
'Zeta':
884 x_u = grid_object[
'Xp1'][:]
885 y_u = grid_object[
'Yp1'][:]
886 z_u = grid_object[
'Z'][:]
888 print 'u_grid_loc not set correctly. Possible options are: U,V,W,T, and Zeta'
891 if v_grid_loc ==
'U':
892 x_v = grid_object['Xp1'][:]
893 y_v = grid_object[
'Y'][:]
894 z_v = grid_object[
'Z'][:]
895 elif v_grid_loc ==
'V':
896 x_v = grid_object[
'X'][:]
897 y_v = grid_object[
'Yp1'][:]
898 z_v = grid_object[
'Z'][:]
899 elif v_grid_loc ==
'W':
900 x_v = grid_object[
'X'][:]
901 y_v = grid_object[
'Y'][:]
902 z_v = grid_object[
'Zl'][:]
903 elif v_grid_loc ==
'T':
904 x_v = grid_object[
'X'][:]
905 y_v = grid_object[
'Y'][:]
906 z_v = grid_object[
'Z'][:]
907 elif v_grid_loc ==
'Zeta':
908 x_v = grid_object[
'Xp1'][:]
909 y_v = grid_object[
'Yp1'][:]
910 z_v = grid_object[
'Z'][:]
912 print 'v_grid_loc not set correctly. Possible options are: U,V,W,T, and Zeta'
915 if w_grid_loc ==
'U':
916 x_w = grid_object['Xp1'][:]
917 y_w = grid_object[
'Y'][:]
918 z_w = grid_object[
'Z'][:]
919 elif w_grid_loc ==
'V':
920 x_w = grid_object[
'X'][:]
921 y_w = grid_object[
'Yp1'][:]
922 z_w = grid_object[
'Z'][:]
923 elif w_grid_loc ==
'W':
924 x_w = grid_object[
'X'][:]
925 y_w = grid_object[
'Y'][:]
926 z_w = grid_object[
'Zl'][:]
927 elif w_grid_loc ==
'T':
928 x_w = grid_object[
'X'][:]
929 y_w = grid_object[
'Y'][:]
930 z_w = grid_object[
'Z'][:]
931 elif w_grid_loc ==
'Zeta':
932 x_w = grid_object[
'Xp1'][:]
933 y_w = grid_object[
'Yp1'][:]
934 z_w = grid_object[
'Z'][:]
936 print 'w_grid_loc not set correctly. Possible options are: U,V,W,T, and Zeta'
953 if u_bias_field
is None:
954 u_bias_field = np.zeros_like(grid_object[
'wet_mask_U'][:])
955 if v_bias_field
is None:
956 v_bias_field = np.zeros_like(grid_object[
'wet_mask_V'][:])
957 if w_bias_field
is None:
958 w_bias_field = np.zeros_like(grid_object[
'wet_mask_W'][1:,...])
960 x_stream = np.ones((len(startx),int(np.fabs(t_max/delta_t))+2))*startx[:,np.newaxis]
961 y_stream = np.ones((len(startx),int(np.fabs(t_max/delta_t))+2))*starty[:,np.newaxis]
962 z_stream = np.ones((len(startx),int(np.fabs(t_max/delta_t))+2))*startz[:,np.newaxis]
963 t_stream = np.ones((int(np.fabs(t_max/delta_t))+2))*startt
972 u_netcdf_filehandle = netCDF4.Dataset(u_netcdf_filename)
973 v_netcdf_filehandle = netCDF4.Dataset(v_netcdf_filename)
974 w_netcdf_filehandle = netCDF4.Dataset(w_netcdf_filename)
976 t_index = np.searchsorted(t,t_RK)
977 t_index_new = np.searchsorted(t,t_RK)
979 raise ValueError(
'Given time value is outside the given velocity fields - too small')
980 elif t_index == len_t:
981 raise ValueError(
'Given time value is outside the given velocity fields - too big')
984 u_field_before = u_netcdf_filehandle.variables[u_netcdf_variable][t_index,...]
985 u_field_after = u_netcdf_filehandle.variables[u_netcdf_variable][t_index+1,...]
986 u_field = (u_field_before + ((u_field_before - u_field_after)*
987 (t_RK - t[t_index])/(t[t_index+1] - t[t_index])) -
990 v_field_before = v_netcdf_filehandle.variables[v_netcdf_variable][t_index,...]
991 v_field_after = v_netcdf_filehandle.variables[v_netcdf_variable][t_index+1,...]
992 v_field = (v_field_before + ((v_field_before - v_field_after)*
993 (t_RK - t[t_index])/(t[t_index+1] - t[t_index])) -
996 w_field_before = w_netcdf_filehandle.variables[w_netcdf_variable][t_index,...]
997 w_field_after = w_netcdf_filehandle.variables[w_netcdf_variable][t_index+1,...]
998 w_field = (w_field_before + ((w_field_before - w_field_after)*
999 (t_RK - t[t_index])/(t[t_index+1] - t[t_index])) -
1004 deg_per_m = np.ones((len(startx),2),dtype=float)
1005 if grid_object[
'grid_type']==
'polar':
1006 deg_per_m[:,0] = np.ones_like(startx)/(1852.*60.)
1009 while i < np.fabs(t_max/delta_t):
1012 if grid_object[
'grid_type']==
'polar':
1014 deg_per_m[:,1] = np.cos(starty*np.pi/180.)/(1852.*60.)
1017 if (t_index_new == t_index):
1021 t_index = np.searchsorted(t,t_RK)
1023 raise ValueError(
'Given time value is outside the given velocity fields - too small')
1024 elif t_index == len_t:
1025 raise ValueError(
'Given time value is outside the given velocity fields - too big')
1028 u_field_before = u_netcdf_filehandle.variables[u_netcdf_variable][t_index,...]
1029 u_field_after = u_netcdf_filehandle.variables[u_netcdf_variable][t_index+1,...]
1030 u_field = (u_field_before + ((u_field_before - u_field_after)*
1031 (t_RK - t[t_index])/(t[t_index+1] - t[t_index])) - u_bias_field)
1033 v_field_before = v_netcdf_filehandle.variables[v_netcdf_variable][t_index,...]
1034 v_field_after = v_netcdf_filehandle.variables[v_netcdf_variable][t_index+1,...]
1035 v_field = (v_field_before + ((v_field_before - v_field_after)*
1036 (t_RK - t[t_index])/(t[t_index+1] - t[t_index])) - v_bias_field)
1038 w_field_before = w_netcdf_filehandle.variables[w_netcdf_variable][t_index,...]
1039 w_field_after = w_netcdf_filehandle.variables[w_netcdf_variable][t_index+1,...]
1040 w_field = (w_field_before + ((w_field_before - w_field_after)*
1041 (t_RK - t[t_index])/(t[t_index+1] - t[t_index])) - w_bias_field)
1044 u_loc = np.ones_like(startx)
1045 v_loc = np.ones_like(startx)
1046 w_loc = np.ones_like(startx)
1052 u_loc = u_loc*deg_per_m[:,1]
1053 v_loc = v_loc*deg_per_m[:,0]
1059 u_loc1 = np.ones_like(startx)
1060 v_loc1 = np.ones_like(startx)
1061 w_loc1 = np.ones_like(startx)
1064 u_field,x_u,y_u,z_u,len_x_u,len_y_u,len_z_u)
1066 v_field,x_v,y_v,z_v,len_x_v,len_y_v,len_z_v)
1068 w_field,x_w,y_w,z_w,len_x_w,len_y_w,len_z_w)
1069 u_loc1 = u_loc1*deg_per_m[:,1]
1070 v_loc1 = v_loc1*deg_per_m[:,0]
1071 dx2 = delta_t*u_loc1
1072 dy2 = delta_t*v_loc1
1073 dz2 = delta_t*w_loc1
1075 u_loc2 = np.ones_like(startx)
1076 v_loc2 = np.ones_like(startx)
1077 w_loc2 = np.ones_like(startx)
1079 u_field,x_u,y_u,z_u,len_x_u,len_y_u,len_z_u)
1081 v_field,x_v,y_v,z_v,len_x_v,len_y_v,len_z_v)
1083 w_field,x_w,y_w,z_w,len_x_w,len_y_w,len_z_w)
1085 u_loc2 = u_loc2*deg_per_m[:,1]
1086 v_loc2 = v_loc2*deg_per_m[:,0]
1087 dx3 = delta_t*u_loc2
1088 dy3 = delta_t*v_loc2
1089 dz3 = delta_t*w_loc2
1091 u_loc3 = np.ones_like(startx)
1092 v_loc3 = np.ones_like(startx)
1093 w_loc3 = np.ones_like(startx)
1095 u_field,x_u,y_u,z_u,len_x_u,len_y_u,len_z_u)
1097 v_field,x_v,y_v,z_v,len_x_v,len_y_v,len_z_v)
1099 w_field,x_w,y_w,z_w,len_x_w,len_y_w,len_z_w)
1101 u_loc3 = u_loc3*deg_per_m[:,1]
1102 v_loc3 = v_loc3*deg_per_m[:,0]
1103 dx4 = delta_t*u_loc3
1104 dy4 = delta_t*v_loc3
1105 dz4 = delta_t*w_loc3
1108 x_RK = x_RK + (dx1 + 2*dx2 + 2*dx3 + dx4)/6
1109 y_RK = y_RK + (dy1 + 2*dy2 + 2*dy3 + dy4)/6
1110 z_RK = z_RK + (dz1 + 2*dz2 + 2*dz3 + dz4)/6
1114 x_stream[:,i] = x_RK
1115 y_stream[:,i] = y_RK
1116 z_stream[:,i] = z_RK
1119 t_index_new = np.searchsorted(t,t_RK)
1122 u_netcdf_filehandle.close()
1123 v_netcdf_filehandle.close()
1124 w_netcdf_filehandle.close()
1126 return x_stream,y_stream,z_stream,t_stream
1136 t_tracking,delta_t, trace_length,
1137 u_netcdf_variable=
'UVEL',
1138 v_netcdf_variable=
'VVEL',
1139 w_netcdf_variable=
'WVEL',
1140 u_grid_loc=
'U',v_grid_loc='V',w_grid_loc='W',
1144 """!A three-dimensional lagrangian particle tracker designed for tracking many particles at once. If you're tracking fewer than O(10) - use the streaklines function.
1146 The velocity fields must be four dimensional (three spatial, one temporal) and have units of m/s.
1147 It should work to track particles forwards or backwards in time (set delta_t <0 for backwards in time). But, be warned, backwards in time hasn't been thoroughly tested yet.
1149 Because this is a very large amount of data, the fields are passed as netcdffile handles.
1153 * x_stream, y_stream, z_stream - all with dimensions (particle,time_level)
1154 * t_stream - with dimensions (time_level)
1156 ## The variables are:
1157 * ?_netcdf_filename = name of the netcdf file with ?'s data in it.
1158 * n_particles = number of particles to track
1159 * startt = start time
1160 * t = vector of time levels that are contained in the velocity data.
1161 * grid_object is m.grid if you followed the standard naming conventions.
1162 * ?_netcdf_variable = name of the "?" variable field in the netcdf file.
1163 * t_tracking = length of time to track particles for, in seconds. This is always positive
1164 * delta_t = timestep for particle tracking algorithm, in seconds. This can be positive or negative.
1165 * trace_length = length of time for each individual trace
1166 * ?_grid_loc = where the field "?" is located on the C-grid. Possibles options are, U, V, W, T and Zeta.
1167 * ?_bias_field = bias to add to that velocity field component. If set to -mean(velocity component), then only the time varying portion of that field will be used.
1170 if u_grid_loc ==
'U':
1171 x_u = grid_object['Xp1'][:]
1172 y_u = grid_object[
'Y'][:]
1173 z_u = grid_object[
'Z'][:]
1174 elif u_grid_loc ==
'V':
1175 x_u = grid_object[
'X'][:]
1176 y_u = grid_object[
'Yp1'][:]
1177 z_u = grid_object[
'Z'][:]
1178 elif u_grid_loc ==
'W':
1179 x_u = grid_object[
'X'][:]
1180 y_u = grid_object[
'Y'][:]
1181 z_u = grid_object[
'Zl'][:]
1182 elif u_grid_loc ==
'T':
1183 x_u = grid_object[
'X'][:]
1184 y_u = grid_object[
'Y'][:]
1185 z_u = grid_object[
'Z'][:]
1186 elif u_grid_loc ==
'Zeta':
1187 x_u = grid_object[
'Xp1'][:]
1188 y_u = grid_object[
'Yp1'][:]
1189 z_u = grid_object[
'Z'][:]
1191 print 'u_grid_loc not set correctly. Possible options are: U,V,W,T, and Zeta'
1194 if v_grid_loc ==
'U':
1195 x_v = grid_object['Xp1'][:]
1196 y_v = grid_object[
'Y'][:]
1197 z_v = grid_object[
'Z'][:]
1198 elif v_grid_loc ==
'V':
1199 x_v = grid_object[
'X'][:]
1200 y_v = grid_object[
'Yp1'][:]
1201 z_v = grid_object[
'Z'][:]
1202 elif v_grid_loc ==
'W':
1203 x_v = grid_object[
'X'][:]
1204 y_v = grid_object[
'Y'][:]
1205 z_v = grid_object[
'Zl'][:]
1206 elif v_grid_loc ==
'T':
1207 x_v = grid_object[
'X'][:]
1208 y_v = grid_object[
'Y'][:]
1209 z_v = grid_object[
'Z'][:]
1210 elif v_grid_loc ==
'Zeta':
1211 x_v = grid_object[
'Xp1'][:]
1212 y_v = grid_object[
'Yp1'][:]
1213 z_v = grid_object[
'Z'][:]
1215 print 'v_grid_loc not set correctly. Possible options are: U,V,W,T, and Zeta'
1218 if w_grid_loc ==
'U':
1219 x_w = grid_object['Xp1'][:]
1220 y_w = grid_object[
'Y'][:]
1221 z_w = grid_object[
'Z'][:]
1222 elif w_grid_loc ==
'V':
1223 x_w = grid_object[
'X'][:]
1224 y_w = grid_object[
'Yp1'][:]
1225 z_w = grid_object[
'Z'][:]
1226 elif w_grid_loc ==
'W':
1227 x_w = grid_object[
'X'][:]
1228 y_w = grid_object[
'Y'][:]
1229 z_w = grid_object[
'Zl'][:]
1230 elif w_grid_loc ==
'T':
1231 x_w = grid_object[
'X'][:]
1232 y_w = grid_object[
'Y'][:]
1233 z_w = grid_object[
'Z'][:]
1234 elif w_grid_loc ==
'Zeta':
1235 x_w = grid_object[
'Xp1'][:]
1236 y_w = grid_object[
'Yp1'][:]
1237 z_w = grid_object[
'Z'][:]
1239 print 'w_grid_loc not set correctly. Possible options are: U,V,W,T, and Zeta'
1256 if u_bias_field
is None:
1257 u_bias_field = np.zeros_like(grid_object[
'wet_mask_U'][:])
1258 if v_bias_field
is None:
1259 v_bias_field = np.zeros_like(grid_object[
'wet_mask_V'][:])
1260 if w_bias_field
is None:
1261 w_bias_field = np.zeros_like(grid_object[
'wet_mask_W'][1:,...])
1264 steps_per_trace = int(trace_length/delta_t)
1265 time_steps_until_jitter = np.random.randint(steps_per_trace, size=n_particles)
1267 startx = (np.random.rand(n_particles)*
1268 (np.max(grid_object[
'X'][:]) - np.min(grid_object[
'X'][:]))) + np.min(grid_object[
'X'][:])
1269 starty = (np.random.rand(n_particles)*
1270 (np.max(grid_object[
'Y'][:]) - np.min(grid_object[
'Y'][:]))) + np.min(grid_object[
'Y'][:])
1271 startz = (np.random.rand(n_particles)*grid_object[
'Z'][1])
1274 x_stream = np.ones((len(startx),int(np.fabs(t_tracking/delta_t))+2))*startx[:,np.newaxis]
1275 y_stream = np.ones((len(startx),int(np.fabs(t_tracking/delta_t))+2))*starty[:,np.newaxis]
1276 z_stream = np.ones((len(startx),int(np.fabs(t_tracking/delta_t))+2))*startz[:,np.newaxis]
1277 t_stream = np.ones((int(np.fabs(t_tracking/delta_t))+2))*startt
1286 u_netcdf_filehandle = netCDF4.Dataset(u_netcdf_filename)
1287 v_netcdf_filehandle = netCDF4.Dataset(v_netcdf_filename)
1288 w_netcdf_filehandle = netCDF4.Dataset(w_netcdf_filename)
1290 t_index = np.searchsorted(t,t_RK)
1291 t_index_new = np.searchsorted(t,t_RK)
1293 raise ValueError(
'Given time value is outside the given velocity fields - too small')
1294 elif t_index == len_t:
1295 raise ValueError(
'Given time value is outside the given velocity fields - too big')
1298 u_field_before = u_netcdf_filehandle.variables[u_netcdf_variable][t_index,...]
1299 u_field_after = u_netcdf_filehandle.variables[u_netcdf_variable][t_index+1,...]
1300 u_field = (u_field_before + ((u_field_before - u_field_after)*
1301 (t_RK - t[t_index])/(t[t_index+1] - t[t_index])) -
1304 v_field_before = v_netcdf_filehandle.variables[v_netcdf_variable][t_index,...]
1305 v_field_after = v_netcdf_filehandle.variables[v_netcdf_variable][t_index+1,...]
1306 v_field = (v_field_before + ((v_field_before - v_field_after)*
1307 (t_RK - t[t_index])/(t[t_index+1] - t[t_index])) -
1310 w_field_before = w_netcdf_filehandle.variables[w_netcdf_variable][t_index,...]
1311 w_field_after = w_netcdf_filehandle.variables[w_netcdf_variable][t_index+1,...]
1312 w_field = (w_field_before + ((w_field_before - w_field_after)*
1313 (t_RK - t[t_index])/(t[t_index+1] - t[t_index])) -
1318 deg_per_m = np.ones((len(startx),2),dtype=float)
1319 if grid_object[
'grid_type']==
'polar':
1320 deg_per_m[:,0] = np.ones_like(startx)/(1852.*60.)
1323 while i < np.fabs(t_tracking/delta_t):
1326 if grid_object[
'grid_type']==
'polar':
1328 deg_per_m[:,1] = np.cos(starty*np.pi/180.)/(1852.*60.)
1331 if (t_index_new == t_index):
1335 t_index = np.searchsorted(t,t_RK)
1337 raise ValueError(
'Given time value is outside the given velocity fields - too small')
1338 elif t_index == len_t:
1339 raise ValueError(
'Given time value is outside the given velocity fields - too big')
1342 u_field_before = u_netcdf_filehandle.variables[u_netcdf_variable][t_index,...]
1343 u_field_after = u_netcdf_filehandle.variables[u_netcdf_variable][t_index+1,...]
1344 u_field = (u_field_before + ((u_field_before - u_field_after)*
1345 (t_RK - t[t_index])/(t[t_index+1] - t[t_index])) - u_bias_field)
1347 v_field_before = v_netcdf_filehandle.variables[v_netcdf_variable][t_index,...]
1348 v_field_after = v_netcdf_filehandle.variables[v_netcdf_variable][t_index+1,...]
1349 v_field = (v_field_before + ((v_field_before - v_field_after)*
1350 (t_RK - t[t_index])/(t[t_index+1] - t[t_index])) - v_bias_field)
1352 w_field_before = w_netcdf_filehandle.variables[w_netcdf_variable][t_index,...]
1353 w_field_after = w_netcdf_filehandle.variables[w_netcdf_variable][t_index+1,...]
1354 w_field = (w_field_before + ((w_field_before - w_field_after)*
1355 (t_RK - t[t_index])/(t[t_index+1] - t[t_index])) - w_bias_field)
1358 for particle
in xrange(0,n_particles):
1359 if time_steps_until_jitter[particle] <= 0:
1360 x_RK[particle] = (np.random.rand(1)*
1361 (np.max(grid_object[
'X'][:]) - np.min(grid_object[
'X'][:]))) + np.min(grid_object[
'X'][:])
1362 y_RK[particle] = (np.random.rand(1)*
1363 (np.max(grid_object[
'Y'][:]) - np.min(grid_object[
'Y'][:]))) + np.min(grid_object[
'Y'][:])
1364 z_RK[particle] = grid_object[
'Z'][1]
1367 time_steps_until_jitter[particle] = steps_per_trace
1371 u_loc = np.ones_like(startx)
1372 v_loc = np.ones_like(startx)
1373 w_loc = np.ones_like(startx)
1379 u_loc = u_loc*deg_per_m[:,1]
1380 v_loc = v_loc*deg_per_m[:,0]
1386 u_loc1 = np.ones_like(startx)
1387 v_loc1 = np.ones_like(startx)
1388 w_loc1 = np.ones_like(startx)
1391 u_field,x_u,y_u,z_u,len_x_u,len_y_u,len_z_u)
1393 v_field,x_v,y_v,z_v,len_x_v,len_y_v,len_z_v)
1395 w_field,x_w,y_w,z_w,len_x_w,len_y_w,len_z_w)
1396 u_loc1 = u_loc1*deg_per_m[:,1]
1397 v_loc1 = v_loc1*deg_per_m[:,0]
1398 dx2 = delta_t*u_loc1
1399 dy2 = delta_t*v_loc1
1400 dz2 = delta_t*w_loc1
1402 u_loc2 = np.ones_like(startx)
1403 v_loc2 = np.ones_like(startx)
1404 w_loc2 = np.ones_like(startx)
1406 u_field,x_u,y_u,z_u,len_x_u,len_y_u,len_z_u)
1408 v_field,x_v,y_v,z_v,len_x_v,len_y_v,len_z_v)
1410 w_field,x_w,y_w,z_w,len_x_w,len_y_w,len_z_w)
1412 u_loc2 = u_loc2*deg_per_m[:,1]
1413 v_loc2 = v_loc2*deg_per_m[:,0]
1414 dx3 = delta_t*u_loc2
1415 dy3 = delta_t*v_loc2
1416 dz3 = delta_t*w_loc2
1418 u_loc3 = np.ones_like(startx)
1419 v_loc3 = np.ones_like(startx)
1420 w_loc3 = np.ones_like(startx)
1422 u_field,x_u,y_u,z_u,len_x_u,len_y_u,len_z_u)
1424 v_field,x_v,y_v,z_v,len_x_v,len_y_v,len_z_v)
1426 w_field,x_w,y_w,z_w,len_x_w,len_y_w,len_z_w)
1428 u_loc3 = u_loc3*deg_per_m[:,1]
1429 v_loc3 = v_loc3*deg_per_m[:,0]
1430 dx4 = delta_t*u_loc3
1431 dy4 = delta_t*v_loc3
1432 dz4 = delta_t*w_loc3
1435 x_RK = x_RK + (dx1 + 2*dx2 + 2*dx3 + dx4)/6
1436 y_RK = y_RK + (dy1 + 2*dy2 + 2*dy3 + dy4)/6
1437 z_RK = z_RK + (dz1 + 2*dz2 + 2*dz3 + dz4)/6
1440 time_steps_until_jitter = time_steps_until_jitter - 1
1442 x_stream[:,i] = x_RK
1443 y_stream[:,i] = y_RK
1444 z_stream[:,i] = z_RK
1447 t_index_new = np.searchsorted(t,t_RK)
1450 u_netcdf_filehandle.close()
1451 v_netcdf_filehandle.close()
1452 w_netcdf_filehandle.close()
1454 return x_stream,y_stream,z_stream,t_stream
1460 def numeric_GLM_xyzt(u_netcdf_filename,v_netcdf_filename,w_netcdf_filename,
1462 startx,starty,startz,startt,
1463 total_time,timestep,
1468 u_netcdf_variable=
'UVEL',
1469 v_netcdf_variable=
'VVEL',
1470 w_netcdf_variable=
'WVEL',
1471 u_grid_loc=
'U',v_grid_loc='V',w_grid_loc='W',
1475 """!A three-dimensional lagrangian particle tracker designed for tracking many particles at once as a method of estimating Generalised Lagrangian-Mean velocities.
1477 The algorithm is a little slow because it spends time checking that the particles are within a given distance of the centre of mass, that they are in the fluid not the bathymetry and that they are below the surface. This means that the cloud of particles should remain within the fluid and not get trapped by the bathymetry.
1479 The velocity fields must be four dimensional (three spatial, one temporal) and have units of m/s.
1480 It should work to track particles forwards or backwards in time (set timestep <0 for backwards in time). But, be warned, backwards in time hasn't been thoroughly tested yet.
1482 Because this is a very large amount of data, the fields are passed as netcdffile handles.
1486 * x_stream, y_stream, z_stream - all with dimensions (particle,time_level)
1487 * t_stream - with dimensions (time_level)
1488 * com_stream - with dimensions (time_level)
1490 ## The variables are:
1491 * ?_netcdf_filename = name of the netcdf file with ?'s data in it.
1492 * n_particles = number of particles to track
1493 * start? = starting value for x, y, z, or time
1494 * total_time = length of time to track particles for, in seconds. This is always positive
1495 * timestep = timestep for particle tracking algorithm, in seconds. This can be positive or negative.
1496 * r_? = radius of sedding ellipsoid in x, y, or z direction
1497 * t = vector of time levels that are contained in the velocity data.
1498 * grid_object is m.grid if you followed the standard naming conventions.
1499 * ?_netcdf_variable = name of the "?" variable field in the netcdf file.
1500 * ?_grid_loc = where the field "?" is located on the C-grid. Possibles options are, U, V, W, T and Zeta.
1501 * ?_bias_field = bias to add to that velocity field component. If set to -mean(velocity component), then only the time varying portion of that field will be used.
1504 if u_grid_loc ==
'U':
1505 x_u = grid_object['Xp1'][:]
1506 y_u = grid_object[
'Y'][:]
1507 z_u = grid_object[
'Z'][:]
1508 elif u_grid_loc ==
'V':
1509 x_u = grid_object[
'X'][:]
1510 y_u = grid_object[
'Yp1'][:]
1511 z_u = grid_object[
'Z'][:]
1512 elif u_grid_loc ==
'W':
1513 x_u = grid_object[
'X'][:]
1514 y_u = grid_object[
'Y'][:]
1515 z_u = grid_object[
'Zl'][:]
1516 elif u_grid_loc ==
'T':
1517 x_u = grid_object[
'X'][:]
1518 y_u = grid_object[
'Y'][:]
1519 z_u = grid_object[
'Z'][:]
1520 elif u_grid_loc ==
'Zeta':
1521 x_u = grid_object[
'Xp1'][:]
1522 y_u = grid_object[
'Yp1'][:]
1523 z_u = grid_object[
'Z'][:]
1525 print 'u_grid_loc not set correctly. Possible options are: U,V,W,T, and Zeta'
1528 if v_grid_loc ==
'U':
1529 x_v = grid_object['Xp1'][:]
1530 y_v = grid_object[
'Y'][:]
1531 z_v = grid_object[
'Z'][:]
1532 elif v_grid_loc ==
'V':
1533 x_v = grid_object[
'X'][:]
1534 y_v = grid_object[
'Yp1'][:]
1535 z_v = grid_object[
'Z'][:]
1536 elif v_grid_loc ==
'W':
1537 x_v = grid_object[
'X'][:]
1538 y_v = grid_object[
'Y'][:]
1539 z_v = grid_object[
'Zl'][:]
1540 elif v_grid_loc ==
'T':
1541 x_v = grid_object[
'X'][:]
1542 y_v = grid_object[
'Y'][:]
1543 z_v = grid_object[
'Z'][:]
1544 elif v_grid_loc ==
'Zeta':
1545 x_v = grid_object[
'Xp1'][:]
1546 y_v = grid_object[
'Yp1'][:]
1547 z_v = grid_object[
'Z'][:]
1549 print 'v_grid_loc not set correctly. Possible options are: U,V,W,T, and Zeta'
1552 if w_grid_loc ==
'U':
1553 x_w = grid_object['Xp1'][:]
1554 y_w = grid_object[
'Y'][:]
1555 z_w = grid_object[
'Z'][:]
1556 elif w_grid_loc ==
'V':
1557 x_w = grid_object[
'X'][:]
1558 y_w = grid_object[
'Yp1'][:]
1559 z_w = grid_object[
'Z'][:]
1560 elif w_grid_loc ==
'W':
1561 x_w = grid_object[
'X'][:]
1562 y_w = grid_object[
'Y'][:]
1563 z_w = grid_object[
'Zl'][:]
1564 elif w_grid_loc ==
'T':
1565 x_w = grid_object[
'X'][:]
1566 y_w = grid_object[
'Y'][:]
1567 z_w = grid_object[
'Z'][:]
1568 elif w_grid_loc ==
'Zeta':
1569 x_w = grid_object[
'Xp1'][:]
1570 y_w = grid_object[
'Yp1'][:]
1571 z_w = grid_object[
'Z'][:]
1573 print 'w_grid_loc not set correctly. Possible options are: U,V,W,T, and Zeta'
1590 if u_bias_field
is None:
1591 u_bias_field = np.zeros_like(grid_object[
'wet_mask_U'][:])
1592 if v_bias_field
is None:
1593 v_bias_field = np.zeros_like(grid_object[
'wet_mask_V'][:])
1594 if w_bias_field
is None:
1595 w_bias_field = np.zeros_like(grid_object[
'wet_mask_W'][1:,...])
1598 ini_x = ((np.random.rand(n_particles)-0.5)*2*r_x + startx)
1599 ini_y = ((np.random.rand(n_particles)-0.5)*2*r_y + starty)
1600 ini_z = ((np.random.rand(n_particles)-0.5)*2*r_z + startz)
1602 x_stream = np.ones((n_particles,int(np.fabs(total_time/timestep))+2))*startx
1603 y_stream = np.ones((n_particles,int(np.fabs(total_time/timestep))+2))*starty
1604 z_stream = np.ones((n_particles,int(np.fabs(total_time/timestep))+2))*startz
1605 t_stream = np.ones((int(np.fabs(total_time/timestep))+2))*startt
1606 com_stream = np.ones((3,int(np.fabs(total_time/timestep))+2))
1618 normed_radius = ( ((ini_x - startx)**2)/(r_x**2) +
1619 ((ini_y - starty)**2)/(r_y**2) +
1620 ((ini_z - startz)**2)/(r_z**2) )
1622 wet_test =
trilinear_interp_arrays(x_RK,y_RK,z_RK,grid_object[
'wet_mask_U'][:],x_u,y_u,z_u,len_x_u,len_y_u,len_z_u)
1624 for particle
in xrange(n_particles):
1625 if (normed_radius[particle] > r_cutoff_factor
or wet_test[particle] < 0.5
or z_RK[particle]*grid_object[
'Z'][2] < 0):
1626 while (normed_radius[particle] > 1
or wet_test[particle] < 0.5
or z_RK[particle]*grid_object[
'Z'][2] < 0):
1627 x_RK[particle] = ((np.random.rand(1)-0.5)*r_x*2 + x_com)
1628 y_RK[particle] = ((np.random.rand(1)-0.5)*r_y*2 + y_com)
1629 z_RK[particle] = ((np.random.rand(1)-0.5)*r_z*2 + z_com)
1630 normed_radius[particle] = ( ((x_RK[particle] - x_com)**2)/(r_x**2) +
1631 ((y_RK[particle] - y_com)**2)/(r_y**2) +
1632 ((z_RK[particle] - z_com)**2)/(r_z**2) )
1633 wet_test[particle] =
trilinear_interp(x_RK[particle],y_RK[particle],z_RK[particle],
1634 grid_object[
'wet_mask_U'][:],x_u,y_u,z_u,len_x_u,len_y_u,len_z_u)
1642 u_netcdf_filehandle = netCDF4.Dataset(u_netcdf_filename)
1643 v_netcdf_filehandle = netCDF4.Dataset(v_netcdf_filename)
1644 w_netcdf_filehandle = netCDF4.Dataset(w_netcdf_filename)
1646 t_index = np.searchsorted(t,t_RK)
1647 t_index_new = np.searchsorted(t,t_RK)
1649 raise ValueError(
'Given time value is outside the given velocity fields - too small')
1650 elif t_index == len_t:
1651 raise ValueError(
'Given time value is outside the given velocity fields - too big')
1654 u_field_before = u_netcdf_filehandle.variables[u_netcdf_variable][t_index,...]
1655 u_field_after = u_netcdf_filehandle.variables[u_netcdf_variable][t_index+1,...]
1656 u_field = (u_field_before + ((u_field_before - u_field_after)*
1657 (t_RK - t[t_index])/(t[t_index+1] - t[t_index])) -
1660 v_field_before = v_netcdf_filehandle.variables[v_netcdf_variable][t_index,...]
1661 v_field_after = v_netcdf_filehandle.variables[v_netcdf_variable][t_index+1,...]
1662 v_field = (v_field_before + ((v_field_before - v_field_after)*
1663 (t_RK - t[t_index])/(t[t_index+1] - t[t_index])) -
1666 w_field_before = w_netcdf_filehandle.variables[w_netcdf_variable][t_index,...]
1667 w_field_after = w_netcdf_filehandle.variables[w_netcdf_variable][t_index+1,...]
1668 w_field = (w_field_before + ((w_field_before - w_field_after)*
1669 (t_RK - t[t_index])/(t[t_index+1] - t[t_index])) -
1674 deg_per_m = np.ones((n_particles,2),dtype=float)
1675 if grid_object[
'grid_type']==
'polar':
1676 deg_per_m[:,0] = np.ones((n_particles))/(1852.*60.)
1679 while i < np.fabs(total_time/timestep):
1682 if grid_object[
'grid_type']==
'polar':
1684 deg_per_m[:,1] = np.cos(np.ones((n_particles))*starty*np.pi/180.)/(1852.*60.)
1687 if (t_index_new == t_index):
1691 t_index = np.searchsorted(t,t_RK)
1693 raise ValueError(
'Given time value is outside the given velocity fields - too small')
1694 elif t_index == len_t:
1695 raise ValueError(
'Given time value is outside the given velocity fields - too big')
1698 u_field_before = u_netcdf_filehandle.variables[u_netcdf_variable][t_index,...]
1699 u_field_after = u_netcdf_filehandle.variables[u_netcdf_variable][t_index+1,...]
1700 u_field = (u_field_before + ((u_field_before - u_field_after)*
1701 (t_RK - t[t_index])/(t[t_index+1] - t[t_index])) - u_bias_field)
1703 v_field_before = v_netcdf_filehandle.variables[v_netcdf_variable][t_index,...]
1704 v_field_after = v_netcdf_filehandle.variables[v_netcdf_variable][t_index+1,...]
1705 v_field = (v_field_before + ((v_field_before - v_field_after)*
1706 (t_RK - t[t_index])/(t[t_index+1] - t[t_index])) - v_bias_field)
1708 w_field_before = w_netcdf_filehandle.variables[w_netcdf_variable][t_index,...]
1709 w_field_after = w_netcdf_filehandle.variables[w_netcdf_variable][t_index+1,...]
1710 w_field = (w_field_before + ((w_field_before - w_field_after)*
1711 (t_RK - t[t_index])/(t[t_index+1] - t[t_index])) - w_bias_field)
1715 for particle
in xrange(n_particles):
1716 if (normed_radius[particle] > r_cutoff_factor
or wet_test[particle] < 0.5
or z_RK[particle]*grid_object[
'Z'][2] < 0):
1717 while (normed_radius[particle] > 1
or wet_test[particle] < 0.5
or z_RK[particle]*grid_object[
'Z'][2] < 0):
1718 x_RK[particle] = ((np.random.rand(1)-0.5)*r_x*2 + x_com)
1719 y_RK[particle] = ((np.random.rand(1)-0.5)*r_y*2 + y_com)
1720 z_RK[particle] = ((np.random.rand(1)-0.5)*r_z*2 + z_com)
1721 normed_radius[particle] = ( ((x_RK[particle] - x_com)**2)/(r_x**2) +
1722 ((y_RK[particle] - y_com)**2)/(r_y**2) +
1723 ((z_RK[particle] - z_com)**2)/(r_z**2) )
1724 wet_test[particle] =
trilinear_interp(x_RK[particle],y_RK[particle],z_RK[particle],
1725 grid_object[
'wet_mask_U'][:],x_u,y_u,z_u,len_x_u,len_y_u,len_z_u)
1733 u_loc = u_loc*deg_per_m[:,1]
1734 v_loc = v_loc*deg_per_m[:,0]
1735 dx1 = timestep*u_loc
1736 dy1 = timestep*v_loc
1737 dz1 = timestep*w_loc
1741 u_field,x_u,y_u,z_u,len_x_u,len_y_u,len_z_u)
1743 v_field,x_v,y_v,z_v,len_x_v,len_y_v,len_z_v)
1745 w_field,x_w,y_w,z_w,len_x_w,len_y_w,len_z_w)
1746 u_loc1 = u_loc1*deg_per_m[:,1]
1747 v_loc1 = v_loc1*deg_per_m[:,0]
1748 dx2 = timestep*u_loc1
1749 dy2 = timestep*v_loc1
1750 dz2 = timestep*w_loc1
1754 u_field,x_u,y_u,z_u,len_x_u,len_y_u,len_z_u)
1756 v_field,x_v,y_v,z_v,len_x_v,len_y_v,len_z_v)
1758 w_field,x_w,y_w,z_w,len_x_w,len_y_w,len_z_w)
1759 u_loc2 = u_loc2*deg_per_m[:,1]
1760 v_loc2 = v_loc2*deg_per_m[:,0]
1761 dx3 = timestep*u_loc2
1762 dy3 = timestep*v_loc2
1763 dz3 = timestep*w_loc2
1767 u_field,x_u,y_u,z_u,len_x_u,len_y_u,len_z_u)
1769 v_field,x_v,y_v,z_v,len_x_v,len_y_v,len_z_v)
1771 w_field,x_w,y_w,z_w,len_x_w,len_y_w,len_z_w)
1773 u_loc3 = u_loc3*deg_per_m[:,1]
1774 v_loc3 = v_loc3*deg_per_m[:,0]
1775 dx4 = timestep*u_loc3
1776 dy4 = timestep*v_loc3
1777 dz4 = timestep*w_loc3
1780 x_RK = x_RK + (dx1 + 2*dx2 + 2*dx3 + dx4)/6
1781 y_RK = y_RK + (dy1 + 2*dy2 + 2*dy3 + dy4)/6
1782 z_RK = z_RK + (dz1 + 2*dz2 + 2*dz3 + dz4)/6
1786 x_com = np.mean(x_RK)
1787 y_com = np.mean(y_RK)
1788 z_com = np.mean(z_RK)
1790 x_stream[:,i] = x_RK
1791 y_stream[:,i] = y_RK
1792 z_stream[:,i] = z_RK
1795 com_stream[0,i] = x_com
1796 com_stream[1,i] = y_com
1797 com_stream[2,i] = z_com
1799 t_index_new = np.searchsorted(t,t_RK)
1800 normed_radius = ( ((x_RK - x_com)**2)/(r_x**2) +
1801 ((y_RK - y_com)**2)/(r_y**2) +
1802 ((z_RK - z_com)**2)/(r_z**2) )
1803 wet_test =
trilinear_interp_arrays(x_RK,y_RK,z_RK,grid_object[
'wet_mask_U'][:],x_u,y_u,z_u,len_x_u,len_y_u,len_z_u)
1805 u_netcdf_filehandle.close()
1806 v_netcdf_filehandle.close()
1807 w_netcdf_filehandle.close()
1809 return x_stream,y_stream,z_stream,t_stream, com_stream
1814 startx,starty,startz,startt,
1815 total_time,timestep,
1819 x_v=
'None',y_v=
'None',z_v=
'None',
1820 x_w=
'None',y_w=
'None',z_w=
'None',
1821 u_grid_loc=
'U',v_grid_loc='V',w_grid_loc='W'):
1824 """!A three-dimensional streamline solver. The velocity fields must be three dimensional and not vary in time.
1825 X_grid_loc variables specify where the field "X" is located on the C-grid. Possibles options are, U, V, W, T and Zeta.
1828 * x_stream, y_stream, z_stream - all with dimensions (particle,time_level)
1829 * t_stream - with dimensions (time_level)
1830 * com_stream - with dimensions (3(x,y,z),time_level)
1833 if u_grid_loc ==
'U':
1834 x_u = copy.deepcopy(grid_object['Xp1'][:])
1835 y_u = copy.deepcopy(grid_object[
'Y'][:])
1836 z_u = copy.deepcopy(grid_object[
'Z'][:])
1837 elif u_grid_loc ==
'V':
1838 x_u = copy.deepcopy(grid_object[
'X'][:])
1839 y_u = copy.deepcopy(grid_object[
'Yp1'][:])
1840 z_u = copy.deepcopy(grid_object[
'Z'][:])
1841 elif u_grid_loc ==
'W':
1842 x_u = copy.deepcopy(grid_object[
'X'][:])
1843 y_u = copy.deepcopy(grid_object[
'Y'][:])
1844 z_u = copy.deepcopy(grid_object[
'Zl'][:])
1845 elif u_grid_loc ==
'T':
1846 x_u = copy.deepcopy(grid_object[
'X'][:])
1847 y_u = copy.deepcopy(grid_object[
'Y'][:])
1848 z_u = copy.deepcopy(grid_object[
'Z'][:])
1849 elif u_grid_loc ==
'Zeta':
1850 x_u = copy.deepcopy(grid_object[
'Xp1'][:])
1851 y_u = copy.deepcopy(grid_object[
'Yp1'][:])
1852 z_u = copy.deepcopy(grid_object[
'Z'][:])
1854 print 'u_grid_loc not set correctly. Possible options are: U,V,W,T, and Zeta'
1857 if v_grid_loc ==
'U':
1858 x_v = copy.deepcopy(grid_object['Xp1'][:])
1859 y_v = copy.deepcopy(grid_object[
'Y'][:])
1860 z_v = copy.deepcopy(grid_object[
'Z'][:])
1861 elif v_grid_loc ==
'V':
1862 x_v = copy.deepcopy(grid_object[
'X'][:])
1863 y_v = copy.deepcopy(grid_object[
'Yp1'][:])
1864 z_v = copy.deepcopy(grid_object[
'Z'][:])
1865 elif v_grid_loc ==
'W':
1866 x_v = copy.deepcopy(grid_object[
'X'][:])
1867 y_v = copy.deepcopy(grid_object[
'Y'][:])
1868 z_v = copy.deepcopy(grid_object[
'Zl'][:])
1869 elif v_grid_loc ==
'T':
1870 x_v = copy.deepcopy(grid_object[
'X'][:])
1871 y_v = copy.deepcopy(grid_object[
'Y'][:])
1872 z_v = copy.deepcopy(grid_object[
'Z'][:])
1873 elif v_grid_loc ==
'Zeta':
1874 x_v = copy.deepcopy(grid_object[
'Xp1'][:])
1875 y_v = copy.deepcopy(grid_object[
'Yp1'][:])
1876 z_v = copy.deepcopy(grid_object[
'Z'][:])
1878 print 'v_grid_loc not set correctly. Possible options are: U,V,W,T, and Zeta'
1881 if w_grid_loc ==
'U':
1882 x_w = copy.deepcopy(grid_object['Xp1'][:])
1883 y_w = copy.deepcopy(grid_object[
'Y'][:])
1884 z_w = copy.deepcopy(grid_object[
'Z'][:])
1885 elif w_grid_loc ==
'V':
1886 x_w = copy.deepcopy(grid_object[
'X'][:])
1887 y_w = copy.deepcopy(grid_object[
'Yp1'][:])
1888 z_w = copy.deepcopy(grid_object[
'Z'][:])
1889 elif w_grid_loc ==
'W':
1890 x_w = copy.deepcopy(grid_object[
'X'][:])
1891 y_w = copy.deepcopy(grid_object[
'Y'][:])
1892 z_w = copy.deepcopy(grid_object[
'Zl'][:])
1893 elif w_grid_loc ==
'T':
1894 x_w = copy.deepcopy(grid_object[
'X'][:])
1895 y_w = copy.deepcopy(grid_object[
'Y'][:])
1896 z_w = copy.deepcopy(grid_object[
'Z'][:])
1897 elif w_grid_loc ==
'Zeta':
1898 x_w = copy.deepcopy(grid_object[
'Xp1'][:])
1899 y_w = copy.deepcopy(grid_object[
'Yp1'][:])
1900 z_w = copy.deepcopy(grid_object[
'Z'][:])
1902 print 'w_grid_loc not set correctly. Possible options are: U,V,W,T, and Zeta'
1919 ini_x = ((np.random.rand(n_particles)-0.5)*2*r_x + startx)
1920 ini_y = ((np.random.rand(n_particles)-0.5)*2*r_y + starty)
1921 ini_z = ((np.random.rand(n_particles)-0.5)*2*r_z + startz)
1923 x_stream = np.ones((n_particles,int(np.fabs(total_time/timestep))+2))*startx
1924 y_stream = np.ones((n_particles,int(np.fabs(total_time/timestep))+2))*starty
1925 z_stream = np.ones((n_particles,int(np.fabs(total_time/timestep))+2))*startz
1926 t_stream = np.ones((int(np.fabs(total_time/timestep))+2))*startt
1927 com_stream = np.ones((3,int(np.fabs(total_time/timestep))+2))
1940 normed_radius = ( ((ini_x - startx)**2)/(r_x**2) +
1941 ((ini_y - starty)**2)/(r_y**2) +
1942 ((ini_z - startz)**2)/(r_z**2) )
1944 wet_test =
trilinear_interp_arrays(x_RK,y_RK,z_RK,grid_object[
'wet_mask_U'][:],x_u,y_u,z_u,len_x_u,len_y_u,len_z_u)
1946 for particle
in xrange(n_particles):
1947 if (normed_radius[particle] > r_cutoff_factor
or wet_test[particle] < 0.5
or z_RK[particle]*grid_object[
'Z'][2] < 0):
1948 while (normed_radius[particle] > 1
or wet_test[particle] < 0.5
or z_RK[particle]*grid_object[
'Z'][2] < 0):
1949 x_RK[particle] = ((np.random.rand(1)-0.5)*r_x*2 + x_com)
1950 y_RK[particle] = ((np.random.rand(1)-0.5)*r_y*2 + y_com)
1951 z_RK[particle] = ((np.random.rand(1)-0.5)*r_z*2 + z_com)
1952 normed_radius[particle] = ( ((x_RK[particle] - x_com)**2)/(r_x**2) +
1953 ((y_RK[particle] - y_com)**2)/(r_y**2) +
1954 ((z_RK[particle] - z_com)**2)/(r_z**2) )
1955 wet_test[particle] =
trilinear_interp(x_RK[particle],y_RK[particle],z_RK[particle],
1956 grid_object[
'wet_mask_U'][:],x_u,y_u,z_u,len_x_u,len_y_u,len_z_u)
1962 deg_per_m = np.ones((n_particles,2),dtype=float)
1963 if grid_object[
'grid_type']==
'polar':
1964 deg_per_m[:,0] = np.ones((n_particles))/(1852.*60.)
1967 while i < np.fabs(total_time/timestep):
1969 if grid_object[
'grid_type']==
'polar':
1971 deg_per_m[:,1] = np.cos(np.ones((n_particles))*starty*np.pi/180.)/(1852.*60.)
1975 for particle
in xrange(n_particles):
1976 if (normed_radius[particle] > r_cutoff_factor
or wet_test[particle] < 0.5
or z_RK[particle]*grid_object[
'Z'][2] < 0):
1977 while (normed_radius[particle] > 1
or wet_test[particle] < 0.5
or z_RK[particle]*grid_object[
'Z'][2] < 0):
1978 x_RK[particle] = ((np.random.rand(1)-0.5)*r_x*2 + x_com)
1979 y_RK[particle] = ((np.random.rand(1)-0.5)*r_y*2 + y_com)
1980 z_RK[particle] = ((np.random.rand(1)-0.5)*r_z*2 + z_com)
1981 normed_radius[particle] = ( ((x_RK[particle] - x_com)**2)/(r_x**2) +
1982 ((y_RK[particle] - y_com)**2)/(r_y**2) +
1983 ((z_RK[particle] - z_com)**2)/(r_z**2) )
1984 wet_test[particle] =
trilinear_interp(x_RK[particle],y_RK[particle],z_RK[particle],
1985 grid_object[
'wet_mask_U'][:],x_u,y_u,z_u,len_x_u,len_y_u,len_z_u)
1991 u_loc = u_loc*deg_per_m[:,1]
1992 v_loc = v_loc*deg_per_m[:,0]
1993 dx1 = timestep*u_loc
1994 dy1 = timestep*v_loc
1995 dz1 = timestep*w_loc
1997 u_loc1 =
trilinear_interp_arrays(x_RK + 0.5*dx1,y_RK + 0.5*dy1,z_RK + 0.5*dz1,u,x_u,y_u,z_u,len_x_u,len_y_u,len_z_u)
1998 v_loc1 =
trilinear_interp_arrays(x_RK + 0.5*dx1,y_RK + 0.5*dy1,z_RK + 0.5*dz1,v,x_v,y_v,z_v,len_x_v,len_y_v,len_z_v)
1999 w_loc1 =
trilinear_interp_arrays(x_RK + 0.5*dx1,y_RK + 0.5*dy1,z_RK + 0.5*dz1,w,x_w,y_w,z_w,len_x_w,len_y_w,len_z_w)
2000 u_loc1 = u_loc1*deg_per_m[:,1]
2001 v_loc1 = v_loc1*deg_per_m[:,0]
2002 dx2 = timestep*u_loc1
2003 dy2 = timestep*v_loc1
2004 dz2 = timestep*w_loc1
2006 u_loc2 =
trilinear_interp_arrays(x_RK + 0.5*dx2,y_RK + 0.5*dy2,z_RK + 0.5*dz2,u,x_u,y_u,z_u,len_x_u,len_y_u,len_z_u)
2007 v_loc2 =
trilinear_interp_arrays(x_RK + 0.5*dx2,y_RK + 0.5*dy2,z_RK + 0.5*dz2,v,x_v,y_v,z_v,len_x_v,len_y_v,len_z_v)
2008 w_loc2 =
trilinear_interp_arrays(x_RK + 0.5*dx2,y_RK + 0.5*dy2,z_RK + 0.5*dz2,w,x_w,y_w,z_w,len_x_w,len_y_w,len_z_w)
2009 u_loc2 = u_loc2*deg_per_m[:,1]
2010 v_loc2 = v_loc2*deg_per_m[:,0]
2011 dx3 = timestep*u_loc2
2012 dy3 = timestep*v_loc2
2013 dz3 = timestep*w_loc2
2018 u_loc3 = u_loc3*deg_per_m[:,1]
2019 v_loc3 = v_loc3*deg_per_m[:,0]
2020 dx4 = timestep*u_loc3
2021 dy4 = timestep*v_loc3
2022 dz4 = timestep*w_loc3
2025 x_RK = x_RK + (dx1 + 2*dx2 + 2*dx3 + dx4)/6
2026 y_RK = y_RK + (dy1 + 2*dy2 + 2*dy3 + dy4)/6
2027 z_RK = z_RK + (dz1 + 2*dz2 + 2*dz3 + dz4)/6
2031 x_com = np.mean(x_RK)
2032 y_com = np.mean(y_RK)
2033 z_com = np.mean(z_RK)
2035 x_stream[:,i] = x_RK
2036 y_stream[:,i] = y_RK
2037 z_stream[:,i] = z_RK
2040 com_stream[0,i] = x_com
2041 com_stream[1,i] = y_com
2042 com_stream[2,i] = z_com
2044 normed_radius = ( ((x_RK - x_com)**2)/(r_x**2) +
2045 ((y_RK - y_com)**2)/(r_y**2) +
2046 ((z_RK - z_com)**2)/(r_z**2) )
2048 wet_test =
trilinear_interp_arrays(x_RK,y_RK,z_RK,grid_object[
'wet_mask_U'][:],x_u,y_u,z_u,len_x_u,len_y_u,len_z_u)
2051 return x_stream,y_stream,z_stream,t_stream, com_stream
2057 """!Do bilinear interpolation of a field. This function assumes that the grid can locally be regarded as cartesian, with everything at right angles.
2059 x0,y0 are the points to interpolate to.
2063 x_index = np.searchsorted(x,x0)
2067 elif x_index == len_x:
2071 y_index = np.searchsorted(y,y0)
2075 elif y_index == len_y:
2087 """!This is a numba accelerated bilinear interpolation. The @numba.jit decorator just above this function causes it to be compiled just before it is run. This introduces a small, Order(1 second), overhead the first time, but not on subsequent calls.
2089 field_interp = ((field[y_index-1,x_index-1]*(x[x_index] - x0)*(y[y_index] - y0) +
2090 field[y_index-1,x_index]*(x0 - x[x_index-1])*(y[y_index] - y0) +
2091 field[y_index,x_index]*(x[x_index] - x0)*(y0 - y[y_index-1]) +
2092 field[y_index,x_index]*(x0 - x[x_index-1])*(y0 - y[y_index-1]))/
2093 ((y[y_index] - y[y_index-1])*(x[x_index] - x[x_index-1])))
2097 """!Do trilinear interpolation of the field in three spatial dimensions. This function assumes that the grid can locally be regarded as cartesian, with everything at right angles. It also requires that the entire field can be held in memory at the same time.
2099 x0,y0, and z0 represent the point to interpolate to.
2103 x_index = x.searchsorted(x0)
2107 elif x_index == len_x:
2111 y_index = y.searchsorted(y0)
2115 elif y_index == len_y:
2123 z_index = z.searchsorted(z0)
2127 elif z_index == len_z:
2141 """!Do trilinear interpolation of the field in three spatial dimensions. This function assumes that the grid can locally be regarded as cartesian, with everything at right angles. It also requires that the entire field can be held in memory at the same time.
2143 x0,y0, and z0 represent the point to interpolate to.
2147 x0[x0<x[0]] = (x[0]+x[1])/2
2148 x0[x0>x[-1]] = (x[-1]+x[-2])/2
2149 x_index = x.searchsorted(x0)
2155 y0[y0<y[0]] = (y[0]+y[1])/2
2156 y0[y0>y[-1]] = (y[-1]+y[-2])/2
2157 y_index = y.searchsorted(y0)
2167 z0[z0<z[0]] = (z[0]+z[1])/2
2168 z0[z0>z[-1]] = (z[-1]+z[-2])/2
2169 z_index = z.searchsorted(z0)
2184 """!This is a numba accelerated trilinear interpolation. The @numba.jit decorator just above this function causes it to be compiled just before it is run. This introduces a small, Order(1 second), overhead the first time, but not on subsequent calls.
2186 field_interp = ((field[z_index-1,y_index-1,x_index-1]*
2187 (x[x_index] - x0)*(y[y_index] - y0)*(z[z_index] - z0) +
2188 field[z_index,y_index-1,x_index-1]*
2189 (x[x_index] - x0)*(y[y_index] - y0)*(z0 - z[z_index-1]) +
2190 field[z_index,y_index,x_index-1]*
2191 (x[x_index] - x0)*(y0 - y[y_index-1])*(z0 - z[z_index-1]) +
2192 field[z_index-1,y_index,x_index-1]*
2193 (x[x_index] - x0)*(y0 - y[y_index-1])*(z[z_index] - z0) +
2194 field[z_index-1,y_index-1,x_index]*
2195 (x0 - x[x_index-1])*(y[y_index] - y0)*(z[z_index] - z0) +
2196 field[z_index,y_index-1,x_index]*
2197 (x0 - x[x_index-1])*(y[y_index] - y0)*(z0 - z[z_index-1]) +
2198 field[z_index,y_index,x_index]*
2199 (x0 - x[x_index-1])*(y0 - y[y_index-1])*(z0 - z[z_index-1]) +
2200 field[z_index-1,y_index,x_index]*
2201 (x0 - x[x_index-1])*(y0 - y[y_index-1])*(z[z_index] - z0))/
2202 ((z[z_index] - z[z_index-1])*(y[y_index] - y[y_index-1])*(x[x_index] - x[x_index-1])))
2208 len_x,len_y,len_z,len_t,
2209 x_index,y_index,z_index,t_index):
2210 """! Do quadralinear interpolation of the velocity field in three spatial dimensions and one temporal dimension to get nice accurate streaklines. This function assumes that the grid can locally be regarded as cartesian, with everything at right angles.
2212 x0,y0,z0, and t0 represent the point to interpolate to.
2214 The velocity field, "field", is passed as a truncated 4D field.
2216 x,y,z,t are vectors of these dimensions.
2221 x_index,y_index,z_index,t_index,
2228 x_index,y_index,z_index,t_index,
2230 """!This is a numba accelerated quadralinear interpolation. The @numba.jit decorator just above this function causes it to be compiled just before it is run. This introduces a small, Order(1 second), overhead the first time, but not on subsequent
2233 field_interp = ((field[0,0,0,0]*
2234 (x[x_index] - x0)*(y[y_index] - y0)*(z[z_index] - z0)*(t[t_index] - t0) +
2236 (x[x_index] - x0)*(y[y_index] - y0)*(z0 - z[z_index-1])*(t[t_index] - t0) +
2238 (x[x_index] - x0)*(y0 - y[y_index-1])*(z0 - z[z_index-1])*(t[t_index] - t0) +
2240 (x[x_index] - x0)*(y0 - y[y_index-1])*(z[z_index] - z0)*(t[t_index] - t0) +
2242 (x0 - x[x_index-1])*(y[y_index] - y0)*(z[z_index] - z0)*(t[t_index] - t0) +
2244 (x0 - x[x_index-1])*(y[y_index] - y0)*(z0 - z[z_index-1])*(t[t_index] - t0) +
2246 (x0 - x[x_index-1])*(y0 - y[y_index-1])*(z0 - z[z_index-1])*(t[t_index] - t0) +
2248 (x0 - x[x_index-1])*(y0 - y[y_index-1])*(z[z_index] - z0)*(t[t_index] - t0) +
2251 (x[x_index] - x0)*(y[y_index] - y0)*(z[z_index] - z0)*(t0 - t[t_index-1]) +
2253 (x[x_index] - x0)*(y[y_index] - y0)*(z0 - z[z_index-1])*(t0 - t[t_index-1]) +
2255 (x[x_index] - x0)*(y0 - y[y_index-1])*(z0 - z[z_index-1])*(t0 - t[t_index-1]) +
2257 (x[x_index] - x0)*(y0 - y[y_index-1])*(z[z_index] - z0)*(t0 - t[t_index-1]) +
2259 (x0 - x[x_index-1])*(y[y_index] - y0)*(z[z_index] - z0)*(t0 - t[t_index-1]) +
2261 (x0 - x[x_index-1])*(y[y_index] - y0)*(z0 - z[z_index-1])*(t0 - t[t_index-1]) +
2263 (x0 - x[x_index-1])*(y0 - y[y_index-1])*(z0 - z[z_index-1])*(t0 - t[t_index-1]) +
2265 (x0 - x[x_index-1])*(y0 - y[y_index-1])*(z[z_index] - z0)*(t0 - t[t_index-1]))/
2266 ((t[t_index] - t[t_index-1])*(z[z_index] - z[z_index-1])*
2267 (y[y_index] - y[y_index-1])*(x[x_index] - x[x_index-1])))
2277 len_x,len_y,len_z,len_t,
2278 netcdf_filehandle,variable, bias_field):
2279 """!A helper function to extract a small 4D hypercube of data from a netCDF file. This isn't intended to be used on its own."""
2282 x_index = np.searchsorted(x,x0)
2283 y_index = np.searchsorted(y,y0)
2288 z_index = np.searchsorted(z,z0)
2291 x_index = max(x_index,1)
2292 x_index = min(x_index,len_x-3)
2293 y_index = max(y_index,1)
2294 y_index = min(y_index,len_y-3)
2295 z_index = max(z_index,1)
2296 z_index = min(z_index,len_z-3)
2298 field = netcdf_filehandle.variables[variable][t_index-1:t_index+2,
2299 z_index-1:z_index+3,
2300 y_index-1:y_index+3,
2301 x_index-1:x_index+3]
2305 bias_field[np.newaxis,z_index-1:z_index+3,y_index-1:y_index+3,x_index-1:x_index+3])
2307 return field,x_index,y_index,z_index
2311 x_axis,y_axis,z_axis,t_axis,
2312 netcdf_filename=
'netcdf file with variable of interest',
2313 netcdf_variable=
'momVort3'):
2314 """!extract the value of a field along a path through a time varying, 3 dimensional field. The field must be in a NetCDF file, since it is assumed to be 4D and very large.
2316 This can also be used to pull out values at specific locations and times.
2319 t_index = np.searchsorted(t_axis,path_t[0])
2320 t_index_new = np.searchsorted(t_axis,path_t[0])
2328 netcdf_filehandle = netCDF4.Dataset(netcdf_filename)
2330 path_x[0],path_y[0],path_z[0],t_index,
2331 len_x,len_y,len_z,len_t,
2332 netcdf_filehandle,netcdf_variable)
2334 field,x_index_new,y_index_new,z_index_new =
indices_and_field(x_axis,y_axis,z_axis,
2335 path_x[0],path_y[0],path_z[0],t_index,
2336 len_x,len_y,len_z,len_t,
2337 netcdf_filehandle,netcdf_variable)
2341 path_variable = np.zeros((path_x.shape))
2347 raise ValueError(
'Given start time is outside the given variable field - too small')
2348 elif t_index == len_t:
2349 raise ValueError(
'Given start time is outside the given variable field - too big')
2352 for i
in xrange(0,len(path_t)):
2354 if (y_index_new==y_index
and
2355 x_index_new==x_index
and
2356 z_index_new==z_index
and
2358 t_index_new == t_index):
2364 t_index = np.searchsorted(t,path_t[i])
2366 raise ValueError(
'Time value is outside the given variable field - too small')
2367 elif t_index == len_t:
2368 raise ValueError(
'Time value is outside the given variable field - too big')
2371 path_x[i],path_y[i],path_z[i],t_index,
2372 len_x,len_y,len_z,len_t,
2373 netcdf_filehandle,netcdf_variable)
2379 x_axis,y_axis,z_axis,t_axis,
2380 len_x,len_y,len_z,len_t,
2381 x_index,y_index,z_index,t_index)
2384 path_variable[i] = field_at_loc
2386 t_index_new = np.searchsorted(t_axis,path_t[i])
2387 x_index_new = np.searchsorted(x_axis,path_x[i])
2388 y_index_new = np.searchsorted(y_axis,path_y[i])
2390 z_index_new = np.searchsorted(-z_axis,-path_z[i])
2392 z_index_new = np.searchsorted(z_axis,path_z[i])
2396 netcdf_filehandle.close()
2398 return path_variable
2403 x_axis,y_axis,z_axis,field):
2404 """!Extract the value of a field along a path through a 3 dimensional field. The field must be passed as an array. Time varying fields are not supported.
2411 path_variable = np.zeros((path_x.shape))
2421 for i
in xrange(0,len(path_x)):
2424 path_variable[i] =
trilinear_interp(path_x[i],path_y[i],path_z[i],field,x_axis,y_axis,z_axis,len_x,len_y,len_z)
2426 return path_variable
2431 x_axis,y_axis,field,order=3,dx=0,dy=0):
2432 """!Extract the value of a field along a path through a 2 dimensional field. The field must be passed as an array. Time varying fields are not supported.
2436 * path_x - x-coordinate of the path.
2437 * path_y - y-coordinate of the path.
2438 * x_axis - vector of the x-coordinate of the input field.
2439 * y_axis - vector of the y-coordinate of the input field.
2440 * field - the input field, the values of which will be extracted along the path.
2441 * order - the order for the interpolation function, must be between 1 and 5 inclusive. 1 -> linear, 3 -> cubic.
2442 * dx, dy - order of the derivative to take in x or y. Optional arguments that are passed to the scipy cubic interpolation function.
2447 path_variable = np.zeros((path_x.shape))
2454 for i
in xrange(0,len(path_x)):
2456 path_variable[i] =
bilinear_interp(path_x[i],path_y[i],field,x_axis,y_axis,len_x,len_y)
2459 interp_field = scipy.interpolate.RectBivariateSpline(y_axis,x_axis,field,kx=order,ky=order)
2461 for i
in xrange(0,len(path_x)):
2464 path_variable[i] =
interp_field(path_y[i],path_x[i],dx=dx,dy=dy)
2466 return path_variable
def quadralinear_interp(x0, y0, z0, t0, field, x, y, z, t, len_x, len_y, len_z, len_t, x_index, y_index, z_index, t_index)
Do quadralinear interpolation of the velocity field in three spatial dimensions and one temporal dime...
def pathlines
A three-dimensional lagrangian particle tracker.
def pathlines_many
A three-dimensional lagrangian particle tracker designed for tracking many particles at once...
def extract_along_path2D
Extract the value of a field along a path through a 2 dimensional field.
def numeric_GLM_xyzt
A three-dimensional lagrangian particle tracker designed for tracking many particles at once as a met...
def actual_trilinear_interp(field, x0, y0, z0, x_index, y_index, z_index, x, y, z)
This is a numba accelerated trilinear interpolation.
def stream3_many
A three-dimensional streamline solver.
def extract_along_path4D
extract the value of a field along a path through a time varying, 3 dimensional field.
def trilinear_interp(x0, y0, z0, field, x, y, z, len_x, len_y, len_z)
Do trilinear interpolation of the field in three spatial dimensions.
def pathlines_for_OLIC_xyzt_ani
A three-dimensional lagrangian particle tracker designed for tracking many particles at once...
def interp_field
Interpolate a given field onto a different grid.
def stream3
A three-dimensional streamline solver.
def actual_quadralinear_interp(field, x0, y0, z0, t0, x_index, y_index, z_index, t_index, x, y, z, t)
This is a numba accelerated quadralinear interpolation.
def extract_along_path3D(path_x, path_y, path_z, x_axis, y_axis, z_axis, field)
Extract the value of a field along a path through a 3 dimensional field.
def bilinear_interp(x0, y0, field, x, y, len_x, len_y)
Do bilinear interpolation of a field.
def numeric_GLM_xyz
A three-dimensional streamline solver.
def trilinear_interp_arrays(x0, y0, z0, field, x, y, z, len_x, len_y, len_z)
Do trilinear interpolation of the field in three spatial dimensions.
def indices_and_field(x, y, z, x0, y0, z0, t_index, len_x, len_y, len_z, len_t, netcdf_filehandle, variable, bias_field)
A helper function to extract a small 4D hypercube of data from a netCDF file.
def actual_bilinear_interp(field, x0, y0, x, y, len_x, len_y, x_index, y_index)
This is a numba accelerated bilinear interpolation.
def stream2
A two-dimensional streamline solver.