-
Notifications
You must be signed in to change notification settings - Fork 4
Add turbo version of baroclinic instability #128
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
Open
MarcoArtiano
wants to merge
14
commits into
main
Choose a base branch
from
ma/turbo
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
0b2677d
fix euler with gravity
MarcoArtiano 0a2248f
fmt
MarcoArtiano da4dc34
add turbo kennedy gruber plus souza
MarcoArtiano 34475ec
fix test
MarcoArtiano a658150
fmt
MarcoArtiano 38087dc
Merge branch 'ma/patch' into ma/turbo
MarcoArtiano 1735ced
add test
MarcoArtiano 45a79c2
fix dummy function for the turbo version
MarcoArtiano ed86e2f
clean up
MarcoArtiano 6dffcaf
remove SSPRK43
MarcoArtiano ad6532c
import kennedy gruber
MarcoArtiano f5cefb8
fix typo
MarcoArtiano 92bf002
fix typo
MarcoArtiano 1bcc8d4
fix
MarcoArtiano File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
280 changes: 280 additions & 0 deletions
280
examples/elixir_euler_energy_baroclinic_instability_turbo.jl
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,280 @@ | ||
| # An idealized baroclinic instability test case | ||
| # For optimal results consider increasing the resolution to 16x16x8 trees per cube face, i.e., | ||
| # set `trees_per_cube_face = (16, 8)` below. | ||
| # | ||
| # This elixir takes about 8 hours, using 16 threads of an AMD Ryzen 7 7800X3D. | ||
| # | ||
| # References: | ||
| # - Paul A. Ullrich, Thomas Melvin, Christiane Jablonowski, Andrew Staniforth (2013) | ||
| # A proposed baroclinic wave test case for deep- and shallow-atmosphere dynamical cores | ||
| # https://doi.org/10.1002/qj.2241 | ||
|
|
||
| using OrdinaryDiffEqLowStorageRK | ||
| using Trixi, TrixiAtmo | ||
| using LinearAlgebra: norm | ||
|
|
||
| @inline Trixi.combine_conservative_and_nonconservative_fluxes(::typeof(flux_kennedy_gruber_souza_etal_turbo), | ||
| equations::CompressibleEulerEnergyEquationsWithGravity3D) = Trixi.True() | ||
|
|
||
| @inline function flux_lmars_turbo(u_ll, u_rr, normal_direction, equations) | ||
| flux = FluxLMARS(340)(u_ll, u_rr, normal_direction, equations) | ||
| return flux, flux | ||
| end | ||
|
|
||
| @inline Trixi.combine_conservative_and_nonconservative_fluxes(::typeof(flux_lmars_turbo), equations::CompressibleEulerEnergyEquationsWithGravity3D) = Trixi.True() | ||
|
|
||
| @inline function boundary_condition_slip_wall(u_inner, | ||
| normal_direction::AbstractVector, | ||
| x, t, | ||
| surface_flux_function::typeof(flux_lmars_turbo), | ||
| equations::CompressibleEulerEnergyEquationsWithGravity3D) | ||
|
Comment on lines
+16
to
+30
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. Can you please add a comment describing what you are doing here and why? |
||
| # normalize the outward pointing direction | ||
| normal = normal_direction / norm(normal_direction) | ||
| # compute the normal momentum | ||
| u_normal = normal[1] * u_inner[2] + normal[2] * u_inner[3] + normal[3] * u_inner[4] | ||
|
|
||
| # create the "external" boundary solution state | ||
| u_boundary = SVector(u_inner[1], | ||
| u_inner[2] - 2 * u_normal * normal[1], | ||
| u_inner[3] - 2 * u_normal * normal[2], | ||
| u_inner[4] - 2 * u_normal * normal[3], | ||
| u_inner[5], u_inner[6]) | ||
|
|
||
| # calculate the boundary flux | ||
| flux, _ = surface_flux_function(u_inner, u_boundary, normal_direction, equations) | ||
| return flux | ||
| end | ||
|
|
||
| # Unperturbed balanced steady-state. | ||
| # Returns primitive variables with only the velocity in longitudinal direction (rho, u, p). | ||
| # The other velocity components are zero. | ||
|
Comment on lines
+48
to
+50
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. I guess the remaining part is just copied from another elixir? |
||
| function basic_state_baroclinic_instability_longitudinal_velocity(lon, lat, z) | ||
| # Parameters from Table 1 in the paper | ||
| # Corresponding names in the paper are commented | ||
| radius_earth = 6.371229e6 # a | ||
| half_width_parameter = 2 # b | ||
| gravitational_acceleration = 9.81 # g | ||
| k = 3 # k | ||
| surface_pressure = 1.0f5 # p₀ | ||
| gas_constant = 287 # R | ||
| surface_equatorial_temperature = 310 # T₀ᴱ | ||
| surface_polar_temperature = 240 # T₀ᴾ | ||
| lapse_rate = 0.005 # Γ | ||
| angular_velocity = 7.29212e-5 # Ω | ||
|
|
||
| # Distance to the center of the Earth | ||
| r = z + radius_earth | ||
|
|
||
| # In the paper: T₀ | ||
| temperature0 = 0.5 * (surface_equatorial_temperature + surface_polar_temperature) | ||
| # In the paper: A, B, C, H | ||
| const_a = 1 / lapse_rate | ||
| const_b = (temperature0 - surface_polar_temperature) / | ||
| (temperature0 * surface_polar_temperature) | ||
| const_c = 0.5 * (k + 2) * (surface_equatorial_temperature - surface_polar_temperature) / | ||
| (surface_equatorial_temperature * surface_polar_temperature) | ||
| const_h = gas_constant * temperature0 / gravitational_acceleration | ||
|
|
||
| # In the paper: (r - a) / bH | ||
| scaled_z = z / (half_width_parameter * const_h) | ||
|
|
||
| # Temporary variables | ||
| temp1 = exp(lapse_rate / temperature0 * z) | ||
| temp2 = exp(-scaled_z^2) | ||
|
|
||
| # In the paper: ̃τ₁, ̃τ₂ | ||
| tau1 = const_a * lapse_rate / temperature0 * temp1 + | ||
| const_b * (1 - 2 * scaled_z^2) * temp2 | ||
| tau2 = const_c * (1 - 2 * scaled_z^2) * temp2 | ||
|
|
||
| # In the paper: ∫τ₁(r') dr', ∫τ₂(r') dr' | ||
| inttau1 = const_a * (temp1 - 1) + const_b * z * temp2 | ||
| inttau2 = const_c * z * temp2 | ||
|
|
||
| # Temporary variables | ||
| temp3 = r / radius_earth * cos(lat) | ||
| temp4 = temp3^k - k / (k + 2) * temp3^(k + 2) | ||
|
|
||
| # In the paper: T | ||
| temperature = 1 / ((r / radius_earth)^2 * (tau1 - tau2 * temp4)) | ||
|
|
||
| # In the paper: U, u (zonal wind, first component of spherical velocity) | ||
| big_u = gravitational_acceleration / radius_earth * k * temperature * inttau2 * | ||
| (temp3^(k - 1) - temp3^(k + 1)) | ||
| temp5 = radius_earth * cos(lat) | ||
| u = -angular_velocity * temp5 + sqrt(angular_velocity^2 * temp5^2 + temp5 * big_u) | ||
|
|
||
| # Hydrostatic pressure | ||
| p = surface_pressure * | ||
| exp(-gravitational_acceleration / gas_constant * (inttau1 - inttau2 * temp4)) | ||
|
|
||
| # Density (via ideal gas law) | ||
| rho = p / (gas_constant * temperature) | ||
|
|
||
| return rho, u, p | ||
| end | ||
|
|
||
| # Perturbation as in Equations 25 and 26 of the paper (analytical derivative) | ||
| function perturbation_stream_function(lon, lat, z) | ||
| # Parameters from Table 1 in the paper | ||
| # Corresponding names in the paper are commented | ||
| perturbation_radius = 1 / 6 # d₀ / a | ||
| perturbed_wind_amplitude = 1 # Vₚ | ||
| perturbation_lon = pi / 9 # Longitude of perturbation location | ||
| perturbation_lat = 2 * pi / 9 # Latitude of perturbation location | ||
| pertz = 15000 # Perturbation height cap | ||
|
|
||
| # Great circle distance (d in the paper) divided by a (radius of the Earth) | ||
| # because we never actually need d without dividing by a | ||
| great_circle_distance_by_a = acos(sin(perturbation_lat) * sin(lat) + | ||
| cos(perturbation_lat) * cos(lat) * | ||
| cos(lon - perturbation_lon)) | ||
|
|
||
| # In the first case, the vertical taper function is per definition zero. | ||
| # In the second case, the stream function is per definition zero. | ||
| if z > pertz || great_circle_distance_by_a > perturbation_radius | ||
| return 0, 0 | ||
| end | ||
|
|
||
| # Vertical tapering of stream function | ||
| perttaper = 1 - 3 * z^2 / pertz^2 + 2 * z^3 / pertz^3 | ||
|
|
||
| # sin/cos(pi * d / (2 * d_0)) in the paper | ||
| sin_, cos_ = sincos(0.5f0 * pi * great_circle_distance_by_a / perturbation_radius) | ||
|
|
||
| # Common factor for both u and v | ||
| factor = 16 / (3 * sqrt(3)) * perturbed_wind_amplitude * perttaper * cos_^3 * sin_ | ||
|
|
||
| u_perturbation = -factor * (-sin(perturbation_lat) * cos(lat) + | ||
| cos(perturbation_lat) * sin(lat) * cos(lon - perturbation_lon)) / | ||
| sin(great_circle_distance_by_a) | ||
|
|
||
| v_perturbation = factor * cos(perturbation_lat) * sin(lon - perturbation_lon) / | ||
| sin(great_circle_distance_by_a) | ||
|
|
||
| return u_perturbation, v_perturbation | ||
| end | ||
|
|
||
| function cartesian_to_sphere(x) | ||
| r = norm(x) | ||
| lambda = atan(x[2], x[1]) | ||
| if lambda < 0 | ||
| lambda += 2 * pi | ||
| end | ||
| phi = asin(x[3] / r) | ||
|
|
||
| return lambda, phi, r | ||
| end | ||
|
|
||
| # Initial condition for an idealized baroclinic instability test | ||
| # https://doi.org/10.1002/qj.2241, Section 3.2 and Appendix A | ||
| function initial_condition_baroclinic_instability(x, t, | ||
| equations::CompressibleEulerEnergyEquationsWithGravity3D) | ||
| lon, lat, r = cartesian_to_sphere(x) | ||
| radius_earth = 6.371229e6 | ||
| # Make sure that the r is not smaller than radius_earth | ||
| z = max(r - radius_earth, 0.0) | ||
|
|
||
| # Unperturbed basic state | ||
| rho, u, p = basic_state_baroclinic_instability_longitudinal_velocity(lon, lat, z) | ||
|
|
||
| # Stream function type perturbation | ||
| u_perturbation, v_perturbation = perturbation_stream_function(lon, lat, z) | ||
|
|
||
| u += u_perturbation | ||
| v = v_perturbation | ||
|
|
||
| # Convert spherical velocity to Cartesian | ||
| v1 = -sin(lon) * u - sin(lat) * cos(lon) * v | ||
| v2 = cos(lon) * u - sin(lat) * sin(lon) * v | ||
| v3 = cos(lat) * v | ||
| radius_earth = 6.371229e6 # a | ||
| gravitational_acceleration = 9.81 # g | ||
|
|
||
| r = norm(x) | ||
| # Make sure that r is not smaller than radius_earth | ||
| z = max(r - radius_earth, 0) | ||
| if z > 0 | ||
| r = norm(x) | ||
| else | ||
| r = -(2 * radius_earth^3) / (x[1]^2 + x[2]^2 + x[3]^2) | ||
| end | ||
| r = -norm(x) | ||
| phi = radius_earth^2 * gravitational_acceleration / r | ||
|
|
||
| return prim2cons(SVector(rho, v1, v2, v3, p, phi), equations) | ||
| end | ||
|
|
||
| @inline function source_terms_baroclinic_instability(u, x, t, | ||
| equations::CompressibleEulerEnergyEquationsWithGravity3D) | ||
| radius_earth = 6.371229e6 # a | ||
| angular_velocity = 7.29212e-5 # Ω | ||
|
|
||
| r = norm(x) | ||
| # Make sure that r is not smaller than radius_earth | ||
| z = max(r - radius_earth, 0) | ||
| r = z + radius_earth | ||
|
|
||
| du1 = zero(eltype(u)) | ||
| du2 = zero(eltype(u)) | ||
| du3 = zero(eltype(u)) | ||
| du4 = zero(eltype(u)) | ||
| du5 = zero(eltype(u)) | ||
| # Coriolis term, -2Ω × ρv = -2 * angular_velocity * (0, 0, 1) × u[2:4] | ||
| du2 -= -2 * angular_velocity * u[3] | ||
| du3 -= 2 * angular_velocity * u[2] | ||
|
|
||
| return SVector(du1, du2, du3, du4, du5, zero(eltype(u))) | ||
| end | ||
| equations = CompressibleEulerEnergyEquationsWithGravity3D(c_p = 1004, | ||
| c_v = 717, | ||
| gravity = 9.81) | ||
|
|
||
| initial_condition = initial_condition_baroclinic_instability | ||
|
|
||
| boundary_conditions = Dict(:inside => boundary_condition_slip_wall, | ||
| :outside => boundary_condition_slip_wall) | ||
|
|
||
| polydeg = 5 | ||
| surface_flux = flux_lmars_turbo | ||
| volume_flux = flux_kennedy_gruber_souza_etal_turbo | ||
|
|
||
| solver = DGSEM(polydeg = polydeg, surface_flux = surface_flux, | ||
| volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) | ||
| trees_per_cube_face = (8, 4) | ||
| mesh = P4estMeshCubedSphere(trees_per_cube_face..., 6.371229e6, 30000, | ||
| polydeg = polydeg, initial_refinement_level = 0) | ||
|
|
||
| semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, | ||
| source_terms = source_terms_baroclinic_instability, | ||
| boundary_conditions = boundary_conditions) | ||
|
|
||
| ############################################################################### | ||
| # ODE solvers, callbacks etc. | ||
| T = 10 # 10 days | ||
| tspan = (0.0, T * SECONDS_PER_DAY) # time in seconds for 10 days | ||
|
|
||
| ode = semidiscretize(semi, tspan) | ||
|
|
||
| summary_callback = SummaryCallback() | ||
|
|
||
| analysis_interval = 1000 | ||
| analysis_callback = AnalysisCallback(semi, interval = analysis_interval) | ||
|
|
||
| alive_callback = AliveCallback(analysis_interval = analysis_interval) | ||
|
|
||
| save_solution = SaveSolutionCallback(dt = 3840, save_initial_solution = true, | ||
| save_final_solution = true) | ||
|
|
||
| callbacks = CallbackSet(summary_callback, | ||
| analysis_callback, | ||
| alive_callback, | ||
| save_solution) | ||
|
|
||
| ############################################################################### | ||
| # Use a Runge-Kutta method with automatic (error based) time step size control | ||
| # Enable threading of the RK method for better performance on multiple threads | ||
| sol = solve(ode, | ||
| RDPK3SpFSAL49(thread = Trixi.True()); | ||
| abstol = 1.0e-5, reltol = 1.0e-5, ode_default_options()..., | ||
| callback = callbacks); | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
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.
Are you still using the same hardware as described there?