44Class to generate NEMO v4.0 s-coordinates
55"""
66
7- from typing import Optional
7+ from typing import Optional , Tuple
88
99import numpy as np
1010import xarray as xr
@@ -43,7 +43,6 @@ class Sco(Zgr):
4343 *) Madec, Delecluse, Crepon & Lott, JPO 26(8):1393-1408, 1996.
4444 """
4545
46- # --------------------------------------------------------------------------
4746 def __call__ (
4847 self ,
4948 min_dep : float ,
@@ -138,17 +137,16 @@ def __call__(
138137 self ._sigmas = self ._compute_sigma (self ._z )
139138
140139 # compute z3 depths of zco vertical levels
141- # dsz = self._sco_z3(ds_env)
140+ z3t , z3w = self ._sco_z3
142141
143142 # compute e3 scale factors
144- # dse = self._compute_e3(dsz) if self._ln_e3_dep else self._analyt_e3(dsz )
143+ e3t , e3w = self ._compute_e3 (z3t , z3w )
145144
146145 # addind this only to not make darglint complying
147- ds = self ._bathy .copy ()
148- ds ["hbatt" ] = self ._envlp
149- return ds
146+ # ds = self._bathy.copy()
147+ # ds["hbatt"] = self._envlp
148+ return self . _merge_z3_and_e3 ( z3t , z3w , e3t , e3w )
150149
151- # --------------------------------------------------------------------------
152150 def _check_stretch_par (self , psurf , pbott , alpha , efold , pbot2 ):
153151 """
154152 Check consistency of stretching parameters
@@ -174,7 +172,6 @@ def _check_stretch_par(self, psurf, pbott, alpha, efold, pbot2):
174172 sf12 stretching."
175173 )
176174
177- # --------------------------------------------------------------------------
178175 def _compute_env (self , depth : DataArray ) -> DataArray :
179176 """
180177 Compute the envelope bathymetry surface by applying the
@@ -215,3 +212,145 @@ def _compute_env(self, depth: DataArray) -> DataArray:
215212 zenv = zenv .where (zenv > self ._min_dep , self ._min_dep )
216213
217214 return zenv
215+
216+ @property
217+ def _sco_z3 (self ) -> Tuple [DataArray , ...]:
218+ """Compute and return z3{t,w} for s-coordinates grids"""
219+
220+ grids = ("T" , "W" )
221+ sigmas = self ._sigmas
222+ scosrf = self ._envlp * 0.0 # unperturbed free-surface
223+
224+ both_z3 = []
225+ for grid , sigma in zip (grids , sigmas ):
226+
227+ if self ._stretch :
228+ # Stretched sco grid
229+ su = - sigma
230+ ss = self ._stretch_sco (- sigma )
231+ a1 = scosrf
232+ a2 = 0.0
233+ a3 = self ._envlp
234+ if self ._stretch != "sf12" :
235+ a2 += self ._hc
236+ a3 -= self ._hc
237+ else :
238+ # Uniform sco grid
239+ su = - sigma
240+ ss = DataArray ((0.0 ))
241+ a1 = a3 = scosrf
242+ a2 = self ._envlp
243+
244+ z3 = self ._compute_z3 (su , ss , a1 , a2 , a3 )
245+
246+ both_z3 += [z3 ]
247+
248+ return tuple (both_z3 )
249+
250+ def _stretch_sco (self , sigma : DataArray ) -> DataArray :
251+ """
252+ Wrapping method for calling generalised analytical
253+ stretching function for terrain-following s-coordinates.
254+
255+ Parameters
256+ ----------
257+ sigma: DataArray
258+ Uniform non-dimensional sigma-coordinate:
259+ MUST BE positive, i.e. 0 <= sigma <= 1
260+
261+ Returns
262+ -------
263+ DataArray
264+ Stretched coordinate
265+ """
266+ if self ._stretch == "sh94" :
267+ ss = self ._sh94 (sigma )
268+ elif self ._stretch == "md96" :
269+ ss = self ._md96 (sigma )
270+ # elif self._stretch == "sf12":
271+ # ss = self._sf12(sigma)
272+
273+ return ss
274+
275+ def _sh94 (self , sigma : DataArray ) -> DataArray :
276+ """
277+ Song and Haidvogel 1994 analytical stretching
278+ function for terrain-following s-coordinates.
279+
280+ Reference:
281+ Song & Haidvogel, J. Comp. Phy., 115, 228-244, 1994.
282+
283+ Parameters
284+ ----------
285+ sigma: DataArray
286+ Uniform non-dimensional sigma-coordinate:
287+ MUST BE positive, i.e. 0 <= sigma <= 1
288+
289+ Returns
290+ -------
291+ DataArray
292+ Stretched coordinate
293+ """
294+ ca = self ._psurf
295+ cb = self ._pbott
296+
297+ if ca == 0.0 :
298+ ss = sigma
299+ else :
300+ ss = (1.0 - cb ) * np .sinh (ca * sigma ) / np .sinh (ca ) + cb * (
301+ (np .tanh (ca * (sigma + 0.0 )) - np .tanh (0.0 * ca ))
302+ / (2.0 * np .tanh (0.0 * ca ))
303+ )
304+
305+ return ss
306+
307+ def _md96 (self , sigma : DataArray ) -> DataArray :
308+ """
309+ Madec et al. 1996 analytical stretching
310+ function for terrain-following s-coordinates.
311+
312+ Reference:
313+ pag 65 of NEMO Manual
314+ Madec, Lott, Delecluse and Crepon, 1996. JPO, 26, 1393-1408
315+
316+ Parameters
317+ ----------
318+ sigma: DataArray
319+ Uniform non-dimensional sigma-coordinate:
320+ MUST BE positive, i.e. 0 <= sigma <= 1
321+
322+ Returns
323+ -------
324+ DataArray
325+ Stretched coordinate
326+ """
327+ ca = self ._psurf
328+ cb = self ._pbott
329+
330+ ss = (
331+ (np .tanh (ca * (sigma + cb )) - np .tanh (cb * ca ))
332+ * (np .cosh (ca ) + np .cosh (ca * (2.0e0 * cb - 1.0e0 )))
333+ / (2.0 * np .sinh (ca ))
334+ )
335+
336+ return ss
337+
338+ # def _sf12(self, sigma: DataArray) -> DataArray:
339+ # """
340+ # Siddorn and Furner 2012 analytical stretching
341+ # function for terrain-following s-coordinates.
342+ #
343+ # Reference:
344+ # Siddorn & Furner, Oce. Mod. 66:1-13, 2013.
345+
346+ # Parameters
347+ # ----------
348+ # sigma: DataArray
349+ # Uniform non-dimensional sigma-coordinate:
350+ # MUST BE positive, i.e. 0 <= sigma <= 1
351+ #
352+ # Returns
353+ # -------
354+ # DataArray
355+ # Stretched coordinate
356+ # """
0 commit comments