Exemplo n.º 1
0
    def second_order_river(self, d):
        jmax = self.input.v('grid', 'maxIndex', 'x')
        kmax = self.input.v('grid', 'maxIndex', 'z')
        fmax = self.input.v('grid', 'maxIndex', 'f')
        ftot = 2 * fmax + 1

        ################################################################################################################
        # Forcing terms
        ################################################################################################################
        F = np.zeros([jmax + 1, kmax + 1, ftot, 1], dtype=complex)
        Fsurf = np.zeros([jmax + 1, 1, ftot, 1], dtype=complex)
        Fbed = np.zeros([jmax + 1, 1, ftot, 1], dtype=complex)

        # erosion
        if self.input.v('u1', 'river') is not None:
            E = erosion(self.ws,
                        2,
                        self.input,
                        self.erosion_method,
                        submodule=(None, 'river', None),
                        friction=self.frictionpar)
            Fbed[:, :, fmax:, 0] = -E

            ################################################################################################################
            # Solve equation
            ################################################################################################################
            cmatrix = self.input.v('cMatrix')
            if cmatrix is not None:
                c, cMatrix = cFunction(None,
                                       cmatrix,
                                       F,
                                       Fsurf,
                                       Fbed,
                                       self.input,
                                       hasMatrix=True)
            else:
                c, cMatrix = cFunction(self.ws,
                                       self.Kv,
                                       F,
                                       Fsurf,
                                       Fbed,
                                       self.input,
                                       hasMatrix=False)
            c = c.reshape((jmax + 1, kmax + 1, ftot))
        else:
            c = np.zeros((jmax + 1, kmax + 1, ftot))

        d['hatc2'] = {}
        d['hatc2']['a'] = {}
        d['hatc2']['a']['erosion'] = {}
        d['hatc2']['a']['erosion'][
            'river_river'] = ny.eliminateNegativeFourier(c, 2)
        return d
Exemplo n.º 2
0
    def component(self, ws, Kv, Kh):
        jmax = self.input.v('grid', 'maxIndex', 'x')
        kmax = self.input.v('grid', 'maxIndex', 'z')
        fmax = self.input.v('grid', 'maxIndex', 'f')

        z = ny.dimensionalAxis(self.input.slice('grid'), 'z')[:, :, 0]
        depth = (self.input.v('grid', 'low', 'z', range(0, jmax+1)) - self.input.v('grid', 'high', 'z', range(0, jmax+1))).reshape((jmax+1, 1))
        B = self.input.v('B', range(0, jmax+1))

        u0 = self.input.v('u0', range(0, jmax+1), range(0, kmax+1), range(0, fmax+1))
        w0 = self.input.v('w0', range(0, jmax+1), range(0, kmax+1), range(0, fmax+1))
        zeta0 = self.input.v('zeta0', range(0, jmax+1), [0], range(0, fmax+1))

        ################################################################################################################
        # Leading order
        ################################################################################################################
        Chat = np.zeros((jmax+1, kmax+1, fmax+1), dtype=complex)
        if ws[0,0] != 0:
            k = depth*ws[:, [-1]]/Kv[:, [-1]]*(1-np.exp(-ws[:, [-1]]/Kv[:, [-1]]*depth))**-1.
        else:
            k = 1
        Chat[:, :, 0] = k*np.exp(-ws[:, [-1]]/Kv[:, [-1]]*(z+depth))        # k is such that depth-av Chat = 1.

        Chatx = ny.derivative(Chat, 'x', self.input.slice('grid'))
        Chatz = -(ws[:, [-1]]/Kv[:, [-1]]).reshape((jmax+1, 1, 1))*Chat

        ################################################################################################################
        # First order
        ################################################################################################################
        F = np.zeros((jmax+1, kmax+1, 2*fmax+1, 2), dtype=complex)
        Fsurf = np.zeros((jmax+1, 1, 2*fmax+1, 2), dtype=complex)
        Fbed = np.zeros((jmax+1, 1, 2*fmax+1, 2), dtype=complex)

        ## forcing terms
        # advection
        F[:, :, fmax:, 0] = -ny.complexAmplitudeProduct(u0, Chatx, 2) - ny.complexAmplitudeProduct(w0, Chatz, 2)
        F[:, :, fmax:, 1] = -ny.complexAmplitudeProduct(u0, Chat, 2)

        ## solve
        Chat1, _ = pFunction(1, ws, Kv, F[:, :, fmax+1], Fsurf[:, :, fmax+1], Fbed[:, :, fmax+1], self.input)
        Chat1 = ny.eliminateNegativeFourier(Chat1, 2)

        ################################################################################################################
        # Closure
        ################################################################################################################
        # transport
        T = {}
        T['adv'] = {}
        T['adv']['tide'] = np.real(ny.integrate(ny.complexAmplitudeProduct(u0, Chat1[:, :, :, 0], 2), 'z', kmax, 0, self.input.slice('grid'))[:, 0, 0]*B)
        for key in self.input.getKeysOf('u1'):
            utemp = self.input.v('u1', key, range(0, jmax+1), range(0, kmax+1), range(0, fmax+1))
            try:
                T['adv'][key] += np.real(ny.integrate(ny.complexAmplitudeProduct(utemp, Chat, 2), 'z', kmax, 0, self.input.slice('grid'))[:, 0, 0]*B)
            except:
                T['adv'][key] = np.real(ny.integrate(ny.complexAmplitudeProduct(utemp, Chat, 2), 'z', kmax, 0, self.input.slice('grid'))[:, 0, 0]*B)
        T['dif'] = - np.real(ny.integrate(ny.complexAmplitudeProduct(Kh, Chatx, 2), 'z', kmax, 0, self.input.slice('grid'))[:, 0, 0]*B)
        T['noflux'] = np.real(ny.complexAmplitudeProduct(ny.complexAmplitudeProduct(u0[:, [0], :], Chat[:, [0], :], 2), zeta0, 2)[:, 0, 0]*B)

        F = {}
        F['adv'] = {}
        F['adv']['tide'] = np.real(ny.integrate(ny.complexAmplitudeProduct(u0, Chat1[:, :, :, -1], 2), 'z', kmax, 0, self.input.slice('grid'))[:, 0, 0]*B)
        F['dif'] = - np.real(Kh[:, 0]*depth[:, 0]*B)

        H1 = np.real(depth[:, 0]*B)

        return T, F, H1, Chat[:, :, 0]
Exemplo n.º 3
0
    def run(self):
        self.logger.info('Running module SedDynamic - first order')
        d = {}

        jmax = self.input.v('grid', 'maxIndex', 'x')
        kmax = self.input.v('grid', 'maxIndex', 'z')
        fmax = self.input.v('grid', 'maxIndex', 'f')
        ftot = 2*fmax+1
        OMEGA = self.input.v('OMEGA')
        self.submodulesToRun = ny.toList(self.input.v('submodules'))
        method = self.input.v('erosion_formulation')
        frictionpar = self.input.v('friction')      # friction parameter used for the erosion, by default the total roughness
        if frictionpar == None:
            frictionpar = 'Roughness'

        ################################################################################################################
        # Left hand side
        ################################################################################################################
        Av = self.input.v('Av', range(0, jmax+1), range(0, kmax+1), range(0, fmax+1))
        Kv = self.input.v('Kv', range(0, jmax+1), range(0, kmax+1), range(0, fmax+1))

        # NB. If Kv is not provided on input, use the module DiffusivityUndamped to compute it. This is a fix for making this module easier to use.
        if Kv is None:
            from DiffusivityUndamped import DiffusivityUndamped
            sr = self.input.v('sigma_rho')
            if sr is None:  # add Prandtl-Schmidt number if it does not exist
                self.input.addData('sigma_rho', 1.)
            md = DiffusivityUndamped(self.input)
            self.input.merge(md.run())
            Kv = self.input.v('Kv', range(0, jmax+1), range(0, kmax+1), range(0, fmax+1))
            d['Kv'] = Kv

        ws = self.input.v('ws0', range(0, jmax+1), range(0, kmax+1), range(0, fmax+1))
        ################################################################################################################
        # Forcing terms
        ################################################################################################################
        if 'sedadv' in self.submodulesToRun and 'sedadv_ax' not in self.submodulesToRun:
            self.submodulesToRun.append('sedadv_ax')
        # determine number of submodules
        nRHS = len(self.submodulesToRun)
        if 'erosion' in self.submodulesToRun:
            keysu1 = self.input.getKeysOf('u1')
            try:
                keysu1.remove('mixing')     # flow due to 'mixing' should not be included in the erosion term
            except:
                pass
            self.submodulesToRun.remove('erosion')  #move to the end of the list
            self.submodulesToRun.append('erosion')
            nRHS = nRHS - 1 + len(self.input.getKeysOf('u1'))

        F = np.zeros([jmax+1, kmax+1, ftot, nRHS], dtype=complex)
        Fsurf = np.zeros([jmax+1, 1, ftot, nRHS], dtype=complex)
        Fbed = np.zeros([jmax+1, 1, ftot, nRHS], dtype=complex)

        c0 = self.input.v('hatc0')
        cx0 = self.input.d('hatc0', dim='x')
        cz0 = self.input.d('hatc0', dim='z')
        # 1. Erosion
        if 'erosion' in self.submodulesToRun:
            # erosion due to first-order bed shear stress
            # E = erosion(ws, Av, 1, self.input, method)                        # 24-04-2017 Obsolete
            # Fbed[:, :, fmax:, self.submodulesToRun.index('erosion')] = -E     # 24-04-2017 Obsolete
            for submod in keysu1:
                E = erosion(ws, 1, self.input, method, submodule=(None, submod), friction=frictionpar)
                Fbed[:, :, fmax:, len(self.submodulesToRun)-1 + keysu1.index(submod)] = -E

        # 2. Advection
        if 'sedadv' in self.submodulesToRun:
            u0 = self.input.v('u0', range(0, jmax+1), range(0, kmax+1), range(0, fmax+1))
            w0 = self.input.v('w0', range(0, jmax+1), range(0, kmax+1), range(0, fmax+1))

            eta = ny.complexAmplitudeProduct(u0, cx0, 2)+ny.complexAmplitudeProduct(w0, cz0, 2)
            F[:, :, fmax:, self.submodulesToRun.index('sedadv')] = -eta
            F[:, :, fmax:, self.submodulesToRun.index('sedadv_ax')] = -ny.complexAmplitudeProduct(u0, c0, 2)

        # 3. First-order fall velocity
        if 'fallvel' in self.submodulesToRun:
            # surface and internal terms
            ws1 = self.input.v('ws1', range(0, jmax+1), range(0, kmax+1), range(0, fmax+1))
            ksi = ny.complexAmplitudeProduct(ws1, c0, 2)
            ksiz = ny.derivative(ksi, 'z', self.input.slice('grid'))
            zeta0 = self.input.v('zeta0', range(0, jmax+1), 0, range(0, fmax+1))

            F[:, :, fmax:, self.submodulesToRun.index('fallvel')] = ksiz
            Fsurf[:, 0, fmax:, self.submodulesToRun.index('fallvel')] = -ny.complexAmplitudeProduct(ksiz[:,0,:], zeta0, 1)

            # adjustment to erosion
            E = erosion(ws1, 0, self.input, method, friction=frictionpar)
            Fbed[:, :, fmax:, self.submodulesToRun.index('fallvel')] = -E

        # 4. First-order eddy diffusivity
        if 'mixing' in self.submodulesToRun:
            # surface, bed and internal terms
            Kv1 = self.input.v('Kv1', range(0, jmax+1), range(0, kmax+1), range(0, fmax+1))
            psi = ny.complexAmplitudeProduct(Kv1, cz0, 2)
            psiz = ny.derivative(psi, 'z', self.input.slice('grid'))

            F[:, :, fmax:, self.submodulesToRun.index('mixing')] = psiz
            Fsurf[:, 0, fmax:, self.submodulesToRun.index('mixing')] = -psi[:, 0, :]
            Fbed[:, 0, fmax:, self.submodulesToRun.index('mixing')] = -psi[:, -1, :]

            # adjustment to erosion
            E = erosion(ws, 1, self.input, method, submodule=(None, 'mixing'), friction=frictionpar)
            Fbed[:, :, fmax:, self.submodulesToRun.index('mixing')] = -E

        # 5. No-flux surface correction
        if 'noflux' in self.submodulesToRun:
            zeta0 = self.input.v('zeta0', range(0, jmax+1), [0], range(0, fmax+1))
            D = np.zeros((jmax+1, 1, fmax+1, fmax+1), dtype=complex)
            D[:, :, range(0, fmax+1), range(0, fmax+1)] = np.arange(0, fmax+1)*1j*OMEGA
            Dc0 = ny.arraydot(D, c0[:, [0], :])

            chi = ny.complexAmplitudeProduct(Dc0, zeta0, 2)
            Fsurf[:, :, fmax:, self.submodulesToRun.index('noflux')] = -chi

        ################################################################################################################
        # Solve equation
        ################################################################################################################
        cmatrix = self.input.v('cMatrix')
        if cmatrix is not None:
            c, cMatrix = cFunction(None, cmatrix, F, Fsurf, Fbed, self.input, hasMatrix = True)
        else:
            c, cMatrix = cFunction(ws, Kv, F, Fsurf, Fbed, self.input, hasMatrix = False)
        c = c.reshape((jmax+1, kmax+1, ftot, nRHS))
        c = ny.eliminateNegativeFourier(c, 2)

        ################################################################################################################
        # Prepare output
        ################################################################################################################
        d['hatc1'] = {}
        d['hatc1']['a'] = {}
        d['hatc1']['ax'] = {}
        for i, submod in enumerate(self.submodulesToRun):
            if submod == 'sedadv_ax':
                d['hatc1']['ax']['sedadv'] = c[:, :, :, i]
            elif submod == 'erosion':
                d['hatc1']['a']['erosion'] = {}
                for j, subsubmod in enumerate(keysu1):
                    d['hatc1']['a']['erosion'][subsubmod] = c[:, :, :, len(self.submodulesToRun)-1+j]
            else:
                d['hatc1']['a'][submod] = c[:, :, :, i]
        if 'sedadv' not in self.submodulesToRun:
            d['hatc1']['ax'] = 0

        return d
Exemplo n.º 4
0
def svarFunction(Kv, F, Fsurf, Fbed, data, hasMatrix=False):
    """Solve a function
    Ds - (Kv s_z)_z = -u0_z + F
    subject to
        Kv s_z (-H) = Fbed
        Kv s_z (0) = Fsurf

    The returned solution has a part 'sCoef' and 'szCoef' for the forcing by u_z and a part 'sForced' and 'szForced' for the
    forcing by F, Fbed and Fsurf.

    Args:
        Kv: (ndarray(jmax+1, kmax+1, fmax+1)) - data on eddy diffusivity
            or a salinityMatrix as calculated before by this function.
        F: (ndarray(jmax+1, kmax+1, fmax+1, nRHS)) - interior forcing. nRHS is the number of individual forcing components
        Fsurf: (ndarray(jmax+1, 1, fmax+1, nRHS)) - surface forcing. nRHS is the number of individual forcing components
        Fbed: (ndarray(jmax+1, 1, fmax+1, nRHS)) - surface forcing. nRHS is the number of individual forcing components
        data: (DataContainer) - should at least contain 'grid', 'OMEGA' and 'u0'
        hasMatrix: (bool) - if True then it is assumed that Kv contains a salinityMatrix as calculated by this function before.
                            The matrix is not computed again, which saves time.

    Returns:
        sCoef and szCoef: (ndarray(jmax+1, kmax+1, fmax+1, 1)) the solution s and its vertical derivative for the forcing by u0_z.
                            the final dimension '1' denotes a single forcing component.
        sForced and szForced: (ndarray(jmax+1, kmax+1, fmax+1, nRHS)) the solution s and its vertical derivative for the other forcings.
                            the solution is separated for each RHS term in F, Fsurf and Fbed.
        salinityMatrix: matrix used in computation. Can be reused for subsequent calls of this function.
    """
    # Init
    jmax = data.v('grid', 'maxIndex', 'x')  # maximum index of x grid (jmax+1 grid points incl. 0)
    kmax = data.v('grid', 'maxIndex', 'z')  # maximum index of z grid (kmax+1 grid points incl. 0)
    fmax = data.v('grid', 'maxIndex', 'f')  # maximum index of f grid (fmax+1 grid points incl. 0)
    OMEGA = data.v('OMEGA')
    uz = data.d('u0', range(0, jmax+1), range(0, kmax+1), range(0, fmax+1), dim='z')
    u0bed = data.v('u0', range(0, jmax+1), [-1], range(0, fmax+1))
    ftot = 2*fmax+1

    # Determine bandwidth of eddy viscosity matrix
    bandwidth = 0
    for n in np.arange(fmax, -1, -1):
        if np.any(abs(Kv[:, :, n]) > 0):
            bandwidth = max(bandwidth, n)

    # Init Ctd
    nRHS = F.shape[-1]
    salinityMatrix = np.empty([jmax+1, 2*ftot+2*bandwidth+1, ftot*(kmax+1)], dtype=complex)
    szCoef = np.zeros([jmax+1, kmax+1, fmax+1, 1], dtype=complex)
    szForced = np.zeros([jmax+1, kmax+1, fmax+1, nRHS], dtype=complex)

    # build, save and solve the velocity matrices in every water column
    for j in range(0, jmax+1):
        # dz vectors
        dz = (data.v('grid', 'axis', 'z')[0, 1:]-data.v('grid', 'axis', 'z')[0, 0:-1])*data.n('H', j)
        dz = dz.reshape(dz.shape[0])
        dz_down = dz[:kmax-1].reshape(kmax-1, 1, 1)
        dz_up = dz[1:kmax].reshape(kmax-1, 1, 1)
        dz_av = 0.5*(dz_down+dz_up)

        ##### LEFT HAND SIDE #####
        if not hasMatrix:
            # Init
            A = np.zeros([2*ftot+2*bandwidth+1, ftot*(kmax+1)], dtype=complex)
            N = np.zeros([kmax+1, 2*bandwidth+1, ftot], dtype=complex)

            # Build eddy viscosity matrix blocks
            N[:, bandwidth, :] = Kv[j, :, 0].reshape(kmax+1, 1)*np.ones([1, ftot])
            for n in range(1, bandwidth+1):
                N[:, bandwidth+n, :-n] = 0.5*Kv[j, :, n].reshape(kmax+1, 1)*np.ones([1, ftot])
                N[:, bandwidth-n, n:] = 0.5*np.conj(Kv[j, :, n]).reshape(kmax+1, 1)*np.ones([1, ftot])

            # Build matrix. Discretisation: central for second derivative, central for first derivative
            #  NB. can use general numerical schemes as dz < 0
            a = -N[:-2, :, :]/dz_down
            b = N[1:kmax, :, :]/dz_up+N[1:kmax, :, :]/dz_down
            c = -N[2:, :, :]/dz_up
            b[:, bandwidth, :] += (np.arange(-fmax, ftot-fmax)*1j*OMEGA).reshape((1, ftot))*dz_av.reshape((kmax-1, 1))

            a = np.swapaxes(a, 0, 1)
            b = np.swapaxes(b, 0, 1)
            c = np.swapaxes(c, 0, 1)

            # Build matrix
            A[2*ftot:2*ftot+2*bandwidth+1, :-2*ftot] = a.reshape(a.shape[0], a.shape[1]*a.shape[2])
            A[2*fmax+1:2*fmax+2*bandwidth+2, ftot:-ftot] = b.reshape(a.shape[0], a.shape[1]*a.shape[2])
            A[0:2*bandwidth+1, 2*ftot:] = c.reshape(a.shape[0], a.shape[1]*a.shape[2])

            # Boundary conditions
            #   Surface (k=0)
            A[2*fmax+1:2*fmax+2*bandwidth+2, :ftot] = N[0, :, :]

            #   Bed (k=kmax)
            A[2*fmax+1:2*fmax+2*bandwidth+2, -ftot:] = N[-1, :, :]

            # save matrix
            salinityMatrix[j, Ellipsis] = A[Ellipsis]
            bandwidthA = bandwidth+ftot
        else:
            A = Kv[j, Ellipsis]     # if hasMatrix Av replaces the role of the matrix in this equation
            bandwidthA = (A.shape[0]-1)/2


        ##### RIGHT HAND SIDE #####
        #   Implicit part of the forcing uz0*dz*Sx
        umat = np.zeros((kmax+1, ftot), dtype=complex)
        umat[1:-1, fmax:ftot] = -uz[j, 1:-1, :]*dz_av.reshape((kmax-1, 1))
        uRHS_implicit = umat.reshape((ftot*(kmax+1), 1))

        #   Forcing from other factors
        uRHS = np.zeros([ftot*(kmax+1), nRHS], dtype=complex)
        uRHS[fmax:ftot, :] = Fsurf[j, 0, :, :]
        uRHS[-ftot+fmax:, :] = Fbed[j, 0, :, :]
        F_full = np.concatenate((np.zeros((jmax+1, kmax+1, fmax, nRHS)), F), 2)
        uRHS[ftot:-ftot, :] = 0.5*(F_full[j, 2:, :, :]-F_full[j, :-2, :, :]).reshape((kmax-1)*ftot, nRHS)

        ##### SOLVE #####
        sz = solve_banded((bandwidthA, bandwidthA), A, np.concatenate((uRHS_implicit, uRHS), 1), overwrite_ab=True, overwrite_b=True)
        sz = sz.reshape(kmax+1, ftot, 1+nRHS)
        szCoef[j, :, :, :] = ny.eliminateNegativeFourier(sz[:, :, :1], 1)
        szForced[j, :, :, :] = ny.eliminateNegativeFourier(sz[:, :, 1:], 1)
        del sz, uRHS_implicit, uRHS

    ##### INTEGRATION CONSTANT #####
    SIGMASAL = data.v('SIGMASAL')
    if hasMatrix:
        KvBed = data.v('Av', range(0, jmax+1), [kmax-1, kmax], range(0, fmax+1))/SIGMASAL # TODO: shift to turbulence model
    else:
        KvBed = Kv[:, [kmax-1, kmax], :]

    Dinv = np.diag((np.arange(0, fmax+1)*1j*OMEGA))
    Dinv[0, 0] = np.inf
    Dinv[range(0, fmax+1), range(0, fmax+1)] = Dinv[range(0, fmax+1), range(0, fmax+1)]**(-1)
    z = ny.dimensionalAxis(data.slice('grid'), 'z')
    dzbed = z[:, [-1], 0] - z[:, [-2], 0]
    sbedCoef = -ny.complexAmplitudeProduct(KvBed[:, [-2], :], szCoef[:, [-2], :, :], 2)/dzbed.reshape(dzbed.shape+(1, 1)) - u0bed.reshape(u0bed.shape+(1,))
    sbedCoef = np.dot(Dinv, sbedCoef)
    sbedCoef = np.rollaxis(sbedCoef, 0, 3)
    sbedForced = (Fbed-ny.complexAmplitudeProduct(KvBed[:, [-2], :], szForced[:, [-2], :, :], 2))/dzbed.reshape(dzbed.shape+(1, 1)) + F[:, [-1], :, :]
    sbedForced = np.dot(Dinv, sbedForced)
    sbedForced = np.rollaxis(sbedForced, 0, 3)

    ##### INTEGRATION #####
    sCoef = ny.integrate(szCoef, 'z', kmax, np.arange(0, kmax+1), data.slice('grid')) + sbedCoef*np.ones((1, kmax+1, 1, 1))
    sForced = ny.integrate(szForced, 'z', kmax, np.arange(0, kmax+1), data.slice('grid')) + sbedForced*np.ones((1, kmax+1, 1, 1))

    ##### CLOSURE FOR THE DEPTH-AVERAGED TIME-AVERAGED SALINITY VARIATION #####
    H = data.v('H', range(0, jmax+1)).reshape((jmax+1, 1, 1, 1))
    sCoef[:, :, [0], :] -= (ny.integrate(sCoef[:, :, [0], :], 'z', kmax, 0, data.slice('grid'))/H)*np.ones((1, kmax+1, 1, 1))
    sForced[:, :, [0], :] -= (ny.integrate(sForced[:, :, [0], :], 'z', kmax, 0, data.slice('grid'))/H)*np.ones((1, kmax+1, 1, 1))

    if hasMatrix:
        return sCoef, sForced, szCoef, szForced, Kv
    else:
        return sCoef, sForced, szCoef, szForced, salinityMatrix
Exemplo n.º 5
0
    def run(self):
        """

        Returns:
            Dictionary with results. At least contains the variables listed as output in the registry
        """
        self.logger.info('Running module HydroFirst')

        # Init
        jmax = self.input.v('grid', 'maxIndex', 'x')
        kmax = self.input.v('grid', 'maxIndex', 'z')
        fmax = self.input.v('grid', 'maxIndex', 'f')
        G = self.input.v('G')
        BETA = self.input.v('BETA')
        OMEGA = self.input.v('OMEGA')
        ftot = 2 * fmax + 1
        submodulesToRun = self.input.v('submodules')

        # check if the river term should be compensated for by reference level. Only if river is on, non-zero and there is no leading-order contribution
        if 'river' in submodulesToRun and self.input.v(
                'Q1') != 0 and not np.any(
                    self.input.v('zeta0', 'river', range(0, jmax + 1), 0, 0)):
            RiverReferenceCompensation = 1
        else:
            RiverReferenceCompensation = 0

        ################################################################################################################
        # velocity as function of water level
        ################################################################################################################
        ## LHS terms
        #   try to get velocityMatrix from the input. If it is not found, proceed to calculate the matrix again
        A = self.input.v(
            'velocityMatrix'
        )  # known that this is numeric data, ask without arguments to retrieve full ndarray
        velocityMatrix = True
        if A is None:
            A = self.input.v('Av', range(0, jmax + 1), range(0, kmax + 1),
                             range(0, fmax + 1))
            velocityMatrix = False
        else:
            A = A

        ## RHS terms
        #   Determine number/names of right hand side
        submodulesVelocityForcing = [
            i for i in ['adv', 'nostress', 'baroc', 'mixing', 'river']
            if i in submodulesToRun
        ]
        #submodulesVelocityConversion = [i for i, mod in enumerate(submodulesToRun) if mod in ['adv', 'nostress', 'baroc', 'mixing']]
        submodulesVelocityConversion = [
            submodulesToRun.index(i) for i in submodulesVelocityForcing
        ]
        nRHS = len(submodulesVelocityForcing)
        F = np.zeros([jmax + 1, kmax + 1, ftot, nRHS], dtype=complex)
        Fsurf = np.zeros([jmax + 1, 1, ftot, nRHS], dtype=complex)
        Fbed = np.zeros([jmax + 1, 1, ftot, nRHS], dtype=complex)
        uFirst = np.zeros([jmax + 1, kmax + 1, ftot,
                           len(submodulesToRun)],
                          dtype=complex)
        uzFirst = np.zeros([jmax + 1, kmax + 1, ftot,
                            len(submodulesToRun)],
                           dtype=complex)

        u0 = self.input.v('u0', range(0, jmax + 1), range(0, kmax + 1),
                          range(0, fmax + 1))
        zeta0 = self.input.v('zeta0', range(0, jmax + 1), [0],
                             range(0, fmax + 1))

        if RiverReferenceCompensation:  # for reference level variation
            F[:, :, fmax,
              submodulesVelocityForcing.index('river')] = -G * self.input.d(
                  'R', range(0, jmax + 1), dim='x').reshape(
                      (jmax + 1, 1)) * np.ones((1, kmax + 1))

        if 'adv' in submodulesVelocityForcing:
            u0x = self.input.d('u0',
                               range(0, jmax + 1),
                               range(0, kmax + 1),
                               range(0, fmax + 1),
                               dim='x')
            u0z = self.input.d('u0',
                               range(0, jmax + 1),
                               range(0, kmax + 1),
                               range(0, fmax + 1),
                               dim='z')
            w0 = self.input.v('w0', range(0, jmax + 1), range(0, kmax + 1),
                              range(0, fmax + 1))
            eta = ny.complexAmplitudeProduct(
                u0, u0x, 2) + ny.complexAmplitudeProduct(w0, u0z, 2)
            eta = np.concatenate((np.zeros([jmax + 1, kmax + 1, fmax]), eta),
                                 2)
            F[:, :, :, submodulesVelocityForcing.index('adv')] = -eta
        if 'nostress' in submodulesVelocityForcing:
            D = (np.arange(0, fmax + 1) * 1j * OMEGA).reshape(
                (1, 1, fmax + 1)) * np.ones((jmax + 1, 1, 1))
            zeta0x = self.input.d('zeta0',
                                  range(0, jmax + 1), [0],
                                  range(0, fmax + 1),
                                  dim='x')
            chi = D * u0[:, [0], :] + G * zeta0x
            chi = ny.complexAmplitudeProduct(chi, zeta0, 2)
            chi = np.concatenate((np.zeros([jmax + 1, 1, fmax]), chi), 2)
            Fsurf[:, :, :, submodulesVelocityForcing.index('nostress')] = -chi
        if 'baroc' in submodulesVelocityForcing:
            sx = self.input.d('s0',
                              range(0, jmax + 1),
                              range(0, kmax + 1),
                              range(0, fmax + 1),
                              dim='x')
            Jsx = -ny.integrate(
                sx, 'z', 0, range(0, kmax + 1), self.input.slice('grid')
            )  # integral from z to 0 has its boundaries inverted and has a minus sign to compensate
            Jsx = np.concatenate((np.zeros([jmax + 1, kmax + 1, fmax]), Jsx),
                                 2)
            F[:, :, :,
              submodulesVelocityForcing.index('baroc')] = -G * BETA * Jsx
        if 'mixing' in submodulesVelocityForcing:
            u0z = self.input.d('u0',
                               range(0, jmax + 1),
                               range(0, kmax + 1),
                               range(0, fmax + 1),
                               dim='z')
            Av1 = self.input.v('Av1', range(0, jmax + 1), range(0, kmax + 1),
                               range(0, fmax + 1))
            ksi = ny.complexAmplitudeProduct(u0z, Av1, 2)
            ksiz = ny.derivative(ksi, 1, self.input.slice('grid'))

            ksi = np.concatenate((np.zeros([jmax + 1, kmax + 1, fmax]), ksi),
                                 2)
            ksiz = np.concatenate((np.zeros([jmax + 1, kmax + 1, fmax]), ksiz),
                                  2)
            F[:, :, :, submodulesVelocityForcing.index('mixing')] = ksiz
            Fsurf[:, :, :,
                  submodulesVelocityForcing.index('mixing')] = -ksi[:, [0],
                                                                    Ellipsis]

            ## Removed 14-7-2017 YMD: Roughness1*u0 and Av1*u0z should be equal, so this term cancels
            # if self.input.v('BottomBC') in ['PartialSlip']:
            #     Fbed[:, :, :, submodulesVelocityForcing.index('mixing')] = -ksi[:,[kmax],Ellipsis]
            #     roughness1 = self.input.v('Roughness1', range(0, jmax+1), [0], range(0, fmax+1))
            #     if roughness1 is not None:
            #         ksi = ny.complexAmplitudeProduct(u0[:, [-1], :], roughness1, 2)
            #         ksi = np.concatenate((np.zeros([jmax+1, 1, fmax]), ksi), 2)
            #         Fbed[:, :, :, submodulesVelocityForcing.index('mixing')] = ksi

        ## Solve equation
        uCoef, uFirst[:, :, :,
                      submodulesVelocityConversion], uzCoef, uzFirst[:, :, :,
                                                                     submodulesVelocityConversion], _ = uFunctionMomentumConservative(
                                                                         A,
                                                                         F,
                                                                         Fsurf,
                                                                         Fbed,
                                                                         self.
                                                                         input,
                                                                         hasMatrix
                                                                         =velocityMatrix
                                                                     )

        ################################################################################################################
        # water level
        ################################################################################################################
        ## LHS terms
        #   try to get zetaMatrix from the input. If it is not found, proceed to calculate the matrix again
        B = self.input.v(
            'zetaMatrix'
        )  # known that this is numeric data, ask without arguments to retrieve full ndarray
        zetaMatrix = True
        if B is None:
            zetaMatrix = False
            utemp = uCoef.reshape(
                uCoef.shape[:2] + (1, ) + uCoef.shape[2:]
            )  # reshape as the 'f' dimension is not grid conform; move it to a higher dimension
            JuCoef = ny.integrate(utemp, 'z', kmax, 0,
                                  self.input.slice('grid'))
            JuCoef = JuCoef.reshape(jmax + 1, 1, ftot,
                                    ftot)  # reshape back to original grid
            B = -G * JuCoef * self.input.v('B', np.arange(
                0, jmax + 1)).reshape(jmax + 1, 1, 1, 1)

        ## RHS terms
        #   advection, no-stress, baroclinic
        utemp = uFirst.reshape(
            uFirst.shape[:2] + (1, ) + uFirst.shape[2:]
        )  # reshape as the 'f' dimension is not grid conform; move it to a higher dimension
        JuFirst = ny.integrate(utemp, 'z', kmax, 0, self.input.slice('grid'))
        JuFirst = JuFirst.reshape(
            jmax + 1, 1, ftot,
            uFirst.shape[-1])  # reshape back to original grid

        #   stokes
        if 'stokes' in submodulesToRun:
            gamma = ny.complexAmplitudeProduct(u0[:, 0, None, Ellipsis], zeta0,
                                               2)
            gamma = np.concatenate((np.zeros([jmax + 1, 1, fmax]), gamma), 2)
            JuFirst[:, :, :, submodulesToRun.index('stokes')] = gamma
        BJuFirst = JuFirst * self.input.v('B', np.arange(0, jmax + 1)).reshape(
            jmax + 1, 1, 1, 1)

        #   open BC: tide
        Fopen = np.zeros([1, 1, ftot, len(submodulesToRun)], dtype=complex)
        if 'tide' in submodulesToRun:
            Fopen[0, 0, fmax:,
                  submodulesToRun.index('tide')] = ny.amp_phase_input(
                      self.input.v('A1'), self.input.v('phase1'), (fmax + 1, ))

        #   closed BC: river
        Fclosed = np.zeros([1, 1, ftot, len(submodulesToRun)], dtype=complex)
        if 'river' in submodulesToRun:
            Fclosed[0, 0, fmax,
                    submodulesToRun.index('river')] = -self.input.v('Q1')

        #   closed BC: other terms
        Fclosed += -JuFirst[jmax, 0, :, :] * self.input.v('B', jmax)

        ## Solve equation
        zetaCoef, zetaxCoef, _ = zetaFunctionMassConservative(
            B, BJuFirst, Fopen, Fclosed, self.input, hasMatrix=zetaMatrix)
        zetax = ny.eliminateNegativeFourier(zetaxCoef, 2)
        zeta = ny.eliminateNegativeFourier(zetaCoef, 2)

        ################################################################################################################
        # velocity
        ################################################################################################################
        u = np.empty((jmax + 1, kmax + 1, ftot, len(submodulesToRun)),
                     dtype=uCoef.dtype)
        uz = np.empty((jmax + 1, kmax + 1, ftot, len(submodulesToRun)),
                      dtype=uCoef.dtype)
        for j in range(0, jmax + 1):
            u[j, :, :, :] = np.dot(uCoef[j, :, :, :],
                                   -G * zetaxCoef[j, 0, :, :])
            uz[j, :, :, :] = np.dot(uzCoef[j, :, :, :],
                                    -G * zetaxCoef[j, 0, :, :])
        u += uFirst
        uz += uzFirst
        u = ny.eliminateNegativeFourier(u, 2)
        uz = ny.eliminateNegativeFourier(uz, 2)

        ################################################################################################################
        # vertical velocity
        ################################################################################################################
        w = self.verticalVelocity(u)

        ################################################################################################################
        # Make final dictionary to return
        ################################################################################################################
        d = {}
        d['zeta1'] = {}
        d['u1'] = {}
        d['w1'] = {}
        for i, submod in enumerate(submodulesToRun):
            nf = ny.functionTemplates.NumericalFunctionWrapper(
                zeta[:, :, :, i], self.input.slice('grid'))
            nf.addDerivative(zetax[:, :, :, i], 'x')
            d['zeta1'][submod] = nf.function

            nfu = ny.functionTemplates.NumericalFunctionWrapper(
                u[:, :, :, i], self.input.slice('grid'))
            nfu.addDerivative(uz[:, :, :, i], 'z')
            d['u1'][submod] = nfu.function
            d['w1'][submod] = w[:, :, :, i]
        return d
Exemplo n.º 6
0
    def run(self):
        self.logger.info('Running module SedDynamic - leading order')
        d = {}

        jmax = self.input.v('grid', 'maxIndex', 'x')
        kmax = self.input.v('grid', 'maxIndex', 'z')
        fmax = self.input.v('grid', 'maxIndex', 'f')
        ftot = 2 * fmax + 1
        self.submodulesToRun = self.input.v('submodules')
        # H = self.input.v('H', range(0, jmax+1))
        method = self.input.v('erosion_formulation')
        frictionpar = self.input.v(
            'friction'
        )  # friction parameter used for the erosion, by default the total roughness
        if frictionpar == None:
            frictionpar = 'Roughness'

        ################################################################################################################
        # Left hand side
        ################################################################################################################
        Av = self.input.v('Av', range(0, jmax + 1), range(0, kmax + 1),
                          range(0, fmax + 1))
        Kv = self.input.v('Kv', range(0, jmax + 1), range(0, kmax + 1),
                          range(0, fmax + 1))

        # NB. If Kv is not provided on input, use the module DiffusivityUndamped to compute it. This is a fix for making this module easier to use.
        if Kv is None:
            from DiffusivityUndamped import DiffusivityUndamped
            sr = self.input.v('sigma_rho')
            if sr is None:  # add Prandtl-Schmidt number if it does not exist
                self.input.addData('sigma_rho', 1.)
            md = DiffusivityUndamped(self.input)
            self.input.merge(md.run())
            Kv = self.input.v('Kv', range(0, jmax + 1), range(0, kmax + 1),
                              range(0, fmax + 1))
            d['Kv'] = Kv

        ws = self.input.v('ws0', range(0, jmax + 1), range(0, kmax + 1),
                          range(0, fmax + 1))

        ################################################################################################################
        # Forcing terms
        ################################################################################################################
        F = np.zeros([jmax + 1, kmax + 1, ftot, 1], dtype=complex)
        Fsurf = np.zeros([jmax + 1, 1, ftot, 1], dtype=complex)
        Fbed = np.zeros([jmax + 1, 1, ftot, 1], dtype=complex)

        # erosion
        E = erosion(ws, 0, self.input, method, friction=frictionpar)
        Fbed[:, :, fmax:, 0] = -E

        ################################################################################################################
        # Solve equation
        ################################################################################################################
        # Coupled system
        c, cMatrix = cFunction(ws,
                               Kv,
                               F,
                               Fsurf,
                               Fbed,
                               self.input,
                               hasMatrix=False)
        c = c.reshape((jmax + 1, kmax + 1, ftot))
        hatc0 = ny.eliminateNegativeFourier(c, 2)

        # Uncoupled system
        # hatc0 = np.zeros((jmax+1, kmax+1, fmax+1), dtype=complex)
        # hatc0[:, :, 0] = cFunctionUncoupled(ws, Kv, F, Fsurf, Fbed, self.input, 0).reshape((jmax+1, kmax+1))
        # hatc0[:, :, 2] = cFunctionUncoupled(ws, Kv, F, Fsurf, Fbed, self.input, 2).reshape((jmax+1, kmax+1))

        # correction at the bed (optional)
        # cbed00 = E[:, -1, 0]/ws[:, -1, 0]
        # frac = cbed00/hatc0[:, -1, 0]
        # hatc0 = hatc0*frac.reshape((jmax+1, 1, 1))

        ## analytical solutions
        # ahatc0 = np.zeros((jmax+1, kmax+1, fmax+1), dtype=complex)
        # ahatc02 = np.zeros((jmax+1, kmax+1, fmax+1), dtype=complex)
        # z = ny.dimensionalAxis(self.input.slice('grid'), 'z')[:, :, 0]
        # ws = ws[:, 0, 0]
        # Kv = Kv[:, 0, 0]
        # OMEGA = self.input.v('OMEGA')
        # H = self.input.v('H', range(0, jmax+1))
        #
        # # M0
        # ahatc0[:, :, 0] = (E[:, 0, 0]/ws).reshape((jmax+1, 1))*np.exp(-(ws/Kv).reshape((jmax+1, 1))*(z+H.reshape((jmax+1, 1))))
        #
        #
        # # M4
        #
        # r1 = -ws/(2.*Kv)+np.sqrt(ws**2+8*1j*OMEGA*Kv)/(2*Kv)
        # r2 = -ws/(2.*Kv)-np.sqrt(ws**2+8*1j*OMEGA*Kv)/(2*Kv)
        # k2 = -E[:, 0, 2]*(Kv*(-r1*(ws+Kv*r2)/(ws+Kv*r1)*np.exp(-r1*H) + r2*np.exp(-r2*H)))**-1.
        # k1 = -k2*(ws+Kv*r2)/(ws+Kv*r1)
        # ahatc0[:, :, 2] = k1.reshape((jmax+1, 1))*np.exp(r1.reshape((jmax+1, 1))*z) + k2.reshape((jmax+1, 1))*np.exp(r2.reshape((jmax+1, 1))*z)

        # import step as st
        # import matplotlib.pyplot as plt
        #
        # st.configure()
        # plt.figure(1, figsize=(1,3))
        # plt.subplot(1,3,1)
        # plt.plot(np.real(ahatc0[0, :, 0]), z[0, :], label='analytical')
        # plt.plot(np.real(hatc0[0, :, 0]), z[0, :], label='numerical')
        # plt.xlim(0, np.max(np.maximum(abs(ahatc0[0, :, 0]), abs(hatc0[0, :, 0])))*1.05)
        #
        # plt.subplot(1,3,2)
        # plt.plot(np.abs(ahatc0[0, :, 2]), z[0, :], label='analytical')
        # # plt.plot(np.abs(ahatc02[0, :, 2]), z[0, :], label='analytical2')
        # plt.plot(np.abs(hatc0[0, :, 2]), z[0, :], label='numerical')
        # # plt.xlim(np.min(np.minimum(abs(ahatc0[0, :, 2]), abs(hatc0[0, :, 2])))*1.05, np.max(np.maximum(abs(ahatc0[0, :, 2]), abs(hatc0[0, :, 2])))*1.05)
        # plt.legend()
        #
        # plt.subplot(1,3,3)
        # plt.plot(np.imag(ahatc0[0, :, 2]), z[0, :], label='analytical')
        # # plt.plot(np.imag(ahatc02[0, :, 2]), z[0, :], label='analytical2')
        # plt.plot(np.imag(hatc0[0, :, 2]), z[0, :], label='numerical')
        # # plt.xlim(np.min(np.minimum(abs(ahatc0[0, :, 2]), abs(hatc0[0, :, 2])))*1.05, np.max(np.maximum(abs(ahatc0[0, :, 2]), abs(hatc0[0, :, 2])))*1.05)
        # plt.legend()
        # st.show()

        d['hatc0'] = {}
        d['hatc0']['a'] = {}
        d['hatc0']['a']['erosion'] = hatc0

        return d
Exemplo n.º 7
0
    def leading_order(self, d):
        jmax = self.input.v('grid', 'maxIndex', 'x')
        kmax = self.input.v('grid', 'maxIndex', 'z')
        fmax = self.input.v('grid', 'maxIndex', 'f')
        ftot = 2 * fmax + 1

        ################################################################################################################
        # Forcing terms
        ################################################################################################################
        F = np.zeros([jmax + 1, kmax + 1, ftot, 1], dtype=complex)
        Fsurf = np.zeros([jmax + 1, 1, ftot, 1], dtype=complex)
        Fbed = np.zeros([jmax + 1, 1, ftot, 1], dtype=complex)

        # erosion
        E = erosion(self.ws,
                    0,
                    self.input,
                    self.erosion_method,
                    friction=self.frictionpar)
        Fbed[:, :, fmax:, 0] = -E

        ################################################################################################################
        # Solve equation
        ################################################################################################################
        # Coupled system
        c, cMatrix = cFunction(self.ws,
                               self.Kv,
                               F,
                               Fsurf,
                               Fbed,
                               self.input,
                               hasMatrix=False)
        c = c.reshape((jmax + 1, kmax + 1, ftot))
        hatc0 = ny.eliminateNegativeFourier(c, 2)

        # Uncoupled system
        # hatc0 = np.zeros((jmax+1, kmax+1, fmax+1), dtype=complex)
        # hatc0[:, :, 0] = cFunctionUncoupled(self.ws, self.Kv, F, Fsurf, Fbed, self.input, 0).reshape((jmax+1, kmax+1))
        # hatc0[:, :, 2] = cFunctionUncoupled(self.ws, self.Kv, F, Fsurf, Fbed, self.input, 2).reshape((jmax+1, kmax+1))

        # correction at the bed (optional)
        # cbed00 = E[:, -1, 0]/self.ws[:, -1, 0]
        # frac = cbed00/hatc0[:, -1, 0]
        # hatc0 = hatc0*frac.reshape((jmax+1, 1, 1))

        ## analytical solutions
        # ahatc0 = np.zeros((jmax+1, kmax+1, fmax+1), dtype=complex)
        # ahatc02 = np.zeros((jmax+1, kmax+1, fmax+1), dtype=complex)
        # z = ny.dimensionalAxis(self.input.slice('grid'), 'z')[:, :, 0]
        # self.ws = self.ws[:, 0, 0]
        # self.Kv = self.Kv[:, 0, 0]
        # OMEGA = self.input.v('OMEGA')
        # H = self.input.v('H', range(0, jmax+1))
        #
        # # M0
        # ahatc0[:, :, 0] = (E[:, 0, 0]/self.ws).reshape((jmax+1, 1))*np.exp(-(self.ws/self.Kv).reshape((jmax+1, 1))*(z+H.reshape((jmax+1, 1))))
        #
        #
        # # M4
        #
        # r1 = -self.ws/(2.*self.Kv)+np.sqrt(self.ws**2+8*1j*OMEGA*self.Kv)/(2*self.Kv)
        # r2 = -self.ws/(2.*self.Kv)-np.sqrt(self.ws**2+8*1j*OMEGA*self.Kv)/(2*self.Kv)
        # k2 = -E[:, 0, 2]*(self.Kv*(-r1*(self.ws+self.Kv*r2)/(self.ws+self.Kv*r1)*np.exp(-r1*H) + r2*np.exp(-r2*H)))**-1.
        # k1 = -k2*(self.ws+self.Kv*r2)/(self.ws+self.Kv*r1)
        # ahatc0[:, :, 2] = k1.reshape((jmax+1, 1))*np.exp(r1.reshape((jmax+1, 1))*z) + k2.reshape((jmax+1, 1))*np.exp(r2.reshape((jmax+1, 1))*z)

        # import step as st
        # import matplotlib.pyplot as plt
        #
        # st.configure()
        # plt.figure(1, figsize=(1,3))
        # plt.subplot(1,3,1)
        # plt.plot(np.real(ahatc0[0, :, 0]), z[0, :], label='analytical')
        # plt.plot(np.real(hatc0[0, :, 0]), z[0, :], label='numerical')
        # plt.xlim(0, np.max(np.maximum(abs(ahatc0[0, :, 0]), abs(hatc0[0, :, 0])))*1.05)
        #
        # plt.subplot(1,3,2)
        # plt.plot(np.abs(ahatc0[0, :, 2]), z[0, :], label='analytical')
        # # plt.plot(np.abs(ahatc02[0, :, 2]), z[0, :], label='analytical2')
        # plt.plot(np.abs(hatc0[0, :, 2]), z[0, :], label='numerical')
        # # plt.xlim(np.min(np.minimum(abs(ahatc0[0, :, 2]), abs(hatc0[0, :, 2])))*1.05, np.max(np.maximum(abs(ahatc0[0, :, 2]), abs(hatc0[0, :, 2])))*1.05)
        # plt.legend()
        #
        # plt.subplot(1,3,3)
        # plt.plot(np.imag(ahatc0[0, :, 2]), z[0, :], label='analytical')
        # # plt.plot(np.imag(ahatc02[0, :, 2]), z[0, :], label='analytical2')
        # plt.plot(np.imag(hatc0[0, :, 2]), z[0, :], label='numerical')
        # # plt.xlim(np.min(np.minimum(abs(ahatc0[0, :, 2]), abs(hatc0[0, :, 2])))*1.05, np.max(np.maximum(abs(ahatc0[0, :, 2]), abs(hatc0[0, :, 2])))*1.05)
        # plt.legend()
        # st.show()

        d['hatc0'] = {}
        d['hatc0']['a'] = {}
        d['hatc0']['a']['erosion'] = hatc0
        d['cMatrix'] = cMatrix
        return d
Exemplo n.º 8
0
    def first_order(self, d):
        jmax = self.input.v('grid', 'maxIndex', 'x')
        kmax = self.input.v('grid', 'maxIndex', 'z')
        fmax = self.input.v('grid', 'maxIndex', 'f')
        ftot = 2 * fmax + 1
        OMEGA = self.input.v('OMEGA')

        ################################################################################################################
        # Forcing terms
        ################################################################################################################
        if 'sedadv' in self.submodulesToRun and 'sedadv_ax' not in self.submodulesToRun:
            self.submodulesToRun.append('sedadv_ax')
        # determine number of submodules
        nRHS = len(self.submodulesToRun)
        if 'erosion' in self.submodulesToRun:
            keysu1 = self.input.getKeysOf('u1')
            try:
                keysu1.remove(
                    'mixing'
                )  # flow due to 'mixing' should not be included in the erosion term
            except:
                pass
            self.submodulesToRun.remove(
                'erosion')  # move to the end of the list
            self.submodulesToRun.append('erosion')
            nRHS = nRHS - 1 + len(self.input.getKeysOf('u1'))

        F = np.zeros([jmax + 1, kmax + 1, ftot, nRHS], dtype=complex)
        Fsurf = np.zeros([jmax + 1, 1, ftot, nRHS], dtype=complex)
        Fbed = np.zeros([jmax + 1, 1, ftot, nRHS], dtype=complex)

        self.input.merge(d)
        c0 = self.input.v('hatc0', range(0, jmax + 1), range(0, kmax + 1),
                          range(0, fmax + 1))
        cx0 = self.input.d('hatc0',
                           range(0, jmax + 1),
                           range(0, kmax + 1),
                           range(0, fmax + 1),
                           dim='x')
        cz0 = self.input.d('hatc0',
                           range(0, jmax + 1),
                           range(0, kmax + 1),
                           range(0, fmax + 1),
                           dim='z')
        # 1. Erosion
        if 'erosion' in self.submodulesToRun:
            # erosion due to first-order bed shear stress
            # E = erosion(self.ws, Av, 1, self.input, self.erosion_method)                        # 24-04-2017 Obsolete
            # Fbed[:, :, fmax:, self.submodulesToRun.index('erosion')] = -E     # 24-04-2017 Obsolete
            for submod in keysu1:
                E = erosion(self.ws,
                            1,
                            self.input,
                            self.erosion_method,
                            submodule=(None, submod),
                            friction=self.frictionpar)
                Fbed[:, :, fmax:,
                     len(self.submodulesToRun) - 1 + keysu1.index(submod)] = -E

        # 2. Advection
        if 'sedadv' in self.submodulesToRun:
            u0 = self.input.v('u0', range(0, jmax + 1), range(0, kmax + 1),
                              range(0, fmax + 1))
            w0 = self.input.v('w0', range(0, jmax + 1), range(0, kmax + 1),
                              range(0, fmax + 1))

            eta = ny.complexAmplitudeProduct(
                u0, cx0, 2) + ny.complexAmplitudeProduct(w0, cz0, 2)
            F[:, :, fmax:, self.submodulesToRun.index('sedadv')] = -eta
            F[:, :, fmax:,
              self.submodulesToRun.
              index('sedadv_ax')] = -ny.complexAmplitudeProduct(u0, c0, 2)

        # 3. First-order fall velocity
        if 'fallvel' in self.submodulesToRun:
            # surface and internal terms
            ws1 = self.input.v('ws1', range(0, jmax + 1), range(0, kmax + 1),
                               range(0, fmax + 1))
            ksi = ny.complexAmplitudeProduct(ws1, c0, 2)
            ksiz = ny.derivative(ksi, 'z', self.input.slice('grid'))

            F[:, :, fmax:, self.submodulesToRun.index('fallvel')] = ksiz
            Fsurf[:, 0, fmax:,
                  self.submodulesToRun.index('fallvel')] = -ksi[:, 0, :]

            # adjustment to erosion; only if erosion depends on the settling velocity
            if self.erosion_method == 'Chernetsky':
                E = erosion(ws1,
                            0,
                            self.input,
                            self.erosion_method,
                            friction=self.frictionpar)
                Fbed[:, :, fmax:, self.submodulesToRun.index('fallvel')] = -E

        # 4. First-order eddy diffusivity
        if 'mixing' in self.submodulesToRun:
            # surface, bed and internal terms
            Kv1 = self.input.v('Kv1', range(0, jmax + 1), range(0, kmax + 1),
                               range(0, fmax + 1))
            psi = ny.complexAmplitudeProduct(Kv1, cz0, 2)
            psiz = ny.derivative(psi, 'z', self.input.slice('grid'))

            F[:, :, fmax:, self.submodulesToRun.index('mixing')] = psiz
            Fsurf[:, 0, fmax:,
                  self.submodulesToRun.index('mixing')] = -psi[:, 0, :]
            Fbed[:, 0, fmax:,
                 self.submodulesToRun.index('mixing')] = -psi[:, -1, :]

            # adjustment to erosion
            E = erosion(self.ws,
                        1,
                        self.input,
                        self.erosion_method,
                        submodule=(None, 'mixing'),
                        friction=self.frictionpar)
            Fbed[:, :, fmax:, self.submodulesToRun.index('mixing')] = -E

        # 5. No-flux surface correction
        if 'noflux' in self.submodulesToRun:
            zeta0 = self.input.v('zeta0', range(0, jmax + 1), [0],
                                 range(0, fmax + 1))
            D = np.zeros((jmax + 1, 1, fmax + 1, fmax + 1), dtype=complex)
            D[:, :, range(0, fmax + 1),
              range(0, fmax + 1)] = np.arange(0, fmax + 1) * 1j * OMEGA
            Dc0 = ny.arraydot(D, c0[:, [0], :])

            chi = ny.complexAmplitudeProduct(Dc0, zeta0, 2)
            Fsurf[:, :, fmax:, self.submodulesToRun.index('noflux')] = -chi

        ################################################################################################################
        # Solve equation
        ################################################################################################################
        cmatrix = self.input.v('cMatrix')
        if cmatrix is not None:
            c, cMatrix = cFunction(None,
                                   cmatrix,
                                   F,
                                   Fsurf,
                                   Fbed,
                                   self.input,
                                   hasMatrix=True)
        else:
            c, cMatrix = cFunction(self.ws,
                                   self.Kv,
                                   F,
                                   Fsurf,
                                   Fbed,
                                   self.input,
                                   hasMatrix=False)
        c = c.reshape((jmax + 1, kmax + 1, ftot, nRHS))
        c = ny.eliminateNegativeFourier(c, 2)

        ################################################################################################################
        # Prepare output
        ################################################################################################################
        d['hatc1'] = {}
        d['hatc1']['a'] = {}
        d['hatc1']['ax'] = {}
        for i, submod in enumerate(self.submodulesToRun):
            if submod == 'sedadv_ax':
                d['hatc1']['ax']['sedadv'] = c[:, :, :, i]
            elif submod == 'erosion':
                d['hatc1']['a']['erosion'] = {}
                for j, subsubmod in enumerate(keysu1):
                    d['hatc1']['a']['erosion'][
                        subsubmod] = c[:, :, :,
                                       len(self.submodulesToRun) - 1 + j]
            else:
                d['hatc1']['a'][submod] = c[:, :, :, i]
        if 'sedadv' not in self.submodulesToRun:
            d['hatc1']['ax'] = 0

        return d
Exemplo n.º 9
0
    def run(self):
        self.logger.info('Running module SedDynamic - second order')
        d = {}

        jmax = self.input.v('grid', 'maxIndex', 'x')
        kmax = self.input.v('grid', 'maxIndex', 'z')
        fmax = self.input.v('grid', 'maxIndex', 'f')
        ftot = 2 * fmax + 1
        self.submodulesToRun = self.input.v('submodules')
        method = self.input.v('erosion_formulation')
        frictionpar = self.input.v(
            'friction'
        )  # friction parameter used for the erosion, by default the total roughness
        if frictionpar == None:
            frictionpar = 'Roughness'

        ################################################################################################################
        # Left hand side
        ################################################################################################################
        Av = self.input.v('Av', range(0, jmax + 1), range(0, kmax + 1),
                          range(0, fmax + 1))
        Kv = self.input.v('Kv', range(0, jmax + 1), range(0, kmax + 1),
                          range(0, fmax + 1))

        # NB. If Kv is not provided on input, use the module DiffusivityUndamped to compute it. This is a fix for making this module easier to use.
        if Kv is None:
            from DiffusivityUndamped import DiffusivityUndamped
            sr = self.input.v('sigma_rho')
            if sr is None:  # add Prandtl-Schmidt number if it does not exist
                self.input.addData('sigma_rho', 1.)
            md = DiffusivityUndamped(self.input)
            self.input.merge(md.run())
            Kv = self.input.v('Kv', range(0, jmax + 1), range(0, kmax + 1),
                              range(0, fmax + 1))
            d['Kv'] = Kv

        ws = self.input.v('ws0', range(0, jmax + 1), range(0, kmax + 1),
                          range(0, fmax + 1))

        ################################################################################################################
        # Forcing terms
        ################################################################################################################
        F = np.zeros([jmax + 1, kmax + 1, ftot, 1], dtype=complex)
        Fsurf = np.zeros([jmax + 1, 1, ftot, 1], dtype=complex)
        Fbed = np.zeros([jmax + 1, 1, ftot, 1], dtype=complex)

        # erosion
        if self.input.v('u1', 'river') is not None:
            E = erosion(ws,
                        2,
                        self.input,
                        method,
                        submodule=(None, 'river', None),
                        friction=frictionpar)
            Fbed[:, :, fmax:, 0] = -E

            ################################################################################################################
            # Solve equation
            ################################################################################################################
            c, cMatrix = cFunction(ws,
                                   Kv,
                                   F,
                                   Fsurf,
                                   Fbed,
                                   self.input,
                                   hasMatrix=False)
            c = c.reshape((jmax + 1, kmax + 1, ftot))
        else:
            c = np.zeros((jmax + 1, kmax + 1, ftot))

        d['hatc2'] = {}
        d['hatc2']['a'] = {}
        d['hatc2']['a']['erosion'] = {}
        d['hatc2']['a']['erosion'][
            'river_river'] = ny.eliminateNegativeFourier(c, 2)
        return d
Exemplo n.º 10
0
    def run(self):
        """

        Returns:
            Dictionary with results. At least contains the variables listed as output in the registry
        """
        self.logger.info('Running module HydroLead')

        # Init
        jmax = self.input.v('grid', 'maxIndex', 'x')
        kmax = self.input.v('grid', 'maxIndex', 'z')
        fmax = self.input.v('grid', 'maxIndex', 'f')
        G = self.input.v('G')
        ftot = 2 * fmax + 1
        submodulesToRun = self.input.v('submodules')

        # check if the river term should be compensated for by reference level. Only if river is on and non-zero
        if 'river' in submodulesToRun and self.input.v('Q0') != 0:
            RiverReferenceCompensation = 1
        else:
            RiverReferenceCompensation = 0

        ################################################################################################################
        # velocity as function of water level
        ################################################################################################################
        # build, save and solve the velocity matrices in every water column
        Av = self.input.v('Av', range(0, jmax + 1), range(0, kmax + 1),
                          range(0, fmax + 1))
        F = np.zeros([jmax + 1, kmax + 1, ftot, RiverReferenceCompensation])
        Fsurf = np.zeros([jmax + 1, 1, ftot, RiverReferenceCompensation])
        Fbed = np.zeros([jmax + 1, 1, ftot, RiverReferenceCompensation])

        if RiverReferenceCompensation:  # for reference level variation
            F[:, :, fmax,
              0] = -G * self.input.d('R', range(0, jmax + 1), dim='x').reshape(
                  (jmax + 1, 1)) * np.ones((1, kmax + 1))

        uCoef, uLead, uzCoef, uzLead, velocityMatrix = uFunctionMomentumConservative(
            Av, F, Fsurf, Fbed, self.input)

        ################################################################################################################
        # water level
        ################################################################################################################
        ## LHS terms
        utemp = uCoef.reshape(
            uCoef.shape[:2] + (1, ) + uCoef.shape[2:]
        )  # reshape as the 'f' dimension is not grid conform; move it to a higher dimension
        JuCoef = ny.integrate(utemp, 'z', kmax, 0, self.input.slice('grid'))
        JuCoef = JuCoef.reshape(jmax + 1, 1, ftot,
                                ftot)  # reshape back to original grid
        BJuCoef = -G * JuCoef * self.input.v('B', np.arange(
            0, jmax + 1)).reshape(jmax + 1, 1, 1, 1)

        #   open BC: tide
        Fopen = np.zeros([1, 1, ftot, len(submodulesToRun)], dtype=complex)
        if 'tide' in submodulesToRun:
            Fopen[0, 0, fmax:,
                  submodulesToRun.index('tide')] = ny.amp_phase_input(
                      self.input.v('A0'), self.input.v('phase0'), (fmax + 1, ))

        #   closed BC: river
        Fclosed = np.zeros([1, 1, ftot, len(submodulesToRun)], dtype=complex)
        if RiverReferenceCompensation:
            Fclosed[0, 0, fmax,
                    submodulesToRun.index('river')] = -self.input.v('Q0')

        ## RHS terms
        IntForce = np.zeros(
            [jmax + 1, 1, ftot, len(submodulesToRun)], dtype=complex)
        if RiverReferenceCompensation:
            utemp = uLead.reshape(
                uLead.shape[:2] + (1, ) + uLead.shape[2:]
            )  # reshape as the 'f' dimension is not grid conform; move it to a higher dimension
            JuLead = ny.integrate(utemp, 'z', kmax, 0,
                                  self.input.slice('grid'))
            JuLead = JuLead.reshape(jmax + 1, 1, ftot) * self.input.v(
                'B', np.arange(0, jmax + 1)).reshape(
                    jmax + 1, 1, 1)  # reshape back to original grid
            IntForce[:, :, :, submodulesToRun.index('river')] = JuLead[:, :, :]
            Fclosed[0, 0, :,
                    submodulesToRun.index('river')] += -JuLead[jmax, 0, :]

        ## Solve equation
        zetaCoef, zetaxCoef, zetaMatrix = zetaFunctionMassConservative(
            BJuCoef, IntForce, Fopen, Fclosed, self.input)
        zetax = ny.eliminateNegativeFourier(zetaxCoef, 2)
        zeta = ny.eliminateNegativeFourier(zetaCoef, 2)

        ################################################################################################################
        # velocity
        ################################################################################################################
        u = np.empty((jmax + 1, kmax + 1, ftot, len(submodulesToRun)),
                     dtype=uCoef.dtype)
        uz = np.empty((jmax + 1, kmax + 1, ftot, len(submodulesToRun)),
                      dtype=uCoef.dtype)
        for j in range(0, jmax + 1):
            u[j, :, :, :] = np.dot(uCoef[j, :, :, :],
                                   -G * zetaxCoef[j, 0, :, :])
            uz[j, :, :, :] = np.dot(uzCoef[j, :, :, :],
                                    -G * zetaxCoef[j, 0, :, :])
        if RiverReferenceCompensation:
            u[:, :, :, submodulesToRun.index('river')] += uLead[:, :, :, 0]
            uz[:, :, :, submodulesToRun.index('river')] += uzLead[:, :, :, 0]
        u = ny.eliminateNegativeFourier(u, 2)
        uz = ny.eliminateNegativeFourier(uz, 2)
        ################################################################################################################
        # vertical velocity
        ################################################################################################################
        w = self.verticalVelocity(u)

        ################################################################################################################
        # Make final dictionary to return
        ################################################################################################################
        d = {}
        d['velocityMatrix'] = velocityMatrix
        d['zetaMatrix'] = zetaMatrix
        d['zeta0'] = {}
        d['u0'] = {}
        d['w0'] = {}
        for i, submod in enumerate(submodulesToRun):
            nf = ny.functionTemplates.NumericalFunctionWrapper(
                zeta[:, :, :, i], self.input.slice('grid'))
            nf.addDerivative(zetax[:, :, :, i], 'x')
            d['zeta0'][submod] = nf.function

            nfu = ny.functionTemplates.NumericalFunctionWrapper(
                u[:, :, :, i], self.input.slice('grid'))
            nfu.addDerivative(uz[:, :, :, i], 'z')
            d['u0'][submod] = nfu.function
            d['w0'][submod] = w[:, :, :, i]

        return d
Exemplo n.º 11
0
    def run(self):
        self.currentOrder = self.input.v('order')
        if self.currentOrder < 2:
            return
        # Init
        if self.currentOrder == 2:
            maxOrder = self.input.v('maxOrder')
            jmax = self.input.v('grid', 'maxIndex', 'x')
            fmax = self.input.v('grid', 'maxIndex', 'f')
            OMEGA = self.input.v('OMEGA')
            G = self.input.v('G')
            self.submodulesToRun = self.input.v('submodules')

            # initialise arrays with surface stress and velocity data
            self.surf_stress = np.nan * np.empty(
                (jmax + 1, 1, fmax + 1, maxOrder, maxOrder),
                dtype=complex)  # x, z, f, order, derivative
            self.surf_u_der = np.nan * np.empty(
                (jmax + 1, 1, fmax + 1, maxOrder, maxOrder + 2),
                dtype=complex)  # x, z, f, order, derivative

            # update those parts of these arrays that are not updated later
            #   surface stress
            D = (np.arange(0, fmax + 1) * 1j * OMEGA).reshape(
                (1, 1, fmax + 1)) * np.ones((jmax + 1, 1, 1))
            u0 = self.input.v('u0', range(0, jmax + 1), [0],
                              range(0, fmax + 1))
            zeta0x = self.input.d('zeta0',
                                  range(0, jmax + 1), [0],
                                  range(0, fmax + 1),
                                  dim='x')
            self.surf_stress[:, :, :, 0, 0] = D * u0[:, [0], :] + G * zeta0x

            #   surface der of u
            self.surf_u_der[:, :, :, 0, 0] = u0
            self.surf_u_der[:, :, :, 0, 1] = self.input.d('u0',
                                                          range(0, jmax + 1),
                                                          [0],
                                                          range(0, fmax + 1),
                                                          dim='z')
            Av = self.input.v('Av', range(0, jmax + 1), [0],
                              range(0, fmax + 1))
            Avz = self.input.d('Av',
                               range(0, jmax + 1), [0],
                               range(0, fmax + 1),
                               dim='z')
            u0z = self.input.d('u0',
                               range(0, jmax + 1), [0],
                               range(0, fmax + 1),
                               dim='z')
            self.surf_u_der[:, :, :, 0, 2] = -self.Avinv_multiply(
                Av, (ny.complexAmplitudeProduct(Avz, u0z, 2) -
                     self.surf_stress[:, :, :, 0, 0]))

        self.logger.info('Running module HydroHigher - order ' +
                         str(self.currentOrder))
        # Init
        jmax = self.input.v('grid', 'maxIndex', 'x')
        kmax = self.input.v('grid', 'maxIndex', 'z')
        fmax = self.input.v('grid', 'maxIndex', 'f')
        G = self.input.v('G')
        BETA = self.input.v('BETA')
        ftot = 2 * fmax + 1
        try:
            maxContributions = int(self.input.v('maxContributions'))
        except:
            maxContributions = self.input.v('maxContributions')
        d = {}

        # update surf_stress and surf_u_der
        self.updateSurfaceData()

        ################################################################################################################
        # Velocity in terms of water level gradient
        ################################################################################################################
        ## LHS terms
        #   try to get velocityMatrix from the input. If it is not found, proceed to calculate the matrix again
        A = self.input.v(
            'velocityMatrix'
        )  # known that this is numeric data, ask without arguments to retrieve full ndarray
        velocityMatrix = True
        if A is None:
            A = self.input.v('Av', range(0, jmax + 1), range(0, kmax + 1),
                             range(0, fmax + 1))
            velocityMatrix = False

        ## RHS terms
        #   Determine number/names of right hand side
        nRHS, nRHSVelocity = self.__numberOfForcings()
        f_index = -1
        f_names = []

        # instantiate the forcing components in the equation
        F = np.zeros([jmax + 1, kmax + 1, ftot, nRHSVelocity], dtype=complex)
        Fsurf = np.zeros([jmax + 1, 1, ftot, nRHSVelocity], dtype=complex)
        Fbed = np.zeros([jmax + 1, 1, ftot, nRHSVelocity], dtype=complex)
        JuFirst = np.zeros([jmax + 1, 1, ftot, nRHS], dtype=complex)
        uFirst = np.zeros([jmax + 1, kmax + 1, ftot, nRHS], dtype=complex)
        uzFirst = np.zeros([jmax + 1, kmax + 1, ftot, nRHS], dtype=complex)

        # determine RHS terms per submodule - first for velocity
        # 1. Advection
        if 'adv' in self.submodulesToRun:
            for order1 in range(0, self.currentOrder):
                order2 = self.currentOrder - order1 - 1

                # labels and submodules
                u_str1 = 'u' + str(order1)
                u_keys1 = self.input.getKeysOf(u_str1)
                u_str2 = 'u' + str(order2)
                u_keys2 = self.input.getKeysOf(u_str2)
                w_str = 'w' + str(order1)

                # retrieve data and make advection forcing
                for submod1 in u_keys1:
                    for submod2 in u_keys2:
                        u = self.input.v(u_str1, submod1, range(0, jmax + 1),
                                         range(0, kmax + 1),
                                         range(0, fmax + 1))
                        ux = self.input.d(u_str2,
                                          submod2,
                                          range(0, jmax + 1),
                                          range(0, kmax + 1),
                                          range(0, fmax + 1),
                                          dim='x')
                        w = self.input.v(w_str, submod1, range(0, jmax + 1),
                                         range(0, kmax + 1),
                                         range(0, fmax + 1))
                        uz = self.input.d(u_str2,
                                          submod2,
                                          range(0, jmax + 1),
                                          range(0, kmax + 1),
                                          range(0, fmax + 1),
                                          dim='z')

                        eta = ny.complexAmplitudeProduct(
                            u, ux, 2) + ny.complexAmplitudeProduct(w, uz, 2)
                        eta = np.concatenate(
                            (np.zeros([jmax + 1, kmax + 1, fmax]), eta), 2)
                        f_index += 1
                        f_names.append([
                            'adv',
                            submod1 + str(order1) + '-' + submod2 + str(order2)
                        ])
                        F[:, :, :, f_index] = -eta
                        del eta

        # 2. No-Stress
        if 'nostress' in self.submodulesToRun:
            chi = 0
            for m in range(1, self.currentOrder + 1):
                for k in range(0, self.currentOrder - m + 1):
                    zetapermutations = self.multiindex(
                        m, self.currentOrder - m - k)
                    # a. make the zeta^m product
                    zetasum = 0
                    for perm in range(0, zetapermutations.shape[0]):
                        zetaname = 'zeta' + str(zetapermutations[perm, 0])
                        zeta = self.input.v(zetaname, range(0, jmax + 1), [0],
                                            range(0, fmax + 1))
                        for comp in range(1, zetapermutations.shape[1]):
                            zetaname = 'zeta' + str(zetapermutations[perm,
                                                                     comp])
                            zeta2 = self.input.v(zetaname, range(0, jmax + 1),
                                                 [0], range(0, fmax + 1))
                            zeta = ny.complexAmplitudeProduct(zeta, zeta2, 2)
                        zetasum = zetasum + zeta

                    # b. make the (Av*uz)^(m) term (use m-1 as surf_stress contains (Av*uz)_z^(m))
                    Avuz = self.surf_stress[:, :, :, k, m - 1]

                    # c. add all to chi
                    chi += 1. / np.math.factorial(
                        m) * ny.complexAmplitudeProduct(Avuz, zetasum, 2)

            chi = np.concatenate((np.zeros([jmax + 1, 1, fmax]), chi), 2)

            f_index += 1
            f_names.append(['nostress', ''])
            Fsurf[:, :, :, f_index] = -chi
            del chi

        # 3. Density-drift # TODO
        # if 'densitydrift' in self.submodulesToRun:
        #     beta_delta = 0
        #     for m in range(1, self.currentOrder):
        #         for k in range(0, self.currentOrder-m):
        #             zetapermutations = self.multiindex(m, self.currentOrder-m-k-1)
        #             # a. make the zeta^m product
        #             zetasum = 0
        #             for perm in range(0, zetapermutations.shape[0]):
        #                 zetaname = 'zeta'+str(zetapermutations[perm, 0])
        #                 zeta = self.input.v(zetaname, range(0, jmax+1), [0], range(0, fmax+1))
        #                 for comp in range(1, zetapermutations.shape[1]):
        #                     zetaname = 'zeta'+str(zetapermutations[perm, comp])
        #                     zeta2 = self.input.v(zetaname, range(0, jmax+1), [0], range(0, fmax+1))
        #                     zeta = ny.complexAmplitudeProduct(zeta, zeta2, 2)
        #                 zetasum = zetasum + zeta
        #
        #             # b. make the (s_x)^(m) term
        #             sname = 's'+str(k)
        #             sx = self.input.d(sname, range(0, jmax+1), range(0, kmax+1), range(0, fmax+1), dim='x')
        #             sxmdz = self.surfaceDerivative(sx, m-1, self.NUMORDER_SURFACE)
        #
        #             # c. add all to beta_delta
        #             beta_delta += G*BETA*1./np.math.factorial(m)*ny.complexAmplitudeProduct(sxmdz, zetasum, 2)
        #
        #     beta_delta = np.concatenate((np.zeros([jmax+1, 1, fmax]), beta_delta), 2)
        #
        #     f_index += 1
        #     f_names.append(['densitydrift', ''])
        #     F[:, :, :, f_index] = -beta_delta*np.ones((jmax+1, kmax+1, fmax+1))

        # 4. Baroclinic
        #   Only use this when salinity on lower order is available
        if 'baroc' in self.submodulesToRun:
            s_str = 's' + str(self.currentOrder - 1)
            sx = self.input.d(s_str,
                              range(0, jmax + 1),
                              range(0, kmax + 1),
                              range(0, fmax + 1),
                              dim='x')
            if sx is not None:
                Jsx = -G * BETA * ny.integrate(
                    sx, 'z', 0, range(0, kmax + 1), self.input.slice('grid')
                )  # integral from z to 0 has its boundaries inverted and has a minus sign to compensate
                Jsx = np.concatenate(
                    (np.zeros([jmax + 1, kmax + 1, fmax]), Jsx), 2)
                f_index += 1
                f_names.append(['baroc', ''])
                F[:, :, :, f_index] = -Jsx
                del Jsx, sx

        # 5. Mixing
        if 'mixing' in self.submodulesToRun:
            ksi = np.zeros([jmax + 1, kmax + 1, fmax + 1], dtype=complex)
            for m in range(1, self.currentOrder + 1):
                Avm = self.input.v('Av' + str(m), range(0, jmax + 1),
                                   range(0, kmax + 1), range(0, fmax + 1))
                if Avm is not None:
                    uz = self.input.d('u' + str(self.currentOrder - m),
                                      range(0, jmax + 1),
                                      range(0, kmax + 1),
                                      range(0, fmax + 1),
                                      dim='z')
                    ksi += ny.complexAmplitudeProduct(Avm, uz, 2)

            ksi_z = ny.derivative(ksi, 'z', self.input.slice('grid'))
            ksi = np.concatenate((np.zeros([jmax + 1, kmax + 1, fmax]), ksi),
                                 2)
            ksi_z = np.concatenate(
                (np.zeros([jmax + 1, kmax + 1, fmax]), ksi_z), 2)

            f_index += 1
            f_names.append(['mixing', 'general'])
            F[:, :, :, f_index] = ksi_z
            Fsurf[:, :, :, f_index] = -ksi[:, [0], :]
            if self.input.v('BottomBC') in ['PartialSlip']:
                Fbed[:, :, :, f_index] = -ksi[:, [-1], :]

                # 5.b higher order no-slip coefficient
                for m in range(1, self.currentOrder + 1):
                    roughness = self.input.v('Roughness' + str(m),
                                             range(0, jmax + 1), [0],
                                             range(0, fmax + 1))
                    if roughness is not None:
                        u_str1 = 'u' + str(self.currentOrder - m)
                        u = self.input.v(u_str1, range(0, jmax + 1), [kmax],
                                         range(0, fmax + 1))
                        ksi = ny.complexAmplitudeProduct(u, roughness, 2)
                        ksi = np.concatenate(
                            (np.zeros([jmax + 1, 1, fmax]), ksi), 2)
                        Fbed[:, :, :, f_index] = ksi

        # 5.b Mixing-no-stress interaction
            ksi = np.zeros([jmax + 1, 1, fmax + 1], dtype=complex)
            for m in range(1, self.currentOrder + 1):
                for k in range(0, self.currentOrder - m + 1):
                    for i in range(1, self.currentOrder - m - k + 1):
                        zetapermutations = self.multiindex(
                            m, self.currentOrder - m - k - i)
                        # a. make the zeta^m product
                        zetasum = 0
                        for perm in range(0, zetapermutations.shape[0]):
                            zetaname = 'zeta' + str(zetapermutations[perm, 0])
                            zeta = self.input.v(zetaname, range(0, jmax + 1),
                                                [0], range(0, fmax + 1))
                            for comp in range(1, zetapermutations.shape[1]):
                                zetaname = 'zeta' + str(zetapermutations[perm,
                                                                         comp])
                                zeta2 = self.input.v(zetaname,
                                                     range(0, jmax + 1), [0],
                                                     range(0, fmax + 1))
                                zeta = ny.complexAmplitudeProduct(
                                    zeta, zeta2, 2)
                            zetasum = zetasum + zeta

                        # b. make the (Av*uz)^(m) term
                        Avuz = 0
                        for j in range(0, m + 1):
                            if j == 0:
                                Avder = self.input.v('Av' + str(i),
                                                     range(0, jmax + 1), [0],
                                                     range(0, fmax + 1))
                            else:
                                Avder = self.input.d('Av' + str(i),
                                                     range(0, jmax + 1), [0],
                                                     range(0, fmax + 1),
                                                     dim='z' * j)
                            if Avder is not None:
                                Avuz += scipy.misc.comb(
                                    m, j) * ny.complexAmplitudeProduct(
                                        Avder, self.surf_u_der[:, :, :, k,
                                                               m - j + 1],
                                        2)  # use m-j+1 as we need u_z^(m-j)

                        # c. add all to ksi
                        if not isinstance(Avuz, int):
                            ksi += 1. / np.math.factorial(
                                m) * ny.complexAmplitudeProduct(
                                    Avuz, zetasum, 2)

            ksi = np.concatenate((np.zeros([jmax + 1, 1, fmax]), ksi), 2)

            f_index += 1
            f_names.append(['mixing', 'no-stress'])
            Fsurf[:, :, :, f_index] = -ksi

        # 6. Stokes drift return flow
        # determine RHS terms per submodule - next for water level
        #   Need to place this separate to make sure that stokes term are at the end.
        #   This way they will not be taken into account for velocity equation
        if 'stokes' in self.submodulesToRun:
            gamma = 0
            for m in range(1, self.currentOrder + 1):
                for k in range(0, self.currentOrder - m + 1):
                    zetapermutations = self.multiindex(
                        m, self.currentOrder - m - k)
                    # a. make the zeta^m product
                    zetasum = 0
                    for perm in range(0, zetapermutations.shape[0]):
                        zetaname = 'zeta' + str(zetapermutations[perm, 0])
                        zeta = self.input.v(zetaname, range(0, jmax + 1), [0],
                                            range(0, fmax + 1))
                        for comp in range(1, zetapermutations.shape[1]):
                            zetaname = 'zeta' + str(zetapermutations[perm,
                                                                     comp])
                            zeta2 = self.input.v(zetaname, range(0, jmax + 1),
                                                 [0], range(0, fmax + 1))
                            zeta = ny.complexAmplitudeProduct(zeta, zeta2, 2)
                        zetasum = zetasum + zeta

                    # b. make the (u)^(m-1) term
                    umz = self.surf_u_der[:, :, :, k, m - 1]

                    # c. add all to chi
                    gamma += 1. / np.math.factorial(
                        m) * ny.complexAmplitudeProduct(umz, zetasum, 2)

            gamma = np.concatenate((np.zeros([jmax + 1, 1, fmax]), gamma), 2)

            f_index += 1
            f_names.append(['stokes', ''])
            JuFirst[:, :, :, f_index] = gamma

        ## Solve equation
        uCoef, uFirst[:, :, :, :
                      nRHSVelocity], uzCoef, uzFirst[:, :, :, :
                                                     nRHSVelocity], AMatrix = uFunctionMomentumConservative(
                                                         A,
                                                         F,
                                                         Fsurf,
                                                         Fbed,
                                                         self.input,
                                                         hasMatrix=
                                                         velocityMatrix)
        if not velocityMatrix:
            d['velocityMatrix'] = AMatrix
        del AMatrix

        ################################################################################################################
        # water level
        ################################################################################################################
        ## LHS terms
        #   try to get zetaMatrix from the input. If it is not found, proceed to calculate the matrix again
        B = self.input.v(
            'zetaMatrix'
        )  # known that this is numeric data, ask without arguments to retrieve full ndarray
        zetaMatrix = True
        if B is None:
            zetaMatrix = False
            utemp = uCoef.reshape(
                uCoef.shape[:2] + (1, ) + uCoef.shape[2:]
            )  # reshape as the 'f' dimension is not grid conform; move it to a higher dimension
            JuCoef = ny.integrate(utemp, 'z', kmax, 0,
                                  self.input.slice('grid'))
            JuCoef = JuCoef.reshape(jmax + 1, 1, ftot,
                                    ftot)  # reshape back to original grid
            B = -G * JuCoef * self.input.v('B', np.arange(
                0, jmax + 1)).reshape(jmax + 1, 1, 1, 1)

        ## RHS terms
        #   advection, no-stress, baroclinic
        utemp = uFirst.reshape(
            uFirst.shape[:2] + (1, ) + uFirst.shape[2:]
        )  # reshape as the 'f' dimension is not grid conform; move it to a higher dimension
        JTemp = ny.integrate(utemp, 'z', kmax, 0, self.input.slice('grid'))
        JuFirst += JTemp.reshape(
            jmax + 1, 1, ftot,
            uFirst.shape[-1])  # reshape back to original grid
        BJuFirst = JuFirst * self.input.v('B', np.arange(0, jmax + 1)).reshape(
            jmax + 1, 1, 1, 1)

        #   no open BC forcing & all terms in closed BC
        Fopen = np.zeros([1, 1, ftot, nRHS], dtype=complex)
        Fclosed = np.zeros([1, 1, ftot, nRHS], dtype=complex)
        Fclosed += -JuFirst[jmax, 0, :, :] * self.input.v('B', jmax)

        ## Solve equation
        zetaCoef, zetaxCoef, BMatrix = zetaFunctionMassConservative(
            B, BJuFirst, Fopen, Fclosed, self.input, hasMatrix=zetaMatrix)
        if not zetaMatrix:
            d['zetaMatrix'] = BMatrix
        del BMatrix
        zetax = ny.eliminateNegativeFourier(zetaxCoef, 2)
        zeta = ny.eliminateNegativeFourier(zetaCoef, 2)

        ################################################################################################################
        # velocity
        ################################################################################################################
        u = np.empty((jmax + 1, kmax + 1, ftot, nRHS), dtype=uCoef.dtype)
        for j in range(0, jmax + 1):
            u[j, :, :, :] = np.dot(uCoef[j, :, :, :],
                                   -G * zetaxCoef[j, 0, :, :])
        u += uFirst
        u = ny.eliminateNegativeFourier(u, 2)

        ################################################################################################################
        # Reduce number of components
        ################################################################################################################
        # Select components by their velocity magnitude.
        # This is measured as the 1-norm over z and f and the 2-norm over x
        if maxContributions != 'all':
            for submod in self.submodulesToRun:
                f_names_numbers = zip(
                    f_names, range(0, len(f_names))
                )  # combine forcing names and its position in the 4th dimension of u and zeta
                f_submod = [
                    f_names_numbers[i] for i in range(0, len(f_names))
                    if f_names[i][0] == submod
                ]  # take only the forcing component of a particular submodule

                # determine norm and sort the list
                if f_submod:
                    unorm = [
                        np.linalg.norm(
                            np.linalg.norm(u[:, :, :, i], 1, (1, 2)), 2, 0)
                        for i in zip(*f_submod)[1]
                    ]
                    sorted_fnames = [
                        list(l) for l in zip(*sorted(zip(unorm, f_submod),
                                                     key=lambda nrm: nrm[0]))
                    ]  # sorted list with entries (unorm, (forcing name, forcing position)) with smallest norm first
                else:
                    unorm = []
                    sorted_fnames = []

                # determine the contributions to be aggregated (redundant positions)
                redundant_positions = [
                    sorted_fnames[1][i][1]
                    for i in range(0,
                                   len(unorm) - maxContributions)
                ]
                if len(redundant_positions) >= 1:
                    # replace first redundant element by sum and label 'other'
                    first_red_pos = redundant_positions[0]
                    u[:, :, :,
                      first_red_pos] = np.sum(u[:, :, :, redundant_positions],
                                              3)
                    zeta[:, :, :, first_red_pos] = np.sum(
                        zeta[:, :, :, redundant_positions], 3)
                    f_names[first_red_pos][1] = 'other'

                    # remove other redundant positions
                    u = np.delete(u, redundant_positions[1:], 3)
                    zeta = np.delete(zeta, redundant_positions[1:], 3)
                    [
                        f_names.pop(i)
                        for i in sorted(redundant_positions[1:], reverse=True)
                    ]

        ################################################################################################################
        # vertical velocity
        ################################################################################################################
        w = self.verticalVelocity(u)

        ################################################################################################################
        # Make final dictionary to return
        ################################################################################################################
        d['zeta' + str(self.currentOrder)] = {}
        d['u' + str(self.currentOrder)] = {}
        d['w' + str(self.currentOrder)] = {}

        for submod in self.submodulesToRun:
            if submod in zip(*f_names)[0]:
                d['zeta' + str(self.currentOrder)][submod] = {}
                d['u' + str(self.currentOrder)][submod] = {}
                d['w' + str(self.currentOrder)][submod] = {}

        for i, submod in enumerate(f_names):
            nf = ny.functionTemplates.NumericalFunctionWrapper(
                zeta[:, :, :, i], self.input.slice('grid'))
            nf.addDerivative(zetax[:, :, :, i], 'x')
            if submod == 'baroc':
                d['zeta' + str(self.currentOrder)][submod[0]] = nf.function
                d['u' + str(self.currentOrder)][submod[0]] = u[:, :, :, i]
                d['w' + str(self.currentOrder)][submod[0]] = w[:, :, :, i]
            else:
                d['zeta' +
                  str(self.currentOrder)][submod[0]][submod[1]] = nf.function
                d['u' +
                  str(self.currentOrder)][submod[0]][submod[1]] = u[:, :, :, i]
                d['w' +
                  str(self.currentOrder)][submod[0]][submod[1]] = w[:, :, :, i]

        d['surfder'] = self.surf_u_der
        d['surfstress'] = self.surf_stress
        return d