|
| 1 | +redirect_stderr(IOContext(stderr, :stacktrace_types_limited => Ref(false))) |
| 2 | +import ClimaComms |
| 3 | +ClimaComms.@import_required_backends |
| 4 | +import ClimaAtmos as CA |
| 5 | +import ClimaCore as CC |
| 6 | +import Random |
| 7 | +Random.seed!(1234) |
| 8 | + |
| 9 | +### -------------------- ### |
| 10 | +### Variable model setup ### |
| 11 | +### -------------------- ### |
| 12 | +output_dir = nothing # customize if desired |
| 13 | +FT = Float32 |
| 14 | + |
| 15 | +t_end = "150days" |
| 16 | + |
| 17 | +##### RCE-small ##### |
| 18 | +x_max = y_max = 96_000 |
| 19 | + |
| 20 | +# spatio-temporal discretization |
| 21 | + |
| 22 | +#~8km grid |
| 23 | +x_elem = y_elem = 4 |
| 24 | +dt = "10secs" |
| 25 | +# ~4km grid |
| 26 | +# x_elem = y_elem = 8 |
| 27 | +# dt = "5secs" |
| 28 | +# ~2km grid |
| 29 | +# x_elem = y_elem = 16 |
| 30 | +# dt = "2secs" |
| 31 | +# ~1km grid |
| 32 | +# x_elem = y_elem = 32 |
| 33 | +# dt = "1secs" |
| 34 | + |
| 35 | +### -------------------- ### |
| 36 | + |
| 37 | + |
| 38 | +## Load model parameters |
| 39 | +params = CA.ClimaAtmosParameters( |
| 40 | + CA.CP.create_toml_dict(FT; override_file = "toml/rcemipii_box.toml"), |
| 41 | +) |
| 42 | + |
| 43 | +## RCEMIP-II model prescriptions |
| 44 | +insolation = CA.RCEMIPIIInsolation() |
| 45 | +sfc_temperature = CA.RCEMIPIISST() |
| 46 | +initial_condition = CA.InitialConditions.RCEMIPIIProfile_300() |
| 47 | + |
| 48 | + |
| 49 | +## Construct the model |
| 50 | +model = CA.AtmosModel(; |
| 51 | + # AtmosWater - Moisture, Precipitation & Clouds |
| 52 | + moisture_model = CA.NonEquilMoistModel(), |
| 53 | + microphysics_model = CA.Microphysics1Moment(), |
| 54 | + cloud_model = CA.GridScaleCloud(), |
| 55 | + noneq_cloud_formation_mode = CA.Explicit(), |
| 56 | + tracer_nonnegativity_method = CA.TracerNonnegativityMethod("elementwise_constraint"), |
| 57 | + |
| 58 | + # AtmosRadiation |
| 59 | + radiation_mode = CA.RRTMGPInterface.AllSkyRadiationWithClearSkyDiagnostics(), |
| 60 | + insolation, |
| 61 | + |
| 62 | + # TODO: See if you need to set: `edmfx_model` |
| 63 | + smagorinsky_lilly = CA.SmagorinskyLilly(; axes = :UV_W), |
| 64 | + rayleigh_sponge = CA.RayleighSponge{FT}(; zd = 30_000), |
| 65 | + |
| 66 | + # AtmosSurface |
| 67 | + sfc_temperature, |
| 68 | + surface_model = CA.PrescribedSST(), |
| 69 | + surface_albedo = CA.ConstantAlbedo{FT}(; α = 0.07), |
| 70 | + |
| 71 | + # numerics |
| 72 | + numerics = CA.AtmosNumerics(; hyperdiff = nothing), |
| 73 | +) |
| 74 | +# @info "AtmosModel: \n$(summary(atmos))" |
| 75 | + |
| 76 | +## Grid creation |
| 77 | +function rcemipii_z_mesh(::Type{FT}) where {FT} |
| 78 | + z_max = 33_000 |
| 79 | + z_elem = 74 |
| 80 | + boundary_layer = |
| 81 | + FT[0, 37, 112, 194, 288, 395, 520, 667, 843, 1062, 1331, 1664, 2055, 2505] |
| 82 | + n_bl = length(boundary_layer) - 1 |
| 83 | + free_atmosphere = range(3000, FT(z_max), length = z_elem - n_bl) # z_elem=74, z_max=33_000m --> 500m spacing |
| 84 | + CT = CC.Geometry.ZPoint{FT} |
| 85 | + faces = CT.([boundary_layer; free_atmosphere]) |
| 86 | + z_domain = CC.Domains.IntervalDomain(CT(0), CT(z_max); boundary_names = (:bottom, :top)) |
| 87 | + z_mesh = CC.Meshes.IntervalMesh(z_domain, faces) |
| 88 | + return z_mesh |
| 89 | +end |
| 90 | +z_mesh = rcemipii_z_mesh(FT) |
| 91 | +grid = CA.BoxGrid(FT; x_elem, x_max, y_elem, y_max, z_mesh) |
| 92 | + |
| 93 | +## Discretization |
| 94 | +import ClimaTimeSteppers as CTS |
| 95 | +newtons_method = |
| 96 | + CTS.NewtonsMethod(; max_iters = 1, update_j = CTS.UpdateEvery(CTS.NewNewtonIteration)) |
| 97 | +ode_config = CTS.IMEXAlgorithm(CTS.ARS343(), newtons_method) |
| 98 | + |
| 99 | +## Output diagnostics |
| 100 | +diagnostics = [ |
| 101 | + Dict( |
| 102 | + "short_name" => [ |
| 103 | + "wa", "ua", "va", "ta", "thetaa", "ha", # dynamics & thermodynamics |
| 104 | + "hus", "hur", "cl", "clw", "cli", # liquid |
| 105 | + "pr", # precipitation |
| 106 | + "ke", # kinetic energy for spectrum |
| 107 | + # Smagorinsky diagnostics |
| 108 | + "Dh_smag", "strainh_smag", # horizontal |
| 109 | + "Dv_smag", "strainv_smag", # vertical |
| 110 | + ], |
| 111 | + "period" => "1hours", |
| 112 | + ), |
| 113 | +] |
| 114 | +### 1M microphysics |
| 115 | +if model.microphysics_model ∈ (CA.Microphysics1Moment(), CA.Microphysics2Moment()) |
| 116 | + push!(diagnostics, Dict("short_name" => ["husra", "hussn"], "period" => "1hours")) |
| 117 | +end |
| 118 | +### 2M microphysics |
| 119 | +if model.microphysics_model == CA.Microphysics2Moment() |
| 120 | + push!(diagnostics, Dict("short_name" => ["cdnc", "ncra"], "period" => "1hours")) |
| 121 | +end |
| 122 | + |
| 123 | +## Assemble simulation |
| 124 | +simulation = CA.AtmosSimulation{FT}(; job_id = "rcemipii_box", |
| 125 | + model, params, grid, |
| 126 | + initial_condition, |
| 127 | + surface_setup = CA.SurfaceConditions.DefaultMoninObukhov(), |
| 128 | + dt, t_end, |
| 129 | + ode_config, |
| 130 | + output_dir, |
| 131 | + # Callbacks |
| 132 | + callback_kwargs = (; dt_cloud_fraction = "3hours", dt_rad = "1hours"), |
| 133 | + # Diagnostics |
| 134 | + default_diagnostics = false, |
| 135 | + diagnostics, |
| 136 | + # Numerics |
| 137 | + approximate_linear_solve_iters = 2, # TODO: Fix implicit diffusion for LES |
| 138 | + # Misc |
| 139 | + checkpoint_frequency = "1days", |
| 140 | + log_to_file = true, |
| 141 | +) |
| 142 | + |
| 143 | +## Solve |
| 144 | + |
| 145 | + |
| 146 | +## Postprocessing |
| 147 | +# include(joinpath(@__DIR__, "..", "reproducibility_tests", "reproducibility_tools.jl")) |
| 148 | +# export_reproducibility_results(sol.u[end], ClimaComms.context(); simulation.job_id, computed_dir = simulation.output_dir) |
0 commit comments