def run_full_timestep_py(SOILTEMP, SOILMOIST, LWFLXNET_srfc, SWFLXNET_srfc,
                         SOILCP, SOILRHO, SOILDEPTH, OCEANMASK, TAIR_nz, QV_nz,
                         WIND_nz, RHO_nz, PSURF, COLP, WINDX_nz, WINDY_nz,
                         RAIN, DRAGCM, DRAGCH, A, dt):

    # comute surface fluxes
    if i_surface_fluxes:
        SMOMXFLX, SMOMYFLX, SSHFLX, SLHFLX = calc_srfc_fluxes(
            SOILTEMP, SOILMOIST, TAIR_nz, QV_nz, WIND_nz, RHO_nz, PSURF, COLP,
            WINDX_nz, WINDY_nz, DRAGCM, DRAGCH, A, dt)
    else:
        SMOMXFLX = wp(0.)
        SMOMYFLX = wp(0.)
        SSHFLX = wp(0.)
        SLHFLX = wp(0.)

    # soil temperature change
    if i_surface_SOILTEMP_tendency:
        dSOILTEMPdt = tendency_SOILTEMP(LWFLXNET_srfc, SWFLXNET_srfc, SSHFLX,
                                        SLHFLX, SOILCP, SOILRHO, SOILDEPTH)
    else:
        dSOILTEMPdt = wp(0.)
    SOILTEMP = timestep_SOILTEMP(SOILTEMP, dSOILTEMPdt, dt)

    # update surface albedo
    SURFALBEDSW, SURFALBEDLW = calc_albedo(OCEANMASK, SOILTEMP, SOILMOIST)

    # soil moisture change
    SOILMOIST -= dt * SLHFLX / con_Lh
    if SOILMOIST > max_moisture_soil:
        SOILMOIST = max_moisture_soil
    SOILMOIST += RAIN

    return (SOILTEMP, SOILMOIST, SURFALBEDSW, SURFALBEDLW, SMOMXFLX, SMOMYFLX,
            SSHFLX, SLHFLX)
Beispiel #2
0
def bulk_richardson_py(QV_k, POTT_k, POTT_km05, POTT_kp05, ALT_km05, ALT_kp05,
                       WINDX_km05, WINDX_kp05, WINDY_km05, WINDY_kp05):
    POTT_v_k = calc_virtual_temperature(POTT_k, QV_k)
    Ri_b_k = ((con_g / POTT_v_k * (POTT_km05 - POTT_kp05) *
               (ALT_km05 - ALT_kp05)) / ((WINDX_km05 - WINDX_kp05)**wp(2.) +
                                         (WINDY_km05 - WINDY_kp05)**wp(2.)))
    return (Ri_b_k)
Beispiel #3
0
    def initial_conditions(self, GR, **fields):
        fields['OCEANMASK'][fields['HSURF'] > 100] = 0
        fields['OCEANMASK'][fields['HSURF'] <= 100] = 1

        fields['SOILDEPTH'][fields['OCEANMASK'] == 0] = depth_soil
        fields['SOILDEPTH'][fields['OCEANMASK'] == 1] = depth_ocean

        fields['SOILCP'][fields['OCEANMASK'] == 0] = cp_soil
        fields['SOILCP'][fields['OCEANMASK'] == 1] = cp_ocean

        fields['SOILRHO'][fields['OCEANMASK'] == 0] = rho_soil
        fields['SOILRHO'][fields['OCEANMASK'] == 1] = rho_water

        fields['SOILTEMP'][:, :,
                           0] = (295 - np.sin(GR.lat_rad[:, :, 0])**2 * 30)
        fields['SOILTEMP'] -= fields['HSURF'] * wp(0.0100)

        fields['SOILMOIST'][fields['OCEANMASK'] == 0] = moisture_soil
        fields['SOILMOIST'][fields['OCEANMASK'] == 1] = moisture_ocean

        fields['SURFALBEDSW'][fields['OCEANMASK'] == 1] = 0.05
        fields['SURFALBEDLW'][fields['OCEANMASK'] == 1] = 0.00
        fields['SURFALBEDSW'][fields['OCEANMASK'] == 0] = 0.20
        fields['SURFALBEDLW'][fields['OCEANMASK'] == 0] = 0.00
        fields['SURFALBEDSW'][fields['SOILTEMP'][:, :, 0] <= wp(273.15)] = 0.6
        fields['SURFALBEDLW'][fields['SOILTEMP'][:, :, 0] <= wp(273.15)] = 0.0

        return (fields)
Beispiel #4
0
def compute_K_coefs_py(HGT_k, WINDX_km05, WINDX_kp05, WINDY_km05, WINDY_kp05,
                       ALT_km05, ALT_kp05, QV_km05, QV_kp05, POTT_k, POTT_km05,
                       POTT_kp05):
    # compute mixing length
    mix_len = con_k * HGT_k / (wp(1.) + con_k * HGT_k / free_mix_len)

    # bulk richardson number
    QV_k = comp_VARVB_log(QV_kp05, QV_km05)
    Ri_b_k = bulk_richardson(QV_k, POTT_k, POTT_km05, POTT_kp05, ALT_km05,
                             ALT_kp05, WINDX_km05, WINDX_kp05, WINDY_km05,
                             WINDY_kp05)

    # vertical wind shear term
    shear_term = sqrt(((WINDX_km05 - WINDX_kp05) /
                       (ALT_km05 - ALT_kp05))**wp(2.) +
                      ((WINDY_km05 - WINDY_kp05) /
                       (ALT_km05 - ALT_kp05))**wp(2.))

    # mixing coefficient for momentum
    KMOM_k = mix_len**wp(2.) * shear_term * (Ri_c - Ri_b_k) / Ri_c

    # negative values possible in above formula but implies zero.
    # also most often the values are way too big ?? TODO
    if KMOM_k < min_KMOM:
        KMOM_k = min_KMOM
    if KMOM_k > max_KMOM:
        KMOM_k = max_KMOM

    # mixing coefficient for heat and moisture
    KHEAT_k = KMOM_k / con_Pr

    ## TODO
    #KHEAT_k = wp(1.)

    return (KMOM_k, KHEAT_k)
def calc_srfc_fluxes_py(SOILTEMP, SOILMOIST, TAIR_nz, QV_nz, WIND_nz, RHO_nz,
                        PSURF, COLP, WINDX_nz, WINDY_nz, DRAGCM, DRAGCH, A,
                        dt):
    # surface momentum flux in x direction pointing towards atmosphere
    SMOMXFLX = -DRAGCM * WIND_nz * WINDX_nz * COLP * A

    # surface momentum flux in y direction pointing towards atmosphere
    SMOMYFLX = -DRAGCM * WIND_nz * WINDY_nz * COLP * A

    # surface sensible heat flux pointing towards atmosphere
    # (w'theta')*rho*con_cp [W m-2]
    SSHFLX = -DRAGCH * WIND_nz * (TAIR_nz - SOILTEMP) * RHO_nz * con_cp

    # for QV of soil assume 60% of saturation specific humidity for SOILTEMP
    QV_soil = calc_specific_humidity(SOILTEMP, wp(60.), PSURF)
    # surface latent heat flux pointing towards atmosphere
    # (w'qv')*rho*con_Lh [W m-2]
    SLHFLX = -DRAGCH * WIND_nz * (QV_nz - QV_soil) * RHO_nz * con_Lh
    # over land apply resistance to evaporation
    if not math.isnan(SOILMOIST):
        SLHFLX *= land_evap_resist
    # only allow for positive latent heat flux (towards atmosphere)
    SLHFLX = max(wp(0.), SLHFLX)
    # reduce latent heat flux if no soil moisture is available over land
    if not math.isnan(SOILMOIST):
        if dt * SLHFLX / con_Lh > SOILMOIST:
            SLHFLX = SOILMOIST * con_Lh / dt

    return (SMOMXFLX, SMOMYFLX, SSHFLX, SLHFLX)
Beispiel #6
0
def interp_COLPA_js_py(COLP, COLP_jm1, COLP_im1, COLP_ip1, COLP_jm1_ip1,
                       COLP_jm1_im1, A, A_jm1, A_im1, A_ip1, A_jm1_ip1,
                       A_jm1_im1):
    """
    """
    return (wp(1.) / wp(8.) * (COLP_jm1_ip1 * A_jm1_ip1 + COLP_ip1 * A_ip1 +
                               wp(2.) * COLP_jm1 * A_jm1 + wp(2.) * COLP * A +
                               COLP_jm1_im1 * A_jm1_im1 + COLP_im1 * A_im1))
def hor_adv_py(VAR, VAR_im1, VAR_ip1, VAR_jm1, VAR_jp1, UFLX, UFLX_ip1, VFLX,
               VFLX_jp1, A):
    """
    Horizontal advection using momentum fluxes UFLX and VFLX.
    """
    return ((+UFLX * (VAR_im1 + VAR) / wp(2.) - UFLX_ip1 *
             (VAR + VAR_ip1) / wp(2.) + VFLX *
             (VAR_jm1 + VAR) / wp(2.) - VFLX_jp1 * (VAR + VAR_jp1) / wp(2.)) /
            A)
Beispiel #8
0
 def initial_conditions(self, GR, TAIR, PAIR, QV, RAINRATE, ACCRAIN):
     for i in range(0, nx + 2 * nb):
         for j in range(0, ny + 2 * nb):
             for k in range(0, nz):
                 QV[i, j,
                    k] = calc_specific_humidity_py(TAIR[i, j, k], RH_init,
                                                   PAIR[i, j, k])
             ACCRAIN[i, j, 0] = wp(0.)
             RAINRATE[i, j, 0] = wp(0.)
     GR.exchange_BC(QV)
Beispiel #9
0
def coriolis_and_spherical_VWIND_py(COLP, COLP_jm1, UWIND, UWIND_jm1,
                                    UWIND_ip1, UWIND_ip1_jm1, corf, corf_jm1,
                                    lat_rad, lat_rad_jm1, dlon_rad, dlat_rad):
    """
    Calculate coriolis acceleration and spherical grid conversion
    terms for VWIND.
    """
    return (-con_rE * dlon_rad * dlat_rad / wp(2.) *
            (COLP_jm1 * (UWIND_jm1 + UWIND_ip1_jm1) / wp(2.) *
             (corf_jm1 * con_rE * cos(lat_rad_jm1) +
              (UWIND_jm1 + UWIND_ip1_jm1) / wp(2.) * sin(lat_rad_jm1)) + COLP *
             (UWIND + UWIND_ip1) / wp(2.) *
             (corf * con_rE * cos(lat_rad) +
              (UWIND + UWIND_ip1) / wp(2.) * sin(lat_rad))))
def calc_virtual_temperature_py(T, qv):
    """
    Compute virtual temperature.
    inputs:
        T: temperature in K
        qv: specific humidity in kg/kg
    outputs:
        T_v: virtual temperature in K
    """
    epsilon = wp(0.622)
    # TODO: do not assume mixing_ratio = qv
    mixing_ratio = qv
    T_v = T * (wp(1.) + mixing_ratio / epsilon) / (wp(1.) + mixing_ratio)
    return (T_v)
Beispiel #11
0
def run_all_gpu(COLP, COLP_im1, COLP_ip1, COLP_jm1, COLP_jp1, COLP_im1_jm1,
                COLP_im1_jp1, COLP_ip1_jm1, COLP_ip1_jp1, COLP_OLD,
                COLP_OLD_im1, COLP_OLD_ip1, COLP_OLD_jm1, COLP_OLD_jp1,
                COLP_OLD_im1_jm1, COLP_OLD_im1_jp1, COLP_OLD_ip1_jm1,
                COLP_OLD_ip1_jp1, UWIND_OLD, dUFLXdt, VWIND_OLD, dVFLXdt,
                POTT_OLD, dPOTTdt, QV_OLD, dQVdt, QC_OLD, dQCdt, A, A_im1,
                A_ip1, A_jm1, A_jp1, A_im1_jm1, A_im1_jp1, A_ip1_jm1,
                A_ip1_jp1, dt, i, j):
    """
    """

    ## UWIND
    if j < ny + nb:
        COLPA_is = interp_COLPA_is(COLP, COLP_im1, COLP_jm1, COLP_jp1,
                                   COLP_im1_jp1, COLP_im1_jm1, A, A_im1, A_jm1,
                                   A_jp1, A_im1_jp1, A_im1_jm1, j)
        COLPA_OLD_is = interp_COLPA_is(COLP_OLD, COLP_OLD_im1, COLP_OLD_jm1,
                                       COLP_OLD_jp1, COLP_OLD_im1_jp1,
                                       COLP_OLD_im1_jm1, A, A_im1, A_jm1,
                                       A_jp1, A_im1_jp1, A_im1_jm1, j)
        UWIND = euler_forward_pw(UWIND_OLD, dUFLXdt, COLPA_is, COLPA_OLD_is,
                                 dt)

    ## VWIND
    if i < nx + nb:
        COLPA_js = interp_COLPA_js(COLP, COLP_jm1, COLP_im1, COLP_ip1,
                                   COLP_ip1_jm1, COLP_im1_jm1, A, A_jm1, A_im1,
                                   A_ip1, A_ip1_jm1, A_im1_jm1)
        COLPA_OLD_js = interp_COLPA_js(COLP_OLD, COLP_OLD_jm1, COLP_OLD_im1,
                                       COLP_OLD_ip1, COLP_OLD_ip1_jm1,
                                       COLP_OLD_im1_jm1, A, A_jm1, A_im1,
                                       A_ip1, A_ip1_jm1, A_im1_jm1)
        VWIND = euler_forward_pw(VWIND_OLD, dVFLXdt, COLPA_js, COLPA_OLD_js,
                                 dt)
    if i < nx + nb and j < ny + nb:
        ## POTT
        POTT = euler_forward_pw(POTT_OLD, dPOTTdt, COLP, COLP_OLD, dt)
        ## QV
        QV = euler_forward_pw(QV_OLD, dQVdt, COLP, COLP_OLD, dt)
        # clip negative values
        if QV < wp(0.):
            QV = wp(0.)
        ## QC
        QC = euler_forward_pw(QC_OLD, dQCdt, COLP, COLP_OLD, dt)
        # clip negative values
        if QC < wp(0.):
            QC = wp(0.)

    return (POTT, UWIND, VWIND, QV, QC)
Beispiel #12
0
def coriolis_and_spherical_UWIND_py(COLP, COLP_im1, VWIND, VWIND_im1,
                                    VWIND_jp1, VWIND_im1_jp1, UWIND, UWIND_im1,
                                    UWIND_ip1, corf_is, lat_is_rad, dlon_rad,
                                    dlat_rad):
    """
    Calculate coriolis acceleration and spherical grid conversion
    terms for UWIND.
    """
    return (con_rE * dlon_rad * dlat_rad / wp(2.) *
            (COLP_im1 * (VWIND_im1 + VWIND_im1_jp1) / wp(2.) *
             (corf_is * con_rE * cos(lat_is_rad) +
              (UWIND_im1 + UWIND) / wp(2.) * sin(lat_is_rad)) + COLP *
             (VWIND + VWIND_jp1) / wp(2.) *
             (corf_is * con_rE * cos(lat_is_rad) +
              (UWIND + UWIND_ip1) / wp(2.) * sin(lat_is_rad))))
def pre_grad_py(PHI, PHI_dm1, COLP, COLP_dm1, POTT, POTT_dm1, PVTF, PVTF_dm1,
                PVTFVB, PVTFVB_dm1, PVTFVB_dm1_kp1, PVTFVB_kp1, dsigma,
                sigma_vb, sigma_vb_kp1, dgrid):
    """
    Pressure gradient term for horizontal velocities.
    dm1 & dp1 mean in the horizontal direction of interest
    -1 & +1 grid point.
    """
    return (-dgrid * ((PHI - PHI_dm1) * (COLP + COLP_dm1) / wp(2.) +
                      (COLP - COLP_dm1) * con_cp / wp(2.) *
                      (+POTT_dm1 / dsigma *
                       (sigma_vb_kp1 * (PVTFVB_dm1_kp1 - PVTF_dm1) + sigma_vb *
                        (PVTF_dm1 - PVTFVB_dm1)) + POTT / dsigma *
                       (sigma_vb_kp1 * (PVTFVB_kp1 - PVTF) + sigma_vb *
                        (PVTF - PVTFVB)))))
def turb_flux_tendency_py(PHI, PHI_kp1, PHI_km1, PHIVB, PHIVB_kp1, VAR,
                          VAR_kp1, VAR_km1, KVAR, KVAR_kp1, RHO, RHOVB,
                          RHOVB_kp1, COLP, surf_flux_VAR, k):
    """
    Vertical turbulent transport. 
    """
    ALT = PHI / con_g
    ALT_kp1 = PHI_kp1 / con_g
    ALT_km1 = PHI_km1 / con_g
    ALTVB = PHIVB / con_g
    ALTVB_kp1 = PHIVB_kp1 / con_g

    if k == wp_int(0):
        #dVARdt_TURB = wp(0.)
        dVARdt_TURB = COLP * ((+wp(0.) -
                               ((VAR - VAR_kp1) /
                                (ALT - ALT_kp1) * RHOVB_kp1 * KVAR_kp1)) /
                              ((ALTVB - ALTVB_kp1) * RHO))
    elif k == nz - 1:
        #dVARdt_TURB = wp(0.)
        dVARdt_TURB = COLP * (
            (+((VAR_km1 - VAR) /
               (ALT_km1 - ALT) * RHOVB * KVAR) + surf_flux_VAR) /
            ((ALTVB - ALTVB_kp1) * RHO))
    else:
        #dVARdt_TURB = wp(0.)
        dVARdt_TURB = COLP * ((+((VAR_km1 - VAR) /
                                 (ALT_km1 - ALT) * RHOVB * KVAR) -
                               ((VAR - VAR_kp1) /
                                (ALT - ALT_kp1) * RHOVB_kp1 * KVAR_kp1)) /
                              ((ALTVB - ALTVB_kp1) * RHO))
    return (dVARdt_TURB)
def num_dif_pw_py(VAR, VAR_im1, VAR_ip1, VAR_jm1, VAR_jp1, COLP, COLP_im1,
                  COLP_ip1, COLP_jm1, COLP_jp1, VAR_dif_coef):
    """
    Numerical diffusion with pressure weighting.
    """
    return (VAR_dif_coef *
            (+COLP_im1 * VAR_im1 + COLP_ip1 * VAR_ip1 + COLP_jm1 * VAR_jm1 +
             COLP_jp1 * VAR_jp1 - wp(4.) * COLP * VAR))
Beispiel #16
0
def add_up_tendencies_py(POTT, POTT_im1, POTT_ip1, POTT_jm1, POTT_jp1,
                         POTT_km1, POTT_kp1, UFLX, UFLX_ip1, VFLX, VFLX_jp1,
                         COLP, COLP_im1, COLP_ip1, COLP_jm1, COLP_jp1, POTTVB,
                         POTTVB_kp1, WWIND, WWIND_kp1, COLP_NEW, PHI, PHI_kp1,
                         PHI_km1, PHIVB, PHIVB_kp1, KHEAT, KHEAT_kp1, RHO,
                         RHOVB, RHOVB_kp1, SSHFLX, dPOTTdt_RAD, A, dsigma,
                         POTT_dif_coef, k):

    dPOTTdt = wp(0.)

    if i_POTT_main_switch:
        # HORIZONTAL ADVECTION
        if i_POTT_hor_adv:
            dPOTTdt = dPOTTdt + hor_adv(POTT, POTT_im1, POTT_ip1, POTT_jm1,
                                        POTT_jp1, UFLX, UFLX_ip1, VFLX,
                                        VFLX_jp1, A)
        # VERTICAL ADVECTION
        if i_POTT_vert_adv:
            dPOTTdt = dPOTTdt + vert_adv(POTTVB, POTTVB_kp1, WWIND, WWIND_kp1,
                                         COLP_NEW, dsigma, k)
        ## VERTICAL TURBULENT TRANSPORT
        if i_POTT_vert_turb:
            surf_flux = SSHFLX / con_cp
            dPOTTdt_TURB = turb_flux_tendency(PHI, PHI_kp1, PHI_km1, PHIVB,
                                              PHIVB_kp1, POTT, POTT_kp1,
                                              POTT_km1, KHEAT, KHEAT_kp1, RHO,
                                              RHOVB, RHOVB_kp1, COLP,
                                              surf_flux, k)
            dPOTTdt = dPOTTdt + dPOTTdt_TURB
            # convert to [K hr-1] for user output
            dPOTTdt_TURB = dPOTTdt_TURB / COLP * wp(3600.)
        # NUMERICAL HORIZONTAL DIFUSION
        if i_POTT_num_dif and (POTT_dif_coef > wp(0.)):
            dPOTTdt = dPOTTdt + num_dif(POTT, POTT_im1, POTT_ip1, POTT_jm1,
                                        POTT_jp1, COLP, COLP_im1, COLP_ip1,
                                        COLP_jm1, COLP_jp1, POTT_dif_coef)
        # RADIATION
        if i_POTT_radiation:
            dPOTTdt = dPOTTdt + radiation(dPOTTdt_RAD, COLP)

    return (dPOTTdt, dPOTTdt_TURB)
Beispiel #17
0
    def exchange_BC(self, FIELD):
        """
        Python function (slow) to exchange boundaries.
        Should not be used within time step loop but just for initializiation.
        Advantage: Does not depend on import grid constants (e.g. nx)
                   Can therefore be used within grid.py and initial_conditiony.py
        """

        dim2 = False
        if len(FIELD.shape) == 2:
            dim2 = True
            fnx,fny = FIELD.shape
        elif len(FIELD.shape) == 3:
            fnx,fny,fnz = FIELD.shape

        # zonal boundaries
        if fnx == self.nxs+2*self.nb: # staggered in x
            FIELD[0,::] = FIELD[self.nxs-1,::] 
            FIELD[self.nxs,::] = FIELD[1,::] 
        else:     # unstaggered in x
            FIELD[0,::] = FIELD[self.nx,::] 
            FIELD[self.nx+1,::] = FIELD[1,::] 

        if dim2:
            # meridional boundaries
            if fny == self.nys+2*self.nb: # staggered in y
                for j in [0,1,self.nys,self.nys+1]:
                    FIELD[:,j] = wp(0.)
            else:     # unstaggered in y
                FIELD[:,0] = FIELD[:,1] 
                FIELD[:,self.ny+1] = FIELD[:,self.ny] 
        else:
            # meridional boundaries
            if fny == self.nys+2*self.nb: # staggered in y
                for j in [0,1,self.nys,self.nys+1]:
                    FIELD[:,j,:] = wp(0.)
            else:     # unstaggered in y
                FIELD[:,0,:] = FIELD[:,1,:] 
                FIELD[:,self.ny+1,:] = FIELD[:,self.ny,:] 

        return(FIELD)
def tendency_SOILTEMP_py(LWFLXNET_srfc, SWFLXNET_srfc, SSHFLX, SLHFLX, SOILCP,
                         SOILRHO, SOILDEPTH):

    dSOILTEMPdt = wp(0.)

    if i_radiation:
        dSOILTEMPdt += ((LWFLXNET_srfc + SWFLXNET_srfc) /
                        (SOILCP * SOILRHO * SOILDEPTH))

    if i_surface_fluxes:
        dSOILTEMPdt -= ((SSHFLX + SLHFLX) / (SOILCP * SOILRHO * SOILDEPTH))

    return (dSOILTEMPdt)
def UVFLX_hor_adv_py(DWIND, DWIND_dm1, DWIND_dp1, DWIND_pm1, DWIND_pp1,
                     DWIND_dm1_pm1, DWIND_dm1_pp1, DWIND_dp1_pm1,
                     DWIND_dp1_pp1, BRFLX, BRFLX_dm1, CQFLX, CQFLX_pp1,
                     DSFLX_dm1, DSFLX_pp1, ETFLX, ETFLX_dm1_pp1,
                     sign_ETFLX_term):
    """
    """
    return (+BRFLX_dm1 * (DWIND_dm1 + DWIND) / wp(2.) - BRFLX *
            (DWIND + DWIND_dp1) / wp(2.) + CQFLX *
            (DWIND_pm1 + DWIND) / wp(2.) - CQFLX_pp1 *
            (DWIND + DWIND_pp1) / wp(2.) + DSFLX_dm1 *
            (DWIND_dm1_pm1 + DWIND) / wp(2.) - DSFLX_pp1 *
            (DWIND + DWIND_dp1_pp1) / wp(2.) + sign_ETFLX_term *
            (+ETFLX * (DWIND_dp1_pm1 + DWIND) / wp(2.) - ETFLX_dm1_pp1 *
             (DWIND + DWIND_dm1_pp1) / wp(2.)))
def interp_VAR_ds_py(VAR, VAR_dm1, VAR_pm1, VAR_pp1, VAR_pm1_dm1, VAR_pp1_dm1,
                     rigid_wall, p_ind, np):
    """
    Interpolate VAR  
    onto position of repective horizontal wind.
    d inds (e.g. dm1 = d minus 1) are in direction of hor. wind
    vector.
    p inds are perpendicular to direction of hor. wind vector.
    if rigid_wall: Special BC for rigid wall parallel to flow
    direction according to hint from Mark Jacobson during mail
    conversation. np is number of grid cells and p_ind current
    index in direction perpeindular to flow.
    """
    # left rigid wall
    if rigid_wall and (p_ind == nb):
        VAR_ds = wp(0.25) * (VAR_pp1_dm1 + VAR_pp1 + VAR_dm1 + VAR) / con_g
    # right rigid wall
    elif rigid_wall and (p_ind == np):
        VAR_ds = wp(0.25) * (VAR_dm1 + VAR + VAR_pm1_dm1 + VAR_pm1) / con_g
    # inside domain (not at boundary of perpendicular dimension)
    else:
        VAR_ds = wp(0.125) * (VAR_pp1_dm1 + VAR_pp1 + wp(2.) * VAR_dm1 +
                              wp(2.) * VAR + VAR_pm1_dm1 + VAR_pm1) / con_g
    return (VAR_ds)
def comp_VARVB_log_py(VAR, VAR_km1):
    """
    Compute variable value at vertical border using 
    logarithmic interpolation.
    (see Jacobson page 213.)
    """
    min_val = wp(0.0000001)
    VAR = max(VAR, min_val)
    VAR_km1 = max(VAR_km1, min_val)
    #VAR_kp1 = max(VAR_kp1, min_val)

    if VAR_km1 == VAR:
        VARVB = VAR
    else:
        VARVB = ((log(VAR_km1) - log(VAR)) / (wp(1.) / VAR - wp(1.) / VAR_km1))

    #if VAR_kp1 == VAR:
    #    VARVB_kp1 = VAR
    #else:
    #    VARVB_kp1   = ( ( log(VAR    ) - log(VAR_kp1) ) /
    #                    ( wp(1.) / VAR_kp1 - wp(1.) / VAR     )
    #                  )

    return (VARVB)
Beispiel #22
0
def launch_numba_cpu(UFLX, VFLX, FLXDIV, UWIND, VWIND, WWIND, COLP, dCOLPdt,
                     COLP_NEW, COLP_OLD, dyis, dxjs, dsigma, sigma_vb, A, dt):

    for i in prange(nb, nx + nb):
        for j in range(nb, ny + nb):
            for k in range(wp_int(0), nz):
                # MOMENTUM FLUXES
                ###############################################################
                UFLX_i = calc_UFLX(UWIND[i, j, k], COLP[i, j, 0],
                                   COLP[i - 1, j, 0], dyis[i, j, 0])
                UFLX_ip1 = calc_UFLX(UWIND[i + 1, j, k], COLP[i + 1, j, 0],
                                     COLP[i, j, 0], dyis[i + 1, j, 0])

                VFLX_j = calc_VFLX(VWIND[i, j, k], COLP[i, j, 0],
                                   COLP[i, j - 1, 0], dxjs[i, j, 0])
                VFLX_jp1 = calc_VFLX(VWIND[i, j + 1, k], COLP[i, j + 1, 0],
                                     COLP[i, j, 0], dxjs[i, j + 1, 0])

                UFLX[i, j, k] = UFLX_i
                VFLX[i, j, k] = VFLX_j

                ## MOMENTUM FLUX DIVERGENCE
                ###############################################################
                FLXDIV[i, j, k] = calc_FLXDIV(UFLX_i, UFLX_ip1, VFLX_j,
                                              VFLX_jp1, dsigma[0, 0,
                                                               k], A[i, j, 0])

    ## COLUMN PRESSURE TENDENCY
    ############################################################################
    if i_COLP_main_switch:
        dCOLPdt[:, :, 0] = -FLXDIV.sum(axis=2)
    else:
        dCOLPdt[:, :, 0] = wp(0.)

    ### PRESSURE TIME STEP
    ############################################################################
    COLP_NEW[:, :, 0] = COLP_OLD[:, :, 0] + dt * dCOLPdt[:, :, 0]

    ### VERTICAL WIND
    ############################################################################
    for i in prange(nb, nx + nb):
        for j in range(nb, ny + nb):
            flxdivsum = FLXDIV[i, j, 0]
            for k in prange(1, nz):
                WWIND[i, j, k] = (
                    -flxdivsum / COLP_NEW[i, j, 0] -
                    sigma_vb[0, 0, k] * dCOLPdt[i, j, 0] / COLP_NEW[i, j, 0])
                flxdivsum += FLXDIV[i, j, k]
Beispiel #23
0
def interp_COLPA_is_py(COLP, COLP_im1, COLP_jm1, COLP_jp1, COLP_im1_jp1,
                       COLP_im1_jm1, A, A_im1, A_jm1, A_jp1, A_im1_jp1,
                       A_im1_jm1, j):
    """
    """
    if j == 1:
        return (wp(1.) / wp(4.) *
                (COLP_im1_jp1 * A_im1_jp1 + COLP_jp1 * A_jp1 +
                 COLP_im1 * A_im1 + COLP * A))
    elif j == ny:
        return (wp(1.) / wp(4.) *
                (COLP_im1_jm1 * A_im1_jm1 + COLP_jm1 * A_jm1 +
                 COLP_im1 * A_im1 + COLP * A))
    else:
        return (wp(1.) / wp(8.) *
                (COLP_im1_jp1 * A_im1_jp1 + COLP_jp1 * A_jp1 +
                 wp(2.) * COLP_im1 * A_im1 + wp(2.) * COLP * A +
                 COLP_im1_jm1 * A_im1_jm1 + COLP_jm1 * A_jm1))
def calc_albedo_py(OCEANMASK, SOILTEMP, SOILMOIST):
    # ocean
    if OCEANMASK:
        SURFALBEDSW = wp(0.05)
        SURFALBEDLW = wp(0.00)
        # sea ice
        if SOILTEMP <= wp(273.15):
            SURFALBEDSW = wp(0.5)
    # land
    else:
        SURFALBEDLW = wp(0.0)
        # desert
        if SOILMOIST < desert_moisture_thresh:
            SURFALBEDSW = wp(0.3)
        else:
            # snow / glacier
            if SOILTEMP <= wp(273.15):
                SURFALBEDSW = wp(0.6)
            # normal land surface
            else:
                SURFALBEDSW = wp(0.2)
    return (SURFALBEDSW, SURFALBEDLW)
def calc_momentum_fluxes_ij_py(UFLX, UFLX_im1, UFLX_im1_jm1, UFLX_im1_jp1,
                               UFLX_ip1, UFLX_ip1_jm1, UFLX_ip1_jp1, UFLX_jm1,
                               UFLX_jp1, VFLX, VFLX_im1, VFLX_im1_jm1,
                               VFLX_im1_jp1, VFLX_ip1, VFLX_ip1_jm1,
                               VFLX_ip1_jp1, VFLX_jm1, VFLX_jp1):
    """
    """
    BFLX = wp(1.) / wp(12.) * (UFLX_jm1 + UFLX_ip1_jm1 + wp(2.) *
                               (UFLX + UFLX_ip1) + UFLX_jp1 + UFLX_ip1_jp1)

    RFLX = wp(1.) / wp(12.) * (VFLX_im1 + VFLX_im1_jp1 + wp(2.) *
                               (VFLX + VFLX_jp1) + VFLX_ip1 + VFLX_ip1_jp1)

    return (BFLX, RFLX)
def calc_momentum_fluxes_isj_py(UFLX, UFLX_im1, UFLX_im1_jm1, UFLX_im1_jp1,
                                UFLX_ip1, UFLX_ip1_jm1, UFLX_ip1_jp1, UFLX_jm1,
                                UFLX_jp1, VFLX, VFLX_im1, VFLX_im1_jm1,
                                VFLX_im1_jp1, VFLX_ip1, VFLX_ip1_jm1,
                                VFLX_ip1_jp1, VFLX_jm1, VFLX_jp1):
    """
    """
    SFLX = wp(1.) / wp(24.) * (VFLX_im1 + VFLX_im1_jp1 + VFLX + VFLX_jp1 +
                               UFLX_im1 + wp(2.) * UFLX + UFLX_ip1)

    TFLX = wp(1.) / wp(24.) * (VFLX_im1 + VFLX_im1_jp1 + VFLX + VFLX_jp1 -
                               UFLX_im1 - wp(2.) * UFLX - UFLX_ip1)

    return (SFLX, TFLX)
def calc_momentum_fluxes_ijs_py(UFLX, UFLX_im1, UFLX_im1_jm1, UFLX_im1_jp1,
                                UFLX_ip1, UFLX_ip1_jm1, UFLX_ip1_jp1, UFLX_jm1,
                                UFLX_jp1, VFLX, VFLX_im1, VFLX_im1_jm1,
                                VFLX_im1_jp1, VFLX_ip1, VFLX_ip1_jm1,
                                VFLX_ip1_jp1, VFLX_jm1, VFLX_jp1):
    """
    """
    DFLX = wp(1.) / wp(24.) * (VFLX_jm1 + wp(2.) * VFLX + VFLX_jp1 + UFLX_jm1 +
                               UFLX + UFLX_ip1_jm1 + UFLX_ip1)

    EFLX = wp(1.) / wp(24.) * (VFLX_jm1 + wp(2.) * VFLX + VFLX_jp1 - UFLX_jm1 -
                               UFLX - UFLX_ip1_jm1 - UFLX_ip1)

    return (DFLX, EFLX)
def exchange_BC_cpu(FIELD):

    fnx, fny, fnz = FIELD.shape

    # zonal boundaries
    if fnx == nxs + 2 * nb:  # staggered in x
        FIELD[0, :, :] = FIELD[nxs - 1, :, :]
        FIELD[nxs, :, :] = FIELD[1, :, :]
        FIELD[nxs + 1, :, :] = FIELD[2, :, :]
    else:  # unstaggered in x
        FIELD[0, :, :] = FIELD[nx, :, :]
        FIELD[nx + 1, :, :] = FIELD[1, :, :]

    # meridional boundaries
    if fny == nys + 2 * nb:  # staggered in y
        for j in [0, 1, nys, nys + 1]:
            FIELD[:, j, :] = wp(0.)
    else:  # unstaggered in y
        FIELD[:, 0, :] = FIELD[:, 1, :]
        FIELD[:, ny + 1, :] = FIELD[:, ny, :]
def calc_momentum_fluxes_isjs_py(UFLX, UFLX_im1, UFLX_im1_jm1, UFLX_im1_jp1,
                                 UFLX_ip1, UFLX_ip1_jm1, UFLX_ip1_jp1,
                                 UFLX_jm1, UFLX_jp1, VFLX, VFLX_im1,
                                 VFLX_im1_jm1, VFLX_im1_jp1, VFLX_ip1,
                                 VFLX_ip1_jm1, VFLX_ip1_jp1, VFLX_jm1,
                                 VFLX_jp1):
    """
    """
    CFLX = wp(1.) / wp(12.) * (VFLX_im1_jm1 + VFLX_jm1 + wp(2.) *
                               (VFLX_im1 + VFLX) + VFLX_im1_jp1 + VFLX_jp1)

    QFLX = wp(1.) / wp(12.) * (UFLX_im1_jm1 + UFLX_im1 + wp(2.) *
                               (UFLX_jm1 + UFLX) + UFLX_ip1_jm1 + UFLX_ip1)

    return (CFLX, QFLX)
def interp_WWIND_UVWIND_py(DWIND, DWIND_km1, WWIND, WWIND_dm1, WWIND_pm1,
                           WWIND_pp1, WWIND_pm1_dm1, WWIND_pp1_dm1, COLP_NEW,
                           COLP_NEW_dm1, COLP_NEW_pm1, COLP_NEW_pp1,
                           COLP_NEW_pm1_dm1, COLP_NEW_pp1_dm1, A, A_dm1, A_pm1,
                           A_pp1, A_pm1_dm1, A_pp1_dm1, dsigma, dsigma_km1,
                           rigid_wall, p_ind, np, k):
    """
    Interpolate WWIND * UVWIND (U or V, depending on direction) 
    onto position of repective horizontal wind.
    d inds (e.g. dm1 = d minus 1) are in direction of hor. wind
    vector.
    p inds are perpendicular to direction of hor. wind vector.
    if rigid_wall: Special BC for rigid wall parallel to flow
    direction according to hint from Mark Jacobson during mail
    conversation. np is number of grid cells and p_ind current
    index in direction perpeindular to flow.
    """
    if k == wp_int(0) or k == nzs - wp_int(1):
        WWIND_DWIND = wp(0.)
    else:
        # left rigid wall
        if rigid_wall and (p_ind == nb):
            COLPAWWIND_ds_ks = wp(0.25) * (
                COLP_NEW_pp1_dm1 * A_pp1_dm1 * WWIND_pp1_dm1 +
                COLP_NEW_pp1 * A_pp1 * WWIND_pp1 +
                COLP_NEW_dm1 * A_dm1 * WWIND_dm1 + COLP_NEW * A * WWIND)
        # right rigid wall
        elif rigid_wall and (p_ind == np):
            COLPAWWIND_ds_ks = wp(0.25) * (
                COLP_NEW_dm1 * A_dm1 * WWIND_dm1 + COLP_NEW * A * WWIND +
                COLP_NEW_pm1_dm1 * A_pm1_dm1 * WWIND_pm1_dm1 +
                COLP_NEW_pm1 * A_pm1 * WWIND_pm1)
        # inside domain (not at boundary of perpendicular dimension)
        else:
            COLPAWWIND_ds_ks = wp(0.125) * (
                COLP_NEW_pp1_dm1 * A_pp1_dm1 * WWIND_pp1_dm1 + COLP_NEW_pp1 *
                A_pp1 * WWIND_pp1 + wp(2.) * COLP_NEW_dm1 * A_dm1 * WWIND_dm1 +
                wp(2.) * COLP_NEW * A * WWIND + COLP_NEW_pm1_dm1 * A_pm1_dm1 *
                WWIND_pm1_dm1 + COLP_NEW_pm1 * A_pm1 * WWIND_pm1)

        # interpolate hor. wind on vertical interface
        DWIND_ks = ((dsigma * DWIND_km1 + dsigma_km1 * DWIND) /
                    (dsigma + dsigma_km1))

        # combine
        WWIND_DWIND = COLPAWWIND_ds_ks * DWIND_ks

    return (WWIND_DWIND)