-
Notifications
You must be signed in to change notification settings - Fork 27
ft: Add Kinematic Driver (KiD) model configuration #4095
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| ## Model | ||
| prescribed_flow: true | ||
| initial_condition: "ShipwayHill2012" | ||
| surface_setup: "ShipwayHill2012" | ||
| energy_q_tot_upwinding: first_order_kid | ||
| tracer_upwinding: first_order | ||
| # moist: "nonequil" | ||
| # precip_model: "1M" | ||
| moist: "equil" | ||
| precip_model: "0M" | ||
| cloud_model: "grid_scale" | ||
| call_cloud_diagnostics_per_stage: true | ||
| config: "column" | ||
| hyperdiff: "false" | ||
| ## Simulation | ||
| z_max: 2e3 | ||
| z_elem: 128 | ||
| z_stretch: false | ||
| use_auto_jacobian: true # Needed!! (+only 1 Newton iteration, which is the default) | ||
| # ode_algo: "ARS111" # try: Explicit Euler | ||
| dt: "1secs" | ||
| t_end: "1hours" | ||
| # t_end: "20mins" | ||
| dt_save_state_to_disk: "1hours" | ||
| toml: [toml/kinematic_driver.toml] | ||
| check_nan_every: 1 | ||
| ## Diagnostics | ||
| output_default_diagnostics: false | ||
| diagnostics: | ||
| - short_name: [ | ||
| # (z,t) fields | ||
| ta, thetaa, ha, rhoa, wa, hur, hus, cl, clw, cli, ua, va, ke, | ||
| # (t,) fields | ||
| lwp, pr, | ||
| # 1M | ||
| # (z,t) fields | ||
| # husra, hussn, | ||
| # (t,) fields | ||
| # rwp, | ||
| ] | ||
| period: 10secs | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| import ClimaComms | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It looks like everything in this file can be handled by the current driver, so there is no need to add a new one. |
||
| import ClimaAtmos as CA | ||
| import ClimaCore: Fields | ||
| import YAML | ||
| import ClimaComms | ||
|
|
||
| import Random | ||
| # Random.seed!(Random.MersenneTwister()) | ||
| Random.seed!(1234) | ||
|
|
||
| # --> get config | ||
| configs_path = joinpath(pkgdir(CA), "config/model_configs/") | ||
| pth = joinpath(configs_path, "kinematic_driver.yml"); | ||
| job_id = "kinematic_driver"; | ||
| config_dict = YAML.load_file(pth) | ||
| # <-- | ||
|
|
||
|
|
||
| config = CA.AtmosConfig(config_dict; job_id) | ||
| simulation = CA.get_simulation(config); | ||
|
|
||
| sol_res = CA.solve_atmos!(simulation); # solve! | ||
|
|
||
| (; integrator) = simulation; | ||
| (; p) = integrator; | ||
| (; atmos, params) = p; | ||
|
|
||
| # --> Make ci plots | ||
| # ]add ClimaAnalysis, ClimaCoreSpectra | ||
| include(joinpath(pkgdir(CA), "post_processing", "ci_plots.jl")) | ||
| make_plots(Val(:kinematic_driver), simulation.output_dir) | ||
| # <-- | ||
|
|
||
| # --> ClimaAnalysis | ||
| import ClimaAnalysis | ||
| # using ClimaAnalysis.Visualize | ||
| import ClimaAnalysis.Visualize as viz | ||
| using ClimaAnalysis.Utils: kwargs | ||
| using CairoMakie; | ||
| CairoMakie.activate!(); | ||
| # using GLMakie; GLMakie.activate!() | ||
| simdir = ClimaAnalysis.SimDir(simulation.output_dir); | ||
|
|
||
| # entr = get(simdir; short_name = "entr") | ||
| # entr.dims # (time, x, y, z) | ||
|
|
||
| # fig = Figure(); | ||
| # viz.plot!(fig, entr, time=0, x=0, y=0, more_kwargs = Dict(:axis => kwargs(dim_on_y = true))) | ||
| # viz.plot!(fig, entr, x=0, y=0); | ||
| # fig | ||
| # <-- | ||
|
|
||
|
|
||
|
|
||
| #= | ||
| %use upwinding for the rain -- yes! | ||
| qr, qs, all specific humidities, | ||
| take 30% acoustic Courant number c=300m/s, divided by vertical res | ||
| - for ~200 | ||
| ill make some plots | ||
| is smag applied to qr??? check this! | ||
| most likely precip would cause blow-ups. | ||
| =# | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -480,8 +480,10 @@ NVTX.@annotate function set_implicit_precomputed_quantities_part1!(Y, p, t) | |
|
|
||
| # TODO: We might want to move this to dss! (and rename dss! to something | ||
| # like enforce_constraints!). | ||
| set_velocity_at_surface!(Y, ᶠuₕ³, turbconv_model) | ||
| set_velocity_at_top!(Y, turbconv_model) | ||
| if !(p.atmos.prescribed_flow isa PrescribedFlow) | ||
| set_velocity_at_surface!(Y, ᶠuₕ³, turbconv_model) | ||
| set_velocity_at_top!(Y, turbconv_model) | ||
| end | ||
|
Comment on lines
+483
to
+486
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In simulations with topography, If you never intend to run this configuration with topography, then you can leave this as is, but add a check somewhere in
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmmm - we saw some inconsistency at the surface in our advected fields that went away only when we removed those |
||
|
|
||
| set_velocity_quantities!(ᶜu, ᶠu³, ᶜK, Y.f.u₃, Y.c.uₕ, ᶠuₕ³) | ||
| ᶜJ = Fields.local_geometry_field(Y.c).J | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
|
|
@@ -1633,3 +1633,43 @@ function (initial_condition::ISDAC)(params) | |||
| ) | ||||
| end | ||||
| end | ||||
|
|
||||
| """ | ||||
| ShipwayHill2012 | ||||
|
|
||||
| The `InitialCondition` described in [ShipwayHill2012](@cite), but with a hydrostatically | ||||
| balanced pressure profile. | ||||
|
|
||||
| B. J. Shipway and A. A. Hill. | ||||
| Diagnosis of systematic differences between multiple parametrizations of warm rain microphysics using a kinematic framework. | ||||
| Quarterly Journal of the Royal Meteorological Society 138, 2196-2211 (2012). | ||||
| """ | ||||
| struct ShipwayHill2012 <: InitialCondition end | ||||
| function (initial_condition::ShipwayHill2012)(params) | ||||
| FT = eltype(params) | ||||
|
|
||||
| ## Initialize the profile | ||||
| z_values = FT[0, 740, 3260] | ||||
| rv_values = FT[0.015, 0.0138, 0.0024] # water vapor mixing ratio | ||||
| θ_values = FT[297.9, 297.9, 312.66] # potential temperature | ||||
| linear_profile(zs, vals) = Intp.extrapolate( | ||||
| Intp.interpolate((zs,), vals, Intp.Gridded(Intp.Linear())), Intp.Linear(), | ||||
| ) | ||||
| # profile of water vapour mixing ratio | ||||
| rv(z) = linear_profile(z_values, rv_values)(z) | ||||
| q_tot(z) = rv(z) / (1 + rv(z)) | ||||
| # profile of potential temperature | ||||
| θ(z) = linear_profile(z_values, θ_values)(z) | ||||
| ## Hydrostatically balanced pressure profile | ||||
| thermo_params = CAP.thermodynamics_params(params) | ||||
| p_0 = FT(100_700) # Pa | ||||
| p = hydrostatic_pressure_profile(; thermo_params, p_0, θ, q_tot) | ||||
| function local_state(local_geometry) | ||||
| (; z) = local_geometry.coordinates | ||||
| return LocalState(; params, geometry = local_geometry, | ||||
| thermo_state = TD.PhaseEquil_pθq(thermo_params, p(z), θ(z), q_tot(z)), | ||||
| precip_state = PrecipStateMassNum(; q_rai = FT(0), q_sno = FT(0)), | ||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Removing this line will probably enable GPU compatibility, since
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wouldn't that mean we are initializing the state vector without precipitation in it?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The current version also initializes the state without precipitation. The new version should be identical, as long as the LocalState constructor automatically pads with zeros. |
||||
| ) | ||||
| end | ||||
| return local_state | ||||
| end | ||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -286,6 +286,10 @@ NVTX.@annotate function explicit_vertical_advection_tendency!(Yₜ, Y, p, t) | |||||||||||||||
| ᶜq_tot = @. lazy(specific(Y.c.ρq_tot, Y.c.ρ)) | ||||||||||||||||
| vtt = vertical_transport(ᶜρ, ᶠu³, ᶜq_tot, FT(dt), energy_q_tot_upwinding) | ||||||||||||||||
| vtt_central = vertical_transport(ᶜρ, ᶠu³, ᶜq_tot, FT(dt), Val(:none)) | ||||||||||||||||
| if energy_q_tot_upwinding == Val(:first_order_kid) | ||||||||||||||||
| vtt = vertical_transport_kid(ᶜρ, ᶠu³, ᶜq_tot, FT(dt), FT(t)) | ||||||||||||||||
| vtt_central = NullBroadcasted() # turn off implicit advection | ||||||||||||||||
| end | ||||||||||||||||
| @. Yₜ.c.ρq_tot += vtt - vtt_central | ||||||||||||||||
|
Comment on lines
+289
to
293
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
If the implicit tendency change is reverted, you can simplify this explicit term by keeping the current first-order upwinding tendency (minus the implicit sound wave component) and just adding a new boundary term, which could look something like function ᶜρq_tot_vertical_transport_bc(ᶠu³, flow::PrescribedFlow{FT}, t) where {FT}
ρ_sfc = FT(1.1650101)
q_tot_sfc = FT(0.014778325)
u₃_sfc = Geometry.WVector(flow(FT(0), t))
ᶜadvdivᵥ = Operators.DivergenceF2C(;
bottom = Operators.SetValue(ρ_sfc * q_tot_sfc * u₃_sfc),
)
return @. lazy(-(ᶜadvdivᵥ(zero(ᶠu³)))
endAlso, since this term is treated explicitly, it should probably be defined here in |
||||||||||||||||
| end | ||||||||||||||||
|
|
||||||||||||||||
|
|
||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -74,11 +74,41 @@ See also: | |||||||||||||||||
| dss!(Y_state, params, t_current) | ||||||||||||||||||
| # The ClimaCore.Field objects within Y_state.c and Y_state.f are now updated | ||||||||||||||||||
| # with DSS applied, ensuring continuity across distributed elements. | ||||||||||||||||||
| ``` | ||||||||||||||||||
| """ | ||||||||||||||||||
|
|
||||||||||||||||||
| NVTX.@annotate function dss!(Y, p, t) | ||||||||||||||||||
| if do_dss(axes(Y.c)) | ||||||||||||||||||
| Spaces.weighted_dss!(Y.c => p.ghost_buffer.c, Y.f => p.ghost_buffer.f) | ||||||||||||||||||
| end | ||||||||||||||||||
| prescribe_flow!(Y, p, t, p.atmos.prescribed_flow) | ||||||||||||||||||
|
Comment on lines
81
to
+84
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
It would be safer to do this in the opposite order, so that DSS is always the last operation in a Runge-Kutta stage. Roundoff errors in the prescribed flow could potentially introduce discontinuities across element boundaries, which will be propagated to the next stage if DSS is not applied afterward. |
||||||||||||||||||
| return nothing | ||||||||||||||||||
| end | ||||||||||||||||||
|
|
||||||||||||||||||
| prescribe_flow!(Y, p, t, ::Nothing) = nothing | ||||||||||||||||||
| function prescribe_flow!(Y, p, t, flow::PrescribedFlow) | ||||||||||||||||||
| ᶠlg = Fields.local_geometry_field(Y.f) | ||||||||||||||||||
| z = Fields.coordinate_field(Y.f).z | ||||||||||||||||||
| @. Y.f.u₃ = C3(Geometry.WVector(flow(z, t)), ᶠlg) | ||||||||||||||||||
|
|
||||||||||||||||||
| # return nothing # comment out to try fixing energy | ||||||||||||||||||
|
|
||||||||||||||||||
| ### Fix energy to initial temperature | ||||||||||||||||||
| ᶜlg = Fields.local_geometry_field(Y.c) | ||||||||||||||||||
| local_state = InitialConditions.ShipwayHill2012()(p.params) | ||||||||||||||||||
| get_ρ_init_dry(ls) = ls.thermo_state.ρ * (1 - ls.thermo_state.q_tot) | ||||||||||||||||||
| get_T_init(ls) = TD.air_temperature(ls.thermo_params, ls.thermo_state) | ||||||||||||||||||
| ᶜρ_init_dry = @. lazy(get_ρ_init_dry(local_state(ᶜlg))) | ||||||||||||||||||
| ᶜT_init = @. lazy(get_T_init(local_state(ᶜlg))) | ||||||||||||||||||
|
|
||||||||||||||||||
| thermo_params = CAP.thermodynamics_params(p.params) | ||||||||||||||||||
| grav = CAP.grav(p.params) | ||||||||||||||||||
| z = Fields.coordinate_field(Y.c).z | ||||||||||||||||||
|
|
||||||||||||||||||
| @. Y.c.ρ = ᶜρ_init_dry + Y.c.ρq_tot | ||||||||||||||||||
| ᶜts = @. lazy(TD.PhaseEquil_ρTq(thermo_params, Y.c.ρ, ᶜT_init, Y.c.ρq_tot / Y.c.ρ)) | ||||||||||||||||||
| ᶜe_kin = compute_kinetic(Y.c.uₕ, Y.f.u₃) | ||||||||||||||||||
| ᶜe_pot = @. lazy(grav * z) | ||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
This is already cached in |
||||||||||||||||||
| @. Y.c.ρe_tot = Y.c.ρ * TD.total_energy(thermo_params, ᶜts, ᶜe_kin, ᶜe_pot) | ||||||||||||||||||
| return nothing | ||||||||||||||||||
| end | ||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -82,6 +82,22 @@ function vertical_transport(ᶜρ, ᶠu³, ᶜχ, dt, ::Val{:first_order}) | |||||||
| ᶠJ = Fields.local_geometry_field(axes(ᶠu³)).J | ||||||||
| return @. lazy(-(ᶜadvdivᵥ(ᶠinterp(ᶜρ * ᶜJ) / ᶠJ * ᶠupwind1(ᶠu³, ᶜχ)))) | ||||||||
| end | ||||||||
| vertical_transport(ᶜρ, ᶠu³, ᶜχ, dt, ::Val{:first_order_kid}) = | ||||||||
| vertical_transport(ᶜρ, ᶠu³, ᶜχ, dt, Val(:first_order)) # transport e.g. ρe_tot as usual | ||||||||
| function vertical_transport_kid(ᶜρ, ᶠu³, ᶜχ, dt, t) | ||||||||
| FT = eltype(ᶜρ) | ||||||||
| ᶜJ = Fields.local_geometry_field(axes(ᶜρ)).J | ||||||||
| ᶠJ = Fields.local_geometry_field(axes(ᶠu³)).J | ||||||||
| ρ_sfc = FT(1.1650101) # TODO: Get from initial conditions or state | ||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would be great to avoid hardcoding. But we can also solve it later |
||||||||
| q_tot_sfc = FT(0.014778325) # TODO: Get from initial conditions or state | ||||||||
| u₃_sfc = ShipwayHill2012VelocityProfile{FT}()(FT(0), t) | ||||||||
|
|
||||||||
| bottom_bc = Geometry.WVector(ρ_sfc * q_tot_sfc * u₃_sfc) | ||||||||
| ᶜadvdivᵥ_kid = Operators.DivergenceF2C( | ||||||||
| bottom = Operators.SetValue(bottom_bc), top = Operators.Extrapolate(), | ||||||||
| ) | ||||||||
| return @. lazy(-(ᶜadvdivᵥ_kid(ᶠinterp(ᶜρ * ᶜJ) / ᶠJ * ᶠupwind1(ᶠu³, ᶜχ)))) | ||||||||
| end | ||||||||
| @static if pkgversion(ClimaCore) ≥ v"0.14.22" | ||||||||
| function vertical_transport(ᶜρ, ᶠu³, ᶜχ, dt, ::Val{:vanleer_limiter}) | ||||||||
| ᶜJ = Fields.local_geometry_field(axes(ᶜρ)).J | ||||||||
|
|
@@ -131,6 +147,9 @@ function implicit_vertical_advection_tendency!(Yₜ, Y, p, t) | |||||||
| if !(moisture_model isa DryModel) | ||||||||
| ᶜq_tot = @. lazy(specific(Y.c.ρq_tot, Y.c.ρ)) | ||||||||
| vtt = vertical_transport(Y.c.ρ, ᶠu³, ᶜq_tot, dt, Val(:none)) | ||||||||
| if p.atmos.numerics.energy_q_tot_upwinding == Val(:first_order_kid) | ||||||||
| vtt = NullBroadcasted() # Turn off implicit energy q_tot advection | ||||||||
| end | ||||||||
|
Comment on lines
+150
to
+152
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
This will make the implicit solver's sound wave propagation inconsistent, with ∂ᶜρq_tot/∂ᶠu₃ being zeroed out while ∂ᶠu₃/∂ᶜρq_tot (and all other ᶜρχ blocks) retains its current nonzero value. To handle sound waves like we do in other configurations, leave the implicit tendency and its Jacobian as they are now. |
||||||||
| @. Yₜ.c.ρq_tot += vtt | ||||||||
| end | ||||||||
|
|
||||||||
|
|
||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This shouldn't be needed if you leave the current implicit tendency unchanged.