9
9
10
10
from pyschism .mesh .hgrid import Hgrid
11
11
12
+ from matplotlib .pyplot import *
13
+
12
14
13
15
def C_of_sigma (sigma , theta_b , theta_f ):
14
16
assert theta_b <= 0. and theta_b <= 1.
@@ -106,8 +108,16 @@ def is3D(self):
106
108
107
109
class LSC2 (Vgrid ):
108
110
109
- def __init__ (self , sigma ):
110
- self .sigma = sigma
111
+ def __init__ (self , hsm , nv , h_c , theta_b , theta_f ):
112
+ self .hsm = np .array (hsm )
113
+ self .nv = np .array (nv )
114
+ self .h_c = h_c
115
+ self .theta_b = theta_b
116
+ self .theta_f = theta_f
117
+ self .m_grid = None
118
+ self ._znd = None
119
+ self ._snd = None
120
+ self ._nlayer = None
111
121
112
122
def __str__ (self ):
113
123
f = [
@@ -131,12 +141,147 @@ def __str__(self):
131
141
return '\n ' .join (f )
132
142
133
143
def get_xyz (self , gr3 , crs = None ):
144
+ if type (gr3 ) == Hgrid :
145
+ gr3 = gr3
146
+ else :
147
+ gr3 = Hgrid .open (gr3 )
134
148
xy = gr3 .get_xy (crs )
135
149
z = gr3 .values [:, None ]* self .sigma
136
150
x = np .tile (xy [:, 0 ], (z .shape [1 ],))
137
151
y = np .tile (xy [:, 0 ], (z .shape [1 ],))
138
152
return np .vstack ([x , y , z .flatten ()]).T
139
153
154
+ def calc_m_grid (self ):
155
+ '''
156
+ create master grid
157
+ Adapted from:
158
+ https://github.com/wzhengui/pylibs/blob/master/pyScripts/gen_vqs.py
159
+ '''
160
+ if self .m_grid :
161
+ pass
162
+ else :
163
+ z_mas = np .ones ([self .nhm ,self .nvrt ])* np .nan ; eta = 0.0
164
+ for m , [hsmi ,nvi ] in enumerate (zip (self .hsm ,self .nv )):
165
+ #strethcing funciton
166
+ hc = min (hsmi ,self .h_c )
167
+ for k in np .arange (nvi ):
168
+ sigma = k / (1 - nvi ) #zi=-sigma #original sigma coordiante
169
+ #compute zcoordinate
170
+ cs = (1 - self .theta_b )* np .sinh (self .theta_f * sigma )/ np .sinh (self .theta_f )+ \
171
+ self .theta_b * (np .tanh (self .theta_f * (sigma + 0.5 ))- \
172
+ np .tanh (self .theta_f * 0.5 ))/ 2 / np .tanh (self .theta_f * 0.5 )
173
+ z_mas [m ,k ]= eta * (1 + sigma )+ hc * sigma + (hsmi - hc )* cs
174
+
175
+ #normalize z_mas
176
+ z_mas [m ]= - (z_mas [m ]- z_mas [m ,0 ])* hsmi / (z_mas [m ,nvi - 1 ]- z_mas [m ,0 ])
177
+ s_mas = np .array ([z_mas [i ]/ self .hsm [i ] for i in np .arange (self .nhm )])
178
+
179
+ self .m_grid = z_mas
180
+
181
+ def make_m_plot (self ):
182
+ '''
183
+ plot master grid
184
+ Adapted from:
185
+ https://github.com/wzhengui/pylibs/blob/master/pyScripts/gen_vqs.py
186
+ '''
187
+ #check master grid
188
+ for i in np .arange (self .nhm - 1 ):
189
+ if min (self .m_grid [i ,:self .nv [i ]]- self .m_grid [i + 1 ,:self .nv [i ]])< 0 : \
190
+ print ('check: master grid layer={}, hsm={}, nv={}' .\
191
+ format (i + 1 ,self .hsm [i + 1 ],self .nv [i + 1 ]))
192
+
193
+ #plot master grid
194
+ figure (figsize = [10 ,5 ])
195
+ for i in np .arange (self .nhm ): plot (i * np .ones (self .nvrt ),\
196
+ self .m_grid [i ],'k-' ,lw = 0.3 )
197
+ for k in np .arange (self .nvrt ): plot (np .arange (self .nhm ),\
198
+ self .m_grid .T [k ],'k-' ,lw = 0.3 )
199
+ setp (gca (),xlim = [- 0.5 ,self .nhm - 0.5 ],ylim = [- self .hsm [- 1 ],0.5 ])
200
+ gcf ().tight_layout ()
201
+
202
+ def calc_lsc2_att (self , gr3 , crs = None ):
203
+ '''
204
+ master grid to lsc2:
205
+ compute vertical layers at nodes
206
+ gr3 is either file or Hgrid Object
207
+ Adapted from:
208
+ https://github.com/wzhengui/pylibs/blob/master/pyScripts/gen_vqs.py
209
+ '''
210
+ if type (gr3 ) == Hgrid :
211
+ gd = gr3
212
+ else :
213
+ gd = Hgrid .open (gr3 )
214
+ dp = gd .values * - 1
215
+ fpz = dp < self .hsm [0 ]
216
+ dp [fpz ]= self .hsm [0 ]
217
+
218
+ #find hsm index for all points
219
+ rat = np .ones (len (gd .nodes .id ))* np .nan
220
+ nlayer = np .zeros (len (gd .nodes .id )).astype ('int' )
221
+ ind1 = np .zeros (len (gd .nodes .id )).astype ('int' )
222
+ ind2 = np .zeros (len (gd .nodes .id )).astype ('int' )
223
+ for m , hsmi in enumerate (self .hsm ):
224
+ if m == 0 :
225
+ fp = dp <= self .hsm [m ]
226
+ ind1 [fp ]= 0 ; ind2 [fp ]= 0
227
+ rat [fp ]= 0 ; nlayer [fp ]= self .nv [0 ]
228
+ else :
229
+ fp = (dp > self .hsm [m - 1 ])* (dp <= self .hsm [m ])
230
+ ind1 [fp ]= m - 1
231
+ ind2 [fp ]= m
232
+ rat [fp ]= (dp [fp ]- self .hsm [m - 1 ])/ (self .hsm [m ]- self .hsm [m - 1 ])
233
+ nlayer [fp ]= self .nv [m ]
234
+
235
+ #Find the last non NaN node and fills the NaN values with it
236
+ last_non_nan = (~ np .isnan (self .m_grid )).cumsum (1 ).argmax (1 )
237
+ z_mas = np .array ([np .nan_to_num (z_mas_arr ,nan = z_mas_arr [last_non_nan [i ]])\
238
+ for i , z_mas_arr in enumerate (self .m_grid )])
239
+ znd = z_mas [ind1 ]* (1 - rat [:,None ])+ z_mas [ind2 ]* rat [:,None ]; #z coordinate
240
+ for i in np .arange (len (gd .nodes .id )):
241
+ znd [i ,nlayer [i ]- 1 ]= - dp [i ]
242
+ znd [i ,nlayer [i ]:]= np .nan
243
+ snd = znd / dp [:,None ]; #sigma coordinate
244
+
245
+ #check vgrid
246
+ for i in np .arange (len (gd .nodes .id )):
247
+ for k in np .arange (self .nvrt - 1 ):
248
+ if znd [i ,k ]<= znd [i ,k + 1 ]:
249
+ raise TypeError (f'wrong vertical layers' )
250
+
251
+ self ._znd = znd
252
+ self ._snd = snd
253
+ self ._nlayer = nlayer
254
+
255
+
256
+ def write (self , path , overwrite = False ):
257
+ '''
258
+ write mg2lsc2 into vgrid.in
259
+ '''
260
+ path = pathlib .Path (path )
261
+ if path .is_file () and not overwrite :
262
+ raise Exception (
263
+ 'File exists, pass overwrite=True to allow overwrite.' )
264
+
265
+ with open (path , 'w' ) as fid :
266
+ fid .write (' 1 !average # of layers={:0.2f}\n {} !nvrt\n ' .format \
267
+ (np .mean (self ._nlayer ),self .nvrt ))
268
+ bli = []#bottom level index
269
+ for i in np .arange (len (self ._nlayer )):
270
+ nlayeri = self ._nlayer [i ]; si = np .flipud (self ._snd [i ,:nlayeri ])
271
+ bli .append (self .nvrt - nlayeri + 1 )
272
+ fstr = f" { self .nvrt - nlayeri + 1 :2} "
273
+ fid .write (fstr )
274
+ for i in range (self .nvrt ):
275
+ fid .write (f'\n { i + 1 } ' )
276
+ for n ,bl in enumerate (bli ):
277
+ si = np .flipud (self ._snd [n ])
278
+ if bl <= i + 1 :
279
+ fid .write (f" { si [i ]:.6f} " )
280
+ else :
281
+ fid .write (f" { - 9. :.6f} " )
282
+ fid .close ()
283
+
284
+
140
285
@classmethod
141
286
def open (cls , path ):
142
287
@@ -174,7 +319,11 @@ def open(cls, path):
174
319
175
320
@property
176
321
def nvrt (self ):
177
- return self .sigma .shape [1 ]
322
+ return self .nv [- 1 ]
323
+
324
+ @property
325
+ def nhm (self ):
326
+ return self .hsm .shape [0 ]
178
327
179
328
180
329
class SZ (Vgrid ):
0 commit comments