CliMA / ClimaAtmos.jl

ClimaAtmos.jl is a library for building atmospheric circulation models that is designed from the outset to leverage data assimilation and machine learning tools. We welcome contributions!
Apache License 2.0
80 stars 14 forks source link

Improve design of nonorographic gravity wave parameterization #897

Open jiahe23 opened 1 year ago

jiahe23 commented 1 year ago

Files

Notes

charleskawczynski commented 1 year ago

Some concrete tasks:

    source_level = argmin(
        abs.(
            unique(parent(Fields.coordinate_field(Y.c).z) .- gw_source_height)
        ),
    )

may require ClimaCore features

charleskawczynski commented 1 year ago

For example, it would be helpful to have

charleskawczynski commented 1 year ago

Note to self, current sketch of changes to gravity_wave_forcing:

function gravity_wave_forcing(::Type{FT}, args) where {FT}
    (; ᶜρ_k, ᶜρ_lev′, ᶜbf_k, kwv_ink, ᶜρ_km1, ᶜΔz_k) = args
    (; k2_ink, source_level) = args
    (; c, c_hat0, ϵ, B0) = args
    fac = FT(0.5) * (ᶜρ_k / ᶜρ_lev′) * kwv_ink / ᶜbf_k

    ᶜHb = ᶜΔz_k / log(ᶜρ_km1 / ᶜρ_k)  # density scale height
    alp2 = FT(0.25) / (ᶜHb * ᶜHb)
    ω_r = sqrt((ᶜbf_k * ᶜbf_k * k2_ink) / (k2_ink + alp2)) # ω_r (critical frequency that marks total internal reflection)

    fm = FT(0)
    for n in 1:nc
        # check only those waves which are still propagating, i.e., mask = 1.0
        if mask[n] == 1
            c_hat = c[n] - ᶜu_k
            # f phase speed matches the wind speed, remove c(n) from the set of propagating waves.
            if c_hat == 0
                mask[n] = 0
            else
                # define the criterion which determines if wave is reflected at this level (test).
                test = abs(c_hat) * kwv_ink - ω_r
                if test >= 0
                    # wave has undergone total internal reflection. remove it from the propagating set.
                    mask[n] = 0
                else
                    # if wave is not reflected at this level, determine if it is
                    # breaking at this level (Foc >= 0), or if wave speed relative to
                    # windspeed has changed sign from its value at the source level
                    # (c_hat0[n] * c_hat <= 0). if it is above the source level and is
                    # breaking, then add its momentum flux to the accumulated sum at
                    # this level.
                    # set mask=0.0 to remove phase speed band c[n] from the set of active 
                    # waves moving upwards to the next level.
                    if c_hat0[n] * c_hat <= 0
                        mask[n] = 0
                        if k > source_level
                            fm = fm + B0[n]
                        end
                    else
                        Foc = B0[n] / (c_hat)^3 - fac
                        if Foc >= 0
                            mask[n] = 0
                            if k > source_level
                                fm = fm + B0[n]
                            end
                        end
                    end
                end # (test >= 0)
            end #(c_hat == 0)
        end # mask = 0

    end # phase speed loop

    # TODO: GFDL option to dump remaining flux at the top of the model

    # compute the gravity wave momentum flux forcing
    # obtained across the entire wave spectrum at this level.
    return if k > source_level
        rbh = sqrt(ᶜρ_k * ᶜρ_km1)
        (ᶜρ_lev′ / rbh) * fm * ϵ / ᶜΔz_k
        # wave_forcing[k] = (ᶜρ_lev′ / rbh) * fm * ϵ / ᶜΔz_k
        # TODO: this just looks like interpolation after?
        # wave_forcing[k - 1] = FT(0.5) * (wave_forcing[k - 1] + wave_forcing[k])
    else
        # wave_forcing[k] = 0
        FT(0)
    end
end
charleskawczynski commented 2 months ago

We should also fix the types of the fields. For example ᶜdTdz is currently a Float32/Float64 field, and it should be a Covariant3Vector or WVector, depending on the equations. cc @xxy220022, @szy21, @dennisYatunin