def normal_current(self, U, V): """Sample normal component of velocity field""" # Interpolerer foreløpig langs s-flater # Offset for interpolation from U and V grid deltaU = -0.5 + self.grid.i0 - self.grid.i0_u deltaV = -0.5 + self.grid.j0 - self.grid.j0_v Usec = np.zeros((self.N, self.nseg)) Vsec = np.zeros((self.N, self.nseg)) for k in range(self.N): Usec[k,:] = sample2D(U[k,:,:], self.Xm+deltaU, self.Ym) Vsec[k,:] = sample2D(V[k,:,:], self.Xm, self.Ym+deltaV) return self.nx*Usec + self.ny*Vsec
def __init__(self, grid, X, Y): self.grid = grid # Vertices, in subgrid coordinates self.X = X - grid.i0 self.Y = Y - grid.j0 # Nodes self.Xm = 0.5*(self.X[:-1] + self.X[1:]) self.Ym = 0.5*(self.Y[:-1] + self.Y[1:]) # Section size self.nseg = len(self.Xm) # Number of segments = Number of nodes self.N = len(self.grid.Cs_r) # Compatible with both SGrid and grdClass try: self.h = sample2D(self.grid.h, self.Xm, self.Ym, mask=self.grid.mask_rho, undef_value=0.0) except AttributeError: self.h = sample2D(self.grid.depth, self.Xm, self.Ym) pm = sample2D(self.grid.pm, self.Xm, self.Ym) pn = sample2D(self.grid.pn, self.Xm, self.Ym) # Unit normal vector (nx, ny) # Sjekk om dette er korrekt hvis pm og pn er ulike dX = (X[1:]-X[:-1]) / pm dY = (Y[1:]-Y[:-1]) / pn # Length of segments # Kan kanskje forbedres med sfærisk avstand self.dS = np.sqrt(dX*dX+dY*dY) # Cumulative distance (at vertices)s self.S = np.concatenate(([0], np.add.accumulate(self.dS))) nx, ny = dY, -dX norm = np.sqrt(nx*nx + ny*ny) self.nx, self.ny = nx/norm, ny/norm # Vertical structure self.z_r = sdepth(self.h, self.grid.hc, self.grid.Cs_r, stagger='rho', Vtransform=self.grid.Vtransform) self.z_w = sdepth(self.h, self.grid.hc, self.grid.Cs_w, stagger='w', Vtransform=self.grid.Vtransform) self.dZ = self.z_w[1:,:]-self.z_w[:-1,:] self.Area = self.dZ * self.dS
def sample3D(self, F): """Sample a 3D field in rho-points with shape (N,Mp,Lp)""" # Not masked ?? Fsec = np.zeros((self.N, self.L)) for k in range(self.N): Fsec[k, :] = sample2D(F[k, :, :], self.X, self.Y, mask=self.grid.mask_rho) return Fsec
def sample3D(self, F): """Sample a 3D field in rho-points with shape (N,Mp,Lp)""" # Interpolerer foreløpig langs s-flater # Sikkert OK for plotting, Godt nok for flux-beregning? Fsec = np.zeros((self.grid.N, self.nseg)) for k in range(self.grid.N): Fsec[k,:] = sample2D(F[k,:,:], self.Xm, self.Ym, mask=self.grid.mask_rho) Fsec = np.ma.masked_where(self.extend_vertically(self.h) == 0, Fsec) return Fsec
def __init__(self, grid, X, Y): self.grid = grid # Vertices, in subgrid coordinates self.X = X self.Y = Y # Section size self.L = len(self.X) # Number of nodes self.N = len(self.grid.Cs_r) # Topography self.h = sample2D(self.grid.h, self.X, self.Y, mask=self.grid.mask_rho, undef_value=1.0) # Metric pm = sample2D(self.grid.pm, self.X, self.Y) pn = sample2D(self.grid.pn, self.X, self.Y) dX = 2 * (X[1:]-X[:-1]) / (pm[:-1] + pm[1:]) # unit = meter dY = 2 * (Y[1:]-Y[:-1]) / (pn[:-1] + pn[1:]) # Assume spacing is close enough to approximate distance self.dS = np.sqrt(dX*dX+dY*dY) # Cumulative distance self.S = np.concatenate(([0], np.add.accumulate(self.dS))) # Weights for trapez integration (linear interpolation) self.W = 0.5*np.concatenate(([self.dS[0]], self.dS[:-1] + self.dS[1:], [self.dS[-1]])) #nx, ny = dY, -dX #norm = np.sqrt(nx*nx + ny*ny) #self.nx, self.ny = nx/norm, ny/norm # Vertical structure self.z_r = sdepth(self.h, self.grid.hc, self.grid.Cs_r, stagger='rho', Vtransform=self.grid.Vtransform) self.z_w = sdepth(self.h, self.grid.hc, self.grid.Cs_w, stagger='w', Vtransform=self.grid.Vtransform) self.dZ = self.z_w[1:, :]-self.z_w[:-1, :] self.Area = self.dZ * self.W
def sample2D(self, F): return sample2D(F, self.Xm, self.Ym)
def xy2ll(self, x, y): return (sample2D(self.lon_rho, x-self.i0, y-self.j0), sample2D(self.lat_rho, x-self.i0, y-self.j0))
def sample2D(self, F): """Sample a horizontal field at rho poins with shape (Mp, Lp)""" return sample2D(F, self.X, self.Y, mask=self.grid.mask_rho)
def xy2ll(self, x, y): return sample2D(self.lon_rho, x, y), \ sample2D(self.lat_rho, x, y)
def sample2D(self, F, X, Y, mask=True, undef=np.nan): if mask: return sample2D(F, X, Y, mask=self.mask_rho, undef_value=undef) else: return sample2D(F, X, Y)