-
Notifications
You must be signed in to change notification settings - Fork 156
Add auxiliary variables, part 1 #3008
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
2bd998a
8b9b556
d9d7054
060054a
88e7f12
15cea5c
fa33421
5f8891f
14ec2f5
1e03b7e
f429f9b
a59ce7e
18305b7
6346829
4be0151
087f507
9cec964
7170717
9d1020e
d707495
ebe1b02
0b2a08d
14868f3
64b4f51
9de7add
468a5db
1d739fd
1a4d0ac
2e19fe7
258c5e4
1a32cf4
1af6698
63849f9
d3328d2
4ab46ba
a720a18
dc893e9
e731a01
8c770ce
3bc28ad
17cb325
2d15209
809a57a
b3ea5f9
dc0c5b9
4518f86
528d23a
2c1c8b8
2a8dab4
b75d164
6af4abc
3975943
526b7c3
b209dae
da3da00
01c1c01
5908986
4782e38
1707894
6f3cdc5
94e97cf
8b8bbd1
3b5bb64
9bab9d0
900914f
34dc3bb
3b59499
19d0a72
9318af8
21b38d1
995ab5b
87ff343
791191c
29646ae
0ff3587
bc6fb09
b1b5ebb
0f466c6
69411f4
8f3437c
0b36ca3
9517e98
540c829
eaa1dfe
a078ffb
68071e4
e40e6b0
9b4beb6
a896214
8909f98
d7262a3
82191a6
bd27c1c
b0e4593
5971eda
29a66a9
5057297
d1b8ac8
05e953c
56b33c7
6a601c8
ee30e6b
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,66 @@ | ||||||||||
| using OrdinaryDiffEqLowStorageRK | ||||||||||
| using Trixi | ||||||||||
|
|
||||||||||
| ############################################################################### | ||||||||||
| # semidiscretization of the acoustic perturbation equations | ||||||||||
|
|
||||||||||
| function auxiliary_variables_mean_values(x, equations) | ||||||||||
| # constant auxiliary variables (mean state) | ||||||||||
| return global_mean_vars(equations) | ||||||||||
| end | ||||||||||
|
Comment on lines
+8
to
+10
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. Does it really make sense to introduce this set of equations if the auxiliary variables are only given by some constants that are also stored in the
Contributor
Author
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. This is indeed not really useful; merely a proof of concept that can be compared to something in main as a sanity check. Non trivial velocity fields would be more exciting. I like the swirling flow by LeVeque: Although in this form it requires time dependent aux vars, which I added quick and dirty here Trixi.jl/src/solvers/dgsem_tree/dg_2d.jl Lines 125 to 128 in 9eea80c
One could of course start with a time constant variant of 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. Nice example! Something like this with constant-in-time (but variable-in-space) velocity would already be nice to ensure that the non-constant case works as expected.
Contributor
Author
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. Done in examples/tree_2d_dgsem/elixir_advection_variable_swirling_flow.jl |
||||||||||
|
|
||||||||||
| equations = AcousticPerturbationEquations2DAuxVars(v_mean_global = (0.5, 0.3), | ||||||||||
| c_mean_global = 2.0, | ||||||||||
| rho_mean_global = 0.9) | ||||||||||
|
|
||||||||||
| initial_condition = initial_condition_convergence_test | ||||||||||
|
|
||||||||||
| # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux | ||||||||||
| solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) | ||||||||||
|
|
||||||||||
| coordinates_min = (0.0, 0.0) # minimum coordinates (min(x), min(y)) | ||||||||||
| coordinates_max = (2.0, 2.0) # maximum coordinates (max(x), max(y)) | ||||||||||
|
|
||||||||||
| # Create a uniformly refined mesh with periodic boundaries | ||||||||||
| mesh = TreeMesh(coordinates_min, coordinates_max, | ||||||||||
| initial_refinement_level = 3, | ||||||||||
| n_cells_max = 30_000, periodicity = true) # set maximum capacity of tree data structure | ||||||||||
|
|
||||||||||
| # A semidiscretization collects data structures and functions for the spatial discretization | ||||||||||
| semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, | ||||||||||
| source_terms = source_terms_convergence_test, | ||||||||||
| boundary_conditions = boundary_condition_periodic, | ||||||||||
| aux_field = auxiliary_variables_mean_values) | ||||||||||
|
benegee marked this conversation as resolved.
|
||||||||||
|
|
||||||||||
| ############################################################################### | ||||||||||
| # ODE solvers, callbacks etc. | ||||||||||
|
|
||||||||||
| # Create ODE problem with time span from 0.0 to 1.0 | ||||||||||
| tspan = (0.0, 1.0) | ||||||||||
| ode = semidiscretize(semi, tspan) | ||||||||||
|
|
||||||||||
| # At the beginning of the main loop, the SummaryCallback prints a summary of the simulation setup | ||||||||||
| # and resets the timers | ||||||||||
| summary_callback = SummaryCallback() | ||||||||||
|
|
||||||||||
| # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results | ||||||||||
| analysis_callback = AnalysisCallback(semi, interval = 100) | ||||||||||
|
|
||||||||||
| # The SaveSolutionCallback allows to save the solution to a file in regular intervals | ||||||||||
| save_solution = SaveSolutionCallback(interval = 100, | ||||||||||
| solution_variables = cons2prim) | ||||||||||
|
|
||||||||||
| # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step | ||||||||||
| stepsize_callback = StepsizeCallback(cfl = 0.5) | ||||||||||
|
|
||||||||||
| # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver | ||||||||||
| callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, | ||||||||||
| stepsize_callback) | ||||||||||
|
|
||||||||||
| ############################################################################### | ||||||||||
| # run the simulation | ||||||||||
|
|
||||||||||
| # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks | ||||||||||
| sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false); | ||||||||||
| dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback | ||||||||||
| ode_default_options()..., callback = callbacks); | ||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,95 @@ | ||
| using OrdinaryDiffEqLowStorageRK | ||
| using Trixi | ||
| using Plots | ||
|
|
||
| ############################################################################### | ||
| # semidiscretization of the acoustic perturbation equations | ||
|
|
||
| equations = AcousticPerturbationEquations2DAuxVars(v_mean_global = (0.5, 0.0), | ||
| c_mean_global = 1.0, | ||
| rho_mean_global = 1.0) | ||
|
|
||
| # Create DG solver with polynomial degree = 5 and (local) Lax-Friedrichs/Rusanov flux as surface flux | ||
| solver = DGSEM(polydeg = 5, surface_flux = flux_lax_friedrichs) | ||
|
|
||
| coordinates_min = (-100.0, 0.0) # minimum coordinates (min(x), min(y)) | ||
| coordinates_max = (100.0, 200.0) # maximum coordinates (max(x), max(y)) | ||
|
|
||
| # Create a uniformly refined mesh with periodic boundaries | ||
| mesh = TreeMesh(coordinates_min, coordinates_max, | ||
| initial_refinement_level = 2, | ||
| n_cells_max = 100_000, | ||
| periodicity = false) | ||
|
|
||
| """ | ||
| initial_condition_gauss_wall(x, t, equations::AcousticPerturbationEquations2DAuxVars) | ||
|
|
||
| A Gaussian pulse, used in the `gauss_wall` example elixir in combination with | ||
| [`boundary_condition_wall`](@ref). Uses the global mean values from `equations`. | ||
| """ | ||
| function initial_condition_gauss_wall(x, t, | ||
| equations::AcousticPerturbationEquations2DAuxVars) | ||
| RealT = eltype(x) | ||
| v1_prime = 0 | ||
| v2_prime = 0 | ||
| p_prime = exp(-log(convert(RealT, 2)) * (x[1]^2 + (x[2] - 25)^2) / 25) | ||
| p_prime_scaled = p_prime / equations.c_mean_global^2 | ||
|
|
||
| return SVector(v1_prime, v2_prime, p_prime_scaled) | ||
| end | ||
| initial_condition = initial_condition_gauss_wall | ||
|
|
||
| function auxiliary_variables_mean_values(x, equations) | ||
| # constant auxiliary variables (mean state) | ||
| return global_mean_vars(equations) | ||
| end | ||
|
|
||
| @inline function p_prime(u, equations::AcousticPerturbationEquations2DAuxVars) | ||
| return u[3] | ||
| end | ||
|
|
||
| # A semidiscretization collects data structures and functions for the spatial discretization | ||
| semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, | ||
| boundary_conditions = boundary_condition_wall, | ||
| aux_field = auxiliary_variables_mean_values) | ||
|
|
||
| ############################################################################### | ||
| # ODE solvers, callbacks etc. | ||
|
|
||
| # Create ODE problem with time span from 0.0 to 30.0 | ||
| tspan = (0.0, 30.0) | ||
| ode = semidiscretize(semi, tspan) | ||
|
|
||
| # At the beginning of the main loop, the SummaryCallback prints a summary of the simulation setup | ||
| # and resets the timers | ||
| summary_callback = SummaryCallback() | ||
|
|
||
| # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results | ||
| analysis_callback = AnalysisCallback(semi, interval = 100) | ||
|
|
||
| # The SaveSolutionCallback allows to save the solution to a file in regular intervals | ||
| save_solution = SaveSolutionCallback(interval = 100, solution_variables = cons2state) | ||
|
|
||
| # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step | ||
| stepsize_callback = StepsizeCallback(cfl = 0.7) | ||
|
|
||
| amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable = p_prime), | ||
| base_level = 2, | ||
| med_level = 4, med_threshold = 0.1, | ||
| max_level = 5, max_threshold = 0.2) | ||
| amr_callback = AMRCallback(semi, amr_controller, | ||
| interval = 5, | ||
| adapt_initial_condition = true, | ||
| adapt_initial_condition_only_refine = true) | ||
|
|
||
| # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver | ||
| callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, | ||
| amr_callback, stepsize_callback) | ||
|
|
||
| ############################################################################### | ||
| # run the simulation | ||
|
|
||
| # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks | ||
| sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false); | ||
| dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback | ||
| ode_default_options()..., callback = callbacks) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| using OrdinaryDiffEqLowStorageRK | ||
| using Trixi | ||
|
|
||
| ############################################################################### | ||
| # semidiscretization of the acoustic perturbation equations | ||
|
|
||
| equations = AcousticPerturbationEquations2DAuxVars(v_mean_global = (0.5, 0.0), | ||
| c_mean_global = 1.0, | ||
| rho_mean_global = 1.0) | ||
|
|
||
| # Create DG solver with polynomial degree = 5 and (local) Lax-Friedrichs/Rusanov flux as surface flux | ||
| solver = DGSEM(polydeg = 5, surface_flux = flux_lax_friedrichs) | ||
|
|
||
| coordinates_min = (-100.0, 0.0) # minimum coordinates (min(x), min(y)) | ||
| coordinates_max = (100.0, 200.0) # maximum coordinates (max(x), max(y)) | ||
|
|
||
| # Create a uniformly refined mesh with periodic boundaries | ||
| mesh = TreeMesh(coordinates_min, coordinates_max, | ||
| initial_refinement_level = 4, | ||
| n_cells_max = 100_000, | ||
| periodicity = false) | ||
|
|
||
| """ | ||
| initial_condition_gauss_wall(x, t, equations::AcousticPerturbationEquations2DAuxVars) | ||
|
|
||
| A Gaussian pulse, used in the `gauss_wall` example elixir in combination with | ||
| [`boundary_condition_wall`](@ref). Uses the global mean values from `equations`. | ||
| """ | ||
| function initial_condition_gauss_wall(x, t, | ||
| equations::AcousticPerturbationEquations2DAuxVars) | ||
| RealT = eltype(x) | ||
| v1_prime = 0 | ||
| v2_prime = 0 | ||
| p_prime = exp(-log(convert(RealT, 2)) * (x[1]^2 + (x[2] - 25)^2) / 25) | ||
| p_prime_scaled = p_prime / equations.c_mean_global^2 | ||
|
|
||
| return SVector(v1_prime, v2_prime, p_prime_scaled) | ||
| end | ||
| initial_condition = initial_condition_gauss_wall | ||
|
|
||
| function auxiliary_variables_mean_values(x, equations) | ||
| # constant auxiliary variables (mean state) | ||
| return global_mean_vars(equations) | ||
| end | ||
|
|
||
| # A semidiscretization collects data structures and functions for the spatial discretization | ||
| semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, | ||
| boundary_conditions = boundary_condition_wall, | ||
| aux_field = auxiliary_variables_mean_values) | ||
|
|
||
| ############################################################################### | ||
| # ODE solvers, callbacks etc. | ||
|
|
||
| # Create ODE problem with time span from 0.0 to 30.0 | ||
| tspan = (0.0, 30.0) | ||
| ode = semidiscretize(semi, tspan) | ||
|
|
||
| # At the beginning of the main loop, the SummaryCallback prints a summary of the simulation setup | ||
| # and resets the timers | ||
| summary_callback = SummaryCallback() | ||
|
|
||
| # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results | ||
| analysis_callback = AnalysisCallback(semi, interval = 100) | ||
|
|
||
| # The SaveSolutionCallback allows to save the solution to a file in regular intervals | ||
| save_solution = SaveSolutionCallback(interval = 100, solution_variables = cons2state) | ||
|
|
||
| # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step | ||
| stepsize_callback = StepsizeCallback(cfl = 0.7) | ||
|
|
||
| # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver | ||
| callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, | ||
| stepsize_callback) | ||
|
|
||
| ############################################################################### | ||
| # run the simulation | ||
|
|
||
| # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks | ||
| sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false); | ||
| dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback | ||
| ode_default_options()..., callback = callbacks) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,126 @@ | ||
| using OrdinaryDiffEqLowStorageRK | ||
| using Trixi | ||
| using Plots | ||
|
|
||
| # Advection test case following | ||
| # Randall J. LeVeque | ||
| # High-Resolution Conservative Algorithms for Advection in Incompressible Flow | ||
| # https://doi.org/10.1137/0733033 | ||
|
|
||
| ############################################################################################ | ||
| # initial condition | ||
|
|
||
| equations = LinearVariableScalarAdvectionEquation2D() | ||
|
|
||
| function initial_condition_advected_objects(x, t, | ||
| equations::LinearVariableScalarAdvectionEquation2D) | ||
| RealT = eltype(x) | ||
|
|
||
| # smooth hump | ||
| x_0, y_0, r_0 = 0.25f0, 0.5f0, convert(RealT, 0.15) | ||
| r = sqrt((x[1] - x_0)^2 + (x[2] - y_0)^2) | ||
| r = min(r, r_0) / r_0 | ||
| hump = 0.25f0 * (1 + cospi(r)) | ||
|
|
||
| # cone | ||
| x_1, y_1, r_1 = 0.5f0, 0.25f0, convert(RealT, 0.15) | ||
| r = sqrt((x[1] - x_1)^2 + (x[2] - y_1)^2) | ||
| cone = 1.0f0 - min(r, r_1) / r_1 | ||
|
|
||
| # slotted disc | ||
| x_2, y_2, r_2 = 0.5f0, 0.75f0, convert(RealT, 0.15) | ||
| w, l = 0.05f0, convert(RealT, 0.25) | ||
| r = sqrt((x[1] - x_2)^2 + (x[2] - y_2)^2) | ||
| disc = 0 | ||
| if r <= r_2 && (x[2] >= y_2 - r_2 + l || abs(x[1] - x_2) >= w) | ||
| disc = 1.0f0 | ||
| end | ||
|
|
||
| return SVector(hump + cone + disc) | ||
| end | ||
|
|
||
| # velocity field at time t = 0 (see reference) | ||
| @inline function velocity_swirling(x, equations) | ||
| u = sinpi(x[1])^2 * sinpi(2 * x[2]) | ||
| v = -sinpi(x[2])^2 * sinpi(2 * x[1]) | ||
| return SVector(u, v) | ||
| end | ||
|
|
||
| ############################################################################################ | ||
| # semidiscretization | ||
| polydeg = 3 | ||
|
|
||
| initial_condition = initial_condition_advected_objects | ||
|
|
||
| surface_flux = flux_lax_friedrichs | ||
| solver = DGSEM(polydeg = polydeg, surface_flux = surface_flux) | ||
|
|
||
| coordinates_min = (0.0, 0.0) | ||
| coordinates_max = (1.0, 1.0) | ||
|
|
||
| mesh = TreeMesh(coordinates_min, coordinates_max, | ||
| initial_refinement_level = 2, | ||
| periodicity = false) | ||
|
|
||
| # boundary conditions | ||
| boundary_condition_dirichlet = BoundaryConditionDirichlet(initial_condition_advected_objects) | ||
| boundary_conditions = (; x_neg = boundary_condition_dirichlet, | ||
| x_pos = boundary_condition_dirichlet, | ||
| y_neg = boundary_condition_dirichlet, | ||
| y_pos = boundary_condition_dirichlet) | ||
|
|
||
| # the velocity is passed as auxiliary_field into the cache | ||
| semi = SemidiscretizationHyperbolic(mesh, | ||
| equations, | ||
| initial_condition, | ||
| solver, | ||
| boundary_conditions = boundary_conditions, | ||
| aux_field = velocity_swirling) | ||
|
|
||
| ############################################################################################## | ||
| # ODE solvers, callbacks etc. | ||
|
|
||
| tspan = (0.0, 1.0) | ||
| ode = semidiscretize(semi, tspan) | ||
|
|
||
| summary_callback = SummaryCallback() | ||
|
|
||
| analysis_interval = 100 | ||
| solution_variables = cons2prim | ||
|
|
||
| analysis_callback = AnalysisCallback(semi, | ||
| interval = analysis_interval) | ||
|
|
||
| alive_callback = AliveCallback(analysis_interval = analysis_interval) | ||
|
|
||
| save_solution = SaveSolutionCallback(interval = 10, | ||
| save_initial_solution = true, | ||
| save_final_solution = true, | ||
| output_directory = "out_swirling", | ||
| solution_variables = solution_variables) | ||
|
|
||
| amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable = first), | ||
| base_level = 2, | ||
| med_level = 4, med_threshold = 0.3, | ||
| max_level = 6, max_threshold = 0.8) | ||
| amr_callback = AMRCallback(semi, amr_controller, | ||
| interval = 20, | ||
| adapt_initial_condition = true, | ||
| adapt_initial_condition_only_refine = true) | ||
|
|
||
| stepsize_callback = StepsizeCallback(cfl = 1.0) | ||
|
|
||
| visualization = VisualizationCallback(semi; interval = 20) #, show_mesh = true) | ||
|
|
||
| callbacks = CallbackSet(summary_callback, | ||
| analysis_callback, | ||
| alive_callback, | ||
| stepsize_callback, | ||
| amr_callback, | ||
| #visualization, | ||
| save_solution) | ||
|
|
||
| ############################################################################### | ||
| # run the simulation | ||
| sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false); | ||
| dt = 1.0, ode_default_options()..., callback = callbacks); |

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.
Would it make sense (or be interesting) to compute first the initial condition and then pass also the initial condition
u0as a parameter to the auxiliary field function?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.
I see this would be convenient when e.g. setting up perturbations of a steady background state.
However,
u0is computed usingcompute_coefficients(t, semi), which takes aSemidiscretizationobject, right?