Example #1
0
def shearstress_exact(tau_order, data, submodule=None, friction='Roughness'):     # Shear stress derived using time series (ordering is difficult)
    jmax = data.v('grid', 'maxIndex', 'x')
    kmax = data.v('grid', 'maxIndex', 'z')
    fmax = data.v('grid', 'maxIndex', 'f')
    fmax = np.maximum(fmax, 3)              ## NB. take fmax 3 at minimum: erosion uses |u0|*u1 which, with standard assumptions, yields an M2 signal for |u0| containing an M2 and M6
    rho0 = data.v('RHO0')
    sf = data.v(friction, range(0, jmax+1), 0, 0)

    if submodule is None:
        submodule = (None, )*(tau_order+1)

    ## 1. bed shear stress
    # the bed shear stress is extended over fmax+1 frequency components to prevent inaccuracies in truncation
    ulist = []
    for i in range(0, tau_order+1):
        if submodule[i] is None:
            u = data.v('u'+str(i), range(0, jmax+1), [kmax], range(0, fmax+1))
        else:
            u = data.v('u'+str(i), submodule[i], range(0, jmax+1), [kmax], range(0, fmax+1))
        if u is None:
            u = np.zeros((jmax+1, 1, fmax+1), dtype=complex)

        ulist.append(u)
    u = sum(ulist)
    utim = ny.invfft(np.concatenate((u, np.zeros((jmax+1, 1, 500))), 2), 2)
    utim = np.abs(utim)
    uabs = ny.fft(utim, 2)[:, :, :fmax+1]
    taub_abs = rho0*sf.reshape((jmax+1, 1, 1))*uabs
    return taub_abs
Example #2
0
def shearstress_truncated(tau_order, data, submodule=None, friction='Roughness'):     # Shear stress derived using time series (truncated, only for standard forcing conditions)
    jmax = data.v('grid', 'maxIndex', 'x')
    kmax = data.v('grid', 'maxIndex', 'z')
    fmax = data.v('grid', 'maxIndex', 'f')
    rho0 = data.v('RHO0')
    sf = data.v(friction, range(0, jmax+1), 0, 0)

    if submodule is None:
        submodule = (None, )*(tau_order+1)

    ## 1. bed shear stress
    # the bed shear stress is extended over fmax+1 frequency components to prevent inaccuracies in truncation
    ulist = []
    for i in range(0, 2):
        if submodule[i] is None:
            u = data.v('u'+str(i), range(0, jmax+1), [kmax], range(0, fmax+1))
        else:
            u = data.v('u'+str(i), submodule[i], range(0, jmax+1), [kmax], range(0, fmax+1))
        if u is None:
            u = np.zeros((jmax+1, 1, fmax+1), dtype=complex)

        ulist.append(u)
    u = sum(ulist)
    utim = ny.invfft2(u, 2, 90)
    utim = np.abs(utim)
    uabs = ny.fft(utim, 2)[:, :, :fmax+1]
    taub_abs = rho0*sf.reshape((jmax+1, 1, 1))*uabs
    if tau_order == 0:
        taub_abs[:, :, 1] =0
    elif tau_order == 1:
        taub_abs[:, :, 0] =0
        taub_abs[:, :, 2] =0
    else:
        taub_abs[:, :, 1:] =0
    return taub_abs
Example #3
0
    def run(self):
        ################################################################################################################
        ## 1. Init
        ################################################################################################################
        # self.timers[0].tic()

        ## prepare output message
        self.logger.info('Running MAW turbulence model')
        denstr = ''
        if self.betac ==0:
            denstr = '- not including density effects'
        self.logger.info('\tMAW rel. difference in Av in last iteration: %s %s' % (self.difference, denstr))

        d = {}

        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')
        rho0 = self.input.v('RHO0')
        uzmin = self.input.v('uzmin')

        Avold = self.input.v('Av', range(0, jmax+1), range(0, kmax+1), range(0, fmax+1))
        Kvold = self.input.v('Kv', range(0, jmax+1), range(0, kmax+1), range(0, fmax+1))
        sfold = self.input.v('Roughness', range(0, jmax+1), 0, 0)
        # self.timers[0].toc()

        ################################################################################################################
        ## 2. KEFitted run
        ################################################################################################################
        # self.timers[1].tic()
        d.update(self.kem.run())
        self.input.merge(d)

        # load data resulting from KEFitted model
        Avmid = self.input.v('Av', range(0, jmax+1), range(0, kmax+1), range(0, fmax+1))
        Kvmid = Avmid/self.input.v('sigma_rho', range(0, jmax+1), range(0, kmax+1), [0])
        sfmid = self.input.v('Roughness', range(0, jmax+1), 0, 0)
        # self.timers[1].toc()

        ################################################################################################################
        ## 3. Density effects
        ################################################################################################################
        if self.betac == 0:     # no density effect included, first let KEFitted spin up
            Av0 = Avmid[:, :, 0]
            Kv0 = Kvmid[:, :, 0]
            sf = sfmid

            Cd = 1.
            MA_av = 1.
            MA_kv = 1.
            Ri = 0.
        else:
            ## Load data
            # self.timers[2].tic()
            cz = self.input.d('c0', range(0, jmax+1), range(0, kmax+1), range(0, fmax+1), dim='z') + self.input.d('c1', range(0, jmax+1), range(0, kmax+1), range(0, fmax+1), dim='z') + self.input.d('c2', range(0, jmax+1), range(0, kmax+1), range(0, fmax+1), dim='z')
            uz = self.input.d('u0', range(0, jmax+1), range(0, kmax+1), range(0, fmax+1), dim='z') + self.input.d('u1', range(0, jmax+1), range(0, kmax+1), range(0, fmax+1), dim='z')
            zeta0 = self.input.v('zeta0', range(0, jmax+1), [0], range(0, fmax+1))
            H = self.input.v('grid', 'low', 'z', range(0, jmax+1)) - self.input.v('grid', 'high', 'z', range(0, jmax+1))
            # self.timers[2].tic()

            ## Convert to time series
            # self.timers[3].tic()
            cz = ny.invfft2(cz, 2, 90)
            uz = ny.invfft2(uz, 2, 90)
            zeta0 = ny.invfft2(zeta0, 2, 90)
            Avmid = ny.invfft2(Avmid, 2, 90)
            Kvmid = ny.invfft2(Kvmid, 2, 90)
            # self.timers[3].toc()
            # self.timers[4].tic()
            uzmin = np.ones(uz.shape)*uzmin

            ## Compute Richardson number
            Ri = -G*self.betac/rho0*cz/(uz**2+uzmin**2)

            Rida = 1./H.reshape((jmax+1, 1, 1))*ny.integrate(Ri.reshape((jmax+1, kmax+1, 1, Ri.shape[-1])), 'z', kmax, 0, self.input.slice('grid')).reshape((jmax+1, 1, Ri.shape[-1]))  # depth-average
            Rida += zeta0*(Ri[:, [0], :]-Rida)/H.reshape((jmax+1, 1, 1))        # depth average continued
            Rida0 = np.maximum(Rida, 0.)                                        # only accept positive Ri
            Ribed = np.maximum(Ri[:, [-1], :], 0.)                              # only accept positive Ri
            Ribedmax = self.input.v('Ribedmax')
            Ribed = np.minimum(Ribed, Ribedmax)                                 # 5-3-2018 limit near-bed Ri

            ## relaxation on Rida
            if hasattr(self, 'Rida'):       # Relaxation of Ri_da using previously saved value
                dRida = self.Rida - Rida0
                Rida = np.max((Rida0, np.min((dRida * (1 - self.RELAX), dRida * (1. + self.RELAX)), axis=0) + Rida0), axis=0)
                Rida = np.min((Rida,   np.max((dRida * (1 - self.RELAX), dRida * (1. + self.RELAX)), axis=0) + Rida0), axis=0)
                self.Rida = Rida
            else:                           # No value saved if the init found an available Ri. Then start with full signal computed here (do not use saved value, as this has been truncated to frequency components)
                Rida = Rida0

            # self.timers[4].toc()

            ## Compute damping functions
            # self.timers[5].tic()
            # Av
            MA_av = (1+10*Rida)**(-0.5)
            dAv = ny.fft(Avmid*MA_av, 2)[:, :, :fmax+1] - Avold
            Av = Avold + (1-self.RELAX)*(self.LOCAL*dAv + .5*(1-self.LOCAL)*dAv[[0]+range(0, jmax), :, :] + .5*(1-self.LOCAL)*dAv[range(1, jmax+1)+[jmax], :, :])
            # Av = Avold + dAv
            Av0 = Av[:, :, 0]

            # Kv
            MA_kv = (1+3.33*Rida)**(-1.5)
            dKv = ny.fft(Kvmid*MA_kv, 2)[:, :, :fmax+1] - Kvold
            Kv = Kvold + (1-self.RELAX)*(self.LOCAL*dKv + .5*(1-self.LOCAL)*dKv[[0]+range(0, jmax), :, :] + .5*(1-self.LOCAL)*dKv[range(1, jmax+1)+[jmax], :, :])
            # Kv = Kvold + dKv
            Kv0 = Kv[:, :, 0]

            # Sf
            Rfmean = np.mean(Ribed[:, 0, :]*(Kvmid*MA_kv)[:, 0, :]/(Avmid*MA_av)[:, 0, :], axis=-1)
            Cd = (1+5.5*Rfmean)**-2.
            damp_sf = Cd
            sf = sfmid*damp_sf
            dsf = sf - sfold
            sf = sfold + (1-self.RELAX)*(self.LOCAL*dsf + .5*(1-self.LOCAL)*dsf[[0]+range(0, jmax)] + .5*(1-self.LOCAL)*dsf[range(1, jmax+1)+[jmax]])
            # self.timers[5].toc()

            # process for output
            MA_av = ny.fft(MA_av, 2)[:, :, :fmax+1]
            MA_kv = ny.fft(MA_kv, 2)[:, :, :fmax+1]
            Ri = ny.fft(Ri, 2)[:, :, :fmax+1]

        ################################################################################################################
        ## Reference level
        ################################################################################################################
        if self.referenceLevel == 'True':
            self.input.merge({'Av': Av0, 'Roughness': sf})
            d['R'] = self.kem.RL.run()['R']

        ################################################################################################################
        ## Compute difference
        ################################################################################################################
        Av0s = ny.savitzky_golay(Av0[:, 0], self.filterlength, 1)
        difference = np.max(abs(Av0s-Avold[:, 0, 0])/abs(Av0s+10**-4))
        self.difference = copy.copy(difference)

        ###############################################################################################################
        # DEBUG plots
        ###############################################################################################################
        # import matplotlib.pyplot as plt
        # import step as st
        # x = ny.dimensionalAxis(self.input.slice('grid'), 'x')[:, 0,0]
        #
        # if self.betac > 0 and np.mod(self.iteration, 3)==0:  # and self.difference>0.15:
        #     st.configure()
        #     plt.figure(1, figsize=(2,2))
        #     plt.subplot(1,2,1)
        #     plt.plot(x/1000., Avold[:, 0, 0], label='old')
        #     plt.plot(x/1000., Av0[:, 0], label='new')
        #     plt.ylim(0, np.maximum(np.max(Av0[:, 0]), np.max(Avold[:, 0, 0])))
        #     plt.legend()
        #
        #     plt.subplot(1,2,2)
        #     plt.plot(x/1000., Avold[:, 0, 0]-Av0[:, 0])
        #     plt.twinx()
        #     plt.plot(x/1000., self.input.v('f', range(0, jmax+1)), color='grey')
        #     plt.ylim(0, 1.)
        #
        #     st.save('plot_'+str(len(x))+'_'+str(self.iteration))
        #
        #     plt.figure(2, figsize=(1, 2))
        #     ws = self.input.v('ws0', range(0, jmax+1), 0, 0)
        #     plt.plot(x/1000., ws)
        #
        #     st.save('ws_'+str(len(x))+'_'+str(self.iteration))


        ################################################################################################################
        ## Prepare Output
        ################################################################################################################
        # self.timers[6].tic()

        x = ny.dimensionalAxis(self.input.slice('grid'),'x')[:, 0,0]
        nf = ny.functionTemplates.NumericalFunctionWrapper(ny.savitzky_golay(Av0[:, 0], self.filterlength, 1).reshape((jmax+1, 1)), self.input.slice('grid'))
        nf.addDerivative(ny.savitzky_golay(ny.derivative(Av0[:, 0], 'x', self.input), self.filterlength, 1).reshape((jmax+1, 1)), 'x')
        nf.addDerivative(ny.savitzky_golay(ny.secondDerivative(Av0[:, 0], 'x', self.input), self.filterlength, 1).reshape((jmax+1, 1)), 'xx')
        d['Av'] = nf.function

        nf2 = ny.functionTemplates.NumericalFunctionWrapper(ny.savitzky_golay(Kv0[:, 0], self.filterlength, 1).reshape((jmax+1, 1)), self.input.slice('grid'))
        nf2.addDerivative(ny.savitzky_golay(ny.derivative(Kv0[:, 0], 'x', self.input), self.filterlength, 1).reshape((jmax+1, 1)), 'x')
        nf2.addDerivative(ny.savitzky_golay(ny.secondDerivative(Kv0[:, 0], 'x', self.input), self.filterlength, 1).reshape((jmax+1, 1)), 'xx')
        d['Kv'] = nf2.function

        d['Roughness'] = sf
        d['skin_friction'] = sfmid
        d['dampingFunctions'] = {}
        d['dampingFunctions']['Roughness'] = Cd
        d['dampingFunctions']['Av'] = MA_av
        d['dampingFunctions']['Kv'] = MA_kv
        d['Ri'] = Ri
        # self.timers[6].toc()

        ## Timers
        # self.timers[0].disp('0 init MAW')
        # self.timers[1].disp('1 KEFitted')
        # self.timers[2].disp('2 load data')
        # self.timers[3].disp('3 invfft')
        # self.timers[4].disp('4 Ri')
        # self.timers[5].disp('5 Compute Av, Kv, sf')
        # self.timers[6].disp('6 Load in dict')

        return d