@@ -884,7 +884,7 @@ def interpolator2D(self, ti, z, y, x, particle=None):
884884 xii = xi if xsi <= .5 else xi + 1
885885 yii = yi if eta <= .5 else yi + 1
886886 return self .data [ti , yii , xii ]
887- elif self .interp_method in ['linear' , 'bgrid_velocity' ]:
887+ elif self .interp_method in ['linear' , 'bgrid_velocity' , 'partialslip' , 'freeslip' ]:
888888 val = (1 - xsi )* (1 - eta ) * self .data [ti , yi , xi ] + \
889889 xsi * (1 - eta ) * self .data [ti , yi , xi + 1 ] + \
890890 xsi * eta * self .data [ti , yi + 1 , xi + 1 ] + \
@@ -972,7 +972,7 @@ def interpolator3D(self, ti, z, y, x, time, particle=None):
972972 xsi * eta * data [yi + 1 , xi + 1 ] + \
973973 (1 - xsi ) * eta * data [yi + 1 , xi ]
974974 return (1 - zeta ) * f0 + zeta * f1
975- elif self .interp_method in ['linear' , 'bgrid_velocity' , 'bgrid_w_velocity' ]:
975+ elif self .interp_method in ['linear' , 'bgrid_velocity' , 'bgrid_w_velocity' , 'partialslip' , 'freeslip' ]:
976976 if self .interp_method == 'bgrid_velocity' :
977977 if self .gridindexingtype == 'mom5' :
978978 zeta = 1.
@@ -1635,8 +1635,91 @@ def spatial_c_grid_interpolation3D(self, ti, z, y, x, time, particle=None):
16351635 w = self .W .units .to_target (w , x , y , z )
16361636 return (u , v , w )
16371637
1638+ def _is_land2D (self , di , yi , xi ):
1639+ if self .U .data .ndim == 3 :
1640+ if di < np .shape (self .U .data )[0 ]:
1641+ return np .isclose (self .U .data [di , yi , xi ], 0. ) and np .isclose (self .V .data [di , yi , xi ], 0. )
1642+ else :
1643+ return True
1644+ else :
1645+ if di < self .U .grid .zdim and yi < np .shape (self .U .data )[- 2 ] and xi < np .shape (self .U .data )[- 1 ]:
1646+ return np .isclose (self .U .data [0 , di , yi , xi ], 0. ) and np .isclose (self .V .data [0 , di , yi , xi ], 0. )
1647+ else :
1648+ return True
1649+
1650+ def spatial_slip_interpolation (self , ti , z , y , x , time , particle = None ):
1651+ (xsi , eta , zeta , xi , yi , zi ) = self .U .search_indices (x , y , z , ti , time , particle = particle )
1652+ di = ti if self .U .grid .zdim == 1 else zi # general third dimension
1653+
1654+ f_u , f_v , f_w = 1 , 1 , 1
1655+ if self ._is_land2D (di , yi , xi ) and self ._is_land2D (di , yi , xi + 1 ) and self ._is_land2D (di + 1 , yi , xi ) \
1656+ and self ._is_land2D (di + 1 , yi , xi + 1 ) and eta > 0 :
1657+ if self .U .interp_method == 'partialslip' :
1658+ f_u = f_u * (.5 + .5 * eta ) / eta
1659+ if self .vector_type == '3D' :
1660+ f_w = f_w * (.5 + .5 * eta ) / eta
1661+ elif self .U .interp_method == 'freeslip' :
1662+ f_u = f_u / eta
1663+ if self .vector_type == '3D' :
1664+ f_w = f_w / eta
1665+ if self ._is_land2D (di , yi + 1 , xi ) and self ._is_land2D (di , yi + 1 , xi + 1 ) and self ._is_land2D (di + 1 , yi + 1 , xi ) \
1666+ and self ._is_land2D (di + 1 , yi + 1 , xi + 1 ) and eta < 1 :
1667+ if self .U .interp_method == 'partialslip' :
1668+ f_u = f_u * (1 - .5 * eta ) / (1 - eta )
1669+ if self .vector_type == '3D' :
1670+ f_w = f_w * (1 - .5 * eta ) / (1 - eta )
1671+ elif self .U .interp_method == 'freeslip' :
1672+ f_u = f_u / (1 - eta )
1673+ if self .vector_type == '3D' :
1674+ f_w = f_w / (1 - eta )
1675+ if self ._is_land2D (di , yi , xi ) and self ._is_land2D (di , yi + 1 , xi ) and self ._is_land2D (di + 1 , yi , xi ) \
1676+ and self ._is_land2D (di + 1 , yi + 1 , xi ) and xsi > 0 :
1677+ if self .U .interp_method == 'partialslip' :
1678+ f_v = f_v * (.5 + .5 * xsi ) / xsi
1679+ if self .vector_type == '3D' :
1680+ f_w = f_w * (.5 + .5 * xsi ) / xsi
1681+ elif self .U .interp_method == 'freeslip' :
1682+ f_v = f_v / xsi
1683+ if self .vector_type == '3D' :
1684+ f_w = f_w / xsi
1685+ if self ._is_land2D (di , yi , xi + 1 ) and self ._is_land2D (di , yi + 1 , xi + 1 ) and self ._is_land2D (di + 1 , yi , xi + 1 ) \
1686+ and self ._is_land2D (di + 1 , yi + 1 , xi + 1 ) and xsi < 1 :
1687+ if self .U .interp_method == 'partialslip' :
1688+ f_v = f_v * (1 - .5 * xsi ) / (1 - xsi )
1689+ if self .vector_type == '3D' :
1690+ f_w = f_w * (1 - .5 * xsi ) / (1 - xsi )
1691+ elif self .U .interp_method == 'freeslip' :
1692+ f_v = f_v / (1 - xsi )
1693+ if self .vector_type == '3D' :
1694+ f_w = f_w / (1 - xsi )
1695+ if self .U .grid .zdim > 1 :
1696+ if self ._is_land2D (di , yi , xi ) and self ._is_land2D (di , yi , xi + 1 ) and self ._is_land2D (di , yi + 1 , xi ) \
1697+ and self ._is_land2D (di , yi + 1 , xi + 1 ) and zeta > 0 :
1698+ if self .U .interp_method == 'partialslip' :
1699+ f_u = f_u * (.5 + .5 * zeta ) / zeta
1700+ f_v = f_v * (.5 + .5 * zeta ) / zeta
1701+ elif self .U .interp_method == 'freeslip' :
1702+ f_u = f_u / zeta
1703+ f_v = f_v / zeta
1704+ if self ._is_land2D (di + 1 , yi , xi ) and self ._is_land2D (di + 1 , yi , xi + 1 ) and self ._is_land2D (di + 1 , yi + 1 , xi ) \
1705+ and self ._is_land2D (di + 1 , yi + 1 , xi + 1 ) and zeta < 1 :
1706+ if self .U .interp_method == 'partialslip' :
1707+ f_u = f_u * (1 - .5 * zeta ) / (1 - zeta )
1708+ f_v = f_v * (1 - .5 * zeta ) / (1 - zeta )
1709+ elif self .U .interp_method == 'freeslip' :
1710+ f_u = f_u / (1 - zeta )
1711+ f_v = f_v / (1 - zeta )
1712+
1713+ u = f_u * self .U .eval (time , z , y , x , particle )
1714+ v = f_v * self .V .eval (time , z , y , x , particle )
1715+ if self .vector_type == '3D' :
1716+ w = f_w * self .W .eval (time , z , y , x , particle )
1717+ return u , v , w
1718+ else :
1719+ return u , v
1720+
16381721 def eval (self , time , z , y , x , particle = None ):
1639- if self .U .interp_method != 'cgrid_velocity' :
1722+ if self .U .interp_method not in [ 'cgrid_velocity' , 'partialslip' , 'freeslip' ] :
16401723 u = self .U .eval (time , z , y , x , particle = particle , applyConversion = False )
16411724 v = self .V .eval (time , z , y , x , particle = particle , applyConversion = False )
16421725 u = self .U .units .to_target (u , x , y , z )
@@ -1648,19 +1731,22 @@ def eval(self, time, z, y, x, particle=None):
16481731 else :
16491732 return (u , v )
16501733 else :
1734+ interp = {'cgrid_velocity' : {'2D' : self .spatial_c_grid_interpolation2D , '3D' : self .spatial_c_grid_interpolation3D },
1735+ 'partialslip' : {'2D' : self .spatial_slip_interpolation , '3D' : self .spatial_slip_interpolation },
1736+ 'freeslip' : {'2D' : self .spatial_slip_interpolation , '3D' : self .spatial_slip_interpolation }}
16511737 grid = self .U .grid
16521738 (ti , periods ) = self .U .time_index (time )
16531739 time -= periods * (grid .time_full [- 1 ]- grid .time_full [0 ])
16541740 if ti < grid .tdim - 1 and time > grid .time [ti ]:
16551741 t0 = grid .time [ti ]
16561742 t1 = grid .time [ti + 1 ]
16571743 if self .vector_type == '3D' :
1658- (u0 , v0 , w0 ) = self .spatial_c_grid_interpolation3D (ti , z , y , x , time , particle = particle )
1659- (u1 , v1 , w1 ) = self .spatial_c_grid_interpolation3D (ti + 1 , z , y , x , time , particle = particle )
1744+ (u0 , v0 , w0 ) = interp [ self .U . interp_method ][ '3D' ] (ti , z , y , x , time , particle = particle )
1745+ (u1 , v1 , w1 ) = interp [ self .U . interp_method ][ '3D' ] (ti + 1 , z , y , x , time , particle = particle )
16601746 w = w0 + (w1 - w0 ) * ((time - t0 ) / (t1 - t0 ))
16611747 else :
1662- (u0 , v0 ) = self .spatial_c_grid_interpolation2D (ti , z , y , x , time , particle = particle )
1663- (u1 , v1 ) = self .spatial_c_grid_interpolation2D (ti + 1 , z , y , x , time , particle = particle )
1748+ (u0 , v0 ) = interp [ self .U . interp_method ][ '2D' ] (ti , z , y , x , time , particle = particle )
1749+ (u1 , v1 ) = interp [ self .U . interp_method ][ '2D' ] (ti + 1 , z , y , x , time , particle = particle )
16641750 u = u0 + (u1 - u0 ) * ((time - t0 ) / (t1 - t0 ))
16651751 v = v0 + (v1 - v0 ) * ((time - t0 ) / (t1 - t0 ))
16661752 if self .vector_type == '3D' :
@@ -1672,9 +1758,9 @@ def eval(self, time, z, y, x, particle=None):
16721758 # of the defined time range or if we have hit an
16731759 # exact value in the time array.
16741760 if self .vector_type == '3D' :
1675- return self .spatial_c_grid_interpolation3D (ti , z , y , x , grid .time [ti ], particle = particle )
1761+ return interp [ self .U . interp_method ][ '3D' ] (ti , z , y , x , grid .time [ti ], particle = particle )
16761762 else :
1677- return self .spatial_c_grid_interpolation2D (ti , z , y , x , grid .time [ti ], particle = particle )
1763+ return interp [ self .U . interp_method ][ '2D' ] (ti , z , y , x , grid .time [ti ], particle = particle )
16781764
16791765 def __getitem__ (self , key ):
16801766 if _isParticle (key ):
0 commit comments