From 151e08958510e96d6ef07bcbf7bfff65fa44db4f Mon Sep 17 00:00:00 2001 From: "Documenter.jl" Date: Fri, 10 Nov 2023 18:29:09 +0000 Subject: [PATCH] build based on 87ae1e6 --- previews/PR1681/.documenter-siteinfo.json | 2 +- previews/PR1681/authors/index.html | 2 +- previews/PR1681/callbacks/index.html | 2 +- previews/PR1681/code_of_conduct/index.html | 2 +- previews/PR1681/contributing/index.html | 2 +- previews/PR1681/conventions/index.html | 2 +- previews/PR1681/development/index.html | 2 +- previews/PR1681/github-git/index.html | 2 +- previews/PR1681/index.html | 2 +- previews/PR1681/license/index.html | 2 +- .../PR1681/meshes/dgmulti_mesh/index.html | 2 +- previews/PR1681/meshes/p4est_mesh/index.html | 2 +- .../PR1681/meshes/structured_mesh/index.html | 2 +- previews/PR1681/meshes/tree_mesh/index.html | 2 +- .../meshes/unstructured_quad_mesh/index.html | 2 +- previews/PR1681/overview/index.html | 2 +- previews/PR1681/parallelization/index.html | 2 +- previews/PR1681/performance/index.html | 2 +- previews/PR1681/reference-trixi/index.html | 334 +- .../PR1681/reference-trixi2vtk/index.html | 2 +- previews/PR1681/restart/index.html | 2 +- previews/PR1681/styleguide/index.html | 2 +- previews/PR1681/testing/index.html | 2 +- previews/PR1681/time_integration/index.html | 2 +- previews/PR1681/troubleshooting/index.html | 2 +- .../PR1681/tutorials/DGMulti_1/0ef25871.svg | 5560 ------ .../DGMulti_1/{6435848f.svg => 9b237cd1.svg} | 3650 ++-- .../PR1681/tutorials/DGMulti_1/b945cc27.svg | 5544 ++++++ .../DGMulti_1/{866a258b.svg => c299c6bb.svg} | 6387 +++--- .../DGMulti_1/{3582722c.svg => cd2c475f.svg} | 2811 ++- .../DGMulti_1/{0beb6b7a.svg => d8522fac.svg} | 8254 ++++---- .../DGMulti_1/{db7d466c.svg => ee6d8341.svg} | 16622 ++++++++-------- .../PR1681/tutorials/DGMulti_1/index.html | 114 +- .../PR1681/tutorials/DGMulti_2/index.html | 2 +- .../{d76be45a.svg => 9e69cdbf.svg} | 230 +- .../{d81dd9bb.svg => eaa6ef71.svg} | 230 +- .../tutorials/DGSEM_FluxDiff/index.html | 30 +- .../{84e8847b.svg => 6bddc81d.svg} | 878 +- .../adaptive_mesh_refinement/index.html | 4 +- .../{42941795.svg => 25adef82.svg} | 62 +- .../adding_new_parabolic_terms/index.html | 4 +- .../{3c496abd.svg => 037a3c25.svg} | 56 +- .../{2d45a4b3.svg => b71d3b97.svg} | 56 +- .../{ed1cdc0b.svg => d1c18207.svg} | 64 +- .../{819aa639.svg => d9d6fd57.svg} | 58 +- .../{b3441695.svg => e8dd2c31.svg} | 56 +- .../adding_new_scalar_equations/index.html | 12 +- .../{02d1b901.svg => 55d6a6f8.svg} | 122 +- .../index.html | 4 +- .../{7fdbc3c2.svg => 3ddb5ee4.svg} | 72 +- .../{6eb03de2.svg => 55d6d008.svg} | 64 +- .../{5051b8ca.svg => 93f61941.svg} | 68 +- .../{80c2f02a.svg => a7508ee1.svg} | 72 +- .../{49e341de.svg => fbdfe4c5.svg} | 72 +- .../custom_semidiscretization/index.html | 152 +- .../{ca93b49c.svg => 1fdc93bc.svg} | 64 +- .../{3e716af2.svg => 36b88e57.svg} | 64 +- .../{2daceea9.svg => 3a730479.svg} | 1598 +- .../{66aeb6f0.svg => 60cd9935.svg} | 2122 +- .../{89f46729.svg => 693c4676.svg} | 1588 +- .../{d754903e.svg => a82db249.svg} | 586 +- .../{1265e464.svg => f8b88653.svg} | 4172 ++-- .../{73e977d3.svg => f92e7ae5.svg} | 3136 +-- .../differentiable_programming/index.html | 28 +- .../tutorials/hohqmesh_tutorial/index.html | 2 +- .../PR1681/tutorials/introduction/index.html | 2 +- .../{22d86131.svg => 67e0973b.svg} | 72 +- .../non_periodic_boundaries/index.html | 4 +- .../PR1681/tutorials/out/restart_000050.h5 | Bin 11976 -> 11976 bytes .../PR1681/tutorials/out/restart_000100.h5 | Bin 11976 -> 11976 bytes .../PR1681/tutorials/out/restart_000150.h5 | Bin 11976 -> 11976 bytes .../PR1681/tutorials/out/restart_000180.h5 | Bin 11976 -> 11976 bytes .../PR1681/tutorials/out/solution_000.pvd | 14 +- .../PR1681/tutorials/out/solution_000000.h5 | Bin 205696 -> 205696 bytes .../PR1681/tutorials/out/solution_000010.h5 | Bin 205696 -> 205696 bytes .../PR1681/tutorials/out/solution_000010.vtu | Bin 18966 -> 18962 bytes .../PR1681/tutorials/out/solution_000020.h5 | Bin 205696 -> 205696 bytes .../PR1681/tutorials/out/solution_000020.vtu | Bin 19000 -> 19007 bytes .../PR1681/tutorials/out/solution_000030.h5 | Bin 205696 -> 205696 bytes .../PR1681/tutorials/out/solution_000030.vtu | Bin 19045 -> 19040 bytes .../PR1681/tutorials/out/solution_000040.h5 | Bin 205696 -> 205696 bytes .../PR1681/tutorials/out/solution_000040.vtu | Bin 19091 -> 19074 bytes .../PR1681/tutorials/out/solution_000050.h5 | Bin 205696 -> 205696 bytes .../PR1681/tutorials/out/solution_000050.vtu | Bin 19110 -> 19114 bytes .../PR1681/tutorials/out/solution_000060.h5 | Bin 205696 -> 205696 bytes .../PR1681/tutorials/out/solution_000060.vtu | Bin 19131 -> 19135 bytes .../PR1681/tutorials/out/solution_000065.h5 | Bin 205696 -> 205696 bytes .../PR1681/tutorials/out/solution_000070.h5 | Bin 11976 -> 11976 bytes .../PR1681/tutorials/out/solution_000070.vtu | Bin 19148 -> 19162 bytes .../PR1681/tutorials/out/solution_000080.h5 | Bin 11976 -> 11976 bytes .../PR1681/tutorials/out/solution_000080.vtu | Bin 19171 -> 19161 bytes .../PR1681/tutorials/out/solution_000090.h5 | Bin 11976 -> 11976 bytes .../PR1681/tutorials/out/solution_000090.vtu | Bin 19175 -> 19180 bytes .../PR1681/tutorials/out/solution_000100.h5 | Bin 11976 -> 11976 bytes .../PR1681/tutorials/out/solution_000100.vtu | Bin 19213 -> 19199 bytes .../PR1681/tutorials/out/solution_000110.h5 | Bin 11976 -> 11976 bytes .../PR1681/tutorials/out/solution_000110.vtu | Bin 19188 -> 19193 bytes .../PR1681/tutorials/out/solution_000120.h5 | Bin 11976 -> 11976 bytes .../PR1681/tutorials/out/solution_000120.vtu | Bin 19147 -> 19152 bytes .../PR1681/tutorials/out/solution_000130.h5 | Bin 11976 -> 11976 bytes .../PR1681/tutorials/out/solution_000130.vtu | Bin 19172 -> 19166 bytes .../PR1681/tutorials/out/solution_000140.h5 | Bin 11976 -> 11976 bytes .../PR1681/tutorials/out/solution_000140.vtu | Bin 19171 -> 19172 bytes .../PR1681/tutorials/out/solution_000150.h5 | Bin 11976 -> 11976 bytes .../PR1681/tutorials/out/solution_000150.vtu | Bin 19176 -> 19164 bytes .../PR1681/tutorials/out/solution_000160.h5 | Bin 11976 -> 11976 bytes .../PR1681/tutorials/out/solution_000160.vtu | Bin 19165 -> 19183 bytes .../PR1681/tutorials/out/solution_000170.h5 | Bin 11976 -> 11976 bytes .../PR1681/tutorials/out/solution_000170.vtu | Bin 19202 -> 19194 bytes .../PR1681/tutorials/out/solution_000180.h5 | Bin 11976 -> 11976 bytes .../PR1681/tutorials/out/solution_000180.vtu | Bin 19180 -> 19171 bytes .../tutorials/out/solution_000_celldata.pvd | 14 +- .../{4c2612a7.svg => 81b5671d.svg} | 62 +- .../tutorials/parabolic_terms/index.html | 4 +- .../{434b34a6.svg => 19b3a3e4.svg} | 64 +- .../{b1d3fba9.svg => 3e433403.svg} | 80 +- .../{953f0248.svg => a332a720.svg} | 64 +- .../{7bdb08b0.svg => b25f27b1.svg} | 68 +- .../{c873c8e9.svg => ee75fe34.svg} | 64 +- .../{952a9e26.svg => f82fb5d5.svg} | 68 +- .../scalar_linear_advection_1d/index.html | 14 +- .../{90d3f665.svg => 1d580507.svg} | 230 +- .../tutorials/shock_capturing/index.html | 4 +- .../structured_mesh_mapping/1b7637f2.svg | 9477 --------- .../structured_mesh_mapping/26f930a1.svg | 3797 ---- .../structured_mesh_mapping/51ddd472.svg | 5570 ------ .../structured_mesh_mapping/5828c73c.svg | 9477 +++++++++ .../structured_mesh_mapping/d406fc84.svg | 5571 ++++++ .../structured_mesh_mapping/e9677294.svg | 3795 ++++ .../structured_mesh_mapping/index.html | 28 +- .../PR1681/tutorials/time_stepping/index.html | 2 +- .../PR1681/tutorials/upwind_fdsbp/index.html | 2 +- previews/PR1681/visualization/index.html | 2 +- 133 files changed, 51772 insertions(+), 51829 deletions(-) delete mode 100644 previews/PR1681/tutorials/DGMulti_1/0ef25871.svg rename previews/PR1681/tutorials/DGMulti_1/{6435848f.svg => 9b237cd1.svg} (89%) create mode 100644 previews/PR1681/tutorials/DGMulti_1/b945cc27.svg rename previews/PR1681/tutorials/DGMulti_1/{866a258b.svg => c299c6bb.svg} (58%) rename previews/PR1681/tutorials/DGMulti_1/{3582722c.svg => cd2c475f.svg} (76%) rename previews/PR1681/tutorials/DGMulti_1/{0beb6b7a.svg => d8522fac.svg} (90%) rename previews/PR1681/tutorials/DGMulti_1/{db7d466c.svg => ee6d8341.svg} (86%) rename previews/PR1681/tutorials/DGSEM_FluxDiff/{d76be45a.svg => 9e69cdbf.svg} (95%) rename previews/PR1681/tutorials/DGSEM_FluxDiff/{d81dd9bb.svg => eaa6ef71.svg} (94%) rename previews/PR1681/tutorials/adaptive_mesh_refinement/{84e8847b.svg => 6bddc81d.svg} (85%) rename previews/PR1681/tutorials/adding_new_parabolic_terms/{42941795.svg => 25adef82.svg} (93%) rename previews/PR1681/tutorials/adding_new_scalar_equations/{3c496abd.svg => 037a3c25.svg} (92%) rename previews/PR1681/tutorials/adding_new_scalar_equations/{2d45a4b3.svg => b71d3b97.svg} (92%) rename previews/PR1681/tutorials/adding_new_scalar_equations/{ed1cdc0b.svg => d1c18207.svg} (91%) rename previews/PR1681/tutorials/adding_new_scalar_equations/{819aa639.svg => d9d6fd57.svg} (85%) rename previews/PR1681/tutorials/adding_new_scalar_equations/{b3441695.svg => e8dd2c31.svg} (84%) rename previews/PR1681/tutorials/adding_nonconservative_equation/{02d1b901.svg => 55d6a6f8.svg} (84%) rename previews/PR1681/tutorials/custom_semidiscretization/{7fdbc3c2.svg => 3ddb5ee4.svg} (86%) rename previews/PR1681/tutorials/custom_semidiscretization/{6eb03de2.svg => 55d6d008.svg} (85%) rename previews/PR1681/tutorials/custom_semidiscretization/{5051b8ca.svg => 93f61941.svg} (86%) rename previews/PR1681/tutorials/custom_semidiscretization/{80c2f02a.svg => a7508ee1.svg} (86%) rename previews/PR1681/tutorials/custom_semidiscretization/{49e341de.svg => fbdfe4c5.svg} (86%) rename previews/PR1681/tutorials/differentiable_programming/{ca93b49c.svg => 1fdc93bc.svg} (84%) rename previews/PR1681/tutorials/differentiable_programming/{3e716af2.svg => 36b88e57.svg} (85%) rename previews/PR1681/tutorials/differentiable_programming/{2daceea9.svg => 3a730479.svg} (57%) rename previews/PR1681/tutorials/differentiable_programming/{66aeb6f0.svg => 60cd9935.svg} (59%) rename previews/PR1681/tutorials/differentiable_programming/{89f46729.svg => 693c4676.svg} (65%) rename previews/PR1681/tutorials/differentiable_programming/{d754903e.svg => a82db249.svg} (69%) rename previews/PR1681/tutorials/differentiable_programming/{1265e464.svg => f8b88653.svg} (66%) rename previews/PR1681/tutorials/differentiable_programming/{73e977d3.svg => f92e7ae5.svg} (67%) rename previews/PR1681/tutorials/non_periodic_boundaries/{22d86131.svg => 67e0973b.svg} (81%) rename previews/PR1681/tutorials/parabolic_terms/{4c2612a7.svg => 81b5671d.svg} (93%) rename previews/PR1681/tutorials/scalar_linear_advection_1d/{434b34a6.svg => 19b3a3e4.svg} (82%) rename previews/PR1681/tutorials/scalar_linear_advection_1d/{b1d3fba9.svg => 3e433403.svg} (79%) rename previews/PR1681/tutorials/scalar_linear_advection_1d/{953f0248.svg => a332a720.svg} (83%) rename previews/PR1681/tutorials/scalar_linear_advection_1d/{7bdb08b0.svg => b25f27b1.svg} (85%) rename previews/PR1681/tutorials/scalar_linear_advection_1d/{c873c8e9.svg => ee75fe34.svg} (83%) rename previews/PR1681/tutorials/scalar_linear_advection_1d/{952a9e26.svg => f82fb5d5.svg} (85%) rename previews/PR1681/tutorials/shock_capturing/{90d3f665.svg => 1d580507.svg} (95%) delete mode 100644 previews/PR1681/tutorials/structured_mesh_mapping/1b7637f2.svg delete mode 100644 previews/PR1681/tutorials/structured_mesh_mapping/26f930a1.svg delete mode 100644 previews/PR1681/tutorials/structured_mesh_mapping/51ddd472.svg create mode 100644 previews/PR1681/tutorials/structured_mesh_mapping/5828c73c.svg create mode 100644 previews/PR1681/tutorials/structured_mesh_mapping/d406fc84.svg create mode 100644 previews/PR1681/tutorials/structured_mesh_mapping/e9677294.svg diff --git a/previews/PR1681/.documenter-siteinfo.json b/previews/PR1681/.documenter-siteinfo.json index 7f7fdf06544..7c1c2ec2032 100644 --- a/previews/PR1681/.documenter-siteinfo.json +++ b/previews/PR1681/.documenter-siteinfo.json @@ -1 +1 @@ -{"documenter":{"julia_version":"1.9.3","generation_timestamp":"2023-11-09T17:23:54","documenter_version":"1.1.2"}} \ No newline at end of file +{"documenter":{"julia_version":"1.9.3","generation_timestamp":"2023-11-10T18:28:27","documenter_version":"1.1.2"}} \ No newline at end of file diff --git a/previews/PR1681/authors/index.html b/previews/PR1681/authors/index.html index 4462e0a7e93..bef9aab8855 100644 --- a/previews/PR1681/authors/index.html +++ b/previews/PR1681/authors/index.html @@ -1,2 +1,2 @@ -Authors · Trixi.jl

Authors

Trixi.jl's development is coordinated by a group of principal developers, who are also its main contributors and who can be contacted in case of questions about Trixi.jl. In addition, there are contributors who have provided substantial additions or modifications. Together, these two groups form "The Trixi.jl Authors" as mentioned under License.

Principal Developers

Contributors

The following people contributed major additions or modifications to Trixi.jl and are listed in alphabetical order:

  • Maximilian D. Bertrand
  • Benjamin Bolm
  • Simon Candelaresi
  • Jesse Chan
  • Lars Christmann
  • Christof Czernik
  • Daniel Doehring
  • Patrick Ersing
  • Erik Faulhaber
  • Gregor Gassner
  • Lucas Gemein
  • Sven Goldberg
  • Joshua Lampert
  • Julia Odenthal
  • Sigrun Ortleb
  • Hendrik Ranocha
  • Andrés M. Rueda-Ramírez
  • Felipe Santillan
  • Michael Schlottke-Lakemper
  • Toskan Theine
  • Andrew Winters
+Authors · Trixi.jl

Authors

Trixi.jl's development is coordinated by a group of principal developers, who are also its main contributors and who can be contacted in case of questions about Trixi.jl. In addition, there are contributors who have provided substantial additions or modifications. Together, these two groups form "The Trixi.jl Authors" as mentioned under License.

Principal Developers

Contributors

The following people contributed major additions or modifications to Trixi.jl and are listed in alphabetical order:

  • Maximilian D. Bertrand
  • Benjamin Bolm
  • Simon Candelaresi
  • Jesse Chan
  • Lars Christmann
  • Christof Czernik
  • Daniel Doehring
  • Patrick Ersing
  • Erik Faulhaber
  • Gregor Gassner
  • Lucas Gemein
  • Sven Goldberg
  • Joshua Lampert
  • Julia Odenthal
  • Sigrun Ortleb
  • Hendrik Ranocha
  • Andrés M. Rueda-Ramírez
  • Felipe Santillan
  • Michael Schlottke-Lakemper
  • Toskan Theine
  • Andrew Winters
diff --git a/previews/PR1681/callbacks/index.html b/previews/PR1681/callbacks/index.html index c2b69cd07eb..1f7f43f53eb 100644 --- a/previews/PR1681/callbacks/index.html +++ b/previews/PR1681/callbacks/index.html @@ -12,4 +12,4 @@ julia> pd2 = PlotData1D(time_series, 2) -julia> plot(pd1["p_prime"]); plot!(pd2["p_prime"], xguide="t")

will yield the following plot:

image

Miscellaneous

Equation-specific callbacks

Some callbacks provided by Trixi.jl implement specific features for certain equations:

Usage of step callbacks

Step callbacks are passed to the solve method from the ODE solver via the keyword argument callback. If you want to use a single callback cb, pass it as callback=cb. When using two or more callbacks, you need to turn them into a CallbackSet first by calling callbacks = CallbackSet(cb1, cb2) and passing it as callback=callbacks.

Note

There are some restrictions regarding the order of callbacks in a CallbackSet.

The callbacks are called after each time step but some callbacks actually belong to the next time step. Therefore, the callbacks should be ordered in the following way:

  • Callbacks that belong to the current time step:
    • SummaryCallback controls, among other things, timers and should thus be first
    • SteadyStateCallback may mark a time step as the last one
    • AnalysisCallback may do some checks that mark a time step as the last one
    • AliveCallback should be nearby AnalysisCallback
    • SaveSolutionCallback/SaveRestartCallback should save the current solution before it is degraded by AMR
    • VisualizationCallback should be called before the mesh is adapted
  • Callbacks that belong to the next time step:
    • AMRCallback
    • StepsizeCallback must be called after AMRCallback to accommodate potential changes to the mesh
    • GlmSpeedCallback must be called after StepsizeCallback because the step size affects the value of c_h
    • LBMCollisionCallback is already part of the calculations of the next time step and should therefore be called after StepsizeCallback

Stage callbacks

PositivityPreservingLimiterZhangShu is a positivity-preserving limiter, used to enforce physical constraints. An example elixir using this feature can be found at examples/tree_2d_dgsem/elixir_euler_positivity.jl.

Implementing new callbacks

Since Trixi.jl is compatible with OrdinaryDiffEq.jl, both packages share the same callback interface. A detailed description of it can be found in the OrdinaryDiffEq.jl documentation. Step callbacks are just called callbacks. Stage callbacks are called stage_limiter!.

An example elixir showing how to implement a new simple stage callback and a new simple step callback can be found at examples/tree_2d_dgsem/elixir_advection_callbacks.jl.

+julia> plot(pd1["p_prime"]); plot!(pd2["p_prime"], xguide="t")

will yield the following plot:

image

Miscellaneous

Equation-specific callbacks

Some callbacks provided by Trixi.jl implement specific features for certain equations:

Usage of step callbacks

Step callbacks are passed to the solve method from the ODE solver via the keyword argument callback. If you want to use a single callback cb, pass it as callback=cb. When using two or more callbacks, you need to turn them into a CallbackSet first by calling callbacks = CallbackSet(cb1, cb2) and passing it as callback=callbacks.

Note

There are some restrictions regarding the order of callbacks in a CallbackSet.

The callbacks are called after each time step but some callbacks actually belong to the next time step. Therefore, the callbacks should be ordered in the following way:

  • Callbacks that belong to the current time step:
    • SummaryCallback controls, among other things, timers and should thus be first
    • SteadyStateCallback may mark a time step as the last one
    • AnalysisCallback may do some checks that mark a time step as the last one
    • AliveCallback should be nearby AnalysisCallback
    • SaveSolutionCallback/SaveRestartCallback should save the current solution before it is degraded by AMR
    • VisualizationCallback should be called before the mesh is adapted
  • Callbacks that belong to the next time step:
    • AMRCallback
    • StepsizeCallback must be called after AMRCallback to accommodate potential changes to the mesh
    • GlmSpeedCallback must be called after StepsizeCallback because the step size affects the value of c_h
    • LBMCollisionCallback is already part of the calculations of the next time step and should therefore be called after StepsizeCallback

Stage callbacks

PositivityPreservingLimiterZhangShu is a positivity-preserving limiter, used to enforce physical constraints. An example elixir using this feature can be found at examples/tree_2d_dgsem/elixir_euler_positivity.jl.

Implementing new callbacks

Since Trixi.jl is compatible with OrdinaryDiffEq.jl, both packages share the same callback interface. A detailed description of it can be found in the OrdinaryDiffEq.jl documentation. Step callbacks are just called callbacks. Stage callbacks are called stage_limiter!.

An example elixir showing how to implement a new simple stage callback and a new simple step callback can be found at examples/tree_2d_dgsem/elixir_advection_callbacks.jl.

diff --git a/previews/PR1681/code_of_conduct/index.html b/previews/PR1681/code_of_conduct/index.html index 977ae3e6e50..0481e1d6ce7 100644 --- a/previews/PR1681/code_of_conduct/index.html +++ b/previews/PR1681/code_of_conduct/index.html @@ -1,2 +1,2 @@ -Code of Conduct · Trixi.jl

Code of Conduct

Contributor Covenant Code of Conduct

Our Pledge

We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.

We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.

Our Standards

Examples of behavior that contributes to a positive environment for our community include:

  • Demonstrating empathy and kindness toward other people
  • Being respectful of differing opinions, viewpoints, and experiences
  • Giving and gracefully accepting constructive feedback
  • Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
  • Focusing on what is best not just for us as individuals, but for the overall community

Examples of unacceptable behavior include:

  • The use of sexualized language or imagery, and sexual attention or advances of any kind
  • Trolling, insulting or derogatory comments, and personal or political attacks
  • Public or private harassment
  • Publishing others' private information, such as a physical or email address, without their explicit permission
  • Other conduct which could reasonably be considered inappropriate in a professional setting

Enforcement Responsibilities

Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.

Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate.

Scope

This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.

Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to Michael Schlottke-Lakemper, Hendrik Ranocha, or any other of the principal developers responsible for enforcement listed in Authors. All complaints will be reviewed and investigated promptly and fairly.

All community leaders are obligated to respect the privacy and security of the reporter of any incident.

Enforcement Guidelines

Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct:

1. Correction

Community Impact: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community.

Consequence: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested.

2. Warning

Community Impact: A violation through a single incident or series of actions.

Consequence: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban.

3. Temporary Ban

Community Impact: A serious violation of community standards, including sustained inappropriate behavior.

Consequence: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban.

4. Permanent Ban

Community Impact: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals.

Consequence: A permanent ban from any sort of public interaction within the community.

Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0, available at https://www.contributor-covenant.org/version/2/0/codeofconduct.html.

Community Impact Guidelines were inspired by Mozilla's code of conduct enforcement ladder.

[homepage]: https://www.contributor-covenant.org

For answers to common questions about this code of conduct, see the FAQ at https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations.

+Code of Conduct · Trixi.jl

Code of Conduct

Contributor Covenant Code of Conduct

Our Pledge

We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.

We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.

Our Standards

Examples of behavior that contributes to a positive environment for our community include:

  • Demonstrating empathy and kindness toward other people
  • Being respectful of differing opinions, viewpoints, and experiences
  • Giving and gracefully accepting constructive feedback
  • Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
  • Focusing on what is best not just for us as individuals, but for the overall community

Examples of unacceptable behavior include:

  • The use of sexualized language or imagery, and sexual attention or advances of any kind
  • Trolling, insulting or derogatory comments, and personal or political attacks
  • Public or private harassment
  • Publishing others' private information, such as a physical or email address, without their explicit permission
  • Other conduct which could reasonably be considered inappropriate in a professional setting

Enforcement Responsibilities

Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.

Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate.

Scope

This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.

Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to Michael Schlottke-Lakemper, Hendrik Ranocha, or any other of the principal developers responsible for enforcement listed in Authors. All complaints will be reviewed and investigated promptly and fairly.

All community leaders are obligated to respect the privacy and security of the reporter of any incident.

Enforcement Guidelines

Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct:

1. Correction

Community Impact: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community.

Consequence: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested.

2. Warning

Community Impact: A violation through a single incident or series of actions.

Consequence: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban.

3. Temporary Ban

Community Impact: A serious violation of community standards, including sustained inappropriate behavior.

Consequence: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban.

4. Permanent Ban

Community Impact: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals.

Consequence: A permanent ban from any sort of public interaction within the community.

Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0, available at https://www.contributor-covenant.org/version/2/0/codeofconduct.html.

Community Impact Guidelines were inspired by Mozilla's code of conduct enforcement ladder.

[homepage]: https://www.contributor-covenant.org

For answers to common questions about this code of conduct, see the FAQ at https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations.

diff --git a/previews/PR1681/contributing/index.html b/previews/PR1681/contributing/index.html index ab2c8b733c0..7488379b2db 100644 --- a/previews/PR1681/contributing/index.html +++ b/previews/PR1681/contributing/index.html @@ -35,4 +35,4 @@ are public and that a record of the contribution (including all personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with - this project or the open source license(s) involved. + this project or the open source license(s) involved. diff --git a/previews/PR1681/conventions/index.html b/previews/PR1681/conventions/index.html index eb4a0909bb4..5353b4f8458 100644 --- a/previews/PR1681/conventions/index.html +++ b/previews/PR1681/conventions/index.html @@ -1,2 +1,2 @@ -Conventions · Trixi.jl

Conventions

Spatial dimensions and directions

We use the following numbering schemes on Cartesian or curved structured meshes.

  • The orientations are numbered as 1 => x, 2 => y, 3 => z. For example, numerical fluxes such as flux_central(u_ll, u_rr, orientation, equations::AbstractEquations) use the orientation in this way.
  • The directions are numbered as 1 => -x, 2 => +x, 3 => -y, 4 => +y, 5 => -z, 6 => +z. For example, the boundary_conditions are ordered in this way when a Tuple of boundary conditions per direction is passed to the constructor of a SemidiscretizationHyperbolic.
  • For structured and unstructured curved meshes the concept of direction is generalized via the variable normal_direction. This variable points in the normal direction at a given, curved surface. For the computation of boundary fluxes the normal_direction is normalized to be a normal_vector used, for example, in FluxRotated.

Cells vs. elements vs. nodes

To uniquely distinguish between different components of the discretization, we use the following naming conventions:

  • The computational domain is discretized by a mesh, which is made up of individual cells. In general, neither the mesh nor the cells should be aware of any solver-specific knowledge, i.e., they should not store anything that goes beyond the geometrical information and the connectivity.
  • The numerical solvers do not directly store their information inside the mesh, but use own data structures. Specifically, for each cell on which a solver wants to operate, the solver creates an element to store solver-specific data.
  • For discretization schemes such as the discontinuous Galerkin or the finite element method, inside each element multiple nodes may be defined, which hold nodal information. The nodes are again a solver-specific component, just like the elements.
  • We often identify elements, nodes, etc. with their (local or global) integer index. Convenience iterators such as eachelement, eachnode use these indices.

Keywords in elixirs

Trixi.jl is distributed with several examples in the form of elixirs, small Julia scripts containing everything to set up and run a simulation. Working interactively from the Julia REPL with these scripts can be quite convenient while for exploratory research and development of Trixi.jl. For example, you can use the convenience function trixi_include to include an elixir with some modified arguments. To enable this, it is helpful to use a consistent naming scheme in elixirs, since trixi_include can only perform simple replacements. Some standard variables names are

  • polydeg for the polynomial degree of a solver
  • surface_flux for the numerical flux at surfaces
  • volume_flux for the numerical flux used in flux differencing volume terms

Moreover, convergence_test requires that the spatial resolution is set via the keywords

Variable names

  • Use descriptive names (using snake_case for variables/functions and CamelCase for types)
  • Use a suffix _ as in name_ for local variables that would otherwise hide existing symbols.
  • Use a prefix _ as in _name to indicate internal methods/data that are "fragile" in the sense that there's no guarantee that they might get changed without notice. These are also not documented with a docstring (but maybe with comments using #).

Array types and wrapping

To allow adaptive mesh refinement efficiently when using time integrators from OrdinaryDiffEq, Trixi.jl allows to represent numerical solutions in two different ways. Some discussion can be found online and in form of comments describing Trixi.wrap_array and Trixi.wrap_array_native in the source code of Trixi.jl. The flexibility introduced by this possible wrapping enables additional performance optimizations. However, it comes at the cost of some additional abstractions (and needs to be used with caution, as described in the source code of Trixi.jl). Thus, we use the following conventions to distinguish between arrays visible to the time integrator and wrapped arrays mainly used internally.

  • Arrays visible to the time integrator have a suffix _ode, e.g., du_ode, u_ode.
  • Wrapped arrays do not have a suffix, e.g., du, u.

Methods either accept arrays visible to the time integrator or wrapped arrays based on the following rules.

  • When some solution is passed together with a semidiscretization semi, the solution must be a u_ode that needs to be wrapped via wrap_array(u_ode, semi) (or wrap_array_native(u_ode, semi)) for further processing.
  • When some solution is passed together with the mesh, equations, solver, cache, ..., it is already wrapped via wrap_array (or wrap_array_native).
  • Exceptions of this rule are possible, e.g. for AMR, but must be documented in the code.
  • wrap_array should be used as default option. wrap_array_native should only be used when necessary, e.g., to avoid additional overhead when interfacing with external C libraries such as HDF5, MPI, or visualization.
+Conventions · Trixi.jl

Conventions

Spatial dimensions and directions

We use the following numbering schemes on Cartesian or curved structured meshes.

  • The orientations are numbered as 1 => x, 2 => y, 3 => z. For example, numerical fluxes such as flux_central(u_ll, u_rr, orientation, equations::AbstractEquations) use the orientation in this way.
  • The directions are numbered as 1 => -x, 2 => +x, 3 => -y, 4 => +y, 5 => -z, 6 => +z. For example, the boundary_conditions are ordered in this way when a Tuple of boundary conditions per direction is passed to the constructor of a SemidiscretizationHyperbolic.
  • For structured and unstructured curved meshes the concept of direction is generalized via the variable normal_direction. This variable points in the normal direction at a given, curved surface. For the computation of boundary fluxes the normal_direction is normalized to be a normal_vector used, for example, in FluxRotated.

Cells vs. elements vs. nodes

To uniquely distinguish between different components of the discretization, we use the following naming conventions:

  • The computational domain is discretized by a mesh, which is made up of individual cells. In general, neither the mesh nor the cells should be aware of any solver-specific knowledge, i.e., they should not store anything that goes beyond the geometrical information and the connectivity.
  • The numerical solvers do not directly store their information inside the mesh, but use own data structures. Specifically, for each cell on which a solver wants to operate, the solver creates an element to store solver-specific data.
  • For discretization schemes such as the discontinuous Galerkin or the finite element method, inside each element multiple nodes may be defined, which hold nodal information. The nodes are again a solver-specific component, just like the elements.
  • We often identify elements, nodes, etc. with their (local or global) integer index. Convenience iterators such as eachelement, eachnode use these indices.

Keywords in elixirs

Trixi.jl is distributed with several examples in the form of elixirs, small Julia scripts containing everything to set up and run a simulation. Working interactively from the Julia REPL with these scripts can be quite convenient while for exploratory research and development of Trixi.jl. For example, you can use the convenience function trixi_include to include an elixir with some modified arguments. To enable this, it is helpful to use a consistent naming scheme in elixirs, since trixi_include can only perform simple replacements. Some standard variables names are

  • polydeg for the polynomial degree of a solver
  • surface_flux for the numerical flux at surfaces
  • volume_flux for the numerical flux used in flux differencing volume terms

Moreover, convergence_test requires that the spatial resolution is set via the keywords

Variable names

  • Use descriptive names (using snake_case for variables/functions and CamelCase for types)
  • Use a suffix _ as in name_ for local variables that would otherwise hide existing symbols.
  • Use a prefix _ as in _name to indicate internal methods/data that are "fragile" in the sense that there's no guarantee that they might get changed without notice. These are also not documented with a docstring (but maybe with comments using #).

Array types and wrapping

To allow adaptive mesh refinement efficiently when using time integrators from OrdinaryDiffEq, Trixi.jl allows to represent numerical solutions in two different ways. Some discussion can be found online and in form of comments describing Trixi.wrap_array and Trixi.wrap_array_native in the source code of Trixi.jl. The flexibility introduced by this possible wrapping enables additional performance optimizations. However, it comes at the cost of some additional abstractions (and needs to be used with caution, as described in the source code of Trixi.jl). Thus, we use the following conventions to distinguish between arrays visible to the time integrator and wrapped arrays mainly used internally.

  • Arrays visible to the time integrator have a suffix _ode, e.g., du_ode, u_ode.
  • Wrapped arrays do not have a suffix, e.g., du, u.

Methods either accept arrays visible to the time integrator or wrapped arrays based on the following rules.

  • When some solution is passed together with a semidiscretization semi, the solution must be a u_ode that needs to be wrapped via wrap_array(u_ode, semi) (or wrap_array_native(u_ode, semi)) for further processing.
  • When some solution is passed together with the mesh, equations, solver, cache, ..., it is already wrapped via wrap_array (or wrap_array_native).
  • Exceptions of this rule are possible, e.g. for AMR, but must be documented in the code.
  • wrap_array should be used as default option. wrap_array_native should only be used when necessary, e.g., to avoid additional overhead when interfacing with external C libraries such as HDF5, MPI, or visualization.
diff --git a/previews/PR1681/development/index.html b/previews/PR1681/development/index.html index 65f44d8a36f..5dea0a1cd9d 100644 --- a/previews/PR1681/development/index.html +++ b/previews/PR1681/development/index.html @@ -39,4 +39,4 @@ Trixi.IdealGlmMhdEquations2D Trixi.IdealGlmMhdMulticomponentEquations1D [...]

Text editors

When writing code, the choice of text editor can have a significant impact on productivity and developer satisfaction. While using the default text editor of the operating system has its own benefits (specifically the lack of an explicit installation procure), usually it makes sense to switch to a more programming-friendly tool. In the following, a few of the many options are listed and discussed:

VS Code

Visual Studio Code is a modern open source editor with good support for Julia. While Juno had some better support in the past, the developers of Juno and the Julia VS Code plugin are joining forces and concentrating on VS Code since support of Atom has been suspended. Basically, all comments on Juno below also apply to VS Code.

Juno

If you are new to programming or do not have a preference for a text editor yet, Juno is a good choice for developing Julia code. It is based on Atom, a sophisticated and widely used editor for software developers, and is enhanced with several Julia-specific features. Furthermore and especially helpful for novice programmers, it has a MATLAB-like appearance with easy and interactive access to the current variables, the help system, and a debugger.

Vim or Emacs

Vim and Emacs are both very popular editors that work great with Julia. One of their advantages is that they are text editors without a GUI and as such are available for almost any operating system. They also are preinstalled on virtually all Unix-like systems. However, Vim and Emacs come with their own, steep learning curve if they have never been used before. Therefore, if in doubt, it is probably easier to get started with a classic GUI-based text editor (like Juno). If you decide to use Vim or Emacs, make sure that you install the corresponding Vim plugin julia-vim or Emacs major mode julia-emacs.

Debugging

Julia offers several options for debugging. A classical debugger is available with the Debugger.jl package or in the Julia extension for VS Code. However, it can be quite slow and, at the time of writing (January 2023), currently does not work properly with Trixi.jl. The Infiltrator.jl package on the other hand does not offer all features of a full debugger, but is a fast and simple tool that allows users to set breakpoints to open a local REPL session and access the call stack and variables.

Infiltrator

The Infiltrator package provides fast, interactive breakpoints using the @infiltrate command, which drops the user into a local REPL session. From there, it is possible to access local variables, see the call stack, and execute statements.

The package can be installed in the Julia REPL by executing

(@v1.9) pkg> add Infiltrator

To load the package in the Julia REPL execute

julia> using Infiltrator

Breakpoints can be set by adding a line with the @infiltrate macro at the respective position in the code. Use Revise if you want to set and delete breakpoints in your package without having to restart Julia.

Use `@autoinfiltrate` when debugging Trixi.jl

When running Julia inside a package environment, e.g., inside the source code of Trixi.jl itself, the @infiltrate macro only works if Infiltrator has been added to the package dependencies. To avoid this, you can use the (non-exported) @autoinfiltrate macro in Trixi.jl, which only requires Infiltrator.jl to be available in the current environment stack and will auto-load it for you.

Triggering the breakpoint starts a REPL session where it is possible to interact with the current local scope. Possible commands are:

To finish a debugging session, either use @continue to continue and eventually stop at the next breakpoint or @exit to skip further breakpoints. After the code has finished, local variables saved with @exfiltrate can be accessed in the REPL using the safehouse variable.

Limitations of using Infiltrator.jl are that local variables cannot be changed, and that it is not possible to step into further calls or access other function scopes.

Releasing a new version of Trixi.jl, Trixi2Vtk

Preview of the documentation

You can build the documentation of Trixi.jl locally by running

julia --project=docs -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()'
-julia --project=docs --color=yes docs/make.jl

from the Trixi.jl main directory. Then, you can look at the html files generated in docs/build. For PRs triggered from branches inside the Trixi.jl main repository previews of the new documentation are generated at https://trixi-framework.github.io/Trixi.jl/previews/PRXXX, where XXX is the number of the PR. This does not work for PRs from forks for security reasons (since anyone could otherwise push arbitrary stuff to the Trixi.jl website, including malicious code).

Developing Trixi2Vtk

Trixi2Vtk has Trixi.jl as dependency and uses Trixi.jl's implementation to, e.g., load mesh files. When developing Trixi2Vtk, one may want to change functions in Trixi.jl to allow them to be reused in Trixi2Vtk. To use a locally modified Trixi.jl clone instead of a Trixi.jl release, one can tell Pkg to use the local source code of Trixi.jl instead of a registered version by running

(@v1.9) pkg> develop path/to/Trixi.jl
+julia --project=docs --color=yes docs/make.jl

from the Trixi.jl main directory. Then, you can look at the html files generated in docs/build. For PRs triggered from branches inside the Trixi.jl main repository previews of the new documentation are generated at https://trixi-framework.github.io/Trixi.jl/previews/PRXXX, where XXX is the number of the PR. This does not work for PRs from forks for security reasons (since anyone could otherwise push arbitrary stuff to the Trixi.jl website, including malicious code).

Developing Trixi2Vtk

Trixi2Vtk has Trixi.jl as dependency and uses Trixi.jl's implementation to, e.g., load mesh files. When developing Trixi2Vtk, one may want to change functions in Trixi.jl to allow them to be reused in Trixi2Vtk. To use a locally modified Trixi.jl clone instead of a Trixi.jl release, one can tell Pkg to use the local source code of Trixi.jl instead of a registered version by running

(@v1.9) pkg> develop path/to/Trixi.jl
diff --git a/previews/PR1681/github-git/index.html b/previews/PR1681/github-git/index.html index b1c66f0bf9e..e25c984f317 100644 --- a/previews/PR1681/github-git/index.html +++ b/previews/PR1681/github-git/index.html @@ -41,4 +41,4 @@ git rebase # Clean reflog and force garbage collection -git reflog expire --expire=now --all && git gc --prune=now --aggressive

IMPORTANT: You need to do a git rebase instead of a git pull when updating the fixed branch.

+git reflog expire --expire=now --all && git gc --prune=now --aggressive

IMPORTANT: You need to do a git rebase instead of a git pull when updating the fixed branch.

diff --git a/previews/PR1681/index.html b/previews/PR1681/index.html index bcbc6c1a008..c3ab5bf3118 100644 --- a/previews/PR1681/index.html +++ b/previews/PR1681/index.html @@ -111,4 +111,4 @@ NumFOCUS --> -

This project has benefited from funding by the Deutsche Forschungsgemeinschaft (DFG, German Research Foundation) through the following grants:

This project has benefited from funding from the European Research Council through the ERC Starting Grant "An Exascale aware and Un-crashable Space-Time-Adaptive Discontinuous Spectral Element Solver for Non-Linear Conservation Laws" (Extreme), ERC grant agreement no. 714487.

This project has benefited from funding from Vetenskapsrådet (VR, Swedish Research Council), Sweden through the VR Starting Grant "Shallow water flows including sediment transport and morphodynamics", VR grant agreement 2020-03642 VR.

This project has benefited from funding from the United States National Science Foundation (NSF) under awards DMS-1719818 and DMS-1943186.

This project has benefited from funding from the German Federal Ministry of Education and Research (BMBF) through the project grant "Adaptive earth system modeling with significantly reduced computation time for exascale supercomputers (ADAPTEX)" (funding id: 16ME0668K).

This project has benefited from funding by the Daimler und Benz Stiftung (Daimler and Benz Foundation) through grant no. 32-10/22.

Trixi.jl is supported by NumFOCUS as an Affiliated Project.

+

This project has benefited from funding by the Deutsche Forschungsgemeinschaft (DFG, German Research Foundation) through the following grants:

This project has benefited from funding from the European Research Council through the ERC Starting Grant "An Exascale aware and Un-crashable Space-Time-Adaptive Discontinuous Spectral Element Solver for Non-Linear Conservation Laws" (Extreme), ERC grant agreement no. 714487.

This project has benefited from funding from Vetenskapsrådet (VR, Swedish Research Council), Sweden through the VR Starting Grant "Shallow water flows including sediment transport and morphodynamics", VR grant agreement 2020-03642 VR.

This project has benefited from funding from the United States National Science Foundation (NSF) under awards DMS-1719818 and DMS-1943186.

This project has benefited from funding from the German Federal Ministry of Education and Research (BMBF) through the project grant "Adaptive earth system modeling with significantly reduced computation time for exascale supercomputers (ADAPTEX)" (funding id: 16ME0668K).

This project has benefited from funding by the Daimler und Benz Stiftung (Daimler and Benz Foundation) through grant no. 32-10/22.

Trixi.jl is supported by NumFOCUS as an Affiliated Project.

diff --git a/previews/PR1681/license/index.html b/previews/PR1681/license/index.html index 39bf8340c2e..e0ccc8b0380 100644 --- a/previews/PR1681/license/index.html +++ b/previews/PR1681/license/index.html @@ -1,2 +1,2 @@ -License · Trixi.jl

License

MIT License

Copyright (c) 2020-present The Trixi.jl Authors (see Authors)

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+License · Trixi.jl

License

MIT License

Copyright (c) 2020-present The Trixi.jl Authors (see Authors)

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

diff --git a/previews/PR1681/meshes/dgmulti_mesh/index.html b/previews/PR1681/meshes/dgmulti_mesh/index.html index b50894badd6..2e5ebbdf88d 100644 --- a/previews/PR1681/meshes/dgmulti_mesh/index.html +++ b/previews/PR1681/meshes/dgmulti_mesh/index.html @@ -5,4 +5,4 @@ surface_flux=flux_central, surface_integral=SurfaceIntegralWeakForm(surface_flux), volume_integral=VolumeIntegralWeakForm(), - RefElemData_kwargs...)

Here, element_type can be Tri(), Quad(), Tet(), or Hex(), and approximation_type can be

Additional options can also be specified through RefElemData_kwargs:

The GaussSBP() approximation type on Quad() and Hex() meshes

When using VolumeIntegralFluxDifferencing on Quad() and Hex() meshes, one can also specify approximation_type = GaussSBP() to use an entropy stable Gauss collocation scheme. Here, GaussSBP() refers to "generalized" summation-by-parts operators (see for example Ranocha 2018 or Fernandez and Zingg 2015).

Unlike traditional SBP operators, generalized SBP operators are constructed from nodes which do not include boundary nodes (i.e., Gauss quadrature nodes as opposed to Gauss-Lobatto quadrature nodes). This makes the computation of interface fluxes slightly more expensive, but also usually results in a more accurate solution. Roughly speaking, an entropy stable Gauss collocation scheme will yield results similar to a modal entropy stable scheme using a Polynomial() approximation type, but will be more efficient at high orders of approximation.

Trixi.jl elixirs on simplicial and tensor product element meshes

Example elixirs with triangular, quadrilateral, and tetrahedral meshes can be found in the examples/dgmulti_2d/ and examples/dgmulti_3d/ folders. Some key elixirs to look at:

For developers

DGMultiMesh wrapper type

DGMulti meshes in Trixi.jl are represented using a DGMultiMesh{NDIMS, ...} type. This mesh type is assumed to have fields md::MeshData, which contains geometric terms derived from the mapping between the reference and physical elements, and boundary_faces, which contains a Dict of boundary segment names (symbols) and list of faces which lie on that boundary segment.

A DGMultiMesh can be constructed in several ways. For example, DGMultiMesh(dg::DGMulti) will return a Cartesian mesh on $[-1, 1]^d$ with element types specified by dg. DGMulti meshes can also be constructed by specifying a list of vertex coordinates vertex_coordinates_x, vertex_coordinates_y, vertex_coordinates_z and a connectivity matrix EToV where EToV[e,:] gives the vertices which correspond to element e. These quantities are available from most unstructured mesh generators.

Initial support for curved DGMultiMeshes is available for flux differencing solvers using SBP and GaussSBP approximation types on quadrilateral and hexahedral meshes. These can be called by specifying mesh = DGMultiMesh(dg, cells_per_dimension, mapping), where mapping is a function which specifies the warping of the mesh (e.g., mapping(xi, eta) = SVector{2}(xi, eta) is the identity mapping) similar to the mapping argument used by StructuredMesh.

Variable naming conventions

We use the convention that coordinates on the reference element are $r$ in 1D, $r, s$ in 2D, or $r, s, t$ in 3D. Physical coordinates use the standard conventions $x$ (1D), $x, y$ (2D), and $x, y, z$ (3D).

"Ref-to-physical mapping"

Derivatives of reference coordinates with respect to physical coordinates are abbreviated, e.g., $\frac{\partial r}{\partial x} = r_x$. Additionally, $J$ is used to denote the determinant of the Jacobian of the reference-to-physical mapping.

Variable meanings and conventions in StartUpDG.jl

StartUpDG.jl exports structs RefElemData{NDIMS, ElemShape, ...} (which contains data associated with the reference element, such as interpolation points, quadrature rules, face nodes, normals, and differentiation/interpolation/projection matrices) and MeshData{NDIMS} (which contains geometric data associated with a mesh). These are currently used for evaluating DG formulations in a matrix-free fashion. These structs contain fields similar (but not identical) to those in Globals1D, Globals2D, Globals3D in the Matlab codes from "Nodal Discontinuous Galerkin Methods" by Hesthaven and Warburton (2007).

In general, we use the following code conventions:

Quantities in rd::RefElemData:

Quantities in md::MeshData:

For more details, please see the StartUpDG.jl docs.

+ RefElemData_kwargs...)

Here, element_type can be Tri(), Quad(), Tet(), or Hex(), and approximation_type can be

Additional options can also be specified through RefElemData_kwargs:

The GaussSBP() approximation type on Quad() and Hex() meshes

When using VolumeIntegralFluxDifferencing on Quad() and Hex() meshes, one can also specify approximation_type = GaussSBP() to use an entropy stable Gauss collocation scheme. Here, GaussSBP() refers to "generalized" summation-by-parts operators (see for example Ranocha 2018 or Fernandez and Zingg 2015).

Unlike traditional SBP operators, generalized SBP operators are constructed from nodes which do not include boundary nodes (i.e., Gauss quadrature nodes as opposed to Gauss-Lobatto quadrature nodes). This makes the computation of interface fluxes slightly more expensive, but also usually results in a more accurate solution. Roughly speaking, an entropy stable Gauss collocation scheme will yield results similar to a modal entropy stable scheme using a Polynomial() approximation type, but will be more efficient at high orders of approximation.

Trixi.jl elixirs on simplicial and tensor product element meshes

Example elixirs with triangular, quadrilateral, and tetrahedral meshes can be found in the examples/dgmulti_2d/ and examples/dgmulti_3d/ folders. Some key elixirs to look at:

For developers

DGMultiMesh wrapper type

DGMulti meshes in Trixi.jl are represented using a DGMultiMesh{NDIMS, ...} type. This mesh type is assumed to have fields md::MeshData, which contains geometric terms derived from the mapping between the reference and physical elements, and boundary_faces, which contains a Dict of boundary segment names (symbols) and list of faces which lie on that boundary segment.

A DGMultiMesh can be constructed in several ways. For example, DGMultiMesh(dg::DGMulti) will return a Cartesian mesh on $[-1, 1]^d$ with element types specified by dg. DGMulti meshes can also be constructed by specifying a list of vertex coordinates vertex_coordinates_x, vertex_coordinates_y, vertex_coordinates_z and a connectivity matrix EToV where EToV[e,:] gives the vertices which correspond to element e. These quantities are available from most unstructured mesh generators.

Initial support for curved DGMultiMeshes is available for flux differencing solvers using SBP and GaussSBP approximation types on quadrilateral and hexahedral meshes. These can be called by specifying mesh = DGMultiMesh(dg, cells_per_dimension, mapping), where mapping is a function which specifies the warping of the mesh (e.g., mapping(xi, eta) = SVector{2}(xi, eta) is the identity mapping) similar to the mapping argument used by StructuredMesh.

Variable naming conventions

We use the convention that coordinates on the reference element are $r$ in 1D, $r, s$ in 2D, or $r, s, t$ in 3D. Physical coordinates use the standard conventions $x$ (1D), $x, y$ (2D), and $x, y, z$ (3D).

"Ref-to-physical mapping"

Derivatives of reference coordinates with respect to physical coordinates are abbreviated, e.g., $\frac{\partial r}{\partial x} = r_x$. Additionally, $J$ is used to denote the determinant of the Jacobian of the reference-to-physical mapping.

Variable meanings and conventions in StartUpDG.jl

StartUpDG.jl exports structs RefElemData{NDIMS, ElemShape, ...} (which contains data associated with the reference element, such as interpolation points, quadrature rules, face nodes, normals, and differentiation/interpolation/projection matrices) and MeshData{NDIMS} (which contains geometric data associated with a mesh). These are currently used for evaluating DG formulations in a matrix-free fashion. These structs contain fields similar (but not identical) to those in Globals1D, Globals2D, Globals3D in the Matlab codes from "Nodal Discontinuous Galerkin Methods" by Hesthaven and Warburton (2007).

In general, we use the following code conventions:

Quantities in rd::RefElemData:

Quantities in md::MeshData:

For more details, please see the StartUpDG.jl docs.

diff --git a/previews/PR1681/meshes/p4est_mesh/index.html b/previews/PR1681/meshes/p4est_mesh/index.html index 6ae9b8fb440..26feb3b1c32 100644 --- a/previews/PR1681/meshes/p4est_mesh/index.html +++ b/previews/PR1681/meshes/p4est_mesh/index.html @@ -133,4 +133,4 @@ & \qquad\; + (1-\xi)(1+\zeta)\texttt{edge}_{12}\quad]. \end{aligned}\]

However, subtracting the edge correction terms $\mathcal{C}_{\texttt{edge}}(\boldsymbol{\xi})$ from $\boldsymbol\Sigma(\boldsymbol{\xi})$ removes the interior element contributions twice. Thus, to complete the construction of the transfinite mapping $\mathbf{X}(\boldsymbol{\xi})$ we add the transfinite map of the straight sided hexahedral element to find

\[\mathbf{X}(\boldsymbol{\xi}) = \boldsymbol\Sigma(\boldsymbol{\xi}) - \mathcal{C}_{\texttt{edge}}(\boldsymbol{\xi}) - + \mathbf{X}_{linear}(\boldsymbol{\xi}).\]

+ + \mathbf{X}_{linear}(\boldsymbol{\xi}).\]

diff --git a/previews/PR1681/meshes/structured_mesh/index.html b/previews/PR1681/meshes/structured_mesh/index.html index fb07356227f..946d62f711b 100644 --- a/previews/PR1681/meshes/structured_mesh/index.html +++ b/previews/PR1681/meshes/structured_mesh/index.html @@ -1,2 +1,2 @@ -Structured mesh · Trixi.jl

Structured mesh

The StructuredMesh is a structured, curvilinear, conforming mesh type available for one-, two-, and three-dimensional simulations.

Due to its curvilinear nature, (numerical) fluxes need to implement methods dispatching on the normal::AbstractVector. Rotationally invariant equations such as the compressible Euler equations can use FluxRotated to wrap numerical fluxes implemented only for Cartesian meshes. This simplifies the re-use of existing functionality for the TreeMesh but is usually less efficient, cf. PR #550.

+Structured mesh · Trixi.jl

Structured mesh

The StructuredMesh is a structured, curvilinear, conforming mesh type available for one-, two-, and three-dimensional simulations.

Due to its curvilinear nature, (numerical) fluxes need to implement methods dispatching on the normal::AbstractVector. Rotationally invariant equations such as the compressible Euler equations can use FluxRotated to wrap numerical fluxes implemented only for Cartesian meshes. This simplifies the re-use of existing functionality for the TreeMesh but is usually less efficient, cf. PR #550.

diff --git a/previews/PR1681/meshes/tree_mesh/index.html b/previews/PR1681/meshes/tree_mesh/index.html index ec837a24364..72a0e4c08d4 100644 --- a/previews/PR1681/meshes/tree_mesh/index.html +++ b/previews/PR1681/meshes/tree_mesh/index.html @@ -1,2 +1,2 @@ -Tree mesh · Trixi.jl

Tree mesh

The TreeMesh is a Cartesian, $h$-non-conforming mesh type used in many parts of Trixi.jl. Often, the support for this mesh type is developed best since it was the first mesh type in Trixi.jl, and it is available in one, two, and three space dimensions.

It is limited to hypercube domains but supports AMR via the AMRCallback. Due to its Cartesian nature, (numerical) fluxes need to implement methods dispatching on the orientation::Integer as described in the conventions.

+Tree mesh · Trixi.jl

Tree mesh

The TreeMesh is a Cartesian, $h$-non-conforming mesh type used in many parts of Trixi.jl. Often, the support for this mesh type is developed best since it was the first mesh type in Trixi.jl, and it is available in one, two, and three space dimensions.

It is limited to hypercube domains but supports AMR via the AMRCallback. Due to its Cartesian nature, (numerical) fluxes need to implement methods dispatching on the orientation::Integer as described in the conventions.

diff --git a/previews/PR1681/meshes/unstructured_quad_mesh/index.html b/previews/PR1681/meshes/unstructured_quad_mesh/index.html index 7c5f083e565..5e461718ddd 100644 --- a/previews/PR1681/meshes/unstructured_quad_mesh/index.html +++ b/previews/PR1681/meshes/unstructured_quad_mesh/index.html @@ -76,4 +76,4 @@ * Upload to YouTube * Obtain responsive code by inserting link on https://embedresponsively.com --> -
+
diff --git a/previews/PR1681/overview/index.html b/previews/PR1681/overview/index.html index 5c654b31f71..6c38243b130 100644 --- a/previews/PR1681/overview/index.html +++ b/previews/PR1681/overview/index.html @@ -1,2 +1,2 @@ -Overview · Trixi.jl

Overview of the structure of Trixi.jl

Trixi.jl is designed as a library of components for discretizations of hyperbolic conservation laws. Thus, it is not a monolithic PDE solver that is configured at runtime via parameter files, as it is often found in classical numerical simulation codes. Instead, each simulation is configured by pure Julia code. Many examples of such simulation setups, called elixirs in Trixi.jl, are provided in the examples/ folder.

Trixi.jl uses the method of lines, i.e., the full space-time discretization is separated into two steps; the spatial semidiscretization is performed at first and the resulting ODE system is solved numerically using a suitable time integration method. Thus, the main ingredients of an elixir designed to solve a PDE numerically are the spatial semidiscretization and the time integration scheme.

Semidiscretizations

Semidiscretizations are high-level descriptions of spatial discretizations specialized for certain PDEs. Trixi.jl's main focus is on hyperbolic conservation laws represented in a SemidiscretizationHyperbolic. Such semidiscretizations are usually named semi in Trixi.jl

semidiscretization_overview

The basic building blocks of a semidiscretization are

  • a mesh describing the geometry of the domain
  • a set of equations describing the physical model
  • a solver describing the numerical approach

In addition, a semidiscretization bundles initial and boundary conditions, and possible source terms. These different ingredients of a semidiscretization can be configured individually and combined together. When a semidiscretization is constructed, it will create an internal cache, i.e., a collection of setup-specific data structures, that is usually passed to all lower level functions.

Due to Trixi.jl's modular nature using Julia's multiple dispatch features, new ingredients can be created specifically for a certain combination of other ingredients. For example, a new mesh type can be created and implemented at first only for a specific solver. Thus, there is no need to consider all possible combinations of meshes, equations, and solvers when implementing new features. This allows rapid prototyping of new ideas and is one of the main design goals behind Trixi.jl. Below is a brief overview of the availability of different features on different mesh types.

FeatureTreeMeshStructuredMeshUnstructuredMesh2DP4estMeshDGMultiMeshFurther reading
Spatial dimension1D, 2D, 3D1D, 2D, 3D2D2D, 3D1D, 2D, 3D
CoordinatesCartesiancurvilinearcurvilinearcurvilinearcurvilinear
Connectivityh-nonconformingconformingconformingh-nonconformingconforming
Element typeline, square, cubeline, quadᵃ, hexᵃquadᵃquadᵃ, hexᵃsimplex, quadᵃ, hexᵃ
Adaptive mesh refinementAMRCallback
Solver typeDGSEMDGSEMDGSEMDGSEMDGMulti
Domainhypercubemapped hypercubearbitraryarbitraryarbitrary
Weak formVolumeIntegralWeakForm
Flux differencingVolumeIntegralFluxDifferencing
Shock capturingVolumeIntegralShockCapturingHG
Nonconservative equationse.g., GLM MHD or shallow water equations
Parabolic termsᵇe.g., CompressibleNavierStokesDiffusion2D

ᵃ: quad = quadrilateral, hex = hexahedron ᵇ: Parabolic terms do not currently support adaptivity.

Time integration methods

Trixi.jl is compatible with the SciML ecosystem for ordinary differential equations. In particular, a spatial semidiscretization can be wrapped in an ODE problem using semidiscretize, which returns an ODEProblem. This ODEProblem is a wrapper of Trixi.rhs!(du_ode, u_ode, semi, t), which gets called in ODE solvers. Further information can be found in the section on time integration methods.

Next steps

We explicitly encourage people interested in Trixi.jl to have a look at the examples/ bundled with Trixi.jl to get an impression of what is possible and the general look and feel of Trixi.jl. Before doing that, it is usually good to get an idea of how to visualize numerical results.

If you like learning by doing, looking at the tutorials and trying to mix your own elixirs based thereon is probably a good next step. Otherwise, you can further dig into the documentation by looking at Trixi.jl's basic building blocks.

+Overview · Trixi.jl

Overview of the structure of Trixi.jl

Trixi.jl is designed as a library of components for discretizations of hyperbolic conservation laws. Thus, it is not a monolithic PDE solver that is configured at runtime via parameter files, as it is often found in classical numerical simulation codes. Instead, each simulation is configured by pure Julia code. Many examples of such simulation setups, called elixirs in Trixi.jl, are provided in the examples/ folder.

Trixi.jl uses the method of lines, i.e., the full space-time discretization is separated into two steps; the spatial semidiscretization is performed at first and the resulting ODE system is solved numerically using a suitable time integration method. Thus, the main ingredients of an elixir designed to solve a PDE numerically are the spatial semidiscretization and the time integration scheme.

Semidiscretizations

Semidiscretizations are high-level descriptions of spatial discretizations specialized for certain PDEs. Trixi.jl's main focus is on hyperbolic conservation laws represented in a SemidiscretizationHyperbolic. Such semidiscretizations are usually named semi in Trixi.jl

semidiscretization_overview

The basic building blocks of a semidiscretization are

  • a mesh describing the geometry of the domain
  • a set of equations describing the physical model
  • a solver describing the numerical approach

In addition, a semidiscretization bundles initial and boundary conditions, and possible source terms. These different ingredients of a semidiscretization can be configured individually and combined together. When a semidiscretization is constructed, it will create an internal cache, i.e., a collection of setup-specific data structures, that is usually passed to all lower level functions.

Due to Trixi.jl's modular nature using Julia's multiple dispatch features, new ingredients can be created specifically for a certain combination of other ingredients. For example, a new mesh type can be created and implemented at first only for a specific solver. Thus, there is no need to consider all possible combinations of meshes, equations, and solvers when implementing new features. This allows rapid prototyping of new ideas and is one of the main design goals behind Trixi.jl. Below is a brief overview of the availability of different features on different mesh types.

FeatureTreeMeshStructuredMeshUnstructuredMesh2DP4estMeshDGMultiMeshFurther reading
Spatial dimension1D, 2D, 3D1D, 2D, 3D2D2D, 3D1D, 2D, 3D
CoordinatesCartesiancurvilinearcurvilinearcurvilinearcurvilinear
Connectivityh-nonconformingconformingconformingh-nonconformingconforming
Element typeline, square, cubeline, quadᵃ, hexᵃquadᵃquadᵃ, hexᵃsimplex, quadᵃ, hexᵃ
Adaptive mesh refinementAMRCallback
Solver typeDGSEMDGSEMDGSEMDGSEMDGMulti
Domainhypercubemapped hypercubearbitraryarbitraryarbitrary
Weak formVolumeIntegralWeakForm
Flux differencingVolumeIntegralFluxDifferencing
Shock capturingVolumeIntegralShockCapturingHG
Nonconservative equationse.g., GLM MHD or shallow water equations
Parabolic termsᵇe.g., CompressibleNavierStokesDiffusion2D

ᵃ: quad = quadrilateral, hex = hexahedron ᵇ: Parabolic terms do not currently support adaptivity.

Time integration methods

Trixi.jl is compatible with the SciML ecosystem for ordinary differential equations. In particular, a spatial semidiscretization can be wrapped in an ODE problem using semidiscretize, which returns an ODEProblem. This ODEProblem is a wrapper of Trixi.rhs!(du_ode, u_ode, semi, t), which gets called in ODE solvers. Further information can be found in the section on time integration methods.

Next steps

We explicitly encourage people interested in Trixi.jl to have a look at the examples/ bundled with Trixi.jl to get an impression of what is possible and the general look and feel of Trixi.jl. Before doing that, it is usually good to get an idea of how to visualize numerical results.

If you like learning by doing, looking at the tutorials and trying to mix your own elixirs based thereon is probably a good next step. Otherwise, you can further dig into the documentation by looking at Trixi.jl's basic building blocks.

diff --git a/previews/PR1681/parallelization/index.html b/previews/PR1681/parallelization/index.html index 4a55058ec98..eab1a5884c0 100644 --- a/previews/PR1681/parallelization/index.html +++ b/previews/PR1681/parallelization/index.html @@ -33,4 +33,4 @@ UUID("f67ccb44-e63f-5c2f-98bd-6dc0ccc4ba2f"), # UUID of HDF5.jl "libhdf5" => "/path/to/your/libhdf5.so", "libhdf5_hl" => "/path/to/your/libhdf5_hl.so", force = true)

Alternatively, with HDF5.jl v0.17.1 or higher you can use

julia> using HDF5
-julia> HDF5.API.set_libraries!("/path/to/your/libhdf5.so", "/path/to/your/libhdf5_hl.so")

For more information see also the documentation of HDF5.jl. In total, you should have a file called LocalPreferences.toml in the project directory that contains a section [MPIPreferences], a section [HDF5] with entries libhdf5 and libhdf5_hl, a section [P4est] with the entry libp4est as well as a section [T8code] with the entries libt8, libp4est and libsc. If you use HDF5.jl v0.16 or older, instead of setting the preferences for HDF5.jl, you need to set the environment variable JULIA_HDF5_PATH to the path, where the HDF5 binaries are located and then call ]build HDF5 from Julia.

If HDF5 is not MPI-enabled, Trixi.jl will fall back on a less efficient I/O mechanism. In that case, all disk I/O is performed only on rank zero and data is distributed to/gathered from the other ranks using regular MPI communication.

+julia> HDF5.API.set_libraries!("/path/to/your/libhdf5.so", "/path/to/your/libhdf5_hl.so")

For more information see also the documentation of HDF5.jl. In total, you should have a file called LocalPreferences.toml in the project directory that contains a section [MPIPreferences], a section [HDF5] with entries libhdf5 and libhdf5_hl, a section [P4est] with the entry libp4est as well as a section [T8code] with the entries libt8, libp4est and libsc. If you use HDF5.jl v0.16 or older, instead of setting the preferences for HDF5.jl, you need to set the environment variable JULIA_HDF5_PATH to the path, where the HDF5 binaries are located and then call ]build HDF5 from Julia.

If HDF5 is not MPI-enabled, Trixi.jl will fall back on a less efficient I/O mechanism. In that case, all disk I/O is performed only on rank zero and data is distributed to/gathered from the other ranks using regular MPI communication.

diff --git a/previews/PR1681/performance/index.html b/previews/PR1681/performance/index.html index 2810655e154..d48304cd063 100644 --- a/previews/PR1681/performance/index.html +++ b/previews/PR1681/performance/index.html @@ -52,4 +52,4 @@ BenchmarkConfig(juliacmd=`$(Base.julia_cmd()) --check-bounds=no --threads=1`, id="main") # baseline ) -julia> export_markdown(pkgdir(Trixi, "benchmark", "results.md"), results)

By default, the target is the current state of the repository. Remember that you need to be in a clean state (commit or stash your changes) to run this successfully. You can also run this comparison and an additional one using two threads via

julia> include("benchmark/run_benchmarks.jl")

Then, markdown files including the results are saved in benchmark/. This example result was obtained using a GitHub action for the PR #535. Note that GitHub actions run on in the cloud in a virtual machine. Hence, we do not really have control over it and performance results must be taken with a grain of salt. Nevertheless, significant runtime differences and differences of memory allocations should be robust indicators of performance changes.

Runtime performance vs. latency aka using @nospecialize selectively

Usually, Julia will compile specialized versions of each method, using as much information from the types of function arguments as possible (based on some heuristics). The compiler will generate code that is as efficient as comparable code written in a low-level language such as C or Fortran. However, there are cases where the runtime performance does not really matter but the time needed to compile specializations becomes significant. This is related to latency or the time-to-first-plot problem, well-known in the Julia community. In such a case, it can be useful to remove some burden from the compiler by avoiding specialization on every possible argument types using the macro @nospecialize. A prime example of such a case is pretty printing of structs in the Julia REPL, see the associated PR for further discussions.

As a rule of thumb:

Performance metrics of the AnalysisCallback

The AnalysisCallback computes two performance indicators that you can use to evaluate the serial and parallel performance of Trixi.jl. They represent measured run times that are normalized by the number of rhs! evaluations and the number of degrees of freedom of the problem setup. The normalization ensures that we can compare different measurements for each type of indicator independent of the number of time steps or mesh size. All indicators have in common that they are still in units of time, thus lower is better for each of them.

Here, the term "degrees of freedom" (DOFs) refers to the number of independent state vectors that are used to represent the numerical solution. For example, if you use a DGSEM-type scheme in 2D on a mesh with 8 elements and with 5-by-5 Gauss-Lobatto nodes in each element (i.e., a polynomial degree of 4), the total number of DOFs would be

\[n_\text{DOFs,DGSEM} = \{\text{number of elements}\} \cdot \{\text{number of nodes per element}\} = 8 \cdot (5 \cdot 5) = 200.\]

In contrast, for a finite volume-type scheme on a mesh with 8 elements, the total number of DOFs would be (independent of the number of spatial dimensions)

\[n_\text{DOFs,FV} = \{\text{number of elements}\} = 8,\]

since for standard finite volume methods you store a single state vector in each element. Note that we specifically count the number of state vectors and not the number of state variables for the DOFs. That is, in the previous example $n_\text{DOFs,FV}$ is equal to 8 independent of whether this is a compressible Euler setup with 5 state variables or a linear scalar advection setup with one state variable.

For each indicator, the measurements are always since the last invocation of the AnalysisCallback. That is, if the analysis callback is called multiple times, the indicators are repeatedly computed and can thus also be used to track the performance over the course of a longer simulation, e.g., to analyze setups with varying performance characteristics. Note that the time spent in the AnalysisCallback itself is always excluded, i.e., the performance measurements are not distorted by potentially expensive solution analysis computations. All other parts of a Trixi.jl simulation are included, however, thus make sure that you disable everything you do not want to be measured (such as I/O callbacks, visualization etc.).

Performance indicators and adaptive mesh refinement

Currently it is not possible to compute meaningful performance indicators for a simulation with arbitrary adaptive mesh refinement, since this would require to explicitly keep track of the number of DOF updates due to the mesh size changing repeatedly. The only way to do this at the moment is by setting the analysis interval to the same value as the AMR interval.

Local, rhs!-only indicator

The local, rhs!-only indicator is computed as

\[\text{time/DOF/rhs!} = \frac{t_\text{\texttt{rhs!}}}{n_\text{DOFs,local} \cdot n_\text{calls,\texttt{rhs!}}},\]

where $t_\text{\texttt{rhs!}}$ is the accumulated time spent in rhs!, $n_\text{DOFs,local}$ is the local number of DOFs (i.e., on the current MPI rank; if doing a serial run, you can just think of this as the number of DOFs), and $n_\text{calls,\texttt{rhs!}}$ is the number of times the rhs! function has been evaluated. Note that for this indicator, we measure only the time spent in rhs!, i.e., by definition all computations outside of rhs! - specifically all other callbacks and the time integration method - are not taken into account.

The local, rhs!-only indicator is usually most useful if you do serial measurements and are interested in the performance of the implementation of your core numerical methods (e.g., when doing performance tuning).

Performance index (PID)

The performance index (PID) is computed as

\[\text{PID} = \frac{t_\text{wall} \cdot n_\text{ranks,MPI}}{n_\text{DOFs,global} \cdot n_\text{calls,\texttt{rhs!}}},\]

where $t_\text{wall}$ is the walltime since the last call to the AnalysisCallback, $n_\text{ranks,MPI}$ is the number of MPI ranks used, $n_\text{DOFs,global}$ is the global number of DOFs (i.e., the sum of DOFs over all MPI ranks; if doing a serial run, you can just think of this as the number of DOFs), and $n_\text{calls,\texttt{rhs!}}$ is the number of times the rhs! function has been evaluated since the last call to the AnalysisCallback. The PID measures everything except the time spent in the AnalysisCallback itself - specifically, all other callbacks and the time integration method itself are included.

The PID is usually most useful if you would like to compare the parallel performance of your code to its serial performance. Specifically, it allows you to evaluate the parallelization overhead of your code by giving you a measure of the resources that are necessary to solve a given simulation setup. In a sense, it mimics the "core hours" metric that is often used by supercomputer centers to measure how many resources a particular compute job requires. It can thus be seen as a proxy for "energy used" and, as an extension, "monetary cost".

Initialization overhead in measurements

When using one of the integration schemes from OrdinaryDiffEq.jl, their implementation will initialize some OrdinaryDiffEq.jl-specific information during the first time step. Among other things, one additional call to rhs! is performed. Therefore, make sure that for performance measurements using the PID either the number of timesteps or the workload per rhs! call is large enough to make the initialization overhead negligible. Note that the extra call to rhs! is properly accounted for in both the number of calls and the measured time, so you do not need to worry about it being expensive. If you want a perfect timing result, you need to set the analysis interval such that the AnalysisCallback is invoked at least once during the course of the simulation and discard the first PID value.

+julia> export_markdown(pkgdir(Trixi, "benchmark", "results.md"), results)

By default, the target is the current state of the repository. Remember that you need to be in a clean state (commit or stash your changes) to run this successfully. You can also run this comparison and an additional one using two threads via

julia> include("benchmark/run_benchmarks.jl")

Then, markdown files including the results are saved in benchmark/. This example result was obtained using a GitHub action for the PR #535. Note that GitHub actions run on in the cloud in a virtual machine. Hence, we do not really have control over it and performance results must be taken with a grain of salt. Nevertheless, significant runtime differences and differences of memory allocations should be robust indicators of performance changes.

Runtime performance vs. latency aka using @nospecialize selectively

Usually, Julia will compile specialized versions of each method, using as much information from the types of function arguments as possible (based on some heuristics). The compiler will generate code that is as efficient as comparable code written in a low-level language such as C or Fortran. However, there are cases where the runtime performance does not really matter but the time needed to compile specializations becomes significant. This is related to latency or the time-to-first-plot problem, well-known in the Julia community. In such a case, it can be useful to remove some burden from the compiler by avoiding specialization on every possible argument types using the macro @nospecialize. A prime example of such a case is pretty printing of structs in the Julia REPL, see the associated PR for further discussions.

As a rule of thumb:

Performance metrics of the AnalysisCallback

The AnalysisCallback computes two performance indicators that you can use to evaluate the serial and parallel performance of Trixi.jl. They represent measured run times that are normalized by the number of rhs! evaluations and the number of degrees of freedom of the problem setup. The normalization ensures that we can compare different measurements for each type of indicator independent of the number of time steps or mesh size. All indicators have in common that they are still in units of time, thus lower is better for each of them.

Here, the term "degrees of freedom" (DOFs) refers to the number of independent state vectors that are used to represent the numerical solution. For example, if you use a DGSEM-type scheme in 2D on a mesh with 8 elements and with 5-by-5 Gauss-Lobatto nodes in each element (i.e., a polynomial degree of 4), the total number of DOFs would be

\[n_\text{DOFs,DGSEM} = \{\text{number of elements}\} \cdot \{\text{number of nodes per element}\} = 8 \cdot (5 \cdot 5) = 200.\]

In contrast, for a finite volume-type scheme on a mesh with 8 elements, the total number of DOFs would be (independent of the number of spatial dimensions)

\[n_\text{DOFs,FV} = \{\text{number of elements}\} = 8,\]

since for standard finite volume methods you store a single state vector in each element. Note that we specifically count the number of state vectors and not the number of state variables for the DOFs. That is, in the previous example $n_\text{DOFs,FV}$ is equal to 8 independent of whether this is a compressible Euler setup with 5 state variables or a linear scalar advection setup with one state variable.

For each indicator, the measurements are always since the last invocation of the AnalysisCallback. That is, if the analysis callback is called multiple times, the indicators are repeatedly computed and can thus also be used to track the performance over the course of a longer simulation, e.g., to analyze setups with varying performance characteristics. Note that the time spent in the AnalysisCallback itself is always excluded, i.e., the performance measurements are not distorted by potentially expensive solution analysis computations. All other parts of a Trixi.jl simulation are included, however, thus make sure that you disable everything you do not want to be measured (such as I/O callbacks, visualization etc.).

Performance indicators and adaptive mesh refinement

Currently it is not possible to compute meaningful performance indicators for a simulation with arbitrary adaptive mesh refinement, since this would require to explicitly keep track of the number of DOF updates due to the mesh size changing repeatedly. The only way to do this at the moment is by setting the analysis interval to the same value as the AMR interval.

Local, rhs!-only indicator

The local, rhs!-only indicator is computed as

\[\text{time/DOF/rhs!} = \frac{t_\text{\texttt{rhs!}}}{n_\text{DOFs,local} \cdot n_\text{calls,\texttt{rhs!}}},\]

where $t_\text{\texttt{rhs!}}$ is the accumulated time spent in rhs!, $n_\text{DOFs,local}$ is the local number of DOFs (i.e., on the current MPI rank; if doing a serial run, you can just think of this as the number of DOFs), and $n_\text{calls,\texttt{rhs!}}$ is the number of times the rhs! function has been evaluated. Note that for this indicator, we measure only the time spent in rhs!, i.e., by definition all computations outside of rhs! - specifically all other callbacks and the time integration method - are not taken into account.

The local, rhs!-only indicator is usually most useful if you do serial measurements and are interested in the performance of the implementation of your core numerical methods (e.g., when doing performance tuning).

Performance index (PID)

The performance index (PID) is computed as

\[\text{PID} = \frac{t_\text{wall} \cdot n_\text{ranks,MPI}}{n_\text{DOFs,global} \cdot n_\text{calls,\texttt{rhs!}}},\]

where $t_\text{wall}$ is the walltime since the last call to the AnalysisCallback, $n_\text{ranks,MPI}$ is the number of MPI ranks used, $n_\text{DOFs,global}$ is the global number of DOFs (i.e., the sum of DOFs over all MPI ranks; if doing a serial run, you can just think of this as the number of DOFs), and $n_\text{calls,\texttt{rhs!}}$ is the number of times the rhs! function has been evaluated since the last call to the AnalysisCallback. The PID measures everything except the time spent in the AnalysisCallback itself - specifically, all other callbacks and the time integration method itself are included.

The PID is usually most useful if you would like to compare the parallel performance of your code to its serial performance. Specifically, it allows you to evaluate the parallelization overhead of your code by giving you a measure of the resources that are necessary to solve a given simulation setup. In a sense, it mimics the "core hours" metric that is often used by supercomputer centers to measure how many resources a particular compute job requires. It can thus be seen as a proxy for "energy used" and, as an extension, "monetary cost".

Initialization overhead in measurements

When using one of the integration schemes from OrdinaryDiffEq.jl, their implementation will initialize some OrdinaryDiffEq.jl-specific information during the first time step. Among other things, one additional call to rhs! is performed. Therefore, make sure that for performance measurements using the PID either the number of timesteps or the workload per rhs! call is large enough to make the initialization overhead negligible. Note that the extra call to rhs! is properly accounted for in both the number of calls and the measured time, so you do not need to worry about it being expensive. If you want a perfect timing result, you need to set the analysis interval such that the AnalysisCallback is invoked at least once during the course of the simulation and discard the first PID value.

diff --git a/previews/PR1681/reference-trixi/index.html b/previews/PR1681/reference-trixi/index.html index 0629bef386b..4a5c6a5e11a 100644 --- a/previews/PR1681/reference-trixi/index.html +++ b/previews/PR1681/reference-trixi/index.html @@ -1,9 +1,9 @@ -Trixi.jl · Trixi.jl

Trixi.jl API

Trixi.TrixiModule
Trixi

Trixi.jl is a numerical simulation framework for hyperbolic conservation laws. A key objective for the framework is to be useful to both scientists and students. Therefore, next to having an extensible design with a fast implementation, Trixi.jl is focused on being easy to use for new or inexperienced users, including the installation and postprocessing procedures.

To get started, run your first simulation with Trixi.jl using

trixi_include(default_example())

See also: trixi-framework/Trixi.jl

source
Trixi.flux_hll_chen_noelleConstant
flux_hll_chen_noelle = FluxHLL(min_max_speed_chen_noelle)

An instance of FluxHLL specific to the shallow water equations that uses the wave speed estimates from min_max_speed_chen_noelle. This HLL flux is guaranteed to have zero numerical mass flux out of a "dry" element, maintain positivity of the water height, and satisfy an entropy inequality.

For complete details see Section 2.4 of the following reference

  • Guoxian Chen and Sebastian Noelle (2017) A new hydrostatic reconstruction scheme based on subcell reconstructions DOI: 10.1137/15M1053074
source
Trixi.AMRCallbackType
AMRCallback(semi, controller [,adaptor=AdaptorAMR(semi)];
+Trixi.jl · Trixi.jl

Trixi.jl API

Trixi.TrixiModule
Trixi

Trixi.jl is a numerical simulation framework for hyperbolic conservation laws. A key objective for the framework is to be useful to both scientists and students. Therefore, next to having an extensible design with a fast implementation, Trixi.jl is focused on being easy to use for new or inexperienced users, including the installation and postprocessing procedures.

To get started, run your first simulation with Trixi.jl using

trixi_include(default_example())

See also: trixi-framework/Trixi.jl

source
Trixi.flux_hll_chen_noelleConstant
flux_hll_chen_noelle = FluxHLL(min_max_speed_chen_noelle)

An instance of FluxHLL specific to the shallow water equations that uses the wave speed estimates from min_max_speed_chen_noelle. This HLL flux is guaranteed to have zero numerical mass flux out of a "dry" element, maintain positivity of the water height, and satisfy an entropy inequality.

For complete details see Section 2.4 of the following reference

  • Guoxian Chen and Sebastian Noelle (2017) A new hydrostatic reconstruction scheme based on subcell reconstructions DOI: 10.1137/15M1053074
source
Trixi.AMRCallbackType
AMRCallback(semi, controller [,adaptor=AdaptorAMR(semi)];
             interval,
             adapt_initial_condition=true,
             adapt_initial_condition_only_refine=true,
-            dynamic_load_balancing=true)

Performs adaptive mesh refinement (AMR) every interval time steps for a given semidiscretization semi using the chosen controller.

source
Trixi.AbstractEquationsType
AbstractEquations{NDIMS, NVARS}

An abstract supertype of specific equations such as the compressible Euler equations. The type parameters encode the number of spatial dimensions (NDIMS) and the number of primary variables (NVARS) of the physics model.

source
Trixi.AbstractMeshType
AbstractMesh{NDIMS}

An abstract supertype of specific mesh types such as TreeMesh or StructuredMesh. The type parameters encode the number of spatial dimensions (NDIMS).

source
Trixi.AcousticPerturbationEquations2DType
AcousticPerturbationEquations2D(v_mean_global, c_mean_global, rho_mean_global)

Acoustic perturbation equations (APE) in two space dimensions. The equations are given by

\[\begin{aligned} + dynamic_load_balancing=true)

Performs adaptive mesh refinement (AMR) every interval time steps for a given semidiscretization semi using the chosen controller.

source
Trixi.AbstractEquationsType
AbstractEquations{NDIMS, NVARS}

An abstract supertype of specific equations such as the compressible Euler equations. The type parameters encode the number of spatial dimensions (NDIMS) and the number of primary variables (NVARS) of the physics model.

source
Trixi.AbstractMeshType
AbstractMesh{NDIMS}

An abstract supertype of specific mesh types such as TreeMesh or StructuredMesh. The type parameters encode the number of spatial dimensions (NDIMS).

source
Trixi.AcousticPerturbationEquations2DType
AcousticPerturbationEquations2D(v_mean_global, c_mean_global, rho_mean_global)

Acoustic perturbation equations (APE) in two space dimensions. The equations are given by

\[\begin{aligned} \frac{\partial\mathbf{v'}}{\partial t} + \nabla (\bar{\mathbf{v}}\cdot\mathbf{v'}) + \nabla\left( \frac{\bar{c}^2 \tilde{p}'}{\bar{\rho}} \right) &= 0 \\ \frac{\partial \tilde{p}'}{\partial t} + @@ -11,13 +11,13 @@ \end{aligned}\]

The bar $\bar{(\cdot)}$ indicates time-averaged quantities. The unknowns of the APE are the perturbed velocities $\mathbf{v'} = (v_1', v_2')^T$ and the scaled perturbed pressure $\tilde{p}' = \frac{p'}{\bar{c}^2}$, where $p'$ denotes the perturbed pressure and the perturbed variables are defined by $\phi' = \phi - \bar{\phi}$.

In addition to the unknowns, Trixi.jl currently stores the mean values in the state vector, i.e. the state vector used internally is given by

\[\mathbf{u} = \begin{pmatrix} v_1' \\ v_2' \\ \tilde{p}' \\ \bar{v}_1 \\ \bar{v}_2 \\ \bar{c} \\ \bar{\rho} - \end{pmatrix}.\]

This affects the implementation and use of these equations in various ways:

  • The flux values corresponding to the mean values must be zero.
  • The mean values have to be considered when defining initial conditions, boundary conditions or source terms.
  • AnalysisCallback analyzes these variables too.
  • Trixi.jl's visualization tools will visualize the mean values by default.

The constructor accepts a 2-tuple v_mean_global and scalars c_mean_global and rho_mean_global which can be used to make the definition of initial conditions for problems with constant mean flow more flexible. These values are ignored if the mean values are defined internally in an initial condition.

The equations are based on the APE-4 system introduced in the following paper:

source
Trixi.AdiabaticType
struct Adiabatic

Used to create a no-slip boundary condition with BoundaryConditionNavierStokesWall. The field boundary_value_normal_flux_function should be a function with signature boundary_value_normal_flux_function(x, t, equations) and return a scalar value for the normal heat flux at point x and time t.

source
Trixi.AliveCallbackType
AliveCallback(analysis_interval=0, alive_interval=analysis_interval÷10)

Inexpensive callback showing that a simulation is still running by printing some information such as the current time to the screen every alive_interval time steps. If analysis_interval ≂̸ 0, the output is omitted every analysis_interval time steps.

source
Trixi.AnalysisCallbackType
AnalysisCallback(semi; interval=0,
+  \end{pmatrix}.\]

This affects the implementation and use of these equations in various ways:

  • The flux values corresponding to the mean values must be zero.
  • The mean values have to be considered when defining initial conditions, boundary conditions or source terms.
  • AnalysisCallback analyzes these variables too.
  • Trixi.jl's visualization tools will visualize the mean values by default.

The constructor accepts a 2-tuple v_mean_global and scalars c_mean_global and rho_mean_global which can be used to make the definition of initial conditions for problems with constant mean flow more flexible. These values are ignored if the mean values are defined internally in an initial condition.

The equations are based on the APE-4 system introduced in the following paper:

source
Trixi.AdiabaticType
struct Adiabatic

Used to create a no-slip boundary condition with BoundaryConditionNavierStokesWall. The field boundary_value_normal_flux_function should be a function with signature boundary_value_normal_flux_function(x, t, equations) and return a scalar value for the normal heat flux at point x and time t.

source
Trixi.AliveCallbackType
AliveCallback(analysis_interval=0, alive_interval=analysis_interval÷10)

Inexpensive callback showing that a simulation is still running by printing some information such as the current time to the screen every alive_interval time steps. If analysis_interval ≂̸ 0, the output is omitted every analysis_interval time steps.

source
Trixi.AnalysisCallbackType
AnalysisCallback(semi; interval=0,
                        save_analysis=false,
                        output_directory="out",
                        analysis_filename="analysis.dat",
                        extra_analysis_errors=Symbol[],
-                       extra_analysis_integrals=())

Analyze a numerical solution every interval time steps and print the results to the screen. If save_analysis, the results are also saved in joinpath(output_directory, analysis_filename).

Additional errors can be computed, e.g. by passing extra_analysis_errors = (:l2_error_primitive, :linf_error_primitive) or extra_analysis_errors = (:conservation_error,).

Further scalar functions func in extra_analysis_integrals are applied to the numerical solution and integrated over the computational domain. Some examples for this are entropy, energy_kinetic, energy_internal, and energy_total. You can also write your own function with the same signature as the examples listed above and pass it via extra_analysis_integrals. See the developer comments about Trixi.analyze, Trixi.pretty_form_utf, and Trixi.pretty_form_ascii for further information on how to create custom analysis quantities.

In addition, the analysis callback records and outputs a number of quantities that are useful for evaluating the computational performance, such as the total runtime, the performance index (time/DOF/rhs!), the time spent in garbage collection (GC), or the current memory usage (alloc'd memory).

source
Trixi.AnalysisCallbackCoupledType
AnalysisCallbackCoupled(semi, callbacks...)

Combine multiple analysis callbacks for coupled simulations with a SemidiscretizationCoupled. For each coupled system, an indididual AnalysisCallback must be created and passed to the AnalysisCallbackCoupled in order, i.e., in the same sequence as the indidvidual semidiscretizations are stored in the SemidiscretizationCoupled.

Experimental code

This is an experimental feature and can change any time.

source
Trixi.AveragingCallbackType
AveragingCallback(semi::SemidiscretizationHyperbolic, tspan; output_directory="out",
-                  filename="averaging.h5")
Experimental code

This callback is experimental and may change in any future release.

A callback that averages the flow field described by semi which must be a semidiscretization of the compressible Euler equations in two dimensions. The callback records the mean velocity, mean speed of sound, mean density, and mean vorticity for each node over the time interval given by tspan and stores the results in an HDF5 file filename in the directory output_directory. Note that this callback does not support adaptive mesh refinement (AMRCallback).

source
Trixi.BoundaryConditionCoupledType
BoundaryConditionCoupled(other_semi_index, indices, uEltype)

Boundary condition to glue two meshes together. Solution values at the boundary of another mesh will be used as boundary values. This requires the use of SemidiscretizationCoupled. The other mesh is specified by other_semi_index, which is the index of the mesh in the tuple of semidiscretizations.

Note that the elements and nodes of the two meshes at the coupled boundary must coincide. This is currently only implemented for StructuredMesh.

Arguments

  • other_semi_index: the index in SemidiscretizationCoupled of the semidiscretization from which the values are copied
  • indices::Tuple: node/cell indices at the boundary of the mesh in the other semidiscretization. See examples below.
  • uEltype::Type: element type of solution

Examples

# Connect the left boundary of mesh 2 to our boundary such that our positive
+                       extra_analysis_integrals=())

Analyze a numerical solution every interval time steps and print the results to the screen. If save_analysis, the results are also saved in joinpath(output_directory, analysis_filename).

Additional errors can be computed, e.g. by passing extra_analysis_errors = (:l2_error_primitive, :linf_error_primitive) or extra_analysis_errors = (:conservation_error,).

Further scalar functions func in extra_analysis_integrals are applied to the numerical solution and integrated over the computational domain. Some examples for this are entropy, energy_kinetic, energy_internal, and energy_total. You can also write your own function with the same signature as the examples listed above and pass it via extra_analysis_integrals. See the developer comments about Trixi.analyze, Trixi.pretty_form_utf, and Trixi.pretty_form_ascii for further information on how to create custom analysis quantities.

In addition, the analysis callback records and outputs a number of quantities that are useful for evaluating the computational performance, such as the total runtime, the performance index (time/DOF/rhs!), the time spent in garbage collection (GC), or the current memory usage (alloc'd memory).

source
Trixi.AnalysisCallbackCoupledType
AnalysisCallbackCoupled(semi, callbacks...)

Combine multiple analysis callbacks for coupled simulations with a SemidiscretizationCoupled. For each coupled system, an indididual AnalysisCallback must be created and passed to the AnalysisCallbackCoupled in order, i.e., in the same sequence as the indidvidual semidiscretizations are stored in the SemidiscretizationCoupled.

Experimental code

This is an experimental feature and can change any time.

source
Trixi.AveragingCallbackType
AveragingCallback(semi::SemidiscretizationHyperbolic, tspan; output_directory="out",
+                  filename="averaging.h5")
Experimental code

This callback is experimental and may change in any future release.

A callback that averages the flow field described by semi which must be a semidiscretization of the compressible Euler equations in two dimensions. The callback records the mean velocity, mean speed of sound, mean density, and mean vorticity for each node over the time interval given by tspan and stores the results in an HDF5 file filename in the directory output_directory. Note that this callback does not support adaptive mesh refinement (AMRCallback).

source
Trixi.BoundaryConditionCoupledType
BoundaryConditionCoupled(other_semi_index, indices, uEltype)

Boundary condition to glue two meshes together. Solution values at the boundary of another mesh will be used as boundary values. This requires the use of SemidiscretizationCoupled. The other mesh is specified by other_semi_index, which is the index of the mesh in the tuple of semidiscretizations.

Note that the elements and nodes of the two meshes at the coupled boundary must coincide. This is currently only implemented for StructuredMesh.

Arguments

  • other_semi_index: the index in SemidiscretizationCoupled of the semidiscretization from which the values are copied
  • indices::Tuple: node/cell indices at the boundary of the mesh in the other semidiscretization. See examples below.
  • uEltype::Type: element type of solution

Examples

# Connect the left boundary of mesh 2 to our boundary such that our positive
 # boundary direction will match the positive y direction of the other boundary
 BoundaryConditionCoupled(2, (:begin, :i), Float64)
 
@@ -25,7 +25,7 @@
 BoundaryConditionCoupled(2, (:begin, :i_backwards), Float64)
 
 # Using this as y_neg boundary will connect `our_cells[i, 1, j]` to `other_cells[j, end-i, end]`
-BoundaryConditionCoupled(2, (:j, :i_backwards, :end), Float64)
Experimental code

This is an experimental feature and can change any time.

source
Trixi.BoundaryConditionDirichletType
BoundaryConditionDirichlet(boundary_value_function)

Create a Dirichlet boundary condition that uses the function boundary_value_function to specify the values at the boundary. This can be used to create a boundary condition that specifies exact boundary values by passing the exact solution of the equation. The passed boundary value function will be called with the same arguments as an initial condition function is called, i.e., as

boundary_value_function(x, t, equations)

where x specifies the coordinates, t is the current time, and equation is the corresponding system of equations.

Examples

julia> BoundaryConditionDirichlet(initial_condition_convergence_test)
source
Trixi.BoundaryConditionNavierStokesWallType
struct BoundaryConditionNavierStokesWall

Creates a wall-type boundary conditions for the compressible Navier-Stokes equations. The fields boundary_condition_velocity and boundary_condition_heat_flux are intended to be boundary condition types such as the NoSlip velocity boundary condition and the Adiabatic or Isothermal heat boundary condition.

Experimental feature

This is an experimental feature and may change in future releases.

source
Trixi.BoundaryConditionNeumannType
BoundaryConditionNeumann(boundary_normal_flux_function)

Similar to BoundaryConditionDirichlet, but creates a Neumann boundary condition for parabolic equations that uses the function boundary_normal_flux_function to specify the values of the normal flux at the boundary. The passed boundary value function will be called with the same arguments as an initial condition function is called, i.e., as

boundary_normal_flux_function(x, t, equations)

where x specifies the coordinates, t is the current time, and equation is the corresponding system of equations.

source
Trixi.BoundsCheckCallbackType
BoundsCheckCallback(; output_directory="out", save_errors=false, interval=1)

Subcell limiting techniques with SubcellLimiterIDP are constructed to adhere certain local or global bounds. To make sure that these bounds are actually met, this callback calculates the maximum deviation from the bounds. The maximum deviation per applied bound is printed to the screen at the end of the simulation. For more insights, when setting save_errors=true the occurring errors are exported every interval time steps during the simulation. Then, the maximum deviations since the last export are saved in "output_directory/deviations.txt". The BoundsCheckCallback has to be applied as a stage callback for the SSPRK time integration scheme.

Note

For SubcellLimiterIDP, the solution is corrected in the a posteriori correction stage SubcellLimiterIDPCorrection. So, to check the final solution, this bounds check callback must be called after the correction stage.

source
Trixi.CarpenterKennedy2N54Type
CarpenterKennedy2N54()

The following structures and methods provide a minimal implementation of the low-storage explicit Runge-Kutta method of

Carpenter, Kennedy (1994) Fourth order 2N storage RK schemes, Solution 3

using the same interface as OrdinaryDiffEq.jl.

source
Trixi.CompressibleEulerEquations1DType
CompressibleEulerEquations1D(gamma)

The compressible Euler equations

\[\frac{\partial}{\partial t} +BoundaryConditionCoupled(2, (:j, :i_backwards, :end), Float64)

Experimental code

This is an experimental feature and can change any time.

source
Trixi.BoundaryConditionDirichletType
BoundaryConditionDirichlet(boundary_value_function)

Create a Dirichlet boundary condition that uses the function boundary_value_function to specify the values at the boundary. This can be used to create a boundary condition that specifies exact boundary values by passing the exact solution of the equation. The passed boundary value function will be called with the same arguments as an initial condition function is called, i.e., as

boundary_value_function(x, t, equations)

where x specifies the coordinates, t is the current time, and equation is the corresponding system of equations.

Examples

julia> BoundaryConditionDirichlet(initial_condition_convergence_test)
source
Trixi.BoundaryConditionNavierStokesWallType
struct BoundaryConditionNavierStokesWall

Creates a wall-type boundary conditions for the compressible Navier-Stokes equations. The fields boundary_condition_velocity and boundary_condition_heat_flux are intended to be boundary condition types such as the NoSlip velocity boundary condition and the Adiabatic or Isothermal heat boundary condition.

Experimental feature

This is an experimental feature and may change in future releases.

source
Trixi.BoundaryConditionNeumannType
BoundaryConditionNeumann(boundary_normal_flux_function)

Similar to BoundaryConditionDirichlet, but creates a Neumann boundary condition for parabolic equations that uses the function boundary_normal_flux_function to specify the values of the normal flux at the boundary. The passed boundary value function will be called with the same arguments as an initial condition function is called, i.e., as

boundary_normal_flux_function(x, t, equations)

where x specifies the coordinates, t is the current time, and equation is the corresponding system of equations.

source
Trixi.BoundsCheckCallbackType
BoundsCheckCallback(; output_directory="out", save_errors=false, interval=1)

Subcell limiting techniques with SubcellLimiterIDP are constructed to adhere certain local or global bounds. To make sure that these bounds are actually met, this callback calculates the maximum deviation from the bounds. The maximum deviation per applied bound is printed to the screen at the end of the simulation. For more insights, when setting save_errors=true the occurring errors are exported every interval time steps during the simulation. Then, the maximum deviations since the last export are saved in "output_directory/deviations.txt". The BoundsCheckCallback has to be applied as a stage callback for the SSPRK time integration scheme.

Note

For SubcellLimiterIDP, the solution is corrected in the a posteriori correction stage SubcellLimiterIDPCorrection. So, to check the final solution, this bounds check callback must be called after the correction stage.

source
Trixi.CarpenterKennedy2N54Type
CarpenterKennedy2N54()

The following structures and methods provide a minimal implementation of the low-storage explicit Runge-Kutta method of

Carpenter, Kennedy (1994) Fourth order 2N storage RK schemes, Solution 3

using the same interface as OrdinaryDiffEq.jl.

source
Trixi.CompressibleEulerEquations1DType
CompressibleEulerEquations1D(gamma)

The compressible Euler equations

\[\frac{\partial}{\partial t} \begin{pmatrix} \rho \\ \rho v_1 \\ \rho e \end{pmatrix} @@ -37,7 +37,7 @@ = \begin{pmatrix} 0 \\ 0 \\ 0 -\end{pmatrix}\]

for an ideal gas with ratio of specific heats gamma in one space dimension. Here, $\rho$ is the density, $v_1$ the velocity, $e$ the specific total energy rather than specific internal energy, and

\[p = (\gamma - 1) \left( \rho e - \frac{1}{2} \rho v_1^2 \right)\]

the pressure.

source
Trixi.CompressibleEulerEquations2DType
CompressibleEulerEquations2D(gamma)

The compressible Euler equations

\[\frac{\partial}{\partial t} +\end{pmatrix}\]

for an ideal gas with ratio of specific heats gamma in one space dimension. Here, $\rho$ is the density, $v_1$ the velocity, $e$ the specific total energy rather than specific internal energy, and

\[p = (\gamma - 1) \left( \rho e - \frac{1}{2} \rho v_1^2 \right)\]

the pressure.

source
Trixi.CompressibleEulerEquations2DType
CompressibleEulerEquations2D(gamma)

The compressible Euler equations

\[\frac{\partial}{\partial t} \begin{pmatrix} \rho \\ \rho v_1 \\ \rho v_2 \\ \rho e \end{pmatrix} @@ -54,7 +54,7 @@ = \begin{pmatrix} 0 \\ 0 \\ 0 \\ 0 -\end{pmatrix}\]

for an ideal gas with ratio of specific heats gamma in two space dimensions. Here, $\rho$ is the density, $v_1$, $v_2$ the velocities, $e$ the specific total energy rather than specific internal energy, and

\[p = (\gamma - 1) \left( \rho e - \frac{1}{2} \rho (v_1^2+v_2^2) \right)\]

the pressure.

source
Trixi.CompressibleEulerEquations3DType
CompressibleEulerEquations3D(gamma)

The compressible Euler equations

\[\frac{\partial}{\partial t} +\end{pmatrix}\]

for an ideal gas with ratio of specific heats gamma in two space dimensions. Here, $\rho$ is the density, $v_1$, $v_2$ the velocities, $e$ the specific total energy rather than specific internal energy, and

\[p = (\gamma - 1) \left( \rho e - \frac{1}{2} \rho (v_1^2+v_2^2) \right)\]

the pressure.

source
Trixi.CompressibleEulerEquations3DType
CompressibleEulerEquations3D(gamma)

The compressible Euler equations

\[\frac{\partial}{\partial t} \begin{pmatrix} \rho \\ \rho v_1 \\ \rho v_2 \\ \rho v_3 \\ \rho e \end{pmatrix} @@ -76,7 +76,7 @@ = \begin{pmatrix} 0 \\ 0 \\ 0 \\ 0 \\ 0 -\end{pmatrix}\]

for an ideal gas with ratio of specific heats gamma in three space dimensions. Here, $\rho$ is the density, $v_1$, $v_2$, $v_3$ the velocities, $e$ the specific total energy rather than specific internal energy, and

\[p = (\gamma - 1) \left( \rho e - \frac{1}{2} \rho (v_1^2+v_2^2+v_3^2) \right)\]

the pressure.

source
Trixi.CompressibleEulerMulticomponentEquations1DType
CompressibleEulerMulticomponentEquations1D(; gammas, gas_constants)

Multicomponent version of the compressible Euler equations

\[\frac{\partial}{\partial t} +\end{pmatrix}\]

for an ideal gas with ratio of specific heats gamma in three space dimensions. Here, $\rho$ is the density, $v_1$, $v_2$, $v_3$ the velocities, $e$ the specific total energy rather than specific internal energy, and

\[p = (\gamma - 1) \left( \rho e - \frac{1}{2} \rho (v_1^2+v_2^2+v_3^2) \right)\]

the pressure.

source
Trixi.CompressibleEulerMulticomponentEquations1DType
CompressibleEulerMulticomponentEquations1D(; gammas, gas_constants)

Multicomponent version of the compressible Euler equations

\[\frac{\partial}{\partial t} \begin{pmatrix} \rho v_1 \\ \rho e \\ \rho_1 \\ \rho_2 \\ \vdots \\ \rho_{n} \end{pmatrix} @@ -89,7 +89,7 @@ = \begin{pmatrix} 0 \\ 0 \\ 0 \\ 0 \\ \vdots \\ 0 -\end{pmatrix}\]

for calorically perfect gas in one space dimension. Here, $\rho_i$ is the density of component $i$, $\rho=\sum_{i=1}^n\rho_i$ the sum of the individual $\rho_i$, $v_1$ the velocity, $e$ the specific total energy rather than specific internal energy, and

\[p = (\gamma - 1) \left( \rho e - \frac{1}{2} \rho v_1^2 \right)\]

the pressure,

\[\gamma=\frac{\sum_{i=1}^n\rho_i C_{v,i}\gamma_i}{\sum_{i=1}^n\rho_i C_{v,i}}\]

total heat capacity ratio, $\gamma_i$ heat capacity ratio of component $i$,

\[C_{v,i}=\frac{R}{\gamma_i-1}\]

specific heat capacity at constant volume of component $i$.

In case of more than one component, the specific heat ratios gammas and the gas constants gas_constants should be passed as tuples, e.g., gammas=(1.4, 1.667).

The remaining variables like the specific heats at constant volume cv or the specific heats at constant pressure cp are then calculated considering a calorically perfect gas.

source
Trixi.CompressibleEulerMulticomponentEquations2DType
CompressibleEulerMulticomponentEquations2D(; gammas, gas_constants)

Multicomponent version of the compressible Euler equations

\[\frac{\partial}{\partial t} +\end{pmatrix}\]

for calorically perfect gas in one space dimension. Here, $\rho_i$ is the density of component $i$, $\rho=\sum_{i=1}^n\rho_i$ the sum of the individual $\rho_i$, $v_1$ the velocity, $e$ the specific total energy rather than specific internal energy, and

\[p = (\gamma - 1) \left( \rho e - \frac{1}{2} \rho v_1^2 \right)\]

the pressure,

\[\gamma=\frac{\sum_{i=1}^n\rho_i C_{v,i}\gamma_i}{\sum_{i=1}^n\rho_i C_{v,i}}\]

total heat capacity ratio, $\gamma_i$ heat capacity ratio of component $i$,

\[C_{v,i}=\frac{R}{\gamma_i-1}\]

specific heat capacity at constant volume of component $i$.

In case of more than one component, the specific heat ratios gammas and the gas constants gas_constants should be passed as tuples, e.g., gammas=(1.4, 1.667).

The remaining variables like the specific heats at constant volume cv or the specific heats at constant pressure cp are then calculated considering a calorically perfect gas.

source
Trixi.CompressibleEulerMulticomponentEquations2DType
CompressibleEulerMulticomponentEquations2D(; gammas, gas_constants)

Multicomponent version of the compressible Euler equations

\[\frac{\partial}{\partial t} \begin{pmatrix} \rho v_1 \\ \rho v_2 \\ \rho e \\ \rho_1 \\ \rho_2 \\ \vdots \\ \rho_{n} \end{pmatrix} @@ -106,7 +106,7 @@ = \begin{pmatrix} 0 \\ 0 \\ 0 \\ 0 \\ 0 \\ \vdots \\ 0 -\end{pmatrix}\]

for calorically perfect gas in two space dimensions. Here, $\rho_i$ is the density of component $i$, $\rho=\sum_{i=1}^n\rho_i$ the sum of the individual $\rho_i$, $v_1$, $v_2$ the velocities, $e$ the specific total energy rather than specific internal energy, and

\[p = (\gamma - 1) \left( \rho e - \frac{1}{2} \rho (v_1^2 + v_2^2) \right)\]

the pressure,

\[\gamma=\frac{\sum_{i=1}^n\rho_i C_{v,i}\gamma_i}{\sum_{i=1}^n\rho_i C_{v,i}}\]

total heat capacity ratio, $\gamma_i$ heat capacity ratio of component $i$,

\[C_{v,i}=\frac{R}{\gamma_i-1}\]

specific heat capacity at constant volume of component $i$.

In case of more than one component, the specific heat ratios gammas and the gas constants gas_constants in [kJ/(kg*K)] should be passed as tuples, e.g., gammas=(1.4, 1.667).

The remaining variables like the specific heats at constant volume cv or the specific heats at constant pressure cp are then calculated considering a calorically perfect gas.

source
Trixi.CompressibleNavierStokesDiffusion1DType
CompressibleNavierStokesDiffusion1D(equations; mu, Pr,
+\end{pmatrix}\]

for calorically perfect gas in two space dimensions. Here, $\rho_i$ is the density of component $i$, $\rho=\sum_{i=1}^n\rho_i$ the sum of the individual $\rho_i$, $v_1$, $v_2$ the velocities, $e$ the specific total energy rather than specific internal energy, and

\[p = (\gamma - 1) \left( \rho e - \frac{1}{2} \rho (v_1^2 + v_2^2) \right)\]

the pressure,

\[\gamma=\frac{\sum_{i=1}^n\rho_i C_{v,i}\gamma_i}{\sum_{i=1}^n\rho_i C_{v,i}}\]

total heat capacity ratio, $\gamma_i$ heat capacity ratio of component $i$,

\[C_{v,i}=\frac{R}{\gamma_i-1}\]

specific heat capacity at constant volume of component $i$.

In case of more than one component, the specific heat ratios gammas and the gas constants gas_constants in [kJ/(kg*K)] should be passed as tuples, e.g., gammas=(1.4, 1.667).

The remaining variables like the specific heats at constant volume cv or the specific heats at constant pressure cp are then calculated considering a calorically perfect gas.

source
Trixi.CompressibleNavierStokesDiffusion1DType
CompressibleNavierStokesDiffusion1D(equations; mu, Pr,
                                     gradient_variables=GradientVariablesPrimitive())

Contains the diffusion (i.e. parabolic) terms applied to mass, momenta, and total energy together with the advective terms from the CompressibleEulerEquations1D.

  • equations: instance of the CompressibleEulerEquations1D
  • mu: dynamic viscosity,
  • Pr: Prandtl number,
  • gradient_variables: which variables the gradients are taken with respect to. Defaults to GradientVariablesPrimitive().

Fluid properties such as the dynamic viscosity $\mu$ can be provided in any consistent unit system, e.g., [$\mu$] = kg m⁻¹ s⁻¹.

The particular form of the compressible Navier-Stokes implemented is

\[\frac{\partial}{\partial t} \begin{pmatrix} \rho \\ \rho v \\ \rho e @@ -120,7 +120,7 @@ \frac{\partial}{\partial x} \begin{pmatrix} 0 \\ \tau \\ \tau v - q -\end{pmatrix}\]

where the system is closed with the ideal gas assumption giving

\[p = (\gamma - 1) \left( \rho e - \frac{1}{2} \rho v^2 \right)\]

as the pressure. The value of the adiabatic constant gamma is taken from the CompressibleEulerEquations1D. The terms on the right hand side of the system above are built from the viscous stress

\[\tau = \mu \frac{\partial}{\partial x} v\]

where the heat flux is

\[q = -\kappa \frac{\partial}{\partial x} \left(T\right),\quad T = \frac{p}{R\rho}\]

where $T$ is the temperature and $\kappa$ is the thermal conductivity for Fick's law. Under the assumption that the gas has a constant Prandtl number, the thermal conductivity is

\[\kappa = \frac{\gamma \mu R}{(\gamma - 1)\textrm{Pr}}.\]

From this combination of temperature $T$ and thermal conductivity $\kappa$ we see that the gas constant R cancels and the heat flux becomes

\[q = -\kappa \frac{\partial}{\partial x} \left(T\right) = -\frac{\gamma \mu}{(\gamma - 1)\textrm{Pr}} \frac{\partial}{\partial x} \left(\frac{p}{\rho}\right)\]

which is the form implemented below in the flux function.

In one spatial dimensions we require gradients for two quantities, e.g., primitive quantities

\[\frac{\partial}{\partial x} v,\, \frac{\partial}{\partial x} T\]

or the entropy variables

\[\frac{\partial}{\partial x} w_2,\, \frac{\partial}{\partial x} w_3\]

where

\[w_2 = \frac{\rho v1}{p},\, w_3 = -\frac{\rho}{p}\]

Experimental code

This code is experimental and may be changed or removed in any future release.

source
Trixi.CompressibleNavierStokesDiffusion2DType
CompressibleNavierStokesDiffusion2D(equations; mu, Pr,
+\end{pmatrix}\]

where the system is closed with the ideal gas assumption giving

\[p = (\gamma - 1) \left( \rho e - \frac{1}{2} \rho v^2 \right)\]

as the pressure. The value of the adiabatic constant gamma is taken from the CompressibleEulerEquations1D. The terms on the right hand side of the system above are built from the viscous stress

\[\tau = \mu \frac{\partial}{\partial x} v\]

where the heat flux is

\[q = -\kappa \frac{\partial}{\partial x} \left(T\right),\quad T = \frac{p}{R\rho}\]

where $T$ is the temperature and $\kappa$ is the thermal conductivity for Fick's law. Under the assumption that the gas has a constant Prandtl number, the thermal conductivity is

\[\kappa = \frac{\gamma \mu R}{(\gamma - 1)\textrm{Pr}}.\]

From this combination of temperature $T$ and thermal conductivity $\kappa$ we see that the gas constant R cancels and the heat flux becomes

\[q = -\kappa \frac{\partial}{\partial x} \left(T\right) = -\frac{\gamma \mu}{(\gamma - 1)\textrm{Pr}} \frac{\partial}{\partial x} \left(\frac{p}{\rho}\right)\]

which is the form implemented below in the flux function.

In one spatial dimensions we require gradients for two quantities, e.g., primitive quantities

\[\frac{\partial}{\partial x} v,\, \frac{\partial}{\partial x} T\]

or the entropy variables

\[\frac{\partial}{\partial x} w_2,\, \frac{\partial}{\partial x} w_3\]

where

\[w_2 = \frac{\rho v1}{p},\, w_3 = -\frac{\rho}{p}\]

Experimental code

This code is experimental and may be changed or removed in any future release.

source
Trixi.CompressibleNavierStokesDiffusion2DType
CompressibleNavierStokesDiffusion2D(equations; mu, Pr,
                                     gradient_variables=GradientVariablesPrimitive())

Contains the diffusion (i.e. parabolic) terms applied to mass, momenta, and total energy together with the advective terms from the CompressibleEulerEquations2D.

  • equations: instance of the CompressibleEulerEquations2D
  • mu: dynamic viscosity,
  • Pr: Prandtl number,
  • gradient_variables: which variables the gradients are taken with respect to. Defaults to GradientVariablesPrimitive().

Fluid properties such as the dynamic viscosity $\mu$ can be provided in any consistent unit system, e.g., [$\mu$] = kg m⁻¹ s⁻¹.

The particular form of the compressible Navier-Stokes implemented is

\[\frac{\partial}{\partial t} \begin{pmatrix} \rho \\ \rho \mathbf{v} \\ \rho e @@ -134,7 +134,7 @@ \nabla \cdot \begin{pmatrix} 0 \\ \underline{\tau} \\ \underline{\tau}\mathbf{v} - \mathbf{q} -\end{pmatrix}\]

where the system is closed with the ideal gas assumption giving

\[p = (\gamma - 1) \left( \rho e - \frac{1}{2} \rho (v_1^2+v_2^2) \right)\]

as the pressure. The value of the adiabatic constant gamma is taken from the CompressibleEulerEquations2D. The terms on the right hand side of the system above are built from the viscous stress tensor

\[\underline{\tau} = \mu \left(\nabla\mathbf{v} + \left(\nabla\mathbf{v}\right)^T\right) - \frac{2}{3} \mu \left(\nabla\cdot\mathbf{v}\right)\underline{I}\]

where $\underline{I}$ is the $2\times 2$ identity matrix and the heat flux is

\[\mathbf{q} = -\kappa\nabla\left(T\right),\quad T = \frac{p}{R\rho}\]

where $T$ is the temperature and $\kappa$ is the thermal conductivity for Fick's law. Under the assumption that the gas has a constant Prandtl number, the thermal conductivity is

\[\kappa = \frac{\gamma \mu R}{(\gamma - 1)\textrm{Pr}}.\]

From this combination of temperature $T$ and thermal conductivity $\kappa$ we see that the gas constant R cancels and the heat flux becomes

\[\mathbf{q} = -\kappa\nabla\left(T\right) = -\frac{\gamma \mu}{(\gamma - 1)\textrm{Pr}}\nabla\left(\frac{p}{\rho}\right)\]

which is the form implemented below in the flux function.

In two spatial dimensions we require gradients for three quantities, e.g., primitive quantities

\[\nabla v_1,\, \nabla v_2,\, \nabla T\]

or the entropy variables

\[\nabla w_2,\, \nabla w_3,\, \nabla w_4\]

where

\[w_2 = \frac{\rho v_1}{p},\, w_3 = \frac{\rho v_2}{p},\, w_4 = -\frac{\rho}{p}\]

Experimental code

This code is experimental and may be changed or removed in any future release.

source
Trixi.CompressibleNavierStokesDiffusion3DType
CompressibleNavierStokesDiffusion3D(equations; mu, Pr,
+\end{pmatrix}\]

where the system is closed with the ideal gas assumption giving

\[p = (\gamma - 1) \left( \rho e - \frac{1}{2} \rho (v_1^2+v_2^2) \right)\]

as the pressure. The value of the adiabatic constant gamma is taken from the CompressibleEulerEquations2D. The terms on the right hand side of the system above are built from the viscous stress tensor

\[\underline{\tau} = \mu \left(\nabla\mathbf{v} + \left(\nabla\mathbf{v}\right)^T\right) - \frac{2}{3} \mu \left(\nabla\cdot\mathbf{v}\right)\underline{I}\]

where $\underline{I}$ is the $2\times 2$ identity matrix and the heat flux is

\[\mathbf{q} = -\kappa\nabla\left(T\right),\quad T = \frac{p}{R\rho}\]

where $T$ is the temperature and $\kappa$ is the thermal conductivity for Fick's law. Under the assumption that the gas has a constant Prandtl number, the thermal conductivity is

\[\kappa = \frac{\gamma \mu R}{(\gamma - 1)\textrm{Pr}}.\]

From this combination of temperature $T$ and thermal conductivity $\kappa$ we see that the gas constant R cancels and the heat flux becomes

\[\mathbf{q} = -\kappa\nabla\left(T\right) = -\frac{\gamma \mu}{(\gamma - 1)\textrm{Pr}}\nabla\left(\frac{p}{\rho}\right)\]

which is the form implemented below in the flux function.

In two spatial dimensions we require gradients for three quantities, e.g., primitive quantities

\[\nabla v_1,\, \nabla v_2,\, \nabla T\]

or the entropy variables

\[\nabla w_2,\, \nabla w_3,\, \nabla w_4\]

where

\[w_2 = \frac{\rho v_1}{p},\, w_3 = \frac{\rho v_2}{p},\, w_4 = -\frac{\rho}{p}\]

Experimental code

This code is experimental and may be changed or removed in any future release.

source
Trixi.CompressibleNavierStokesDiffusion3DType
CompressibleNavierStokesDiffusion3D(equations; mu, Pr,
                                     gradient_variables=GradientVariablesPrimitive())

Contains the diffusion (i.e. parabolic) terms applied to mass, momenta, and total energy together with the advective terms from the CompressibleEulerEquations3D.

  • equations: instance of the CompressibleEulerEquations3D
  • mu: dynamic viscosity,
  • Pr: Prandtl number,
  • gradient_variables: which variables the gradients are taken with respect to. Defaults to GradientVariablesPrimitive().

Fluid properties such as the dynamic viscosity $\mu$ can be provided in any consistent unit system, e.g., [$\mu$] = kg m⁻¹ s⁻¹.

The particular form of the compressible Navier-Stokes implemented is

\[\frac{\partial}{\partial t} \begin{pmatrix} \rho \\ \rho \mathbf{v} \\ \rho e @@ -148,40 +148,40 @@ \nabla \cdot \begin{pmatrix} 0 \\ \underline{\tau} \\ \underline{\tau}\mathbf{v} - \mathbf{q} -\end{pmatrix}\]

where the system is closed with the ideal gas assumption giving

\[p = (\gamma - 1) \left( \rho e - \frac{1}{2} \rho (v_1^2+v_2^2+v_3^2) \right)\]

as the pressure. The value of the adiabatic constant gamma is taken from the CompressibleEulerEquations2D. The terms on the right hand side of the system above are built from the viscous stress tensor

\[\underline{\tau} = \mu \left(\nabla\mathbf{v} + \left(\nabla\mathbf{v}\right)^T\right) - \frac{2}{3} \mu \left(\nabla\cdot\mathbf{v}\right)\underline{I}\]

where $\underline{I}$ is the $3\times 3$ identity matrix and the heat flux is

\[\mathbf{q} = -\kappa\nabla\left(T\right),\quad T = \frac{p}{R\rho}\]

where $T$ is the temperature and $\kappa$ is the thermal conductivity for Fick's law. Under the assumption that the gas has a constant Prandtl number, the thermal conductivity is

\[\kappa = \frac{\gamma \mu R}{(\gamma - 1)\textrm{Pr}}.\]

From this combination of temperature $T$ and thermal conductivity $\kappa$ we see that the gas constant R cancels and the heat flux becomes

\[\mathbf{q} = -\kappa\nabla\left(T\right) = -\frac{\gamma \mu}{(\gamma - 1)\textrm{Pr}}\nabla\left(\frac{p}{\rho}\right)\]

which is the form implemented below in the flux function.

In two spatial dimensions we require gradients for three quantities, e.g., primitive quantities

\[\nabla v_1,\, \nabla v_2,\, \nabla v_3,\, \nabla T\]

or the entropy variables

\[\nabla w_2,\, \nabla w_3,\, \nabla w_4\, \nabla w_5\]

where

\[w_2 = \frac{\rho v_1}{p},\, w_3 = \frac{\rho v_2}{p},\, w_4 = \frac{\rho v_3}{p},\, w_5 = -\frac{\rho}{p}\]

Experimental code

This code is experimental and may be changed or removed in any future release.

source
Trixi.ControllerThreeLevelType
ControllerThreeLevel(semi, indicator; base_level=1,
+\end{pmatrix}\]

where the system is closed with the ideal gas assumption giving

\[p = (\gamma - 1) \left( \rho e - \frac{1}{2} \rho (v_1^2+v_2^2+v_3^2) \right)\]

as the pressure. The value of the adiabatic constant gamma is taken from the CompressibleEulerEquations2D. The terms on the right hand side of the system above are built from the viscous stress tensor

\[\underline{\tau} = \mu \left(\nabla\mathbf{v} + \left(\nabla\mathbf{v}\right)^T\right) - \frac{2}{3} \mu \left(\nabla\cdot\mathbf{v}\right)\underline{I}\]

where $\underline{I}$ is the $3\times 3$ identity matrix and the heat flux is

\[\mathbf{q} = -\kappa\nabla\left(T\right),\quad T = \frac{p}{R\rho}\]

where $T$ is the temperature and $\kappa$ is the thermal conductivity for Fick's law. Under the assumption that the gas has a constant Prandtl number, the thermal conductivity is

\[\kappa = \frac{\gamma \mu R}{(\gamma - 1)\textrm{Pr}}.\]

From this combination of temperature $T$ and thermal conductivity $\kappa$ we see that the gas constant R cancels and the heat flux becomes

\[\mathbf{q} = -\kappa\nabla\left(T\right) = -\frac{\gamma \mu}{(\gamma - 1)\textrm{Pr}}\nabla\left(\frac{p}{\rho}\right)\]

which is the form implemented below in the flux function.

In two spatial dimensions we require gradients for three quantities, e.g., primitive quantities

\[\nabla v_1,\, \nabla v_2,\, \nabla v_3,\, \nabla T\]

or the entropy variables

\[\nabla w_2,\, \nabla w_3,\, \nabla w_4\, \nabla w_5\]

where

\[w_2 = \frac{\rho v_1}{p},\, w_3 = \frac{\rho v_2}{p},\, w_4 = \frac{\rho v_3}{p},\, w_5 = -\frac{\rho}{p}\]

Experimental code

This code is experimental and may be changed or removed in any future release.

source
Trixi.ControllerThreeLevelType
ControllerThreeLevel(semi, indicator; base_level=1,
                                       med_level=base_level, med_threshold=0.0,
-                                      max_level=base_level, max_threshold=1.0)

An AMR controller based on three levels (in descending order of precedence):

  • set the target level to max_level if indicator > max_threshold
  • set the target level to med_level if indicator > med_threshold; if med_level < 0, set the target level to the current level
  • set the target level to base_level otherwise
source
Trixi.ControllerThreeLevelCombinedType
ControllerThreeLevelCombined(semi, indicator_primary, indicator_secondary;
+                                      max_level=base_level, max_threshold=1.0)

An AMR controller based on three levels (in descending order of precedence):

  • set the target level to max_level if indicator > max_threshold
  • set the target level to med_level if indicator > med_threshold; if med_level < 0, set the target level to the current level
  • set the target level to base_level otherwise
source
Trixi.ControllerThreeLevelCombinedType
ControllerThreeLevelCombined(semi, indicator_primary, indicator_secondary;
                              base_level=1,
                              med_level=base_level, med_threshold=0.0,
                              max_level=base_level, max_threshold=1.0,
-                             max_threshold_secondary=1.0)

An AMR controller based on three levels (in descending order of precedence):

  • set the target level to max_level if indicator_primary > max_threshold
  • set the target level to med_level if indicator_primary > med_threshold; if med_level < 0, set the target level to the current level
  • set the target level to base_level otherwise

If indicator_secondary >= max_threshold_secondary, set the target level to max_level.

source
Trixi.DGMultiMethod
DGMulti(approximation_type::AbstractDerivativeOperator;
+                             max_threshold_secondary=1.0)

An AMR controller based on three levels (in descending order of precedence):

  • set the target level to max_level if indicator_primary > max_threshold
  • set the target level to med_level if indicator_primary > med_threshold; if med_level < 0, set the target level to the current level
  • set the target level to base_level otherwise

If indicator_secondary >= max_threshold_secondary, set the target level to max_level.

source
Trixi.DGMultiMethod
DGMulti(approximation_type::AbstractDerivativeOperator;
         element_type::AbstractElemShape,
         surface_flux=flux_central,
         surface_integral=SurfaceIntegralWeakForm(surface_flux),
         volume_integral=VolumeIntegralWeakForm(),
-        kwargs...)

Create a summation by parts (SBP) discretization on the given element_type using a tensor product structure based on the 1D SBP derivative operator passed as approximation_type.

For more info, see the documentations of StartUpDG.jl and SummationByPartsOperators.jl.

source
Trixi.DGMultiMethod
DGMulti(; polydeg::Integer,
+        kwargs...)

Create a summation by parts (SBP) discretization on the given element_type using a tensor product structure based on the 1D SBP derivative operator passed as approximation_type.

For more info, see the documentations of StartUpDG.jl and SummationByPartsOperators.jl.

source
Trixi.DGMultiMethod
DGMulti(; polydeg::Integer,
           element_type::AbstractElemShape,
           approximation_type=Polynomial(),
           surface_flux=flux_central,
           surface_integral=SurfaceIntegralWeakForm(surface_flux),
           volume_integral=VolumeIntegralWeakForm(),
-          RefElemData_kwargs...)

Create a discontinuous Galerkin method which uses

  • approximations of polynomial degree polydeg
  • element type element_type (Tri(), Quad(), Tet(), and Hex() currently supported)

Optional:

  • approximation_type (default is Polynomial(); SBP() also supported for Tri(), Quad(), and Hex() element types).
  • RefElemData_kwargs are additional keyword arguments for RefElemData, such as quad_rule_vol. For more info, see the StartUpDG.jl docs.
source
Trixi.DGMultiMeshType
DGMultiMesh{NDIMS, ...}

DGMultiMesh describes a mesh type which wraps StartUpDG.MeshData and boundary_faces in a dispatchable type. This is intended to store geometric data and connectivities for any type of mesh (Cartesian, affine, curved, structured/unstructured).

source
Trixi.DGMultiMeshMethod
DGMultiMesh(dg::DGMulti{2, Tri}, triangulateIO, boundary_dict::Dict{Symbol, Int})
  • dg::DGMulti contains information associated with to the reference element (e.g., quadrature, basis evaluation, differentiation, etc).
  • triangulateIO is a TriangulateIO mesh representation
  • boundary_dict is a Dict{Symbol, Int} which associates each integer TriangulateIO boundary tag with a Symbol.
source
Trixi.DGMultiMeshMethod
DGMultiMesh(dg::DGMulti)

Constructs a single-element DGMultiMesh for a single periodic element given a DGMulti with approximation_type set to a periodic (finite difference) SBP operator from SummationByPartsOperators.jl.

source
Trixi.DGMultiMeshMethod
DGMultiMesh(dg::DGMulti{NDIMS}, vertex_coordinates, EToV;
+          RefElemData_kwargs...)

Create a discontinuous Galerkin method which uses

  • approximations of polynomial degree polydeg
  • element type element_type (Tri(), Quad(), Tet(), and Hex() currently supported)

Optional:

  • approximation_type (default is Polynomial(); SBP() also supported for Tri(), Quad(), and Hex() element types).
  • RefElemData_kwargs are additional keyword arguments for RefElemData, such as quad_rule_vol. For more info, see the StartUpDG.jl docs.
source
Trixi.DGMultiMeshType
DGMultiMesh{NDIMS, ...}

DGMultiMesh describes a mesh type which wraps StartUpDG.MeshData and boundary_faces in a dispatchable type. This is intended to store geometric data and connectivities for any type of mesh (Cartesian, affine, curved, structured/unstructured).

source
Trixi.DGMultiMeshMethod
DGMultiMesh(dg::DGMulti{2, Tri}, triangulateIO, boundary_dict::Dict{Symbol, Int})
  • dg::DGMulti contains information associated with to the reference element (e.g., quadrature, basis evaluation, differentiation, etc).
  • triangulateIO is a TriangulateIO mesh representation
  • boundary_dict is a Dict{Symbol, Int} which associates each integer TriangulateIO boundary tag with a Symbol.
source
Trixi.DGMultiMeshMethod
DGMultiMesh(dg::DGMulti)

Constructs a single-element DGMultiMesh for a single periodic element given a DGMulti with approximation_type set to a periodic (finite difference) SBP operator from SummationByPartsOperators.jl.

source
Trixi.DGMultiMeshMethod
DGMultiMesh(dg::DGMulti{NDIMS}, vertex_coordinates, EToV;
             is_on_boundary=nothing,
-            periodicity=ntuple(_->false, NDIMS)) where {NDIMS}
  • dg::DGMulti contains information associated with to the reference element (e.g., quadrature, basis evaluation, differentiation, etc).
  • vertex_coordinates is a tuple of vectors containing x,y,... components of the vertex coordinates
  • EToV is a 2D array containing element-to-vertex connectivities for each element
  • is_on_boundary specifies boundary using a Dict{Symbol, <:Function}
  • periodicity is a tuple of booleans specifying if the domain is periodic true/false in the (x,y,z) direction.
source
Trixi.DGMultiMeshMethod
DGMultiMesh(dg::DGMulti{NDIMS}, cells_per_dimension, mapping;
+            periodicity=ntuple(_->false, NDIMS)) where {NDIMS}
  • dg::DGMulti contains information associated with to the reference element (e.g., quadrature, basis evaluation, differentiation, etc).
  • vertex_coordinates is a tuple of vectors containing x,y,... components of the vertex coordinates
  • EToV is a 2D array containing element-to-vertex connectivities for each element
  • is_on_boundary specifies boundary using a Dict{Symbol, <:Function}
  • periodicity is a tuple of booleans specifying if the domain is periodic true/false in the (x,y,z) direction.
source
Trixi.DGMultiMeshMethod
DGMultiMesh(dg::DGMulti{NDIMS}, cells_per_dimension, mapping;
             is_on_boundary=nothing,
-            periodicity=ntuple(_ -> false, NDIMS), kwargs...) where {NDIMS}

Constructs a Curved() DGMultiMesh with element type dg.basis.element_type.

  • mapping is a function which maps from a reference [-1, 1]^NDIMS domain to a mapped domain, e.g., xy = mapping(x, y) in 2D.
  • is_on_boundary specifies boundary using a Dict{Symbol, <:Function}
  • periodicity is a tuple of Bools specifying periodicity = true/false in the (x,y,z) direction.
source
Trixi.DGMultiMeshMethod
DGMultiMesh(dg::DGMulti, cells_per_dimension;
+            periodicity=ntuple(_ -> false, NDIMS), kwargs...) where {NDIMS}

Constructs a Curved() DGMultiMesh with element type dg.basis.element_type.

  • mapping is a function which maps from a reference [-1, 1]^NDIMS domain to a mapped domain, e.g., xy = mapping(x, y) in 2D.
  • is_on_boundary specifies boundary using a Dict{Symbol, <:Function}
  • periodicity is a tuple of Bools specifying periodicity = true/false in the (x,y,z) direction.
source
Trixi.DGMultiMeshMethod
DGMultiMesh(dg::DGMulti, cells_per_dimension;
             coordinates_min=(-1.0, -1.0), coordinates_max=(1.0, 1.0),
             is_on_boundary=nothing,
-            periodicity=ntuple(_ -> false, NDIMS))

Constructs a Cartesian DGMultiMesh with element type dg.basis.element_type. The domain is the tensor product of the intervals [coordinates_min[i], coordinates_max[i]].

  • is_on_boundary specifies boundary using a Dict{Symbol, <:Function}
  • periodicity is a tuple of Bools specifying periodicity = true/false in the (x,y,z) direction.
source
Trixi.DGMultiMeshMethod
DGMultiMesh(dg::DGMulti, filename::String)
  • dg::DGMulti contains information associated with the reference element (e.g., quadrature, basis evaluation, differentiation, etc).
  • filename is a path specifying a .mesh file generated by HOHQMesh.
source
Trixi.DGSEMType
DGSEM(; RealT=Float64, polydeg::Integer,
+            periodicity=ntuple(_ -> false, NDIMS))

Constructs a Cartesian DGMultiMesh with element type dg.basis.element_type. The domain is the tensor product of the intervals [coordinates_min[i], coordinates_max[i]].

  • is_on_boundary specifies boundary using a Dict{Symbol, <:Function}
  • periodicity is a tuple of Bools specifying periodicity = true/false in the (x,y,z) direction.
source
Trixi.DGMultiMeshMethod
DGMultiMesh(dg::DGMulti, filename::String)
  • dg::DGMulti contains information associated with the reference element (e.g., quadrature, basis evaluation, differentiation, etc).
  • filename is a path specifying a .mesh file generated by HOHQMesh.
source
Trixi.DGSEMType
DGSEM(; RealT=Float64, polydeg::Integer,
         surface_flux=flux_central,
         surface_integral=SurfaceIntegralWeakForm(surface_flux),
         volume_integral=VolumeIntegralWeakForm(),
-        mortar=MortarL2(basis))

Create a discontinuous Galerkin spectral element method (DGSEM) using a LobattoLegendreBasis with polynomials of degree polydeg.

source
Trixi.DissipationLocalLaxFriedrichsType
DissipationLocalLaxFriedrichs(max_abs_speed=max_abs_speed_naive)

Create a local Lax-Friedrichs dissipation operator where the maximum absolute wave speed is estimated as max_abs_speed(u_ll, u_rr, orientation_or_normal_direction, equations), defaulting to max_abs_speed_naive.

source
Trixi.EulerAcousticsCouplingCallbackType
EulerAcousticsCouplingCallback
Experimental code

This callback is experimental and may change in any future release.

A callback that couples the acoustic perturbation equations and compressible Euler equations. Must be used in conjunction with SemidiscretizationEulerAcoustics. This callback manages the flow solver - which is always one time step ahead of the acoustics solver - and calculates the acoustic source term after each time step. The linearized Lamb vector is used as the source term, i.e.

\[\mathbf{s} = -(\mathbf{\omega'} \times \bar{\mathbf{v}} - + \bar{\mathbf{\omega}} \times \mathbf{v'}),\]

where $\mathbf{v}$ denotes the velocity, $\mathbf{\omega}$ denotes the vorticity, the bar $\bar{(\cdot)}$ indicates time-averaged quantities (see AveragingCallback) and prime $(\cdot)'$ denotes perturbed quantities defined by $\phi' = \phi - \bar{\phi}$. Note that the perturbed quantities here are based entirely on the pure flow solution and should not be confused with the state variables of the acoustic perturbation equations.

In addition, this callback manages the time step size for both solvers and initializes the mean values of the acoustic perturbation equations using results obtained with the AveragingCallback.

source
Trixi.EulerAcousticsCouplingCallbackMethod
EulerAcousticsCouplingCallback(ode_euler, averaging_file::AbstractString, alg,
-                               cfl_acoustics::Real, cfl_euler::Real; kwargs...)
Experimental code

This callback is experimental and may change in any future release.

Creates an EulerAcousticsCouplingCallback based on the pure flow ODEProblem given by ode_euler. Creates an integrator using the time integration method alg and the keyword arguments to solve ode_euler (consult the OrdinaryDiffEq documentation for further information). Manages the step size for both solvers by using the minimum of the maximum step size obtained with CFL numbers cfl_acoustics for the acoustics solver and cfl_euler for and flow solver, respectively. The mean values for the acoustic perturbation equations are read from averaging_file (see AveragingCallback).

source
Trixi.DissipationLocalLaxFriedrichsType
DissipationLocalLaxFriedrichs(max_abs_speed=max_abs_speed_naive)

Create a local Lax-Friedrichs dissipation operator where the maximum absolute wave speed is estimated as max_abs_speed(u_ll, u_rr, orientation_or_normal_direction, equations), defaulting to max_abs_speed_naive.

source
Trixi.EulerAcousticsCouplingCallbackType
EulerAcousticsCouplingCallback
Experimental code

This callback is experimental and may change in any future release.

A callback that couples the acoustic perturbation equations and compressible Euler equations. Must be used in conjunction with SemidiscretizationEulerAcoustics. This callback manages the flow solver - which is always one time step ahead of the acoustics solver - and calculates the acoustic source term after each time step. The linearized Lamb vector is used as the source term, i.e.

\[\mathbf{s} = -(\mathbf{\omega'} \times \bar{\mathbf{v}} + + \bar{\mathbf{\omega}} \times \mathbf{v'}),\]

where $\mathbf{v}$ denotes the velocity, $\mathbf{\omega}$ denotes the vorticity, the bar $\bar{(\cdot)}$ indicates time-averaged quantities (see AveragingCallback) and prime $(\cdot)'$ denotes perturbed quantities defined by $\phi' = \phi - \bar{\phi}$. Note that the perturbed quantities here are based entirely on the pure flow solution and should not be confused with the state variables of the acoustic perturbation equations.

In addition, this callback manages the time step size for both solvers and initializes the mean values of the acoustic perturbation equations using results obtained with the AveragingCallback.

source
Trixi.EulerAcousticsCouplingCallbackMethod
EulerAcousticsCouplingCallback(ode_euler, averaging_file::AbstractString, alg,
+                               cfl_acoustics::Real, cfl_euler::Real; kwargs...)
Experimental code

This callback is experimental and may change in any future release.

Creates an EulerAcousticsCouplingCallback based on the pure flow ODEProblem given by ode_euler. Creates an integrator using the time integration method alg and the keyword arguments to solve ode_euler (consult the OrdinaryDiffEq documentation for further information). Manages the step size for both solvers by using the minimum of the maximum step size obtained with CFL numbers cfl_acoustics for the acoustics solver and cfl_euler for and flow solver, respectively. The mean values for the acoustic perturbation equations are read from averaging_file (see AveragingCallback).

source
Trixi.EulerAcousticsCouplingCallbackMethod
EulerAcousticsCouplingCallback(ode_euler,
                                averaging_callback::DiscreteCallback{<:Any, <:AveragingCallback},
-                               alg, cfl_acoustics::Real, cfl_euler::Real; kwargs...)
Experimental code

This callback is experimental and may change in any future release.

Creates an EulerAcousticsCouplingCallback based on the pure flow ODEProblem given by ode_euler. Creates an integrator using the time integration method alg and the keyword arguments to solve ode_euler (consult the OrdinaryDiffEq documentation for further information). Manages the step size for both solvers by using the minimum of the maximum step size obtained with CFL numbers cfl_acoustics for the acoustics solver and cfl_euler for and flow solver, respectively. The mean values for the acoustic perturbation equations are read from averaging_callback (see AveragingCallback).

source
Trixi.FDSBPType
FDSBP(D_SBP; surface_integral, volume_integral)

Specialization of DG methods that uses general summation by parts (SBP) operators from SummationByPartsOperators.jl. In particular, this includes classical finite difference (FD) SBP methods. These methods have the same structure as classical DG methods - local operations on elements with connectivity through interfaces without imposing any continuity constraints.

D_SBP is an SBP derivative operator from SummationByPartsOperators.jl. The other arguments have the same meaning as in DG or DGSEM.

Experimental implementation (upwind SBP)

This is an experimental feature and may change in future releases.

source
Trixi.FluxHLLType
FluxHLL(min_max_speed=min_max_speed_naive)

Create an HLL (Harten, Lax, van Leer) numerical flux where the minimum and maximum wave speeds are estimated as λ_min, λ_max = min_max_speed(u_ll, u_rr, orientation_or_normal_direction, equations), defaulting to min_max_speed_naive. Original paper:

  • Amiram Harten, Peter D. Lax, Bram van Leer (1983) On Upstream Differencing and Godunov-Type Schemes for Hyperbolic Conservation Laws DOI: 10.1137/1025002
source
Trixi.FluxHydrostaticReconstructionType
FluxHydrostaticReconstruction(numerical_flux, hydrostatic_reconstruction)
Experimental code

This numerical flux is experimental and may change in any future release.

Allow for some kind of hydrostatic reconstruction of the solution state prior to the surface flux computation. This is a particular strategy to ensure that the method remains well-balanced for the shallow water equations, see ShallowWaterEquations1D or ShallowWaterEquations2D.

For example, the hydrostatic reconstruction from Audusse et al. is implemented in one and two spatial dimensions, see hydrostatic_reconstruction_audusse_etal or the original paper

  • Emmanuel Audusse, François Bouchut, Marie-Odile Bristeau, Rupert Klein, and Benoit Perthame (2004) A fast and stable well-balanced scheme with hydrostatic reconstruction for shallow water flows DOI: 10.1137/S1064827503431090

Other hydrostatic reconstruction techniques are available, particularly to handle wet / dry fronts. A good overview of the development and application of hydrostatic reconstruction can be found in

  • Guoxian Chen and Sebastian Noelle A unified surface-gradient and hydrostatic reconstruction scheme for the shallow water equations (2021) RWTH Aachen preprint
  • Andreas Buttinger-Kreuzhuber, Zsolt Horváth, Sebastian Noelle, Günter Blöschl and Jürgen Waser (2019) A fast second-order shallow water scheme on two-dimensional structured grids over abrupt topography DOI: 10.1016/j.advwatres.2019.03.010
source
Trixi.FluxLMARSType
FluxLMARS(c)(u_ll, u_rr, orientation_or_normal_direction,
-             equations::CompressibleEulerEquations3D)

Low Mach number approximate Riemann solver (LMARS) for atmospheric flows using an estimate c of the speed of sound.

References:

  • Xi Chen et al. (2013) A Control-Volume Model of the Compressible Euler Equations with a Vertical Lagrangian Coordinate DOI: 10.1175/MWR-D-12-00129.1
source
Trixi.FluxPlusDissipationType
FluxPlusDissipation(numerical_flux, dissipation)

Combine a numerical_flux with a dissipation operator to create a new numerical flux.

source
Trixi.FluxRotatedType
FluxRotated(numerical_flux)

Compute a numerical_flux flux in direction of a normal vector by rotating the solution, computing the numerical flux in x-direction, and rotating the calculated flux back.

Requires a rotationally invariant equation with equation-specific functions rotate_to_x and rotate_from_x.

source
Trixi.FluxUpwindType
FluxUpwind(splitting)

A numerical flux f(u_left, u_right) = f⁺(u_left) + f⁻(u_right) based on flux vector splitting.

The SurfaceIntegralUpwind with a given splitting is equivalent to the SurfaceIntegralStrongForm with FluxUpwind(splitting) as numerical flux (up to floating point differences).

Experimental implementation (upwind SBP)

This is an experimental feature and may change in future releases.

source
Trixi.GlmSpeedCallbackType
GlmSpeedCallback(; glm_scale=0.5, cfl)

Update the divergence cleaning wave speed c_h according to the time step computed in StepsizeCallback for the ideal GLM-MHD equations. The cfl number should be set to the same value as for the time step size calculation. The glm_scale ensures that the GLM wave speed is lower than the fastest physical waves in the MHD solution and should thus be set to a value within the interval [0,1]. Note that glm_scale = 0 deactivates the divergence cleaning.

source
Trixi.GradientVariablesPrimitiveType
Experimental code

This code is experimental and may be changed or removed in any future release.

GradientVariablesPrimitive and GradientVariablesEntropy are gradient variable type parameters for CompressibleNavierStokesDiffusion1D. By default, the gradient variables are set to be GradientVariablesPrimitive. Specifying GradientVariablesEntropy instead uses the entropy variable formulation from

  • Hughes, Mallet, Franca (1986) A new finite element formulation for computational fluid dynamics: I. Symmetric forms of the compressible Euler and Navier-Stokes equations and the second law of thermodynamics. https://doi.org/10.1016/0045-7825(86)90127-1

Under GradientVariablesEntropy, the Navier-Stokes discretization is provably entropy stable.

source
Trixi.HypDiffN3Erk3Sstar52Type
HypDiffN3Erk3Sstar52()

Five stage, second-order accurate explicit Runge-Kutta scheme with stability region optimized for the hyperbolic diffusion equation with LLF flux and polynomials of degree polydeg=3.

source
Trixi.HyperbolicDiffusionEquations1DType
HyperbolicDiffusionEquations1D

The linear hyperbolic diffusion equations in one space dimension. A description of this system can be found in Sec. 2.5 of the book

Further analysis can be found in the paper

source
Trixi.IdealGlmMhdEquations1DType
IdealGlmMhdEquations1D(gamma)

The ideal compressible GLM-MHD equations for an ideal gas with ratio of specific heats gamma in one space dimension.

Note

There is no divergence cleaning variable psi because the divergence-free constraint is satisfied trivially in one spatial dimension.

source
Trixi.IdealGlmMhdEquations2DType
IdealGlmMhdEquations2D(gamma)

The ideal compressible GLM-MHD equations for an ideal gas with ratio of specific heats gamma in two space dimensions.

source
Trixi.IdealGlmMhdEquations3DType
IdealGlmMhdEquations3D(gamma)

The ideal compressible GLM-MHD equations for an ideal gas with ratio of specific heats gamma in three space dimensions.

source
Trixi.IndicatorHennemannGassnerType
IndicatorHennemannGassner(equations::AbstractEquations, basis;
+                               alg, cfl_acoustics::Real, cfl_euler::Real; kwargs...)
Experimental code

This callback is experimental and may change in any future release.

Creates an EulerAcousticsCouplingCallback based on the pure flow ODEProblem given by ode_euler. Creates an integrator using the time integration method alg and the keyword arguments to solve ode_euler (consult the OrdinaryDiffEq documentation for further information). Manages the step size for both solvers by using the minimum of the maximum step size obtained with CFL numbers cfl_acoustics for the acoustics solver and cfl_euler for and flow solver, respectively. The mean values for the acoustic perturbation equations are read from averaging_callback (see AveragingCallback).

source
Trixi.FDSBPType
FDSBP(D_SBP; surface_integral, volume_integral)

Specialization of DG methods that uses general summation by parts (SBP) operators from SummationByPartsOperators.jl. In particular, this includes classical finite difference (FD) SBP methods. These methods have the same structure as classical DG methods - local operations on elements with connectivity through interfaces without imposing any continuity constraints.

D_SBP is an SBP derivative operator from SummationByPartsOperators.jl. The other arguments have the same meaning as in DG or DGSEM.

Experimental implementation (upwind SBP)

This is an experimental feature and may change in future releases.

source
Trixi.FluxHLLType
FluxHLL(min_max_speed=min_max_speed_naive)

Create an HLL (Harten, Lax, van Leer) numerical flux where the minimum and maximum wave speeds are estimated as λ_min, λ_max = min_max_speed(u_ll, u_rr, orientation_or_normal_direction, equations), defaulting to min_max_speed_naive. Original paper:

  • Amiram Harten, Peter D. Lax, Bram van Leer (1983) On Upstream Differencing and Godunov-Type Schemes for Hyperbolic Conservation Laws DOI: 10.1137/1025002
source
Trixi.FluxHydrostaticReconstructionType
FluxHydrostaticReconstruction(numerical_flux, hydrostatic_reconstruction)
Experimental code

This numerical flux is experimental and may change in any future release.

Allow for some kind of hydrostatic reconstruction of the solution state prior to the surface flux computation. This is a particular strategy to ensure that the method remains well-balanced for the shallow water equations, see ShallowWaterEquations1D or ShallowWaterEquations2D.

For example, the hydrostatic reconstruction from Audusse et al. is implemented in one and two spatial dimensions, see hydrostatic_reconstruction_audusse_etal or the original paper

  • Emmanuel Audusse, François Bouchut, Marie-Odile Bristeau, Rupert Klein, and Benoit Perthame (2004) A fast and stable well-balanced scheme with hydrostatic reconstruction for shallow water flows DOI: 10.1137/S1064827503431090

Other hydrostatic reconstruction techniques are available, particularly to handle wet / dry fronts. A good overview of the development and application of hydrostatic reconstruction can be found in

  • Guoxian Chen and Sebastian Noelle A unified surface-gradient and hydrostatic reconstruction scheme for the shallow water equations (2021) RWTH Aachen preprint
  • Andreas Buttinger-Kreuzhuber, Zsolt Horváth, Sebastian Noelle, Günter Blöschl and Jürgen Waser (2019) A fast second-order shallow water scheme on two-dimensional structured grids over abrupt topography DOI: 10.1016/j.advwatres.2019.03.010
source
Trixi.FluxLMARSType
FluxLMARS(c)(u_ll, u_rr, orientation_or_normal_direction,
+             equations::CompressibleEulerEquations3D)

Low Mach number approximate Riemann solver (LMARS) for atmospheric flows using an estimate c of the speed of sound.

References:

  • Xi Chen et al. (2013) A Control-Volume Model of the Compressible Euler Equations with a Vertical Lagrangian Coordinate DOI: 10.1175/MWR-D-12-00129.1
source
Trixi.FluxPlusDissipationType
FluxPlusDissipation(numerical_flux, dissipation)

Combine a numerical_flux with a dissipation operator to create a new numerical flux.

source
Trixi.FluxRotatedType
FluxRotated(numerical_flux)

Compute a numerical_flux flux in direction of a normal vector by rotating the solution, computing the numerical flux in x-direction, and rotating the calculated flux back.

Requires a rotationally invariant equation with equation-specific functions rotate_to_x and rotate_from_x.

source
Trixi.FluxUpwindType
FluxUpwind(splitting)

A numerical flux f(u_left, u_right) = f⁺(u_left) + f⁻(u_right) based on flux vector splitting.

The SurfaceIntegralUpwind with a given splitting is equivalent to the SurfaceIntegralStrongForm with FluxUpwind(splitting) as numerical flux (up to floating point differences).

Experimental implementation (upwind SBP)

This is an experimental feature and may change in future releases.

source
Trixi.GlmSpeedCallbackType
GlmSpeedCallback(; glm_scale=0.5, cfl)

Update the divergence cleaning wave speed c_h according to the time step computed in StepsizeCallback for the ideal GLM-MHD equations. The cfl number should be set to the same value as for the time step size calculation. The glm_scale ensures that the GLM wave speed is lower than the fastest physical waves in the MHD solution and should thus be set to a value within the interval [0,1]. Note that glm_scale = 0 deactivates the divergence cleaning.

source
Trixi.GradientVariablesPrimitiveType
Experimental code

This code is experimental and may be changed or removed in any future release.

GradientVariablesPrimitive and GradientVariablesEntropy are gradient variable type parameters for CompressibleNavierStokesDiffusion1D. By default, the gradient variables are set to be GradientVariablesPrimitive. Specifying GradientVariablesEntropy instead uses the entropy variable formulation from

  • Hughes, Mallet, Franca (1986) A new finite element formulation for computational fluid dynamics: I. Symmetric forms of the compressible Euler and Navier-Stokes equations and the second law of thermodynamics. https://doi.org/10.1016/0045-7825(86)90127-1

Under GradientVariablesEntropy, the Navier-Stokes discretization is provably entropy stable.

source
Trixi.HypDiffN3Erk3Sstar52Type
HypDiffN3Erk3Sstar52()

Five stage, second-order accurate explicit Runge-Kutta scheme with stability region optimized for the hyperbolic diffusion equation with LLF flux and polynomials of degree polydeg=3.

source
Trixi.HyperbolicDiffusionEquations1DType
HyperbolicDiffusionEquations1D

The linear hyperbolic diffusion equations in one space dimension. A description of this system can be found in Sec. 2.5 of the book

Further analysis can be found in the paper

source
Trixi.IdealGlmMhdEquations1DType
IdealGlmMhdEquations1D(gamma)

The ideal compressible GLM-MHD equations for an ideal gas with ratio of specific heats gamma in one space dimension.

Note

There is no divergence cleaning variable psi because the divergence-free constraint is satisfied trivially in one spatial dimension.

source
Trixi.IdealGlmMhdEquations2DType
IdealGlmMhdEquations2D(gamma)

The ideal compressible GLM-MHD equations for an ideal gas with ratio of specific heats gamma in two space dimensions.

source
Trixi.IdealGlmMhdEquations3DType
IdealGlmMhdEquations3D(gamma)

The ideal compressible GLM-MHD equations for an ideal gas with ratio of specific heats gamma in three space dimensions.

source
Trixi.IndicatorHennemannGassnerType
IndicatorHennemannGassner(equations::AbstractEquations, basis;
                           alpha_max=0.5,
                           alpha_min=0.001,
                           alpha_smooth=true,
@@ -190,24 +190,24 @@
                           alpha_max=0.5,
                           alpha_min=0.001,
                           alpha_smooth=true,
-                          variable)

Indicator used for shock-capturing (when passing the equations and the basis) or adaptive mesh refinement (AMR, when passing the semi).

See also VolumeIntegralShockCapturingHG.

References

  • Hennemann, Gassner (2020) "A provably entropy stable subcell shock capturing approach for high order split form DG" arXiv: 2008.12044
source
Trixi.IndicatorHennemannGassnerShallowWaterType
IndicatorHennemannGassnerShallowWater(equations::AbstractEquations, basis;
                                       alpha_max=0.5,
                                       alpha_min=0.001,
                                       alpha_smooth=true,
-                                      variable)

Modified version of the IndicatorHennemannGassner indicator used for shock-capturing for shallow water equations. After the element-wise values for the blending factors are computed an additional check is made to see if the element is partially wet. In this case, partially wet elements are set to use the pure finite volume scheme that is guaranteed to be well-balanced for this wet/dry transition state of the flow regime.

See also VolumeIntegralShockCapturingHG.

References

  • Hennemann, Gassner (2020) "A provably entropy stable subcell shock capturing approach for high order split form DG" arXiv: 2008.12044
source
Trixi.IndicatorLöhnerType
IndicatorLöhner (equivalent to IndicatorLoehner)
+                                      variable)

Modified version of the IndicatorHennemannGassner indicator used for shock-capturing for shallow water equations. After the element-wise values for the blending factors are computed an additional check is made to see if the element is partially wet. In this case, partially wet elements are set to use the pure finite volume scheme that is guaranteed to be well-balanced for this wet/dry transition state of the flow regime.

See also VolumeIntegralShockCapturingHG.

References

  • Hennemann, Gassner (2020) "A provably entropy stable subcell shock capturing approach for high order split form DG" arXiv: 2008.12044
source
Trixi.IndicatorLöhnerType
IndicatorLöhner (equivalent to IndicatorLoehner)
 
 IndicatorLöhner(equations::AbstractEquations, basis;
                 f_wave=0.2, variable)
 IndicatorLöhner(semi::AbstractSemidiscretization;
-                f_wave=0.2, variable)

AMR indicator adapted from a FEM indicator by Löhner (1987), also used in the FLASH code as standard AMR indicator. The indicator estimates a weighted second derivative of a specified variable locally.

When constructed to be used for AMR, pass the semi. Pass the equations, and basis if this indicator should be used for shock capturing.

References

source
Trixi.IndicatorMaxType
IndicatorMax(equations::AbstractEquations, basis; variable)
-IndicatorMax(semi::AbstractSemidiscretization; variable)

A simple indicator returning the maximum of variable in an element. When constructed to be used for AMR, pass the semi. Pass the equations, and basis if this indicator should be used for shock capturing.

source
Trixi.IndicatorNeuralNetworkType
IndicatorNeuralNetwork

Artificial neural network based indicator used for shock-capturing or AMR. Depending on the indicator_type, different input values and corresponding trained networks are used.

indicator_type = NeuralNetworkPerssonPeraire()

  • Input: The energies in lower modes as well as nnodes(dg).

indicator_type = NeuralNetworkRayHesthaven()

  • 1d Input: Cell average of the cell and its neighboring cells as well as the interface values.

  • 2d Input: Linear modal values of the cell and its neighboring cells.

  • Ray, Hesthaven (2018) "An artificial neural network as a troubled-cell indicator" doi:10.1016/j.jcp.2018.04.029

  • Ray, Hesthaven (2019) "Detecting troubled-cells on two-dimensional unstructured grids using a neural network" doi:10.1016/j.jcp.2019.07.043

indicator_type = CNN (Only in 2d)

  • Based on convolutional neural network.
  • 2d Input: Interpolation of the nodal values of the indicator.variable to the 4x4 LGL nodes.

If alpha_continuous == true the continuous network output for troubled cells (alpha > 0.5) is considered. If the cells are good (alpha < 0.5), alpha is set to 0. If alpha_continuous == false, the blending factor is set to alpha = 0 for good cells and alpha = 1 for troubled cells.

Experimental implementation

This is an experimental feature and may change in future releases.

source
Trixi.IsothermalType
struct Isothermal

Used to create a no-slip boundary condition with BoundaryConditionNavierStokesWall. The field boundary_value_function should be a function with signature boundary_value_function(x, t, equations) and return a scalar value for the temperature at point x and time t.

source
Trixi.LaplaceDiffusion1DType
LaplaceDiffusion1D(diffusivity, equations)

LaplaceDiffusion1D represents a scalar diffusion term $\nabla \cdot (\kappa\nabla u))$ with diffusivity $\kappa$ applied to each solution component defined by equations.

source
Trixi.LaplaceDiffusion2DType
LaplaceDiffusion2D(diffusivity, equations)

LaplaceDiffusion2D represents a scalar diffusion term $\nabla \cdot (\kappa\nabla u))$ with diffusivity $\kappa$ applied to each solution component defined by equations.

source
Trixi.LaplaceDiffusion3DType
LaplaceDiffusion3D(diffusivity, equations)

LaplaceDiffusion3D represents a scalar diffusion term $\nabla \cdot (\kappa\nabla u))$ with diffusivity $\kappa$ applied to each solution component defined by equations.

source
Trixi.LatticeBoltzmannEquations2DType
LatticeBoltzmannEquations2D(; Ma, Re, collision_op=collision_bgk,
+                f_wave=0.2, variable)

AMR indicator adapted from a FEM indicator by Löhner (1987), also used in the FLASH code as standard AMR indicator. The indicator estimates a weighted second derivative of a specified variable locally.

When constructed to be used for AMR, pass the semi. Pass the equations, and basis if this indicator should be used for shock capturing.

References

source
Trixi.IndicatorMaxType
IndicatorMax(equations::AbstractEquations, basis; variable)
+IndicatorMax(semi::AbstractSemidiscretization; variable)

A simple indicator returning the maximum of variable in an element. When constructed to be used for AMR, pass the semi. Pass the equations, and basis if this indicator should be used for shock capturing.

source
Trixi.IndicatorNeuralNetworkType
IndicatorNeuralNetwork

Artificial neural network based indicator used for shock-capturing or AMR. Depending on the indicator_type, different input values and corresponding trained networks are used.

indicator_type = NeuralNetworkPerssonPeraire()

  • Input: The energies in lower modes as well as nnodes(dg).

indicator_type = NeuralNetworkRayHesthaven()

  • 1d Input: Cell average of the cell and its neighboring cells as well as the interface values.

  • 2d Input: Linear modal values of the cell and its neighboring cells.

  • Ray, Hesthaven (2018) "An artificial neural network as a troubled-cell indicator" doi:10.1016/j.jcp.2018.04.029

  • Ray, Hesthaven (2019) "Detecting troubled-cells on two-dimensional unstructured grids using a neural network" doi:10.1016/j.jcp.2019.07.043

indicator_type = CNN (Only in 2d)

  • Based on convolutional neural network.
  • 2d Input: Interpolation of the nodal values of the indicator.variable to the 4x4 LGL nodes.

If alpha_continuous == true the continuous network output for troubled cells (alpha > 0.5) is considered. If the cells are good (alpha < 0.5), alpha is set to 0. If alpha_continuous == false, the blending factor is set to alpha = 0 for good cells and alpha = 1 for troubled cells.

Experimental implementation

This is an experimental feature and may change in future releases.

source
Trixi.IsothermalType
struct Isothermal

Used to create a no-slip boundary condition with BoundaryConditionNavierStokesWall. The field boundary_value_function should be a function with signature boundary_value_function(x, t, equations) and return a scalar value for the temperature at point x and time t.

source
Trixi.LaplaceDiffusion1DType
LaplaceDiffusion1D(diffusivity, equations)

LaplaceDiffusion1D represents a scalar diffusion term $\nabla \cdot (\kappa\nabla u))$ with diffusivity $\kappa$ applied to each solution component defined by equations.

source
Trixi.LaplaceDiffusion2DType
LaplaceDiffusion2D(diffusivity, equations)

LaplaceDiffusion2D represents a scalar diffusion term $\nabla \cdot (\kappa\nabla u))$ with diffusivity $\kappa$ applied to each solution component defined by equations.

source
Trixi.LaplaceDiffusion3DType
LaplaceDiffusion3D(diffusivity, equations)

LaplaceDiffusion3D represents a scalar diffusion term $\nabla \cdot (\kappa\nabla u))$ with diffusivity $\kappa$ applied to each solution component defined by equations.

source
Trixi.LatticeBoltzmannEquations2DType
LatticeBoltzmannEquations2D(; Ma, Re, collision_op=collision_bgk,
                            c=1, L=1, rho0=1, u0=nothing, nu=nothing)

The Lattice-Boltzmann equations

\[\partial_t u_\alpha + v_{\alpha,1} \partial_1 u_\alpha + v_{\alpha,2} \partial_2 u_\alpha = 0\]

in two space dimensions for the D2Q9 scheme.

The characteristic Mach number and Reynolds numbers are specified as Ma and Re. By the default, the collision operator collision_op is set to the BGK model. c, L, and rho0 specify the mean thermal molecular velocity, the characteristic length, and the reference density, respectively. They can usually be left to the default values. If desired, instead of the Mach number, one can set the macroscopic reference velocity u0 directly (Ma needs to be set to nothing in this case). Likewise, instead of the Reynolds number one can specify the kinematic viscosity nu directly (in this case, Re needs to be set to nothing).

The nine discrete velocity directions of the D2Q9 scheme are sorted as follows [4]:

  6     2     5       y
     ┌───┼───┐         │
     │       │         │
   3 ┼   9   ┼ 1        ──── x
     │       │        ╱
     └───┼───┘       ╱
-  7     4     8    z

Note that usually the velocities are numbered from 0 to 8, where 0 corresponds to the zero velocity. Due to Julia using 1-based indexing, here we use indices from 1 to 9, where 1 through 8 correspond to the velocity directions in [4] and 9 is the zero velocity.

The corresponding opposite directions are:

  • 1 ←→ 3
  • 2 ←→ 4
  • 3 ←→ 1
  • 4 ←→ 2
  • 5 ←→ 7
  • 6 ←→ 8
  • 7 ←→ 5
  • 8 ←→ 6
  • 9 ←→ 9

The main sources for the base implementation were

  1. Misun Min, Taehun Lee, A spectral-element discontinuous Galerkin lattice Boltzmann method for nearly incompressible flows, J Comput Phys 230(1), 2011 doi:10.1016/j.jcp.2010.09.024
  2. Karsten Golly, Anwendung der Lattice-Boltzmann Discontinuous Galerkin Spectral Element Method (LB-DGSEM) auf laminare und turbulente nahezu inkompressible Strömungen im dreidimensionalen Raum, Master Thesis, University of Cologne, 2018.
  3. Dieter Hänel, Molekulare Gasdynamik, Springer-Verlag Berlin Heidelberg, 2004 doi:10.1007/3-540-35047-0
  4. Dieter Krüger et al., The Lattice Boltzmann Method, Springer International Publishing, 2017 doi:10.1007/978-3-319-44649-3
source
Trixi.LatticeBoltzmannEquations3DType
LatticeBoltzmannEquations3D(; Ma, Re, collision_op=collision_bgk,
+  7     4     8    z

Note that usually the velocities are numbered from 0 to 8, where 0 corresponds to the zero velocity. Due to Julia using 1-based indexing, here we use indices from 1 to 9, where 1 through 8 correspond to the velocity directions in [4] and 9 is the zero velocity.

The corresponding opposite directions are:

  • 1 ←→ 3
  • 2 ←→ 4
  • 3 ←→ 1
  • 4 ←→ 2
  • 5 ←→ 7
  • 6 ←→ 8
  • 7 ←→ 5
  • 8 ←→ 6
  • 9 ←→ 9

The main sources for the base implementation were

  1. Misun Min, Taehun Lee, A spectral-element discontinuous Galerkin lattice Boltzmann method for nearly incompressible flows, J Comput Phys 230(1), 2011 doi:10.1016/j.jcp.2010.09.024
  2. Karsten Golly, Anwendung der Lattice-Boltzmann Discontinuous Galerkin Spectral Element Method (LB-DGSEM) auf laminare und turbulente nahezu inkompressible Strömungen im dreidimensionalen Raum, Master Thesis, University of Cologne, 2018.
  3. Dieter Hänel, Molekulare Gasdynamik, Springer-Verlag Berlin Heidelberg, 2004 doi:10.1007/3-540-35047-0
  4. Dieter Krüger et al., The Lattice Boltzmann Method, Springer International Publishing, 2017 doi:10.1007/978-3-319-44649-3
source
Trixi.LatticeBoltzmannEquations3DType
LatticeBoltzmannEquations3D(; Ma, Re, collision_op=collision_bgk,
                            c=1, L=1, rho0=1, u0=nothing, nu=nothing)

The Lattice-Boltzmann equations

\[\partial_t u_\alpha + v_{\alpha,1} \partial_1 u_\alpha + v_{\alpha,2} \partial_2 u_\alpha + v_{\alpha,3} \partial_3 u_\alpha = 0\]

in three space dimensions for the D3Q27 scheme.

The characteristic Mach number and Reynolds numbers are specified as Ma and Re. By the default, the collision operator collision_op is set to the BGK model. c, L, and rho0 specify the mean thermal molecular velocity, the characteristic length, and the reference density, respectively. They can usually be left to the default values. If desired, instead of the Mach number, one can set the macroscopic reference velocity u0 directly (Ma needs to be set to nothing in this case). Likewise, instead of the Reynolds number one can specify the kinematic viscosity nu directly (in this case, Re needs to be set to nothing).

The twenty-seven discrete velocity directions of the D3Q27 scheme are sorted as follows [4]:

  • plane at z = -1:
      24    17     21       y
          ┌───┼───┐          │
          │       │          │
    @@ -226,7 +226,7 @@
       16 ┼   5   ┼ 9         ──── x
          │       │         ╱
          └───┼───┘        ╱
    -  22    18     23    z

Note that usually the velocities are numbered from 0 to 26, where 0 corresponds to the zero velocity. Due to Julia using 1-based indexing, here we use indices from 1 to 27, where 1 through 26 correspond to the velocity directions in [4] and 27 is the zero velocity.

The corresponding opposite directions are:

  • 1 ←→ 2
  • 2 ←→ 1
  • 3 ←→ 4
  • 4 ←→ 3
  • 5 ←→ 6
  • 6 ←→ 5
  • 7 ←→ 8
  • 8 ←→ 7
  • 9 ←→ 10
  • 10 ←→ 9
  • 11 ←→ 12
  • 12 ←→ 11
  • 13 ←→ 14
  • 14 ←→ 13
  • 15 ←→ 16
  • 16 ←→ 15
  • 17 ←→ 18
  • 18 ←→ 17
  • 19 ←→ 20
  • 20 ←→ 19
  • 21 ←→ 22
  • 22 ←→ 21
  • 23 ←→ 24
  • 24 ←→ 23
  • 25 ←→ 26
  • 26 ←→ 25
  • 27 ←→ 27

The main sources for the base implementation were

  1. Misun Min, Taehun Lee, A spectral-element discontinuous Galerkin lattice Boltzmann method for nearly incompressible flows, J Comput Phys 230(1), 2011 doi:10.1016/j.jcp.2010.09.024
  2. Karsten Golly, Anwendung der Lattice-Boltzmann Discontinuous Galerkin Spectral Element Method (LB-DGSEM) auf laminare und turbulente nahezu inkompressible Strömungen im dreidimensionalen Raum, Master Thesis, University of Cologne, 2018.
  3. Dieter Hänel, Molekulare Gasdynamik, Springer-Verlag Berlin Heidelberg, 2004 doi:10.1007/3-540-35047-0
  4. Dieter Krüger et al., The Lattice Boltzmann Method, Springer International Publishing, 2017 doi:10.1007/978-3-319-44649-3
source
Trixi.LinearScalarAdvectionEquation2DType
LinearScalarAdvectionEquation2D

The linear scalar advection equation

\[\partial_t u + a_1 \partial_1 u + a_2 \partial_2 u = 0\]

in two space dimensions with constant velocity a.

source
Trixi.LinearScalarAdvectionEquation3DType
LinearScalarAdvectionEquation3D

The linear scalar advection equation

\[\partial_t u + a_1 \partial_1 u + a_2 \partial_2 u + a_3 \partial_3 u = 0\]

in three space dimensions with constant velocity a.

source
Trixi.LinearizedEulerEquations2DType
LinearizedEulerEquations2D(v_mean_global, c_mean_global, rho_mean_global)

Linearized euler equations in two space dimensions. The equations are given by

\[\partial_t + 22 18 23 z

Note that usually the velocities are numbered from 0 to 26, where 0 corresponds to the zero velocity. Due to Julia using 1-based indexing, here we use indices from 1 to 27, where 1 through 26 correspond to the velocity directions in [4] and 27 is the zero velocity.

The corresponding opposite directions are:

  • 1 ←→ 2
  • 2 ←→ 1
  • 3 ←→ 4
  • 4 ←→ 3
  • 5 ←→ 6
  • 6 ←→ 5
  • 7 ←→ 8
  • 8 ←→ 7
  • 9 ←→ 10
  • 10 ←→ 9
  • 11 ←→ 12
  • 12 ←→ 11
  • 13 ←→ 14
  • 14 ←→ 13
  • 15 ←→ 16
  • 16 ←→ 15
  • 17 ←→ 18
  • 18 ←→ 17
  • 19 ←→ 20
  • 20 ←→ 19
  • 21 ←→ 22
  • 22 ←→ 21
  • 23 ←→ 24
  • 24 ←→ 23
  • 25 ←→ 26
  • 26 ←→ 25
  • 27 ←→ 27

The main sources for the base implementation were

  1. Misun Min, Taehun Lee, A spectral-element discontinuous Galerkin lattice Boltzmann method for nearly incompressible flows, J Comput Phys 230(1), 2011 doi:10.1016/j.jcp.2010.09.024
  2. Karsten Golly, Anwendung der Lattice-Boltzmann Discontinuous Galerkin Spectral Element Method (LB-DGSEM) auf laminare und turbulente nahezu inkompressible Strömungen im dreidimensionalen Raum, Master Thesis, University of Cologne, 2018.
  3. Dieter Hänel, Molekulare Gasdynamik, Springer-Verlag Berlin Heidelberg, 2004 doi:10.1007/3-540-35047-0
  4. Dieter Krüger et al., The Lattice Boltzmann Method, Springer International Publishing, 2017 doi:10.1007/978-3-319-44649-3
source
Trixi.LinearScalarAdvectionEquation2DType
LinearScalarAdvectionEquation2D

The linear scalar advection equation

\[\partial_t u + a_1 \partial_1 u + a_2 \partial_2 u = 0\]

in two space dimensions with constant velocity a.

source
Trixi.LinearScalarAdvectionEquation3DType
LinearScalarAdvectionEquation3D

The linear scalar advection equation

\[\partial_t u + a_1 \partial_1 u + a_2 \partial_2 u + a_3 \partial_3 u = 0\]

in three space dimensions with constant velocity a.

source
Trixi.LinearizedEulerEquations2DType
LinearizedEulerEquations2D(v_mean_global, c_mean_global, rho_mean_global)

Linearized euler equations in two space dimensions. The equations are given by

\[\partial_t \begin{pmatrix} \rho' \\ v_1' \\ v_2' \\ p' \end{pmatrix} @@ -243,19 +243,19 @@ = \begin{pmatrix} 0 \\ 0 \\ 0 \\ 0 -\end{pmatrix}\]

The bar $\bar{(\cdot)}$ indicates uniform mean flow variables and c is the speed of sound. The unknowns are the acoustic velocities $v' = (v_1', v_2')$, the pressure $p'$ and the density $\rho'$.

source
Trixi.LobattoLegendreBasisType
LobattoLegendreBasis([RealT=Float64,] polydeg::Integer)

Create a nodal Lobatto-Legendre basis for polynomials of degree polydeg.

For the special case polydeg=0 the DG method reduces to a finite volume method. Therefore, this function sets the center point of the cell as single node.

source
Trixi.NoSlipType
struct NoSlip

Use to create a no-slip boundary condition with BoundaryConditionNavierStokesWall. The field boundary_value_function should be a function with signature boundary_value_function(x, t, equations) and should return a SVector{NDIMS} whose entries are the velocity vector at a point x and time t.

source
Trixi.NonConservativeLocalType
NonConservativeLocal()

Struct used for multiple dispatch on non-conservative flux functions in the format of "local * symmetric". When the argument nonconservative_type is of type NonConservativeLocal, the function returns the local part of the non-conservative term.

source
Trixi.NonConservativeSymmetricType
NonConservativeSymmetric()

Struct used for multiple dispatch on non-conservative flux functions in the format of "local * symmetric". When the argument nonconservative_type is of type NonConservativeSymmetric, the function returns the symmetric part of the non-conservative term.

source
Trixi.P4estMeshType
P4estMesh{NDIMS} <: AbstractMesh{NDIMS}

An unstructured curved mesh based on trees that uses the C library p4est to manage trees and mesh refinement.

source
Trixi.P4estMeshMethod
P4estMesh(trees_per_dimension; polydeg,
+\end{pmatrix}\]

The bar $\bar{(\cdot)}$ indicates uniform mean flow variables and c is the speed of sound. The unknowns are the acoustic velocities $v' = (v_1', v_2')$, the pressure $p'$ and the density $\rho'$.

source
Trixi.LobattoLegendreBasisType
LobattoLegendreBasis([RealT=Float64,] polydeg::Integer)

Create a nodal Lobatto-Legendre basis for polynomials of degree polydeg.

For the special case polydeg=0 the DG method reduces to a finite volume method. Therefore, this function sets the center point of the cell as single node.

source
Trixi.NoSlipType
struct NoSlip

Use to create a no-slip boundary condition with BoundaryConditionNavierStokesWall. The field boundary_value_function should be a function with signature boundary_value_function(x, t, equations) and should return a SVector{NDIMS} whose entries are the velocity vector at a point x and time t.

source
Trixi.NonConservativeLocalType
NonConservativeLocal()

Struct used for multiple dispatch on non-conservative flux functions in the format of "local * symmetric". When the argument nonconservative_type is of type NonConservativeLocal, the function returns the local part of the non-conservative term.

source
Trixi.NonConservativeSymmetricType
NonConservativeSymmetric()

Struct used for multiple dispatch on non-conservative flux functions in the format of "local * symmetric". When the argument nonconservative_type is of type NonConservativeSymmetric, the function returns the symmetric part of the non-conservative term.

source
Trixi.P4estMeshType
P4estMesh{NDIMS} <: AbstractMesh{NDIMS}

An unstructured curved mesh based on trees that uses the C library p4est to manage trees and mesh refinement.

source
Trixi.P4estMeshMethod
P4estMesh(trees_per_dimension; polydeg,
           mapping=nothing, faces=nothing, coordinates_min=nothing, coordinates_max=nothing,
           RealT=Float64, initial_refinement_level=0, periodicity=true, unsaved_changes=true,
-          p4est_partition_allow_for_coarsening=true)

Create a structured curved P4estMesh of the specified size.

There are three ways to map the mesh to the physical domain.

  1. Define a mapping that maps the hypercube [-1, 1]^n.
  2. Specify a Tuple faces of functions that parametrize each face.
  3. Create a rectangular mesh by specifying coordinates_min and coordinates_max.

Non-periodic boundaries will be called :x_neg, :x_pos, :y_neg, :y_pos, :z_neg, :z_pos.

Arguments

  • trees_per_dimension::NTupleE{NDIMS, Int}: the number of trees in each dimension.
  • polydeg::Integer: polynomial degree used to store the geometry of the mesh. The mapping will be approximated by an interpolation polynomial of the specified degree for each tree.
  • mapping: a function of NDIMS variables to describe the mapping that transforms the reference mesh ([-1, 1]^n) to the physical domain. Use only one of mapping, faces and coordinates_min/coordinates_max.
  • faces::NTuple{2*NDIMS}: a tuple of 2 * NDIMS functions that describe the faces of the domain. Each function must take NDIMS-1 arguments. faces[1] describes the face onto which the face in negative x-direction of the unit hypercube is mapped. The face in positive x-direction of the unit hypercube will be mapped onto the face described by faces[2]. faces[3:4] describe the faces in positive and negative y-direction respectively (in 2D and 3D). faces[5:6] describe the faces in positive and negative z-direction respectively (in 3D). Use only one of mapping, faces and coordinates_min/coordinates_max.
  • coordinates_min: vector or tuple of the coordinates of the corner in the negative direction of each dimension to create a rectangular mesh. Use only one of mapping, faces and coordinates_min/coordinates_max.
  • coordinates_max: vector or tuple of the coordinates of the corner in the positive direction of each dimension to create a rectangular mesh. Use only one of mapping, faces and coordinates_min/coordinates_max.
  • RealT::Type: the type that should be used for coordinates.
  • initial_refinement_level::Integer: refine the mesh uniformly to this level before the simulation starts.
  • periodicity: either a Bool deciding if all of the boundaries are periodic or an NTuple{NDIMS, Bool} deciding for each dimension if the boundaries in this dimension are periodic.
  • unsaved_changes::Bool: if set to true, the mesh will be saved to a mesh file.
  • p4est_partition_allow_for_coarsening::Bool: Must be true when using AMR to make mesh adaptivity independent of domain partitioning. Should be false for static meshes to permit more fine-grained partitioning.
source
Trixi.P4estMeshMethod
P4estMesh{NDIMS}(meshfile::String;
+          p4est_partition_allow_for_coarsening=true)

Create a structured curved P4estMesh of the specified size.

There are three ways to map the mesh to the physical domain.

  1. Define a mapping that maps the hypercube [-1, 1]^n.
  2. Specify a Tuple faces of functions that parametrize each face.
  3. Create a rectangular mesh by specifying coordinates_min and coordinates_max.

Non-periodic boundaries will be called :x_neg, :x_pos, :y_neg, :y_pos, :z_neg, :z_pos.

Arguments

  • trees_per_dimension::NTupleE{NDIMS, Int}: the number of trees in each dimension.
  • polydeg::Integer: polynomial degree used to store the geometry of the mesh. The mapping will be approximated by an interpolation polynomial of the specified degree for each tree.
  • mapping: a function of NDIMS variables to describe the mapping that transforms the reference mesh ([-1, 1]^n) to the physical domain. Use only one of mapping, faces and coordinates_min/coordinates_max.
  • faces::NTuple{2*NDIMS}: a tuple of 2 * NDIMS functions that describe the faces of the domain. Each function must take NDIMS-1 arguments. faces[1] describes the face onto which the face in negative x-direction of the unit hypercube is mapped. The face in positive x-direction of the unit hypercube will be mapped onto the face described by faces[2]. faces[3:4] describe the faces in positive and negative y-direction respectively (in 2D and 3D). faces[5:6] describe the faces in positive and negative z-direction respectively (in 3D). Use only one of mapping, faces and coordinates_min/coordinates_max.
  • coordinates_min: vector or tuple of the coordinates of the corner in the negative direction of each dimension to create a rectangular mesh. Use only one of mapping, faces and coordinates_min/coordinates_max.
  • coordinates_max: vector or tuple of the coordinates of the corner in the positive direction of each dimension to create a rectangular mesh. Use only one of mapping, faces and coordinates_min/coordinates_max.
  • RealT::Type: the type that should be used for coordinates.
  • initial_refinement_level::Integer: refine the mesh uniformly to this level before the simulation starts.
  • periodicity: either a Bool deciding if all of the boundaries are periodic or an NTuple{NDIMS, Bool} deciding for each dimension if the boundaries in this dimension are periodic.
  • unsaved_changes::Bool: if set to true, the mesh will be saved to a mesh file.
  • p4est_partition_allow_for_coarsening::Bool: Must be true when using AMR to make mesh adaptivity independent of domain partitioning. Should be false for static meshes to permit more fine-grained partitioning.
source
Trixi.P4estMeshMethod
P4estMesh{NDIMS}(meshfile::String;
                  mapping=nothing, polydeg=1, RealT=Float64,
                  initial_refinement_level=0, unsaved_changes=true,
-                 p4est_partition_allow_for_coarsening=true)

Main mesh constructor for the P4estMesh that imports an unstructured, conforming mesh from an Abaqus mesh file (.inp). Each element of the conforming mesh parsed from the meshfile is created as a p4est tree datatype.

To create a curved unstructured mesh P4estMesh two strategies are available:

  • p4est_mesh_from_hohqmesh_abaqus: High-order, curved boundary information created by HOHQMesh.jl is available in the meshfile. The mesh polynomial degree polydeg of the boundaries is provided from the meshfile. The computation of the mapped tree coordinates is done with transfinite interpolation with linear blending similar to UnstructuredMesh2D. Boundary name information is also parsed from the meshfile such that different boundary conditions can be set at each named boundary on a given tree.
  • p4est_mesh_from_standard_abaqus: By default, with mapping=nothing and polydeg=1, this creates a straight-sided from the information parsed from the meshfile. If a mapping function is specified then it computes the mapped tree coordinates via polynomial interpolants with degree polydeg. The mesh created by this function will only have one boundary :all, as distinguishing different physical boundaries is non-trivial.

Note that the mapping and polydeg keyword arguments are only used by the p4est_mesh_from_standard_abaqus function. The p4est_mesh_from_hohqmesh_abaqus function obtains the mesh polydeg directly from the meshfile and constructs the transfinite mapping internally.

The particular strategy is selected according to the header present in the meshfile where the constructor checks whether or not the meshfile was created with HOHQMesh.jl. If the Abaqus file header is not present in the meshfile then the P4estMesh is created with the function p4est_mesh_from_standard_abaqus.

The default keyword argument initial_refinement_level=0 corresponds to a forest where the number of trees is the same as the number of elements in the original meshfile. Increasing the initial_refinement_level allows one to uniformly refine the base mesh given in the meshfile to create a forest with more trees before the simulation begins. For example, if a two-dimensional base mesh contains 25 elements then setting initial_refinement_level=1 creates an initial forest of 2^2 * 25 = 100 trees.

Arguments

  • meshfile::String: an uncurved Abaqus mesh file that can be imported by p4est.
  • mapping: a function of NDIMS variables to describe the mapping that transforms the imported mesh to the physical domain. Use nothing for the identity map.
  • polydeg::Integer: polynomial degree used to store the geometry of the mesh. The mapping will be approximated by an interpolation polynomial of the specified degree for each tree. The default of 1 creates an uncurved geometry. Use a higher value if the mapping will curve the imported uncurved mesh.
  • RealT::Type: the type that should be used for coordinates.
  • initial_refinement_level::Integer: refine the mesh uniformly to this level before the simulation starts.
  • unsaved_changes::Bool: if set to true, the mesh will be saved to a mesh file.
  • p4est_partition_allow_for_coarsening::Bool: Must be true when using AMR to make mesh adaptivity independent of domain partitioning. Should be false for static meshes to permit more fine-grained partitioning.
source
Trixi.ParametersEulerGravityType
ParametersEulerGravity(; background_density=0.0,
+                 p4est_partition_allow_for_coarsening=true)

Main mesh constructor for the P4estMesh that imports an unstructured, conforming mesh from an Abaqus mesh file (.inp). Each element of the conforming mesh parsed from the meshfile is created as a p4est tree datatype.

To create a curved unstructured mesh P4estMesh two strategies are available:

  • p4est_mesh_from_hohqmesh_abaqus: High-order, curved boundary information created by HOHQMesh.jl is available in the meshfile. The mesh polynomial degree polydeg of the boundaries is provided from the meshfile. The computation of the mapped tree coordinates is done with transfinite interpolation with linear blending similar to UnstructuredMesh2D. Boundary name information is also parsed from the meshfile such that different boundary conditions can be set at each named boundary on a given tree.
  • p4est_mesh_from_standard_abaqus: By default, with mapping=nothing and polydeg=1, this creates a straight-sided from the information parsed from the meshfile. If a mapping function is specified then it computes the mapped tree coordinates via polynomial interpolants with degree polydeg. The mesh created by this function will only have one boundary :all, as distinguishing different physical boundaries is non-trivial.

Note that the mapping and polydeg keyword arguments are only used by the p4est_mesh_from_standard_abaqus function. The p4est_mesh_from_hohqmesh_abaqus function obtains the mesh polydeg directly from the meshfile and constructs the transfinite mapping internally.

The particular strategy is selected according to the header present in the meshfile where the constructor checks whether or not the meshfile was created with HOHQMesh.jl. If the Abaqus file header is not present in the meshfile then the P4estMesh is created with the function p4est_mesh_from_standard_abaqus.

The default keyword argument initial_refinement_level=0 corresponds to a forest where the number of trees is the same as the number of elements in the original meshfile. Increasing the initial_refinement_level allows one to uniformly refine the base mesh given in the meshfile to create a forest with more trees before the simulation begins. For example, if a two-dimensional base mesh contains 25 elements then setting initial_refinement_level=1 creates an initial forest of 2^2 * 25 = 100 trees.

Arguments

  • meshfile::String: an uncurved Abaqus mesh file that can be imported by p4est.
  • mapping: a function of NDIMS variables to describe the mapping that transforms the imported mesh to the physical domain. Use nothing for the identity map.
  • polydeg::Integer: polynomial degree used to store the geometry of the mesh. The mapping will be approximated by an interpolation polynomial of the specified degree for each tree. The default of 1 creates an uncurved geometry. Use a higher value if the mapping will curve the imported uncurved mesh.
  • RealT::Type: the type that should be used for coordinates.
  • initial_refinement_level::Integer: refine the mesh uniformly to this level before the simulation starts.
  • unsaved_changes::Bool: if set to true, the mesh will be saved to a mesh file.
  • p4est_partition_allow_for_coarsening::Bool: Must be true when using AMR to make mesh adaptivity independent of domain partitioning. Should be false for static meshes to permit more fine-grained partitioning.
source
Trixi.PerformanceCounterType
PerformanceCounter()

A PerformanceCounter can be used to track the runtime performance of some calls. Add a new runtime measurement via put!(counter, runtime) and get the averaged runtime of all measurements added so far via take!(counter), resetting the counter.

source
Trixi.PerformanceCounterListType
PerformanceCounterList{N}()

A PerformanceCounterList{N} can be used to track the runtime performance of calls to multiple functions, adding them up. Add a new runtime measurement via put!(counter.counters[i], runtime) and get the averaged runtime of all measurements added so far via take!(counter), resetting the counter.

source
Trixi.PlotData1DType
PlotData1D

Holds all relevant data for creating 1D plots of multiple solution variables and to visualize the mesh.

Experimental implementation

This is an experimental feature and may change in future releases.

source
Trixi.PlotData1DMethod
PlotData1D(u, semi [or mesh, equations, solver, cache];
-           solution_variables=nothing, nvisnodes=nothing)

Create a new PlotData1D object that can be used for visualizing 1D DGSEM solution data array u with Plots.jl. All relevant geometrical information is extracted from the semidiscretization semi. By default, the primitive variables (if existent) or the conservative variables (otherwise) from the solution are used for plotting. This can be changed by passing an appropriate conversion function to solution_variables.

nvisnodes specifies the number of visualization nodes to be used. If it is nothing, twice the number of solution DG nodes are used for visualization, and if set to 0, exactly the number of nodes in the DG elements are used.

When visualizing data from a two-dimensional simulation, a 1D slice is extracted for plotting. slice specifies the axis along which the slice is extracted and may be :x, or :y. The slice position is specified by a point that lies on it, which defaults to (0.0, 0.0). Both of these values are ignored when visualizing 1D data. This applies analogously to three-dimensional simulations, where slice may be :xy, :xz, or :yz.

Another way to visualize 2D/3D data is by creating a plot along a given curve. This is done with the keyword argument curve. It can be set to a list of 2D/3D points which define the curve. When using curve any other input from slice or point will be ignored.

Experimental implementation

This is an experimental feature and may change in future releases.

source
Trixi.PlotData1DMethod
PlotData1D(sol; kwargs...)

Create a PlotData1D object from a solution object created by either OrdinaryDiffEq.solve! (which returns a SciMLBase.ODESolution) or Trixi.jl's own solve! (which returns a TimeIntegratorSolution).

Experimental implementation

This is an experimental feature and may change in future releases.

source
Trixi.PlotData2DCartesianType
PlotData2D

Holds all relevant data for creating 2D plots of multiple solution variables and to visualize the mesh.

Experimental implementation

This is an experimental feature and may change in future releases.

source
Trixi.PerformanceCounterType
PerformanceCounter()

A PerformanceCounter can be used to track the runtime performance of some calls. Add a new runtime measurement via put!(counter, runtime) and get the averaged runtime of all measurements added so far via take!(counter), resetting the counter.

source
Trixi.PerformanceCounterListType
PerformanceCounterList{N}()

A PerformanceCounterList{N} can be used to track the runtime performance of calls to multiple functions, adding them up. Add a new runtime measurement via put!(counter.counters[i], runtime) and get the averaged runtime of all measurements added so far via take!(counter), resetting the counter.

source
Trixi.PlotData1DType
PlotData1D

Holds all relevant data for creating 1D plots of multiple solution variables and to visualize the mesh.

Experimental implementation

This is an experimental feature and may change in future releases.

source
Trixi.PlotData1DMethod
PlotData1D(u, semi [or mesh, equations, solver, cache];
+           solution_variables=nothing, nvisnodes=nothing)

Create a new PlotData1D object that can be used for visualizing 1D DGSEM solution data array u with Plots.jl. All relevant geometrical information is extracted from the semidiscretization semi. By default, the primitive variables (if existent) or the conservative variables (otherwise) from the solution are used for plotting. This can be changed by passing an appropriate conversion function to solution_variables.

nvisnodes specifies the number of visualization nodes to be used. If it is nothing, twice the number of solution DG nodes are used for visualization, and if set to 0, exactly the number of nodes in the DG elements are used.

When visualizing data from a two-dimensional simulation, a 1D slice is extracted for plotting. slice specifies the axis along which the slice is extracted and may be :x, or :y. The slice position is specified by a point that lies on it, which defaults to (0.0, 0.0). Both of these values are ignored when visualizing 1D data. This applies analogously to three-dimensional simulations, where slice may be :xy, :xz, or :yz.

Another way to visualize 2D/3D data is by creating a plot along a given curve. This is done with the keyword argument curve. It can be set to a list of 2D/3D points which define the curve. When using curve any other input from slice or point will be ignored.

Experimental implementation

This is an experimental feature and may change in future releases.

source
Trixi.PlotData1DMethod
PlotData1D(sol; kwargs...)

Create a PlotData1D object from a solution object created by either OrdinaryDiffEq.solve! (which returns a SciMLBase.ODESolution) or Trixi.jl's own solve! (which returns a TimeIntegratorSolution).

Experimental implementation

This is an experimental feature and may change in future releases.

source
Trixi.PlotData2DCartesianType
PlotData2D

Holds all relevant data for creating 2D plots of multiple solution variables and to visualize the mesh.

Experimental implementation

This is an experimental feature and may change in future releases.

source
Trixi.PolytropicEulerEquations2DType
PolytropicEulerEquations2D(gamma, kappa)

The polytropic Euler equations

\[\frac{\partial}{\partial t} \begin{pmatrix} \rho \\ \rho v_1 \\ \rho v_2 \end{pmatrix} @@ -272,41 +272,41 @@ = \begin{pmatrix} 0 \\ 0 \\ 0 -\end{pmatrix}\]

for an ideal gas with ratio of specific heats gamma in two space dimensions. Here, $\rho$ is the density and $v_1$ andv_2 the velocities and

\[p = \kappa\rho^\gamma\]

the pressure, which we replaced using this relation.

source
Trixi.PositivityPreservingLimiterShallowWaterType
PositivityPreservingLimiterShallowWater(; variables)

The limiter is specifically designed for the shallow water equations. It is applied to all scalar variables in their given order using the defined threshold_limiter from the ShallowWaterEquations1D struct or the ShallowWaterEquations2D struct to determine the minimal acceptable values. The order of the variables is important and might have a strong influence on the robustness.

As opposed to the standard version of the PositivityPreservingLimiterZhangShu, nodes with a water height below the threshold_limiter are treated in a special way. To avoid numerical problems caused by velocities close to zero, the velocity is cut off, such that the node can be identified as "dry". The special feature of the ShallowWaterEquations used here is that the bottom topography is stored as an additional quantity in the solution vector u. However, the value of the bottom topography should not be changed. That is why, it is not limited.

After the limiting process is applied to all degrees of freedom, for safety reasons, the threshold_limiter is applied again on all the DG nodes in order to avoid water height below. In the case where the cell mean value is below the threshold before applying the limiter, there could still be dry nodes afterwards due to the logic of the limiter.

This fully-discrete positivity-preserving limiter is based on the work of

  • Zhang, Shu (2011) Maximum-principle-satisfying and positivity-preserving high-order schemes for conservation laws: survey and new developments doi: 10.1098/rspa.2011.0153
source
Trixi.PositivityPreservingLimiterZhangShuType
PositivityPreservingLimiterZhangShu(; threshold, variables)

The fully-discrete positivity-preserving limiter of

  • Zhang, Shu (2011) Maximum-principle-satisfying and positivity-preserving high-order schemes for conservation laws: survey and new developments doi: 10.1098/rspa.2011.0153

The limiter is applied to all scalar variables in their given order using the associated thresholds to determine the minimal acceptable values. The order of the variables is important and might have a strong influence on the robustness.

source
Trixi.SaveRestartCallbackType
SaveRestartCallback(; interval=0,
+\end{pmatrix}\]

for an ideal gas with ratio of specific heats gamma in two space dimensions. Here, $\rho$ is the density and $v_1$ andv_2 the velocities and

\[p = \kappa\rho^\gamma\]

the pressure, which we replaced using this relation.

source
Trixi.PositivityPreservingLimiterShallowWaterType
PositivityPreservingLimiterShallowWater(; variables)

The limiter is specifically designed for the shallow water equations. It is applied to all scalar variables in their given order using the defined threshold_limiter from the ShallowWaterEquations1D struct or the ShallowWaterEquations2D struct to determine the minimal acceptable values. The order of the variables is important and might have a strong influence on the robustness.

As opposed to the standard version of the PositivityPreservingLimiterZhangShu, nodes with a water height below the threshold_limiter are treated in a special way. To avoid numerical problems caused by velocities close to zero, the velocity is cut off, such that the node can be identified as "dry". The special feature of the ShallowWaterEquations used here is that the bottom topography is stored as an additional quantity in the solution vector u. However, the value of the bottom topography should not be changed. That is why, it is not limited.

After the limiting process is applied to all degrees of freedom, for safety reasons, the threshold_limiter is applied again on all the DG nodes in order to avoid water height below. In the case where the cell mean value is below the threshold before applying the limiter, there could still be dry nodes afterwards due to the logic of the limiter.

This fully-discrete positivity-preserving limiter is based on the work of

  • Zhang, Shu (2011) Maximum-principle-satisfying and positivity-preserving high-order schemes for conservation laws: survey and new developments doi: 10.1098/rspa.2011.0153
source
Trixi.PositivityPreservingLimiterZhangShuType
PositivityPreservingLimiterZhangShu(; threshold, variables)

The fully-discrete positivity-preserving limiter of

  • Zhang, Shu (2011) Maximum-principle-satisfying and positivity-preserving high-order schemes for conservation laws: survey and new developments doi: 10.1098/rspa.2011.0153

The limiter is applied to all scalar variables in their given order using the associated thresholds to determine the minimal acceptable values. The order of the variables is important and might have a strong influence on the robustness.

source
Trixi.SaveRestartCallbackType
SaveRestartCallback(; interval=0,
                       save_final_restart=true,
-                      output_directory="out")

Save the current numerical solution in a restart file every interval time steps.

source
Trixi.SaveSolutionCallbackType
SaveSolutionCallback(; interval::Integer=0,
+                      output_directory="out")

Save the current numerical solution in a restart file every interval time steps.

source
Trixi.SaveSolutionCallbackType
SaveSolutionCallback(; interval::Integer=0,
                        dt=nothing,
                        save_initial_solution=true,
                        save_final_solution=true,
                        output_directory="out",
-                       solution_variables=cons2prim)

Save the current numerical solution in regular intervals. Either pass interval to save every interval time steps or pass dt to save in intervals of dt in terms of integration time by adding additional (shortened) time steps where necessary (note that this may change the solution). solution_variables can be any callable that converts the conservative variables at a single point to a set of solution variables. The first parameter passed to solution_variables will be the set of conservative variables and the second parameter is the equation struct.

source
Trixi.SemidiscretizationCoupledType
SemidiscretizationCoupled

A struct used to bundle multiple semidiscretizations. semidiscretize will return an ODEProblem that synchronizes time steps between the semidiscretizations. Each call of rhs! will call rhs! for each semidiscretization individually. The semidiscretizations can be coupled by gluing meshes together using BoundaryConditionCoupled.

Experimental code

This is an experimental feature and can change any time.

source
Trixi.SemidiscretizationEulerAcousticsType
SemidiscretizationEulerAcoustics(semi_acoustics::SemiAcoustics, semi_euler::SemiEuler;
-                                 source_region=x->true, weights=x->1.0)
Experimental code

This semidiscretization is experimental and may change in any future release.

Construct a semidiscretization of the acoustic perturbation equations that is coupled with the compressible Euler equations via source terms for the perturbed velocity. Both semidiscretizations have to use the same mesh and solvers with a shared basis. The coupling region is described by a function source_region that maps the coordinates of a single node to true or false depending on whether the point lies within the coupling region or not. A weighting function weights that maps coordinates to weights is applied to the acoustic source terms. Note that this semidiscretization should be used in conjunction with EulerAcousticsCouplingCallback and only works in two dimensions.

source
Trixi.SemidiscretizationEulerGravityType
SemidiscretizationEulerGravity

A struct containing everything needed to describe a spatial semidiscretization of a the compressible Euler equations with self-gravity, reformulating the Poisson equation for the gravitational potential as steady-state problem of the hyperblic diffusion equations.

  • Michael Schlottke-Lakemper, Andrew R. Winters, Hendrik Ranocha, Gregor J. Gassner (2020) "A purely hyperbolic discontinuous Galerkin approach for self-gravitating gas dynamics" arXiv: 2008.10593
source
Trixi.SemidiscretizationHyperbolicMethod
SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver;
+                       solution_variables=cons2prim)

Save the current numerical solution in regular intervals. Either pass interval to save every interval time steps or pass dt to save in intervals of dt in terms of integration time by adding additional (shortened) time steps where necessary (note that this may change the solution). solution_variables can be any callable that converts the conservative variables at a single point to a set of solution variables. The first parameter passed to solution_variables will be the set of conservative variables and the second parameter is the equation struct.

source
Trixi.SemidiscretizationCoupledType
SemidiscretizationCoupled

A struct used to bundle multiple semidiscretizations. semidiscretize will return an ODEProblem that synchronizes time steps between the semidiscretizations. Each call of rhs! will call rhs! for each semidiscretization individually. The semidiscretizations can be coupled by gluing meshes together using BoundaryConditionCoupled.

Experimental code

This is an experimental feature and can change any time.

source
Trixi.SemidiscretizationEulerAcousticsType
SemidiscretizationEulerAcoustics(semi_acoustics::SemiAcoustics, semi_euler::SemiEuler;
+                                 source_region=x->true, weights=x->1.0)
Experimental code

This semidiscretization is experimental and may change in any future release.

Construct a semidiscretization of the acoustic perturbation equations that is coupled with the compressible Euler equations via source terms for the perturbed velocity. Both semidiscretizations have to use the same mesh and solvers with a shared basis. The coupling region is described by a function source_region that maps the coordinates of a single node to true or false depending on whether the point lies within the coupling region or not. A weighting function weights that maps coordinates to weights is applied to the acoustic source terms. Note that this semidiscretization should be used in conjunction with EulerAcousticsCouplingCallback and only works in two dimensions.

source
Trixi.SemidiscretizationEulerGravityType
SemidiscretizationEulerGravity

A struct containing everything needed to describe a spatial semidiscretization of a the compressible Euler equations with self-gravity, reformulating the Poisson equation for the gravitational potential as steady-state problem of the hyperblic diffusion equations.

  • Michael Schlottke-Lakemper, Andrew R. Winters, Hendrik Ranocha, Gregor J. Gassner (2020) "A purely hyperbolic discontinuous Galerkin approach for self-gravitating gas dynamics" arXiv: 2008.10593
source
Trixi.SemidiscretizationHyperbolicMethod
SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver;
                              source_terms=nothing,
                              boundary_conditions=boundary_condition_periodic,
                              RealT=real(solver),
                              uEltype=RealT,
-                             initial_cache=NamedTuple())

Construct a semidiscretization of a hyperbolic PDE.

source
Trixi.SemidiscretizationHyperbolicParabolicMethod
SemidiscretizationHyperbolicParabolic(mesh, both_equations, initial_condition, solver;
                                       solver_parabolic=default_parabolic_solver(),
                                       source_terms=nothing,
                                       both_boundary_conditions=(boundary_condition_periodic, boundary_condition_periodic),
                                       RealT=real(solver),
                                       uEltype=RealT,
-                                      both_initial_caches=(NamedTuple(), NamedTuple()))

Construct a semidiscretization of a hyperbolic-parabolic PDE.

source
Trixi.ShallowWaterEquations1DType
ShallowWaterEquations1D(; gravity, H0 = 0, threshold_limiter = nothing threshold_wet = nothing)

Shallow water equations (SWE) in one space dimension. The equations are given by

\[\begin{aligned} + both_initial_caches=(NamedTuple(), NamedTuple()))

Construct a semidiscretization of a hyperbolic-parabolic PDE.

source
Trixi.ShallowWaterEquations1DType
ShallowWaterEquations1D(; gravity, H0 = 0, threshold_limiter = nothing threshold_wet = nothing)

Shallow water equations (SWE) in one space dimension. The equations are given by

\[\begin{aligned} \frac{\partial h}{\partial t} + \frac{\partial}{\partial x}(h v) &= 0 \\ \frac{\partial}{\partial t}(h v) + \frac{\partial}{\partial x}\left(h v^2 + \frac{g}{2}h^2\right) + g h \frac{\partial b}{\partial x} &= 0 -\end{aligned}\]

The unknown quantities of the SWE are the water height $h$ and the velocity $v$. The gravitational constant is denoted by g and the (possibly) variable bottom topography function $b(x)$. Conservative variable water height $h$ is measured from the bottom topography $b$, therefore one also defines the total water height as $H = h + b$.

The additional quantity $H_0$ is also available to store a reference value for the total water height that is useful to set initial conditions or test the "lake-at-rest" well-balancedness.

Also, there are two thresholds which prevent numerical problems as well as instabilities. Both of them do not have to be passed, as default values are defined within the struct. The first one, threshold_limiter, is used in PositivityPreservingLimiterShallowWater on the water height, as a (small) shift on the initial condition and cutoff before the next time step. The second one, threshold_wet, is applied on the water height to define when the flow is "wet" before calculating the numerical flux.

The bottom topography function $b(x)$ is set inside the initial condition routine for a particular problem setup. To test the conservative form of the SWE one can set the bottom topography variable b to zero.

In addition to the unknowns, Trixi.jl currently stores the bottom topography values at the approximation points despite being fixed in time. This is done for convenience of computing the bottom topography gradients on the fly during the approximation as well as computing auxiliary quantities like the total water height $H$ or the entropy variables. This affects the implementation and use of these equations in various ways:

  • The flux values corresponding to the bottom topography must be zero.
  • The bottom topography values must be included when defining initial conditions, boundary conditions or source terms.
  • AnalysisCallback analyzes this variable.
  • Trixi.jl's visualization tools will visualize the bottom topography by default.

References for the SWE are many but a good introduction is available in Chapter 13 of the book:

source
Trixi.ShallowWaterEquations2DType
ShallowWaterEquations2D(; gravity, H0 = 0, threshold_limiter = nothing, threshold_wet = nothing)

Shallow water equations (SWE) in two space dimensions. The equations are given by

\[\begin{aligned} +\end{aligned}\]

The unknown quantities of the SWE are the water height $h$ and the velocity $v$. The gravitational constant is denoted by g and the (possibly) variable bottom topography function $b(x)$. Conservative variable water height $h$ is measured from the bottom topography $b$, therefore one also defines the total water height as $H = h + b$.

The additional quantity $H_0$ is also available to store a reference value for the total water height that is useful to set initial conditions or test the "lake-at-rest" well-balancedness.

Also, there are two thresholds which prevent numerical problems as well as instabilities. Both of them do not have to be passed, as default values are defined within the struct. The first one, threshold_limiter, is used in PositivityPreservingLimiterShallowWater on the water height, as a (small) shift on the initial condition and cutoff before the next time step. The second one, threshold_wet, is applied on the water height to define when the flow is "wet" before calculating the numerical flux.

The bottom topography function $b(x)$ is set inside the initial condition routine for a particular problem setup. To test the conservative form of the SWE one can set the bottom topography variable b to zero.

In addition to the unknowns, Trixi.jl currently stores the bottom topography values at the approximation points despite being fixed in time. This is done for convenience of computing the bottom topography gradients on the fly during the approximation as well as computing auxiliary quantities like the total water height $H$ or the entropy variables. This affects the implementation and use of these equations in various ways:

  • The flux values corresponding to the bottom topography must be zero.
  • The bottom topography values must be included when defining initial conditions, boundary conditions or source terms.
  • AnalysisCallback analyzes this variable.
  • Trixi.jl's visualization tools will visualize the bottom topography by default.

References for the SWE are many but a good introduction is available in Chapter 13 of the book:

source
Trixi.ShallowWaterEquations2DType
ShallowWaterEquations2D(; gravity, H0 = 0, threshold_limiter = nothing, threshold_wet = nothing)

Shallow water equations (SWE) in two space dimensions. The equations are given by

\[\begin{aligned} \frac{\partial h}{\partial t} + \frac{\partial}{\partial x}(h v_1) + \frac{\partial}{\partial y}(h v_2) &= 0 \\ \frac{\partial}{\partial t}(h v_1) + \frac{\partial}{\partial x}\left(h v_1^2 + \frac{g}{2}h^2\right) + \frac{\partial}{\partial y}(h v_1 v_2) + g h \frac{\partial b}{\partial x} &= 0 \\ \frac{\partial}{\partial t}(h v_2) + \frac{\partial}{\partial x}(h v_1 v_2) + \frac{\partial}{\partial y}\left(h v_2^2 + \frac{g}{2}h^2\right) + g h \frac{\partial b}{\partial y} &= 0. -\end{aligned}\]

The unknown quantities of the SWE are the water height $h$ and the velocities $\mathbf{v} = (v_1, v_2)^T$. The gravitational constant is denoted by g and the (possibly) variable bottom topography function $b(x,y)$. Conservative variable water height $h$ is measured from the bottom topography $b$, therefore one also defines the total water height as $H = h + b$.

The additional quantity $H_0$ is also available to store a reference value for the total water height that is useful to set initial conditions or test the "lake-at-rest" well-balancedness.

Also, there are two thresholds which prevent numerical problems as well as instabilities. Both of them do not have to be passed, as default values are defined within the struct. The first one, threshold_limiter, is used in PositivityPreservingLimiterShallowWater on the water height, as a (small) shift on the initial condition and cutoff before the next time step. The second one, threshold_wet, is applied on the water height to define when the flow is "wet" before calculating the numerical flux.

The bottom topography function $b(x,y)$ is set inside the initial condition routine for a particular problem setup. To test the conservative form of the SWE one can set the bottom topography variable b to zero.

In addition to the unknowns, Trixi.jl currently stores the bottom topography values at the approximation points despite being fixed in time. This is done for convenience of computing the bottom topography gradients on the fly during the approximation as well as computing auxiliary quantities like the total water height $H$ or the entropy variables. This affects the implementation and use of these equations in various ways:

  • The flux values corresponding to the bottom topography must be zero.
  • The bottom topography values must be included when defining initial conditions, boundary conditions or source terms.
  • AnalysisCallback analyzes this variable.
  • Trixi.jl's visualization tools will visualize the bottom topography by default.

References for the SWE are many but a good introduction is available in Chapter 13 of the book:

source
Trixi.ShallowWaterEquationsQuasi1DType
ShallowWaterEquationsQuasi1D(; gravity, H0 = 0, threshold_limiter = nothing threshold_wet = nothing)

The quasi-1D shallow water equations (SWE). The equations are given by

\[\begin{aligned} +\end{aligned}\]

The unknown quantities of the SWE are the water height $h$ and the velocities $\mathbf{v} = (v_1, v_2)^T$. The gravitational constant is denoted by g and the (possibly) variable bottom topography function $b(x,y)$. Conservative variable water height $h$ is measured from the bottom topography $b$, therefore one also defines the total water height as $H = h + b$.

The additional quantity $H_0$ is also available to store a reference value for the total water height that is useful to set initial conditions or test the "lake-at-rest" well-balancedness.

Also, there are two thresholds which prevent numerical problems as well as instabilities. Both of them do not have to be passed, as default values are defined within the struct. The first one, threshold_limiter, is used in PositivityPreservingLimiterShallowWater on the water height, as a (small) shift on the initial condition and cutoff before the next time step. The second one, threshold_wet, is applied on the water height to define when the flow is "wet" before calculating the numerical flux.

The bottom topography function $b(x,y)$ is set inside the initial condition routine for a particular problem setup. To test the conservative form of the SWE one can set the bottom topography variable b to zero.

In addition to the unknowns, Trixi.jl currently stores the bottom topography values at the approximation points despite being fixed in time. This is done for convenience of computing the bottom topography gradients on the fly during the approximation as well as computing auxiliary quantities like the total water height $H$ or the entropy variables. This affects the implementation and use of these equations in various ways:

  • The flux values corresponding to the bottom topography must be zero.
  • The bottom topography values must be included when defining initial conditions, boundary conditions or source terms.
  • AnalysisCallback analyzes this variable.
  • Trixi.jl's visualization tools will visualize the bottom topography by default.

References for the SWE are many but a good introduction is available in Chapter 13 of the book:

source
Trixi.ShallowWaterEquationsQuasi1DType
ShallowWaterEquationsQuasi1D(; gravity, H0 = 0, threshold_limiter = nothing threshold_wet = nothing)

The quasi-1D shallow water equations (SWE). The equations are given by

\[\begin{aligned} \frac{\partial}{\partial t}(a h) + \frac{\partial}{\partial x}(a h v) &= 0 \\ \frac{\partial}{\partial t}(a h v) + \frac{\partial}{\partial x}(a h v^2) + g a h \frac{\partial}{\partial x}(h + b) &= 0 -\end{aligned}\]

The unknown quantities of the Quasi-1D SWE are the water height $h$ and the scaled velocity $v$. The gravitational constant is denoted by g, the (possibly) variable bottom topography function $b(x)$, and (possibly) variable channel width $a(x)$. The water height $h$ is measured from the bottom topography $b$, therefore one also defines the total water height as $H = h + b$.

The additional quantity $H_0$ is also available to store a reference value for the total water height that is useful to set initial conditions or test the "lake-at-rest" well-balancedness.

Also, there are two thresholds which prevent numerical problems as well as instabilities. Both of them do not have to be passed, as default values are defined within the struct. The first one, threshold_limiter, is used in PositivityPreservingLimiterShallowWater on the water height, as a (small) shift on the initial condition and cutoff before the next time step. The second one, threshold_wet, is applied on the water height to define when the flow is "wet" before calculating the numerical flux.

The bottom topography function $b(x)$ and channel width $a(x)$ are set inside the initial condition routine for a particular problem setup. To test the conservative form of the SWE one can set the bottom topography variable b to zero and $a$ to one.

In addition to the unknowns, Trixi.jl currently stores the bottom topography and channel width values at the approximation points despite being fixed in time. This is done for convenience of computing the bottom topography gradients on the fly during the approximation as well as computing auxiliary quantities like the total water height $H$ or the entropy variables. This affects the implementation and use of these equations in various ways:

  • The flux values corresponding to the bottom topography and channel width must be zero.
  • The bottom topography and channel width values must be included when defining initial conditions, boundary conditions or source terms.
  • AnalysisCallback analyzes this variable.
  • Trixi.jl's visualization tools will visualize the bottom topography and channel width by default.
source
Trixi.ShallowWaterTwoLayerEquations1DType
ShallowWaterTwoLayerEquations1D(gravity, H0, rho_upper, rho_lower)

Two-Layer Shallow Water equations (2LSWE) in one space dimension. The equations are given by

\[\begin{alignat*}{4} +\end{aligned}\]

The unknown quantities of the Quasi-1D SWE are the water height $h$ and the scaled velocity $v$. The gravitational constant is denoted by g, the (possibly) variable bottom topography function $b(x)$, and (possibly) variable channel width $a(x)$. The water height $h$ is measured from the bottom topography $b$, therefore one also defines the total water height as $H = h + b$.

The additional quantity $H_0$ is also available to store a reference value for the total water height that is useful to set initial conditions or test the "lake-at-rest" well-balancedness.

Also, there are two thresholds which prevent numerical problems as well as instabilities. Both of them do not have to be passed, as default values are defined within the struct. The first one, threshold_limiter, is used in PositivityPreservingLimiterShallowWater on the water height, as a (small) shift on the initial condition and cutoff before the next time step. The second one, threshold_wet, is applied on the water height to define when the flow is "wet" before calculating the numerical flux.

The bottom topography function $b(x)$ and channel width $a(x)$ are set inside the initial condition routine for a particular problem setup. To test the conservative form of the SWE one can set the bottom topography variable b to zero and $a$ to one.

In addition to the unknowns, Trixi.jl currently stores the bottom topography and channel width values at the approximation points despite being fixed in time. This is done for convenience of computing the bottom topography gradients on the fly during the approximation as well as computing auxiliary quantities like the total water height $H$ or the entropy variables. This affects the implementation and use of these equations in various ways:

  • The flux values corresponding to the bottom topography and channel width must be zero.
  • The bottom topography and channel width values must be included when defining initial conditions, boundary conditions or source terms.
  • AnalysisCallback analyzes this variable.
  • Trixi.jl's visualization tools will visualize the bottom topography and channel width by default.
source
Trixi.ShallowWaterTwoLayerEquations1DType
ShallowWaterTwoLayerEquations1D(gravity, H0, rho_upper, rho_lower)

Two-Layer Shallow Water equations (2LSWE) in one space dimension. The equations are given by

\[\begin{alignat*}{4} &\frac{\partial}{\partial t}h_{upper} &&+ \frac{\partial}{\partial x}\left(h_{upper} v_{1,upper}\right) &&= 0 \\ @@ -319,7 +319,7 @@ &\frac{\partial}{\partial t}\left(h_{lower}v_{1,lower}\right) &&+ \frac{\partial}{\partial x}\left(h_{lower}v_{1,lower}^2 + \dfrac{gh_{lower}^2}{2}\right) &&= -gh_{lower}\frac{\partial}{\partial x}\left(b+\dfrac{\rho_{upper}}{\rho_{lower}}h_{upper}\right). -\end{alignat*}\]

The unknown quantities of the 2LSWE are the water heights of the {lower} layer $h_{lower}$ and the {upper} layer $h_{upper}$ with respective velocities $v_{1,upper}$ and $v_{1,lower}$. The gravitational constant is denoted by g, the layer densitites by $\rho_{upper}$and $\rho_{lower}$ and the (possibly) variable bottom topography function $b(x)$. The conservative variable water height $h_{lower}$ is measured from the bottom topography $b$ and $h_{upper}$ relative to $h_{lower}$, therefore one also defines the total water heights as $H_{upper} = h_{upper} + h_{upper} + b$ and $H_{lower} = h_{lower} + b$.

The densities must be chosen such that $\rho_{upper} < \rho_{lower}$, to make sure that the heavier fluid $\rho_{lower}$ is in the bottom layer and the lighter fluid $\rho_{upper}$ in the {upper} layer.

The additional quantity $H_0$ is also available to store a reference value for the total water height that is useful to set initial conditions or test the "lake-at-rest" well-balancedness.

The bottom topography function $b(x)$ is set inside the initial condition routine for a particular problem setup.

In addition to the unknowns, Trixi currently stores the bottom topography values at the approximation points despite being fixed in time. This is done for convenience of computing the bottom topography gradients on the fly during the approximation as well as computing auxiliary quantities like the total water height $H$ or the entropy variables. This affects the implementation and use of these equations in various ways:

  • The flux values corresponding to the bottom topography must be zero.
  • The bottom topography values must be included when defining initial conditions, boundary conditions or source terms.
  • AnalysisCallback analyzes this variable.
  • Trixi's visualization tools will visualize the bottom topography by default.

A good introduction for the 2LSWE is available in Chapter 12 of the book:

source
Trixi.ShallowWaterTwoLayerEquations2DType
ShallowWaterTwoLayerEquations2D(gravity, H0, rho_upper, rho_lower)

Two-Layer Shallow water equations (2LSWE) in two space dimension. The equations are given by

\[\begin{alignat*}{8} +\end{alignat*}\]

The unknown quantities of the 2LSWE are the water heights of the {lower} layer $h_{lower}$ and the {upper} layer $h_{upper}$ with respective velocities $v_{1,upper}$ and $v_{1,lower}$. The gravitational constant is denoted by g, the layer densitites by $\rho_{upper}$and $\rho_{lower}$ and the (possibly) variable bottom topography function $b(x)$. The conservative variable water height $h_{lower}$ is measured from the bottom topography $b$ and $h_{upper}$ relative to $h_{lower}$, therefore one also defines the total water heights as $H_{upper} = h_{upper} + h_{upper} + b$ and $H_{lower} = h_{lower} + b$.

The densities must be chosen such that $\rho_{upper} < \rho_{lower}$, to make sure that the heavier fluid $\rho_{lower}$ is in the bottom layer and the lighter fluid $\rho_{upper}$ in the {upper} layer.

The additional quantity $H_0$ is also available to store a reference value for the total water height that is useful to set initial conditions or test the "lake-at-rest" well-balancedness.

The bottom topography function $b(x)$ is set inside the initial condition routine for a particular problem setup.

In addition to the unknowns, Trixi currently stores the bottom topography values at the approximation points despite being fixed in time. This is done for convenience of computing the bottom topography gradients on the fly during the approximation as well as computing auxiliary quantities like the total water height $H$ or the entropy variables. This affects the implementation and use of these equations in various ways:

  • The flux values corresponding to the bottom topography must be zero.
  • The bottom topography values must be included when defining initial conditions, boundary conditions or source terms.
  • AnalysisCallback analyzes this variable.
  • Trixi's visualization tools will visualize the bottom topography by default.

A good introduction for the 2LSWE is available in Chapter 12 of the book:

source
Trixi.ShallowWaterTwoLayerEquations2DType
ShallowWaterTwoLayerEquations2D(gravity, H0, rho_upper, rho_lower)

Two-Layer Shallow water equations (2LSWE) in two space dimension. The equations are given by

\[\begin{alignat*}{8} &\frac{\partial}{\partial t}h_{upper} &&+ \frac{\partial}{\partial x}\left(h_{upper} v_{1,upper}\right) &&+ \frac{\partial}{\partial y}\left(h_{upper} v_{2,upper}\right) \quad @@ -344,30 +344,30 @@ &&+ \frac{\partial}{\partial x}\left(h_{lower} v_{1,lower} v_{2,lower}\right) &&+ \frac{\partial}{\partial y}\left(h_{lower} v_{2,lower}^2 + \frac{gh_{lower}^2}{2}\right) &&= -gh_{lower}\frac{\partial}{\partial y}\left(b+\frac{\rho_{upper}}{\rho_{lower}} h_{upper}\right) -\end{alignat*}\]

The unknown quantities of the 2LSWE are the water heights of the lower layer $h_{lower}$ and the upper layer $h_{upper}$ and the respective velocities in x-direction $v_{1,lower}$ and $v_{1,upper}$ and in y-direction $v_{2,lower}$ and $v_{2,upper}$. The gravitational constant is denoted by g, the layer densitites by $\rho_{upper}$and $\rho_{lower}$ and the (possibly) variable bottom topography function by $b(x)$. Conservative variable water height $h_{lower}$ is measured from the bottom topography $b$ and $h_{upper}$ relative to $h_{lower}$, therefore one also defines the total water heights as $H_{lower} = h_{lower} + b$ and $H_{upper} = h_{upper} + h_{lower} + b$.

The densities must be chosen such that $\rho_{upper} < \rho_{lower}$, to make sure that the heavier fluid $\rho_{lower}$ is in the bottom layer and the lighter fluid $\rho_{upper}$ in the upper layer.

The additional quantity $H_0$ is also available to store a reference value for the total water height that is useful to set initial conditions or test the "lake-at-rest" well-balancedness.

The bottom topography function $b(x)$ is set inside the initial condition routine for a particular problem setup.

In addition to the unknowns, Trixi currently stores the bottom topography values at the approximation points despite being fixed in time. This is done for convenience of computing the bottom topography gradients on the fly during the approximation as well as computing auxiliary quantities like the total water height $H$ or the entropy variables. This affects the implementation and use of these equations in various ways:

  • The flux values corresponding to the bottom topography must be zero.
  • The bottom topography values must be included when defining initial conditions, boundary conditions or source terms.
  • AnalysisCallback analyzes this variable.
  • Trixi's visualization tools will visualize the bottom topography by default.

A good introduction for the 2LSWE is available in Chapter 12 of the book:

source
Trixi.SimpleSSPRK33Type
SimpleSSPRK33(; stage_callbacks=())

The third-order SSP Runge-Kutta method of Shu and Osher.

References

Experimental implementation

This is an experimental feature and may change in future releases.

source
Trixi.StepsizeCallbackType
StepsizeCallback(; cfl=1.0)

Set the time step size according to a CFL condition with CFL number cfl if the time integration method isn't adaptive itself.

source
Trixi.StructuredMeshType
StructuredMesh{NDIMS} <: AbstractMesh{NDIMS}

A structured curved mesh.

Different numbers of cells per dimension are possible and arbitrary functions can be used as domain faces.

source
Trixi.StructuredMeshMethod
StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max; periodicity=true)

Create a StructuredMesh that represents a uncurved structured mesh with a rectangular domain.

Arguments

  • cells_per_dimension::NTuple{NDIMS, Int}: the number of cells in each dimension.
  • coordinates_min::NTuple{NDIMS, RealT}: coordinate of the corner in the negative direction of each dimension.
  • coordinates_max::NTuple{NDIMS, RealT}: coordinate of the corner in the positive direction of each dimension.
  • periodicity: either a Bool deciding if all of the boundaries are periodic or an NTuple{NDIMS, Bool} deciding for each dimension if the boundaries in this dimension are periodic.
source
Trixi.StructuredMeshMethod
StructuredMesh(cells_per_dimension, mapping; RealT=Float64, unsaved_changes=true, mapping_as_string=mapping2string(mapping, length(cells_per_dimension)))

Create a StructuredMesh of the given size and shape that uses RealT as coordinate type.

Arguments

  • cells_per_dimension::NTupleE{NDIMS, Int}: the number of cells in each dimension.
  • mapping: a function of NDIMS variables to describe the mapping, which transforms the reference mesh to the physical domain. If no mapping_as_string is defined, this function must be defined with the name mapping to allow for restarts. This will be changed in the future, see https://github.com/trixi-framework/Trixi.jl/issues/541.
  • RealT::Type: the type that should be used for coordinates.
  • periodicity: either a Bool deciding if all of the boundaries are periodic or an NTuple{NDIMS, Bool} deciding for each dimension if the boundaries in this dimension are periodic.
  • unsaved_changes::Bool: if set to true, the mesh will be saved to a mesh file.
  • mapping_as_string::String: the code that defines the mapping. If CodeTracking can't find the function definition, it can be passed directly here. The code string must define the mapping function with the name mapping. This will be changed in the future, see https://github.com/trixi-framework/Trixi.jl/issues/541.
source
Trixi.StructuredMeshMethod
StructuredMesh(cells_per_dimension, faces; RealT=Float64, unsaved_changes=true, faces_as_string=faces2string(faces))

Create a StructuredMesh of the given size and shape that uses RealT as coordinate type.

Arguments

  • cells_per_dimension::NTupleE{NDIMS, Int}: the number of cells in each dimension.
  • faces::NTuple{2*NDIMS}: a tuple of 2 * NDIMS functions that describe the faces of the domain. Each function must take NDIMS-1 arguments. faces[1] describes the face onto which the face in negative x-direction of the unit hypercube is mapped. The face in positive x-direction of the unit hypercube will be mapped onto the face described by faces[2]. faces[3:4] describe the faces in positive and negative y-direction respectively (in 2D and 3D). faces[5:6] describe the faces in positive and negative z-direction respectively (in 3D).
  • RealT::Type: the type that should be used for coordinates.
  • periodicity: either a Bool deciding if all of the boundaries are periodic or an NTuple{NDIMS, Bool} deciding for each dimension if the boundaries in this dimension are periodic.
source
Trixi.SubcellLimiterIDPType
SubcellLimiterIDP(equations::AbstractEquations, basis;
+\end{alignat*}\]

The unknown quantities of the 2LSWE are the water heights of the lower layer $h_{lower}$ and the upper layer $h_{upper}$ and the respective velocities in x-direction $v_{1,lower}$ and $v_{1,upper}$ and in y-direction $v_{2,lower}$ and $v_{2,upper}$. The gravitational constant is denoted by g, the layer densitites by $\rho_{upper}$and $\rho_{lower}$ and the (possibly) variable bottom topography function by $b(x)$. Conservative variable water height $h_{lower}$ is measured from the bottom topography $b$ and $h_{upper}$ relative to $h_{lower}$, therefore one also defines the total water heights as $H_{lower} = h_{lower} + b$ and $H_{upper} = h_{upper} + h_{lower} + b$.

The densities must be chosen such that $\rho_{upper} < \rho_{lower}$, to make sure that the heavier fluid $\rho_{lower}$ is in the bottom layer and the lighter fluid $\rho_{upper}$ in the upper layer.

The additional quantity $H_0$ is also available to store a reference value for the total water height that is useful to set initial conditions or test the "lake-at-rest" well-balancedness.

The bottom topography function $b(x)$ is set inside the initial condition routine for a particular problem setup.

In addition to the unknowns, Trixi currently stores the bottom topography values at the approximation points despite being fixed in time. This is done for convenience of computing the bottom topography gradients on the fly during the approximation as well as computing auxiliary quantities like the total water height $H$ or the entropy variables. This affects the implementation and use of these equations in various ways:

  • The flux values corresponding to the bottom topography must be zero.
  • The bottom topography values must be included when defining initial conditions, boundary conditions or source terms.
  • AnalysisCallback analyzes this variable.
  • Trixi's visualization tools will visualize the bottom topography by default.

A good introduction for the 2LSWE is available in Chapter 12 of the book:

source
Trixi.SimpleSSPRK33Type
SimpleSSPRK33(; stage_callbacks=())

The third-order SSP Runge-Kutta method of Shu and Osher.

References

Experimental implementation

This is an experimental feature and may change in future releases.

source
Trixi.StepsizeCallbackType
StepsizeCallback(; cfl=1.0)

Set the time step size according to a CFL condition with CFL number cfl if the time integration method isn't adaptive itself.

source
Trixi.StructuredMeshType
StructuredMesh{NDIMS} <: AbstractMesh{NDIMS}

A structured curved mesh.

Different numbers of cells per dimension are possible and arbitrary functions can be used as domain faces.

source
Trixi.StructuredMeshMethod
StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max; periodicity=true)

Create a StructuredMesh that represents a uncurved structured mesh with a rectangular domain.

Arguments

  • cells_per_dimension::NTuple{NDIMS, Int}: the number of cells in each dimension.
  • coordinates_min::NTuple{NDIMS, RealT}: coordinate of the corner in the negative direction of each dimension.
  • coordinates_max::NTuple{NDIMS, RealT}: coordinate of the corner in the positive direction of each dimension.
  • periodicity: either a Bool deciding if all of the boundaries are periodic or an NTuple{NDIMS, Bool} deciding for each dimension if the boundaries in this dimension are periodic.
source
Trixi.StructuredMeshMethod
StructuredMesh(cells_per_dimension, mapping; RealT=Float64, unsaved_changes=true, mapping_as_string=mapping2string(mapping, length(cells_per_dimension)))

Create a StructuredMesh of the given size and shape that uses RealT as coordinate type.

Arguments

  • cells_per_dimension::NTupleE{NDIMS, Int}: the number of cells in each dimension.
  • mapping: a function of NDIMS variables to describe the mapping, which transforms the reference mesh to the physical domain. If no mapping_as_string is defined, this function must be defined with the name mapping to allow for restarts. This will be changed in the future, see https://github.com/trixi-framework/Trixi.jl/issues/541.
  • RealT::Type: the type that should be used for coordinates.
  • periodicity: either a Bool deciding if all of the boundaries are periodic or an NTuple{NDIMS, Bool} deciding for each dimension if the boundaries in this dimension are periodic.
  • unsaved_changes::Bool: if set to true, the mesh will be saved to a mesh file.
  • mapping_as_string::String: the code that defines the mapping. If CodeTracking can't find the function definition, it can be passed directly here. The code string must define the mapping function with the name mapping. This will be changed in the future, see https://github.com/trixi-framework/Trixi.jl/issues/541.
source
Trixi.StructuredMeshMethod
StructuredMesh(cells_per_dimension, faces; RealT=Float64, unsaved_changes=true, faces_as_string=faces2string(faces))

Create a StructuredMesh of the given size and shape that uses RealT as coordinate type.

Arguments

  • cells_per_dimension::NTupleE{NDIMS, Int}: the number of cells in each dimension.
  • faces::NTuple{2*NDIMS}: a tuple of 2 * NDIMS functions that describe the faces of the domain. Each function must take NDIMS-1 arguments. faces[1] describes the face onto which the face in negative x-direction of the unit hypercube is mapped. The face in positive x-direction of the unit hypercube will be mapped onto the face described by faces[2]. faces[3:4] describe the faces in positive and negative y-direction respectively (in 2D and 3D). faces[5:6] describe the faces in positive and negative z-direction respectively (in 3D).
  • RealT::Type: the type that should be used for coordinates.
  • periodicity: either a Bool deciding if all of the boundaries are periodic or an NTuple{NDIMS, Bool} deciding for each dimension if the boundaries in this dimension are periodic.
source
Trixi.SubcellLimiterIDPType
SubcellLimiterIDP(equations::AbstractEquations, basis;
                   positivity_variables_cons = [],
-                  positivity_correction_factor = 0.1)

Subcell invariant domain preserving (IDP) limiting used with VolumeIntegralSubcellLimiting including:

  • positivity limiting for conservative variables (positivity_variables_cons)

The bounds are calculated using the low-order FV solution. The positivity limiter uses positivity_correction_factor such that u^new >= positivity_correction_factor * u^FV.

Note

This limiter and the correction callback SubcellLimiterIDPCorrection only work together. Without the callback, no correction takes place, leading to a standard low-order FV scheme.

References

Experimental implementation

This is an experimental feature and may change in future releases.

source
Trixi.SubcellLimiterIDPCorrectionType
SubcellLimiterIDPCorrection()

Perform antidiffusive correction stage for the a posteriori IDP limiter SubcellLimiterIDP called with VolumeIntegralSubcellLimiting.

Note

This callback and the actual limiter SubcellLimiterIDP only work together. This is not a replacement but a necessary addition.

References

Experimental implementation

This is an experimental feature and may change in future releases.

source
Trixi.SurfaceIntegralWeakFormType
SurfaceIntegralWeakForm(surface_flux=flux_central)

The classical weak form surface integral type for DG methods as explained in standard textbooks.

See also VolumeIntegralWeakForm.

References

source
Trixi.T8codeMeshType
T8codeMesh{NDIMS} <: AbstractMesh{NDIMS}

An unstructured curved mesh based on trees that uses the C library 't8code' to manage trees and mesh refinement.

source
Trixi.T8codeMeshMethod
T8codeMesh(trees_per_dimension; polydeg, mapping=identity,
-           RealT=Float64, initial_refinement_level=0, periodicity=true)

Create a structured potentially curved 'T8codeMesh' of the specified size.

Non-periodic boundaries will be called ':xneg', ':xpos', ':yneg', ':ypos', ':zneg', ':zpos'.

Arguments

  • 'treesperdimension::NTupleE{NDIMS, Int}': the number of trees in each dimension.
  • 'polydeg::Integer': polynomial degree used to store the geometry of the mesh. The mapping will be approximated by an interpolation polynomial of the specified degree for each tree.
  • 'mapping': a function of 'NDIMS' variables to describe the mapping that transforms the reference mesh ('[-1, 1]^n') to the physical domain.
  • 'RealT::Type': the type that should be used for coordinates.
  • 'initialrefinementlevel::Integer': refine the mesh uniformly to this level before the simulation starts.
  • 'periodicity': either a 'Bool' deciding if all of the boundaries are periodic or an 'NTuple{NDIMS, Bool}' deciding for each dimension if the boundaries in this dimension are periodic.
source
Trixi.T8codeMeshMethod
T8codeMesh{NDIMS}(conn::Ptr{p4est_connectivity},
+                  positivity_correction_factor = 0.1)

Subcell invariant domain preserving (IDP) limiting used with VolumeIntegralSubcellLimiting including:

  • positivity limiting for conservative variables (positivity_variables_cons)

The bounds are calculated using the low-order FV solution. The positivity limiter uses positivity_correction_factor such that u^new >= positivity_correction_factor * u^FV.

Note

This limiter and the correction callback SubcellLimiterIDPCorrection only work together. Without the callback, no correction takes place, leading to a standard low-order FV scheme.

References

Experimental implementation

This is an experimental feature and may change in future releases.

source
Trixi.SubcellLimiterIDPCorrectionType
SubcellLimiterIDPCorrection()

Perform antidiffusive correction stage for the a posteriori IDP limiter SubcellLimiterIDP called with VolumeIntegralSubcellLimiting.

Note

This callback and the actual limiter SubcellLimiterIDP only work together. This is not a replacement but a necessary addition.

References

Experimental implementation

This is an experimental feature and may change in future releases.

source
Trixi.SurfaceIntegralWeakFormType
SurfaceIntegralWeakForm(surface_flux=flux_central)

The classical weak form surface integral type for DG methods as explained in standard textbooks.

See also VolumeIntegralWeakForm.

References

source
Trixi.T8codeMeshType
T8codeMesh{NDIMS} <: AbstractMesh{NDIMS}

An unstructured curved mesh based on trees that uses the C library 't8code' to manage trees and mesh refinement.

source
Trixi.T8codeMeshMethod
T8codeMesh(trees_per_dimension; polydeg, mapping=identity,
+           RealT=Float64, initial_refinement_level=0, periodicity=true)

Create a structured potentially curved 'T8codeMesh' of the specified size.

Non-periodic boundaries will be called ':xneg', ':xpos', ':yneg', ':ypos', ':zneg', ':zpos'.

Arguments

  • 'treesperdimension::NTupleE{NDIMS, Int}': the number of trees in each dimension.
  • 'polydeg::Integer': polynomial degree used to store the geometry of the mesh. The mapping will be approximated by an interpolation polynomial of the specified degree for each tree.
  • 'mapping': a function of 'NDIMS' variables to describe the mapping that transforms the reference mesh ('[-1, 1]^n') to the physical domain.
  • 'RealT::Type': the type that should be used for coordinates.
  • 'initialrefinementlevel::Integer': refine the mesh uniformly to this level before the simulation starts.
  • 'periodicity': either a 'Bool' deciding if all of the boundaries are periodic or an 'NTuple{NDIMS, Bool}' deciding for each dimension if the boundaries in this dimension are periodic.
source
Trixi.T8codeMeshMethod
T8codeMesh{NDIMS}(conn::Ptr{p4est_connectivity},
                   mapping=nothing, polydeg=1, RealT=Float64,
-                  initial_refinement_level=0)

Main mesh constructor for the T8codeMesh that imports an unstructured, conforming mesh from a p4est_connectivity data structure.

Arguments

  • conn::Ptr{p4est_connectivity}: Pointer to a P4est connectivity object.
  • mapping: a function of NDIMS variables to describe the mapping that transforms the imported mesh to the physical domain. Use nothing for the identity map.
  • polydeg::Integer: polynomial degree used to store the geometry of the mesh. The mapping will be approximated by an interpolation polynomial of the specified degree for each tree. The default of 1 creates an uncurved geometry. Use a higher value if the mapping will curve the imported uncurved mesh.
  • RealT::Type: the type that should be used for coordinates.
  • initial_refinement_level::Integer: refine the mesh uniformly to this level before the simulation starts.
source
Trixi.T8codeMeshMethod
T8codeMesh{NDIMS}(cmesh::Ptr{t8_cmesh},
+                  initial_refinement_level=0)

Main mesh constructor for the T8codeMesh that imports an unstructured, conforming mesh from a p4est_connectivity data structure.

Arguments

  • conn::Ptr{p4est_connectivity}: Pointer to a P4est connectivity object.
  • mapping: a function of NDIMS variables to describe the mapping that transforms the imported mesh to the physical domain. Use nothing for the identity map.
  • polydeg::Integer: polynomial degree used to store the geometry of the mesh. The mapping will be approximated by an interpolation polynomial of the specified degree for each tree. The default of 1 creates an uncurved geometry. Use a higher value if the mapping will curve the imported uncurved mesh.
  • RealT::Type: the type that should be used for coordinates.
  • initial_refinement_level::Integer: refine the mesh uniformly to this level before the simulation starts.
source
Trixi.T8codeMeshMethod
T8codeMesh{NDIMS}(cmesh::Ptr{t8_cmesh},
                  mapping=nothing, polydeg=1, RealT=Float64,
-                 initial_refinement_level=0)

Main mesh constructor for the T8codeMesh that imports an unstructured, conforming mesh from a t8_cmesh data structure.

Arguments

  • cmesh::Ptr{t8_cmesh}: Pointer to a cmesh object.
  • mapping: a function of NDIMS variables to describe the mapping that transforms the imported mesh to the physical domain. Use nothing for the identity map.
  • polydeg::Integer: polynomial degree used to store the geometry of the mesh. The mapping will be approximated by an interpolation polynomial of the specified degree for each tree. The default of 1 creates an uncurved geometry. Use a higher value if the mapping will curve the imported uncurved mesh.
  • RealT::Type: the type that should be used for coordinates.
  • initial_refinement_level::Integer: refine the mesh uniformly to this level before the simulation starts.
source
Trixi.T8codeMeshMethod
T8codeMesh{NDIMS}(meshfile::String;
+                 initial_refinement_level=0)

Main mesh constructor for the T8codeMesh that imports an unstructured, conforming mesh from a t8_cmesh data structure.

Arguments

  • cmesh::Ptr{t8_cmesh}: Pointer to a cmesh object.
  • mapping: a function of NDIMS variables to describe the mapping that transforms the imported mesh to the physical domain. Use nothing for the identity map.
  • polydeg::Integer: polynomial degree used to store the geometry of the mesh. The mapping will be approximated by an interpolation polynomial of the specified degree for each tree. The default of 1 creates an uncurved geometry. Use a higher value if the mapping will curve the imported uncurved mesh.
  • RealT::Type: the type that should be used for coordinates.
  • initial_refinement_level::Integer: refine the mesh uniformly to this level before the simulation starts.
source
Trixi.T8codeMeshMethod
T8codeMesh{NDIMS}(meshfile::String;
                  mapping=nothing, polydeg=1, RealT=Float64,
-                 initial_refinement_level=0)

Main mesh constructor for the T8codeMesh that imports an unstructured, conforming mesh from a Gmsh mesh file (.msh).

Arguments

  • meshfile::String: path to a Gmsh mesh file.
  • mapping: a function of NDIMS variables to describe the mapping that transforms the imported mesh to the physical domain. Use nothing for the identity map.
  • polydeg::Integer: polynomial degree used to store the geometry of the mesh. The mapping will be approximated by an interpolation polynomial of the specified degree for each tree. The default of 1 creates an uncurved geometry. Use a higher value if the mapping will curve the imported uncurved mesh.
  • RealT::Type: the type that should be used for coordinates.
  • initial_refinement_level::Integer: refine the mesh uniformly to this level before the simulation starts.
source
Trixi.TimeSeriesCallbackType
TimeSeriesCallback(semi, point_coordinates;
+                 initial_refinement_level=0)

Main mesh constructor for the T8codeMesh that imports an unstructured, conforming mesh from a Gmsh mesh file (.msh).

Arguments

  • meshfile::String: path to a Gmsh mesh file.
  • mapping: a function of NDIMS variables to describe the mapping that transforms the imported mesh to the physical domain. Use nothing for the identity map.
  • polydeg::Integer: polynomial degree used to store the geometry of the mesh. The mapping will be approximated by an interpolation polynomial of the specified degree for each tree. The default of 1 creates an uncurved geometry. Use a higher value if the mapping will curve the imported uncurved mesh.
  • RealT::Type: the type that should be used for coordinates.
  • initial_refinement_level::Integer: refine the mesh uniformly to this level before the simulation starts.
source
Trixi.TimeSeriesCallbackType
TimeSeriesCallback(semi, point_coordinates;
                    interval=1, solution_variables=cons2cons,
                    output_directory="out", filename="time_series.h5",
-                   RealT=real(solver), uEltype=eltype(cache.elements))

Create a callback that records point-wise data at points given in point_coordinates every interval time steps. The point coordinates are to be specified either as a vector of coordinate tuples or as a two-dimensional array where the first dimension is the point number and the second dimension is the coordinate dimension. By default, the conservative variables are recorded, but this can be controlled by passing a different conversion function to solution_variables.

After the last time step, the results are stored in an HDF5 file filename in directory output_directory.

The real data type RealT and data type for solution variables uEltype default to the respective types used in the solver and the cache.

Experimental implementation

This is an experimental feature and may change in future releases.

source
Trixi.TreeMeshType
TreeMesh{NDIMS} <: AbstractMesh{NDIMS}

A Cartesian mesh based on trees of hypercubes to support adaptive mesh refinement.

source
Trixi.UnstructuredMesh2DType
UnstructuredMesh2D <: AbstractMesh{2}

An unstructured (possibly curved) quadrilateral mesh.

UnstructuredMesh2D(filename; RealT=Float64, periodicity=false)

All mesh information, neighbour coupling, and boundary curve information is read in from a mesh file filename.

source
Trixi.UnstructuredSortedBoundaryTypesType
UnstructuredSortedBoundaryTypes

General container to sort the boundary conditions by type for some unstructured meshes/solvers. It stores a set of global indices for each boundary condition type to expedite computation during the call to calc_boundary_flux!. The original dictionary form of the boundary conditions set by the user in the elixir file is also stored for printing.

source
Trixi.ViscousFormulationLocalDGType
ViscousFormulationLocalDG(penalty_parameter)

The local DG (LDG) flux from "The Local Discontinuous Galerkin Method for Time-Dependent Convection-Diffusion Systems" by Cockburn and Shu (1998).

Note that, since this implementation does not involve the parabolic "upwinding" vector, the LDG solver is equivalent to ViscousFormulationBassiRebay1 with an LDG-type penalization.

source
Trixi.VisualizationCallbackMethod
VisualizationCallback(; interval=0,
+                   RealT=real(solver), uEltype=eltype(cache.elements))

Create a callback that records point-wise data at points given in point_coordinates every interval time steps. The point coordinates are to be specified either as a vector of coordinate tuples or as a two-dimensional array where the first dimension is the point number and the second dimension is the coordinate dimension. By default, the conservative variables are recorded, but this can be controlled by passing a different conversion function to solution_variables.

After the last time step, the results are stored in an HDF5 file filename in directory output_directory.

The real data type RealT and data type for solution variables uEltype default to the respective types used in the solver and the cache.

Experimental implementation

This is an experimental feature and may change in future releases.

source
Trixi.TreeMeshType
TreeMesh{NDIMS} <: AbstractMesh{NDIMS}

A Cartesian mesh based on trees of hypercubes to support adaptive mesh refinement.

source
Trixi.UnstructuredMesh2DType
UnstructuredMesh2D <: AbstractMesh{2}

An unstructured (possibly curved) quadrilateral mesh.

UnstructuredMesh2D(filename; RealT=Float64, periodicity=false)

All mesh information, neighbour coupling, and boundary curve information is read in from a mesh file filename.

source
Trixi.UnstructuredSortedBoundaryTypesType
UnstructuredSortedBoundaryTypes

General container to sort the boundary conditions by type for some unstructured meshes/solvers. It stores a set of global indices for each boundary condition type to expedite computation during the call to calc_boundary_flux!. The original dictionary form of the boundary conditions set by the user in the elixir file is also stored for printing.

source
Trixi.ViscousFormulationLocalDGType
ViscousFormulationLocalDG(penalty_parameter)

The local DG (LDG) flux from "The Local Discontinuous Galerkin Method for Time-Dependent Convection-Diffusion Systems" by Cockburn and Shu (1998).

Note that, since this implementation does not involve the parabolic "upwinding" vector, the LDG solver is equivalent to ViscousFormulationBassiRebay1 with an LDG-type penalization.

source
Trixi.VisualizationCallbackMethod
VisualizationCallback(; interval=0,
                         solution_variables=cons2prim,
                         variable_names=[],
                         show_mesh=false,
                         plot_data_creator=PlotData2D,
                         plot_creator=show_plot,
-                        plot_arguments...)

Create a callback that visualizes results during a simulation, also known as in-situ visualization.

Experimental implementation

This is an experimental feature and may change in any future releases.

The interval specifies the number of time step iterations after which a new plot is generated. The available variables to plot are configured with the solution_variables parameter, which acts the same way as for the SaveSolutionCallback. The variables to be actually plotted can be selected by providing a single string or a list of strings to variable_names, and if show_mesh is true, an additional plot with the mesh will be generated.

To customize the generated figure, plot_data_creator allows to use different plot data types. With plot_creator you can further specify an own function to visualize results, which must support the same interface as the default implementation show_plot. All remaining keyword arguments are collected and passed as additional arguments to the plotting command.

source
Trixi.VolumeIntegralFluxDifferencingType
VolumeIntegralFluxDifferencing(volume_flux)

Volume integral type for DG methods based on SBP operators and flux differencing using a symmetric two-point volume_flux. This volume_flux needs to satisfy the interface of numerical fluxes in Trixi.jl.

References

source
Trixi.VolumeIntegralPureLGLFiniteVolumeType
VolumeIntegralPureLGLFiniteVolume(volume_flux_fv)

A volume integral that only uses the subcell finite volume schemes of the VolumeIntegralShockCapturingHG.

This gives a formally O(1)-accurate finite volume scheme on an LGL-type subcell mesh (LGL = Legendre-Gauss-Lobatto).

Experimental implementation

This is an experimental feature and may change in future releases.

References

  • Hennemann, Gassner (2020) "A provably entropy stable subcell shock capturing approach for high order split form DG" arXiv: 2008.12044
source
Trixi.VolumeIntegralShockCapturingHGType
VolumeIntegralShockCapturingHG(indicator; volume_flux_dg=flux_central,
-                                          volume_flux_fv=flux_lax_friedrichs)

Shock-capturing volume integral type for DG methods using a convex blending of the finite volume method with numerical flux volume_flux_fv and the VolumeIntegralFluxDifferencing with volume flux volume_flux_dg. The amount of blending is determined by the indicator, e.g., IndicatorHennemannGassner.

References

  • Hennemann, Gassner (2020) "A provably entropy stable subcell shock capturing approach for high order split form DG" arXiv: 2008.12044
source
Trixi.VolumeIntegralSubcellLimitingType
VolumeIntegralSubcellLimiting(limiter;
-                              volume_flux_dg, volume_flux_fv)

A subcell limiting volume integral type for DG methods based on subcell blending approaches with a low-order FV method. Used with limiter SubcellLimiterIDP.

Experimental implementation

This is an experimental feature and may change in future releases.

source
Trixi.VolumeIntegralUpwindType
VolumeIntegralUpwind(splitting)

Specialized volume integral for finite difference summation-by-parts (FDSBP) solvers. Can be used together with the upwind SBP operators of Mattsson (2017) implemented in SummationByPartsOperators.jl. The splitting controls the discretization.

See also splitting_steger_warming, splitting_lax_friedrichs, splitting_vanleer_haenel.

References

Experimental implementation (upwind SBP)

This is an experimental feature and may change in future releases.

source
Trixi.VolumeIntegralWeakFormType
VolumeIntegralWeakForm()

The classical weak form volume integral type for DG methods as explained in standard textbooks.

References

VolumeIntegralWeakForm() is only implemented for conserved terms as non-conservative terms should always be discretized in conjunction with a flux-splitting scheme, see VolumeIntegralFluxDifferencing. This treatment is required to achieve, e.g., entropy-stability or well-balancedness.

source
Base.getindexMethod
Base.getindex(pd::AbstractPlotData, variable_name)

Extract a single variable variable_name from pd for plotting with Plots.plot.

Experimental implementation

This is an experimental feature and may change in future releases.

source
Base.resize!Method
resize!(c::AbstractContainer, new_length) -> AbstractContainer

Resize c to contain new_length elements. If new_length is smaller than the current container length, the first new_length elements will be retained. If new_length is larger, the new elements are invalidated.

source
PolynomialBases.compute_coefficientsMethod
compute_coefficients(func, t, semi::AbstractSemidiscretization)

Compute the discrete coefficients of the continuous function func at time t associated with the semidiscretization semi. For example, the discrete coefficients of func for a discontinuous Galerkin spectral element method (DGSEM) are the values of func at the Lobatto-Legendre nodes. Similarly, a classical finite difference method will use the values of func at the nodes of the grid assoociated with the semidiscretization semi.

For semidiscretizations semi associated with an initial condition, func can be omitted to use the given initial condition at time t.

source
PolynomialBases.integrateMethod
integrate(f, u, basis::LobattoLegendreBasis)

Map the function f to the coefficients u and integrate with respect to the quadrature rule given by basis.

source
PolynomialBases.integrateMethod
integrate([func=(u_node,equations)->u_node,] u_ode, semi::AbstractSemidiscretization; normalize=true)

Call func(u_node, equations) for each vector of nodal variables u_node in u_ode and integrate the result using a quadrature associated with the semidiscretization semi.

If normalize is true, the result is divided by the total volume of the computational domain.

source
SummationByPartsOperators.semidiscretizeMethod
semidiscretize(semi::SemidiscretizationHyperbolicParabolic, tspan)

Wrap the semidiscretization semi as a split ODE problem in the time interval tspan that can be passed to solve from the SciML ecosystem. The parabolic right-hand side is the first function of the split ODE problem and will be used by default by the implicit part of IMEX methods from the SciML ecosystem.

source
SummationByPartsOperators.semidiscretizeMethod
semidiscretize(semi::AbstractSemidiscretization, tspan, restart_file::AbstractString)

Wrap the semidiscretization semi as an ODE problem in the time interval tspan that can be passed to solve from the SciML ecosystem. The initial condition etc. is taken from the restart_file.

source
Trixi.DGMultiBasisMethod
DGMultiBasis(element_type, polydeg; approximation_type = Polynomial(), kwargs...)

Constructs a basis for DGMulti solvers. Returns a "StartUpDG.RefElemData" object. The kwargs arguments are additional keyword arguments for RefElemData, such as quad_rule_vol. These are the same as the RefElemData_kwargs used in DGMulti. For more info, see the StartUpDG.jl docs.

source
Trixi.P4estMeshCubedSphereMethod
P4estMeshCubedSphere(trees_per_face_dimension, layers, inner_radius, thickness;
+                        plot_arguments...)

Create a callback that visualizes results during a simulation, also known as in-situ visualization.

Experimental implementation

This is an experimental feature and may change in any future releases.

The interval specifies the number of time step iterations after which a new plot is generated. The available variables to plot are configured with the solution_variables parameter, which acts the same way as for the SaveSolutionCallback. The variables to be actually plotted can be selected by providing a single string or a list of strings to variable_names, and if show_mesh is true, an additional plot with the mesh will be generated.

To customize the generated figure, plot_data_creator allows to use different plot data types. With plot_creator you can further specify an own function to visualize results, which must support the same interface as the default implementation show_plot. All remaining keyword arguments are collected and passed as additional arguments to the plotting command.

source
Trixi.VolumeIntegralFluxDifferencingType
VolumeIntegralFluxDifferencing(volume_flux)

Volume integral type for DG methods based on SBP operators and flux differencing using a symmetric two-point volume_flux. This volume_flux needs to satisfy the interface of numerical fluxes in Trixi.jl.

References

source
Trixi.VolumeIntegralPureLGLFiniteVolumeType
VolumeIntegralPureLGLFiniteVolume(volume_flux_fv)

A volume integral that only uses the subcell finite volume schemes of the VolumeIntegralShockCapturingHG.

This gives a formally O(1)-accurate finite volume scheme on an LGL-type subcell mesh (LGL = Legendre-Gauss-Lobatto).

Experimental implementation

This is an experimental feature and may change in future releases.

References

  • Hennemann, Gassner (2020) "A provably entropy stable subcell shock capturing approach for high order split form DG" arXiv: 2008.12044
source
Trixi.VolumeIntegralShockCapturingHGType
VolumeIntegralShockCapturingHG(indicator; volume_flux_dg=flux_central,
+                                          volume_flux_fv=flux_lax_friedrichs)

Shock-capturing volume integral type for DG methods using a convex blending of the finite volume method with numerical flux volume_flux_fv and the VolumeIntegralFluxDifferencing with volume flux volume_flux_dg. The amount of blending is determined by the indicator, e.g., IndicatorHennemannGassner.

References

  • Hennemann, Gassner (2020) "A provably entropy stable subcell shock capturing approach for high order split form DG" arXiv: 2008.12044
source
Trixi.VolumeIntegralSubcellLimitingType
VolumeIntegralSubcellLimiting(limiter;
+                              volume_flux_dg, volume_flux_fv)

A subcell limiting volume integral type for DG methods based on subcell blending approaches with a low-order FV method. Used with limiter SubcellLimiterIDP.

Experimental implementation

This is an experimental feature and may change in future releases.

source
Trixi.VolumeIntegralUpwindType
VolumeIntegralUpwind(splitting)

Specialized volume integral for finite difference summation-by-parts (FDSBP) solvers. Can be used together with the upwind SBP operators of Mattsson (2017) implemented in SummationByPartsOperators.jl. The splitting controls the discretization.

See also splitting_steger_warming, splitting_lax_friedrichs, splitting_vanleer_haenel.

References

Experimental implementation (upwind SBP)

This is an experimental feature and may change in future releases.

source
Trixi.VolumeIntegralWeakFormType
VolumeIntegralWeakForm()

The classical weak form volume integral type for DG methods as explained in standard textbooks.

References

VolumeIntegralWeakForm() is only implemented for conserved terms as non-conservative terms should always be discretized in conjunction with a flux-splitting scheme, see VolumeIntegralFluxDifferencing. This treatment is required to achieve, e.g., entropy-stability or well-balancedness.

source
Base.getindexMethod
Base.getindex(pd::AbstractPlotData, variable_name)

Extract a single variable variable_name from pd for plotting with Plots.plot.

Experimental implementation

This is an experimental feature and may change in future releases.

source
Base.resize!Method
resize!(c::AbstractContainer, new_length) -> AbstractContainer

Resize c to contain new_length elements. If new_length is smaller than the current container length, the first new_length elements will be retained. If new_length is larger, the new elements are invalidated.

source
PolynomialBases.compute_coefficientsMethod
compute_coefficients(func, t, semi::AbstractSemidiscretization)

Compute the discrete coefficients of the continuous function func at time t associated with the semidiscretization semi. For example, the discrete coefficients of func for a discontinuous Galerkin spectral element method (DGSEM) are the values of func at the Lobatto-Legendre nodes. Similarly, a classical finite difference method will use the values of func at the nodes of the grid assoociated with the semidiscretization semi.

For semidiscretizations semi associated with an initial condition, func can be omitted to use the given initial condition at time t.

source
PolynomialBases.integrateMethod
integrate(f, u, basis::LobattoLegendreBasis)

Map the function f to the coefficients u and integrate with respect to the quadrature rule given by basis.

source
PolynomialBases.integrateMethod
integrate([func=(u_node,equations)->u_node,] u_ode, semi::AbstractSemidiscretization; normalize=true)

Call func(u_node, equations) for each vector of nodal variables u_node in u_ode and integrate the result using a quadrature associated with the semidiscretization semi.

If normalize is true, the result is divided by the total volume of the computational domain.

source
SummationByPartsOperators.semidiscretizeMethod
semidiscretize(semi::SemidiscretizationHyperbolicParabolic, tspan)

Wrap the semidiscretization semi as a split ODE problem in the time interval tspan that can be passed to solve from the SciML ecosystem. The parabolic right-hand side is the first function of the split ODE problem and will be used by default by the implicit part of IMEX methods from the SciML ecosystem.

source
SummationByPartsOperators.semidiscretizeMethod
semidiscretize(semi::AbstractSemidiscretization, tspan, restart_file::AbstractString)

Wrap the semidiscretization semi as an ODE problem in the time interval tspan that can be passed to solve from the SciML ecosystem. The initial condition etc. is taken from the restart_file.

source
Trixi.DGMultiBasisMethod
DGMultiBasis(element_type, polydeg; approximation_type = Polynomial(), kwargs...)

Constructs a basis for DGMulti solvers. Returns a "StartUpDG.RefElemData" object. The kwargs arguments are additional keyword arguments for RefElemData, such as quad_rule_vol. These are the same as the RefElemData_kwargs used in DGMulti. For more info, see the StartUpDG.jl docs.

source
Trixi.P4estMeshCubedSphereMethod
P4estMeshCubedSphere(trees_per_face_dimension, layers, inner_radius, thickness;
                      polydeg, RealT=Float64,
                      initial_refinement_level=0, unsaved_changes=true,
-                     p4est_partition_allow_for_coarsening=true)

Build a "Cubed Sphere" mesh as P4estMesh with 6 * trees_per_face_dimension^2 * layers trees.

The mesh will have two boundaries, :inside and :outside.

Arguments

  • trees_per_face_dimension::Integer: the number of trees in the first two local dimensions of each face.
  • layers::Integer: the number of trees in the third local dimension of each face, i.e., the number of layers of the sphere.
  • inner_radius::Integer: the inner radius of the sphere.
  • thickness::Integer: the thickness of the sphere. The outer radius will be inner_radius + thickness.
  • polydeg::Integer: polynomial degree used to store the geometry of the mesh. The mapping will be approximated by an interpolation polynomial of the specified degree for each tree.
  • RealT::Type: the type that should be used for coordinates.
  • initial_refinement_level::Integer: refine the mesh uniformly to this level before the simulation starts.
  • unsaved_changes::Bool: if set to true, the mesh will be saved to a mesh file.
  • p4est_partition_allow_for_coarsening::Bool: Must be true when using AMR to make mesh adaptivity independent of domain partitioning. Should be false for static meshes to permit more fine-grained partitioning.
source
Trixi.PlotData2DMethod
PlotData2D(u, semi [or mesh, equations, solver, cache];
+                     p4est_partition_allow_for_coarsening=true)

Build a "Cubed Sphere" mesh as P4estMesh with 6 * trees_per_face_dimension^2 * layers trees.

The mesh will have two boundaries, :inside and :outside.

Arguments

  • trees_per_face_dimension::Integer: the number of trees in the first two local dimensions of each face.
  • layers::Integer: the number of trees in the third local dimension of each face, i.e., the number of layers of the sphere.
  • inner_radius::Integer: the inner radius of the sphere.
  • thickness::Integer: the thickness of the sphere. The outer radius will be inner_radius + thickness.
  • polydeg::Integer: polynomial degree used to store the geometry of the mesh. The mapping will be approximated by an interpolation polynomial of the specified degree for each tree.
  • RealT::Type: the type that should be used for coordinates.
  • initial_refinement_level::Integer: refine the mesh uniformly to this level before the simulation starts.
  • unsaved_changes::Bool: if set to true, the mesh will be saved to a mesh file.
  • p4est_partition_allow_for_coarsening::Bool: Must be true when using AMR to make mesh adaptivity independent of domain partitioning. Should be false for static meshes to permit more fine-grained partitioning.
source
Trixi.PlotData2DMethod
PlotData2D(u, semi [or mesh, equations, solver, cache];
            solution_variables=nothing,
            grid_lines=true, max_supported_level=11, nvisnodes=nothing,
            slice=:xy, point=(0.0, 0.0, 0.0))

Create a new PlotData2D object that can be used for visualizing 2D/3D DGSEM solution data array u with Plots.jl. All relevant geometrical information is extracted from the semidiscretization semi. By default, the primitive variables (if existent) or the conservative variables (otherwise) from the solution are used for plotting. This can be changed by passing an appropriate conversion function to solution_variables.

If grid_lines is true, also extract grid vertices for visualizing the mesh. The output resolution is indirectly set via max_supported_level: all data is interpolated to 2^max_supported_level uniformly distributed points in each spatial direction, also setting the maximum allowed refinement level in the solution. nvisnodes specifies the number of visualization nodes to be used. If it is nothing, twice the number of solution DG nodes are used for visualization, and if set to 0, exactly the number of nodes in the DG elements are used.

When visualizing data from a three-dimensional simulation, a 2D slice is extracted for plotting. slice specifies the plane that is being sliced and may be :xy, :xz, or :yz. The slice position is specified by a point that lies on it, which defaults to (0.0, 0.0, 0.0). Both of these values are ignored when visualizing 2D data.

Experimental implementation

This is an experimental feature and may change in future releases.

Examples

julia> using Trixi, Plots
@@ -382,200 +382,200 @@
 
 julia> plot(pd["scalar"]) # To plot only a single variable
 
-julia> plot!(getmesh(pd)) # To add grid lines to the plot
source
Trixi.PlotData2DMethod
PlotData2D(sol; kwargs...)

Create a PlotData2D object from a solution object created by either OrdinaryDiffEq.solve! (which returns a SciMLBase.ODESolution) or Trixi.jl's own solve! (which returns a TimeIntegratorSolution).

Experimental implementation

This is an experimental feature and may change in future releases.

source
Trixi.ScalarPlotData2DMethod
ScalarPlotData2D(u, semi::AbstractSemidiscretization; kwargs...)

Returns an PlotData2DTriangulated object which is used to visualize a single scalar field. u should be an array whose entries correspond to values of the scalar field at nodal points.

source
Trixi.SummaryCallbackFunction
SummaryCallback()

Create and return a callback that prints a human-readable summary of the simulation setup at the beginning of a simulation and then resets the timer. When the returned callback is executed directly, the current timer values are shown.

source
Trixi.adapt_to_mesh_level!Method
adapt_to_mesh_level!(u_ode, semi, level)
-adapt_to_mesh_level!(sol::Trixi.TrixiODESolution, level)

Like adapt_to_mesh_level, but modifies the solution and parts of the semidiscretization (mesh and caches) in place.

source
Trixi.adapt_to_mesh_levelMethod
adapt_to_mesh_level(u_ode, semi, level)
-adapt_to_mesh_level(sol::Trixi.TrixiODESolution, level)

Use the regular adaptive mesh refinement routines to adaptively refine/coarsen the solution u_ode with semidiscretization semi towards a uniformly refined grid with refinement level level. The solution and semidiscretization are copied such that the original objects remain unaltered.

A convenience method accepts an ODE solution object, from which solution and semidiscretization are extracted as needed.

See also: adapt_to_mesh_level!

source
Trixi.PlotData2DMethod
PlotData2D(sol; kwargs...)

Create a PlotData2D object from a solution object created by either OrdinaryDiffEq.solve! (which returns a SciMLBase.ODESolution) or Trixi.jl's own solve! (which returns a TimeIntegratorSolution).

Experimental implementation

This is an experimental feature and may change in future releases.

source
Trixi.ScalarPlotData2DMethod
ScalarPlotData2D(u, semi::AbstractSemidiscretization; kwargs...)

Returns an PlotData2DTriangulated object which is used to visualize a single scalar field. u should be an array whose entries correspond to values of the scalar field at nodal points.

source
Trixi.SummaryCallbackFunction
SummaryCallback()

Create and return a callback that prints a human-readable summary of the simulation setup at the beginning of a simulation and then resets the timer. When the returned callback is executed directly, the current timer values are shown.

source
Trixi.adapt_to_mesh_level!Method
adapt_to_mesh_level!(u_ode, semi, level)
+adapt_to_mesh_level!(sol::Trixi.TrixiODESolution, level)

Like adapt_to_mesh_level, but modifies the solution and parts of the semidiscretization (mesh and caches) in place.

source
Trixi.adapt_to_mesh_levelMethod
adapt_to_mesh_level(u_ode, semi, level)
+adapt_to_mesh_level(sol::Trixi.TrixiODESolution, level)

Use the regular adaptive mesh refinement routines to adaptively refine/coarsen the solution u_ode with semidiscretization semi towards a uniformly refined grid with refinement level level. The solution and semidiscretization are copied such that the original objects remain unaltered.

A convenience method accepts an ODE solution object, from which solution and semidiscretization are extracted as needed.

See also: adapt_to_mesh_level!

source
Trixi.boundary_condition_noslip_wallMethod
boundary_condition_noslip_wall(u_inner, orientation, direction, x, t,
                                surface_flux_function,
-                               equations::LatticeBoltzmannEquations2D)

No-slip wall boundary condition using the bounce-back approach.

source
Trixi.boundary_condition_slip_wallMethod
boundary_condition_slip_wall(u_inner, normal_direction, x, t, surface_flux_function,
-                             equations::AcousticPerturbationEquations2D)

Use an orthogonal projection of the perturbed velocities to zero out the normal velocity while retaining the possibility of a tangential velocity in the boundary state. Further details are available in the paper:

  • Marcus Bauer, Jürgen Dierke and Roland Ewert (2011) Application of a discontinuous Galerkin method to discretize acoustic perturbation equations DOI: 10.2514/1.J050333
source
Trixi.boundary_condition_slip_wallMethod
boundary_condition_slip_wall(u_inner, normal_direction, x, t, surface_flux_function,
-                             equations::CompressibleEulerEquations2D)

Determine the boundary numerical surface flux for a slip wall condition. Imposes a zero normal velocity at the wall. Density is taken from the internal solution state and pressure is computed as an exact solution of a 1D Riemann problem. Further details about this boundary state are available in the paper:

  • J. J. W. van der Vegt and H. van der Ven (2002) Slip flow boundary conditions in discontinuous Galerkin discretizations of the Euler equations of gas dynamics PDF

Details about the 1D pressure Riemann solution can be found in Section 6.3.3 of the book

  • Eleuterio F. Toro (2009) Riemann Solvers and Numerical Methods for Fluid Dynamics: A Practical Introduction 3rd edition DOI: 10.1007/b79761

Should be used together with UnstructuredMesh2D.

source
Trixi.boundary_condition_slip_wallMethod
boundary_condition_slip_wall(u_inner, normal_direction, x, t, surface_flux_function,
-                             equations::CompressibleEulerEquations3D)

Determine the boundary numerical surface flux for a slip wall condition. Imposes a zero normal velocity at the wall. Density is taken from the internal solution state and pressure is computed as an exact solution of a 1D Riemann problem. Further details about this boundary state are available in the paper:

  • J. J. W. van der Vegt and H. van der Ven (2002) Slip flow boundary conditions in discontinuous Galerkin discretizations of the Euler equations of gas dynamics PDF

Details about the 1D pressure Riemann solution can be found in Section 6.3.3 of the book

  • Eleuterio F. Toro (2009) Riemann Solvers and Numerical Methods for Fluid Dynamics: A Practical Introduction 3rd edition DOI: 10.1007/b79761
source
Trixi.boundary_condition_slip_wallMethod
boundary_condition_slip_wall(u_inner, normal_direction, x, t, surface_flux_function,
-                             equations::ShallowWaterEquations2D)

Create a boundary state by reflecting the normal velocity component and keep the tangential velocity component unchanged. The boundary water height is taken from the internal value. For details see Section 9.2.5 of the book:

  • Eleuterio F. Toro (2001) Shock-Capturing Methods for Free-Surface Shallow Flows 1st edition ISBN 0471987662
source
Trixi.boundary_condition_slip_wallMethod
boundary_condition_slip_wall(u_inner, normal_direction, x, t, surface_flux_function,
-                             equations::ShallowWaterTwoLayerEquations2D)

Create a boundary state by reflecting the normal velocity component and keep the tangential velocity component unchanged. The boundary water height is taken from the internal value.

For details see Section 9.2.5 of the book:

  • Eleuterio F. Toro (2001) Shock-Capturing Methods for Free-Surface Shallow Flows 1st edition ISBN 0471987662
source
Trixi.boundary_condition_slip_wallMethod
boundary_condition_slip_wall(u_inner, orientation, direction, x, t,
-                             surface_flux_function, equations::CompressibleEulerEquations1D)

Determine the boundary numerical surface flux for a slip wall condition. Imposes a zero normal velocity at the wall. Density is taken from the internal solution state and pressure is computed as an exact solution of a 1D Riemann problem. Further details about this boundary state are available in the paper:

  • J. J. W. van der Vegt and H. van der Ven (2002) Slip flow boundary conditions in discontinuous Galerkin discretizations of the Euler equations of gas dynamics PDF

    Should be used together with TreeMesh.

source
Trixi.boundary_condition_slip_wallMethod
boundary_condition_slip_wall(u_inner, orientation_or_normal, x, t, surface_flux_function,
-                              equations::ShallowWaterEquations1D)

Create a boundary state by reflecting the normal velocity component and keep the tangential velocity component unchanged. The boundary water height is taken from the internal value.

For details see Section 9.2.5 of the book:

  • Eleuterio F. Toro (2001) Shock-Capturing Methods for Free-Surface Shallow Flows 1st edition ISBN 0471987662
source
Trixi.boundary_condition_slip_wallMethod
boundary_condition_slip_wall(u_inner, orientation_or_normal, x, t, surface_flux_function,
-                             equations::ShallowWaterTwoLayerEquations1D)

Create a boundary state by reflecting the normal velocity component and keep the tangential velocity component unchanged. The boundary water height is taken from the internal value.

For details see Section 9.2.5 of the book:

  • Eleuterio F. Toro (2001) Shock-Capturing Methods for Free-Surface Shallow Flows 1st edition ISBN 0471987662
source
Trixi.boundary_condition_wallMethod
boundary_condition_wall(u_inner, orientation, direction, x, t, surface_flux_function,
-                        equations::AcousticPerturbationEquations2D)

Boundary conditions for a solid wall.

source
Trixi.boundary_condition_wallMethod
boundary_condition_wall(u_inner, orientation, direction, x, t, surface_flux_function,
-                            equations::LinearizedEulerEquations2D)

Boundary conditions for a solid wall.

source
Trixi.calc_error_normsMethod
calc_error_norms([func=(u_node,equations)->u_node,] u_ode, t, analyzer, semi::AbstractSemidiscretization, cache_analysis)

Calculate discrete L2 and L∞ error norms of func applied to each nodal variable u_node in u_ode. If no exact solution is available, "errors" are calculated using some reference state and can be useful for regression tests.

source
Trixi.calc_fast_wavespeed_roeMethod
calc_fast_wavespeed_roe(u_ll, u_rr, direction, equations::IdealGlmMhdEquations1D)

Compute the fast magnetoacoustic wave speed using Roe averages as given by

  • Cargo and Gallice (1997) Roe Matrices for Ideal MHD and Systematic Construction of Roe Matrices for Systems of Conservation Laws DOI: 10.1006/jcph.1997.5773
source
Trixi.calc_fast_wavespeed_roeMethod
calc_fast_wavespeed_roe(u_ll, u_rr, orientation_or_normal_direction, equations::IdealGlmMhdEquations2D)

Compute the fast magnetoacoustic wave speed using Roe averages as given by

  • Cargo and Gallice (1997) Roe Matrices for Ideal MHD and Systematic Construction of Roe Matrices for Systems of Conservation Laws DOI: 10.1006/jcph.1997.5773
source
Trixi.calc_fast_wavespeed_roeMethod
calc_fast_wavespeed_roe(u_ll, u_rr, orientation_or_normal_direction, equations::IdealGlmMhdEquations3D)

Compute the fast magnetoacoustic wave speed using Roe averages as given by

  • Cargo and Gallice (1997) Roe Matrices for Ideal MHD and Systematic Construction of Roe Matrices for Systems of Conservation Laws DOI: 10.1006/jcph.1997.5773
source
Trixi.calc_wavespeed_roeMethod
calc_wavespeed_roe(u_ll, u_rr, direction::Integer,
-                   equations::ShallowWaterEquations1D)

Calculate Roe-averaged velocity v_roe and wavespeed c_roe = sqrt{g * h_roe} See for instance equation (62) in

  • Paul A. Ullrich, Christiane Jablonowski, and Bram van Leer (2010) High-order finite-volume methods for the shallow-water equations on the sphere DOI: 10.1016/j.jcp.2010.04.044

Or equation (9.17) in this lecture notes.

source
Trixi.calc_wavespeed_roeMethod
calc_wavespeed_roe(u_ll, u_rr, direction::Integer,
-                   equations::ShallowWaterEquations2D)

Calculate Roe-averaged velocity v_roe and wavespeed c_roe = sqrt{g * h_roe} depending on direction. See for instance equation (62) in

  • Paul A. Ullrich, Christiane Jablonowski, and Bram van Leer (2010) High-order finite-volume methods for the shallow-water equations on the sphere DOI: 10.1016/j.jcp.2010.04.044

Or this slides, slides 8 and 9.

source
Trixi.collision_bgkMethod
collision_bgk(u, dt, equations::LatticeBoltzmannEquations2D)

Collision operator for the Bhatnagar, Gross, and Krook (BGK) model.

source
Trixi.collision_bgkMethod
collision_bgk(u, dt, equations::LatticeBoltzmannEquations3D)

Collision operator for the Bhatnagar, Gross, and Krook (BGK) model.

source
Trixi.cons2consMethod
cons2cons(u, equations)

Return the conserved variables u. While this function is as trivial as identity, it is also as useful.

source
Trixi.cons2entropyFunction
cons2entropy(u, equations)

Convert the conserved variables u to the entropy variables for a given set of equations with chosen standard entropy.

u is a vector type of the correct length nvariables(equations). Notice the function doesn't include any error checks for the purpose of efficiency, so please make sure your input is correct. The inverse conversion is performed by entropy2cons.

source
Trixi.cons2primFunction
cons2prim(u, equations)

Convert the conserved variables u to the primitive variables for a given set of equations. u is a vector type of the correct length nvariables(equations). Notice the function doesn't include any error checks for the purpose of efficiency, so please make sure your input is correct. The inverse conversion is performed by prim2cons.

source
Trixi.convergence_testMethod
convergence_test([mod::Module=Main,] elixir::AbstractString, iterations; kwargs...)

Run iterations Trixi.jl simulations using the setup given in elixir and compute the experimental order of convergence (EOC) in the $L^2$ and $L^\infty$ norm. In each iteration, the resolution of the respective mesh will be doubled. Additional keyword arguments kwargs... and the optional module mod are passed directly to trixi_include.

This function assumes that the spatial resolution is set via the keywords initial_refinement_level (an integer) or cells_per_dimension (a tuple of integers, one per spatial dimension).

source
Trixi.default_example_unstructuredMethod
default_example_unstructured()

Return the path to an example elixir that can be used to quickly see Trixi.jl in action on an UnstructuredMesh2D. This simulation is run on the example curved, unstructured mesh given in the Trixi.jl documentation regarding unstructured meshes.

source
Trixi.densityMethod
density(p::Real, equations::LatticeBoltzmannEquations2D)
-density(u, equations::LatticeBoltzmannEquations2D)

Calculate the macroscopic density from the pressure p or the particle distribution functions u.

source
Trixi.densityMethod
density(p::Real, equations::LatticeBoltzmannEquations3D)
-density(u, equations::LatticeBoltzmannEquations3D)

Calculate the macroscopic density from the pressure p or the particle distribution functions u.

source
Trixi.each_dof_globalMethod
each_dof_global(mesh::DGMultiMesh, dg::DGMulti, other_args...)

Return an iterator over the indices that specify the location in relevant data structures for the degrees of freedom (DOF) in dg. In particular, not the DOFs themselves are returned.

source
Trixi.each_face_nodeMethod
each_face_node(mesh::DGMultiMesh, dg::DGMulti, other_args...)

Return an iterator over the indices that specify the location in relevant data structures for the face nodes in dg. In particular, not the face_nodes themselves are returned.

source
Trixi.each_face_node_globalMethod
each_face_node_global(mesh::DGMultiMesh, dg::DGMulti, other_args...)

Return an iterator over the indices that specify the location in relevant data structures for the face nodes in mesh. In particular, not the face nodes themselves are returned.

source
Trixi.each_quad_nodeMethod
each_quad_node(mesh::DGMultiMesh, dg::DGMulti, other_args...)

Return an iterator over the indices that specify the location in relevant data structures for the quadrature nodes in dg. In particular, not the quadrature nodes themselves are returned.

source
Trixi.each_quad_node_globalMethod
each_quad_node_global(mesh::DGMultiMesh, dg::DGMulti, other_args...)

Return an iterator over the indices that specify the location in relevant data structures for the global quadrature nodes in mesh. In particular, not the quadrature nodes themselves are returned.

source
Trixi.eachboundaryMethod
eachboundary(dg::DG, cache)

Return an iterator over the indices that specify the location in relevant data structures for the boundaries in cache. In particular, not the boundaries themselves are returned.

source
Trixi.eachcomponentMethod
eachcomponent(equations::AbstractCompressibleEulerMulticomponentEquations)

Return an iterator over the indices that specify the location in relevant data structures for the components in AbstractCompressibleEulerMulticomponentEquations. In particular, not the components themselves are returned.

source
Trixi.eachcomponentMethod
eachcomponent(equations::AbstractIdealGlmMhdMulticomponentEquations)

Return an iterator over the indices that specify the location in relevant data structures for the components in AbstractIdealGlmMhdMulticomponentEquations. In particular, not the components themselves are returned.

source
Trixi.eachdimMethod
eachdim(mesh)

Return an iterator over the indices that specify the location in relevant data structures for the dimensions in AbstractTree. In particular, not the dimensions themselves are returned.

source
Trixi.eachdirectionMethod
eachdirection(tree::AbstractTree)

Return an iterator over the indices that specify the location in relevant data structures for the directions in AbstractTree. In particular, not the directions themselves are returned.

source
Trixi.eachelementMethod
eachelement(dg::DG, cache)

Return an iterator over the indices that specify the location in relevant data structures for the elements in cache. In particular, not the elements themselves are returned.

source
Trixi.eachelementMethod
eachelement(mesh::DGMultiMesh, dg::DGMulti, other_args...)

Return an iterator over the indices that specify the location in relevant data structures for the elements in mesh. In particular, not the elements themselves are returned.

source
Trixi.eachelementMethod
eachelement(elements::ElementContainer1D)

Return an iterator over the indices that specify the location in relevant data structures for the elements in elements. In particular, not the elements themselves are returned.

source
Trixi.eachelementMethod
eachelement(elements::ElementContainer2D)

Return an iterator over the indices that specify the location in relevant data structures for the elements in elements. In particular, not the elements themselves are returned.

source
Trixi.eachelementMethod
eachelement(elements::ElementContainer3D)

Return an iterator over the indices that specify the location in relevant data structures for the elements in elements. In particular, not the elements themselves are returned.

source
Trixi.eachelementMethod
eachelement(elements::UnstructuredElementContainer2D)

Return an iterator over the indices that specify the location in relevant data structures for the elements in elements. In particular, not the elements themselves are returned.

source
Trixi.eachinterfaceMethod
eachinterface(dg::DG, cache)

Return an iterator over the indices that specify the location in relevant data structures for the interfaces in cache. In particular, not the interfaces themselves are returned.

source
Trixi.eachmortarMethod
eachmortar(dg::DG, cache)

Return an iterator over the indices that specify the location in relevant data structures for the mortars in cache. In particular, not the mortars themselves are returned.

source
Trixi.eachmpiinterfaceMethod
eachmpiinterface(dg::DG, cache)

Return an iterator over the indices that specify the location in relevant data structures for the MPI interfaces in cache. In particular, not the interfaces themselves are returned.

source
Trixi.eachmpimortarMethod
eachmpimortar(dg::DG, cache)

Return an iterator over the indices that specify the location in relevant data structures for the MPI mortars in cache. In particular, not the mortars themselves are returned.

source
Trixi.eachnodeMethod
eachnode(dg::DG)

Return an iterator over the indices that specify the location in relevant data structures for the nodes in dg. In particular, not the nodes themselves are returned.

source
Trixi.eachnodeMethod
eachnode(basis::LobattoLegendreBasis)

Return an iterator over the indices that specify the location in relevant data structures for the nodes in basis. In particular, not the nodes themselves are returned.

source
Trixi.eachnodeMethod
eachnode(analyzer::LobattoLegendreAnalyzer)

Return an iterator over the indices that specify the location in relevant data structures for the nodes in analyzer. In particular, not the nodes themselves are returned.

source
Trixi.eachvariableMethod
eachvariable(equations::AbstractEquations)

Return an iterator over the indices that specify the location in relevant data structures for the variables in equations. In particular, not the variables themselves are returned.

source
Trixi.energy_internalFunction
energy_internal(u, equations)

Return the internal energy of the conserved variables u for a given set of equations, e.g., the CompressibleEulerEquations2D.

u is a vector of the conserved variables at a single node, i.e., a vector of the correct length nvariables(equations).

source
Trixi.energy_kineticFunction
energy_kinetic(u, equations)

Return the kinetic energy of the conserved variables u for a given set of equations, e.g., the CompressibleEulerEquations2D.

u is a vector of the conserved variables at a single node, i.e., a vector of the correct length nvariables(equations).

source
Trixi.energy_totalFunction
energy_total(u, equations)

Return the total energy of the conserved variables u for a given set of equations, e.g., the CompressibleEulerEquations2D.

u is a vector of the conserved variables at a single node, i.e., a vector of the correct length nvariables(equations).

source
Trixi.entropyFunction
entropy(u, equations)

Return the chosen entropy of the conserved variables u for a given set of equations.

u is a vector of the conserved variables at a single node, i.e., a vector of the correct length nvariables(equations).

source
Trixi.entropy2consFunction
entropy2cons(w, equations)

Convert the entropy variables w based on a standard entropy to the conserved variables for a given set of equations. u is a vector type of the correct length nvariables(equations). Notice the function doesn't include any error checks for the purpose of efficiency, so please make sure your input is correct. The inverse conversion is performed by cons2entropy.

source
Trixi.equilibrium_distributionMethod
equilibrium_distribution(alpha, rho, v1, v2, v3, equations::LatticeBoltzmannEquations3D)

Calculate the local equilibrium distribution for the distribution function with index alpha and given the macroscopic state defined by rho, v1, v2, v3.

source
Trixi.equilibrium_distributionMethod
equilibrium_distribution(alpha, rho, v1, v2, equations::LatticeBoltzmannEquations2D)

Calculate the local equilibrium distribution for the distribution function with index alpha and given the macroscopic state defined by rho, v1, v2.

source
Trixi.examples_dirMethod
examples_dir()

Return the directory where the example files provided with Trixi.jl are located. If Trixi.jl is installed as a regular package (with ]add Trixi), these files are read-only and should not be modified. To find out which files are available, use, e.g., readdir:

Examples

readdir(examples_dir())
source
Trixi.fluxFunction
flux(u, orientation_or_normal, equations)

Given the conservative variables u, calculate the (physical) flux in Cartesian direction orientation::Integer or in arbitrary direction normal::AbstractVector for the corresponding set of governing equations. orientation is 1, 2, and 3 for the x-, y-, and z-directions, respectively.

source
Trixi.fluxMethod
flux(u, normal_direction::AbstractVector, equations::AbstractEquations{1})

Enables calling flux with a non-integer argument normal_direction for one-dimensional equations. Returns the value of flux(u, 1, equations) scaled by normal_direction[1].

source
Trixi.flux_centralMethod
flux_central(u_ll, u_rr, orientation_or_normal_direction, equations::AbstractEquations)

The classical central numerical flux f((u_ll) + f(u_rr)) / 2. When this flux is used as volume flux, the discretization is equivalent to the classical weak form DG method (except floating point errors).

source
Trixi.flux_chan_etalMethod
flux_chan_etal(u_ll, u_rr, orientation,
-               equations::ShallowWaterEquationsQuasi1D)

Total energy conservative (mathematical entropy for quasi 1D shallow water equations) split form. When the bottom topography is nonzero this scheme will be well-balanced when used as a volume_flux. The surface_flux should still use, e.g., FluxPlusDissipation(flux_chan_etal, DissipationLocalLaxFriedrichs()).

Further details are available in the paper:

  • Jesse Chan, Khemraj Shukla, Xinhui Wu, Ruofeng Liu, Prani Nalluri (2023) High order entropy stable schemes for the quasi-one-dimensional shallow water and compressible Euler equations DOI: 10.48550/arXiv.2307.12089
source
Trixi.flux_chandrashekarMethod
flux_chandrashekar(u_ll, u_rr, orientation, equations::CompressibleEulerEquations1D)

Entropy conserving two-point flux by

  • Chandrashekar (2013) Kinetic Energy Preserving and Entropy Stable Finite Volume Schemes for Compressible Euler and Navier-Stokes Equations DOI: 10.4208/cicp.170712.010313a
source
Trixi.flux_chandrashekarMethod
flux_chandrashekar(u_ll, u_rr, orientation, equations::CompressibleEulerEquations2D)

Entropy conserving two-point flux by

  • Chandrashekar (2013) Kinetic Energy Preserving and Entropy Stable Finite Volume Schemes for Compressible Euler and Navier-Stokes Equations DOI: 10.4208/cicp.170712.010313a
source
Trixi.flux_chandrashekarMethod
flux_chandrashekar(u_ll, u_rr, orientation, equations::CompressibleEulerEquations3D)

Entropy conserving two-point flux by

  • Chandrashekar (2013) Kinetic Energy Preserving and Entropy Stable Finite Volume Schemes for Compressible Euler and Navier-Stokes Equations DOI: 10.4208/cicp.170712.010313a
source
Trixi.flux_chandrashekarMethod
flux_chandrashekar(u_ll, u_rr, orientation, equations::CompressibleEulerMulticomponentEquations1D)

Entropy conserving two-point flux by

  • Ayoub Gouasmi, Karthik Duraisamy (2020) "Formulation of Entropy-Stable schemes for the multicomponent compressible Euler equations" arXiv:1904.00972v3 [math.NA] 4 Feb 2020
source
Trixi.flux_chandrashekarMethod
flux_chandrashekar(u_ll, u_rr, orientation, equations::CompressibleEulerMulticomponentEquations2D)

Adaption of the entropy conserving two-point flux by

  • Ayoub Gouasmi, Karthik Duraisamy (2020) "Formulation of Entropy-Stable schemes for the multicomponent compressible Euler equations" arXiv:1904.00972v3 [math.NA] 4 Feb 2020
source
Trixi.flux_derigs_etalMethod
flux_derigs_etal(u_ll, u_rr, orientation, equations::IdealGlmMhdEquations1D)

Entropy conserving two-point flux by

  • Derigs et al. (2018) Ideal GLM-MHD: About the entropy consistent nine-wave magnetic field divergence diminishing ideal magnetohydrodynamics equations DOI: 10.1016/j.jcp.2018.03.002
source
Trixi.flux_derigs_etalMethod
flux_derigs_etal(u_ll, u_rr, orientation, equations::IdealGlmMhdEquations2D)

Entropy conserving two-point flux by

  • Derigs et al. (2018) Ideal GLM-MHD: About the entropy consistent nine-wave magnetic field divergence diminishing ideal magnetohydrodynamics equations DOI: 10.1016/j.jcp.2018.03.002
source
Trixi.flux_derigs_etalMethod
flux_derigs_etal(u_ll, u_rr, orientation, equations::IdealGlmMhdEquations3D)

Entropy conserving two-point flux by

  • Derigs et al. (2018) Ideal GLM-MHD: About the entropy consistent nine-wave magnetic field divergence diminishing ideal magnetohydrodynamics equations DOI: 10.1016/j.jcp.2018.03.002
source
Trixi.flux_derigs_etalMethod
flux_derigs_etal(u_ll, u_rr, orientation, equations::IdealGlmMhdEquations1D)

Entropy conserving two-point flux adapted by

  • Derigs et al. (2018) Ideal GLM-MHD: About the entropy consistent nine-wave magnetic field divergence diminishing ideal magnetohydrodynamics equations for multicomponent DOI: 10.1016/j.jcp.2018.03.002
source
Trixi.flux_derigs_etalMethod
flux_derigs_etal(u_ll, u_rr, orientation, equations::IdealGlmMhdMulticomponentEquations2D)

Entropy conserving two-point flux adapted by

  • Derigs et al. (2018) Ideal GLM-MHD: About the entropy consistent nine-wave magnetic field divergence diminishing ideal magnetohydrodynamics equations for multicomponent DOI: 10.1016/j.jcp.2018.03.002
source
Trixi.flux_es_fjordholm_etalMethod
flux_es_fjordholm_etal(u_ll, u_rr, orientation_or_normal_direction,
-                       equations::ShallowWaterTwoLayerEquations1D)

Entropy stable surface flux for the two-layer shallow water equations. Uses the entropy conservative flux_fjordholm_etal and adds a Lax-Friedrichs type dissipation dependent on the jump of entropy variables.

Further details are available in the paper:

  • Ulrik Skre Fjordholm (2012)

Energy conservative and stable schemes for the two-layer shallow water equations. DOI: 10.1142/9789814417099_0039 It should be noted that the equations are ordered differently and the designation of the upper and lower layer has been changed which leads to a slightly different formulation.

source
Trixi.flux_es_fjordholm_etalMethod
flux_es_fjordholm_etal(u_ll, u_rr, orientation,
-                       equations::ShallowWaterTwoLayerEquations1D)

Entropy stable surface flux for the two-layer shallow water equations. Uses the entropy conservative flux_fjordholm_etal and adds a Lax-Friedrichs type dissipation dependent on the jump of entropy variables.

Further details are available in the paper:

It should be noted that the equations are ordered differently and the designation of the upper and lower layer has been changed which leads to a slightly different formulation.

source
Trixi.flux_fjordholm_etalMethod
flux_fjordholm_etal(u_ll, u_rr, orientation,
-                    equations::ShallowWaterEquations1D)

Total energy conservative (mathematical entropy for shallow water equations). When the bottom topography is nonzero this should only be used as a surface flux otherwise the scheme will not be well-balanced. For well-balancedness in the volume flux use flux_wintermeyer_etal.

Details are available in Eq. (4.1) in the paper:

  • Ulrik S. Fjordholm, Siddhartha Mishr and Eitan Tadmor (2011) Well-balanced and energy stable schemes for the shallow water equations with discontinuous topography DOI: 10.1016/j.jcp.2011.03.042
source
Trixi.flux_fjordholm_etalMethod
flux_fjordholm_etal(u_ll, u_rr, orientation_or_normal_direction,
-                    equations::ShallowWaterEquations2D)

Total energy conservative (mathematical entropy for shallow water equations). When the bottom topography is nonzero this should only be used as a surface flux otherwise the scheme will not be well-balanced. For well-balancedness in the volume flux use flux_wintermeyer_etal.

Details are available in Eq. (4.1) in the paper:

  • Ulrik S. Fjordholm, Siddhartha Mishr and Eitan Tadmor (2011) Well-balanced and energy stable schemes for the shallow water equations with discontinuous topography DOI: 10.1016/j.jcp.2011.03.042
source
Trixi.flux_fjordholm_etalMethod
flux_fjordholm_etal(u_ll, u_rr, orientation,
-                    equations::ShallowWaterTwoLayerEquations1D)

Total energy conservative (mathematical entropy for shallow water equations). When the bottom topography is nonzero this should only be used as a surface flux otherwise the scheme will not be well-balanced. For well-balancedness in the volume flux use flux_wintermeyer_etal.

Details are available in Eq. (4.1) in the paper:

  • Ulrik S. Fjordholm, Siddhartha Mishra and Eitan Tadmor (2011) Well-balanced and energy stable schemes for the shallow water equations with discontinuous topography DOI: 10.1016/j.jcp.2011.03.042

and the application to two layers is shown in the paper:

It should be noted that the equations are ordered differently and the designation of the upper and lower layer has been changed which leads to a slightly different formulation.

source
Trixi.flux_fjordholm_etalMethod
flux_fjordholm_etal(u_ll, u_rr, orientation,
-                    equations::ShallowWaterTwoLayerEquations2D)

Total energy conservative (mathematical entropy for two-layer shallow water equations). When the bottom topography is nonzero this should only be used as a surface flux otherwise the scheme will not be well-balanced. For well-balancedness in the volume flux use flux_wintermeyer_etal.

Details are available in Eq. (4.1) in the paper:

  • Ulrik S. Fjordholm, Siddhartha Mishra and Eitan Tadmor (2011) Well-balanced and energy stable schemes for the shallow water equations with discontinuous topography DOI: 10.1016/j.jcp.2011.03.042

and the application to two layers is shown in the paper:

It should be noted that the equations are ordered differently and the designation of the upper and lower layer has been changed which leads to a slightly different formulation.

source
Trixi.flux_godunovMethod
flux_godunov(u_ll, u_rr, orientation_or_normal_direction,
-             equations::LinearizedEulerEquations2D)

An upwind flux for the linearized Euler equations based on diagonalization of the physical flux matrix. Given the physical flux $Au$, $A=T \Lambda T^{-1}$ with $\Lambda$ being a diagonal matrix that holds the eigenvalues of $A$, decompose $\Lambda = \Lambda^+ + \Lambda^-$ where $\Lambda^+$ and $\Lambda^-$ are diagonal matrices holding the positive and negative eigenvalues of $A$, respectively. Then for left and right states $u_L, u_R$, the numerical flux calculated by this function is given by $A^+ u_L + A^- u_R$ where $A^{\pm} = T \Lambda^{\pm} T^{-1}$.

The diagonalization of the flux matrix can be found in

source
Trixi.flux_hindenlang_gassnerMethod
flux_hindenlang_gassner(u_ll, u_rr, orientation_or_normal_direction,
-                        equations::IdealGlmMhdEquations1D)

Entropy conserving and kinetic energy preserving two-point flux of Hindenlang and Gassner (2019), extending flux_ranocha to the MHD equations.

References

  • Florian Hindenlang, Gregor Gassner (2019) A new entropy conservative two-point flux for ideal MHD equations derived from first principles. Presented at HONOM 2019: European workshop on high order numerical methods for evolutionary PDEs, theory and applications
  • Hendrik Ranocha (2018) Generalised Summation-by-Parts Operators and Entropy Stability of Numerical Methods for Hyperbolic Balance Laws PhD thesis, TU Braunschweig
  • Hendrik Ranocha (2020) Entropy Conserving and Kinetic Energy Preserving Numerical Methods for the Euler Equations Using Summation-by-Parts Operators Proceedings of ICOSAHOM 2018
source
Trixi.flux_hindenlang_gassnerMethod
flux_hindenlang_gassner(u_ll, u_rr, orientation_or_normal_direction,
-                        equations::IdealGlmMhdEquations2D)

Entropy conserving and kinetic energy preserving two-point flux of Hindenlang and Gassner (2019), extending flux_ranocha to the MHD equations.

References

  • Florian Hindenlang, Gregor Gassner (2019) A new entropy conservative two-point flux for ideal MHD equations derived from first principles. Presented at HONOM 2019: European workshop on high order numerical methods for evolutionary PDEs, theory and applications
  • Hendrik Ranocha (2018) Generalised Summation-by-Parts Operators and Entropy Stability of Numerical Methods for Hyperbolic Balance Laws PhD thesis, TU Braunschweig
  • Hendrik Ranocha (2020) Entropy Conserving and Kinetic Energy Preserving Numerical Methods for the Euler Equations Using Summation-by-Parts Operators Proceedings of ICOSAHOM 2018
source
Trixi.flux_hindenlang_gassnerMethod
flux_hindenlang_gassner(u_ll, u_rr, orientation_or_normal_direction,
-                        equations::IdealGlmMhdEquations3D)

Entropy conserving and kinetic energy preserving two-point flux of Hindenlang and Gassner (2019), extending flux_ranocha to the MHD equations.

References

  • Florian Hindenlang, Gregor Gassner (2019) A new entropy conservative two-point flux for ideal MHD equations derived from first principles. Presented at HONOM 2019: European workshop on high order numerical methods for evolutionary PDEs, theory and applications
  • Hendrik Ranocha (2018) Generalised Summation-by-Parts Operators and Entropy Stability of Numerical Methods for Hyperbolic Balance Laws PhD thesis, TU Braunschweig
  • Hendrik Ranocha (2020) Entropy Conserving and Kinetic Energy Preserving Numerical Methods for the Euler Equations Using Summation-by-Parts Operators Proceedings of ICOSAHOM 2018
source
Trixi.flux_hindenlang_gassnerMethod
flux_hindenlang_gassner(u_ll, u_rr, orientation_or_normal_direction,
-                        equations::IdealGlmMhdMulticomponentEquations1D)

Adaption of the entropy conserving and kinetic energy preserving two-point flux of Hindenlang (2019), extending flux_ranocha to the MHD equations.

References

  • Florian Hindenlang, Gregor Gassner (2019) A new entropy conservative two-point flux for ideal MHD equations derived from first principles. Presented at HONOM 2019: European workshop on high order numerical methods for evolutionary PDEs, theory and applications
  • Hendrik Ranocha (2018) Generalised Summation-by-Parts Operators and Entropy Stability of Numerical Methods for Hyperbolic Balance Laws PhD thesis, TU Braunschweig
  • Hendrik Ranocha (2020) Entropy Conserving and Kinetic Energy Preserving Numerical Methods for the Euler Equations Using Summation-by-Parts Operators Proceedings of ICOSAHOM 2018
source
Trixi.flux_hindenlang_gassnerMethod
flux_hindenlang_gassner(u_ll, u_rr, orientation_or_normal_direction,
-                        equations::IdealGlmMhdMulticomponentEquations2D)

Adaption of the entropy conserving and kinetic energy preserving two-point flux of Hindenlang (2019), extending flux_ranocha to the MHD equations.

References

  • Florian Hindenlang, Gregor Gassner (2019) A new entropy conservative two-point flux for ideal MHD equations derived from first principles. Presented at HONOM 2019: European workshop on high order numerical methods for evolutionary PDEs, theory and applications
  • Hendrik Ranocha (2018) Generalised Summation-by-Parts Operators and Entropy Stability of Numerical Methods for Hyperbolic Balance Laws PhD thesis, TU Braunschweig
  • Hendrik Ranocha (2020) Entropy Conserving and Kinetic Energy Preserving Numerical Methods for the Euler Equations Using Summation-by-Parts Operators Proceedings of ICOSAHOM 2018
source
Trixi.flux_kennedy_gruberMethod
flux_kennedy_gruber(u_ll, u_rr, orientation, equations::CompressibleEulerEquations1D)

Kinetic energy preserving two-point flux by

  • Kennedy and Gruber (2008) Reduced aliasing formulations of the convective terms within the Navier-Stokes equations for a compressible fluid DOI: 10.1016/j.jcp.2007.09.020
source
Trixi.flux_kennedy_gruberMethod
flux_kennedy_gruber(u_ll, u_rr, orientation_or_normal_direction,
-                    equations::CompressibleEulerEquations2D)

Kinetic energy preserving two-point flux by

  • Kennedy and Gruber (2008) Reduced aliasing formulations of the convective terms within the Navier-Stokes equations for a compressible fluid DOI: 10.1016/j.jcp.2007.09.020
source
Trixi.flux_kennedy_gruberMethod
flux_kennedy_gruber(u_ll, u_rr, orientation_or_normal_direction,
-                    equations::CompressibleEulerEquations3D)

Kinetic energy preserving two-point flux by

  • Kennedy and Gruber (2008) Reduced aliasing formulations of the convective terms within the Navier-Stokes equations for a compressible fluid DOI: 10.1016/j.jcp.2007.09.020
source
Trixi.flux_nonconservative_audusse_etalMethod
flux_nonconservative_audusse_etal(u_ll, u_rr, orientation::Integer,
-                                  equations::ShallowWaterEquations1D)

Non-symmetric two-point surface flux that discretizes the nonconservative (source) term. The discretization uses the hydrostatic_reconstruction_audusse_etal on the conservative variables.

This hydrostatic reconstruction ensures that the finite volume numerical fluxes remain well-balanced for discontinuous bottom topographies ShallowWaterEquations1D. Should be used together with FluxHydrostaticReconstruction and hydrostatic_reconstruction_audusse_etal in the surface flux to ensure consistency.

Further details on the hydrostatic reconstruction and its motivation can be found in

  • Emmanuel Audusse, François Bouchut, Marie-Odile Bristeau, Rupert Klein, and Benoit Perthame (2004) A fast and stable well-balanced scheme with hydrostatic reconstruction for shallow water flows DOI: 10.1137/S1064827503431090
source
Trixi.boundary_condition_slip_wallMethod
boundary_condition_slip_wall(u_inner, normal_direction, x, t, surface_flux_function,
+                             equations::AcousticPerturbationEquations2D)

Use an orthogonal projection of the perturbed velocities to zero out the normal velocity while retaining the possibility of a tangential velocity in the boundary state. Further details are available in the paper:

  • Marcus Bauer, Jürgen Dierke and Roland Ewert (2011) Application of a discontinuous Galerkin method to discretize acoustic perturbation equations DOI: 10.2514/1.J050333
source
Trixi.boundary_condition_slip_wallMethod
boundary_condition_slip_wall(u_inner, normal_direction, x, t, surface_flux_function,
+                             equations::CompressibleEulerEquations2D)

Determine the boundary numerical surface flux for a slip wall condition. Imposes a zero normal velocity at the wall. Density is taken from the internal solution state and pressure is computed as an exact solution of a 1D Riemann problem. Further details about this boundary state are available in the paper:

  • J. J. W. van der Vegt and H. van der Ven (2002) Slip flow boundary conditions in discontinuous Galerkin discretizations of the Euler equations of gas dynamics PDF

Details about the 1D pressure Riemann solution can be found in Section 6.3.3 of the book

  • Eleuterio F. Toro (2009) Riemann Solvers and Numerical Methods for Fluid Dynamics: A Practical Introduction 3rd edition DOI: 10.1007/b79761

Should be used together with UnstructuredMesh2D.

source
Trixi.boundary_condition_slip_wallMethod
boundary_condition_slip_wall(u_inner, normal_direction, x, t, surface_flux_function,
+                             equations::CompressibleEulerEquations3D)

Determine the boundary numerical surface flux for a slip wall condition. Imposes a zero normal velocity at the wall. Density is taken from the internal solution state and pressure is computed as an exact solution of a 1D Riemann problem. Further details about this boundary state are available in the paper:

  • J. J. W. van der Vegt and H. van der Ven (2002) Slip flow boundary conditions in discontinuous Galerkin discretizations of the Euler equations of gas dynamics PDF

Details about the 1D pressure Riemann solution can be found in Section 6.3.3 of the book

  • Eleuterio F. Toro (2009) Riemann Solvers and Numerical Methods for Fluid Dynamics: A Practical Introduction 3rd edition DOI: 10.1007/b79761
source
Trixi.boundary_condition_slip_wallMethod
boundary_condition_slip_wall(u_inner, normal_direction, x, t, surface_flux_function,
+                             equations::ShallowWaterEquations2D)

Create a boundary state by reflecting the normal velocity component and keep the tangential velocity component unchanged. The boundary water height is taken from the internal value. For details see Section 9.2.5 of the book:

  • Eleuterio F. Toro (2001) Shock-Capturing Methods for Free-Surface Shallow Flows 1st edition ISBN 0471987662
source
Trixi.boundary_condition_slip_wallMethod
boundary_condition_slip_wall(u_inner, normal_direction, x, t, surface_flux_function,
+                             equations::ShallowWaterTwoLayerEquations2D)

Create a boundary state by reflecting the normal velocity component and keep the tangential velocity component unchanged. The boundary water height is taken from the internal value.

For details see Section 9.2.5 of the book:

  • Eleuterio F. Toro (2001) Shock-Capturing Methods for Free-Surface Shallow Flows 1st edition ISBN 0471987662
source
Trixi.boundary_condition_slip_wallMethod
boundary_condition_slip_wall(u_inner, orientation, direction, x, t,
+                             surface_flux_function, equations::CompressibleEulerEquations1D)

Determine the boundary numerical surface flux for a slip wall condition. Imposes a zero normal velocity at the wall. Density is taken from the internal solution state and pressure is computed as an exact solution of a 1D Riemann problem. Further details about this boundary state are available in the paper:

  • J. J. W. van der Vegt and H. van der Ven (2002) Slip flow boundary conditions in discontinuous Galerkin discretizations of the Euler equations of gas dynamics PDF

    Should be used together with TreeMesh.

source
Trixi.boundary_condition_slip_wallMethod
boundary_condition_slip_wall(u_inner, orientation_or_normal, x, t, surface_flux_function,
+                              equations::ShallowWaterEquations1D)

Create a boundary state by reflecting the normal velocity component and keep the tangential velocity component unchanged. The boundary water height is taken from the internal value.

For details see Section 9.2.5 of the book:

  • Eleuterio F. Toro (2001) Shock-Capturing Methods for Free-Surface Shallow Flows 1st edition ISBN 0471987662
source
Trixi.boundary_condition_slip_wallMethod
boundary_condition_slip_wall(u_inner, orientation_or_normal, x, t, surface_flux_function,
+                             equations::ShallowWaterTwoLayerEquations1D)

Create a boundary state by reflecting the normal velocity component and keep the tangential velocity component unchanged. The boundary water height is taken from the internal value.

For details see Section 9.2.5 of the book:

  • Eleuterio F. Toro (2001) Shock-Capturing Methods for Free-Surface Shallow Flows 1st edition ISBN 0471987662
source
Trixi.boundary_condition_wallMethod
boundary_condition_wall(u_inner, orientation, direction, x, t, surface_flux_function,
+                        equations::AcousticPerturbationEquations2D)

Boundary conditions for a solid wall.

source
Trixi.boundary_condition_wallMethod
boundary_condition_wall(u_inner, orientation, direction, x, t, surface_flux_function,
+                            equations::LinearizedEulerEquations2D)

Boundary conditions for a solid wall.

source
Trixi.calc_error_normsMethod
calc_error_norms([func=(u_node,equations)->u_node,] u_ode, t, analyzer, semi::AbstractSemidiscretization, cache_analysis)

Calculate discrete L2 and L∞ error norms of func applied to each nodal variable u_node in u_ode. If no exact solution is available, "errors" are calculated using some reference state and can be useful for regression tests.

source
Trixi.calc_fast_wavespeed_roeMethod
calc_fast_wavespeed_roe(u_ll, u_rr, direction, equations::IdealGlmMhdEquations1D)

Compute the fast magnetoacoustic wave speed using Roe averages as given by

  • Cargo and Gallice (1997) Roe Matrices for Ideal MHD and Systematic Construction of Roe Matrices for Systems of Conservation Laws DOI: 10.1006/jcph.1997.5773
source
Trixi.calc_fast_wavespeed_roeMethod
calc_fast_wavespeed_roe(u_ll, u_rr, orientation_or_normal_direction, equations::IdealGlmMhdEquations2D)

Compute the fast magnetoacoustic wave speed using Roe averages as given by

  • Cargo and Gallice (1997) Roe Matrices for Ideal MHD and Systematic Construction of Roe Matrices for Systems of Conservation Laws DOI: 10.1006/jcph.1997.5773
source
Trixi.calc_fast_wavespeed_roeMethod
calc_fast_wavespeed_roe(u_ll, u_rr, orientation_or_normal_direction, equations::IdealGlmMhdEquations3D)

Compute the fast magnetoacoustic wave speed using Roe averages as given by

  • Cargo and Gallice (1997) Roe Matrices for Ideal MHD and Systematic Construction of Roe Matrices for Systems of Conservation Laws DOI: 10.1006/jcph.1997.5773
source
Trixi.calc_wavespeed_roeMethod
calc_wavespeed_roe(u_ll, u_rr, direction::Integer,
+                   equations::ShallowWaterEquations1D)

Calculate Roe-averaged velocity v_roe and wavespeed c_roe = sqrt{g * h_roe} See for instance equation (62) in

  • Paul A. Ullrich, Christiane Jablonowski, and Bram van Leer (2010) High-order finite-volume methods for the shallow-water equations on the sphere DOI: 10.1016/j.jcp.2010.04.044

Or equation (9.17) in this lecture notes.

source
Trixi.calc_wavespeed_roeMethod
calc_wavespeed_roe(u_ll, u_rr, direction::Integer,
+                   equations::ShallowWaterEquations2D)

Calculate Roe-averaged velocity v_roe and wavespeed c_roe = sqrt{g * h_roe} depending on direction. See for instance equation (62) in

  • Paul A. Ullrich, Christiane Jablonowski, and Bram van Leer (2010) High-order finite-volume methods for the shallow-water equations on the sphere DOI: 10.1016/j.jcp.2010.04.044

Or this slides, slides 8 and 9.

source
Trixi.collision_bgkMethod
collision_bgk(u, dt, equations::LatticeBoltzmannEquations2D)

Collision operator for the Bhatnagar, Gross, and Krook (BGK) model.

source
Trixi.collision_bgkMethod
collision_bgk(u, dt, equations::LatticeBoltzmannEquations3D)

Collision operator for the Bhatnagar, Gross, and Krook (BGK) model.

source
Trixi.cons2consMethod
cons2cons(u, equations)

Return the conserved variables u. While this function is as trivial as identity, it is also as useful.

source
Trixi.cons2entropyFunction
cons2entropy(u, equations)

Convert the conserved variables u to the entropy variables for a given set of equations with chosen standard entropy.

u is a vector type of the correct length nvariables(equations). Notice the function doesn't include any error checks for the purpose of efficiency, so please make sure your input is correct. The inverse conversion is performed by entropy2cons.

source
Trixi.cons2primFunction
cons2prim(u, equations)

Convert the conserved variables u to the primitive variables for a given set of equations. u is a vector type of the correct length nvariables(equations). Notice the function doesn't include any error checks for the purpose of efficiency, so please make sure your input is correct. The inverse conversion is performed by prim2cons.

source
Trixi.convergence_testMethod
convergence_test([mod::Module=Main,] elixir::AbstractString, iterations; kwargs...)

Run iterations Trixi.jl simulations using the setup given in elixir and compute the experimental order of convergence (EOC) in the $L^2$ and $L^\infty$ norm. In each iteration, the resolution of the respective mesh will be doubled. Additional keyword arguments kwargs... and the optional module mod are passed directly to trixi_include.

This function assumes that the spatial resolution is set via the keywords initial_refinement_level (an integer) or cells_per_dimension (a tuple of integers, one per spatial dimension).

source
Trixi.default_example_unstructuredMethod
default_example_unstructured()

Return the path to an example elixir that can be used to quickly see Trixi.jl in action on an UnstructuredMesh2D. This simulation is run on the example curved, unstructured mesh given in the Trixi.jl documentation regarding unstructured meshes.

source
Trixi.densityMethod
density(p::Real, equations::LatticeBoltzmannEquations2D)
+density(u, equations::LatticeBoltzmannEquations2D)

Calculate the macroscopic density from the pressure p or the particle distribution functions u.

source
Trixi.densityMethod
density(p::Real, equations::LatticeBoltzmannEquations3D)
+density(u, equations::LatticeBoltzmannEquations3D)

Calculate the macroscopic density from the pressure p or the particle distribution functions u.

source
Trixi.each_dof_globalMethod
each_dof_global(mesh::DGMultiMesh, dg::DGMulti, other_args...)

Return an iterator over the indices that specify the location in relevant data structures for the degrees of freedom (DOF) in dg. In particular, not the DOFs themselves are returned.

source
Trixi.each_face_nodeMethod
each_face_node(mesh::DGMultiMesh, dg::DGMulti, other_args...)

Return an iterator over the indices that specify the location in relevant data structures for the face nodes in dg. In particular, not the face_nodes themselves are returned.

source
Trixi.each_face_node_globalMethod
each_face_node_global(mesh::DGMultiMesh, dg::DGMulti, other_args...)

Return an iterator over the indices that specify the location in relevant data structures for the face nodes in mesh. In particular, not the face nodes themselves are returned.

source
Trixi.each_quad_nodeMethod
each_quad_node(mesh::DGMultiMesh, dg::DGMulti, other_args...)

Return an iterator over the indices that specify the location in relevant data structures for the quadrature nodes in dg. In particular, not the quadrature nodes themselves are returned.

source
Trixi.each_quad_node_globalMethod
each_quad_node_global(mesh::DGMultiMesh, dg::DGMulti, other_args...)

Return an iterator over the indices that specify the location in relevant data structures for the global quadrature nodes in mesh. In particular, not the quadrature nodes themselves are returned.

source
Trixi.eachboundaryMethod
eachboundary(dg::DG, cache)

Return an iterator over the indices that specify the location in relevant data structures for the boundaries in cache. In particular, not the boundaries themselves are returned.

source
Trixi.eachcomponentMethod
eachcomponent(equations::AbstractCompressibleEulerMulticomponentEquations)

Return an iterator over the indices that specify the location in relevant data structures for the components in AbstractCompressibleEulerMulticomponentEquations. In particular, not the components themselves are returned.

source
Trixi.eachcomponentMethod
eachcomponent(equations::AbstractIdealGlmMhdMulticomponentEquations)

Return an iterator over the indices that specify the location in relevant data structures for the components in AbstractIdealGlmMhdMulticomponentEquations. In particular, not the components themselves are returned.

source
Trixi.eachdimMethod
eachdim(mesh)

Return an iterator over the indices that specify the location in relevant data structures for the dimensions in AbstractTree. In particular, not the dimensions themselves are returned.

source
Trixi.eachdirectionMethod
eachdirection(tree::AbstractTree)

Return an iterator over the indices that specify the location in relevant data structures for the directions in AbstractTree. In particular, not the directions themselves are returned.

source
Trixi.eachelementMethod
eachelement(dg::DG, cache)

Return an iterator over the indices that specify the location in relevant data structures for the elements in cache. In particular, not the elements themselves are returned.

source
Trixi.eachelementMethod
eachelement(mesh::DGMultiMesh, dg::DGMulti, other_args...)

Return an iterator over the indices that specify the location in relevant data structures for the elements in mesh. In particular, not the elements themselves are returned.

source
Trixi.eachelementMethod
eachelement(elements::ElementContainer1D)

Return an iterator over the indices that specify the location in relevant data structures for the elements in elements. In particular, not the elements themselves are returned.

source
Trixi.eachelementMethod
eachelement(elements::ElementContainer2D)

Return an iterator over the indices that specify the location in relevant data structures for the elements in elements. In particular, not the elements themselves are returned.

source
Trixi.eachelementMethod
eachelement(elements::ElementContainer3D)

Return an iterator over the indices that specify the location in relevant data structures for the elements in elements. In particular, not the elements themselves are returned.

source
Trixi.eachelementMethod
eachelement(elements::UnstructuredElementContainer2D)

Return an iterator over the indices that specify the location in relevant data structures for the elements in elements. In particular, not the elements themselves are returned.

source
Trixi.eachinterfaceMethod
eachinterface(dg::DG, cache)

Return an iterator over the indices that specify the location in relevant data structures for the interfaces in cache. In particular, not the interfaces themselves are returned.

source
Trixi.eachmortarMethod
eachmortar(dg::DG, cache)

Return an iterator over the indices that specify the location in relevant data structures for the mortars in cache. In particular, not the mortars themselves are returned.

source
Trixi.eachmpiinterfaceMethod
eachmpiinterface(dg::DG, cache)

Return an iterator over the indices that specify the location in relevant data structures for the MPI interfaces in cache. In particular, not the interfaces themselves are returned.

source
Trixi.eachmpimortarMethod
eachmpimortar(dg::DG, cache)

Return an iterator over the indices that specify the location in relevant data structures for the MPI mortars in cache. In particular, not the mortars themselves are returned.

source
Trixi.eachnodeMethod
eachnode(dg::DG)

Return an iterator over the indices that specify the location in relevant data structures for the nodes in dg. In particular, not the nodes themselves are returned.

source
Trixi.eachnodeMethod
eachnode(basis::LobattoLegendreBasis)

Return an iterator over the indices that specify the location in relevant data structures for the nodes in basis. In particular, not the nodes themselves are returned.

source
Trixi.eachnodeMethod
eachnode(analyzer::LobattoLegendreAnalyzer)

Return an iterator over the indices that specify the location in relevant data structures for the nodes in analyzer. In particular, not the nodes themselves are returned.

source
Trixi.eachvariableMethod
eachvariable(equations::AbstractEquations)

Return an iterator over the indices that specify the location in relevant data structures for the variables in equations. In particular, not the variables themselves are returned.

source
Trixi.energy_internalFunction
energy_internal(u, equations)

Return the internal energy of the conserved variables u for a given set of equations, e.g., the CompressibleEulerEquations2D.

u is a vector of the conserved variables at a single node, i.e., a vector of the correct length nvariables(equations).

source
Trixi.energy_kineticFunction
energy_kinetic(u, equations)

Return the kinetic energy of the conserved variables u for a given set of equations, e.g., the CompressibleEulerEquations2D.

u is a vector of the conserved variables at a single node, i.e., a vector of the correct length nvariables(equations).

source
Trixi.energy_totalFunction
energy_total(u, equations)

Return the total energy of the conserved variables u for a given set of equations, e.g., the CompressibleEulerEquations2D.

u is a vector of the conserved variables at a single node, i.e., a vector of the correct length nvariables(equations).

source
Trixi.entropyFunction
entropy(u, equations)

Return the chosen entropy of the conserved variables u for a given set of equations.

u is a vector of the conserved variables at a single node, i.e., a vector of the correct length nvariables(equations).

source
Trixi.entropy2consFunction
entropy2cons(w, equations)

Convert the entropy variables w based on a standard entropy to the conserved variables for a given set of equations. u is a vector type of the correct length nvariables(equations). Notice the function doesn't include any error checks for the purpose of efficiency, so please make sure your input is correct. The inverse conversion is performed by cons2entropy.

source
Trixi.equilibrium_distributionMethod
equilibrium_distribution(alpha, rho, v1, v2, v3, equations::LatticeBoltzmannEquations3D)

Calculate the local equilibrium distribution for the distribution function with index alpha and given the macroscopic state defined by rho, v1, v2, v3.

source
Trixi.equilibrium_distributionMethod
equilibrium_distribution(alpha, rho, v1, v2, equations::LatticeBoltzmannEquations2D)

Calculate the local equilibrium distribution for the distribution function with index alpha and given the macroscopic state defined by rho, v1, v2.

source
Trixi.examples_dirMethod
examples_dir()

Return the directory where the example files provided with Trixi.jl are located. If Trixi.jl is installed as a regular package (with ]add Trixi), these files are read-only and should not be modified. To find out which files are available, use, e.g., readdir:

Examples

readdir(examples_dir())
source
Trixi.fluxFunction
flux(u, orientation_or_normal, equations)

Given the conservative variables u, calculate the (physical) flux in Cartesian direction orientation::Integer or in arbitrary direction normal::AbstractVector for the corresponding set of governing equations. orientation is 1, 2, and 3 for the x-, y-, and z-directions, respectively.

source
Trixi.fluxMethod
flux(u, normal_direction::AbstractVector, equations::AbstractEquations{1})

Enables calling flux with a non-integer argument normal_direction for one-dimensional equations. Returns the value of flux(u, 1, equations) scaled by normal_direction[1].

source
Trixi.flux_centralMethod
flux_central(u_ll, u_rr, orientation_or_normal_direction, equations::AbstractEquations)

The classical central numerical flux f((u_ll) + f(u_rr)) / 2. When this flux is used as volume flux, the discretization is equivalent to the classical weak form DG method (except floating point errors).

source
Trixi.flux_chan_etalMethod
flux_chan_etal(u_ll, u_rr, orientation,
+               equations::ShallowWaterEquationsQuasi1D)

Total energy conservative (mathematical entropy for quasi 1D shallow water equations) split form. When the bottom topography is nonzero this scheme will be well-balanced when used as a volume_flux. The surface_flux should still use, e.g., FluxPlusDissipation(flux_chan_etal, DissipationLocalLaxFriedrichs()).

Further details are available in the paper:

  • Jesse Chan, Khemraj Shukla, Xinhui Wu, Ruofeng Liu, Prani Nalluri (2023) High order entropy stable schemes for the quasi-one-dimensional shallow water and compressible Euler equations DOI: 10.48550/arXiv.2307.12089
source
Trixi.flux_chandrashekarMethod
flux_chandrashekar(u_ll, u_rr, orientation, equations::CompressibleEulerEquations1D)

Entropy conserving two-point flux by

  • Chandrashekar (2013) Kinetic Energy Preserving and Entropy Stable Finite Volume Schemes for Compressible Euler and Navier-Stokes Equations DOI: 10.4208/cicp.170712.010313a
source
Trixi.flux_chandrashekarMethod
flux_chandrashekar(u_ll, u_rr, orientation, equations::CompressibleEulerEquations2D)

Entropy conserving two-point flux by

  • Chandrashekar (2013) Kinetic Energy Preserving and Entropy Stable Finite Volume Schemes for Compressible Euler and Navier-Stokes Equations DOI: 10.4208/cicp.170712.010313a
source
Trixi.flux_chandrashekarMethod
flux_chandrashekar(u_ll, u_rr, orientation, equations::CompressibleEulerEquations3D)

Entropy conserving two-point flux by

  • Chandrashekar (2013) Kinetic Energy Preserving and Entropy Stable Finite Volume Schemes for Compressible Euler and Navier-Stokes Equations DOI: 10.4208/cicp.170712.010313a
source
Trixi.flux_chandrashekarMethod
flux_chandrashekar(u_ll, u_rr, orientation, equations::CompressibleEulerMulticomponentEquations1D)

Entropy conserving two-point flux by

  • Ayoub Gouasmi, Karthik Duraisamy (2020) "Formulation of Entropy-Stable schemes for the multicomponent compressible Euler equations" arXiv:1904.00972v3 [math.NA] 4 Feb 2020
source
Trixi.flux_chandrashekarMethod
flux_chandrashekar(u_ll, u_rr, orientation, equations::CompressibleEulerMulticomponentEquations2D)

Adaption of the entropy conserving two-point flux by

  • Ayoub Gouasmi, Karthik Duraisamy (2020) "Formulation of Entropy-Stable schemes for the multicomponent compressible Euler equations" arXiv:1904.00972v3 [math.NA] 4 Feb 2020
source
Trixi.flux_derigs_etalMethod
flux_derigs_etal(u_ll, u_rr, orientation, equations::IdealGlmMhdEquations1D)

Entropy conserving two-point flux by

  • Derigs et al. (2018) Ideal GLM-MHD: About the entropy consistent nine-wave magnetic field divergence diminishing ideal magnetohydrodynamics equations DOI: 10.1016/j.jcp.2018.03.002
source
Trixi.flux_derigs_etalMethod
flux_derigs_etal(u_ll, u_rr, orientation, equations::IdealGlmMhdEquations2D)

Entropy conserving two-point flux by

  • Derigs et al. (2018) Ideal GLM-MHD: About the entropy consistent nine-wave magnetic field divergence diminishing ideal magnetohydrodynamics equations DOI: 10.1016/j.jcp.2018.03.002
source
Trixi.flux_derigs_etalMethod
flux_derigs_etal(u_ll, u_rr, orientation, equations::IdealGlmMhdEquations3D)

Entropy conserving two-point flux by

  • Derigs et al. (2018) Ideal GLM-MHD: About the entropy consistent nine-wave magnetic field divergence diminishing ideal magnetohydrodynamics equations DOI: 10.1016/j.jcp.2018.03.002
source
Trixi.flux_derigs_etalMethod
flux_derigs_etal(u_ll, u_rr, orientation, equations::IdealGlmMhdEquations1D)

Entropy conserving two-point flux adapted by

  • Derigs et al. (2018) Ideal GLM-MHD: About the entropy consistent nine-wave magnetic field divergence diminishing ideal magnetohydrodynamics equations for multicomponent DOI: 10.1016/j.jcp.2018.03.002
source
Trixi.flux_derigs_etalMethod
flux_derigs_etal(u_ll, u_rr, orientation, equations::IdealGlmMhdMulticomponentEquations2D)

Entropy conserving two-point flux adapted by

  • Derigs et al. (2018) Ideal GLM-MHD: About the entropy consistent nine-wave magnetic field divergence diminishing ideal magnetohydrodynamics equations for multicomponent DOI: 10.1016/j.jcp.2018.03.002
source
Trixi.flux_es_fjordholm_etalMethod
flux_es_fjordholm_etal(u_ll, u_rr, orientation_or_normal_direction,
+                       equations::ShallowWaterTwoLayerEquations1D)

Entropy stable surface flux for the two-layer shallow water equations. Uses the entropy conservative flux_fjordholm_etal and adds a Lax-Friedrichs type dissipation dependent on the jump of entropy variables.

Further details are available in the paper:

  • Ulrik Skre Fjordholm (2012)

Energy conservative and stable schemes for the two-layer shallow water equations. DOI: 10.1142/9789814417099_0039 It should be noted that the equations are ordered differently and the designation of the upper and lower layer has been changed which leads to a slightly different formulation.

source
Trixi.flux_es_fjordholm_etalMethod
flux_es_fjordholm_etal(u_ll, u_rr, orientation,
+                       equations::ShallowWaterTwoLayerEquations1D)

Entropy stable surface flux for the two-layer shallow water equations. Uses the entropy conservative flux_fjordholm_etal and adds a Lax-Friedrichs type dissipation dependent on the jump of entropy variables.

Further details are available in the paper:

It should be noted that the equations are ordered differently and the designation of the upper and lower layer has been changed which leads to a slightly different formulation.

source
Trixi.flux_fjordholm_etalMethod
flux_fjordholm_etal(u_ll, u_rr, orientation,
+                    equations::ShallowWaterEquations1D)

Total energy conservative (mathematical entropy for shallow water equations). When the bottom topography is nonzero this should only be used as a surface flux otherwise the scheme will not be well-balanced. For well-balancedness in the volume flux use flux_wintermeyer_etal.

Details are available in Eq. (4.1) in the paper:

  • Ulrik S. Fjordholm, Siddhartha Mishr and Eitan Tadmor (2011) Well-balanced and energy stable schemes for the shallow water equations with discontinuous topography DOI: 10.1016/j.jcp.2011.03.042
source
Trixi.flux_fjordholm_etalMethod
flux_fjordholm_etal(u_ll, u_rr, orientation_or_normal_direction,
+                    equations::ShallowWaterEquations2D)

Total energy conservative (mathematical entropy for shallow water equations). When the bottom topography is nonzero this should only be used as a surface flux otherwise the scheme will not be well-balanced. For well-balancedness in the volume flux use flux_wintermeyer_etal.

Details are available in Eq. (4.1) in the paper:

  • Ulrik S. Fjordholm, Siddhartha Mishr and Eitan Tadmor (2011) Well-balanced and energy stable schemes for the shallow water equations with discontinuous topography DOI: 10.1016/j.jcp.2011.03.042
source
Trixi.flux_fjordholm_etalMethod
flux_fjordholm_etal(u_ll, u_rr, orientation,
+                    equations::ShallowWaterTwoLayerEquations1D)

Total energy conservative (mathematical entropy for shallow water equations). When the bottom topography is nonzero this should only be used as a surface flux otherwise the scheme will not be well-balanced. For well-balancedness in the volume flux use flux_wintermeyer_etal.

Details are available in Eq. (4.1) in the paper:

  • Ulrik S. Fjordholm, Siddhartha Mishra and Eitan Tadmor (2011) Well-balanced and energy stable schemes for the shallow water equations with discontinuous topography DOI: 10.1016/j.jcp.2011.03.042

and the application to two layers is shown in the paper:

It should be noted that the equations are ordered differently and the designation of the upper and lower layer has been changed which leads to a slightly different formulation.

source
Trixi.flux_fjordholm_etalMethod
flux_fjordholm_etal(u_ll, u_rr, orientation,
+                    equations::ShallowWaterTwoLayerEquations2D)

Total energy conservative (mathematical entropy for two-layer shallow water equations). When the bottom topography is nonzero this should only be used as a surface flux otherwise the scheme will not be well-balanced. For well-balancedness in the volume flux use flux_wintermeyer_etal.

Details are available in Eq. (4.1) in the paper:

  • Ulrik S. Fjordholm, Siddhartha Mishra and Eitan Tadmor (2011) Well-balanced and energy stable schemes for the shallow water equations with discontinuous topography DOI: 10.1016/j.jcp.2011.03.042

and the application to two layers is shown in the paper:

It should be noted that the equations are ordered differently and the designation of the upper and lower layer has been changed which leads to a slightly different formulation.

source
Trixi.flux_godunovMethod
flux_godunov(u_ll, u_rr, orientation_or_normal_direction,
+             equations::LinearizedEulerEquations2D)

An upwind flux for the linearized Euler equations based on diagonalization of the physical flux matrix. Given the physical flux $Au$, $A=T \Lambda T^{-1}$ with $\Lambda$ being a diagonal matrix that holds the eigenvalues of $A$, decompose $\Lambda = \Lambda^+ + \Lambda^-$ where $\Lambda^+$ and $\Lambda^-$ are diagonal matrices holding the positive and negative eigenvalues of $A$, respectively. Then for left and right states $u_L, u_R$, the numerical flux calculated by this function is given by $A^+ u_L + A^- u_R$ where $A^{\pm} = T \Lambda^{\pm} T^{-1}$.

The diagonalization of the flux matrix can be found in

source
Trixi.flux_hindenlang_gassnerMethod
flux_hindenlang_gassner(u_ll, u_rr, orientation_or_normal_direction,
+                        equations::IdealGlmMhdEquations1D)

Entropy conserving and kinetic energy preserving two-point flux of Hindenlang and Gassner (2019), extending flux_ranocha to the MHD equations.

References

  • Florian Hindenlang, Gregor Gassner (2019) A new entropy conservative two-point flux for ideal MHD equations derived from first principles. Presented at HONOM 2019: European workshop on high order numerical methods for evolutionary PDEs, theory and applications
  • Hendrik Ranocha (2018) Generalised Summation-by-Parts Operators and Entropy Stability of Numerical Methods for Hyperbolic Balance Laws PhD thesis, TU Braunschweig
  • Hendrik Ranocha (2020) Entropy Conserving and Kinetic Energy Preserving Numerical Methods for the Euler Equations Using Summation-by-Parts Operators Proceedings of ICOSAHOM 2018
source
Trixi.flux_hindenlang_gassnerMethod
flux_hindenlang_gassner(u_ll, u_rr, orientation_or_normal_direction,
+                        equations::IdealGlmMhdEquations2D)

Entropy conserving and kinetic energy preserving two-point flux of Hindenlang and Gassner (2019), extending flux_ranocha to the MHD equations.

References

  • Florian Hindenlang, Gregor Gassner (2019) A new entropy conservative two-point flux for ideal MHD equations derived from first principles. Presented at HONOM 2019: European workshop on high order numerical methods for evolutionary PDEs, theory and applications
  • Hendrik Ranocha (2018) Generalised Summation-by-Parts Operators and Entropy Stability of Numerical Methods for Hyperbolic Balance Laws PhD thesis, TU Braunschweig
  • Hendrik Ranocha (2020) Entropy Conserving and Kinetic Energy Preserving Numerical Methods for the Euler Equations Using Summation-by-Parts Operators Proceedings of ICOSAHOM 2018
source
Trixi.flux_hindenlang_gassnerMethod
flux_hindenlang_gassner(u_ll, u_rr, orientation_or_normal_direction,
+                        equations::IdealGlmMhdEquations3D)

Entropy conserving and kinetic energy preserving two-point flux of Hindenlang and Gassner (2019), extending flux_ranocha to the MHD equations.

References

  • Florian Hindenlang, Gregor Gassner (2019) A new entropy conservative two-point flux for ideal MHD equations derived from first principles. Presented at HONOM 2019: European workshop on high order numerical methods for evolutionary PDEs, theory and applications
  • Hendrik Ranocha (2018) Generalised Summation-by-Parts Operators and Entropy Stability of Numerical Methods for Hyperbolic Balance Laws PhD thesis, TU Braunschweig
  • Hendrik Ranocha (2020) Entropy Conserving and Kinetic Energy Preserving Numerical Methods for the Euler Equations Using Summation-by-Parts Operators Proceedings of ICOSAHOM 2018
source
Trixi.flux_hindenlang_gassnerMethod
flux_hindenlang_gassner(u_ll, u_rr, orientation_or_normal_direction,
+                        equations::IdealGlmMhdMulticomponentEquations1D)

Adaption of the entropy conserving and kinetic energy preserving two-point flux of Hindenlang (2019), extending flux_ranocha to the MHD equations.

References

  • Florian Hindenlang, Gregor Gassner (2019) A new entropy conservative two-point flux for ideal MHD equations derived from first principles. Presented at HONOM 2019: European workshop on high order numerical methods for evolutionary PDEs, theory and applications
  • Hendrik Ranocha (2018) Generalised Summation-by-Parts Operators and Entropy Stability of Numerical Methods for Hyperbolic Balance Laws PhD thesis, TU Braunschweig
  • Hendrik Ranocha (2020) Entropy Conserving and Kinetic Energy Preserving Numerical Methods for the Euler Equations Using Summation-by-Parts Operators Proceedings of ICOSAHOM 2018
source
Trixi.flux_hindenlang_gassnerMethod
flux_hindenlang_gassner(u_ll, u_rr, orientation_or_normal_direction,
+                        equations::IdealGlmMhdMulticomponentEquations2D)

Adaption of the entropy conserving and kinetic energy preserving two-point flux of Hindenlang (2019), extending flux_ranocha to the MHD equations.

References

  • Florian Hindenlang, Gregor Gassner (2019) A new entropy conservative two-point flux for ideal MHD equations derived from first principles. Presented at HONOM 2019: European workshop on high order numerical methods for evolutionary PDEs, theory and applications
  • Hendrik Ranocha (2018) Generalised Summation-by-Parts Operators and Entropy Stability of Numerical Methods for Hyperbolic Balance Laws PhD thesis, TU Braunschweig
  • Hendrik Ranocha (2020) Entropy Conserving and Kinetic Energy Preserving Numerical Methods for the Euler Equations Using Summation-by-Parts Operators Proceedings of ICOSAHOM 2018
source
Trixi.flux_kennedy_gruberMethod
flux_kennedy_gruber(u_ll, u_rr, orientation, equations::CompressibleEulerEquations1D)

Kinetic energy preserving two-point flux by

  • Kennedy and Gruber (2008) Reduced aliasing formulations of the convective terms within the Navier-Stokes equations for a compressible fluid DOI: 10.1016/j.jcp.2007.09.020
source
Trixi.flux_kennedy_gruberMethod
flux_kennedy_gruber(u_ll, u_rr, orientation_or_normal_direction,
+                    equations::CompressibleEulerEquations2D)

Kinetic energy preserving two-point flux by

  • Kennedy and Gruber (2008) Reduced aliasing formulations of the convective terms within the Navier-Stokes equations for a compressible fluid DOI: 10.1016/j.jcp.2007.09.020
source
Trixi.flux_kennedy_gruberMethod
flux_kennedy_gruber(u_ll, u_rr, orientation_or_normal_direction,
+                    equations::CompressibleEulerEquations3D)

Kinetic energy preserving two-point flux by

  • Kennedy and Gruber (2008) Reduced aliasing formulations of the convective terms within the Navier-Stokes equations for a compressible fluid DOI: 10.1016/j.jcp.2007.09.020
source
Trixi.flux_nonconservative_audusse_etalMethod
flux_nonconservative_audusse_etal(u_ll, u_rr, orientation::Integer,
+                                  equations::ShallowWaterEquations1D)

Non-symmetric two-point surface flux that discretizes the nonconservative (source) term. The discretization uses the hydrostatic_reconstruction_audusse_etal on the conservative variables.

This hydrostatic reconstruction ensures that the finite volume numerical fluxes remain well-balanced for discontinuous bottom topographies ShallowWaterEquations1D. Should be used together with FluxHydrostaticReconstruction and hydrostatic_reconstruction_audusse_etal in the surface flux to ensure consistency.

Further details on the hydrostatic reconstruction and its motivation can be found in

  • Emmanuel Audusse, François Bouchut, Marie-Odile Bristeau, Rupert Klein, and Benoit Perthame (2004) A fast and stable well-balanced scheme with hydrostatic reconstruction for shallow water flows DOI: 10.1137/S1064827503431090
source
Trixi.flux_nonconservative_audusse_etalMethod
flux_nonconservative_audusse_etal(u_ll, u_rr, orientation::Integer,
                                   equations::ShallowWaterEquations2D)
 flux_nonconservative_audusse_etal(u_ll, u_rr,
                                   normal_direction_ll     ::AbstractVector,
                                   normal_direction_average::AbstractVector,
-                                  equations::ShallowWaterEquations2D)

Non-symmetric two-point surface flux that discretizes the nonconservative (source) term. The discretization uses the hydrostatic_reconstruction_audusse_etal on the conservative variables.

This hydrostatic reconstruction ensures that the finite volume numerical fluxes remain well-balanced for discontinuous bottom topographies ShallowWaterEquations2D. Should be used together with FluxHydrostaticReconstruction and hydrostatic_reconstruction_audusse_etal in the surface flux to ensure consistency.

Further details for the hydrostatic reconstruction and its motivation can be found in

  • Emmanuel Audusse, François Bouchut, Marie-Odile Bristeau, Rupert Klein, and Benoit Perthame (2004) A fast and stable well-balanced scheme with hydrostatic reconstruction for shallow water flows DOI: 10.1137/S1064827503431090
source
Trixi.flux_nonconservative_chan_etalMethod
flux_nonconservative_chan_etal(u_ll, u_rr, orientation::Integer,
-                               equations::ShallowWaterEquationsQuasi1D)

Non-symmetric two-point volume flux discretizing the nonconservative (source) term that contains the gradient of the bottom topography ShallowWaterEquationsQuasi1D and the channel width.

Further details are available in the paper:

  • Jesse Chan, Khemraj Shukla, Xinhui Wu, Ruofeng Liu, Prani Nalluri (2023) High order entropy stable schemes for the quasi-one-dimensional shallow water and compressible Euler equations DOI: 10.48550/arXiv.2307.12089
source
Trixi.flux_nonconservative_chen_noelleMethod
flux_nonconservative_chen_noelle(u_ll, u_rr,
+                                  equations::ShallowWaterEquations2D)

Non-symmetric two-point surface flux that discretizes the nonconservative (source) term. The discretization uses the hydrostatic_reconstruction_audusse_etal on the conservative variables.

This hydrostatic reconstruction ensures that the finite volume numerical fluxes remain well-balanced for discontinuous bottom topographies ShallowWaterEquations2D. Should be used together with FluxHydrostaticReconstruction and hydrostatic_reconstruction_audusse_etal in the surface flux to ensure consistency.

Further details for the hydrostatic reconstruction and its motivation can be found in

  • Emmanuel Audusse, François Bouchut, Marie-Odile Bristeau, Rupert Klein, and Benoit Perthame (2004) A fast and stable well-balanced scheme with hydrostatic reconstruction for shallow water flows DOI: 10.1137/S1064827503431090
source
Trixi.flux_nonconservative_chan_etalMethod
flux_nonconservative_chan_etal(u_ll, u_rr, orientation::Integer,
+                               equations::ShallowWaterEquationsQuasi1D)

Non-symmetric two-point volume flux discretizing the nonconservative (source) term that contains the gradient of the bottom topography ShallowWaterEquationsQuasi1D and the channel width.

Further details are available in the paper:

  • Jesse Chan, Khemraj Shukla, Xinhui Wu, Ruofeng Liu, Prani Nalluri (2023) High order entropy stable schemes for the quasi-one-dimensional shallow water and compressible Euler equations DOI: 10.48550/arXiv.2307.12089
source
Trixi.flux_nonconservative_chen_noelleMethod
flux_nonconservative_chen_noelle(u_ll, u_rr,
                                  orientation::Integer,
-                                 equations::ShallowWaterEquations1D)

Non-symmetric two-point surface flux that discretizes the nonconservative (source) term. The discretization uses the hydrostatic_reconstruction_chen_noelle on the conservative variables.

Should be used together with FluxHydrostaticReconstruction and hydrostatic_reconstruction_chen_noelle in the surface flux to ensure consistency.

Further details on the hydrostatic reconstruction and its motivation can be found in

  • Guoxian Chen and Sebastian Noelle (2017) A new hydrostatic reconstruction scheme based on subcell reconstructions DOI:10.1137/15M1053074
source
Trixi.flux_nonconservative_chen_noelleMethod
flux_nonconservative_chen_noelle(u_ll, u_rr,
+                                 equations::ShallowWaterEquations1D)

Non-symmetric two-point surface flux that discretizes the nonconservative (source) term. The discretization uses the hydrostatic_reconstruction_chen_noelle on the conservative variables.

Should be used together with FluxHydrostaticReconstruction and hydrostatic_reconstruction_chen_noelle in the surface flux to ensure consistency.

Further details on the hydrostatic reconstruction and its motivation can be found in

  • Guoxian Chen and Sebastian Noelle (2017) A new hydrostatic reconstruction scheme based on subcell reconstructions DOI:10.1137/15M1053074
source
Trixi.flux_nonconservative_chen_noelleMethod
flux_nonconservative_chen_noelle(u_ll, u_rr,
                                  orientation::Integer,
                                  equations::ShallowWaterEquations2D)
 flux_nonconservative_chen_noelle(u_ll, u_rr,
                                  normal_direction_ll      ::AbstractVector,
                                  normal_direction_average ::AbstractVector,
-                                 equations::ShallowWaterEquations2D)

Non-symmetric two-point surface flux that discretizes the nonconservative (source) term. The discretization uses the hydrostatic_reconstruction_chen_noelle on the conservative variables.

Should be used together with FluxHydrostaticReconstruction and hydrostatic_reconstruction_chen_noelle in the surface flux to ensure consistency.

Further details on the hydrostatic reconstruction and its motivation can be found in

  • Guoxian Chen and Sebastian Noelle (2017) A new hydrostatic reconstruction scheme based on subcell reconstructions DOI:10.1137/15M1053074
source
Trixi.flux_nonconservative_fjordholm_etalMethod
flux_nonconservative_fjordholm_etal(u_ll, u_rr, orientation::Integer,
-                                    equations::ShallowWaterEquations1D)

Non-symmetric two-point surface flux discretizing the nonconservative (source) term of that contains the gradient of the bottom topography ShallowWaterEquations1D.

This contains additional terms compared to flux_nonconservative_wintermeyer_etal that account for possible discontinuities in the bottom topography function. Thus, this flux should be used in general at interfaces. For flux differencing volume terms, flux_nonconservative_wintermeyer_etal is analytically equivalent but slightly cheaper.

Further details for the original finite volume formulation are available in

  • Ulrik S. Fjordholm, Siddhartha Mishr and Eitan Tadmor (2011) Well-balanced and energy stable schemes for the shallow water equations with discontinuous topography DOI: 10.1016/j.jcp.2011.03.042

and for curvilinear 2D case in the paper:

  • Niklas Wintermeyer, Andrew R. Winters, Gregor J. Gassner and David A. Kopriva (2017) An entropy stable nodal discontinuous Galerkin method for the two dimensional shallow water equations on unstructured curvilinear meshes with discontinuous bathymetry DOI: 10.1016/j.jcp.2017.03.036
source
Trixi.flux_nonconservative_fjordholm_etalMethod
flux_nonconservative_fjordholm_etal(u_ll, u_rr, orientation::Integer,
+                                 equations::ShallowWaterEquations2D)

Non-symmetric two-point surface flux that discretizes the nonconservative (source) term. The discretization uses the hydrostatic_reconstruction_chen_noelle on the conservative variables.

Should be used together with FluxHydrostaticReconstruction and hydrostatic_reconstruction_chen_noelle in the surface flux to ensure consistency.

Further details on the hydrostatic reconstruction and its motivation can be found in

  • Guoxian Chen and Sebastian Noelle (2017) A new hydrostatic reconstruction scheme based on subcell reconstructions DOI:10.1137/15M1053074
source
Trixi.flux_nonconservative_fjordholm_etalMethod
flux_nonconservative_fjordholm_etal(u_ll, u_rr, orientation::Integer,
+                                    equations::ShallowWaterEquations1D)

Non-symmetric two-point surface flux discretizing the nonconservative (source) term of that contains the gradient of the bottom topography ShallowWaterEquations1D.

This contains additional terms compared to flux_nonconservative_wintermeyer_etal that account for possible discontinuities in the bottom topography function. Thus, this flux should be used in general at interfaces. For flux differencing volume terms, flux_nonconservative_wintermeyer_etal is analytically equivalent but slightly cheaper.

Further details for the original finite volume formulation are available in

  • Ulrik S. Fjordholm, Siddhartha Mishr and Eitan Tadmor (2011) Well-balanced and energy stable schemes for the shallow water equations with discontinuous topography DOI: 10.1016/j.jcp.2011.03.042

and for curvilinear 2D case in the paper:

  • Niklas Wintermeyer, Andrew R. Winters, Gregor J. Gassner and David A. Kopriva (2017) An entropy stable nodal discontinuous Galerkin method for the two dimensional shallow water equations on unstructured curvilinear meshes with discontinuous bathymetry DOI: 10.1016/j.jcp.2017.03.036
source
Trixi.flux_nonconservative_fjordholm_etalMethod
flux_nonconservative_fjordholm_etal(u_ll, u_rr, orientation::Integer,
                                     equations::ShallowWaterEquations2D)
 flux_nonconservative_fjordholm_etal(u_ll, u_rr,
                                     normal_direction_ll     ::AbstractVector,
                                     normal_direction_average::AbstractVector,
-                                    equations::ShallowWaterEquations2D)

Non-symmetric two-point surface flux discretizing the nonconservative (source) term of that contains the gradient of the bottom topography ShallowWaterEquations2D.

On curvilinear meshes, this nonconservative flux depends on both the contravariant vector (normal direction) at the current node and the averaged one. This is different from numerical fluxes used to discretize conservative terms.

This contains additional terms compared to flux_nonconservative_wintermeyer_etal that account for possible discontinuities in the bottom topography function. Thus, this flux should be used in general at interfaces. For flux differencing volume terms, flux_nonconservative_wintermeyer_etal is analytically equivalent but slightly cheaper.

Further details for the original finite volume formulation are available in

  • Ulrik S. Fjordholm, Siddhartha Mishr and Eitan Tadmor (2011) Well-balanced and energy stable schemes for the shallow water equations with discontinuous topography DOI: 10.1016/j.jcp.2011.03.042

and for curvilinear 2D case in the paper:

  • Niklas Wintermeyer, Andrew R. Winters, Gregor J. Gassner and David A. Kopriva (2017) An entropy stable nodal discontinuous Galerkin method for the two dimensional shallow water equations on unstructured curvilinear meshes with discontinuous bathymetry DOI: 10.1016/j.jcp.2017.03.036
source
Trixi.flux_nonconservative_fjordholm_etalMethod
flux_nonconservative_fjordholm_etal(u_ll, u_rr, orientation::Integer,
-                                    equations::ShallowWaterTwoLayerEquations1D)
Experimental code

This numerical flux is experimental and may change in any future release.

Non-symmetric two-point surface flux discretizing the nonconservative (source) term that contains the gradients of the bottom topography and an additional term that couples the momentum of both layers ShallowWaterTwoLayerEquations2D.

Further details are available in the paper:

It should be noted that the equations are ordered differently and the designation of the upper and lower layer has been changed which leads to a slightly different formulation.

source
Trixi.flux_nonconservative_fjordholm_etalMethod
flux_nonconservative_fjordholm_etal(u_ll, u_rr, orientation::Integer,
-                                    equations::ShallowWaterTwoLayerEquations2D)
Experimental code

This numerical flux is experimental and may change in any future release.

Non-symmetric two-point surface flux discretizing the nonconservative (source) term that contains the gradients of the bottom topography and an additional term that couples the momentum of both layers ShallowWaterTwoLayerEquations2D.

Further details are available in the paper:

It should be noted that the equations are ordered differently and the designation of the upper and lower layer has been changed which leads to a slightly different formulation.

source
Trixi.flux_nonconservative_powellMethod
flux_nonconservative_powell(u_ll, u_rr, orientation::Integer,
+                                    equations::ShallowWaterEquations2D)

Non-symmetric two-point surface flux discretizing the nonconservative (source) term of that contains the gradient of the bottom topography ShallowWaterEquations2D.

On curvilinear meshes, this nonconservative flux depends on both the contravariant vector (normal direction) at the current node and the averaged one. This is different from numerical fluxes used to discretize conservative terms.

This contains additional terms compared to flux_nonconservative_wintermeyer_etal that account for possible discontinuities in the bottom topography function. Thus, this flux should be used in general at interfaces. For flux differencing volume terms, flux_nonconservative_wintermeyer_etal is analytically equivalent but slightly cheaper.

Further details for the original finite volume formulation are available in

  • Ulrik S. Fjordholm, Siddhartha Mishr and Eitan Tadmor (2011) Well-balanced and energy stable schemes for the shallow water equations with discontinuous topography DOI: 10.1016/j.jcp.2011.03.042

and for curvilinear 2D case in the paper:

  • Niklas Wintermeyer, Andrew R. Winters, Gregor J. Gassner and David A. Kopriva (2017) An entropy stable nodal discontinuous Galerkin method for the two dimensional shallow water equations on unstructured curvilinear meshes with discontinuous bathymetry DOI: 10.1016/j.jcp.2017.03.036
source
Trixi.flux_nonconservative_fjordholm_etalMethod
flux_nonconservative_fjordholm_etal(u_ll, u_rr, orientation::Integer,
+                                    equations::ShallowWaterTwoLayerEquations1D)
Experimental code

This numerical flux is experimental and may change in any future release.

Non-symmetric two-point surface flux discretizing the nonconservative (source) term that contains the gradients of the bottom topography and an additional term that couples the momentum of both layers ShallowWaterTwoLayerEquations2D.

Further details are available in the paper:

It should be noted that the equations are ordered differently and the designation of the upper and lower layer has been changed which leads to a slightly different formulation.

source
Trixi.flux_nonconservative_fjordholm_etalMethod
flux_nonconservative_fjordholm_etal(u_ll, u_rr, orientation::Integer,
+                                    equations::ShallowWaterTwoLayerEquations2D)
Experimental code

This numerical flux is experimental and may change in any future release.

Non-symmetric two-point surface flux discretizing the nonconservative (source) term that contains the gradients of the bottom topography and an additional term that couples the momentum of both layers ShallowWaterTwoLayerEquations2D.

Further details are available in the paper:

It should be noted that the equations are ordered differently and the designation of the upper and lower layer has been changed which leads to a slightly different formulation.

source
Trixi.flux_nonconservative_powellMethod
flux_nonconservative_powell(u_ll, u_rr, orientation::Integer,
                             equations::IdealGlmMhdEquations2D)
 flux_nonconservative_powell(u_ll, u_rr,
                             normal_direction_ll     ::AbstractVector,
                             normal_direction_average::AbstractVector,
-                            equations::IdealGlmMhdEquations2D)

Non-symmetric two-point flux discretizing the nonconservative (source) term of Powell and the Galilean nonconservative term associated with the GLM multiplier of the IdealGlmMhdEquations2D.

On curvilinear meshes, this nonconservative flux depends on both the contravariant vector (normal direction) at the current node and the averaged one. This is different from numerical fluxes used to discretize conservative terms.

References

  • Marvin Bohm, Andrew R.Winters, Gregor J. Gassner, Dominik Derigs, Florian Hindenlang, Joachim Saur An entropy stable nodal discontinuous Galerkin method for the resistive MHD equations. Part I: Theory and numerical verification DOI: 10.1016/j.jcp.2018.06.027
source
Trixi.flux_nonconservative_powellMethod
flux_nonconservative_powell(u_ll, u_rr, orientation::Integer,
+                            equations::IdealGlmMhdEquations2D)

Non-symmetric two-point flux discretizing the nonconservative (source) term of Powell and the Galilean nonconservative term associated with the GLM multiplier of the IdealGlmMhdEquations2D.

On curvilinear meshes, this nonconservative flux depends on both the contravariant vector (normal direction) at the current node and the averaged one. This is different from numerical fluxes used to discretize conservative terms.

References

  • Marvin Bohm, Andrew R.Winters, Gregor J. Gassner, Dominik Derigs, Florian Hindenlang, Joachim Saur An entropy stable nodal discontinuous Galerkin method for the resistive MHD equations. Part I: Theory and numerical verification DOI: 10.1016/j.jcp.2018.06.027
source
Trixi.flux_nonconservative_powellMethod
flux_nonconservative_powell(u_ll, u_rr, orientation::Integer,
                             equations::IdealGlmMhdEquations3D)
 flux_nonconservative_powell(u_ll, u_rr,
                             normal_direction_ll     ::AbstractVector,
                             normal_direction_average::AbstractVector,
-                            equations::IdealGlmMhdEquations3D)

Non-symmetric two-point flux discretizing the nonconservative (source) term of Powell and the Galilean nonconservative term associated with the GLM multiplier of the IdealGlmMhdEquations3D.

On curvilinear meshes, this nonconservative flux depends on both the contravariant vector (normal direction) at the current node and the averaged one. This is different from numerical fluxes used to discretize conservative terms.

References

  • Marvin Bohm, Andrew R.Winters, Gregor J. Gassner, Dominik Derigs, Florian Hindenlang, Joachim Saur An entropy stable nodal discontinuous Galerkin method for the resistive MHD equations. Part I: Theory and numerical verification DOI: 10.1016/j.jcp.2018.06.027
source
Trixi.flux_nonconservative_powellMethod
flux_nonconservative_powell(u_ll, u_rr, orientation::Integer,
-                            equations::IdealGlmMhdMulticomponentEquations2D)

Non-symmetric two-point flux discretizing the nonconservative (source) term of Powell and the Galilean nonconservative term associated with the GLM multiplier of the IdealGlmMhdMulticomponentEquations2D.

References

  • Marvin Bohm, Andrew R.Winters, Gregor J. Gassner, Dominik Derigs, Florian Hindenlang, Joachim Saur An entropy stable nodal discontinuous Galerkin method for the resistive MHD equations. Part I: Theory and numerical verification DOI: 10.1016/j.jcp.2018.06.027
source
Trixi.flux_nonconservative_powell_local_symmetricMethod
flux_nonconservative_powell_local_symmetric(u_ll, orientation::Integer,
+                            equations::IdealGlmMhdEquations3D)

Non-symmetric two-point flux discretizing the nonconservative (source) term of Powell and the Galilean nonconservative term associated with the GLM multiplier of the IdealGlmMhdEquations3D.

On curvilinear meshes, this nonconservative flux depends on both the contravariant vector (normal direction) at the current node and the averaged one. This is different from numerical fluxes used to discretize conservative terms.

References

  • Marvin Bohm, Andrew R.Winters, Gregor J. Gassner, Dominik Derigs, Florian Hindenlang, Joachim Saur An entropy stable nodal discontinuous Galerkin method for the resistive MHD equations. Part I: Theory and numerical verification DOI: 10.1016/j.jcp.2018.06.027
source
Trixi.flux_nonconservative_powellMethod
flux_nonconservative_powell(u_ll, u_rr, orientation::Integer,
+                            equations::IdealGlmMhdMulticomponentEquations2D)

Non-symmetric two-point flux discretizing the nonconservative (source) term of Powell and the Galilean nonconservative term associated with the GLM multiplier of the IdealGlmMhdMulticomponentEquations2D.

References

  • Marvin Bohm, Andrew R.Winters, Gregor J. Gassner, Dominik Derigs, Florian Hindenlang, Joachim Saur An entropy stable nodal discontinuous Galerkin method for the resistive MHD equations. Part I: Theory and numerical verification DOI: 10.1016/j.jcp.2018.06.027
source
Trixi.flux_nonconservative_powell_local_symmetricMethod
flux_nonconservative_powell_local_symmetric(u_ll, orientation::Integer,
                                             equations::IdealGlmMhdEquations2D,
                                             nonconservative_type::NonConservativeSymmetric,
-                                            nonconservative_term::Integer)

Symmetric part of the Powell and GLM non-conservative terms. Needed for the calculation of the non-conservative staggered "fluxes" for subcell limiting. See, e.g.,

  • Rueda-Ramírez, Gassner (2023). A Flux-Differencing Formula for Split-Form Summation By Parts Discretizations of Non-Conservative Systems. https://arxiv.org/pdf/2211.14009.pdf.

This function is used to compute the subcell fluxes in dg2dsubcell_limiters.jl.

source
Trixi.flux_nonconservative_powell_local_symmetricMethod
flux_nonconservative_powell_local_symmetric(u_ll, u_rr,
+                                            nonconservative_term::Integer)

Symmetric part of the Powell and GLM non-conservative terms. Needed for the calculation of the non-conservative staggered "fluxes" for subcell limiting. See, e.g.,

  • Rueda-Ramírez, Gassner (2023). A Flux-Differencing Formula for Split-Form Summation By Parts Discretizations of Non-Conservative Systems. https://arxiv.org/pdf/2211.14009.pdf.

This function is used to compute the subcell fluxes in dg2dsubcell_limiters.jl.

source
Trixi.flux_nonconservative_powell_local_symmetricMethod
flux_nonconservative_powell_local_symmetric(u_ll, u_rr,
                                             orientation::Integer,
-                                            equations::IdealGlmMhdEquations2D)

Non-symmetric two-point flux discretizing the nonconservative (source) term of Powell and the Galilean nonconservative term associated with the GLM multiplier of the IdealGlmMhdEquations2D.

This implementation uses a non-conservative term that can be written as the product of local and symmetric parts. It is equivalent to the non-conservative flux of Bohm et al. (flux_nonconservative_powell) for conforming meshes but it yields different results on non-conforming meshes(!).

The two other flux functions with the same name return either the local or symmetric portion of the non-conservative flux based on the type of the nonconservativetype argument, employing multiple dispatch. They are used to compute the subcell fluxes in dg2dsubcelllimiters.jl.

References

  • Rueda-Ramírez, Gassner (2023). A Flux-Differencing Formula for Split-Form Summation By Parts Discretizations of Non-Conservative Systems. https://arxiv.org/pdf/2211.14009.pdf.
source
Trixi.flux_nonconservative_powell_local_symmetricMethod
flux_nonconservative_powell_local_symmetric(u_ll, orientation::Integer,
+                                            equations::IdealGlmMhdEquations2D)

Non-symmetric two-point flux discretizing the nonconservative (source) term of Powell and the Galilean nonconservative term associated with the GLM multiplier of the IdealGlmMhdEquations2D.

This implementation uses a non-conservative term that can be written as the product of local and symmetric parts. It is equivalent to the non-conservative flux of Bohm et al. (flux_nonconservative_powell) for conforming meshes but it yields different results on non-conforming meshes(!).

The two other flux functions with the same name return either the local or symmetric portion of the non-conservative flux based on the type of the nonconservativetype argument, employing multiple dispatch. They are used to compute the subcell fluxes in dg2dsubcelllimiters.jl.

References

  • Rueda-Ramírez, Gassner (2023). A Flux-Differencing Formula for Split-Form Summation By Parts Discretizations of Non-Conservative Systems. https://arxiv.org/pdf/2211.14009.pdf.
source
Trixi.flux_nonconservative_powell_local_symmetricMethod
flux_nonconservative_powell_local_symmetric(u_ll, orientation::Integer,
                                             equations::IdealGlmMhdEquations2D,
                                             nonconservative_type::NonConservativeLocal,
-                                            nonconservative_term::Integer)

Local part of the Powell and GLM non-conservative terms. Needed for the calculation of the non-conservative staggered "fluxes" for subcell limiting. See, e.g.,

  • Rueda-Ramírez, Gassner (2023). A Flux-Differencing Formula for Split-Form Summation By Parts Discretizations of Non-Conservative Systems. https://arxiv.org/pdf/2211.14009.pdf.

This function is used to compute the subcell fluxes in dg2dsubcell_limiters.jl.

source
Trixi.flux_nonconservative_wintermeyer_etalMethod
flux_nonconservative_wintermeyer_etal(u_ll, u_rr, orientation::Integer,
-                                      equations::ShallowWaterEquations1D)

Non-symmetric two-point volume flux discretizing the nonconservative (source) term that contains the gradient of the bottom topography ShallowWaterEquations1D.

Further details are available in the paper:

  • Niklas Wintermeyer, Andrew R. Winters, Gregor J. Gassner and David A. Kopriva (2017) An entropy stable nodal discontinuous Galerkin method for the two dimensional shallow water equations on unstructured curvilinear meshes with discontinuous bathymetry DOI: 10.1016/j.jcp.2017.03.036
source
Trixi.flux_nonconservative_wintermeyer_etalMethod
flux_nonconservative_wintermeyer_etal(u_ll, u_rr, orientation::Integer,
+                                            nonconservative_term::Integer)

Local part of the Powell and GLM non-conservative terms. Needed for the calculation of the non-conservative staggered "fluxes" for subcell limiting. See, e.g.,

  • Rueda-Ramírez, Gassner (2023). A Flux-Differencing Formula for Split-Form Summation By Parts Discretizations of Non-Conservative Systems. https://arxiv.org/pdf/2211.14009.pdf.

This function is used to compute the subcell fluxes in dg2dsubcell_limiters.jl.

source
Trixi.flux_nonconservative_wintermeyer_etalMethod
flux_nonconservative_wintermeyer_etal(u_ll, u_rr, orientation::Integer,
+                                      equations::ShallowWaterEquations1D)

Non-symmetric two-point volume flux discretizing the nonconservative (source) term that contains the gradient of the bottom topography ShallowWaterEquations1D.

Further details are available in the paper:

  • Niklas Wintermeyer, Andrew R. Winters, Gregor J. Gassner and David A. Kopriva (2017) An entropy stable nodal discontinuous Galerkin method for the two dimensional shallow water equations on unstructured curvilinear meshes with discontinuous bathymetry DOI: 10.1016/j.jcp.2017.03.036
source
Trixi.flux_nonconservative_wintermeyer_etalMethod
flux_nonconservative_wintermeyer_etal(u_ll, u_rr, orientation::Integer,
                                       equations::ShallowWaterEquations2D)
 flux_nonconservative_wintermeyer_etal(u_ll, u_rr,
                                       normal_direction_ll     ::AbstractVector,
                                       normal_direction_average::AbstractVector,
-                                      equations::ShallowWaterEquations2D)

Non-symmetric two-point volume flux discretizing the nonconservative (source) term that contains the gradient of the bottom topography ShallowWaterEquations2D.

On curvilinear meshes, this nonconservative flux depends on both the contravariant vector (normal direction) at the current node and the averaged one. This is different from numerical fluxes used to discretize conservative terms.

Further details are available in the paper:

  • Niklas Wintermeyer, Andrew R. Winters, Gregor J. Gassner and David A. Kopriva (2017) An entropy stable nodal discontinuous Galerkin method for the two dimensional shallow water equations on unstructured curvilinear meshes with discontinuous bathymetry DOI: 10.1016/j.jcp.2017.03.036
source
Trixi.flux_nonconservative_wintermeyer_etalMethod
flux_nonconservative_wintermeyer_etal(u_ll, u_rr, orientation::Integer,
-                                      equations::ShallowWaterTwoLayerEquations1D)
Experimental code

This numerical flux is experimental and may change in any future release.

Non-symmetric two-point volume flux discretizing the nonconservative (source) term that contains the gradient of the bottom topography ShallowWaterTwoLayerEquations2D and an additional term that couples the momentum of both layers. This is a slightly modified version to account for the additional source term compared to the standard SWE described in the paper.

Further details are available in the paper:

  • Niklas Wintermeyer, Andrew R. Winters, Gregor J. Gassner and David A. Kopriva (2017) An entropy stable nodal discontinuous Galerkin method for the two dimensional shallow water equations on unstructured curvilinear meshes with discontinuous bathymetry DOI: 10.1016/j.jcp.2017.03.036
source
Trixi.flux_nonconservative_wintermeyer_etalMethod
flux_nonconservative_wintermeyer_etal(u_ll, u_rr, orientation::Integer,
-                                      equations::ShallowWaterTwoLayerEquations2D)
Experimental code

This numerical flux is experimental and may change in any future release.

Non-symmetric two-point volume flux discretizing the nonconservative (source) term that contains the gradient of the bottom topography ShallowWaterTwoLayerEquations2D and an additional term that couples the momentum of both layers. This is a slightly modified version to account for the additional source term compared to the standard SWE described in the paper.

Further details are available in the paper:

  • Niklas Wintermeyer, Andrew R. Winters, Gregor J. Gassner and David A. Kopriva (2017) An entropy stable nodal discontinuous Galerkin method for the two dimensional shallow water equations on unstructured curvilinear meshes with discontinuous bathymetry DOI: 10.1016/j.jcp.2017.03.036
source
Trixi.flux_ranochaMethod
flux_ranocha(u_ll, u_rr, orientation_or_normal_direction, equations::CompressibleEulerEquations1D)

Entropy conserving and kinetic energy preserving two-point flux by

  • Hendrik Ranocha (2018) Generalised Summation-by-Parts Operators and Entropy Stability of Numerical Methods for Hyperbolic Balance Laws PhD thesis, TU Braunschweig

See also

  • Hendrik Ranocha (2020) Entropy Conserving and Kinetic Energy Preserving Numerical Methods for the Euler Equations Using Summation-by-Parts Operators Proceedings of ICOSAHOM 2018
source
Trixi.flux_ranochaMethod
flux_ranocha(u_ll, u_rr, orientation_or_normal_direction,
-             equations::CompressibleEulerEquations2D)

Entropy conserving and kinetic energy preserving two-point flux by

  • Hendrik Ranocha (2018) Generalised Summation-by-Parts Operators and Entropy Stability of Numerical Methods for Hyperbolic Balance Laws PhD thesis, TU Braunschweig

See also

  • Hendrik Ranocha (2020) Entropy Conserving and Kinetic Energy Preserving Numerical Methods for the Euler Equations Using Summation-by-Parts Operators Proceedings of ICOSAHOM 2018
source
Trixi.flux_ranochaMethod
flux_ranocha(u_ll, u_rr, orientation_or_normal_direction,
-             equations::CompressibleEulerEquations3D)

Entropy conserving and kinetic energy preserving two-point flux by

  • Hendrik Ranocha (2018) Generalised Summation-by-Parts Operators and Entropy Stability of Numerical Methods for Hyperbolic Balance Laws PhD thesis, TU Braunschweig

See also

  • Hendrik Ranocha (2020) Entropy Conserving and Kinetic Energy Preserving Numerical Methods for the Euler Equations Using Summation-by-Parts Operators Proceedings of ICOSAHOM 2018
source
Trixi.flux_ranochaMethod
flux_ranocha(u_ll, u_rr, orientation_or_normal_direction,
-             equations::CompressibleEulerMulticomponentEquations1D)

Adaption of the entropy conserving and kinetic energy preserving two-point flux by

  • Hendrik Ranocha (2018) Generalised Summation-by-Parts Operators and Entropy Stability of Numerical Methods for Hyperbolic Balance Laws PhD thesis, TU Braunschweig

See also

  • Hendrik Ranocha (2020) Entropy Conserving and Kinetic Energy Preserving Numerical Methods for the Euler Equations Using Summation-by-Parts Operators Proceedings of ICOSAHOM 2018
source
Trixi.flux_ranochaMethod
flux_ranocha(u_ll, u_rr, orientation_or_normal_direction,
-             equations::CompressibleEulerMulticomponentEquations2D)

Adaption of the entropy conserving and kinetic energy preserving two-point flux by

  • Hendrik Ranocha (2018) Generalised Summation-by-Parts Operators and Entropy Stability of Numerical Methods for Hyperbolic Balance Laws PhD thesis, TU Braunschweig

See also

  • Hendrik Ranocha (2020) Entropy Conserving and Kinetic Energy Preserving Numerical Methods for the Euler Equations Using Summation-by-Parts Operators Proceedings of ICOSAHOM 2018
source
Trixi.flux_shima_etalMethod
flux_shima_etal(u_ll, u_rr, orientation, equations::CompressibleEulerEquations1D)

This flux is is a modification of the original kinetic energy preserving two-point flux by

  • Yuichi Kuya, Kosuke Totani and Soshi Kawai (2018) Kinetic energy and entropy preserving schemes for compressible flows by split convective forms DOI: 10.1016/j.jcp.2018.08.058

The modification is in the energy flux to guarantee pressure equilibrium and was developed by

  • Nao Shima, Yuichi Kuya, Yoshiharu Tamaki, Soshi Kawai (JCP 2020) Preventing spurious pressure oscillations in split convective form discretizations for compressible flows DOI: 10.1016/j.jcp.2020.110060
source
Trixi.flux_shima_etalMethod
flux_shima_etal(u_ll, u_rr, orientation_or_normal_direction,
-                equations::CompressibleEulerEquations2D)

This flux is is a modification of the original kinetic energy preserving two-point flux by

  • Yuichi Kuya, Kosuke Totani and Soshi Kawai (2018) Kinetic energy and entropy preserving schemes for compressible flows by split convective forms DOI: 10.1016/j.jcp.2018.08.058

The modification is in the energy flux to guarantee pressure equilibrium and was developed by

  • Nao Shima, Yuichi Kuya, Yoshiharu Tamaki, Soshi Kawai (JCP 2020) Preventing spurious pressure oscillations in split convective form discretizations for compressible flows DOI: 10.1016/j.jcp.2020.110060
source
Trixi.flux_shima_etalMethod
flux_shima_etal(u_ll, u_rr, orientation_or_normal_direction,
-                equations::CompressibleEulerEquations3D)

This flux is is a modification of the original kinetic energy preserving two-point flux by

  • Yuichi Kuya, Kosuke Totani and Soshi Kawai (2018) Kinetic energy and entropy preserving schemes for compressible flows by split convective forms DOI: 10.1016/j.jcp.2018.08.058

The modification is in the energy flux to guarantee pressure equilibrium and was developed by

  • Nao Shima, Yuichi Kuya, Yoshiharu Tamaki, Soshi Kawai (JCP 2020) Preventing spurious pressure oscillations in split convective form discretizations for compressible flows DOI: 10.1016/j.jcp.2020.110060
source
Trixi.flux_wintermeyer_etalMethod
flux_wintermeyer_etal(u_ll, u_rr, orientation,
-                      equations::ShallowWaterEquations1D)

Total energy conservative (mathematical entropy for shallow water equations) split form. When the bottom topography is nonzero this scheme will be well-balanced when used as a volume_flux. The surface_flux should still use, e.g., flux_fjordholm_etal.

Further details are available in Theorem 1 of the paper:

  • Niklas Wintermeyer, Andrew R. Winters, Gregor J. Gassner and David A. Kopriva (2017) An entropy stable nodal discontinuous Galerkin method for the two dimensional shallow water equations on unstructured curvilinear meshes with discontinuous bathymetry DOI: 10.1016/j.jcp.2017.03.036
source
Trixi.flux_wintermeyer_etalMethod
flux_wintermeyer_etal(u_ll, u_rr, orientation_or_normal_direction,
-                      equations::ShallowWaterEquations2D)

Total energy conservative (mathematical entropy for shallow water equations) split form. When the bottom topography is nonzero this scheme will be well-balanced when used as a volume_flux. The surface_flux should still use, e.g., flux_fjordholm_etal.

Further details are available in Theorem 1 of the paper:

  • Niklas Wintermeyer, Andrew R. Winters, Gregor J. Gassner and David A. Kopriva (2017) An entropy stable nodal discontinuous Galerkin method for the two dimensional shallow water equations on unstructured curvilinear meshes with discontinuous bathymetry DOI: 10.1016/j.jcp.2017.03.036
source
Trixi.flux_wintermeyer_etalMethod
flux_wintermeyer_etal(u_ll, u_rr, orientation,
-                      equations::ShallowWaterTwoLayerEquations1D)

Total energy conservative (mathematical entropy for two-layer shallow water equations) split form. When the bottom topography is nonzero this scheme will be well-balanced when used as a volume_flux. The surface_flux should still use, e.g., flux_fjordholm_etal. To obtain the flux for the two-layer shallow water equations the flux that is described in the paper for the normal shallow water equations is used within each layer.

Further details are available in Theorem 1 of the paper:

  • Niklas Wintermeyer, Andrew R. Winters, Gregor J. Gassner and David A. Kopriva (2017) An entropy stable nodal discontinuous Galerkin method for the two dimensional shallow water equations on unstructured curvilinear meshes with discontinuous bathymetry DOI: 10.1016/j.jcp.2017.03.036
source
Trixi.flux_wintermeyer_etalMethod
flux_wintermeyer_etal(u_ll, u_rr, orientation,
-                      equations::ShallowWaterTwoLayerEquations2D)

Total energy conservative (mathematical entropy for two-layer shallow water equations) split form. When the bottom topography is nonzero this scheme will be well-balanced when used as a volume_flux. The surface_flux should still use, e.g., flux_fjordholm_etal. To obtain the flux for the two-layer shallow water equations the flux that is described in the paper for the normal shallow water equations is used within each layer.

Further details are available in Theorem 1 of the paper:

  • Niklas Wintermeyer, Andrew R. Winters, Gregor J. Gassner and David A. Kopriva (2017) An entropy stable nodal discontinuous Galerkin method for the two dimensional shallow water equations on unstructured curvilinear meshes with discontinuous bathymetry DOI: 10.1016/j.jcp.2017.03.036
source
Trixi.flux_winters_etalMethod
flux_winters_etal(u_ll, u_rr, normal_direction,
-                  equations::PolytropicEulerEquations2D)

Entropy conserving two-point flux for isothermal or polytropic gases. Requires a special weighted Stolarsky mean for the evaluation of the density denoted here as stolarsky_mean. Note, for isothermal gases where gamma = 1 this stolarsky_mean becomes the ln_mean.

For details see Section 3.2 of the following reference

  • Andrew R. Winters, Christof Czernik, Moritz B. Schily & Gregor J. Gassner (2020) Entropy stable numerical approximations for the isothermal and polytropic Euler equations DOI: 10.1007/s10543-019-00789-w
source
Trixi.get_nameMethod
get_name(x)

Returns a name of x ready for pretty printing. By default, return string(y) if x isa Val{y} and return string(x) otherwise.

Examples

julia> Trixi.get_name("test")
+                                      equations::ShallowWaterEquations2D)

Non-symmetric two-point volume flux discretizing the nonconservative (source) term that contains the gradient of the bottom topography ShallowWaterEquations2D.

On curvilinear meshes, this nonconservative flux depends on both the contravariant vector (normal direction) at the current node and the averaged one. This is different from numerical fluxes used to discretize conservative terms.

Further details are available in the paper:

  • Niklas Wintermeyer, Andrew R. Winters, Gregor J. Gassner and David A. Kopriva (2017) An entropy stable nodal discontinuous Galerkin method for the two dimensional shallow water equations on unstructured curvilinear meshes with discontinuous bathymetry DOI: 10.1016/j.jcp.2017.03.036
source
Trixi.flux_nonconservative_wintermeyer_etalMethod
flux_nonconservative_wintermeyer_etal(u_ll, u_rr, orientation::Integer,
+                                      equations::ShallowWaterTwoLayerEquations1D)
Experimental code

This numerical flux is experimental and may change in any future release.

Non-symmetric two-point volume flux discretizing the nonconservative (source) term that contains the gradient of the bottom topography ShallowWaterTwoLayerEquations2D and an additional term that couples the momentum of both layers. This is a slightly modified version to account for the additional source term compared to the standard SWE described in the paper.

Further details are available in the paper:

  • Niklas Wintermeyer, Andrew R. Winters, Gregor J. Gassner and David A. Kopriva (2017) An entropy stable nodal discontinuous Galerkin method for the two dimensional shallow water equations on unstructured curvilinear meshes with discontinuous bathymetry DOI: 10.1016/j.jcp.2017.03.036
source
Trixi.flux_nonconservative_wintermeyer_etalMethod
flux_nonconservative_wintermeyer_etal(u_ll, u_rr, orientation::Integer,
+                                      equations::ShallowWaterTwoLayerEquations2D)
Experimental code

This numerical flux is experimental and may change in any future release.

Non-symmetric two-point volume flux discretizing the nonconservative (source) term that contains the gradient of the bottom topography ShallowWaterTwoLayerEquations2D and an additional term that couples the momentum of both layers. This is a slightly modified version to account for the additional source term compared to the standard SWE described in the paper.

Further details are available in the paper:

  • Niklas Wintermeyer, Andrew R. Winters, Gregor J. Gassner and David A. Kopriva (2017) An entropy stable nodal discontinuous Galerkin method for the two dimensional shallow water equations on unstructured curvilinear meshes with discontinuous bathymetry DOI: 10.1016/j.jcp.2017.03.036
source
Trixi.flux_ranochaMethod
flux_ranocha(u_ll, u_rr, orientation_or_normal_direction, equations::CompressibleEulerEquations1D)

Entropy conserving and kinetic energy preserving two-point flux by

  • Hendrik Ranocha (2018) Generalised Summation-by-Parts Operators and Entropy Stability of Numerical Methods for Hyperbolic Balance Laws PhD thesis, TU Braunschweig

See also

  • Hendrik Ranocha (2020) Entropy Conserving and Kinetic Energy Preserving Numerical Methods for the Euler Equations Using Summation-by-Parts Operators Proceedings of ICOSAHOM 2018
source
Trixi.flux_ranochaMethod
flux_ranocha(u_ll, u_rr, orientation_or_normal_direction,
+             equations::CompressibleEulerEquations2D)

Entropy conserving and kinetic energy preserving two-point flux by

  • Hendrik Ranocha (2018) Generalised Summation-by-Parts Operators and Entropy Stability of Numerical Methods for Hyperbolic Balance Laws PhD thesis, TU Braunschweig

See also

  • Hendrik Ranocha (2020) Entropy Conserving and Kinetic Energy Preserving Numerical Methods for the Euler Equations Using Summation-by-Parts Operators Proceedings of ICOSAHOM 2018
source
Trixi.flux_ranochaMethod
flux_ranocha(u_ll, u_rr, orientation_or_normal_direction,
+             equations::CompressibleEulerEquations3D)

Entropy conserving and kinetic energy preserving two-point flux by

  • Hendrik Ranocha (2018) Generalised Summation-by-Parts Operators and Entropy Stability of Numerical Methods for Hyperbolic Balance Laws PhD thesis, TU Braunschweig

See also

  • Hendrik Ranocha (2020) Entropy Conserving and Kinetic Energy Preserving Numerical Methods for the Euler Equations Using Summation-by-Parts Operators Proceedings of ICOSAHOM 2018
source
Trixi.flux_ranochaMethod
flux_ranocha(u_ll, u_rr, orientation_or_normal_direction,
+             equations::CompressibleEulerMulticomponentEquations1D)

Adaption of the entropy conserving and kinetic energy preserving two-point flux by

  • Hendrik Ranocha (2018) Generalised Summation-by-Parts Operators and Entropy Stability of Numerical Methods for Hyperbolic Balance Laws PhD thesis, TU Braunschweig

See also

  • Hendrik Ranocha (2020) Entropy Conserving and Kinetic Energy Preserving Numerical Methods for the Euler Equations Using Summation-by-Parts Operators Proceedings of ICOSAHOM 2018
source
Trixi.flux_ranochaMethod
flux_ranocha(u_ll, u_rr, orientation_or_normal_direction,
+             equations::CompressibleEulerMulticomponentEquations2D)

Adaption of the entropy conserving and kinetic energy preserving two-point flux by

  • Hendrik Ranocha (2018) Generalised Summation-by-Parts Operators and Entropy Stability of Numerical Methods for Hyperbolic Balance Laws PhD thesis, TU Braunschweig

See also

  • Hendrik Ranocha (2020) Entropy Conserving and Kinetic Energy Preserving Numerical Methods for the Euler Equations Using Summation-by-Parts Operators Proceedings of ICOSAHOM 2018
source
Trixi.flux_shima_etalMethod
flux_shima_etal(u_ll, u_rr, orientation, equations::CompressibleEulerEquations1D)

This flux is is a modification of the original kinetic energy preserving two-point flux by

  • Yuichi Kuya, Kosuke Totani and Soshi Kawai (2018) Kinetic energy and entropy preserving schemes for compressible flows by split convective forms DOI: 10.1016/j.jcp.2018.08.058

The modification is in the energy flux to guarantee pressure equilibrium and was developed by

  • Nao Shima, Yuichi Kuya, Yoshiharu Tamaki, Soshi Kawai (JCP 2020) Preventing spurious pressure oscillations in split convective form discretizations for compressible flows DOI: 10.1016/j.jcp.2020.110060
source
Trixi.flux_shima_etalMethod
flux_shima_etal(u_ll, u_rr, orientation_or_normal_direction,
+                equations::CompressibleEulerEquations2D)

This flux is is a modification of the original kinetic energy preserving two-point flux by

  • Yuichi Kuya, Kosuke Totani and Soshi Kawai (2018) Kinetic energy and entropy preserving schemes for compressible flows by split convective forms DOI: 10.1016/j.jcp.2018.08.058

The modification is in the energy flux to guarantee pressure equilibrium and was developed by

  • Nao Shima, Yuichi Kuya, Yoshiharu Tamaki, Soshi Kawai (JCP 2020) Preventing spurious pressure oscillations in split convective form discretizations for compressible flows DOI: 10.1016/j.jcp.2020.110060
source
Trixi.flux_shima_etalMethod
flux_shima_etal(u_ll, u_rr, orientation_or_normal_direction,
+                equations::CompressibleEulerEquations3D)

This flux is is a modification of the original kinetic energy preserving two-point flux by

  • Yuichi Kuya, Kosuke Totani and Soshi Kawai (2018) Kinetic energy and entropy preserving schemes for compressible flows by split convective forms DOI: 10.1016/j.jcp.2018.08.058

The modification is in the energy flux to guarantee pressure equilibrium and was developed by

  • Nao Shima, Yuichi Kuya, Yoshiharu Tamaki, Soshi Kawai (JCP 2020) Preventing spurious pressure oscillations in split convective form discretizations for compressible flows DOI: 10.1016/j.jcp.2020.110060
source
Trixi.flux_wintermeyer_etalMethod
flux_wintermeyer_etal(u_ll, u_rr, orientation,
+                      equations::ShallowWaterEquations1D)

Total energy conservative (mathematical entropy for shallow water equations) split form. When the bottom topography is nonzero this scheme will be well-balanced when used as a volume_flux. The surface_flux should still use, e.g., flux_fjordholm_etal.

Further details are available in Theorem 1 of the paper:

  • Niklas Wintermeyer, Andrew R. Winters, Gregor J. Gassner and David A. Kopriva (2017) An entropy stable nodal discontinuous Galerkin method for the two dimensional shallow water equations on unstructured curvilinear meshes with discontinuous bathymetry DOI: 10.1016/j.jcp.2017.03.036
source
Trixi.flux_wintermeyer_etalMethod
flux_wintermeyer_etal(u_ll, u_rr, orientation_or_normal_direction,
+                      equations::ShallowWaterEquations2D)

Total energy conservative (mathematical entropy for shallow water equations) split form. When the bottom topography is nonzero this scheme will be well-balanced when used as a volume_flux. The surface_flux should still use, e.g., flux_fjordholm_etal.

Further details are available in Theorem 1 of the paper:

  • Niklas Wintermeyer, Andrew R. Winters, Gregor J. Gassner and David A. Kopriva (2017) An entropy stable nodal discontinuous Galerkin method for the two dimensional shallow water equations on unstructured curvilinear meshes with discontinuous bathymetry DOI: 10.1016/j.jcp.2017.03.036
source
Trixi.flux_wintermeyer_etalMethod
flux_wintermeyer_etal(u_ll, u_rr, orientation,
+                      equations::ShallowWaterTwoLayerEquations1D)

Total energy conservative (mathematical entropy for two-layer shallow water equations) split form. When the bottom topography is nonzero this scheme will be well-balanced when used as a volume_flux. The surface_flux should still use, e.g., flux_fjordholm_etal. To obtain the flux for the two-layer shallow water equations the flux that is described in the paper for the normal shallow water equations is used within each layer.

Further details are available in Theorem 1 of the paper:

  • Niklas Wintermeyer, Andrew R. Winters, Gregor J. Gassner and David A. Kopriva (2017) An entropy stable nodal discontinuous Galerkin method for the two dimensional shallow water equations on unstructured curvilinear meshes with discontinuous bathymetry DOI: 10.1016/j.jcp.2017.03.036
source
Trixi.flux_wintermeyer_etalMethod
flux_wintermeyer_etal(u_ll, u_rr, orientation,
+                      equations::ShallowWaterTwoLayerEquations2D)

Total energy conservative (mathematical entropy for two-layer shallow water equations) split form. When the bottom topography is nonzero this scheme will be well-balanced when used as a volume_flux. The surface_flux should still use, e.g., flux_fjordholm_etal. To obtain the flux for the two-layer shallow water equations the flux that is described in the paper for the normal shallow water equations is used within each layer.

Further details are available in Theorem 1 of the paper:

  • Niklas Wintermeyer, Andrew R. Winters, Gregor J. Gassner and David A. Kopriva (2017) An entropy stable nodal discontinuous Galerkin method for the two dimensional shallow water equations on unstructured curvilinear meshes with discontinuous bathymetry DOI: 10.1016/j.jcp.2017.03.036
source
Trixi.flux_winters_etalMethod
flux_winters_etal(u_ll, u_rr, normal_direction,
+                  equations::PolytropicEulerEquations2D)

Entropy conserving two-point flux for isothermal or polytropic gases. Requires a special weighted Stolarsky mean for the evaluation of the density denoted here as stolarsky_mean. Note, for isothermal gases where gamma = 1 this stolarsky_mean becomes the ln_mean.

For details see Section 3.2 of the following reference

  • Andrew R. Winters, Christof Czernik, Moritz B. Schily & Gregor J. Gassner (2020) Entropy stable numerical approximations for the isothermal and polytropic Euler equations DOI: 10.1007/s10543-019-00789-w
source
Trixi.get_nameMethod
get_name(x)

Returns a name of x ready for pretty printing. By default, return string(y) if x isa Val{y} and return string(x) otherwise.

Examples

julia> Trixi.get_name("test")
 "test"
 
 julia> Trixi.get_name(Val(:test))
-"test"
source
Trixi.get_nameMethod
get_name(equations::AbstractEquations)

Returns the canonical, human-readable name for the given system of equations.

Examples

julia> Trixi.get_name(CompressibleEulerEquations1D(1.4))
-"CompressibleEulerEquations1D"
source
Trixi.getmeshMethod
getmesh(pd::AbstractPlotData)

Extract grid lines from pd for plotting with Plots.plot.

Experimental implementation

This is an experimental feature and may change in future releases.

source
Trixi.global_mean_varsMethod
global_mean_vars(equations::AcousticPerturbationEquations2D)

Returns the global mean variables stored in equations. This makes it easier to define flexible initial conditions for problems with constant mean flow.

source
Trixi.have_nonconservative_termsMethod
have_nonconservative_terms(equations)

Trait function determining whether equations represent a conservation law with or without nonconservative terms. Classical conservation laws such as the CompressibleEulerEquations2D do not have nonconservative terms. The ShallowWaterEquations2D with non-constant bottom topography are an example of equations with nonconservative terms. The return value will be True() or False() to allow dispatching on the return type.

source
Trixi.hydrostatic_reconstruction_audusse_etalMethod
hydrostatic_reconstruction_audusse_etal(u_ll, u_rr, orientation::Integer,
-                                        equations::ShallowWaterEquations1D)

A particular type of hydrostatic reconstruction on the water height to guarantee well-balancedness for a general bottom topography ShallowWaterEquations1D. The reconstructed solution states u_ll_star and u_rr_star variables are then used to evaluate the surface numerical flux at the interface. Use in combination with the generic numerical flux routine FluxHydrostaticReconstruction.

Further details on this hydrostatic reconstruction and its motivation can be found in

  • Emmanuel Audusse, François Bouchut, Marie-Odile Bristeau, Rupert Klein, and Benoit Perthame (2004) A fast and stable well-balanced scheme with hydrostatic reconstruction for shallow water flows DOI: 10.1137/S1064827503431090
source
Trixi.hydrostatic_reconstruction_audusse_etalMethod
hydrostatic_reconstruction_audusse_etal(u_ll, u_rr, orientation_or_normal_direction,
-                                        equations::ShallowWaterEquations2D)

A particular type of hydrostatic reconstruction on the water height to guarantee well-balancedness for a general bottom topography ShallowWaterEquations2D. The reconstructed solution states u_ll_star and u_rr_star variables are used to evaluate the surface numerical flux at the interface. Use in combination with the generic numerical flux routine FluxHydrostaticReconstruction.

Further details for the hydrostatic reconstruction and its motivation can be found in

  • Emmanuel Audusse, François Bouchut, Marie-Odile Bristeau, Rupert Klein, and Benoit Perthame (2004) A fast and stable well-balanced scheme with hydrostatic reconstruction for shallow water flows DOI: 10.1137/S1064827503431090
source
Trixi.hydrostatic_reconstruction_chen_noelleMethod
hydrostatic_reconstruction_chen_noelle(u_ll, u_rr, orientation::Integer,
-                                       equations::ShallowWaterEquations1D)

A particular type of hydrostatic reconstruction of the water height to guarantee well-balancedness for a general bottom topography of the ShallowWaterEquations1D. The reconstructed solution states u_ll_star and u_rr_star variables are used to evaluate the surface numerical flux at the interface. The key idea is a linear reconstruction of the bottom and water height at the interfaces using subcells. Use in combination with the generic numerical flux routine FluxHydrostaticReconstruction.

Further details on this hydrostatic reconstruction and its motivation can be found in

  • Guoxian Chen and Sebastian Noelle (2017) A new hydrostatic reconstruction scheme based on subcell reconstructions DOI:10.1137/15M1053074
source
Trixi.hydrostatic_reconstruction_chen_noelleMethod
hydrostatic_reconstruction_chen_noelle(u_ll, u_rr, orientation::Integer,
-                                       equations::ShallowWaterEquations2D)

A particular type of hydrostatic reconstruction of the water height to guarantee well-balancedness for a general bottom topography of the ShallowWaterEquations2D. The reconstructed solution states u_ll_star and u_rr_star variables are then used to evaluate the surface numerical flux at the interface. The key idea is a linear reconstruction of the bottom and water height at the interfaces using subcells. Use in combination with the generic numerical flux routine FluxHydrostaticReconstruction.

Further details on this hydrostatic reconstruction and its motivation can be found in

  • Guoxian Chen and Sebastian Noelle (2017) A new hydrostatic reconstruction scheme based on subcell reconstructions DOI:10.1137/15M1053074
source
Trixi.init_mpiMethod
init_mpi()

Initialize MPI by calling MPI.Initialized(). The function will check if MPI is already initialized and if yes, do nothing, thus it is safe to call it multiple times.

source
Trixi.init_p4estMethod
init_p4est()

Initialize p4est by calling p4est_init and setting the log level to SC_LP_ERROR. This function will check if p4est is already initialized and if yes, do nothing, thus it is safe to call it multiple times.

source
Trixi.init_t8codeMethod
init_t8code()

Initialize t8code by calling sc_init, p4est_init, and t8_init while setting the log level to SC_LP_ERROR. This function will check if t8code is already initialized and if yes, do nothing, thus it is safe to call it multiple times.

source
Trixi.initial_condition_constantMethod
initial_condition_constant(x, t, equations::AcousticPerturbationEquations2D)

A constant initial condition where the state variables are zero and the mean flow is constant. Uses the global mean values from equations.

source
Trixi.initial_condition_density_waveMethod
initial_condition_density_wave(x, t, equations::CompressibleEulerEquations1D)

A sine wave in the density with constant velocity and pressure; reduces the compressible Euler equations to the linear advection equations. This setup is the test case for stability of EC fluxes from paper

  • Gregor J. Gassner, Magnus Svärd, Florian J. Hindenlang (2020) Stability issues of entropy-stable and/or split-form high-order schemes arXiv: 2007.09026

with the following parameters

  • domain [-1, 1]
  • mesh = 4x4
  • polydeg = 5
source
Trixi.initial_condition_density_waveMethod
initial_condition_density_wave(x, t, equations::CompressibleEulerEquations2D)

A sine wave in the density with constant velocity and pressure; reduces the compressible Euler equations to the linear advection equations. This setup is the test case for stability of EC fluxes from paper

  • Gregor J. Gassner, Magnus Svärd, Florian J. Hindenlang (2020) Stability issues of entropy-stable and/or split-form high-order schemes arXiv: 2007.09026

with the following parameters

  • domain [-1, 1]
  • mesh = 4x4
  • polydeg = 5
source
Trixi.initial_condition_eoc_test_coupled_euler_gravityMethod
initial_condition_eoc_test_coupled_euler_gravity(x, t, equations::CompressibleEulerEquations1D)

One dimensional variant of the setup used for convergence tests of the Euler equations with self-gravity from

  • Michael Schlottke-Lakemper, Andrew R. Winters, Hendrik Ranocha, Gregor J. Gassner (2020) A purely hyperbolic discontinuous Galerkin approach for self-gravitating gas dynamics arXiv: 2008.10593
Note

There is no additional source term necessary for the manufactured solution in one spatial dimension. Thus, source_terms_eoc_test_coupled_euler_gravity is not present there.

source
Trixi.initial_condition_eoc_test_coupled_euler_gravityMethod
initial_condition_eoc_test_coupled_euler_gravity(x, t, equations::CompressibleEulerEquations2D)

Setup used for convergence tests of the Euler equations with self-gravity used in

  • Michael Schlottke-Lakemper, Andrew R. Winters, Hendrik Ranocha, Gregor J. Gassner (2020) A purely hyperbolic discontinuous Galerkin approach for self-gravitating gas dynamics arXiv: 2008.10593

in combination with source_terms_eoc_test_coupled_euler_gravity or source_terms_eoc_test_euler.

source
Trixi.initial_condition_eoc_test_coupled_euler_gravityMethod
initial_condition_eoc_test_coupled_euler_gravity(x, t, equations::CompressibleEulerEquations3D)

Setup used for convergence tests of the Euler equations with self-gravity used in

  • Michael Schlottke-Lakemper, Andrew R. Winters, Hendrik Ranocha, Gregor J. Gassner (2020) A purely hyperbolic discontinuous Galerkin approach for self-gravitating gas dynamics arXiv: 2008.10593

in combination with source_terms_eoc_test_coupled_euler_gravity or source_terms_eoc_test_euler.

source
Trixi.initial_condition_gaussMethod
initial_condition_gauss(x, t, equations::AcousticPerturbationEquations2D)

A Gaussian pulse in a constant mean flow. Uses the global mean values from equations.

source
Trixi.initial_condition_weak_blast_waveMethod
initial_condition_weak_blast_wave(x, t, equations::CompressibleEulerEquations1D)

A weak blast wave taken from

  • Sebastian Hennemann, Gregor J. Gassner (2020) A provably entropy stable subcell shock capturing approach for high order split form DG arXiv: 2008.12044
source
Trixi.initial_condition_weak_blast_waveMethod
initial_condition_weak_blast_wave(x, t, equations::CompressibleEulerEquations2D)

A weak blast wave taken from

  • Sebastian Hennemann, Gregor J. Gassner (2020) A provably entropy stable subcell shock capturing approach for high order split form DG arXiv: 2008.12044
source
Trixi.initial_condition_weak_blast_waveMethod
initial_condition_weak_blast_wave(x, t, equations::CompressibleEulerEquations3D)

A weak blast wave taken from

  • Sebastian Hennemann, Gregor J. Gassner (2020) A provably entropy stable subcell shock capturing approach for high order split form DG arXiv: 2008.12044
source
Trixi.initial_condition_weak_blast_waveMethod
initial_condition_weak_blast_wave(x, t, equations::CompressibleEulerMulticomponentEquations1D)

A for multicomponent adapted weak blast wave adapted to multicomponent and taken from

  • Sebastian Hennemann, Gregor J. Gassner (2020) A provably entropy stable subcell shock capturing approach for high order split form DG arXiv: 2008.12044
source
Trixi.initial_condition_weak_blast_waveMethod
initial_condition_weak_blast_wave(x, t, equations::CompressibleEulerMulticomponentEquations2D)

A for multicomponent adapted weak blast wave taken from

  • Sebastian Hennemann, Gregor J. Gassner (2020) A provably entropy stable subcell shock capturing approach for high order split form DG arXiv: 2008.12044
source
Trixi.initial_condition_weak_blast_waveMethod
initial_condition_weak_blast_wave(x, t, equations::IdealGlmMhdEquations1D)

A weak blast wave adapted from

  • Sebastian Hennemann, Gregor J. Gassner (2020) A provably entropy stable subcell shock capturing approach for high order split form DG arXiv: 2008.12044
source
Trixi.initial_condition_weak_blast_waveMethod
initial_condition_weak_blast_wave(x, t, equations::IdealGlmMhdEquations2D)

A weak blast wave adapted from

  • Sebastian Hennemann, Gregor J. Gassner (2020) A provably entropy stable subcell shock capturing approach for high order split form DG arXiv: 2008.12044
source
Trixi.initial_condition_weak_blast_waveMethod
initial_condition_weak_blast_wave(x, t, equations::IdealGlmMhdEquations3D)

A weak blast wave adapted from

  • Sebastian Hennemann, Gregor J. Gassner (2020) A provably entropy stable subcell shock capturing approach for high order split form DG arXiv: 2008.12044
source
Trixi.initial_condition_weak_blast_waveMethod
initial_condition_weak_blast_wave(x, t, equations::IdealGlmMhdMulticomponentEquations1D)

A weak blast wave adapted from

  • Sebastian Hennemann, Gregor J. Gassner (2020) A provably entropy stable subcell shock capturing approach for high order split form DG arXiv: 2008.12044
source
Trixi.initial_condition_weak_blast_waveMethod
initial_condition_weak_blast_wave(x, t, equations::IdealGlmMhdMulticomponentEquations2D)

A weak blast wave adapted from

  • Sebastian Hennemann, Gregor J. Gassner (2020) A provably entropy stable subcell shock capturing approach for high order split form DG arXiv: 2008.12044
source
Trixi.initial_condition_weak_blast_waveMethod
initial_condition_weak_blast_wave(x, t, equations::PolytropicEulerEquations2D)

A weak blast wave adapted from

  • Sebastian Hennemann, Gregor J. Gassner (2020) A provably entropy stable subcell shock capturing approach for high order split form DG arXiv: 2008.12044
source
Trixi.initial_condition_weak_blast_waveMethod
initial_condition_weak_blast_wave(x, t, equations::ShallowWaterEquations1D)

A weak blast wave discontinuity useful for testing, e.g., total energy conservation. Note for the shallow water equations to the total energy acts as a mathematical entropy function.

source
Trixi.initial_condition_weak_blast_waveMethod
initial_condition_weak_blast_wave(x, t, equations::ShallowWaterEquations2D)

A weak blast wave discontinuity useful for testing, e.g., total energy conservation. Note for the shallow water equations to the total energy acts as a mathematical entropy function.

source
Trixi.integrate_via_indicesMethod
integrate_via_indices(func, u_ode, semi::AbstractSemidiscretization, args...; normalize=true)

Call func(u, i..., element, equations, solver, args...) for all nodal indices i..., element and integrate the result using a quadrature associated with the semidiscretization semi.

If normalize is true, the result is divided by the total volume of the computational domain.

source
Trixi.inv_ln_meanMethod
inv_ln_mean(x, y)

Compute the inverse 1 / ln_mean(x, y) of the logarithmic mean ln_mean.

This function may be used to increase performance where the inverse of the logarithmic mean is needed, by replacing a (slow) division by a (fast) multiplication.

source
Trixi.get_nameMethod
get_name(equations::AbstractEquations)

Returns the canonical, human-readable name for the given system of equations.

Examples

julia> Trixi.get_name(CompressibleEulerEquations1D(1.4))
+"CompressibleEulerEquations1D"
source
Trixi.getmeshMethod
getmesh(pd::AbstractPlotData)

Extract grid lines from pd for plotting with Plots.plot.

Experimental implementation

This is an experimental feature and may change in future releases.

source
Trixi.global_mean_varsMethod
global_mean_vars(equations::AcousticPerturbationEquations2D)

Returns the global mean variables stored in equations. This makes it easier to define flexible initial conditions for problems with constant mean flow.

source
Trixi.have_nonconservative_termsMethod
have_nonconservative_terms(equations)

Trait function determining whether equations represent a conservation law with or without nonconservative terms. Classical conservation laws such as the CompressibleEulerEquations2D do not have nonconservative terms. The ShallowWaterEquations2D with non-constant bottom topography are an example of equations with nonconservative terms. The return value will be True() or False() to allow dispatching on the return type.

source
Trixi.hydrostatic_reconstruction_audusse_etalMethod
hydrostatic_reconstruction_audusse_etal(u_ll, u_rr, orientation::Integer,
+                                        equations::ShallowWaterEquations1D)

A particular type of hydrostatic reconstruction on the water height to guarantee well-balancedness for a general bottom topography ShallowWaterEquations1D. The reconstructed solution states u_ll_star and u_rr_star variables are then used to evaluate the surface numerical flux at the interface. Use in combination with the generic numerical flux routine FluxHydrostaticReconstruction.

Further details on this hydrostatic reconstruction and its motivation can be found in

  • Emmanuel Audusse, François Bouchut, Marie-Odile Bristeau, Rupert Klein, and Benoit Perthame (2004) A fast and stable well-balanced scheme with hydrostatic reconstruction for shallow water flows DOI: 10.1137/S1064827503431090
source
Trixi.hydrostatic_reconstruction_audusse_etalMethod
hydrostatic_reconstruction_audusse_etal(u_ll, u_rr, orientation_or_normal_direction,
+                                        equations::ShallowWaterEquations2D)

A particular type of hydrostatic reconstruction on the water height to guarantee well-balancedness for a general bottom topography ShallowWaterEquations2D. The reconstructed solution states u_ll_star and u_rr_star variables are used to evaluate the surface numerical flux at the interface. Use in combination with the generic numerical flux routine FluxHydrostaticReconstruction.

Further details for the hydrostatic reconstruction and its motivation can be found in

  • Emmanuel Audusse, François Bouchut, Marie-Odile Bristeau, Rupert Klein, and Benoit Perthame (2004) A fast and stable well-balanced scheme with hydrostatic reconstruction for shallow water flows DOI: 10.1137/S1064827503431090
source
Trixi.hydrostatic_reconstruction_chen_noelleMethod
hydrostatic_reconstruction_chen_noelle(u_ll, u_rr, orientation::Integer,
+                                       equations::ShallowWaterEquations1D)

A particular type of hydrostatic reconstruction of the water height to guarantee well-balancedness for a general bottom topography of the ShallowWaterEquations1D. The reconstructed solution states u_ll_star and u_rr_star variables are used to evaluate the surface numerical flux at the interface. The key idea is a linear reconstruction of the bottom and water height at the interfaces using subcells. Use in combination with the generic numerical flux routine FluxHydrostaticReconstruction.

Further details on this hydrostatic reconstruction and its motivation can be found in

  • Guoxian Chen and Sebastian Noelle (2017) A new hydrostatic reconstruction scheme based on subcell reconstructions DOI:10.1137/15M1053074
source
Trixi.hydrostatic_reconstruction_chen_noelleMethod
hydrostatic_reconstruction_chen_noelle(u_ll, u_rr, orientation::Integer,
+                                       equations::ShallowWaterEquations2D)

A particular type of hydrostatic reconstruction of the water height to guarantee well-balancedness for a general bottom topography of the ShallowWaterEquations2D. The reconstructed solution states u_ll_star and u_rr_star variables are then used to evaluate the surface numerical flux at the interface. The key idea is a linear reconstruction of the bottom and water height at the interfaces using subcells. Use in combination with the generic numerical flux routine FluxHydrostaticReconstruction.

Further details on this hydrostatic reconstruction and its motivation can be found in

  • Guoxian Chen and Sebastian Noelle (2017) A new hydrostatic reconstruction scheme based on subcell reconstructions DOI:10.1137/15M1053074
source
Trixi.init_mpiMethod
init_mpi()

Initialize MPI by calling MPI.Initialized(). The function will check if MPI is already initialized and if yes, do nothing, thus it is safe to call it multiple times.

source
Trixi.init_p4estMethod
init_p4est()

Initialize p4est by calling p4est_init and setting the log level to SC_LP_ERROR. This function will check if p4est is already initialized and if yes, do nothing, thus it is safe to call it multiple times.

source
Trixi.init_t8codeMethod
init_t8code()

Initialize t8code by calling sc_init, p4est_init, and t8_init while setting the log level to SC_LP_ERROR. This function will check if t8code is already initialized and if yes, do nothing, thus it is safe to call it multiple times.

source
Trixi.initial_condition_constantMethod
initial_condition_constant(x, t, equations::AcousticPerturbationEquations2D)

A constant initial condition where the state variables are zero and the mean flow is constant. Uses the global mean values from equations.

source
Trixi.initial_condition_density_waveMethod
initial_condition_density_wave(x, t, equations::CompressibleEulerEquations1D)

A sine wave in the density with constant velocity and pressure; reduces the compressible Euler equations to the linear advection equations. This setup is the test case for stability of EC fluxes from paper

  • Gregor J. Gassner, Magnus Svärd, Florian J. Hindenlang (2020) Stability issues of entropy-stable and/or split-form high-order schemes arXiv: 2007.09026

with the following parameters

  • domain [-1, 1]
  • mesh = 4x4
  • polydeg = 5
source
Trixi.initial_condition_density_waveMethod
initial_condition_density_wave(x, t, equations::CompressibleEulerEquations2D)

A sine wave in the density with constant velocity and pressure; reduces the compressible Euler equations to the linear advection equations. This setup is the test case for stability of EC fluxes from paper

  • Gregor J. Gassner, Magnus Svärd, Florian J. Hindenlang (2020) Stability issues of entropy-stable and/or split-form high-order schemes arXiv: 2007.09026

with the following parameters

  • domain [-1, 1]
  • mesh = 4x4
  • polydeg = 5
source
Trixi.initial_condition_eoc_test_coupled_euler_gravityMethod
initial_condition_eoc_test_coupled_euler_gravity(x, t, equations::CompressibleEulerEquations1D)

One dimensional variant of the setup used for convergence tests of the Euler equations with self-gravity from

  • Michael Schlottke-Lakemper, Andrew R. Winters, Hendrik Ranocha, Gregor J. Gassner (2020) A purely hyperbolic discontinuous Galerkin approach for self-gravitating gas dynamics arXiv: 2008.10593
Note

There is no additional source term necessary for the manufactured solution in one spatial dimension. Thus, source_terms_eoc_test_coupled_euler_gravity is not present there.

source
Trixi.initial_condition_eoc_test_coupled_euler_gravityMethod
initial_condition_eoc_test_coupled_euler_gravity(x, t, equations::CompressibleEulerEquations2D)

Setup used for convergence tests of the Euler equations with self-gravity used in

  • Michael Schlottke-Lakemper, Andrew R. Winters, Hendrik Ranocha, Gregor J. Gassner (2020) A purely hyperbolic discontinuous Galerkin approach for self-gravitating gas dynamics arXiv: 2008.10593

in combination with source_terms_eoc_test_coupled_euler_gravity or source_terms_eoc_test_euler.

source
Trixi.initial_condition_eoc_test_coupled_euler_gravityMethod
initial_condition_eoc_test_coupled_euler_gravity(x, t, equations::CompressibleEulerEquations3D)

Setup used for convergence tests of the Euler equations with self-gravity used in

  • Michael Schlottke-Lakemper, Andrew R. Winters, Hendrik Ranocha, Gregor J. Gassner (2020) A purely hyperbolic discontinuous Galerkin approach for self-gravitating gas dynamics arXiv: 2008.10593

in combination with source_terms_eoc_test_coupled_euler_gravity or source_terms_eoc_test_euler.

source
Trixi.initial_condition_gaussMethod
initial_condition_gauss(x, t, equations::AcousticPerturbationEquations2D)

A Gaussian pulse in a constant mean flow. Uses the global mean values from equations.

source
Trixi.initial_condition_weak_blast_waveMethod
initial_condition_weak_blast_wave(x, t, equations::CompressibleEulerEquations1D)

A weak blast wave taken from

  • Sebastian Hennemann, Gregor J. Gassner (2020) A provably entropy stable subcell shock capturing approach for high order split form DG arXiv: 2008.12044
source
Trixi.initial_condition_weak_blast_waveMethod
initial_condition_weak_blast_wave(x, t, equations::CompressibleEulerEquations2D)

A weak blast wave taken from

  • Sebastian Hennemann, Gregor J. Gassner (2020) A provably entropy stable subcell shock capturing approach for high order split form DG arXiv: 2008.12044
source
Trixi.initial_condition_weak_blast_waveMethod
initial_condition_weak_blast_wave(x, t, equations::CompressibleEulerEquations3D)

A weak blast wave taken from

  • Sebastian Hennemann, Gregor J. Gassner (2020) A provably entropy stable subcell shock capturing approach for high order split form DG arXiv: 2008.12044
source
Trixi.initial_condition_weak_blast_waveMethod
initial_condition_weak_blast_wave(x, t, equations::CompressibleEulerMulticomponentEquations1D)

A for multicomponent adapted weak blast wave adapted to multicomponent and taken from

  • Sebastian Hennemann, Gregor J. Gassner (2020) A provably entropy stable subcell shock capturing approach for high order split form DG arXiv: 2008.12044
source
Trixi.initial_condition_weak_blast_waveMethod
initial_condition_weak_blast_wave(x, t, equations::CompressibleEulerMulticomponentEquations2D)

A for multicomponent adapted weak blast wave taken from

  • Sebastian Hennemann, Gregor J. Gassner (2020) A provably entropy stable subcell shock capturing approach for high order split form DG arXiv: 2008.12044
source
Trixi.initial_condition_weak_blast_waveMethod
initial_condition_weak_blast_wave(x, t, equations::IdealGlmMhdEquations1D)

A weak blast wave adapted from

  • Sebastian Hennemann, Gregor J. Gassner (2020) A provably entropy stable subcell shock capturing approach for high order split form DG arXiv: 2008.12044
source
Trixi.initial_condition_weak_blast_waveMethod
initial_condition_weak_blast_wave(x, t, equations::IdealGlmMhdEquations2D)

A weak blast wave adapted from

  • Sebastian Hennemann, Gregor J. Gassner (2020) A provably entropy stable subcell shock capturing approach for high order split form DG arXiv: 2008.12044
source
Trixi.initial_condition_weak_blast_waveMethod
initial_condition_weak_blast_wave(x, t, equations::IdealGlmMhdEquations3D)

A weak blast wave adapted from

  • Sebastian Hennemann, Gregor J. Gassner (2020) A provably entropy stable subcell shock capturing approach for high order split form DG arXiv: 2008.12044
source
Trixi.initial_condition_weak_blast_waveMethod
initial_condition_weak_blast_wave(x, t, equations::IdealGlmMhdMulticomponentEquations1D)

A weak blast wave adapted from

  • Sebastian Hennemann, Gregor J. Gassner (2020) A provably entropy stable subcell shock capturing approach for high order split form DG arXiv: 2008.12044
source
Trixi.initial_condition_weak_blast_waveMethod
initial_condition_weak_blast_wave(x, t, equations::IdealGlmMhdMulticomponentEquations2D)

A weak blast wave adapted from

  • Sebastian Hennemann, Gregor J. Gassner (2020) A provably entropy stable subcell shock capturing approach for high order split form DG arXiv: 2008.12044
source
Trixi.initial_condition_weak_blast_waveMethod
initial_condition_weak_blast_wave(x, t, equations::PolytropicEulerEquations2D)

A weak blast wave adapted from

  • Sebastian Hennemann, Gregor J. Gassner (2020) A provably entropy stable subcell shock capturing approach for high order split form DG arXiv: 2008.12044
source
Trixi.initial_condition_weak_blast_waveMethod
initial_condition_weak_blast_wave(x, t, equations::ShallowWaterEquations1D)

A weak blast wave discontinuity useful for testing, e.g., total energy conservation. Note for the shallow water equations to the total energy acts as a mathematical entropy function.

source
Trixi.initial_condition_weak_blast_waveMethod
initial_condition_weak_blast_wave(x, t, equations::ShallowWaterEquations2D)

A weak blast wave discontinuity useful for testing, e.g., total energy conservation. Note for the shallow water equations to the total energy acts as a mathematical entropy function.

source
Trixi.integrate_via_indicesMethod
integrate_via_indices(func, u_ode, semi::AbstractSemidiscretization, args...; normalize=true)

Call func(u, i..., element, equations, solver, args...) for all nodal indices i..., element and integrate the result using a quadrature associated with the semidiscretization semi.

If normalize is true, the result is divided by the total volume of the computational domain.

source
Trixi.inv_ln_meanMethod
inv_ln_mean(x, y)

Compute the inverse 1 / ln_mean(x, y) of the logarithmic mean ln_mean.

This function may be used to increase performance where the inverse of the logarithmic mean is needed, by replacing a (slow) division by a (fast) multiplication.

source
Trixi.jacobian_ad_forwardMethod
jacobian_ad_forward(semi::AbstractSemidiscretization;
                     t0=zero(real(semi)),
-                    u0_ode=compute_coefficients(t0, semi))

Uses the right-hand side operator of the semidiscretization semi and forward mode automatic differentiation to compute the Jacobian J of the semidiscretization semi at state u0_ode.

source
Trixi.jacobian_fdMethod
jacobian_fd(semi::AbstractSemidiscretization;
+                    u0_ode=compute_coefficients(t0, semi))

Uses the right-hand side operator of the semidiscretization semi and forward mode automatic differentiation to compute the Jacobian J of the semidiscretization semi at state u0_ode.

source
Trixi.jacobian_fdMethod
jacobian_fd(semi::AbstractSemidiscretization;
             t0=zero(real(semi)),
-            u0_ode=compute_coefficients(t0, semi))

Uses the right-hand side operator of the semidiscretization semi and simple second order finite difference to compute the Jacobian J of the semidiscretization semi at state u0_ode.

source
Trixi.linear_structureMethod
linear_structure(semi::AbstractSemidiscretization;
-                 t0=zero(real(semi)))

Wraps the right-hand side operator of the semidiscretization semi at time t0 as an affine-linear operator given by a linear operator A and a vector b.

source
Trixi.ln_meanMethod
ln_mean(x, y)

Compute the logarithmic mean

ln_mean(x, y) = (y - x) / (log(y) - log(x)) = (y - x) / log(y / x)

Problem: The formula above has a removable singularity at x == y. Thus, some care must be taken to implement it correctly without problems or loss of accuracy when x ≈ y. Here, we use the approach proposed by Ismail and Roe (2009). Set ξ = y / x. Then, we have

(y - x) / log(y / x) = (x + y) / log(ξ) * (ξ - 1) / (ξ + 1)

Set f = (ξ - 1) / (ξ + 1) = (y - x) / (x + y). Then, we use the expansion

log(ξ) = 2 * f * (1 + f^2 / 3 + f^4 / 5 + f^6 / 7) + O(ξ^9)

Inserting the first few terms of this expansion yields

(y - x) / log(ξ) ≈ (x + y) * f / (2 * f * (1 + f^2 / 3 + f^4 / 5 + f^6 / 7))
+            u0_ode=compute_coefficients(t0, semi))

Uses the right-hand side operator of the semidiscretization semi and simple second order finite difference to compute the Jacobian J of the semidiscretization semi at state u0_ode.

source
Trixi.linear_structureMethod
linear_structure(semi::AbstractSemidiscretization;
+                 t0=zero(real(semi)))

Wraps the right-hand side operator of the semidiscretization semi at time t0 as an affine-linear operator given by a linear operator A and a vector b.

source
Trixi.ln_meanMethod
ln_mean(x, y)

Compute the logarithmic mean

ln_mean(x, y) = (y - x) / (log(y) - log(x)) = (y - x) / log(y / x)

Problem: The formula above has a removable singularity at x == y. Thus, some care must be taken to implement it correctly without problems or loss of accuracy when x ≈ y. Here, we use the approach proposed by Ismail and Roe (2009). Set ξ = y / x. Then, we have

(y - x) / log(y / x) = (x + y) / log(ξ) * (ξ - 1) / (ξ + 1)

Set f = (ξ - 1) / (ξ + 1) = (y - x) / (x + y). Then, we use the expansion

log(ξ) = 2 * f * (1 + f^2 / 3 + f^4 / 5 + f^6 / 7) + O(ξ^9)

Inserting the first few terms of this expansion yields

(y - x) / log(ξ) ≈ (x + y) * f / (2 * f * (1 + f^2 / 3 + f^4 / 5 + f^6 / 7))
                  = (x + y) / (2 + 2/3 * f^2 + 2/5 * f^4 + 2/7 * f^6)

Since divisions are usually more expensive on modern hardware than multiplications (Agner Fog), we try to avoid computing two divisions. Thus, we use

f^2 = (y - x)^2 / (x + y)^2
     = (x * (x - 2 * y) + y * y) / (x * (x + 2 * y) + y * y)

Given ε = 1.0e-4, we use the following algorithm.

if f^2 < ε
   # use the expansion above
 else
   # use the direct formula (y - x) / log(y / x)
-end

References

source
Trixi.load_adaptive_time_integrator!Method
load_adaptive_time_integrator!(integrator, restart_file::AbstractString)

Load the context information for time integrators with error-based step size control saved in a restart_file.

source
Trixi.load_dtMethod
load_dt(restart_file::AbstractString)

Load the time step size (dt in OrdinaryDiffEq.jl) saved in a restart_file.

source
Trixi.load_meshMethod
load_mesh(restart_file::AbstractString; n_cells_max)

Load the mesh from the restart_file.

source
Trixi.load_timeMethod
load_time(restart_file::AbstractString)

Load the time saved in a restart_file.

source
Trixi.load_timestep!Method
load_timestep!(integrator, restart_file::AbstractString)

Load the time step number saved in a restart_file and assign it to both the time step number and and the number of accepted steps (iter and stats.naccept in OrdinaryDiffEq.jl, respectively) in integrator.

source
Trixi.load_timestepMethod
load_timestep(restart_file::AbstractString)

Load the time step number (iter in OrdinaryDiffEq.jl) saved in a restart_file.

source
Trixi.maxMethod
max(x, y, ...)

Return the maximum of the arguments. See also the maximum function to take the maximum element from a collection.

This version in Trixi.jl is semantically equivalent to Base.max but may be implemented differently. In particular, it may avoid potentially expensive checks necessary in the presence of NaNs (or signed zeros).

Examples

julia> max(2, 5, 1)
-5
source
Trixi.max_abs_speed_naiveFunction
max_abs_speed_naive(u_ll, u_rr, orientation::Integer,   equations)
-max_abs_speed_naive(u_ll, u_rr, normal_direction::AbstractVector, equations)

Simple and fast estimate of the maximal wave speed of the Riemann problem with left and right states u_ll, u_rr, based only on the local wave speeds associated to u_ll and u_rr.

For non-integer arguments normal_direction in one dimension, max_abs_speed_naive returns abs(normal_direction[1]) * max_abs_speed_naive(u_ll, u_rr, 1, equations).

source
Trixi.minMethod
min(x, y, ...)

Return the minimum of the arguments. See also the minimum function to take the minimum element from a collection.

This version in Trixi.jl is semantically equivalent to Base.min but may be implemented differently. In particular, it may avoid potentially expensive checks necessary in the presence of NaNs (or signed zeros).

Examples

julia> min(2, 5, 1)
-1
source
Trixi.min_max_speed_chen_noelleMethod
min_max_speed_chen_noelle(u_ll, u_rr, orientation::Integer,
-                          equations::ShallowWaterEquations1D)

The approximated speeds for the HLL type numerical flux used by Chen and Noelle for their hydrostatic reconstruction. As they state in the paper, these speeds are chosen for the numerical flux to ensure positivity and to satisfy an entropy inequality.

Further details on this hydrostatic reconstruction and its motivation can be found in

  • Guoxian Chen and Sebastian Noelle (2017) A new hydrostatic reconstruction scheme based on subcell reconstructions DOI:10.1137/15M1053074
source
Trixi.load_adaptive_time_integrator!Method
load_adaptive_time_integrator!(integrator, restart_file::AbstractString)

Load the context information for time integrators with error-based step size control saved in a restart_file.

source
Trixi.load_dtMethod
load_dt(restart_file::AbstractString)

Load the time step size (dt in OrdinaryDiffEq.jl) saved in a restart_file.

source
Trixi.load_meshMethod
load_mesh(restart_file::AbstractString; n_cells_max)

Load the mesh from the restart_file.

source
Trixi.load_timeMethod
load_time(restart_file::AbstractString)

Load the time saved in a restart_file.

source
Trixi.load_timestep!Method
load_timestep!(integrator, restart_file::AbstractString)

Load the time step number saved in a restart_file and assign it to both the time step number and and the number of accepted steps (iter and stats.naccept in OrdinaryDiffEq.jl, respectively) in integrator.

source
Trixi.load_timestepMethod
load_timestep(restart_file::AbstractString)

Load the time step number (iter in OrdinaryDiffEq.jl) saved in a restart_file.

source
Trixi.maxMethod
max(x, y, ...)

Return the maximum of the arguments. See also the maximum function to take the maximum element from a collection.

This version in Trixi.jl is semantically equivalent to Base.max but may be implemented differently. In particular, it may avoid potentially expensive checks necessary in the presence of NaNs (or signed zeros).

Examples

julia> max(2, 5, 1)
+5
source
Trixi.max_abs_speed_naiveFunction
max_abs_speed_naive(u_ll, u_rr, orientation::Integer,   equations)
+max_abs_speed_naive(u_ll, u_rr, normal_direction::AbstractVector, equations)

Simple and fast estimate of the maximal wave speed of the Riemann problem with left and right states u_ll, u_rr, based only on the local wave speeds associated to u_ll and u_rr.

For non-integer arguments normal_direction in one dimension, max_abs_speed_naive returns abs(normal_direction[1]) * max_abs_speed_naive(u_ll, u_rr, 1, equations).

source
Trixi.minMethod
min(x, y, ...)

Return the minimum of the arguments. See also the minimum function to take the minimum element from a collection.

This version in Trixi.jl is semantically equivalent to Base.min but may be implemented differently. In particular, it may avoid potentially expensive checks necessary in the presence of NaNs (or signed zeros).

Examples

julia> min(2, 5, 1)
+1
source
Trixi.min_max_speed_chen_noelleMethod
min_max_speed_chen_noelle(u_ll, u_rr, orientation::Integer,
+                          equations::ShallowWaterEquations1D)

The approximated speeds for the HLL type numerical flux used by Chen and Noelle for their hydrostatic reconstruction. As they state in the paper, these speeds are chosen for the numerical flux to ensure positivity and to satisfy an entropy inequality.

Further details on this hydrostatic reconstruction and its motivation can be found in

  • Guoxian Chen and Sebastian Noelle (2017) A new hydrostatic reconstruction scheme based on subcell reconstructions DOI:10.1137/15M1053074
source
Trixi.min_max_speed_chen_noelleMethod
min_max_speed_chen_noelle(u_ll, u_rr, orientation::Integer,
                           equations::ShallowWaterEquations2D)
 min_max_speed_chen_noelle(u_ll, u_rr, normal_direction::AbstractVector,
-                          equations::ShallowWaterEquations2D)

Special estimate of the minimal and maximal wave speed of the shallow water equations for the left and right states u_ll, u_rr. These approximate speeds are used for the HLL-type numerical flux flux_hll_chen_noelle. These wave speed estimates together with a particular hydrostatic reconstruction technique guarantee that the numerical flux is positive and satisfies an entropy inequality.

Further details on this hydrostatic reconstruction and its motivation can be found in the reference below. The definition of the wave speeds are given in Equation (2.20).

  • Guoxian Chen and Sebastian Noelle (2017) A new hydrostatic reconstruction scheme based on subcell reconstructions DOI:10.1137/15M1053074
source
Trixi.min_max_speed_davisFunction
min_max_speed_davis(u_ll, u_rr, orientation::Integer, equations)
-min_max_speed_davis(u_ll, u_rr, normal_direction::AbstractVector, equations)

Simple and fast estimates of the minimal and maximal wave speed of the Riemann problem with left and right states u_ll, u_rr, usually based only on the local wave speeds associated to u_ll and u_rr.

See also FluxHLL, min_max_speed_naive, min_max_speed_einfeldt.

source
Trixi.min_max_speed_einfeldtFunction
min_max_speed_einfeldt(u_ll, u_rr, orientation::Integer, equations)
-min_max_speed_einfeldt(u_ll, u_rr, normal_direction::AbstractVector, equations)

More advanced mininmal and maximal wave speed computation based on

originally developed for the compressible Euler equations. A compact representation can be found in this lecture notes, eq. (9.28).

See also FluxHLL, min_max_speed_naive, min_max_speed_davis.

source
Trixi.min_max_speed_einfeldtMethod
min_max_speed_einfeldt(u_ll, u_rr, normal_direction, equations::CompressibleEulerEquations2D)

Computes the HLLE (Harten-Lax-van Leer-Einfeldt) flux for the compressible Euler equations. Special estimates of the signal velocites and linearization of the Riemann problem developed by Einfeldt to ensure that the internal energy and density remain positive during the computation of the numerical flux.

source
Trixi.min_max_speed_einfeldtMethod
min_max_speed_einfeldt(u_ll, u_rr, normal_direction, equations::CompressibleEulerEquations3D)

Computes the HLLE (Harten-Lax-van Leer-Einfeldt) flux for the compressible Euler equations. Special estimates of the signal velocites and linearization of the Riemann problem developed by Einfeldt to ensure that the internal energy and density remain positive during the computation of the numerical flux.

source
Trixi.min_max_speed_einfeldtMethod
min_max_speed_einfeldt(u_ll, u_rr, orientation, equations::CompressibleEulerEquations1D)

Computes the HLLE (Harten-Lax-van Leer-Einfeldt) flux for the compressible Euler equations. Special estimates of the signal velocites and linearization of the Riemann problem developed by Einfeldt to ensure that the internal energy and density remain positive during the computation of the numerical flux.

Original publication:

Compactly summarized:

  • Siddhartha Mishra, Ulrik Skre Fjordholm and Rémi Abgrall Numerical methods for conservation laws and related equations. Link
source
Trixi.min_max_speed_einfeldtMethod
min_max_speed_einfeldt(u_ll, u_rr, orientation, equations::CompressibleEulerEquations2D)

Computes the HLLE (Harten-Lax-van Leer-Einfeldt) flux for the compressible Euler equations. Special estimates of the signal velocites and linearization of the Riemann problem developed by Einfeldt to ensure that the internal energy and density remain positive during the computation of the numerical flux.

source
Trixi.min_max_speed_einfeldtMethod
min_max_speed_einfeldt(u_ll, u_rr, orientation, equations::CompressibleEulerEquations3D)

Computes the HLLE (Harten-Lax-van Leer-Einfeldt) flux for the compressible Euler equations. Special estimates of the signal velocites and linearization of the Riemann problem developed by Einfeldt to ensure that the internal energy and density remain positive during the computation of the numerical flux.

source
Trixi.min_max_speed_naiveFunction
min_max_speed_naive(u_ll, u_rr, orientation::Integer, equations)
-min_max_speed_naive(u_ll, u_rr, normal_direction::AbstractVector, equations)

Simple and fast estimate(!) of the minimal and maximal wave speed of the Riemann problem with left and right states u_ll, u_rr, usually based only on the local wave speeds associated to u_ll and u_rr.

  • Amiram Harten, Peter D. Lax, Bram van Leer (1983) On Upstream Differencing and Godunov-Type Schemes for Hyperbolic Conservation Laws DOI: 10.1137/1025002

See also FluxHLL, min_max_speed_davis, min_max_speed_einfeldt.

source
Trixi.multiply_dimensionwiseMethod
multiply_dimensionwise(matrix::AbstractMatrix, data_in::AbstractArray{<:Any, NDIMS+1})

Multiply the array data_in by matrix in each coordinate direction, where data_in is assumed to have the first coordinate for the number of variables and the remaining coordinates are multiplied by matrix.

source
Trixi.n_nonconservative_termsFunction
n_nonconservative_terms(equations)

Number of nonconservative terms in the form local * symmetric for a particular equation. This function needs to be specialized only if equations with nonconservative terms are combined with certain solvers (e.g., subcell limiting).

source
Trixi.ndofsMethod
ndofs(semi::AbstractSemidiscretization)

Return the number of degrees of freedom associated with each scalar variable.

source
Trixi.negative_partMethod
negative_part(x)

Return x if x is negative, else zero. In other words, return (x - abs(x)) / 2 for real numbers x.

source
Trixi.ode_default_optionsMethod
ode_default_options()

Return the default options for OrdinaryDiffEq's solve. Pass ode_default_options()... to solve to only return the solution at the final time and enable MPI aware error-based step size control, whenever MPI is used. For example, use solve(ode, alg; ode_default_options()...).

source
Trixi.ode_normMethod
ode_norm(u, t)

Implementation of the weighted L2 norm of Hairer and Wanner used for error-based step size control in OrdinaryDiffEq.jl. This function is aware of MPI and uses global MPI communication when running in parallel.

You must pass this function as a keyword argument internalnorm=ode_norm to OrdinaryDiffEq.jl's solve when using error-based step size control with MPI parallel execution of Trixi.jl.

See the "Advanced Adaptive Stepsize Control" section of the documentation.

source
Trixi.ode_unstable_checkMethod
ode_unstable_check(dt, u, semi, t)

Implementation of the basic check for instability used in OrdinaryDiffEq.jl. Instead of checking something like any(isnan, u), this function just checks isnan(dt). This helps when using MPI parallelization, since no additional global communication is required and all ranks will return the same result.

You should pass this function as a keyword argument unstable_check=ode_unstable_check to OrdinaryDiffEq.jl's solve when using error-based step size control with MPI parallel execution of Trixi.jl.

See the "Miscellaneous" section of the documentation.

source
Trixi.partition!Method
partition!(mesh::ParallelTreeMesh, allow_coarsening=true)

Partition mesh using a static domain decomposition algorithm based on leaf cell count and tree structure. If allow_coarsening is true, the algorithm will keep leaf cells together on one rank when needed for local coarsening (i.e. when all children of a cell are leaves).

source
Trixi.positive_partMethod
positive_part(x)

Return x if x is positive, else zero. In other words, return (x + abs(x)) / 2 for real numbers x.

source
Trixi.pressureMethod
pressure(rho::Real, equations::LatticeBoltzmannEquations2D)
-pressure(u, equations::LatticeBoltzmannEquations2D)

Calculate the macroscopic pressure from the density rho or the particle distribution functions u.

source
Trixi.pressureMethod
pressure(rho::Real, equations::LatticeBoltzmannEquations3D)
-pressure(u, equations::LatticeBoltzmannEquations3D)

Calculate the macroscopic pressure from the density rho or the particle distribution functions u.

source
Trixi.prim2consFunction
prim2cons(u, equations)

Convert the primitive variables u to the conserved variables for a given set of equations. u is a vector type of the correct length nvariables(equations). Notice the function doesn't include any error checks for the purpose of efficiency, so please make sure your input is correct. The inverse conversion is performed by cons2prim.

source
Trixi.rotate_from_xFunction
rotate_from_x(u, normal, equations)

Apply the rotation that maps the x-axis onto normal to the convservative variables u. This is used by FluxRotated to calculate the numerical flux of rotationally invariant equations in arbitrary normal directions.

See also: rotate_to_x

source
Trixi.rotate_to_xFunction
rotate_to_x(u, normal, equations)

Apply the rotation that maps normal onto the x-axis to the convservative variables u. This is used by FluxRotated to calculate the numerical flux of rotationally invariant equations in arbitrary normal directions.

See also: rotate_from_x

source
Trixi.save_plotMethod
save_plot(plot_data, variable_names;
+                          equations::ShallowWaterEquations2D)

Special estimate of the minimal and maximal wave speed of the shallow water equations for the left and right states u_ll, u_rr. These approximate speeds are used for the HLL-type numerical flux flux_hll_chen_noelle. These wave speed estimates together with a particular hydrostatic reconstruction technique guarantee that the numerical flux is positive and satisfies an entropy inequality.

Further details on this hydrostatic reconstruction and its motivation can be found in the reference below. The definition of the wave speeds are given in Equation (2.20).

  • Guoxian Chen and Sebastian Noelle (2017) A new hydrostatic reconstruction scheme based on subcell reconstructions DOI:10.1137/15M1053074
source
Trixi.min_max_speed_davisFunction
min_max_speed_davis(u_ll, u_rr, orientation::Integer, equations)
+min_max_speed_davis(u_ll, u_rr, normal_direction::AbstractVector, equations)

Simple and fast estimates of the minimal and maximal wave speed of the Riemann problem with left and right states u_ll, u_rr, usually based only on the local wave speeds associated to u_ll and u_rr.

See also FluxHLL, min_max_speed_naive, min_max_speed_einfeldt.

source
Trixi.min_max_speed_einfeldtFunction
min_max_speed_einfeldt(u_ll, u_rr, orientation::Integer, equations)
+min_max_speed_einfeldt(u_ll, u_rr, normal_direction::AbstractVector, equations)

More advanced mininmal and maximal wave speed computation based on

originally developed for the compressible Euler equations. A compact representation can be found in this lecture notes, eq. (9.28).

See also FluxHLL, min_max_speed_naive, min_max_speed_davis.

source
Trixi.min_max_speed_einfeldtMethod
min_max_speed_einfeldt(u_ll, u_rr, normal_direction, equations::CompressibleEulerEquations2D)

Computes the HLLE (Harten-Lax-van Leer-Einfeldt) flux for the compressible Euler equations. Special estimates of the signal velocites and linearization of the Riemann problem developed by Einfeldt to ensure that the internal energy and density remain positive during the computation of the numerical flux.

source
Trixi.min_max_speed_einfeldtMethod
min_max_speed_einfeldt(u_ll, u_rr, normal_direction, equations::CompressibleEulerEquations3D)

Computes the HLLE (Harten-Lax-van Leer-Einfeldt) flux for the compressible Euler equations. Special estimates of the signal velocites and linearization of the Riemann problem developed by Einfeldt to ensure that the internal energy and density remain positive during the computation of the numerical flux.

source
Trixi.min_max_speed_einfeldtMethod
min_max_speed_einfeldt(u_ll, u_rr, orientation, equations::CompressibleEulerEquations1D)

Computes the HLLE (Harten-Lax-van Leer-Einfeldt) flux for the compressible Euler equations. Special estimates of the signal velocites and linearization of the Riemann problem developed by Einfeldt to ensure that the internal energy and density remain positive during the computation of the numerical flux.

Original publication:

Compactly summarized:

  • Siddhartha Mishra, Ulrik Skre Fjordholm and Rémi Abgrall Numerical methods for conservation laws and related equations. Link
source
Trixi.min_max_speed_einfeldtMethod
min_max_speed_einfeldt(u_ll, u_rr, orientation, equations::CompressibleEulerEquations2D)

Computes the HLLE (Harten-Lax-van Leer-Einfeldt) flux for the compressible Euler equations. Special estimates of the signal velocites and linearization of the Riemann problem developed by Einfeldt to ensure that the internal energy and density remain positive during the computation of the numerical flux.

source
Trixi.min_max_speed_einfeldtMethod
min_max_speed_einfeldt(u_ll, u_rr, orientation, equations::CompressibleEulerEquations3D)

Computes the HLLE (Harten-Lax-van Leer-Einfeldt) flux for the compressible Euler equations. Special estimates of the signal velocites and linearization of the Riemann problem developed by Einfeldt to ensure that the internal energy and density remain positive during the computation of the numerical flux.

source
Trixi.min_max_speed_naiveFunction
min_max_speed_naive(u_ll, u_rr, orientation::Integer, equations)
+min_max_speed_naive(u_ll, u_rr, normal_direction::AbstractVector, equations)

Simple and fast estimate(!) of the minimal and maximal wave speed of the Riemann problem with left and right states u_ll, u_rr, usually based only on the local wave speeds associated to u_ll and u_rr.

  • Amiram Harten, Peter D. Lax, Bram van Leer (1983) On Upstream Differencing and Godunov-Type Schemes for Hyperbolic Conservation Laws DOI: 10.1137/1025002

See also FluxHLL, min_max_speed_davis, min_max_speed_einfeldt.

source
Trixi.multiply_dimensionwiseMethod
multiply_dimensionwise(matrix::AbstractMatrix, data_in::AbstractArray{<:Any, NDIMS+1})

Multiply the array data_in by matrix in each coordinate direction, where data_in is assumed to have the first coordinate for the number of variables and the remaining coordinates are multiplied by matrix.

source
Trixi.n_nonconservative_termsFunction
n_nonconservative_terms(equations)

Number of nonconservative terms in the form local * symmetric for a particular equation. This function needs to be specialized only if equations with nonconservative terms are combined with certain solvers (e.g., subcell limiting).

source
Trixi.ndofsMethod
ndofs(semi::AbstractSemidiscretization)

Return the number of degrees of freedom associated with each scalar variable.

source
Trixi.negative_partMethod
negative_part(x)

Return x if x is negative, else zero. In other words, return (x - abs(x)) / 2 for real numbers x.

source
Trixi.ode_default_optionsMethod
ode_default_options()

Return the default options for OrdinaryDiffEq's solve. Pass ode_default_options()... to solve to only return the solution at the final time and enable MPI aware error-based step size control, whenever MPI is used. For example, use solve(ode, alg; ode_default_options()...).

source
Trixi.ode_normMethod
ode_norm(u, t)

Implementation of the weighted L2 norm of Hairer and Wanner used for error-based step size control in OrdinaryDiffEq.jl. This function is aware of MPI and uses global MPI communication when running in parallel.

You must pass this function as a keyword argument internalnorm=ode_norm to OrdinaryDiffEq.jl's solve when using error-based step size control with MPI parallel execution of Trixi.jl.

See the "Advanced Adaptive Stepsize Control" section of the documentation.

source
Trixi.ode_unstable_checkMethod
ode_unstable_check(dt, u, semi, t)

Implementation of the basic check for instability used in OrdinaryDiffEq.jl. Instead of checking something like any(isnan, u), this function just checks isnan(dt). This helps when using MPI parallelization, since no additional global communication is required and all ranks will return the same result.

You should pass this function as a keyword argument unstable_check=ode_unstable_check to OrdinaryDiffEq.jl's solve when using error-based step size control with MPI parallel execution of Trixi.jl.

See the "Miscellaneous" section of the documentation.

source
Trixi.partition!Method
partition!(mesh::ParallelTreeMesh, allow_coarsening=true)

Partition mesh using a static domain decomposition algorithm based on leaf cell count and tree structure. If allow_coarsening is true, the algorithm will keep leaf cells together on one rank when needed for local coarsening (i.e. when all children of a cell are leaves).

source
Trixi.positive_partMethod
positive_part(x)

Return x if x is positive, else zero. In other words, return (x + abs(x)) / 2 for real numbers x.

source
Trixi.pressureMethod
pressure(rho::Real, equations::LatticeBoltzmannEquations2D)
+pressure(u, equations::LatticeBoltzmannEquations2D)

Calculate the macroscopic pressure from the density rho or the particle distribution functions u.

source
Trixi.pressureMethod
pressure(rho::Real, equations::LatticeBoltzmannEquations3D)
+pressure(u, equations::LatticeBoltzmannEquations3D)

Calculate the macroscopic pressure from the density rho or the particle distribution functions u.

source
Trixi.prim2consFunction
prim2cons(u, equations)

Convert the primitive variables u to the conserved variables for a given set of equations. u is a vector type of the correct length nvariables(equations). Notice the function doesn't include any error checks for the purpose of efficiency, so please make sure your input is correct. The inverse conversion is performed by cons2prim.

source
Trixi.rotate_from_xFunction
rotate_from_x(u, normal, equations)

Apply the rotation that maps the x-axis onto normal to the convservative variables u. This is used by FluxRotated to calculate the numerical flux of rotationally invariant equations in arbitrary normal directions.

See also: rotate_to_x

source
Trixi.rotate_to_xFunction
rotate_to_x(u, normal, equations)

Apply the rotation that maps normal onto the x-axis to the convservative variables u. This is used by FluxRotated to calculate the numerical flux of rotationally invariant equations in arbitrary normal directions.

See also: rotate_from_x

source
Trixi.save_plotMethod
save_plot(plot_data, variable_names;
           show_mesh=true, plot_arguments=Dict{Symbol,Any}(),
-          time=nothing, timestep=nothing)

Visualize the plot data object provided in plot_data and save result as a PNG file in the out directory, plotting only the variables in variable_names and, optionally, the mesh (if show_mesh is true). Additionally, plot_arguments will be unpacked and passed as keyword arguments to the Plots.plot command.

The timestep is used in the filename. time is currently unused by this function.

Experimental implementation

This is an experimental feature and may change in future releases.

See also: VisualizationCallback, show_plot

source
Trixi.show_plotMethod
show_plot(plot_data, variable_names;
+          time=nothing, timestep=nothing)

Visualize the plot data object provided in plot_data and save result as a PNG file in the out directory, plotting only the variables in variable_names and, optionally, the mesh (if show_mesh is true). Additionally, plot_arguments will be unpacked and passed as keyword arguments to the Plots.plot command.

The timestep is used in the filename. time is currently unused by this function.

Experimental implementation

This is an experimental feature and may change in future releases.

See also: VisualizationCallback, show_plot

source
Trixi.show_plotMethod
show_plot(plot_data, variable_names;
           show_mesh=true, plot_arguments=Dict{Symbol,Any}(),
-          time=nothing, timestep=nothing)

Visualize the plot data object provided in plot_data and display result, plotting only the variables in variable_names and, optionally, the mesh (if show_mesh is true). Additionally, plot_arguments will be unpacked and passed as keyword arguments to the Plots.plot command.

This function is the default plot_creator argument for the VisualizationCallback. time and timestep are currently unused by this function.

Experimental implementation

This is an experimental feature and may change in future releases.

See also: VisualizationCallback, save_plot

source
Trixi.solveFunction
solve(ode, alg; dt, callbacks, kwargs...)

The following structures and methods provide the infrastructure for SSP Runge-Kutta methods of type SimpleAlgorithmSSP.

Experimental implementation

This is an experimental feature and may change in future releases.

source
Trixi.source_terms_convergence_testMethod
source_terms_convergence_test(u, x, t, equations::ShallowWaterEquations2D)

Source terms used for convergence tests in combination with initial_condition_convergence_test (and BoundaryConditionDirichlet(initial_condition_convergence_test) in non-periodic domains).

This manufactured solution source term is specifically designed for the bottom topography function b(x,y) = 2 + 0.5 * sin(sqrt(2)*pi*x) + 0.5 * sin(sqrt(2)*pi*y) as defined in initial_condition_convergence_test.

source
Trixi.source_terms_convergence_testMethod
source_terms_convergence_test(u, x, t, equations::ShallowWaterEquationsQuasi1D)

Source terms used for convergence tests in combination with initial_condition_convergence_test (and BoundaryConditionDirichlet(initial_condition_convergence_test) in non-periodic domains).

This manufactured solution source term is specifically designed for the bottom topography function b(x) = 0.2 - 0.05 * sin(sqrt(2) * pi *x[1]) and channel width 'a(x)= 1 + 0.1 * cos(sqrt(2) * pi * x[1])' as defined in initial_condition_convergence_test.

source
Trixi.source_terms_eoc_test_coupled_euler_gravityMethod
source_terms_eoc_test_coupled_euler_gravity(u, x, t, equations::CompressibleEulerEquations2D)

Setup used for convergence tests of the Euler equations with self-gravity used in

  • Michael Schlottke-Lakemper, Andrew R. Winters, Hendrik Ranocha, Gregor J. Gassner (2020) A purely hyperbolic discontinuous Galerkin approach for self-gravitating gas dynamics arXiv: 2008.10593

in combination with initial_condition_eoc_test_coupled_euler_gravity.

source
Trixi.source_terms_eoc_test_coupled_euler_gravityMethod
source_terms_eoc_test_coupled_euler_gravity(u, x, t, equations::CompressibleEulerEquations3D)

Setup used for convergence tests of the Euler equations with self-gravity used in

  • Michael Schlottke-Lakemper, Andrew R. Winters, Hendrik Ranocha, Gregor J. Gassner (2020) A purely hyperbolic discontinuous Galerkin approach for self-gravitating gas dynamics arXiv: 2008.10593

in combination with initial_condition_eoc_test_coupled_euler_gravity.

source
Trixi.source_terms_eoc_test_eulerMethod
source_terms_eoc_test_euler(u, x, t, equations::CompressibleEulerEquations3D)

Setup used for convergence tests of the Euler equations with self-gravity used in

  • Michael Schlottke-Lakemper, Andrew R. Winters, Hendrik Ranocha, Gregor J. Gassner (2020) A purely hyperbolic discontinuous Galerkin approach for self-gravitating gas dynamics arXiv: 2008.10593

in combination with initial_condition_eoc_test_coupled_euler_gravity.

Note

This method is to be used for testing pure Euler simulations with analytic self-gravity. If you intend to do coupled Euler-gravity simulations, you need to use source_terms_eoc_test_coupled_euler_gravity instead.

source
Trixi.source_terms_harmonicMethod
source_terms_harmonic(u, x, t, equations::HyperbolicDiffusionEquations1D)

Source term that only includes the forcing from the hyperbolic diffusion system.

source
Trixi.source_terms_harmonicMethod
source_terms_harmonic(u, x, t, equations::HyperbolicDiffusionEquations2D)

Source term that only includes the forcing from the hyperbolic diffusion system.

source
Trixi.source_terms_harmonicMethod
source_terms_harmonic(u, x, t, equations::HyperbolicDiffusionEquations3D)

Source term that only includes the forcing from the hyperbolic diffusion system.

source
Trixi.splitting_coirier_vanleerMethod
splitting_coirier_vanleer(u, orientation::Integer,
+          time=nothing, timestep=nothing)

Visualize the plot data object provided in plot_data and display result, plotting only the variables in variable_names and, optionally, the mesh (if show_mesh is true). Additionally, plot_arguments will be unpacked and passed as keyword arguments to the Plots.plot command.

This function is the default plot_creator argument for the VisualizationCallback. time and timestep are currently unused by this function.

Experimental implementation

This is an experimental feature and may change in future releases.

See also: VisualizationCallback, save_plot

source
Trixi.solveFunction
solve(ode, alg; dt, callbacks, kwargs...)

The following structures and methods provide the infrastructure for SSP Runge-Kutta methods of type SimpleAlgorithmSSP.

Experimental implementation

This is an experimental feature and may change in future releases.

source
Trixi.source_terms_convergence_testMethod
source_terms_convergence_test(u, x, t, equations::ShallowWaterEquations2D)

Source terms used for convergence tests in combination with initial_condition_convergence_test (and BoundaryConditionDirichlet(initial_condition_convergence_test) in non-periodic domains).

This manufactured solution source term is specifically designed for the bottom topography function b(x,y) = 2 + 0.5 * sin(sqrt(2)*pi*x) + 0.5 * sin(sqrt(2)*pi*y) as defined in initial_condition_convergence_test.

source
Trixi.source_terms_convergence_testMethod
source_terms_convergence_test(u, x, t, equations::ShallowWaterEquationsQuasi1D)

Source terms used for convergence tests in combination with initial_condition_convergence_test (and BoundaryConditionDirichlet(initial_condition_convergence_test) in non-periodic domains).

This manufactured solution source term is specifically designed for the bottom topography function b(x) = 0.2 - 0.05 * sin(sqrt(2) * pi *x[1]) and channel width 'a(x)= 1 + 0.1 * cos(sqrt(2) * pi * x[1])' as defined in initial_condition_convergence_test.

source
Trixi.source_terms_eoc_test_coupled_euler_gravityMethod
source_terms_eoc_test_coupled_euler_gravity(u, x, t, equations::CompressibleEulerEquations2D)

Setup used for convergence tests of the Euler equations with self-gravity used in

  • Michael Schlottke-Lakemper, Andrew R. Winters, Hendrik Ranocha, Gregor J. Gassner (2020) A purely hyperbolic discontinuous Galerkin approach for self-gravitating gas dynamics arXiv: 2008.10593

in combination with initial_condition_eoc_test_coupled_euler_gravity.

source
Trixi.source_terms_eoc_test_coupled_euler_gravityMethod
source_terms_eoc_test_coupled_euler_gravity(u, x, t, equations::CompressibleEulerEquations3D)

Setup used for convergence tests of the Euler equations with self-gravity used in

  • Michael Schlottke-Lakemper, Andrew R. Winters, Hendrik Ranocha, Gregor J. Gassner (2020) A purely hyperbolic discontinuous Galerkin approach for self-gravitating gas dynamics arXiv: 2008.10593

in combination with initial_condition_eoc_test_coupled_euler_gravity.

source
Trixi.source_terms_eoc_test_eulerMethod
source_terms_eoc_test_euler(u, x, t, equations::CompressibleEulerEquations3D)

Setup used for convergence tests of the Euler equations with self-gravity used in

  • Michael Schlottke-Lakemper, Andrew R. Winters, Hendrik Ranocha, Gregor J. Gassner (2020) A purely hyperbolic discontinuous Galerkin approach for self-gravitating gas dynamics arXiv: 2008.10593

in combination with initial_condition_eoc_test_coupled_euler_gravity.

Note

This method is to be used for testing pure Euler simulations with analytic self-gravity. If you intend to do coupled Euler-gravity simulations, you need to use source_terms_eoc_test_coupled_euler_gravity instead.

source
Trixi.source_terms_harmonicMethod
source_terms_harmonic(u, x, t, equations::HyperbolicDiffusionEquations1D)

Source term that only includes the forcing from the hyperbolic diffusion system.

source
Trixi.source_terms_harmonicMethod
source_terms_harmonic(u, x, t, equations::HyperbolicDiffusionEquations2D)

Source term that only includes the forcing from the hyperbolic diffusion system.

source
Trixi.source_terms_harmonicMethod
source_terms_harmonic(u, x, t, equations::HyperbolicDiffusionEquations3D)

Source term that only includes the forcing from the hyperbolic diffusion system.

source
Trixi.splitting_coirier_vanleerMethod
splitting_coirier_vanleer(u, orientation::Integer,
                           equations::CompressibleEulerEquations1D)
 splitting_coirier_vanleer(u, which::Union{Val{:minus}, Val{:plus}}
                           orientation::Integer,
-                          equations::CompressibleEulerEquations1D)

Splitting of the compressible Euler flux from Coirier and van Leer. The splitting has correction terms in the pressure splitting as well as the mass and energy flux components. The motivation for these corrections are to handle flows at the low Mach number limit.

Returns a tuple of the fluxes "minus" (associated with waves going into the negative axis direction) and "plus" (associated with waves going into the positive axis direction). If only one of the fluxes is required, use the function signature with argument which set to Val{:minus}() or Val{:plus}().

Experimental implementation (upwind SBP)

This is an experimental feature and may change in future releases.

References

  • William Coirier and Bram van Leer (1991) Numerical flux formulas for the Euler and Navier-Stokes equations. II - Progress in flux-vector splitting DOI: 10.2514/6.1991-1566
source
Trixi.splitting_lax_friedrichsMethod
splitting_lax_friedrichs(u, orientation::Integer,
+                          equations::CompressibleEulerEquations1D)

Splitting of the compressible Euler flux from Coirier and van Leer. The splitting has correction terms in the pressure splitting as well as the mass and energy flux components. The motivation for these corrections are to handle flows at the low Mach number limit.

Returns a tuple of the fluxes "minus" (associated with waves going into the negative axis direction) and "plus" (associated with waves going into the positive axis direction). If only one of the fluxes is required, use the function signature with argument which set to Val{:minus}() or Val{:plus}().

Experimental implementation (upwind SBP)

This is an experimental feature and may change in future releases.

References

  • William Coirier and Bram van Leer (1991) Numerical flux formulas for the Euler and Navier-Stokes equations. II - Progress in flux-vector splitting DOI: 10.2514/6.1991-1566
source
Trixi.splitting_lax_friedrichsMethod
splitting_lax_friedrichs(u, orientation::Integer,
                          equations::CompressibleEulerEquations2D)
 splitting_lax_friedrichs(u, which::Union{Val{:minus}, Val{:plus}}
                          orientation::Integer,
-                         equations::CompressibleEulerEquations2D)

Naive local Lax-Friedrichs style flux splitting of the form f⁺ = 0.5 (f + λ u) and f⁻ = 0.5 (f - λ u) similar to a flux splitting one would apply, e.g., to Burgers' equation.

Returns a tuple of the fluxes "minus" (associated with waves going into the negative axis direction) and "plus" (associated with waves going into the positive axis direction). If only one of the fluxes is required, use the function signature with argument which set to Val{:minus}() or Val{:plus}().

Experimental implementation (upwind SBP)

This is an experimental feature and may change in future releases.

source
Trixi.splitting_lax_friedrichsMethod
splitting_lax_friedrichs(u, orientation::Integer,
+                         equations::CompressibleEulerEquations2D)

Naive local Lax-Friedrichs style flux splitting of the form f⁺ = 0.5 (f + λ u) and f⁻ = 0.5 (f - λ u) similar to a flux splitting one would apply, e.g., to Burgers' equation.

Returns a tuple of the fluxes "minus" (associated with waves going into the negative axis direction) and "plus" (associated with waves going into the positive axis direction). If only one of the fluxes is required, use the function signature with argument which set to Val{:minus}() or Val{:plus}().

Experimental implementation (upwind SBP)

This is an experimental feature and may change in future releases.

source
Trixi.splitting_lax_friedrichsMethod
splitting_lax_friedrichs(u, orientation::Integer,
                          equations::InviscidBurgersEquation1D)
 splitting_lax_friedrichs(u, which::Union{Val{:minus}, Val{:plus}}
                          orientation::Integer,
-                         equations::InviscidBurgersEquation1D)

Naive local Lax-Friedrichs style flux splitting of the form f⁺ = 0.5 (f + λ u) and f⁻ = 0.5 (f - λ u) where λ = abs(u).

Returns a tuple of the fluxes "minus" (associated with waves going into the negative axis direction) and "plus" (associated with waves going into the positive axis direction). If only one of the fluxes is required, use the function signature with argument which set to Val{:minus}() or Val{:plus}().

Experimental implementation (upwind SBP)

This is an experimental feature and may change in future releases.

source
Trixi.splitting_lax_friedrichsMethod
splitting_lax_friedrichs(u, orientation::Integer,
+                         equations::InviscidBurgersEquation1D)

Naive local Lax-Friedrichs style flux splitting of the form f⁺ = 0.5 (f + λ u) and f⁻ = 0.5 (f - λ u) where λ = abs(u).

Returns a tuple of the fluxes "minus" (associated with waves going into the negative axis direction) and "plus" (associated with waves going into the positive axis direction). If only one of the fluxes is required, use the function signature with argument which set to Val{:minus}() or Val{:plus}().

Experimental implementation (upwind SBP)

This is an experimental feature and may change in future releases.

source
Trixi.splitting_lax_friedrichsMethod
splitting_lax_friedrichs(u, orientation::Integer,
                          equations::LinearScalarAdvectionEquation1D)
 splitting_lax_friedrichs(u, which::Union{Val{:minus}, Val{:plus}}
                          orientation::Integer,
-                         equations::LinearScalarAdvectionEquation1D)

Naive local Lax-Friedrichs style flux splitting of the form f⁺ = 0.5 (f + λ u) and f⁻ = 0.5 (f - λ u) where λ is the absolute value of the advection velocity.

Returns a tuple of the fluxes "minus" (associated with waves going into the negative axis direction) and "plus" (associated with waves going into the positive axis direction). If only one of the fluxes is required, use the function signature with argument which set to Val{:minus}() or Val{:plus}().

Experimental implementation (upwind SBP)

This is an experimental feature and may change in future releases.

source
Trixi.splitting_steger_warmingMethod
splitting_steger_warming(u, orientation::Integer,
+                         equations::LinearScalarAdvectionEquation1D)

Naive local Lax-Friedrichs style flux splitting of the form f⁺ = 0.5 (f + λ u) and f⁻ = 0.5 (f - λ u) where λ is the absolute value of the advection velocity.

Returns a tuple of the fluxes "minus" (associated with waves going into the negative axis direction) and "plus" (associated with waves going into the positive axis direction). If only one of the fluxes is required, use the function signature with argument which set to Val{:minus}() or Val{:plus}().

Experimental implementation (upwind SBP)

This is an experimental feature and may change in future releases.

source
Trixi.splitting_steger_warmingMethod
splitting_steger_warming(u, orientation::Integer,
                          equations::CompressibleEulerEquations1D)
 splitting_steger_warming(u, which::Union{Val{:minus}, Val{:plus}}
                          orientation::Integer,
-                         equations::CompressibleEulerEquations1D)

Splitting of the compressible Euler flux of Steger and Warming.

Returns a tuple of the fluxes "minus" (associated with waves going into the negative axis direction) and "plus" (associated with waves going into the positive axis direction). If only one of the fluxes is required, use the function signature with argument which set to Val{:minus}() or Val{:plus}().

Experimental implementation (upwind SBP)

This is an experimental feature and may change in future releases.

References

  • Joseph L. Steger and R. F. Warming (1979) Flux Vector Splitting of the Inviscid Gasdynamic Equations With Application to Finite Difference Methods NASA Technical Memorandum
source
Trixi.splitting_steger_warmingMethod
splitting_steger_warming(u, orientation::Integer,
+                         equations::CompressibleEulerEquations1D)

Splitting of the compressible Euler flux of Steger and Warming.

Returns a tuple of the fluxes "minus" (associated with waves going into the negative axis direction) and "plus" (associated with waves going into the positive axis direction). If only one of the fluxes is required, use the function signature with argument which set to Val{:minus}() or Val{:plus}().

Experimental implementation (upwind SBP)

This is an experimental feature and may change in future releases.

References

  • Joseph L. Steger and R. F. Warming (1979) Flux Vector Splitting of the Inviscid Gasdynamic Equations With Application to Finite Difference Methods NASA Technical Memorandum
source
Trixi.splitting_steger_warmingMethod
splitting_steger_warming(u, orientation::Integer,
                          equations::CompressibleEulerEquations2D)
 splitting_steger_warming(u, which::Union{Val{:minus}, Val{:plus}}
                          orientation::Integer,
-                         equations::CompressibleEulerEquations2D)

Splitting of the compressible Euler flux of Steger and Warming.

Returns a tuple of the fluxes "minus" (associated with waves going into the negative axis direction) and "plus" (associated with waves going into the positive axis direction). If only one of the fluxes is required, use the function signature with argument which set to Val{:minus}() or Val{:plus}().

Experimental implementation (upwind SBP)

This is an experimental feature and may change in future releases.

References

  • Joseph L. Steger and R. F. Warming (1979) Flux Vector Splitting of the Inviscid Gasdynamic Equations With Application to Finite Difference Methods NASA Technical Memorandum
source
Trixi.splitting_steger_warmingMethod
splitting_steger_warming(u, orientation::Integer,
+                         equations::CompressibleEulerEquations2D)

Splitting of the compressible Euler flux of Steger and Warming.

Returns a tuple of the fluxes "minus" (associated with waves going into the negative axis direction) and "plus" (associated with waves going into the positive axis direction). If only one of the fluxes is required, use the function signature with argument which set to Val{:minus}() or Val{:plus}().

Experimental implementation (upwind SBP)

This is an experimental feature and may change in future releases.

References

  • Joseph L. Steger and R. F. Warming (1979) Flux Vector Splitting of the Inviscid Gasdynamic Equations With Application to Finite Difference Methods NASA Technical Memorandum
source
Trixi.splitting_steger_warmingMethod
splitting_steger_warming(u, orientation::Integer,
                          equations::CompressibleEulerEquations3D)
 splitting_steger_warming(u, which::Union{Val{:minus}, Val{:plus}}
                          orientation::Integer,
-                         equations::CompressibleEulerEquations3D)

Splitting of the compressible Euler flux of Steger and Warming.

Returns a tuple of the fluxes "minus" (associated with waves going into the negative axis direction) and "plus" (associated with waves going into the positive axis direction). If only one of the fluxes is required, use the function signature with argument which set to Val{:minus}() or Val{:plus}().

Experimental implementation (upwind SBP)

This is an experimental feature and may change in future releases.

References

  • Joseph L. Steger and R. F. Warming (1979) Flux Vector Splitting of the Inviscid Gasdynamic Equations With Application to Finite Difference Methods NASA Technical Memorandum
source
Trixi.splitting_vanleer_haenelMethod
splitting_vanleer_haenel(u, orientation::Integer,
+                         equations::CompressibleEulerEquations3D)

Splitting of the compressible Euler flux of Steger and Warming.

Returns a tuple of the fluxes "minus" (associated with waves going into the negative axis direction) and "plus" (associated with waves going into the positive axis direction). If only one of the fluxes is required, use the function signature with argument which set to Val{:minus}() or Val{:plus}().

Experimental implementation (upwind SBP)

This is an experimental feature and may change in future releases.

References

  • Joseph L. Steger and R. F. Warming (1979) Flux Vector Splitting of the Inviscid Gasdynamic Equations With Application to Finite Difference Methods NASA Technical Memorandum
source
Trixi.splitting_vanleer_haenelMethod
splitting_vanleer_haenel(u, orientation::Integer,
                          equations::CompressibleEulerEquations1D)
 splitting_vanleer_haenel(u, which::Union{Val{:minus}, Val{:plus}}
                          orientation::Integer,
-                         equations::CompressibleEulerEquations1D)

Splitting of the compressible Euler flux from van Leer. This splitting further contains a reformulation due to Hänel et al. where the energy flux uses the enthalpy. The pressure splitting is independent from the splitting of the convective terms. As such there are many pressure splittings suggested across the literature. We implement the 'p4' variant suggested by Liou and Steffen as it proved the most robust in practice.

Returns a tuple of the fluxes "minus" (associated with waves going into the negative axis direction) and "plus" (associated with waves going into the positive axis direction). If only one of the fluxes is required, use the function signature with argument which set to Val{:minus}() or Val{:plus}().

Experimental implementation (upwind SBP)

This is an experimental feature and may change in future releases.

References

source
Trixi.splitting_vanleer_haenelMethod
splitting_vanleer_haenel(u, orientation::Integer,
+                         equations::CompressibleEulerEquations1D)

Splitting of the compressible Euler flux from van Leer. This splitting further contains a reformulation due to Hänel et al. where the energy flux uses the enthalpy. The pressure splitting is independent from the splitting of the convective terms. As such there are many pressure splittings suggested across the literature. We implement the 'p4' variant suggested by Liou and Steffen as it proved the most robust in practice.

Returns a tuple of the fluxes "minus" (associated with waves going into the negative axis direction) and "plus" (associated with waves going into the positive axis direction). If only one of the fluxes is required, use the function signature with argument which set to Val{:minus}() or Val{:plus}().

Experimental implementation (upwind SBP)

This is an experimental feature and may change in future releases.

References

source
Trixi.splitting_vanleer_haenelMethod
splitting_vanleer_haenel(u, orientation::Integer,
                          equations::CompressibleEulerEquations2D)
 splitting_vanleer_haenel(u, which::Union{Val{:minus}, Val{:plus}}
                          orientation::Integer,
-                         equations::CompressibleEulerEquations2D)

Splitting of the compressible Euler flux from van Leer. This splitting further contains a reformulation due to Hänel et al. where the energy flux uses the enthalpy. The pressure splitting is independent from the splitting of the convective terms. As such there are many pressure splittings suggested across the literature. We implement the 'p4' variant suggested by Liou and Steffen as it proved the most robust in practice.

Returns a tuple of the fluxes "minus" (associated with waves going into the negative axis direction) and "plus" (associated with waves going into the positive axis direction). If only one of the fluxes is required, use the function signature with argument which set to Val{:minus}() or Val{:plus}().

Experimental implementation (upwind SBP)

This is an experimental feature and may change in future releases.

References

source
Trixi.stolarsky_meanMethod
stolarsky_mean(x, y, gamma)

Compute an instance of a weighted Stolarsky mean of the form

stolarsky_mean(x, y, gamma) = (gamma - 1)/gamma * (y^gamma - x^gamma) / (y^(gamma-1) - x^(gamma-1))

where gamma > 1.

Problem: The formula above has a removable singularity at x == y. Thus, some care must be taken to implement it correctly without problems or loss of accuracy when x ≈ y. Here, we use the approach proposed by Winters et al. (2020). Set f = (y - x) / (y + x) and g = gamma (for compact notation). Then, we use the expansions

((1+f)^g - (1-f)^g) / g = 2*f + (g-1)(g-2)/3 * f^3 + (g-1)(g-2)(g-3)(g-4)/60 * f^5 + O(f^7)

and

((1+f)^(g-1) - (1-f)^(g-1)) / (g-1) = 2*f + (g-2)(g-3)/3 * f^3 + (g-2)(g-3)(g-4)(g-5)/60 * f^5 + O(f^7)

Inserting the first few terms of these expansions and performing polynomial long division we find that

stolarsky_mean(x, y, gamma) ≈ (y + x) / 2 * (1 + (g-2)/3 * f^2 - (g+1)(g-2)(g-3)/45 * f^4 + (g+1)(g-2)(g-3)(2g(g-2)-9)/945 * f^6)

Since divisions are usually more expensive on modern hardware than multiplications (Agner Fog), we try to avoid computing two divisions. Thus, we use

f^2 = (y - x)^2 / (x + y)^2
+                         equations::CompressibleEulerEquations2D)

Splitting of the compressible Euler flux from van Leer. This splitting further contains a reformulation due to Hänel et al. where the energy flux uses the enthalpy. The pressure splitting is independent from the splitting of the convective terms. As such there are many pressure splittings suggested across the literature. We implement the 'p4' variant suggested by Liou and Steffen as it proved the most robust in practice.

Returns a tuple of the fluxes "minus" (associated with waves going into the negative axis direction) and "plus" (associated with waves going into the positive axis direction). If only one of the fluxes is required, use the function signature with argument which set to Val{:minus}() or Val{:plus}().

Experimental implementation (upwind SBP)

This is an experimental feature and may change in future releases.

References

source
Trixi.stolarsky_meanMethod
stolarsky_mean(x, y, gamma)

Compute an instance of a weighted Stolarsky mean of the form

stolarsky_mean(x, y, gamma) = (gamma - 1)/gamma * (y^gamma - x^gamma) / (y^(gamma-1) - x^(gamma-1))

where gamma > 1.

Problem: The formula above has a removable singularity at x == y. Thus, some care must be taken to implement it correctly without problems or loss of accuracy when x ≈ y. Here, we use the approach proposed by Winters et al. (2020). Set f = (y - x) / (y + x) and g = gamma (for compact notation). Then, we use the expansions

((1+f)^g - (1-f)^g) / g = 2*f + (g-1)(g-2)/3 * f^3 + (g-1)(g-2)(g-3)(g-4)/60 * f^5 + O(f^7)

and

((1+f)^(g-1) - (1-f)^(g-1)) / (g-1) = 2*f + (g-2)(g-3)/3 * f^3 + (g-2)(g-3)(g-4)(g-5)/60 * f^5 + O(f^7)

Inserting the first few terms of these expansions and performing polynomial long division we find that

stolarsky_mean(x, y, gamma) ≈ (y + x) / 2 * (1 + (g-2)/3 * f^2 - (g+1)(g-2)(g-3)/45 * f^4 + (g+1)(g-2)(g-3)(2g(g-2)-9)/945 * f^6)

Since divisions are usually more expensive on modern hardware than multiplications (Agner Fog), we try to avoid computing two divisions. Thus, we use

f^2 = (y - x)^2 / (x + y)^2
     = (x * (x - 2 * y) + y * y) / (x * (x + 2 * y) + y * y)

Given ε = 1.0e-4, we use the following algorithm.

if f^2 < ε
   # use the expansion above
 else
   # use the direct formula (gamma - 1)/gamma * (y^gamma - x^gamma) / (y^(gamma-1) - x^(gamma-1))
-end

References

source
Trixi.totalgammaMethod
totalgamma(u, equations::CompressibleEulerMulticomponentEquations1D)

Function that calculates the total gamma out of all partial gammas using the partial density fractions as well as the partial specific heats at constant volume.

source
Trixi.totalgammaMethod
totalgamma(u, equations::CompressibleEulerMulticomponentEquations2D)

Function that calculates the total gamma out of all partial gammas using the partial density fractions as well as the partial specific heats at constant volume.

source
Trixi.trixi_includeMethod
trixi_include([mod::Module=Main,] elixir::AbstractString; kwargs...)

include the file elixir and evaluate its content in the global scope of module mod. You can override specific assignments in elixir by supplying keyword arguments. It's basic purpose is to make it easier to modify some parameters while running Trixi.jl from the REPL. Additionally, this is used in tests to reduce the computational burden for CI while still providing examples with sensible default values for users.

Before replacing assignments in elixir, the keyword argument maxiters is inserted into calls to solve and Trixi.solve with it's default value used in the SciML ecosystem for ODEs, see the "Miscellaneous" section of the documentation.

Examples

julia> redirect_stdout(devnull) do
+end

References

source
Trixi.totalgammaMethod
totalgamma(u, equations::CompressibleEulerMulticomponentEquations1D)

Function that calculates the total gamma out of all partial gammas using the partial density fractions as well as the partial specific heats at constant volume.

source
Trixi.totalgammaMethod
totalgamma(u, equations::CompressibleEulerMulticomponentEquations2D)

Function that calculates the total gamma out of all partial gammas using the partial density fractions as well as the partial specific heats at constant volume.

source
Trixi.trixi_includeMethod
trixi_include([mod::Module=Main,] elixir::AbstractString; kwargs...)

include the file elixir and evaluate its content in the global scope of module mod. You can override specific assignments in elixir by supplying keyword arguments. It's basic purpose is to make it easier to modify some parameters while running Trixi.jl from the REPL. Additionally, this is used in tests to reduce the computational burden for CI while still providing examples with sensible default values for users.

Before replacing assignments in elixir, the keyword argument maxiters is inserted into calls to solve and Trixi.solve with it's default value used in the SciML ecosystem for ODEs, see the "Miscellaneous" section of the documentation.

Examples

julia> redirect_stdout(devnull) do
          trixi_include(@__MODULE__, joinpath(examples_dir(), "tree_1d_dgsem", "elixir_advection_extended.jl"),
                        tspan=(0.0, 0.1))
          sol.t[end]
        end
 [ Info: You just called `trixi_include`. Julia may now compile the code, please be patient.
-0.1
source
Trixi.varnamesFunction
varnames(conversion_function, equations)

Return the list of variable names when applying conversion_function to the conserved variables associated to equations. This function is mainly used internally to determine output to screen and for IO, e.g., for the AnalysisCallback and the SaveSolutionCallback. Common choices of the conversion_function are cons2cons and cons2prim.

source
Trixi.velocityMethod
velocity(u, orientation, equations::LatticeBoltzmannEquations2D)

Calculate the macroscopic velocity for the given orientation (1 -> x, 2 -> y) from the particle distribution functions u.

source
Trixi.velocityMethod
velocity(u, orientation, equations::LatticeBoltzmannEquations3D)

Calculate the macroscopic velocity for the given orientation (1 -> x, 2 -> y, 3 -> z) from the particle distribution functions u.

source
Trixi.velocityMethod
velocity(u, equations::LatticeBoltzmannEquations2D)

Calculate the macroscopic velocity vector from the particle distribution functions u.

source
Trixi.velocityMethod
velocity(u, equations::LatticeBoltzmannEquations3D)

Calculate the macroscopic velocity vector from the particle distribution functions u.

source
Trixi.@autoinfiltrateMacro
@autoinfiltrate
-@autoinfiltrate condition::Bool

Invoke the @infiltrate macro of the package Infiltrator.jl to create a breakpoint for ad-hoc interactive debugging in the REPL. If the optional argument condition is given, the breakpoint is only enabled if condition evaluates to true.

As opposed to using Infiltrator.@infiltrate directly, this macro does not require Infiltrator.jl to be added as a dependency to Trixi.jl. As a bonus, the macro will also attempt to load the Infiltrator module if it has not yet been loaded manually.

Note: For this macro to work, the Infiltrator.jl package needs to be installed in your current Julia environment stack.

See also: Infiltrator.jl

Internal use only

Please note that this macro is intended for internal use only. It is not part of the public API of Trixi.jl, and it thus can altered (or be removed) at any time without it being considered a breaking change.

source
Trixi.@threadedMacro
@threaded for ... end

Semantically the same as Threads.@threads when iterating over a AbstractUnitRange but without guarantee that the underlying implementation uses Threads.@threads or works for more general for loops. In particular, there may be an additional check whether only one thread is used to reduce the overhead of serial execution or the underlying threading capabilities might be provided by other packages such as Polyester.jl.

Warn

This macro does not necessarily work for general for loops. For example, it does not necessarily support general iterables such as eachline(filename).

Some discussion can be found at https://discourse.julialang.org/t/overhead-of-threads-threads/53964 and https://discourse.julialang.org/t/threads-threads-with-one-thread-how-to-remove-the-overhead/58435.

source
+0.1source
Trixi.varnamesFunction
varnames(conversion_function, equations)

Return the list of variable names when applying conversion_function to the conserved variables associated to equations. This function is mainly used internally to determine output to screen and for IO, e.g., for the AnalysisCallback and the SaveSolutionCallback. Common choices of the conversion_function are cons2cons and cons2prim.

source
Trixi.velocityMethod
velocity(u, orientation, equations::LatticeBoltzmannEquations2D)

Calculate the macroscopic velocity for the given orientation (1 -> x, 2 -> y) from the particle distribution functions u.

source
Trixi.velocityMethod
velocity(u, orientation, equations::LatticeBoltzmannEquations3D)

Calculate the macroscopic velocity for the given orientation (1 -> x, 2 -> y, 3 -> z) from the particle distribution functions u.

source
Trixi.velocityMethod
velocity(u, equations::LatticeBoltzmannEquations2D)

Calculate the macroscopic velocity vector from the particle distribution functions u.

source
Trixi.velocityMethod
velocity(u, equations::LatticeBoltzmannEquations3D)

Calculate the macroscopic velocity vector from the particle distribution functions u.

source
Trixi.@autoinfiltrateMacro
@autoinfiltrate
+@autoinfiltrate condition::Bool

Invoke the @infiltrate macro of the package Infiltrator.jl to create a breakpoint for ad-hoc interactive debugging in the REPL. If the optional argument condition is given, the breakpoint is only enabled if condition evaluates to true.

As opposed to using Infiltrator.@infiltrate directly, this macro does not require Infiltrator.jl to be added as a dependency to Trixi.jl. As a bonus, the macro will also attempt to load the Infiltrator module if it has not yet been loaded manually.

Note: For this macro to work, the Infiltrator.jl package needs to be installed in your current Julia environment stack.

See also: Infiltrator.jl

Internal use only

Please note that this macro is intended for internal use only. It is not part of the public API of Trixi.jl, and it thus can altered (or be removed) at any time without it being considered a breaking change.

source
Trixi.@threadedMacro
@threaded for ... end

Semantically the same as Threads.@threads when iterating over a AbstractUnitRange but without guarantee that the underlying implementation uses Threads.@threads or works for more general for loops. In particular, there may be an additional check whether only one thread is used to reduce the overhead of serial execution or the underlying threading capabilities might be provided by other packages such as Polyester.jl.

Warn

This macro does not necessarily work for general for loops. For example, it does not necessarily support general iterables such as eachline(filename).

Some discussion can be found at https://discourse.julialang.org/t/overhead-of-threads-threads/53964 and https://discourse.julialang.org/t/threads-threads-with-one-thread-how-to-remove-the-overhead/58435.

source
diff --git a/previews/PR1681/reference-trixi2vtk/index.html b/previews/PR1681/reference-trixi2vtk/index.html index 446321258ee..af718a6fff9 100644 --- a/previews/PR1681/reference-trixi2vtk/index.html +++ b/previews/PR1681/reference-trixi2vtk/index.html @@ -3,4 +3,4 @@ format=:vtu, verbose=false, hide_progress=false, pvd=nothing, output_directory=".", nvisnodes=nothing, save_celldata=true, reinterpolate=true, data_is_uniform=false)

Convert Trixi-generated output files to VTK files (VTU or VTI).

Arguments

Examples

julia> trixi2vtk("out/solution_000*.h5")
-[...]
source +[...]source diff --git a/previews/PR1681/restart/index.html b/previews/PR1681/restart/index.html index 391007426c8..5a3d98b0835 100644 --- a/previews/PR1681/restart/index.html +++ b/previews/PR1681/restart/index.html @@ -3,4 +3,4 @@ save_final_restart=true)

Make this part of your CallbackSet.

An example is examples/examples/structured_2d_dgsem/elixir_advection_extended.jl.

Perform the simulation restart

Since all of the information about the simulation can be obtained from the last snapshot, the restart can be done with relatively few lines in an extra elixir file. However, some might prefer to keep everything in one elixir and conditionals like if restart with a boolean variable restart that is user defined.

First we need to define from which file we want to restart, e.g.

restart_file = "restart_000021.h5"
 restart_filename = joinpath("out", restart_file)

Then we load the mesh file:

mesh = load_mesh(restart_filename)

This is then needed for the semidiscretization:

semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver)

We then define a new time span for the simulation that takes as starting time the one form the snapshot:

tspan = (load_time(restart_filename), 2.0)

We now also take the last dt, so that our solver does not need to first find one to fulfill the CFL condition:

dt = load_dt(restart_filename)

The ODE that we will pass to the solver is now:

ode = semidiscretize(semi, tspan, restart_filename)

You should now define a SaveSolutionCallback similar to the original simulation, but with save_initial_solution=false, otherwise our initial snapshot will be overwritten. If you are using one file for the original simulation and the restart you can reuse your SaveSolutionCallback, but need to set

save_solution.condition.save_initial_solution = false

Before we compute the solution using OrdinaryDiffEq.jl we need to set the integrator and its time step number, e.g.:

integrator = init(ode, CarpenterKennedy2N54(williamson_condition=false),
                   dt=dt, save_everystep=false, callback=callbacks);
-load_timestep!(integrator, restart_filename)

Now we can compute the solution:

sol = solve!(integrator)

An example is in examples/structured_2d_dgsem/elixir_advection_restart.jl.

+load_timestep!(integrator, restart_filename)

Now we can compute the solution:

sol = solve!(integrator)

An example is in examples/structured_2d_dgsem/elixir_advection_restart.jl.

diff --git a/previews/PR1681/styleguide/index.html b/previews/PR1681/styleguide/index.html index 4d801fd22c6..e6e676fcc14 100644 --- a/previews/PR1681/styleguide/index.html +++ b/previews/PR1681/styleguide/index.html @@ -1,2 +1,2 @@ -Style guide · Trixi.jl

Style guide

Coding style is an inherently personal - and thus hotly contested - issue. Since code is usually "written once, read often", it helps regular developers, new users, and reviewers if code is formatted consistently. We therefore believe in the merit of using a common coding style throughout Trixi.jl, even at the expense that not everyone can be happy with every detailed style decision. If you came here because you are furious about our code formatting rules, here is a happy little whale for you to calm you down: 🐳

Conventions

The following lists a few coding conventions for Trixi.jl. Note that in addition to these conventions, we apply and enforce automated source code formatting (see below for more details):

  • Modules, types, structs with CamelCase.
  • Functions, variables with lowercase snake_case.
  • Indentation with 4 spaces (never tabs!)
  • Maximum line length (strictly): 92.
  • Functions that mutate their input are named with a trailing !.
  • Functions order their parameters similar to Julia Base.
    • The main modified argument comes first. For example, if the right-hand side du is modified, it should come first. If only the cache is modified, e.g., in prolong2interfaces! and its siblings, put the cache first.
    • Otherwise, use the order mesh, equations, solver, cache.
    • If something needs to be specified in more detail for dispatch, put the additional argument before the general one that is specified in more detail. For example, we use have_nonconservative_terms(equations), equations and dg.mortar, dg.
  • Prefer for i in ... to for i = ... for better semantic clarity and greater flexibility.
  • Executable code should only use ASCII characters.
  • Docstrings and comments can and should use Unicode characters where it helps understanding.
  • Multiline expressions should be explicitly grouped by parentheses and not rely on Julia's implicit line continuation syntax.
  • When naming multiple functions of a single or similar category, prefer to put the general classification first and the specialization second. Example: Use flux_central instead of central_flux. This helps when searching for available functions on the REPL (e.g., when trying to find all flux functions).

Automated source code formatting

We use JuliaFormatter.jl to format the source code of Trixi.jl, which will also enforce some of the Conventions listed above (e.g., line length or indentation with 4 spaces are automatically handled, while capitalization of names is not). Our format is mostly based on the SciML-style formatting rules. For more details you can have a look at the current .JuliaFormatter.toml file that holds the configuration options we use for JuliaFormatter.jl.

Note that we expect all contributions to Trixi.jl to be formatted with JuliaFormatter.jl before being merged to the main branch. We ensure this by running a automated check on all PRs that verify that running JuliaFormatter.jl again will not change the source code.

To format your contributions before created a PR (or, at least, before requesting a review of your PR), you need to install JuliaFormatter.jl first by running

julia -e 'using Pkg; Pkg.add("JuliaFormatter")'

You can then recursively format the core Julia files in the Trixi.jl repo by executing

julia -e 'using JuliaFormatter; format(["benchmark", "examples", "ext", "src", "test", "utils"])'

from inside the Trixi.jl repository. For convenience, there is also a script you can directly run from your terminal shell, which will automatically install JuliaFormatter in a temporary environment and then run it:

utils/trixi-format.jl

You can get more information about using the convenience script by running it with the --help/-h flag.

Checking formatting before committing

It can be convenient to check the formatting of source code automatically before each commit. We use git-hooks for it and provide a pre-commit script in the utils folder. The script uses JuliaFormatter.jl just like formatting script that runs over the whole Trixi.jl directory. You can copy the pre-commit-script into .git/hooks/pre-commit and it will check your formatting before each commit. If errors are found the commit is aborted and you can add the corrections via

git add -p
+Style guide · Trixi.jl

Style guide

Coding style is an inherently personal - and thus hotly contested - issue. Since code is usually "written once, read often", it helps regular developers, new users, and reviewers if code is formatted consistently. We therefore believe in the merit of using a common coding style throughout Trixi.jl, even at the expense that not everyone can be happy with every detailed style decision. If you came here because you are furious about our code formatting rules, here is a happy little whale for you to calm you down: 🐳

Conventions

The following lists a few coding conventions for Trixi.jl. Note that in addition to these conventions, we apply and enforce automated source code formatting (see below for more details):

  • Modules, types, structs with CamelCase.
  • Functions, variables with lowercase snake_case.
  • Indentation with 4 spaces (never tabs!)
  • Maximum line length (strictly): 92.
  • Functions that mutate their input are named with a trailing !.
  • Functions order their parameters similar to Julia Base.
    • The main modified argument comes first. For example, if the right-hand side du is modified, it should come first. If only the cache is modified, e.g., in prolong2interfaces! and its siblings, put the cache first.
    • Otherwise, use the order mesh, equations, solver, cache.
    • If something needs to be specified in more detail for dispatch, put the additional argument before the general one that is specified in more detail. For example, we use have_nonconservative_terms(equations), equations and dg.mortar, dg.
  • Prefer for i in ... to for i = ... for better semantic clarity and greater flexibility.
  • Executable code should only use ASCII characters.
  • Docstrings and comments can and should use Unicode characters where it helps understanding.
  • Multiline expressions should be explicitly grouped by parentheses and not rely on Julia's implicit line continuation syntax.
  • When naming multiple functions of a single or similar category, prefer to put the general classification first and the specialization second. Example: Use flux_central instead of central_flux. This helps when searching for available functions on the REPL (e.g., when trying to find all flux functions).

Automated source code formatting

We use JuliaFormatter.jl to format the source code of Trixi.jl, which will also enforce some of the Conventions listed above (e.g., line length or indentation with 4 spaces are automatically handled, while capitalization of names is not). Our format is mostly based on the SciML-style formatting rules. For more details you can have a look at the current .JuliaFormatter.toml file that holds the configuration options we use for JuliaFormatter.jl.

Note that we expect all contributions to Trixi.jl to be formatted with JuliaFormatter.jl before being merged to the main branch. We ensure this by running a automated check on all PRs that verify that running JuliaFormatter.jl again will not change the source code.

To format your contributions before created a PR (or, at least, before requesting a review of your PR), you need to install JuliaFormatter.jl first by running

julia -e 'using Pkg; Pkg.add("JuliaFormatter")'

You can then recursively format the core Julia files in the Trixi.jl repo by executing

julia -e 'using JuliaFormatter; format(["benchmark", "examples", "ext", "src", "test", "utils"])'

from inside the Trixi.jl repository. For convenience, there is also a script you can directly run from your terminal shell, which will automatically install JuliaFormatter in a temporary environment and then run it:

utils/trixi-format.jl

You can get more information about using the convenience script by running it with the --help/-h flag.

Checking formatting before committing

It can be convenient to check the formatting of source code automatically before each commit. We use git-hooks for it and provide a pre-commit script in the utils folder. The script uses JuliaFormatter.jl just like formatting script that runs over the whole Trixi.jl directory. You can copy the pre-commit-script into .git/hooks/pre-commit and it will check your formatting before each commit. If errors are found the commit is aborted and you can add the corrections via

git add -p
diff --git a/previews/PR1681/testing/index.html b/previews/PR1681/testing/index.html index 763016eed70..8a2c71a9015 100644 --- a/previews/PR1681/testing/index.html +++ b/previews/PR1681/testing/index.html @@ -3,4 +3,4 @@ include(joinpath("test", "test_p4est_2d.jl")) julia> # Run all 1D tests for the Euler equations on the TreeMesh - include(joinpath("test", "test_tree_1d_euler.jl"))

For the automated tests with GitHub Actions, we run multiple jobs in parallel to reduce the waiting time until all tests are finished. You can see the different components that are run as jobs by looking at the TRIXI_TEST variable in test/runtests.jl.

Adding new tests

We use Julia's built-in unit testing capabilities to configure tests. In general, newly added code must be covered by at least one test, and all new elixirs added to the examples/ directory must be used at least once during testing. New tests should be added to the corresponding test/test_xxx.jl file, e.g., a test involving the 3D linear advection equation on the TreeMesh would go into test/test_tree_3d_advection.jl. Please study one of the existing tests and stay consistent to the current style when creating new tests.

Since we want to test as much as possible, we have a lot of tests and frequently create new ones. Naturally, this increases the time to wait for all tests to pass with each novel feature added to Trixi.jl. Therefore, new tests should be as short as reasonably possible, i.e., without being too insensitive to pick up changes or errors in the code.

When you add new tests, please check whether all CI jobs still take approximately the same time. If the job where you added new tests takes much longer than everything else, please consider moving some tests from one job to another (or report this incident and ask the main developers for help).

Test duration

As a general rule, tests should last no more than 10 seconds when run with a single thread and after compilation (i.e., excluding the first run).

Test coverage

In addition to ensuring that the code produces the expected results, the automated tests also record the code coverage. The resulting coverage reports, i.e., which lines of code were executed by at least one test and are thus considered "covered" by testing, are automatically uploaded to Coveralls for easy analysis. Typically, you see a number of Coveralls results at the bottom of each pull request: One for each parallel job (see Testing setup), which can usually be ignored since they only cover parts of the code by definition, and a cumulative coverage result named coverage/coveralls. The "Details" link takes you to a detailed report on which lines of code are covered by tests, which ones are missed, and especially which new lines the pull requests adds to Trixi.jl's code base that are not yet covered by testing.

Coverage requirements

In general, we require pull requests to not decrease the overall test coverage percentage in main, with a hard lower bound of 97%.

+ include(joinpath("test", "test_tree_1d_euler.jl"))

For the automated tests with GitHub Actions, we run multiple jobs in parallel to reduce the waiting time until all tests are finished. You can see the different components that are run as jobs by looking at the TRIXI_TEST variable in test/runtests.jl.

Adding new tests

We use Julia's built-in unit testing capabilities to configure tests. In general, newly added code must be covered by at least one test, and all new elixirs added to the examples/ directory must be used at least once during testing. New tests should be added to the corresponding test/test_xxx.jl file, e.g., a test involving the 3D linear advection equation on the TreeMesh would go into test/test_tree_3d_advection.jl. Please study one of the existing tests and stay consistent to the current style when creating new tests.

Since we want to test as much as possible, we have a lot of tests and frequently create new ones. Naturally, this increases the time to wait for all tests to pass with each novel feature added to Trixi.jl. Therefore, new tests should be as short as reasonably possible, i.e., without being too insensitive to pick up changes or errors in the code.

When you add new tests, please check whether all CI jobs still take approximately the same time. If the job where you added new tests takes much longer than everything else, please consider moving some tests from one job to another (or report this incident and ask the main developers for help).

Test duration

As a general rule, tests should last no more than 10 seconds when run with a single thread and after compilation (i.e., excluding the first run).

Test coverage

In addition to ensuring that the code produces the expected results, the automated tests also record the code coverage. The resulting coverage reports, i.e., which lines of code were executed by at least one test and are thus considered "covered" by testing, are automatically uploaded to Coveralls for easy analysis. Typically, you see a number of Coveralls results at the bottom of each pull request: One for each parallel job (see Testing setup), which can usually be ignored since they only cover parts of the code by definition, and a cumulative coverage result named coverage/coveralls. The "Details" link takes you to a detailed report on which lines of code are covered by tests, which ones are missed, and especially which new lines the pull requests adds to Trixi.jl's code base that are not yet covered by testing.

Coverage requirements

In general, we require pull requests to not decrease the overall test coverage percentage in main, with a hard lower bound of 97%.

diff --git a/previews/PR1681/time_integration/index.html b/previews/PR1681/time_integration/index.html index b8d56627afb..a6e85e9e798 100644 --- a/previews/PR1681/time_integration/index.html +++ b/previews/PR1681/time_integration/index.html @@ -1,2 +1,2 @@ -Time integration · Trixi.jl

Time integration methods

Trixi.jl is compatible with the SciML ecosystem for ordinary differential equations. In particular, explicit Runge-Kutta methods from OrdinaryDiffEq.jl are tested extensively. Interesting classes of time integration schemes are

Some common options for solve from OrdinaryDiffEq.jl are the following. Further documentation can be found in the SciML docs.

  • If you use a fixed time step method like CarpenterKennedy2N54, you need to pass a time step as dt=.... If you use a StepsizeCallback, the value passed as dt=... is irrelevant since it will be overwritten by the StepsizeCallback. If you want to use an adaptive time step method such as SSPRK43 or RDPK3SpFSAL49 and still want to use CFL-based step size control via the StepsizeCallback, you need to pass the keyword argument adaptive=false to solve.
  • You should usually set save_everystep=false. Otherwise, OrdinaryDiffEq.jl will (try to) save the numerical solution after every time step in RAM (until you run out of memory or start to swap).
  • You can set the maximal number of time steps via maxiters=....
  • SSP methods and many low-storage methods from OrdinaryDiffEq.jl support stage_limiter!s and step_limiter!s, e.g., PositivityPreservingLimiterZhangShu from Trixi.jl.
  • If you start Julia with multiple threads and want to use them also in the time integration method from OrdinaryDiffEq.jl, you need to pass the keyword argument thread=OrdinaryDiffEq.True() to the algorithm, e.g., RDPK3SpFSAL49(thread=OrdinaryDiffEq.True()) or CarpenterKennedy2N54(thread=OrdinaryDiffEq.True(), williamson_condition=false). For more information on using thread-based parallelism in Trixi.jl, please refer to Shared-memory parallelization with threads.
  • If you use error-based step size control (see also the section on error-based adaptive step sizes together with MPI, you need to pass internalnorm=ode_norm and you should pass unstable_check=ode_unstable_check to OrdinaryDiffEq's solve, which are both included in ode_default_options.
Number of `rhs!` calls

If you use explicit Runge-Kutta methods from OrdinaryDiffEq.jl, the total number of rhs! calls can be (slightly) bigger than the number of steps times the number of stages, e.g. to allow for interpolation (dense output), root-finding for continuous callbacks, and error-based time step control. In general, you often should not need to worry about this if you use Trixi.jl.

+Time integration · Trixi.jl

Time integration methods

Trixi.jl is compatible with the SciML ecosystem for ordinary differential equations. In particular, explicit Runge-Kutta methods from OrdinaryDiffEq.jl are tested extensively. Interesting classes of time integration schemes are

Some common options for solve from OrdinaryDiffEq.jl are the following. Further documentation can be found in the SciML docs.

  • If you use a fixed time step method like CarpenterKennedy2N54, you need to pass a time step as dt=.... If you use a StepsizeCallback, the value passed as dt=... is irrelevant since it will be overwritten by the StepsizeCallback. If you want to use an adaptive time step method such as SSPRK43 or RDPK3SpFSAL49 and still want to use CFL-based step size control via the StepsizeCallback, you need to pass the keyword argument adaptive=false to solve.
  • You should usually set save_everystep=false. Otherwise, OrdinaryDiffEq.jl will (try to) save the numerical solution after every time step in RAM (until you run out of memory or start to swap).
  • You can set the maximal number of time steps via maxiters=....
  • SSP methods and many low-storage methods from OrdinaryDiffEq.jl support stage_limiter!s and step_limiter!s, e.g., PositivityPreservingLimiterZhangShu from Trixi.jl.
  • If you start Julia with multiple threads and want to use them also in the time integration method from OrdinaryDiffEq.jl, you need to pass the keyword argument thread=OrdinaryDiffEq.True() to the algorithm, e.g., RDPK3SpFSAL49(thread=OrdinaryDiffEq.True()) or CarpenterKennedy2N54(thread=OrdinaryDiffEq.True(), williamson_condition=false). For more information on using thread-based parallelism in Trixi.jl, please refer to Shared-memory parallelization with threads.
  • If you use error-based step size control (see also the section on error-based adaptive step sizes together with MPI, you need to pass internalnorm=ode_norm and you should pass unstable_check=ode_unstable_check to OrdinaryDiffEq's solve, which are both included in ode_default_options.
Number of `rhs!` calls

If you use explicit Runge-Kutta methods from OrdinaryDiffEq.jl, the total number of rhs! calls can be (slightly) bigger than the number of steps times the number of stages, e.g. to allow for interpolation (dense output), root-finding for continuous callbacks, and error-based time step control. In general, you often should not need to worry about this if you use Trixi.jl.

diff --git a/previews/PR1681/troubleshooting/index.html b/previews/PR1681/troubleshooting/index.html index 61a99fed78b..388f5b48db8 100644 --- a/previews/PR1681/troubleshooting/index.html +++ b/previews/PR1681/troubleshooting/index.html @@ -44,4 +44,4 @@ set_preferences!(uuid, "PrecompileNoSpecialize" => false) set_preferences!(uuid, "PrecompileNonStiff" => true) set_preferences!(uuid, "PrecompileStiff" => false) -end

This disables precompilation of all implicit methods. This should usually not affect the runtime latency with Trixi.jl since most setups use explicit time integration methods.

+end

This disables precompilation of all implicit methods. This should usually not affect the runtime latency with Trixi.jl since most setups use explicit time integration methods.

diff --git a/previews/PR1681/tutorials/DGMulti_1/0ef25871.svg b/previews/PR1681/tutorials/DGMulti_1/0ef25871.svg deleted file mode 100644 index d0233df5cc7..00000000000 --- a/previews/PR1681/tutorials/DGMulti_1/0ef25871.svg +++ /dev/null @@ -1,5560 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/previews/PR1681/tutorials/DGMulti_1/6435848f.svg b/previews/PR1681/tutorials/DGMulti_1/9b237cd1.svg similarity index 89% rename from previews/PR1681/tutorials/DGMulti_1/6435848f.svg rename to previews/PR1681/tutorials/DGMulti_1/9b237cd1.svg index 6d5da87d956..033df0ff743 100644 --- a/previews/PR1681/tutorials/DGMulti_1/6435848f.svg +++ b/previews/PR1681/tutorials/DGMulti_1/9b237cd1.svg @@ -1,45 +1,45 @@ - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + diff --git a/previews/PR1681/tutorials/DGMulti_1/b945cc27.svg b/previews/PR1681/tutorials/DGMulti_1/b945cc27.svg new file mode 100644 index 00000000000..48772342bb7 --- /dev/null +++ b/previews/PR1681/tutorials/DGMulti_1/b945cc27.svg @@ -0,0 +1,5544 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/previews/PR1681/tutorials/DGMulti_1/866a258b.svg b/previews/PR1681/tutorials/DGMulti_1/c299c6bb.svg similarity index 58% rename from previews/PR1681/tutorials/DGMulti_1/866a258b.svg rename to previews/PR1681/tutorials/DGMulti_1/c299c6bb.svg index 3930d8f193d..2d04bc28594 100644 --- a/previews/PR1681/tutorials/DGMulti_1/866a258b.svg +++ b/previews/PR1681/tutorials/DGMulti_1/c299c6bb.svg @@ -1,45 +1,45 @@ - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - + - + - - + + - + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - + - + - - + + - + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - + - + - - + + - + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - + - + - + diff --git a/previews/PR1681/tutorials/DGMulti_1/3582722c.svg b/previews/PR1681/tutorials/DGMulti_1/cd2c475f.svg similarity index 76% rename from previews/PR1681/tutorials/DGMulti_1/3582722c.svg rename to previews/PR1681/tutorials/DGMulti_1/cd2c475f.svg index 57a9b451c05..1d8ed349853 100644 --- a/previews/PR1681/tutorials/DGMulti_1/3582722c.svg +++ b/previews/PR1681/tutorials/DGMulti_1/cd2c475f.svg @@ -1,45 +1,45 @@ - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - + - + - - + + - + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - + - + - - + + - + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - + - + - - + + - + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - + - + - + diff --git a/previews/PR1681/tutorials/DGMulti_1/0beb6b7a.svg b/previews/PR1681/tutorials/DGMulti_1/d8522fac.svg similarity index 90% rename from previews/PR1681/tutorials/DGMulti_1/0beb6b7a.svg rename to previews/PR1681/tutorials/DGMulti_1/d8522fac.svg index 095529cf2a1..a9790ab1463 100644 --- a/previews/PR1681/tutorials/DGMulti_1/0beb6b7a.svg +++ b/previews/PR1681/tutorials/DGMulti_1/d8522fac.svg @@ -1,45 +1,45 @@ - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + diff --git a/previews/PR1681/tutorials/DGMulti_1/db7d466c.svg b/previews/PR1681/tutorials/DGMulti_1/ee6d8341.svg similarity index 86% rename from previews/PR1681/tutorials/DGMulti_1/db7d466c.svg rename to previews/PR1681/tutorials/DGMulti_1/ee6d8341.svg index db446472d2e..d2bc0e43d6e 100644 --- a/previews/PR1681/tutorials/DGMulti_1/db7d466c.svg +++ b/previews/PR1681/tutorials/DGMulti_1/ee6d8341.svg @@ -1,8337 +1,8331 @@ - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + diff --git a/previews/PR1681/tutorials/DGMulti_1/index.html b/previews/PR1681/tutorials/DGMulti_1/index.html index 1eb0e92826a..e994d9ed2a3 100644 --- a/previews/PR1681/tutorials/DGMulti_1/index.html +++ b/previews/PR1681/tutorials/DGMulti_1/index.html @@ -28,31 +28,31 @@ ──────────────────────────────────────────────────────────────────────────────────────────────────── Simulation running 'CompressibleEulerEquations2D' with DGMulti(polydeg=3) ──────────────────────────────────────────────────────────────────────────────────────────────────── - #timesteps: 0 run time: 1.23200000e-06 s + #timesteps: 0 run time: 1.31200000e-06 s Δt: 0.00000000e+00 └── GC time: 0.00000000e+00 s (0.000%) sim. time: 0.00000000e+00 (0.000%) time/DOF/rhs!: NaN s PID: Inf s - #DOFs per field: 16384 alloc'd memory: 2618.465 MiB + #DOFs per field: 16384 alloc'd memory: 2787.571 MiB #elements: 1024 Variable: rho rho_v1 rho_v2 rho_e L2 error: 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 Linf error: 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 - ∑∂S/∂U ⋅ Uₜ : 1.75467851e-16 + ∑∂S/∂U ⋅ Uₜ : -4.07691781e-17 ──────────────────────────────────────────────────────────────────────────────────────────────────── -#timesteps: 10 │ Δt: 8.7782e-03 │ sim. time: 6.2446e-02 (15.612%) │ run time: 1.5207e-01 s -#timesteps: 20 │ Δt: 1.2426e-02 │ sim. time: 1.7307e-01 (43.267%) │ run time: 2.9967e-01 s -#timesteps: 30 │ Δt: 1.3710e-02 │ sim. time: 3.0622e-01 (76.554%) │ run time: 4.4919e-01 s +#timesteps: 10 │ Δt: 8.7782e-03 │ sim. time: 6.2446e-02 (15.612%) │ run time: 1.5279e-01 s +#timesteps: 20 │ Δt: 1.2426e-02 │ sim. time: 1.7307e-01 (43.267%) │ run time: 3.0127e-01 s +#timesteps: 30 │ Δt: 1.3710e-02 │ sim. time: 3.0622e-01 (76.554%) │ run time: 4.5031e-01 s ──────────────────────────────────────────────────────────────────────────────────────────────────── Simulation running 'CompressibleEulerEquations2D' with DGMulti(polydeg=3) ──────────────────────────────────────────────────────────────────────────────────────────────────── - #timesteps: 37 run time: 5.56760668e-01 s + #timesteps: 37 run time: 5.58218354e-01 s Δt: 9.57329122e-03 └── GC time: 0.00000000e+00 s (0.000%) - sim. time: 4.00000000e-01 (100.000%) time/DOF/rhs!: 9.37189527e-08 s - PID: 1.00613558e-07 s - #DOFs per field: 16384 alloc'd memory: 2623.326 MiB + sim. time: 4.00000000e-01 (100.000%) time/DOF/rhs!: 9.42812449e-08 s + PID: 1.00838390e-07 s + #DOFs per field: 16384 alloc'd memory: 2792.433 MiB #elements: 1024 Variable: rho rho_v1 rho_v2 rho_e @@ -65,8 +65,8 @@ Trixi.jl simulation finished. Final time: 0.4 Time steps: 37 (accepted), 37 (total) ────────────────────────────────────────────────────────────────────────────────────────────────────
using Plots
 pd = PlotData2D(sol)
-plot(pd)
Example block output
plot(pd["rho"])
-plot!(getmesh(pd))
Example block output

This simulation is not as fast as the equivalent with TreeMesh since no special optimizations for quads (for instance tensor product structure) have been implemented. Figure 4 in "Efficient implementation of modern entropy stable and kinetic energy preserving discontinuous Galerkin methods for conservation laws" (2021) provides a nice runtime comparison between the different mesh types. On the other hand, the functions are more general and thus we have more option we can choose from.

Simulation with Gauss nodes

For instance, we can change the approximation type of our simulation.

using Trixi, OrdinaryDiffEq
+plot(pd)
Example block output
plot(pd["rho"])
+plot!(getmesh(pd))
Example block output

This simulation is not as fast as the equivalent with TreeMesh since no special optimizations for quads (for instance tensor product structure) have been implemented. Figure 4 in "Efficient implementation of modern entropy stable and kinetic energy preserving discontinuous Galerkin methods for conservation laws" (2021) provides a nice runtime comparison between the different mesh types. On the other hand, the functions are more general and thus we have more option we can choose from.

Simulation with Gauss nodes

For instance, we can change the approximation type of our simulation.

using Trixi, OrdinaryDiffEq
 equations = CompressibleEulerEquations2D(1.4)
 initial_condition = initial_condition_weak_blast_wave
initial_condition_weak_blast_wave (generic function with 13 methods)

We now use Gauss nodes instead of Gauss-Lobatto nodes which can be done for the element types Quad() and Hex(). Therefore, we set approximation_type=GaussSBP(). Alternatively, we can use a modal approach using the approximation type Polynomial().

dg = DGMulti(polydeg = 3,
              element_type = Quad(),
@@ -95,32 +95,32 @@
 ────────────────────────────────────────────────────────────────────────────────────────────────────
  Simulation running 'CompressibleEulerEquations2D' with DGMulti(polydeg=3)
 ────────────────────────────────────────────────────────────────────────────────────────────────────
- #timesteps:                  0                run time:       1.39300000e-06 s
+ #timesteps:                  0                run time:       1.52300000e-06 s
  Δt:             0.00000000e+00                └── GC time:    0.00000000e+00 s (0.000%)
  sim. time:      0.00000000e+00 (0.000%)       time/DOF/rhs!:         NaN s
                                                PID:                   Inf s
- #DOFs per field:         16384                alloc'd memory:       2681.011 MiB
+ #DOFs per field:         16384                alloc'd memory:       2847.831 MiB
  #elements:                1024
 
  Variable:       rho              rho_v1           rho_v2           rho_e
- L2 error:       4.43964341e-16   1.20627145e-17   1.18320917e-17   1.17617386e-15
- Linf error:     1.11022302e-15   1.94289029e-16   1.66533454e-16   2.66453526e-15
+ L2 error:       3.17057848e-16   8.94192483e-18   9.07727588e-18   5.97871667e-16
+ Linf error:     8.88178420e-16   1.38777878e-16   1.38777878e-16   2.66453526e-15
  ∑∂S/∂U ⋅ Uₜ :  -1.01164379e-01
 ────────────────────────────────────────────────────────────────────────────────────────────────────
 
-#timesteps:     10 │ Δt: 5.0548e-03 │ sim. time: 3.3436e-02 (8.359%)   │ run time: 5.0320e-01 s
-#timesteps:     20 │ Δt: 8.8313e-03 │ sim. time: 1.0601e-01 (26.503%)  │ run time: 9.6951e-01 s
-#timesteps:     30 │ Δt: 1.0521e-02 │ sim. time: 2.0438e-01 (51.094%)  │ run time: 1.4399e+00 s
-#timesteps:     40 │ Δt: 1.1006e-02 │ sim. time: 3.1245e-01 (78.113%)  │ run time: 1.9097e+00 s
+#timesteps:     10 │ Δt: 5.0548e-03 │ sim. time: 3.3436e-02 (8.359%)   │ run time: 4.8149e-01 s
+#timesteps:     20 │ Δt: 8.8313e-03 │ sim. time: 1.0601e-01 (26.503%)  │ run time: 9.4880e-01 s
+#timesteps:     30 │ Δt: 1.0521e-02 │ sim. time: 2.0438e-01 (51.094%)  │ run time: 1.4344e+00 s
+#timesteps:     40 │ Δt: 1.1006e-02 │ sim. time: 3.1245e-01 (78.113%)  │ run time: 1.9091e+00 s
 
 ────────────────────────────────────────────────────────────────────────────────────────────────────
  Simulation running 'CompressibleEulerEquations2D' with DGMulti(polydeg=3)
 ────────────────────────────────────────────────────────────────────────────────────────────────────
- #timesteps:                 48                run time:       2.29348536e+00 s
- Δt:             1.00192333e-02                └── GC time:    2.31713460e-02 s (1.010%)
- sim. time:      4.00000000e-01 (100.000%)     time/DOF/rhs!:  3.04118384e-07 s
-                                               PID:            3.20893969e-07 s
- #DOFs per field:         16384                alloc'd memory:       2641.472 MiB
+ #timesteps:                 48                run time:       2.32773718e+00 s
+ Δt:             1.00192333e-02                └── GC time:    3.43579320e-02 s (1.476%)
+ sim. time:      4.00000000e-01 (100.000%)     time/DOF/rhs!:  3.06974574e-07 s
+                                               PID:            3.20841844e-07 s
+ #DOFs per field:         16384                alloc'd memory:       2765.785 MiB
  #elements:                1024
 
  Variable:       rho              rho_v1           rho_v2           rho_e
@@ -133,7 +133,7 @@
 Trixi.jl simulation finished.  Final time: 0.4  Time steps: 48 (accepted), 48 (total)
 ────────────────────────────────────────────────────────────────────────────────────────────────────
using Plots
 pd = PlotData2D(sol)
-plot(pd)
Example block output

Simulation with triangular elements

Also, we can set another element type. We want to use triangles now.

using Trixi, OrdinaryDiffEq
+plot(pd)
Example block output

Simulation with triangular elements

Also, we can set another element type. We want to use triangles now.

using Trixi, OrdinaryDiffEq
 equations = CompressibleEulerEquations2D(1.4)
 initial_condition = initial_condition_weak_blast_wave
initial_condition_weak_blast_wave (generic function with 13 methods)

Since there is no direct equivalent to Gauss-Lobatto nodes on triangles, the approximation type SBP() now uses Gauss-Lobatto nodes on faces and special nodes in the interior of the triangular. More details can be found in the documentation of StartUpDG.jl.

dg = DGMulti(polydeg = 3,
              element_type = Tri(),
@@ -162,46 +162,46 @@
 ────────────────────────────────────────────────────────────────────────────────────────────────────
  Simulation running 'CompressibleEulerEquations2D' with DGMulti(polydeg=3)
 ────────────────────────────────────────────────────────────────────────────────────────────────────
- #timesteps:                  0                run time:       1.05200000e-06 s
+ #timesteps:                  0                run time:       9.12000000e-07 s
  Δt:             0.00000000e+00                └── GC time:    0.00000000e+00 s (0.000%)
  sim. time:      0.00000000e+00 (0.000%)       time/DOF/rhs!:         NaN s
                                                PID:                   Inf s
- #DOFs per field:         30720                alloc'd memory:       2696.624 MiB
+ #DOFs per field:         30720                alloc'd memory:       2876.464 MiB
  #elements:                2048
 
  Variable:       rho              rho_v1           rho_v2           rho_e
  L2 error:       0.00000000e+00   0.00000000e+00   0.00000000e+00   0.00000000e+00
  Linf error:     0.00000000e+00   0.00000000e+00   0.00000000e+00   0.00000000e+00
- ∑∂S/∂U ⋅ Uₜ :  -1.47243897e-03
+ ∑∂S/∂U ⋅ Uₜ :  -6.74736856e-03
 ────────────────────────────────────────────────────────────────────────────────────────────────────
 
-#timesteps:     10 │ Δt: 6.8298e-03 │ sim. time: 4.7460e-02 (11.865%)  │ run time: 8.2207e-01 s
-#timesteps:     20 │ Δt: 1.0569e-02 │ sim. time: 1.3920e-01 (34.799%)  │ run time: 1.6360e+00 s
-#timesteps:     30 │ Δt: 1.2136e-02 │ sim. time: 2.5437e-01 (63.592%)  │ run time: 2.4521e+00 s
-#timesteps:     40 │ Δt: 1.2611e-02 │ sim. time: 3.7838e-01 (94.594%)  │ run time: 3.2765e+00 s
+#timesteps:     10 │ Δt: 6.6947e-03 │ sim. time: 4.5960e-02 (11.490%)  │ run time: 8.6797e-01 s
+#timesteps:     20 │ Δt: 1.0524e-02 │ sim. time: 1.3699e-01 (34.249%)  │ run time: 1.6683e+00 s
+#timesteps:     30 │ Δt: 1.2096e-02 │ sim. time: 2.5197e-01 (62.993%)  │ run time: 2.4816e+00 s
+#timesteps:     40 │ Δt: 1.2622e-02 │ sim. time: 3.7597e-01 (93.993%)  │ run time: 3.3032e+00 s
 
 ────────────────────────────────────────────────────────────────────────────────────────────────────
  Simulation running 'CompressibleEulerEquations2D' with DGMulti(polydeg=3)
 ────────────────────────────────────────────────────────────────────────────────────────────────────
- #timesteps:                 42                run time:       3.45287722e+00 s
- Δt:             8.95037648e-03                └── GC time:    0.00000000e+00 s (0.000%)
- sim. time:      4.00000000e-01 (100.000%)     time/DOF/rhs!:  2.86623879e-07 s
-                                               PID:            2.94082336e-07 s
- #DOFs per field:         30720                alloc'd memory:       2705.535 MiB
+ #timesteps:                 42                run time:       3.47926301e+00 s
+ Δt:             1.13592115e-02                └── GC time:    3.47181810e-02 s (0.998%)
+ sim. time:      4.00000000e-01 (100.000%)     time/DOF/rhs!:  2.86626528e-07 s
+                                               PID:            2.96339755e-07 s
+ #DOFs per field:         30720                alloc'd memory:       2807.227 MiB
  #elements:                2048
 
  Variable:       rho              rho_v1           rho_v2           rho_e
- L2 error:       6.07447366e-02   4.92034807e-02   4.92042744e-02   2.22199121e-01
- Linf error:     2.69025841e-01   2.45671112e-01   2.45749171e-01   9.33986997e-01
- ∑∂S/∂U ⋅ Uₜ :  -1.96358137e-03
+ L2 error:       6.07149048e-02   4.91826834e-02   4.91814198e-02   2.22089274e-01
+ Linf error:     2.69551549e-01   2.45792366e-01   2.45935623e-01   9.34191621e-01
+ ∑∂S/∂U ⋅ Uₜ :  -1.95711055e-03
 ────────────────────────────────────────────────────────────────────────────────────────────────────
 
 ────────────────────────────────────────────────────────────────────────────────────────────────────
 Trixi.jl simulation finished.  Final time: 0.4  Time steps: 42 (accepted), 42 (total)
 ────────────────────────────────────────────────────────────────────────────────────────────────────
using Plots
 pd = PlotData2D(sol)
-plot(pd)
Example block output
plot(pd["rho"])
-plot!(getmesh(pd))
Example block output

Triangular meshes on non-Cartesian domains

To use triangular meshes on a non-Cartesian domain, Trixi.jl uses the package StartUpDG.jl. The following example is based on elixir_euler_triangulate_pkg_mesh.jl and uses a pre-defined mesh from StartUpDG.jl.

using Trixi, OrdinaryDiffEq

We want to simulate the smooth initial condition initial_condition_convergence_test with source terms source_terms_convergence_test for the 2D compressible Euler equations.

equations = CompressibleEulerEquations2D(1.4)
+plot(pd)
Example block output
plot(pd["rho"])
+plot!(getmesh(pd))
Example block output

Triangular meshes on non-Cartesian domains

To use triangular meshes on a non-Cartesian domain, Trixi.jl uses the package StartUpDG.jl. The following example is based on elixir_euler_triangulate_pkg_mesh.jl and uses a pre-defined mesh from StartUpDG.jl.

using Trixi, OrdinaryDiffEq

We want to simulate the smooth initial condition initial_condition_convergence_test with source terms source_terms_convergence_test for the 2D compressible Euler equations.

equations = CompressibleEulerEquations2D(1.4)
 initial_condition = initial_condition_convergence_test
 source_terms = source_terms_convergence_test
source_terms_convergence_test (generic function with 13 methods)

We create the solver DGMulti with triangular elements (Tri()) as before.

dg = DGMulti(polydeg = 3, element_type = Tri(),
              approximation_type=Polynomial(),
@@ -242,11 +242,11 @@
 ────────────────────────────────────────────────────────────────────────────────────────────────────
  Simulation running 'CompressibleEulerEquations2D' with DGMulti(polydeg=3)
 ────────────────────────────────────────────────────────────────────────────────────────────────────
- #timesteps:                  0                run time:       1.10200000e-06 s
+ #timesteps:                  0                run time:       1.09200000e-06 s
  Δt:             1.49245207e-03                └── GC time:    0.00000000e+00 s (0.000%)
  sim. time:      0.00000000e+00 (0.000%)       time/DOF/rhs!:         NaN s
                                                PID:                   Inf s
- #DOFs per field:          5980                alloc'd memory:       2732.856 MiB
+ #DOFs per field:          5980                alloc'd memory:       2909.962 MiB
  #elements:                 598
 
  Variable:       rho              rho_v1           rho_v2           rho_e
@@ -255,12 +255,12 @@
  ∑∂S/∂U ⋅ Uₜ :  -1.23444983e-02
 ────────────────────────────────────────────────────────────────────────────────────────────────────
 
-#timesteps:     20 │ Δt: 1.4925e-03 │ sim. time: 2.9849e-02 (14.925%)  │ run time: 5.3753e-01 s
-#timesteps:     40 │ Δt: 1.4925e-03 │ sim. time: 5.9698e-02 (29.849%)  │ run time: 1.0620e+00 s
-#timesteps:     60 │ Δt: 1.4925e-03 │ sim. time: 8.9547e-02 (44.774%)  │ run time: 1.5864e+00 s
-#timesteps:     80 │ Δt: 1.4925e-03 │ sim. time: 1.1940e-01 (59.698%)  │ run time: 2.1105e+00 s
-#timesteps:    100 │ Δt: 1.4925e-03 │ sim. time: 1.4925e-01 (74.623%)  │ run time: 2.6360e+00 s
-#timesteps:    120 │ Δt: 1.4925e-03 │ sim. time: 1.7909e-01 (89.547%)  │ run time: 3.1603e+00 s
+#timesteps:     20 │ Δt: 1.4925e-03 │ sim. time: 2.9849e-02 (14.925%)  │ run time: 5.5053e-01 s
+#timesteps:     40 │ Δt: 1.4925e-03 │ sim. time: 5.9698e-02 (29.849%)  │ run time: 1.0751e+00 s
+#timesteps:     60 │ Δt: 1.4925e-03 │ sim. time: 8.9547e-02 (44.774%)  │ run time: 1.5972e+00 s
+#timesteps:     80 │ Δt: 1.4925e-03 │ sim. time: 1.1940e-01 (59.698%)  │ run time: 2.1195e+00 s
+#timesteps:    100 │ Δt: 1.4925e-03 │ sim. time: 1.4925e-01 (74.623%)  │ run time: 2.6476e+00 s
+#timesteps:    120 │ Δt: 1.4925e-03 │ sim. time: 1.7909e-01 (89.547%)  │ run time: 3.1707e+00 s
 ────────────────────────────────────────────────────────────────────────────────────────────────────
 Trixi.jl simulation finished.  Final time: 0.2  Time steps: 135 (accepted), 135 (total)
 ────────────────────────────────────────────────────────────────────────────────────────────────────
@@ -269,11 +269,11 @@
 ────────────────────────────────────────────────────────────────────────────────────────────────────
  Simulation running 'CompressibleEulerEquations2D' with DGMulti(polydeg=3)
 ────────────────────────────────────────────────────────────────────────────────────────────────────
- #timesteps:                135                run time:       3.55457108e+00 s
+ #timesteps:                135                run time:       3.56302582e+00 s
  Δt:             1.14223386e-05                └── GC time:    0.00000000e+00 s (0.000%)
- sim. time:      2.00000000e-01 (100.000%)     time/DOF/rhs!:  8.71140762e-07 s
-                                               PID:            8.77820928e-07 s
- #DOFs per field:          5980                alloc'd memory:       2733.329 MiB
+ sim. time:      2.00000000e-01 (100.000%)     time/DOF/rhs!:  8.73188619e-07 s
+                                               PID:            8.79911983e-07 s
+ #DOFs per field:          5980                alloc'd memory:       2910.434 MiB
  #elements:                 598
 
  Variable:       rho              rho_v1           rho_v2           rho_e
@@ -283,7 +283,7 @@
 ────────────────────────────────────────────────────────────────────────────────────────────────────
using Plots
 pd = PlotData2D(sol)
 plot(pd["rho"])
-plot!(getmesh(pd))
Example block output

For more information, please have a look in the StartUpDG.jl documentation.

Package versions

These results were obtained using the following versions.

using InteractiveUtils
+plot!(getmesh(pd))
Example block output

For more information, please have a look in the StartUpDG.jl documentation.

Package versions

These results were obtained using the following versions.

using InteractiveUtils
 versioninfo()
 
 using Pkg
@@ -305,4 +305,4 @@
   [1dea7af3] OrdinaryDiffEq v6.59.0
   [91a5bcdd] Plots v1.39.0
   [472ebc20] StartUpDG v0.17.7
-  [a7f1ee26] Trixi v0.5.48-pre `~/work/Trixi.jl/Trixi.jl`

This page was generated using Literate.jl.

+ [a7f1ee26] Trixi v0.5.48-pre `~/work/Trixi.jl/Trixi.jl`

This page was generated using Literate.jl.

diff --git a/previews/PR1681/tutorials/DGMulti_2/index.html b/previews/PR1681/tutorials/DGMulti_2/index.html index 1ea06b5fb51..43f61eae4b6 100644 --- a/previews/PR1681/tutorials/DGMulti_2/index.html +++ b/previews/PR1681/tutorials/DGMulti_2/index.html @@ -33,4 +33,4 @@ Status `~/work/Trixi.jl/Trixi.jl/docs/Manifest.toml` [472ebc20] StartUpDG v0.17.7 [9f78cca6] SummationByPartsOperators v0.5.51 - [a7f1ee26] Trixi v0.5.48-pre `~/work/Trixi.jl/Trixi.jl`

This page was generated using Literate.jl.

+ [a7f1ee26] Trixi v0.5.48-pre `~/work/Trixi.jl/Trixi.jl`

This page was generated using Literate.jl.

diff --git a/previews/PR1681/tutorials/DGSEM_FluxDiff/d76be45a.svg b/previews/PR1681/tutorials/DGSEM_FluxDiff/9e69cdbf.svg similarity index 95% rename from previews/PR1681/tutorials/DGSEM_FluxDiff/d76be45a.svg rename to previews/PR1681/tutorials/DGSEM_FluxDiff/9e69cdbf.svg index 9b049ee9289..5049e6a3224 100644 --- a/previews/PR1681/tutorials/DGSEM_FluxDiff/d76be45a.svg +++ b/previews/PR1681/tutorials/DGSEM_FluxDiff/9e69cdbf.svg @@ -1,45 +1,45 @@ - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - + - + - - + + - + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - + - + - - + + - + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - + - + - - + + - + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - + - + - + diff --git a/previews/PR1681/tutorials/DGSEM_FluxDiff/d81dd9bb.svg b/previews/PR1681/tutorials/DGSEM_FluxDiff/eaa6ef71.svg similarity index 94% rename from previews/PR1681/tutorials/DGSEM_FluxDiff/d81dd9bb.svg rename to previews/PR1681/tutorials/DGSEM_FluxDiff/eaa6ef71.svg index 8948470ce89..2ca956d165b 100644 --- a/previews/PR1681/tutorials/DGSEM_FluxDiff/d81dd9bb.svg +++ b/previews/PR1681/tutorials/DGSEM_FluxDiff/eaa6ef71.svg @@ -1,45 +1,45 @@ - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - + - + - - + + - + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - + - + - - + + - + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - + - + - - + + - + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - + - + - + diff --git a/previews/PR1681/tutorials/DGSEM_FluxDiff/index.html b/previews/PR1681/tutorials/DGSEM_FluxDiff/index.html index 99fb67472bb..c5a13fa02eb 100644 --- a/previews/PR1681/tutorials/DGSEM_FluxDiff/index.html +++ b/previews/PR1681/tutorials/DGSEM_FluxDiff/index.html @@ -54,11 +54,11 @@ ──────────────────────────────────────────────────────────────────────────────────────────────────── Simulation running 'CompressibleEulerEquations2D' with DGSEM(polydeg=3) ──────────────────────────────────────────────────────────────────────────────────────────────────── - #timesteps: 0 run time: 9.02000000e-07 s + #timesteps: 0 run time: 5.81000000e-07 s Δt: 0.00000000e+00 └── GC time: 0.00000000e+00 s (0.000%) sim. time: 0.00000000e+00 (0.000%) time/DOF/rhs!: NaN s PID: Inf s - #DOFs per field: 16384 alloc'd memory: 2771.467 MiB + #DOFs per field: 16384 alloc'd memory: 2861.722 MiB #elements: 1024 Variable: rho rho_v1 rho_v2 rho_e @@ -71,11 +71,11 @@ ──────────────────────────────────────────────────────────────────────────────────────────────────── Simulation running 'CompressibleEulerEquations2D' with DGSEM(polydeg=3) ──────────────────────────────────────────────────────────────────────────────────────────────────── - #timesteps: 61 run time: 8.57462912e-01 s + #timesteps: 61 run time: 8.98897482e-01 s Δt: 2.65388338e-06 └── GC time: 0.00000000e+00 s (0.000%) - sim. time: 4.00000000e-01 (100.000%) time/DOF/rhs!: 8.58427127e-08 s - PID: 9.43576000e-08 s - #DOFs per field: 16384 alloc'd memory: 2773.195 MiB + sim. time: 4.00000000e-01 (100.000%) time/DOF/rhs!: 9.09343694e-08 s + PID: 9.89345085e-08 s + #DOFs per field: 16384 alloc'd memory: 2863.449 MiB #elements: 1024 Variable: rho rho_v1 rho_v2 rho_e @@ -83,7 +83,7 @@ Linf error: 2.91149630e-01 3.21787795e-01 3.22040740e-01 1.04645370e+00 ∑∂S/∂U ⋅ Uₜ : -2.34481695e-18 ────────────────────────────────────────────────────────────────────────────────────────────────────

A look at the change in entropy $\sum \partial S/\partial U \cdot U_t$ in the analysis callback confirms that the flux is entropy conserving since the change is about machine precision.

We can plot the approximated solution at the time t=0.4.

using Plots
-plot(sol)
Example block output

Now, we can use for instance the dissipative flux flux_lax_friedrichs as surface flux to get an entropy stable method.

using OrdinaryDiffEq, Trixi
+plot(sol)
Example block output

Now, we can use for instance the dissipative flux flux_lax_friedrichs as surface flux to get an entropy stable method.

using OrdinaryDiffEq, Trixi
 
 gamma = 1.4
 equations = CompressibleEulerEquations2D(gamma)
@@ -113,11 +113,11 @@
 ────────────────────────────────────────────────────────────────────────────────────────────────────
  Simulation running 'CompressibleEulerEquations2D' with DGSEM(polydeg=3)
 ────────────────────────────────────────────────────────────────────────────────────────────────────
- #timesteps:                  0                run time:       6.71000000e-07 s
+ #timesteps:                  0                run time:       1.51300000e-06 s
  Δt:             0.00000000e+00                └── GC time:    0.00000000e+00 s (0.000%)
  sim. time:      0.00000000e+00 (0.000%)       time/DOF/rhs!:         NaN s
                                                PID:                   Inf s
- #DOFs per field:         16384                alloc'd memory:       2773.602 MiB
+ #DOFs per field:         16384                alloc'd memory:       2871.072 MiB
  #elements:                1024
 
  Variable:       rho              rho_v1           rho_v2           rho_e
@@ -130,11 +130,11 @@
 ────────────────────────────────────────────────────────────────────────────────────────────────────
  Simulation running 'CompressibleEulerEquations2D' with DGSEM(polydeg=3)
 ────────────────────────────────────────────────────────────────────────────────────────────────────
- #timesteps:                 37                run time:       4.89125711e-01 s
+ #timesteps:                 37                run time:       5.22638322e-01 s
  Δt:             9.70561500e-03                └── GC time:    0.00000000e+00 s (0.000%)
- sim. time:      4.00000000e-01 (100.000%)     time/DOF/rhs!:  8.14398056e-08 s
-                                               PID:            8.81177895e-08 s
- #DOFs per field:         16384                alloc'd memory:       2775.329 MiB
+ sim. time:      4.00000000e-01 (100.000%)     time/DOF/rhs!:  8.64187236e-08 s
+                                               PID:            9.41739905e-08 s
+ #DOFs per field:         16384                alloc'd memory:       2872.798 MiB
  #elements:                1024
 
  Variable:       rho              rho_v1           rho_v2           rho_e
@@ -142,7 +142,7 @@
  Linf error:     2.61815838e-01   2.48816692e-01   2.48316760e-01   9.30972696e-01
  ∑∂S/∂U ⋅ Uₜ :  -1.40306972e-04
 ────────────────────────────────────────────────────────────────────────────────────────────────────

The change in entropy confirms the expected entropy stability.

using Plots
-plot(sol)
Example block output

Of course, you can use more than these two fluxes in Trixi. Here, we will give a short list of possible fluxes for the compressible Euler equations. For the volume flux Trixi.jl provides for example flux_ranocha, flux_shima_etal, flux_chandrashekar, flux_kennedy_gruber. As surface flux you can use all volume fluxes and additionally for instance flux_lax_friedrichs, flux_hll, flux_hllc.

Package versions

These results were obtained using the following versions.

using InteractiveUtils
+plot(sol)
Example block output

Of course, you can use more than these two fluxes in Trixi. Here, we will give a short list of possible fluxes for the compressible Euler equations. For the volume flux Trixi.jl provides for example flux_ranocha, flux_shima_etal, flux_chandrashekar, flux_kennedy_gruber. As surface flux you can use all volume fluxes and additionally for instance flux_lax_friedrichs, flux_hll, flux_hllc.

Package versions

These results were obtained using the following versions.

using InteractiveUtils
 versioninfo()
 
 using Pkg
@@ -163,4 +163,4 @@
 Status `~/work/Trixi.jl/Trixi.jl/docs/Manifest.toml`
   [1dea7af3] OrdinaryDiffEq v6.59.0
   [91a5bcdd] Plots v1.39.0
-  [a7f1ee26] Trixi v0.5.48-pre `~/work/Trixi.jl/Trixi.jl`

This page was generated using Literate.jl.

+ [a7f1ee26] Trixi v0.5.48-pre `~/work/Trixi.jl/Trixi.jl`

This page was generated using Literate.jl.

diff --git a/previews/PR1681/tutorials/adaptive_mesh_refinement/84e8847b.svg b/previews/PR1681/tutorials/adaptive_mesh_refinement/6bddc81d.svg similarity index 85% rename from previews/PR1681/tutorials/adaptive_mesh_refinement/84e8847b.svg rename to previews/PR1681/tutorials/adaptive_mesh_refinement/6bddc81d.svg index a4a8fe8206e..2ef0ff4ac0c 100644 --- a/previews/PR1681/tutorials/adaptive_mesh_refinement/84e8847b.svg +++ b/previews/PR1681/tutorials/adaptive_mesh_refinement/6bddc81d.svg @@ -1,35 +1,35 @@ - + - + - + - + - + - - - - - - - - - - - - - + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + diff --git a/previews/PR1681/tutorials/adaptive_mesh_refinement/index.html b/previews/PR1681/tutorials/adaptive_mesh_refinement/index.html index 69374f62212..c839031a859 100644 --- a/previews/PR1681/tutorials/adaptive_mesh_refinement/index.html +++ b/previews/PR1681/tutorials/adaptive_mesh_refinement/index.html @@ -53,7 +53,7 @@ save_everystep=false, callback=callbacks);

We plot the solution and add the refined mesh at the end of the simulation.

using Plots
 pd = PlotData2D(sol)
 plot(pd)
-plot!(getmesh(pd))
Example block output

More examples

Trixi.jl provides many elixirs using AMR. We want to give some examples for different mesh types:

Animations of more interesting and complicated AMR simulations can be found below and on Trixi.jl's youtube channel "Trixi Framework".

First, we give a purely hyperbolic simulation of a Sedov blast wave with self-gravity. This simulation uses the mesh type TreeMesh as we did and the AMR indicator IndicatorHennemannGassner.

EJ#kxqqBzRV_O`Avx$qT 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

tkETDTl5=JAxjbpe8!%6#>{&C#6jR_WA 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 JFT0I^>p$kUbnyTH diff --git a/previews/PR1681/tutorials/out/solution_000010.vtu b/previews/PR1681/tutorials/out/solution_000010.vtu index c093326c6effaabd4f24c1affeb4877db3565f0a..431cdad652b6ab649cbfcc86f87d14cf88c95415 100644 GIT binary patch delta 12013 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 diff --git a/previews/PR1681/tutorials/out/solution_000020.h5 b/previews/PR1681/tutorials/out/solution_000020.h5 index e77a52f19ed0c93f884ceff58dfdbef4a5bc492c..0b3f21ad360cc6dc13249493deec644d8241ed23 100644 GIT binary patch literal 205696 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