diff --git a/.github/workflows/CacheNotebooks.yml b/.github/workflows/CacheNotebooks.yml index c8599d13f26..f89560d8158 100644 --- a/.github/workflows/CacheNotebooks.yml +++ b/.github/workflows/CacheNotebooks.yml @@ -11,7 +11,7 @@ jobs: steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - name: Checkout caching branch - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: tutorial_notebooks diff --git a/.github/workflows/DocPreviewCleanup.yml b/.github/workflows/DocPreviewCleanup.yml index 66d0b342b2e..0850369c9cc 100644 --- a/.github/workflows/DocPreviewCleanup.yml +++ b/.github/workflows/DocPreviewCleanup.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout gh-pages branch - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: gh-pages diff --git a/.github/workflows/Documenter.yml b/.github/workflows/Documenter.yml index 6b557960c89..129c41a3b5c 100644 --- a/.github/workflows/Documenter.yml +++ b/.github/workflows/Documenter.yml @@ -33,7 +33,7 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: julia-actions/setup-julia@v1 with: version: '1.9' diff --git a/.github/workflows/FormatCheck.yml b/.github/workflows/FormatCheck.yml index 628d938dd76..a733cb7cc21 100644 --- a/.github/workflows/FormatCheck.yml +++ b/.github/workflows/FormatCheck.yml @@ -20,7 +20,7 @@ jobs: with: version: ${{ matrix.julia-version }} - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install JuliaFormatter and format # This will use the latest version by default but you can set the version like so: # @@ -30,7 +30,7 @@ jobs: # format(".") run: | julia -e 'using Pkg; Pkg.add(PackageSpec(name = "JuliaFormatter"))' - julia -e 'using JuliaFormatter; format(["benchmark", "ext", "src", "utils"])' + julia -e 'using JuliaFormatter; format(["benchmark", "examples", "ext", "src", "test", "utils"])' - name: Format check run: | julia -e ' diff --git a/.github/workflows/Invalidations.yml b/.github/workflows/Invalidations.yml index ba81f83e0ad..18048d26be8 100644 --- a/.github/workflows/Invalidations.yml +++ b/.github/workflows/Invalidations.yml @@ -19,12 +19,12 @@ jobs: - uses: julia-actions/setup-julia@v1 with: version: '1' - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: julia-actions/julia-buildpkg@v1 - uses: julia-actions/julia-invalidations@v1 id: invs_pr - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: ${{ github.event.repository.default_branch }} - uses: julia-actions/julia-buildpkg@v1 diff --git a/.github/workflows/ReviewChecklist.yml b/.github/workflows/ReviewChecklist.yml index 959a04752d7..d8854411804 100644 --- a/.github/workflows/ReviewChecklist.yml +++ b/.github/workflows/ReviewChecklist.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Add review checklist uses: trixi-framework/add-pr-review-checklist@v1 with: diff --git a/.github/workflows/SpellCheck.yml b/.github/workflows/SpellCheck.yml index 6ebb288ea30..366cb1183a0 100644 --- a/.github/workflows/SpellCheck.yml +++ b/.github/workflows/SpellCheck.yml @@ -8,6 +8,6 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout Actions Repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Check spelling - uses: crate-ci/typos@v1.16.5 + uses: crate-ci/typos@v1.16.23 diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index c5c95558c8c..2ea30d6fddb 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -15,7 +15,7 @@ jobs: arch: - x64 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - run: | diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f5b037fba7d..a2298971962 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -102,7 +102,7 @@ jobs: arch: x64 trixi_test: threaded steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: julia-actions/setup-julia@v1 with: version: ${{ matrix.version }} @@ -176,7 +176,7 @@ jobs: # Instead, we use the more tedious approach described above. # At first, we check out the repository and download all artifacts # (and list files for debugging). - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/download-artifact@v3 - run: ls -R # Next, we merge the individual coverage files and upload diff --git a/.github/workflows/downstream.yml b/.github/workflows/downstream.yml new file mode 100644 index 00000000000..b40d5d365c0 --- /dev/null +++ b/.github/workflows/downstream.yml @@ -0,0 +1,94 @@ +# Note: this file is inspired by the downstream testing facilities in the SciML ecosystem +# x-ref: https://github.com/SciML/SciMLBase.jl/blob/ffe68aebedee5915190623cb08160d7ef1fbcce0/.github/workflows/Downstream.yml + +name: Downstream +on: + push: + branches: + - main + paths-ignore: + - 'AUTHORS.md' + - 'CITATION.bib' + - 'CONTRIBUTING.md' + - 'LICENSE.md' + - 'NEWS.md' + - 'README.md' + - '.zenodo.json' + - '.github/workflows/benchmark.yml' + - '.github/workflows/CompatHelper.yml' + - '.github/workflows/TagBot.yml' + - 'benchmark/**' + # - 'docs/**' + - 'utils/**' + pull_request: + paths-ignore: + - 'AUTHORS.md' + - 'CITATION.bib' + - 'CONTRIBUTING.md' + - 'LICENSE.md' + - 'NEWS.md' + - 'README.md' + - '.zenodo.json' + - '.github/workflows/benchmark.yml' + - '.github/workflows/CompatHelper.yml' + - '.github/workflows/TagBot.yml' + - 'benchmark/**' + # - 'docs/**' + - 'utils/**' + workflow_dispatch: + +# Cancel redundant CI tests automatically +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + test: + if: "!contains(github.event.head_commit.message, 'skip ci')" + # We could also include the Julia version as in + # name: ${{ matrix.trixi_test }} - ${{ matrix.os }} - Julia ${{ matrix.version }} - ${{ matrix.arch }} - ${{ github.event_name }} + # to be more specific. However, that requires us updating the required CI tests whenever we update Julia. + name: ${{ matrix.package }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + version: + - '1.9' + os: + - ubuntu-latest + arch: + - x64 + package: + - Trixi2Vtk.jl + - TrixiShallowWater.jl + steps: + - uses: actions/checkout@v4 + - uses: julia-actions/setup-julia@v1 + with: + version: ${{ matrix.version }} + arch: ${{ matrix.arch }} + - run: julia -e 'using InteractiveUtils; versioninfo(verbose=true)' + - uses: julia-actions/cache@v1 + - uses: julia-actions/julia-buildpkg@v1 + - name: Retrieve downstream package + # Note: we retrieve the current `main` branch of the downstream package to ensure + # that compatibility errors we make in Trixi.jl are detected already here + # See also https://github.com/trixi-framework/Trixi.jl/pull/1707#discussion_r1382938895 + uses: actions/checkout@v4 + with: + repository: trixi-framework/${{ matrix.package }} + path: downstream + - name: Load upstream package into downstream environment + shell: julia --color=yes --project=downstream {0} + run: | + using Pkg + Pkg.develop(PackageSpec(path=".")) + Pkg.update() + - name: Run downstream tests (without coverage) + shell: julia --color=yes --project=downstream {0} + run: | + using Pkg + Pkg.test(coverage=false) + env: + TRIXI_TEST: upstream diff --git a/.zenodo.json b/.zenodo.json index 95879af1e90..905c0170ab9 100644 --- a/.zenodo.json +++ b/.zenodo.json @@ -15,7 +15,7 @@ "orcid": "0000-0002-1752-1158" }, { - "affiliation": "Applied Mathematics, University of Hamburg, Germany", + "affiliation": "Numerical Mathematics, Johannes Gutenberg University Mainz, Germany", "name": "Ranocha, Hendrik", "orcid": "0000-0002-3456-2277" }, diff --git a/AUTHORS.md b/AUTHORS.md index 74bfaa9c852..f1debf8ba76 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -12,7 +12,7 @@ provided substantial additions or modifications. Together, these two groups form * [Gregor Gassner](https://www.mi.uni-koeln.de/NumSim/gregor-gassner), University of Cologne, Germany * [Hendrik Ranocha](https://ranocha.de), - University of Hamburg, Germany + Johannes Gutenberg University Mainz, Germany * [Andrew Winters](https://liu.se/en/employee/andwi94), Linköping University, Sweden * [Jesse Chan](https://jlchan.github.io), diff --git a/NEWS.md b/NEWS.md index 4b96e1e2834..265979c3508 100644 --- a/NEWS.md +++ b/NEWS.md @@ -4,6 +4,31 @@ Trixi.jl follows the interpretation of [semantic versioning (semver)](https://ju used in the Julia ecosystem. Notable changes will be documented in this file for human readability. +## Changes when updating to v0.6 from v0.5.x + +#### Added +- AMR for hyperbolic-parabolic equations on 2D `P4estMesh` + +#### Changed + +- The wave speed estimates for `flux_hll`, `FluxHLL()` are now consistent across equations. + In particular, the functions `min_max_speed_naive`, `min_max_speed_einfeldt` are now + conceptually identical across equations. + Users, who have been using `flux_hll` for MHD have now to use `flux_hlle` in order to use the + Einfeldt wave speed estimate. +- Parabolic diffusion terms are now officially supported and not marked as experimental + anymore. + +#### Deprecated + +#### Removed + +- The neural network-based shock indicators have been migrated to a new repository + [TrixiSmartShockFinder.jl](https://github.com/trixi-framework/TrixiSmartShockFinder.jl). + To continue using the indicators, you will need to use both Trixi.jl and + TrixiSmartShockFinder.jl, as explained in the latter packages' `README.md`. + + ## Changes in the v0.5 lifecycle #### Added @@ -12,7 +37,12 @@ for human readability. - Non-uniform `TreeMesh` available for hyperbolic-parabolic equations. - Capability to set truly discontinuous initial conditions in 1D. - Wetting and drying feature and examples for 1D and 2D shallow water equations -- Subcell positivity limiting support for conservative variables in 2D for `TreeMesh` +- Implementation of the polytropic Euler equations in 2D +- Implementation of the quasi-1D shallow water equations +- Subcell (positivity and local min/max) limiting support for conservative variables + in 2D for `TreeMesh` +- AMR for hyperbolic-parabolic equations on 2D/3D `TreeMesh` +- Added `GradientVariables` type parameter to `AbstractEquationsParabolic` #### Changed @@ -29,6 +59,9 @@ for human readability. #### Removed +- Migrate neural network-based shock indicators to a new repository + [TrixiSmartShockFinder.jl](https://github.com/trixi-framework/TrixiSmartShockFinder.jl). + ## Changes when updating to v0.5 from v0.4.x diff --git a/Project.toml b/Project.toml index 4374eaa3b0a..a834ddeea73 100644 --- a/Project.toml +++ b/Project.toml @@ -1,11 +1,12 @@ name = "Trixi" uuid = "a7f1ee26-1774-49b1-8366-f1abc58fbfcb" authors = ["Michael Schlottke-Lakemper ", "Gregor Gassner ", "Hendrik Ranocha ", "Andrew R. Winters ", "Jesse Chan "] -version = "0.5.40-pre" +version = "0.6.5-pre" [deps] CodeTracking = "da1fd8a2-8d9e-5ec2-8556-3022fb5608a2" ConstructionBase = "187b0558-2788-49d3-abe0-74a17ed4e7c9" +DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" DiffEqCallbacks = "459566f4-90b8-5000-8ac3-15dfb0a30def" EllipsisNotation = "da5c29d0-fa7d-589e-88eb-ea29b0a81949" FillArrays = "1a297f60-69ca-5386-bcde-b61e274b549b" @@ -52,12 +53,14 @@ TrixiMakieExt = "Makie" [compat] CodeTracking = "1.0.5" ConstructionBase = "1.3" +DataStructures = "0.18.15" DiffEqCallbacks = "2.25" EllipsisNotation = "1.0" FillArrays = "0.13.2, 1" ForwardDiff = "0.10.18" -HDF5 = "0.14, 0.15, 0.16" +HDF5 = "0.14, 0.15, 0.16, 0.17" IfElse = "0.1" +LinearAlgebra = "1" LinearMaps = "2.7, 3.0" LoopVectorization = "0.12.118" MPI = "0.20" @@ -65,15 +68,17 @@ Makie = "0.19" MuladdMacro = "0.2.2" Octavian = "0.3.5" OffsetArrays = "1.3" -P4est = "0.4" +P4est = "0.4.9" Polyester = "0.7.5" PrecompileTools = "1.1" +Printf = "1" RecipesBase = "1.1" Reexport = "1.0" Requires = "1.1" -SciMLBase = "1.90" +SciMLBase = "1.90, 2" Setfield = "0.8, 1" SimpleUnPack = "1.1" +SparseArrays = "1" StartUpDG = "0.17" Static = "0.3, 0.4, 0.5, 0.6, 0.7, 0.8" StaticArrayInterface = "1.4" @@ -81,8 +86,8 @@ StaticArrays = "1" StrideArrays = "0.1.18" StructArrays = "0.6" SummationByPartsOperators = "0.5.41" -T8code = "0.4.1" -TimerOutputs = "0.5" +T8code = "0.4.3, 0.5" +TimerOutputs = "0.5.7" Triangulate = "2.0" TriplotBase = "0.1" TriplotRecipes = "0.1" diff --git a/README.md b/README.md index 7eaee8750dd..c531ab4d1a4 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ [![Build Status](https://github.com/trixi-framework/Trixi.jl/workflows/CI/badge.svg)](https://github.com/trixi-framework/Trixi.jl/actions?query=workflow%3ACI) [![Codecov](https://codecov.io/gh/trixi-framework/Trixi.jl/branch/main/graph/badge.svg)](https://codecov.io/gh/trixi-framework/Trixi.jl) [![Coveralls](https://coveralls.io/repos/github/trixi-framework/Trixi.jl/badge.svg?branch=main)](https://coveralls.io/github/trixi-framework/Trixi.jl?branch=main) +[![Aqua QA](https://raw.githubusercontent.com/JuliaTesting/Aqua.jl/master/badge.svg)](https://github.com/JuliaTesting/Aqua.jl) [![License: MIT](https://img.shields.io/badge/License-MIT-success.svg)](https://opensource.org/licenses/MIT) [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.3996439.svg)](https://doi.org/10.5281/zenodo.3996439) [![Downloads](https://shields.io/endpoint?url=https://pkgs.genieframework.com/api/v1/badge/Trixi)](https://pkgs.genieframework.com?packages=Trixi) @@ -17,17 +18,7 @@

-*** -**Trixi.jl at JuliaCon 2023**
-At this year's JuliaCon, we will be present with an online contribution that involves Trixi.jl: - -* [Scaling Trixi.jl to more than 10,000 cores using MPI](https://pretalx.com/juliacon2023/talk/PC8PZ8/), - 27th July 2023, 10:30–11:30 (US/Eastern), 32-G449 (Kiva) - -We are looking forward to seeing you there ♥️ -*** - -**Trixi.jl** is a numerical simulation framework for hyperbolic conservation +**Trixi.jl** is a numerical simulation framework for conservation laws written in [Julia](https://julialang.org). 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 @@ -55,6 +46,7 @@ installation and postprocessing procedures. Its features include: * Periodic and weakly-enforced boundary conditions * Multiple governing equations: * Compressible Euler equations + * Compressible Navier-Stokes equations * Magnetohydrodynamics (MHD) equations * Multi-component compressible Euler and MHD equations * Linearized Euler and acoustic perturbation equations @@ -65,6 +57,7 @@ installation and postprocessing procedures. Its features include: * Multi-physics simulations * [Self-gravitating gas dynamics](https://github.com/trixi-framework/paper-self-gravitating-gas-dynamics) * Shared-memory parallelization via multithreading +* Multi-node parallelization via MPI * Visualization and postprocessing of the results * In-situ and a posteriori visualization with [Plots.jl](https://github.com/JuliaPlots/Plots.jl) * Interactive visualization with [Makie.jl](https://makie.juliaplots.org/) @@ -247,7 +240,7 @@ Schlottke-Lakemper](https://lakemper.eu) (RWTH Aachen University/High-Performance Computing Center Stuttgart (HLRS), Germany) and [Gregor Gassner](https://www.mi.uni-koeln.de/NumSim/gregor-gassner) (University of Cologne, Germany). Together with [Hendrik Ranocha](https://ranocha.de) -(University of Hamburg, Germany), [Andrew Winters](https://liu.se/en/employee/andwi94) +(Johannes Gutenberg University Mainz, Germany), [Andrew Winters](https://liu.se/en/employee/andwi94) (Linköping University, Sweden), and [Jesse Chan](https://jlchan.github.io) (Rice University, US), they are the principal developers of Trixi.jl. The full list of contributors can be found in [AUTHORS.md](AUTHORS.md). @@ -265,31 +258,48 @@ or [create an issue](https://github.com/trixi-framework/Trixi.jl/issues/new). ## Acknowledgments -

- +

-This project has benefited from funding by the Deutsche Forschungsgemeinschaft (DFG, German Research Foundation) -under Germany's Excellence Strategy EXC 2044-390685587, Mathematics Münster: -Dynamics-Geometry-Structure. +This project has benefited from funding by the [Deutsche +Forschungsgemeinschaft](https://www.dfg.de/) (DFG, German Research Foundation) +through the following grants: +* Excellence Strategy EXC 2044-390685587, Mathematics Münster: Dynamics-Geometry-Structure. +* Research unit FOR 5409 "Structure-Preserving Numerical Methods for Bulk- and + Interface Coupling of Heterogeneous Models (SNuBIC)" (project number 463312734). +* Individual grant no. 528753982. -This project has benefited from funding by the Deutsche Forschungsgemeinschaft (DFG, German Research Foundation) -through the research unit FOR 5409 "Structure-Preserving Numerical Methods for Bulk- and -Interface Coupling of Heterogeneous Models (SNuBIC)" (project number 463312734). - -This project has benefited from funding from the European Research Council through the +This project has benefited from funding from the [European Research Council](https://erc.europa.eu) +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 +This project has benefited from funding from [Vetenskapsrådet](https://www.vr.se) +(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 under awards +This project has benefited from funding from the United States +[National Science Foundation](https://www.nsf.gov/) (NSF) under awards DMS-1719818 and DMS-1943186. -This project has benefited from funding from the German Federal Ministry of -Education and Research through the project grant "Adaptive earth system modeling +This project has benefited from funding from the German +[Federal Ministry of Education and Research](https://www.bmbf.de) (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](https://www.daimler-benz-stiftung.de) (Daimler and Benz Foundation) +through grant no. 32-10/22. + +Trixi.jl is supported by [NumFOCUS](https://numfocus.org/) as an Affiliated Project. diff --git a/benchmark/Project.toml b/benchmark/Project.toml index fb985572532..e94144cfd15 100644 --- a/benchmark/Project.toml +++ b/benchmark/Project.toml @@ -8,4 +8,4 @@ Trixi = "a7f1ee26-1774-49b1-8366-f1abc58fbfcb" BenchmarkTools = "0.5, 0.7, 1.0" OrdinaryDiffEq = "5.65, 6" PkgBenchmark = "0.2.10" -Trixi = "0.4, 0.5" +Trixi = "0.4, 0.5, 0.6" diff --git a/docs/Project.toml b/docs/Project.toml index 9fc974d6f38..3a091f5b4f1 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -13,7 +13,7 @@ Trixi2Vtk = "bc1476a1-1ca6-4cc3-950b-c312b255ff95" [compat] CairoMakie = "0.6, 0.7, 0.8, 0.9, 0.10" -Documenter = "0.27" +Documenter = "1" ForwardDiff = "0.10" HOHQMesh = "0.1, 0.2" LaTeXStrings = "1.2" @@ -21,4 +21,5 @@ Literate = "2.9" Measurements = "2.5" OrdinaryDiffEq = "6.49.1" Plots = "1.9" +Test = "1" Trixi2Vtk = "0.3" diff --git a/docs/literate/make.jl b/docs/literate/make.jl index b620f85c975..a04d8a0b333 100644 --- a/docs/literate/make.jl +++ b/docs/literate/make.jl @@ -51,12 +51,25 @@ function create_tutorials(files) # Run tests on all tutorial files @testset "TrixiTutorials" begin for (i, (title, filename)) in enumerate(files) + # Evaluate each tutorial in its own module to avoid leaking of + # function/variable names, polluting the namespace of later tutorials + # by stuff defined in earlier tutorials. if filename isa Vector # Several files of one topic for j in eachindex(filename) - @testset "$(filename[j][2][2])" begin include(joinpath(repo_src, filename[j][2][1], filename[j][2][2])) end + mod = gensym(filename[j][2][2]) + @testset "$(filename[j][2][2])" begin + @eval module $mod + include(joinpath($repo_src, $(filename[j][2][1]), $(filename[j][2][2]))) + end + end end else # Single files - @testset "$title" begin include(joinpath(repo_src, filename)) end + mod = gensym(title) + @testset "$title" begin + @eval module $mod + include(joinpath($repo_src, $filename)) + end + end end end end diff --git a/docs/literate/src/files/DGMulti_1.jl b/docs/literate/src/files/DGMulti_1.jl index 0d78e79907c..6c9a5aea936 100644 --- a/docs/literate/src/files/DGMulti_1.jl +++ b/docs/literate/src/files/DGMulti_1.jl @@ -168,7 +168,7 @@ meshIO = StartUpDG.triangulate_domain(StartUpDG.RectangularDomainWithHole()); # The pre-defined Triangulate geometry in StartUpDG has integer boundary tags. With [`DGMultiMesh`](@ref) # we assign boundary faces based on these integer boundary tags and create a mesh compatible with Trixi.jl. -mesh = DGMultiMesh(meshIO, dg, Dict(:outer_boundary=>1, :inner_boundary=>2)) +mesh = DGMultiMesh(dg, meshIO, Dict(:outer_boundary=>1, :inner_boundary=>2)) #- boundary_condition_convergence_test = BoundaryConditionDirichlet(initial_condition) boundary_conditions = (; :outer_boundary => boundary_condition_convergence_test, @@ -194,3 +194,15 @@ plot(pd["rho"]) plot!(getmesh(pd)) # For more information, please have a look in the [StartUpDG.jl documentation](https://jlchan.github.io/StartUpDG.jl/stable/). + + +# ## Package versions + +# These results were obtained using the following versions. + +using InteractiveUtils +versioninfo() + +using Pkg +Pkg.status(["Trixi", "StartUpDG", "OrdinaryDiffEq", "Plots"], + mode=PKGMODE_MANIFEST) diff --git a/docs/literate/src/files/DGMulti_2.jl b/docs/literate/src/files/DGMulti_2.jl index 92dce43cdab..06248562343 100644 --- a/docs/literate/src/files/DGMulti_2.jl +++ b/docs/literate/src/files/DGMulti_2.jl @@ -38,3 +38,15 @@ D = couple_continuously(legendre_derivative_operator(xmin=0.0, xmax=1.0, N=4), # For more information and other SBP operators, see the documentations of [StartUpDG.jl](https://jlchan.github.io/StartUpDG.jl/dev/) # and [SummationByPartsOperators.jl](https://ranocha.de/SummationByPartsOperators.jl/stable/). + + +# ## Package versions + +# These results were obtained using the following versions. + +using InteractiveUtils +versioninfo() + +using Pkg +Pkg.status(["Trixi", "StartUpDG", "SummationByPartsOperators"], + mode=PKGMODE_MANIFEST) diff --git a/docs/literate/src/files/DGSEM_FluxDiff.jl b/docs/literate/src/files/DGSEM_FluxDiff.jl index 5ec156ebbe3..a5769900269 100644 --- a/docs/literate/src/files/DGSEM_FluxDiff.jl +++ b/docs/literate/src/files/DGSEM_FluxDiff.jl @@ -236,3 +236,15 @@ plot(sol) # [`flux_chandrashekar`](@ref), [`flux_kennedy_gruber`](@ref). # As surface flux you can use all volume fluxes and additionally for instance [`flux_lax_friedrichs`](@ref), # [`flux_hll`](@ref), [`flux_hllc`](@ref). + + +# ## Package versions + +# These results were obtained using the following versions. + +using InteractiveUtils +versioninfo() + +using Pkg +Pkg.status(["Trixi", "OrdinaryDiffEq", "Plots"], + mode=PKGMODE_MANIFEST) diff --git a/docs/literate/src/files/adaptive_mesh_refinement.jl b/docs/literate/src/files/adaptive_mesh_refinement.jl index d6150e887a8..46af8f79523 100644 --- a/docs/literate/src/files/adaptive_mesh_refinement.jl +++ b/docs/literate/src/files/adaptive_mesh_refinement.jl @@ -202,3 +202,15 @@ plot!(getmesh(pd)) # Source: Trixi.jl's YouTube channel [`Trixi Framework`](https://www.youtube.com/channel/UCpd92vU2HjjTPup-AIN0pkg) # For more information, please have a look at the respective links. + + +# ## Package versions + +# These results were obtained using the following versions. + +using InteractiveUtils +versioninfo() + +using Pkg +Pkg.status(["Trixi", "OrdinaryDiffEq", "Plots"], + mode=PKGMODE_MANIFEST) diff --git a/docs/literate/src/files/adding_new_parabolic_terms.jl b/docs/literate/src/files/adding_new_parabolic_terms.jl index 882f73f66ff..209ef62c988 100644 --- a/docs/literate/src/files/adding_new_parabolic_terms.jl +++ b/docs/literate/src/files/adding_new_parabolic_terms.jl @@ -18,8 +18,15 @@ equations_hyperbolic = LinearScalarAdvectionEquation2D(advection_velocity); # `ConstantAnisotropicDiffusion2D` has a field for `equations_hyperbolic`. It is useful to have # information about the hyperbolic system available to the parabolic part so that we can reuse # functions defined for hyperbolic equations (such as `varnames`). - -struct ConstantAnisotropicDiffusion2D{E, T} <: Trixi.AbstractEquationsParabolic{2, 1} +# +# The abstract type `Trixi.AbstractEquationsParabolic` has three parameters: `NDIMS` (the spatial dimension, +# e.g., 1D, 2D, or 3D), `NVARS` (the number of variables), and `GradientVariable`, which we set as +# `GradientVariablesConservative`. This indicates that the gradient should be taken with respect to the +# conservative variables (e.g., the same variables used in `equations_hyperbolic`). Users can also take +# the gradient with respect to a different set of variables; see, for example, the implementation of +# [`CompressibleNavierStokesDiffusion2D`](@ref), which can utilize either "primitive" or "entropy" variables. + +struct ConstantAnisotropicDiffusion2D{E, T} <: Trixi.AbstractEquationsParabolic{2, 1, GradientVariablesConservative} diffusivity::T equations_hyperbolic::E end @@ -158,3 +165,15 @@ sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, using Plots plot(sol) + +# ## Package versions + +# These results were obtained using the following versions. + +using InteractiveUtils +versioninfo() + +using Pkg +Pkg.status(["Trixi", "OrdinaryDiffEq", "Plots"], + mode=PKGMODE_MANIFEST) + diff --git a/docs/literate/src/files/adding_new_scalar_equations.jl b/docs/literate/src/files/adding_new_scalar_equations.jl index fec7bcf667a..a65b4de7f1a 100644 --- a/docs/literate/src/files/adding_new_scalar_equations.jl +++ b/docs/literate/src/files/adding_new_scalar_equations.jl @@ -211,3 +211,15 @@ semi = remake(semi, solver=DGSEM(3, flux_godunov, VolumeIntegralFluxDifferencing ode = semidiscretize(semi, (0.0, 0.5)) sol = solve(ode, SSPRK43(); ode_default_options()...) plot(sol) + + +# ## Package versions + +# These results were obtained using the following versions. + +using InteractiveUtils +versioninfo() + +using Pkg +Pkg.status(["Trixi", "OrdinaryDiffEq", "Plots"], + mode=PKGMODE_MANIFEST) diff --git a/docs/literate/src/files/adding_nonconservative_equation.jl b/docs/literate/src/files/adding_nonconservative_equation.jl index 110fa486070..b40e21fb11a 100644 --- a/docs/literate/src/files/adding_nonconservative_equation.jl +++ b/docs/literate/src/files/adding_nonconservative_equation.jl @@ -288,3 +288,15 @@ sol = solve(ode, Tsit5(), abstol=1.0e-6, reltol=1.0e-6, ## Plot the numerical solution at the final time using Plots: plot plot(sol); + + +# ## Package versions + +# These results were obtained using the following versions. + +using InteractiveUtils +versioninfo() + +using Pkg +Pkg.status(["Trixi", "OrdinaryDiffEq", "Plots"], + mode=PKGMODE_MANIFEST) diff --git a/docs/literate/src/files/custom_semidiscretization.jl b/docs/literate/src/files/custom_semidiscretization.jl new file mode 100644 index 00000000000..fd432fb0826 --- /dev/null +++ b/docs/literate/src/files/custom_semidiscretization.jl @@ -0,0 +1,324 @@ +#src # Custom semidiscretizations + +# As described in the [overview section](@ref overview-semidiscretizations), +# semidiscretizations are high-level descriptions of spatial discretizations +# in Trixi.jl. Trixi.jl's main focus is on hyperbolic conservation +# laws represented in a [`SemidiscretizationHyperbolic`](@ref). +# Hyperbolic-parabolic problems based on the advection-diffusion equation or +# the compressible Navier-Stokes equations can be represented in a +# [`SemidiscretizationHyperbolicParabolic`](@ref). This is described in the +# [basic tutorial on parabolic terms](@ref parabolic_terms) and its extension to +# [custom parabolic terms](@ref adding_new_parabolic_terms). +# In this tutorial, we will describe how these semidiscretizations work and how +# they can be used to create custom semidiscretizations involving also other tasks. + + +# ## Overview of the right-hand side evaluation + +# The semidiscretizations provided by Trixi.jl are set up to create `ODEProblem`s from the +# [SciML ecosystem for ordinary differential equations](https://diffeq.sciml.ai/latest/). +# In particular, a spatial semidiscretization can be wrapped in an ODE problem +# using [`semidiscretize`](@ref), which returns an `ODEProblem`. This `ODEProblem` +# bundles an initial condition, a right-hand side (RHS) function, the time span, +# and possible parameters. The `ODEProblem`s created by Trixi.jl use the semidiscretization +# passed to [`semidiscretize`](@ref) as a parameter. +# For a [`SemidiscretizationHyperbolic`](@ref), the `ODEProblem` wraps +# `Trixi.rhs!` as ODE RHS. +# For a [`SemidiscretizationHyperbolicParabolic`](@ref), Trixi.jl +# uses a `SplitODEProblem` combining `Trixi.rhs_parabolic!` for the +# (potentially) stiff part and `Trixi.rhs!` for the other part. + + +# ## Standard Trixi.jl setup + +# In this tutorial, we will consider the linear advection equation +# with source term +# ```math +# \partial_t u(t,x) + \partial_x u(t,x) = -\exp(-t) \sin\bigl(\pi (x - t) \bigr) +# ``` +# with periodic boundary conditions in the domain `[-1, 1]` as a +# model problem. +# The initial condition is +# ```math +# u(0,x) = \sin(\pi x). +# ``` +# The source term results in some damping and the analytical solution +# ```math +# u(t,x) = \exp(-t) \sin\bigl(\pi (x - t) \bigr). +# ``` +# First, we discretize this equation using the standard functionality +# of Trixi.jl. + +using Trixi, OrdinaryDiffEq, Plots + +# The linear scalar advection equation is already implemented in +# Trixi.jl as [`LinearScalarAdvectionEquation1D`](@ref). We construct +# it with an advection velocity `1.0`. + +equations = LinearScalarAdvectionEquation1D(1.0) + +# Next, we use a standard [`DGSEM`](@ref) solver. + +solver = DGSEM(polydeg = 3) + +# We create a simple [`TreeMesh`](@ref) in 1D. + +coordinates_min = (-1.0,) +coordinates_max = (+1.0,) +mesh = TreeMesh(coordinates_min, coordinates_max; + initial_refinement_level = 4, + n_cells_max = 10^4, + periodicity = true) + +# We wrap everything in in a semidiscretization and pass the source +# terms as a standard Julia function. Please note that Trixi.jl uses +# `SVector`s from +# [StaticArrays.jl](https://github.com/JuliaArrays/StaticArrays.jl) +# to store the conserved variables `u`. Thus, the return value of the +# source terms must be wrapped in an `SVector` - even if we consider +# just a scalar problem. + +function initial_condition(x, t, equations) + return SVector(exp(-t) * sinpi(x[1] - t)) +end + +function source_terms_standard(u, x, t, equations) + return -initial_condition(x, t, equations) +end + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, + solver; + source_terms = source_terms_standard) + +# Now, we can create the `ODEProblem`, solve the resulting ODE +# using a time integration method from +# [OrdinaryDiffEq.jl](https://github.com/SciML/OrdinaryDiffEq.jl), +# and visualize the numerical solution at the final time using +# [Plots.jl](https://github.com/JuliaPlots/Plots.jl). + +tspan = (0.0, 3.0) +ode = semidiscretize(semi, tspan) + +sol = solve(ode, RDPK3SpFSAL49(); ode_default_options()...) + +plot(sol; label = "numerical sol.", legend = :topright) + +# We can also plot the analytical solution for comparison. +# Since Trixi.jl uses `SVector`s for the variables, we take their `first` +# (and only) component to get the scalar value for manual plotting. + +let + x = range(-1.0, 1.0; length = 200) + plot!(x, first.(initial_condition.(x, sol.t[end], equations)), + label = "analytical sol.", linestyle = :dash, legend = :topright) +end + +# We can also add the initial condition to the plot. + +plot!(sol.u[1], semi, label = "u0", linestyle = :dot, legend = :topleft) + +# You can of course also use some +# [callbacks](https://trixi-framework.github.io/Trixi.jl/stable/callbacks/) +# provided by Trixi.jl as usual. + +summary_callback = SummaryCallback() +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi; interval = analysis_interval) +alive_callback = AliveCallback(; analysis_interval) +callbacks = CallbackSet(summary_callback, + analysis_callback, + alive_callback) + +sol = solve(ode, RDPK3SpFSAL49(); + ode_default_options()..., callback = callbacks) +summary_callback() + + +# ## Using a custom ODE right-hand side function + +# Next, we will solve the same problem but use our own ODE RHS function. +# To demonstrate this, we will artificially create a global variable +# containing the current time of the simulation. + +const GLOBAL_TIME = Ref(0.0) + +function source_terms_custom(u, x, t, equations) + t = GLOBAL_TIME[] + return -initial_condition(x, t, equations) +end + +# Next, we create our own RHS function to update the global time of +# the simulation before calling the RHS function from Trixi.jl. + +function rhs_source_custom!(du_ode, u_ode, semi, t) + GLOBAL_TIME[] = t + Trixi.rhs!(du_ode, u_ode, semi, t) +end + +# Next, we create an `ODEProblem` manually copying over the data from +# the one we got from [`semidiscretize`](@ref) earlier. + +ode_source_custom = ODEProblem(rhs_source_custom!, + ode.u0, + ode.tspan, + ode.p #= semi =#) +sol_source_custom = solve(ode_source_custom, RDPK3SpFSAL49(); + ode_default_options()...) + +plot(sol_source_custom; label = "numerical sol.") +let + x = range(-1.0, 1.0; length = 200) + plot!(x, first.(initial_condition.(x, sol_source_custom.t[end], equations)), + label = "analytical sol.", linestyle = :dash, legend = :topleft) +end +plot!(sol_source_custom.u[1], semi, label = "u0", linestyle = :dot, legend = :topleft) + +# This also works with callbacks as usual. + +summary_callback = SummaryCallback() +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi; interval = analysis_interval) +alive_callback = AliveCallback(; analysis_interval) +callbacks = CallbackSet(summary_callback, + analysis_callback, + alive_callback) + +sol = solve(ode_source_custom, RDPK3SpFSAL49(); + ode_default_options()..., callback = callbacks) +summary_callback() + + +# ## Setting up a custom semidiscretization + +# Using a global constant is of course not really nice from a software +# engineering point of view. Thus, it can often be useful to collect +# additional data in the parameters of the `ODEProblem`. Thus, it is +# time to create our own semidiscretization. Here, we create a small +# wrapper of a standard semidiscretization of Trixi.jl and the current +# global time of the simulation. + +struct CustomSemidiscretization{Semi, T} <: Trixi.AbstractSemidiscretization + semi::Semi + t::T +end + +semi_custom = CustomSemidiscretization(semi, Ref(0.0)) + +# To get pretty printing in the REPL, you can consider specializing +# +# - `Base.show(io::IO, parameters::CustomSemidiscretization)` +# - `Base.show(io::IO, ::MIME"text/plain", parameters::CustomSemidiscretization)` +# +# for your custom semidiscretiation. + +# Next, we create our own source terms that use the global time stored +# in the custom semidiscretiation. + +source_terms_custom_semi = let semi_custom = semi_custom + function source_terms_custom_semi(u, x, t, equations) + t = semi_custom.t[] + return -initial_condition(x, t, equations) + end +end + +# We also create a custom ODE RHS to update the current global time +# stored in the custom semidiscretization. We unpack the standard +# semidiscretization created by Trixi.jl and pass it to `Trixi.rhs!`. + +function rhs_semi_custom!(du_ode, u_ode, semi_custom, t) + semi_custom.t[] = t + Trixi.rhs!(du_ode, u_ode, semi_custom.semi, t) +end + +# Finally, we set up an `ODEProblem` and solve it numerically. + +ode_semi_custom = ODEProblem(rhs_semi_custom!, + ode.u0, + ode.tspan, + semi_custom) +sol_semi_custom = solve(ode_semi_custom, RDPK3SpFSAL49(); + ode_default_options()...) + +# If we want to make use of additional functionality provided by +# Trixi.jl, e.g., for plotting, we need to implement a few additional +# specializations. In this case, we forward everything to the standard +# semidiscretization provided by Trixi.jl wrapped in our custom +# semidiscretization. + +Base.ndims(semi::CustomSemidiscretization) = ndims(semi.semi) +function Trixi.mesh_equations_solver_cache(semi::CustomSemidiscretization) + Trixi.mesh_equations_solver_cache(semi.semi) +end + +# Now, we can plot the numerical solution as usual. + +plot(sol_semi_custom; label = "numerical sol.") +let + x = range(-1.0, 1.0; length = 200) + plot!(x, first.(initial_condition.(x, sol_semi_custom.t[end], equations)), + label = "analytical sol.", linestyle = :dash, legend = :topleft) +end +plot!(sol_semi_custom.u[1], semi, label = "u0", linestyle = :dot, legend = :topleft) + +# This also works with many callbacks as usual. However, the +# [`AnalysisCallback`](@ref) requires some special handling since it +# makes use of a performance counter contained in the standard +# semidiscretizations of Trixi.jl to report some +# [performance metrics](@ref performance-metrics). +# Here, we forward all accesses to the performance counter to the +# wrapped semidiscretization. + +function Base.getproperty(semi::CustomSemidiscretization, s::Symbol) + if s === :performance_counter + wrapped_semi = getfield(semi, :semi) + wrapped_semi.performance_counter + else + getfield(semi, s) + end +end + +# Moreover, the [`AnalysisCallback`](@ref) also performs some error +# calculations. We also need to forward them to the wrapped +# semidiscretization. + +function Trixi.calc_error_norms(func, u, t, analyzer, + semi::CustomSemidiscretization, + cache_analysis) + Trixi.calc_error_norms(func, u, t, analyzer, + semi.semi, + cache_analysis) +end + +# Now, we can work with the callbacks used before as usual. + +summary_callback = SummaryCallback() +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi_custom; + interval = analysis_interval) +alive_callback = AliveCallback(; analysis_interval) +callbacks = CallbackSet(summary_callback, + analysis_callback, + alive_callback) + +sol = solve(ode_semi_custom, RDPK3SpFSAL49(); + ode_default_options()..., callback = callbacks) +summary_callback() + +# For even more advanced usage of custom semidiscretizations, you +# may look at the source code of the ones contained in Trixi.jl, e.g., +# - [`SemidiscretizationHyperbolicParabolic`](@ref) +# - [`SemidiscretizationEulerGravity`](@ref) +# - [`SemidiscretizationEulerAcoustics`](@ref) +# - [`SemidiscretizationCoupled`](@ref) + + +# ## Package versions + +# These results were obtained using the following versions. + +using InteractiveUtils +versioninfo() + +using Pkg +Pkg.status(["Trixi", "OrdinaryDiffEq", "Plots"], + mode=PKGMODE_MANIFEST) diff --git a/docs/literate/src/files/differentiable_programming.jl b/docs/literate/src/files/differentiable_programming.jl index 5c5a7cd7440..0960ba25d9f 100644 --- a/docs/literate/src/files/differentiable_programming.jl +++ b/docs/literate/src/files/differentiable_programming.jl @@ -43,7 +43,7 @@ scatter(real.(λ), imag.(λ), label="central flux") # As you can see here, the maximal real part is close to zero. relative_maximum = maximum(real, λ) / maximum(abs, λ) -@test 3.0e-10 < relative_maximum < 8.0e-10 #src +@test 3.0e-10 < relative_maximum < 9.0e-10 #src # Interestingly, if we add dissipation by switching to the `flux_lax_friedrichs` # at the interfaces, the maximal real part of the eigenvalues increases. @@ -87,7 +87,7 @@ scatter(real.(λ), imag.(λ), label="central flux") # Here, the maximal real part is basically zero to machine accuracy. relative_maximum = maximum(real, λ) / maximum(abs, λ) -@test 1.0e-17 < relative_maximum < 1.0e-15 #src +@test 1.0e-17 < relative_maximum < 2.0e-15 #src # Moreover, the eigenvectors are not as ill-conditioned as in 2D. @@ -446,3 +446,15 @@ scatter(real.(λ), imag.(λ)) λ = eigvals(Matrix(A)) relative_maximum = maximum(real, λ) / maximum(abs, λ) @test relative_maximum < 1.0e-15 #src + + +# ## Package versions + +# These results were obtained using the following versions. + +using InteractiveUtils +versioninfo() + +using Pkg +Pkg.status(["Trixi", "OrdinaryDiffEq", "Plots", "ForwardDiff"], + mode=PKGMODE_MANIFEST) diff --git a/docs/literate/src/files/hohqmesh_tutorial.jl b/docs/literate/src/files/hohqmesh_tutorial.jl index 87076108d91..b19d363c4bf 100644 --- a/docs/literate/src/files/hohqmesh_tutorial.jl +++ b/docs/literate/src/files/hohqmesh_tutorial.jl @@ -566,3 +566,15 @@ mesh = UnstructuredMesh2D(mesh_file); # for details. # ![simulation_straight_sides_p4est_amr](https://user-images.githubusercontent.com/74359358/168049930-8abce6ac-cd47-4d04-b40b-0fa459bbd98d.png) + + +# ## Package versions + +# These results were obtained using the following versions. + +using InteractiveUtils +versioninfo() + +using Pkg +Pkg.status(["Trixi", "OrdinaryDiffEq", "Plots", "Trixi2Vtk", "HOHQMesh"], + mode=PKGMODE_MANIFEST) diff --git a/docs/literate/src/files/index.jl b/docs/literate/src/files/index.jl index 0c8de66bf42..d42695611f6 100644 --- a/docs/literate/src/files/index.jl +++ b/docs/literate/src/files/index.jl @@ -76,21 +76,30 @@ # In this part, another physics model is implemented, the nonconservative linear advection equation. # We run two different simulations with different levels of refinement and compare the resulting errors. -# ### [10 Adaptive mesh refinement](@ref adaptive_mesh_refinement) +# ### [10 Parabolic terms](@ref parabolic_terms) +#- +# This tutorial describes how parabolic terms are implemented in Trixi.jl, e.g., +# to solve the advection-diffusion equation. + +# ### [11 Adding new parabolic terms](@ref adding_new_parabolic_terms) +#- +# This tutorial describes how new parabolic terms can be implemented using Trixi.jl. + +# ### [12 Adaptive mesh refinement](@ref adaptive_mesh_refinement) #- # Adaptive mesh refinement (AMR) helps to increase the accuracy in sensitive or turbolent regions while # not wasting resources for less interesting parts of the domain. This leads to much more efficient # simulations. This tutorial presents the implementation strategy of AMR in Trixi.jl, including the use of # different indicators and controllers. -# ### [11 Structured mesh with curvilinear mapping](@ref structured_mesh_mapping) +# ### [13 Structured mesh with curvilinear mapping](@ref structured_mesh_mapping) #- # In this tutorial, the use of Trixi.jl's structured curved mesh type [`StructuredMesh`](@ref) is explained. # We present the two basic option to initialize such a mesh. First, the curved domain boundaries # of a circular cylinder are set by explicit boundary functions. Then, a fully curved mesh is # defined by passing the transformation mapping. -# ### [12 Unstructured meshes with HOHQMesh.jl](@ref hohqmesh_tutorial) +# ### [14 Unstructured meshes with HOHQMesh.jl](@ref hohqmesh_tutorial) #- # The purpose of this tutorial is to demonstrate how to use the [`UnstructuredMesh2D`](@ref) # functionality of Trixi.jl. This begins by running and visualizing an available unstructured @@ -99,19 +108,24 @@ # software in the Trixi.jl ecosystem, and then run a simulation using Trixi.jl on said mesh. # In the end, the tutorial briefly explains how to simulate an example using AMR via `P4estMesh`. -# ### [13 Explicit time stepping](@ref time_stepping) +# ### [15 Explicit time stepping](@ref time_stepping) #- # This tutorial is about time integration using [OrdinaryDiffEq.jl](https://github.com/SciML/OrdinaryDiffEq.jl). # It explains how to use their algorithms and presents two types of time step choices - with error-based # and CFL-based adaptive step size control. -# ### [14 Differentiable programming](@ref differentiable_programming) +# ### [16 Differentiable programming](@ref differentiable_programming) #- # This part deals with some basic differentiable programming topics. For example, a Jacobian, its # eigenvalues and a curve of total energy (through the simulation) are calculated and plotted for # a few semidiscretizations. Moreover, we calculate an example for propagating errors with Measurement.jl # at the end. +# ### [17 Custom semidiscretization](@ref custom_semidiscretization) +#- +# This tutorial describes the [semidiscretiations](@ref overview-semidiscretizations) of Trixi.jl +# and explains how to extend them for custom tasks. + # ## Examples in Trixi.jl diff --git a/docs/literate/src/files/non_periodic_boundaries.jl b/docs/literate/src/files/non_periodic_boundaries.jl index 54da88a64aa..7ed6324ff99 100644 --- a/docs/literate/src/files/non_periodic_boundaries.jl +++ b/docs/literate/src/files/non_periodic_boundaries.jl @@ -155,3 +155,15 @@ end #
# ``` # Source: [`Video`](https://www.youtube.com/watch?v=w0A9X38cSe4) on Trixi.jl's YouTube channel [`Trixi Framework`](https://www.youtube.com/watch?v=WElqqdMhY4A) + + +# ## Package versions + +# These results were obtained using the following versions. + +using InteractiveUtils +versioninfo() + +using Pkg +Pkg.status(["Trixi", "OrdinaryDiffEq", "Plots"], + mode=PKGMODE_MANIFEST) diff --git a/docs/literate/src/files/parabolic_terms.jl b/docs/literate/src/files/parabolic_terms.jl index bac0098f8e9..d0a355bbc19 100644 --- a/docs/literate/src/files/parabolic_terms.jl +++ b/docs/literate/src/files/parabolic_terms.jl @@ -86,3 +86,14 @@ sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, using Plots plot(sol) + +# ## Package versions + +# These results were obtained using the following versions. + +using InteractiveUtils +versioninfo() + +using Pkg +Pkg.status(["Trixi", "OrdinaryDiffEq", "Plots"], + mode=PKGMODE_MANIFEST) diff --git a/docs/literate/src/files/scalar_linear_advection_1d.jl b/docs/literate/src/files/scalar_linear_advection_1d.jl index 42c831c98ba..77ba7b087cc 100644 --- a/docs/literate/src/files/scalar_linear_advection_1d.jl +++ b/docs/literate/src/files/scalar_linear_advection_1d.jl @@ -511,3 +511,15 @@ sol_trixi = solve(ode_trixi, RDPK3SpFSAL49(); abstol=1.0e-6, reltol=1.0e-6, ode plot!(sol_trixi, label="solution at t=$(tspan[2]) with Trixi.jl", legend=:topleft, linestyle=:dash, lw=2) @test maximum(abs.(vec(u0) - sol_trixi.u[end])) ≈ maximum(abs.(u0 - sol.u[end])) #src + + +# ## Package versions + +# These results were obtained using the following versions. + +using InteractiveUtils +versioninfo() + +using Pkg +Pkg.status(["Trixi", "OrdinaryDiffEq", "Plots"], + mode=PKGMODE_MANIFEST) diff --git a/docs/literate/src/files/shock_capturing.jl b/docs/literate/src/files/shock_capturing.jl index afa34cbf06a..dd6698c2a86 100644 --- a/docs/literate/src/files/shock_capturing.jl +++ b/docs/literate/src/files/shock_capturing.jl @@ -224,3 +224,15 @@ sol = solve(ode, CarpenterKennedy2N54(stage_limiter!, williamson_condition=false using Plots plot(sol) + + +# ## Package versions + +# These results were obtained using the following versions. + +using InteractiveUtils +versioninfo() + +using Pkg +Pkg.status(["Trixi", "OrdinaryDiffEq", "Plots"], + mode=PKGMODE_MANIFEST) diff --git a/docs/literate/src/files/structured_mesh_mapping.jl b/docs/literate/src/files/structured_mesh_mapping.jl index 0ae9cf723f8..c8da30bc2bf 100644 --- a/docs/literate/src/files/structured_mesh_mapping.jl +++ b/docs/literate/src/files/structured_mesh_mapping.jl @@ -201,3 +201,15 @@ plot!(getmesh(pd)) # unstructured mesh type [`UnstructuredMesh2D`] and its use of the # [High-Order Hex-Quad Mesh (HOHQMesh) generator](https://github.com/trixi-framework/HOHQMesh), # created and developed by David Kopriva. + + +# ## Package versions + +# These results were obtained using the following versions. + +using InteractiveUtils +versioninfo() + +using Pkg +Pkg.status(["Trixi", "OrdinaryDiffEq", "Plots"], + mode=PKGMODE_MANIFEST) diff --git a/docs/literate/src/files/time_stepping.jl b/docs/literate/src/files/time_stepping.jl index d400c4a94be..de7a2a83a41 100644 --- a/docs/literate/src/files/time_stepping.jl +++ b/docs/literate/src/files/time_stepping.jl @@ -49,7 +49,7 @@ # ```math # \Delta t_n = \text{CFL} * \min_i \frac{\Delta x_i}{\lambda_{\max}(u_i^n)} # ``` -# We compute $\Delta x_i$ by scaling the element size by a factor of $1/(N+1)$, cf. +# We compute $\Delta x_i$ by scaling the element size by a factor of $1/(N+1)$, cf. # [Gassner and Kopriva (2011)](https://doi.org/10.1137/100807211), Section 5. # Trixi.jl provides such a CFL-based step size control. It is implemented as the callback @@ -73,3 +73,15 @@ # You can find simple examples with a CFL-based step size control for instance in the elixirs # [`elixir_advection_basic.jl`](https://github.com/trixi-framework/Trixi.jl/blob/main/examples/tree_2d_dgsem/elixir_advection_basic.jl) # or [`elixir_euler_source_terms.jl`](https://github.com/trixi-framework/Trixi.jl/blob/main/examples/tree_2d_dgsem/elixir_euler_source_terms.jl). + + +# ## Package versions + +# These results were obtained using the following versions. + +using InteractiveUtils +versioninfo() + +using Pkg +Pkg.status(["Trixi", "OrdinaryDiffEq"], + mode=PKGMODE_MANIFEST) diff --git a/docs/literate/src/files/upwind_fdsbp.jl b/docs/literate/src/files/upwind_fdsbp.jl index 36ca1b57404..6d3379fa30d 100644 --- a/docs/literate/src/files/upwind_fdsbp.jl +++ b/docs/literate/src/files/upwind_fdsbp.jl @@ -62,3 +62,15 @@ Matrix(D_upw.plus) # flux vector splitting, e.g., # - [`elixir_euler_vortex.jl`](https://github.com/trixi-framework/Trixi.jl/blob/main/examples/tree_2d_fdsbp/elixir_euler_vortex.jl) # - [`elixir_euler_taylor_green_vortex.jl`](https://github.com/trixi-framework/Trixi.jl/blob/main/examples/tree_3d_fdsbp/elixir_euler_taylor_green_vortex.jl) + + +# ## Package versions + +# These results were obtained using the following versions. + +using InteractiveUtils +versioninfo() + +using Pkg +Pkg.status(["Trixi", "SummationByPartsOperators"], + mode=PKGMODE_MANIFEST) diff --git a/docs/make.jl b/docs/make.jl index 57629577ddb..df8ac04be12 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -68,6 +68,7 @@ files = [ # Topic: other stuff "Explicit time stepping" => "time_stepping.jl", "Differentiable programming" => "differentiable_programming.jl", + "Custom semidiscretizations" => "custom_semidiscretization.jl" ] tutorials = create_tutorials(files) @@ -76,7 +77,7 @@ makedocs( # Specify modules for which docstrings should be shown modules = [Trixi, Trixi2Vtk], # Set sitename to Trixi.jl - sitename="Trixi.jl", + sitename = "Trixi.jl", # Provide additional formatting options format = Documenter.HTML( # Disable pretty URLs during manual testing @@ -84,7 +85,8 @@ makedocs( # Explicitly add favicon as asset assets = ["assets/favicon.ico"], # Set canonical URL to GitHub pages URL - canonical = "https://trixi-framework.github.io/Trixi.jl/stable" + canonical = "https://trixi-framework.github.io/Trixi.jl/stable", + size_threshold_ignore = ["reference-trixi.md"] ), # Explicitly specify documentation structure pages = [ @@ -123,9 +125,8 @@ makedocs( "Authors" => "authors.md", "Contributing" => "contributing.md", "Code of Conduct" => "code_of_conduct.md", - "License" => "license.md" - ], - strict = true # to make the GitHub action fail when doctests fail, see https://github.com/neuropsychology/Psycho.jl/issues/34 + "License" => "license.md", + ] ) deploydocs( diff --git a/docs/src/callbacks.md b/docs/src/callbacks.md index 1d3e5e34b51..f018bcf7c39 100644 --- a/docs/src/callbacks.md +++ b/docs/src/callbacks.md @@ -30,7 +30,12 @@ An example elixir using AMR can be found at [`examples/tree_2d_dgsem/elixir_adve The [`AnalysisCallback`](@ref) can be used to analyze the numerical solution, e.g. calculate errors or user-specified integrals, and print the results to the screen. The results can also be saved in a file. An example can be found at [`examples/tree_2d_dgsem/elixir_euler_vortex.jl`](https://github.com/trixi-framework/Trixi.jl/blob/main/examples/tree_2d_dgsem/elixir_euler_vortex.jl). -In [Performance metrics of the `AnalysisCallback`](@ref) you can find a detailed +Note that the errors (e.g. `L2 error` or `Linf error`) are computed with respect to the initial condition. +The percentage of the simulation time refers to the ratio of the current time and the final time, i.e. it does +not consider the maximal number of iterations. So the simulation could finish before 100% are reached. +Note that, e.g., due to AMR or smaller time step sizes, the simulation can actually take longer than +the percentage indicates. +In [Performance metrics of the `AnalysisCallback`](@ref performance-metrics) you can find a detailed description of the different performance metrics the `AnalysisCallback` computes. ### I/O @@ -106,7 +111,7 @@ will yield the following plot: the automated performance measurements, including an output of the recorded timers after a simulation. * The [`VisualizationCallback`](@ref) can be used for in-situ visualization. See [Visualizing results during a simulation](@ref). -* The [`TrivialCallback`](@ref) does nothing and can be used to to easily disable some callbacks +* The [`TrivialCallback`](@ref) does nothing and can be used to easily disable some callbacks via [`trixi_include`](@ref). ### Equation-specific callbacks diff --git a/docs/src/index.md b/docs/src/index.md index 3af785bc681..fbb4b36b224 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -7,11 +7,12 @@ [![Build Status](https://github.com/trixi-framework/Trixi.jl/workflows/CI/badge.svg)](https://github.com/trixi-framework/Trixi.jl/actions?query=workflow%3ACI) [![Codecov](https://codecov.io/gh/trixi-framework/Trixi.jl/branch/main/graph/badge.svg)](https://codecov.io/gh/trixi-framework/Trixi.jl) [![Coveralls](https://coveralls.io/repos/github/trixi-framework/Trixi.jl/badge.svg?branch=main)](https://coveralls.io/github/trixi-framework/Trixi.jl?branch=main) +[![Aqua QA](https://raw.githubusercontent.com/JuliaTesting/Aqua.jl/master/badge.svg)](https://github.com/JuliaTesting/Aqua.jl) [![License: MIT](https://img.shields.io/badge/License-MIT-success.svg)](https://opensource.org/licenses/MIT) [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.3996439.svg)](https://doi.org/10.5281/zenodo.3996439) [**Trixi.jl**](https://github.com/trixi-framework/Trixi.jl) -is a numerical simulation framework for hyperbolic conservation +is a numerical simulation framework for conservation laws written in [Julia](https://julialang.org). 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 @@ -39,6 +40,7 @@ installation and postprocessing procedures. Its features include: * Periodic and weakly-enforced boundary conditions * Multiple governing equations: * Compressible Euler equations + * Compressible Navier-Stokes equations * Magnetohydrodynamics (MHD) equations * Multi-component compressible Euler and MHD equations * Linearized Euler and acoustic perturbation equations @@ -49,6 +51,7 @@ installation and postprocessing procedures. Its features include: * Multi-physics simulations * [Self-gravitating gas dynamics](https://github.com/trixi-framework/paper-self-gravitating-gas-dynamics) * Shared-memory parallelization via multithreading +* Multi-node parallelization via MPI * Visualization and postprocessing of the results * In-situ and a posteriori visualization with [Plots.jl](https://github.com/JuliaPlots/Plots.jl) * Interactive visualization with [Makie.jl](https://makie.juliaplots.org/) @@ -324,7 +327,7 @@ Schlottke-Lakemper](https://lakemper.eu) (RWTH Aachen University/High-Performance Computing Center Stuttgart (HLRS), Germany) and [Gregor Gassner](https://www.mi.uni-koeln.de/NumSim/gregor-gassner) (University of Cologne, Germany). Together with [Hendrik Ranocha](https://ranocha.de) -(University of Hamburg, Germany) and [Andrew Winters](https://liu.se/en/employee/andwi94) +(Johannes Gutenberg University Mainz, Germany) and [Andrew Winters](https://liu.se/en/employee/andwi94) (Linköping University, Sweden), and [Jesse Chan](https://jlchan.github.io) (Rice University, US), they are the principal developers of Trixi.jl. The full list of contributors can be found under [Authors](@ref). @@ -343,29 +346,58 @@ or [create an issue](https://github.com/trixi-framework/Trixi.jl/issues/new). ## Acknowledgments -![funding-logo](https://user-images.githubusercontent.com/3637659/233821022-84910be7-8649-4999-a0ff-22d5e20f0b90.jpg) - -This project has benefited from funding by the Deutsche Forschungsgemeinschaft (DFG, German Research Foundation) -under Germany's Excellence Strategy EXC 2044-390685587, Mathematics Münster: -Dynamics-Geometry-Structure. +```@raw html +
+
+
+
+
+
+
+
+``` -This project has benefited from funding by the Deutsche Forschungsgemeinschaft (DFG, German Research Foundation) -through the research unit FOR 5409 "Structure-Preserving Numerical Methods for Bulk- and -Interface Coupling of Heterogeneous Models (SNuBIC)" (project number 463312734). +This project has benefited from funding by the [Deutsche +Forschungsgemeinschaft](https://www.dfg.de/) (DFG, German Research Foundation) +through the following grants: +* Excellence Strategy EXC 2044-390685587, Mathematics Münster: Dynamics-Geometry-Structure. +* Research unit FOR 5409 "Structure-Preserving Numerical Methods for Bulk- and + Interface Coupling of Heterogeneous Models (SNuBIC)" (project number 463312734). +* Individual grant no. 528753982. -This project has benefited from funding from the European Research Council through the +This project has benefited from funding from the [European Research Council](https://erc.europa.eu) +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 +This project has benefited from funding from [Vetenskapsrådet](https://www.vr.se) +(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 under awards +This project has benefited from funding from the United States +[National Science Foundation](https://www.nsf.gov/) (NSF) under awards DMS-1719818 and DMS-1943186. -This project has benefited from funding from the German Federal Ministry of -Education and Research through the project grant "Adaptive earth system modeling +This project has benefited from funding from the German +[Federal Ministry of Education and Research](https://www.bmbf.de) (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](https://www.daimler-benz-stiftung.de) (Daimler and Benz Foundation) +through grant no. 32-10/22. + +Trixi.jl is supported by [NumFOCUS](https://numfocus.org/) as an Affiliated Project. diff --git a/docs/src/meshes/dgmulti_mesh.md b/docs/src/meshes/dgmulti_mesh.md index fc086bba146..efa71334bf8 100644 --- a/docs/src/meshes/dgmulti_mesh.md +++ b/docs/src/meshes/dgmulti_mesh.md @@ -21,7 +21,7 @@ around Jonathan Shewchuk's [Triangle](https://www.cs.cmu.edu/~quake/triangle.htm ## The `DGMulti` solver type -Trixi.jl solvers on simplicial meshes use the `[DGMulti](@ref)` solver type, which allows users to specify +Trixi.jl solvers on simplicial meshes use the [`DGMulti`](@ref) solver type, which allows users to specify `element_type` and `approximation_type` in addition to `polydeg`, `surface_flux`, `surface_integral`, and `volume_integral`. diff --git a/docs/src/overview.md b/docs/src/overview.md index 46bc28b6025..9bc523ca297 100644 --- a/docs/src/overview.md +++ b/docs/src/overview.md @@ -16,7 +16,7 @@ to solve a PDE numerically are the spatial semidiscretization and the time integration scheme. -## Semidiscretizations +## [Semidiscretizations](@id overview-semidiscretizations) Semidiscretizations are high-level descriptions of spatial discretizations specialized for certain PDEs. Trixi.jl's main focus is on hyperbolic conservation @@ -55,14 +55,14 @@ different features on different mesh types. | Element type | line, square, cube | line, quadᵃ, hexᵃ | quadᵃ | quadᵃ, hexᵃ | simplex, quadᵃ, hexᵃ | | Adaptive mesh refinement | ✅ | ❌ | ❌ | ✅ | ❌ | [`AMRCallback`](@ref) | Solver type | [`DGSEM`](@ref) | [`DGSEM`](@ref) | [`DGSEM`](@ref) | [`DGSEM`](@ref) | [`DGMulti`](@ref) | -| Domain | hypercube | mapped hypercube | arbitrary | arbitrary | arbitraryᵇ | +| Domain | hypercube | mapped hypercube | arbitrary | arbitrary | arbitrary | | Weak form | ✅ | ✅ | ✅ | ✅ | ✅ | [`VolumeIntegralWeakForm`](@ref) | Flux differencing | ✅ | ✅ | ✅ | ✅ | ✅ | [`VolumeIntegralFluxDifferencing`](@ref) | Shock capturing | ✅ | ✅ | ✅ | ✅ | ❌ | [`VolumeIntegralShockCapturingHG`](@ref) | Nonconservative equations | ✅ | ✅ | ✅ | ✅ | ✅ | e.g., GLM MHD or shallow water equations +| Parabolic terms | ✅ | ✅ | ❌ | ✅ | ✅ | e.g., [`CompressibleNavierStokesDiffusion2D`](@ref) ᵃ: quad = quadrilateral, hex = hexahedron -ᵇ: curved meshes supported for `SBP` and `GaussSBP` approximation types for `VolumeIntegralFluxDifferencing` solvers on quadrilateral and hexahedral `DGMultiMesh`es (non-conservative terms not yet supported) ## Time integration methods diff --git a/docs/src/parallelization.md b/docs/src/parallelization.md index 08470fd064a..f599eb5fafe 100644 --- a/docs/src/parallelization.md +++ b/docs/src/parallelization.md @@ -22,7 +22,7 @@ julia --threads=4 If both the environment variable and the command line argument are specified at the same time, the latter takes precedence. -If you use time integration methods from +If you use time integration methods from [OrdinaryDiffEq.jl](https://github.com/SciML/OrdinaryDiffEq.jl) and want to use multiple threads therein, you need to set the keyword argument `thread=OrdinaryDiffEq.True()` of the algorithms, as described in the @@ -53,17 +53,79 @@ a system-provided MPI installation with Trixi.jl can be found in the following s ### [Using a system-provided MPI installation](@id parallel_system_MPI) -When using Trixi.jl with a system-provided MPI backend the underlying [`p4est`](https://github.com/cburstedde/p4est) -library needs to be compiled with the same MPI installation. Therefore, you also need to use -a system-provided `p4est` installation (for notes on how to install `p4est` see e.g. -[here](https://github.com/cburstedde/p4est/blob/master/README), use the configure option -`--enable-mpi`). In addition, [P4est.jl](https://github.com/trixi-framework/P4est.jl) needs to -be configured to use the custom `p4est` installation. Follow the steps described -[here](https://github.com/trixi-framework/P4est.jl/blob/main/README.md) for the configuration. -In total, in your active Julia project you should have a LocalPreferences.toml file with sections -`[MPIPreferences]` and `[P4est]` as well as an entry `MPIPreferences` in your Project.toml to -use a custom MPI installation. +When using Trixi.jl with a system-provided MPI backend, the underlying +[`p4est`](https://github.com/cburstedde/p4est), [`t8code`](https://github.com/DLR-AMR/t8code) +and [`HDF5`](https://github.com/HDFGroup/hdf5) libraries need to be compiled with the same MPI +installation. If you want to use `p4est` (via the `P4estMesh`) or `t8code` (via the `T8codeMesh`) +from Trixi.jl, you also need to use system-provided `p4est` or `t8code` installations +(for notes on how to install `p4est` and `t8code` see, e.g., [here](https://github.com/cburstedde/p4est/blob/master/README) +and [here](https://github.com/DLR-AMR/t8code/wiki/Installation), use the configure option +`--enable-mpi`). Otherwise, there will be warnings that no preference is set for P4est.jl and +T8code.jl that can be ignored if you do not use these libraries from Trixi.jl. Note that +`t8code` already comes with a `p4est` installation, so it suffices to install `t8code`. +In order to use system-provided `p4est` and `t8code` installations, [P4est.jl](https://github.com/trixi-framework/P4est.jl) +and [T8code.jl](https://github.com/DLR-AMR/T8code.jl) need to be configured to use the custom +installations. Follow the steps described [here](https://github.com/DLR-AMR/T8code.jl/blob/main/README.md#installation) and +[here](https://github.com/trixi-framework/P4est.jl/blob/main/README.md#installation) for the configuration. +The paths that point to `libp4est.so` (and potentially to `libsc.so`) need to be +the same for P4est.jl and T8code.jl. This could, e.g., be `libp4est.so` that usually can be found +in `lib/` or `local/lib/` in the installation directory of `t8code`. Note that the `T8codeMesh`, however, +does not support MPI yet. +The preferences for [HDF5.jl](https://github.com/JuliaIO/HDF5.jl) always need to be set, even if you +do not want to use `HDF5` from Trixi.jl, see also [issue #1079 in HDF5.jl](https://github.com/JuliaIO/HDF5.jl/issues/1079). +To set the preferences for HDF5.jl, follow the instructions described +[here](https://trixi-framework.github.io/Trixi.jl/stable/parallelization/#Using-parallel-input-and-output). +In total, in your active Julia project you should have a `LocalPreferences.toml` file with sections +`[MPIPreferences]`, `[T8code]` (only needed if `T8codeMesh` is used), `[P4est]` (only needed if +`P4estMesh` is used), and `[HDF5]` as well as an entry `MPIPreferences` in your +`Project.toml` to use a custom MPI installation. A `LocalPreferences.toml` file +created as described above might look something like the following: +```toml +[HDF5] +libhdf5 = "/usr/lib/x86_64-linux-gnu/hdf5/openmpi/libhdf5.so" +libhdf5_hl = "/usr/lib/x86_64-linux-gnu/hdf5/openmpi/libhdf5_hl.so" + +[HDF5_jll] +libhdf5_hl_path = "/usr/lib/x86_64-linux-gnu/hdf5/openmpi/libhdf5_hl.so" +libhdf5_path = "/usr/lib/x86_64-linux-gnu/hdf5/openmpi/libhdf5.so" + +[MPIPreferences] +__clear__ = ["preloads_env_switch"] +_format = "1.0" +abi = "OpenMPI" +binary = "system" +cclibs = [] +libmpi = "/lib/x86_64-linux-gnu/libmpi.so" +mpiexec = "mpiexec" +preloads = [] + +[P4est] +libp4est = "/home/mschlott/hackathon/libtrixi/t8code/install/lib/libp4est.so" +libsc = "/home/mschlott/hackathon/libtrixi/t8code/install/lib/libsc.so" + +[T8code] +libp4est = "/home/mschlott/hackathon/libtrixi/t8code/install/lib/libp4est.so" +libsc = "/home/mschlott/hackathon/libtrixi/t8code/install/lib/libsc.so" +libt8 = "/home/mschlott/hackathon/libtrixi/t8code/install/lib/libt8.so" +``` + +This file is created with the following sequence of commands: +```julia +julia> using MPIPreferences +julia> MPIPreferences.use_system_binary() +``` +Restart the Julia REPL +```julia +julia> using P4est +julia> P4est.set_library_p4est!("/home/mschlott/hackathon/libtrixi/t8code/install/lib/libp4est.so") +julia> P4est.set_library_sc!("/home/mschlott/hackathon/libtrixi/t8code/install/lib/libsc.so") +julia> using T8code +julia> T8code.set_libraries_path!("/home/mschlott/hackathon/libtrixi/t8code/install/lib/") +julia> using HDF5 +julia> HDF5.API.set_libraries!("/usr/lib/x86_64-linux-gnu/hdf5/openmpi/libhdf5.so", "/usr/lib/x86_64-linux-gnu/hdf5/openmpi/libhdf5_hl.so") +``` +After the preferences are set, restart the Julia REPL again. ### [Usage](@id parallel_usage) @@ -135,7 +197,7 @@ To start Trixi.jl in parallel with MPI, there are three options: Switching between panes can be done by `Ctrl+b` followed by `o`. As of March 2022, newer versions of tmpi also support mpich, which is the default backend of MPI.jl (via MPICH_Jll.jl). To use this setup, you need to install - `mpiexecjl` as described in the + `mpiexecjl` as described in the [documentation of MPI.jl](https://juliaparallel.org/MPI.jl/v0.20/usage/#Julia-wrapper-for-mpiexec) and make it available as `mpirun`, e.g., via a symlink of the form ```bash @@ -153,22 +215,46 @@ To start Trixi.jl in parallel with MPI, there are three options: ### [Performance](@id parallel_performance) For information on how to evaluate the parallel performance of Trixi.jl, please -have a look at the [Performance metrics of the `AnalysisCallback`](@ref) +have a look at the [Performance metrics of the `AnalysisCallback`](@ref performance-metrics) section, specifically at the descriptions of the performance index (PID). ### Using error-based step size control with MPI -If you use error-based step size control (see also the section on [error-based adaptive step sizes](@ref 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`](https://docs.sciml.ai/DiffEqDocs/latest/basics/common_solver_opts/), +If you use error-based step size control (see also the section on +[error-based adaptive step sizes](@ref 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`](https://docs.sciml.ai/DiffEqDocs/latest/basics/common_solver_opts/), which are both included in [`ode_default_options`](@ref). ### Using parallel input and output -Trixi.jl allows parallel I/O using MPI by leveraging parallel HDF5.jl. To enable this, you first need -to use a system-provided MPI library, see also [here](@ref parallel_system_MPI) and you need to tell -[HDF5.jl](https://github.com/JuliaIO/HDF5.jl) to use this library. -To do so, set the environment variable `JULIA_HDF5_PATH` to the local path -that contains the `libhdf5.so` shared object file and build HDF5.jl by executing `using Pkg; Pkg.build("HDF5")`. -For more information see also the [documentation of HDF5.jl](https://juliaio.github.io/HDF5.jl/stable/mpi/). - -If you do not perform these steps to use parallel HDF5 or if the 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. +Trixi.jl allows parallel I/O using MPI by leveraging parallel HDF5.jl. On most systems, this is +enabled by default. Additionally, you can also use a local installation of the HDF5 library +(with MPI support). For this, you first need to use a system-provided MPI library, see also +[here](@ref parallel_system_MPI) and you need to tell [HDF5.jl](https://github.com/JuliaIO/HDF5.jl) +to use this library. To do so with HDF5.jl v0.17 and newer, set the preferences `libhdf5` and +`libhdf5_hl` to the local paths of the libraries `libhdf5` and `libhdf5_hl`, which can be done by +```julia +julia> using Preferences, UUIDs +julia> set_preferences!( + 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 +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](https://juliaio.github.io/HDF5.jl/stable/mpi/). 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/docs/src/performance.md b/docs/src/performance.md index 428672ec75f..df66f451b79 100644 --- a/docs/src/performance.md +++ b/docs/src/performance.md @@ -34,7 +34,7 @@ Hence, you should at least investigate the performance roughly by comparing the timings of several elixirs. Deeper investigations and micro-benchmarks should usually use [BenchmarkTools.jl](https://github.com/JuliaCI/BenchmarkTools.jl). For example, the following steps were used to benchmark the changes introduced in -https://github.com/trixi-framework/Trixi.jl/pull/256. +[PR #256](https://github.com/trixi-framework/Trixi.jl/pull/256). 1. `git checkout e7ebf3846b3fd62ee1d0042e130afb50d7fe8e48` (new version) 2. Start `julia --threads=1 --check-bounds=no`. @@ -170,7 +170,7 @@ As a rule of thumb: - Consider using `@nospecialize` for methods like custom implementations of `Base.show`. -## Performance metrics of the `AnalysisCallback` +## [Performance metrics of the `AnalysisCallback`](@id performance-metrics) The [`AnalysisCallback`](@ref) 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 diff --git a/docs/src/restart.md b/docs/src/restart.md index 767269ff27d..c7cbcd11852 100644 --- a/docs/src/restart.md +++ b/docs/src/restart.md @@ -77,8 +77,7 @@ and its time step number, e.g.: ```julia integrator = init(ode, CarpenterKennedy2N54(williamson_condition=false), dt=dt, save_everystep=false, callback=callbacks); -integrator.iter = load_timestep(restart_filename) -integrator.stats.naccept = integrator.iter +load_timestep!(integrator, restart_filename) ``` Now we can compute the solution: diff --git a/docs/src/styleguide.md b/docs/src/styleguide.md index 60e227204ca..2f28dbfcb17 100644 --- a/docs/src/styleguide.md +++ b/docs/src/styleguide.md @@ -17,11 +17,11 @@ conventions, we apply and enforce automated source code formatting * Maximum line length (strictly): **92**. * Functions that mutate their *input* are named with a trailing `!`. * Functions order their parameters [similar to Julia Base](https://docs.julialang.org/en/v1/manual/style-guide/#Write-functions-with-argument-ordering-similar-to-Julia-Base-1). - * 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!` + * 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 + * 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. @@ -55,7 +55,7 @@ julia -e 'using Pkg; Pkg.add("JuliaFormatter")' ``` You can then recursively format the core Julia files in the Trixi.jl repo by executing ```shell -julia -e 'using JuliaFormatter; format(["benchmark", "ext", "src", "utils"])' +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 @@ -67,12 +67,12 @@ You can get more information about using the convenience script by running it wi `--help`/`-h` flag. ### Checking formatting before committing -It can be convenient to check the formatting of source code automatically before each commit. +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](https://github.com/domluna/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 +[JuliaFormatter.jl](https://github.com/domluna/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 -```shell +```shell git add -p ``` diff --git a/examples/dgmulti_1d/elixir_advection_gauss_sbp.jl b/examples/dgmulti_1d/elixir_advection_gauss_sbp.jl index d06ed05a621..09d66fe8aea 100644 --- a/examples/dgmulti_1d/elixir_advection_gauss_sbp.jl +++ b/examples/dgmulti_1d/elixir_advection_gauss_sbp.jl @@ -23,8 +23,8 @@ dg = DGMulti(polydeg = 3, cells_per_dimension = (8,) mesh = DGMultiMesh(dg, cells_per_dimension, - coordinates_min=(-1.0,), coordinates_max=(1.0,), - periodicity=true) + coordinates_min = (-1.0,), coordinates_max = (1.0,), + periodicity = true) ############################################################################### # setup the test problem (no source term needed for linear advection) @@ -49,10 +49,10 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() # analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = 100, uEltype = real(dg)) # handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=0.75) +stepsize_callback = StepsizeCallback(cfl = 0.75) # collect all callbacks such that they can be passed to the ODE solver callbacks = CallbackSet(summary_callback, analysis_callback, stepsize_callback) @@ -60,9 +60,8 @@ callbacks = CallbackSet(summary_callback, analysis_callback, stepsize_callback) ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, save_everystep = false, callback = callbacks); # Print the timer summary summary_callback() - diff --git a/examples/dgmulti_1d/elixir_euler_fdsbp_periodic.jl b/examples/dgmulti_1d/elixir_euler_fdsbp_periodic.jl index 3566185d110..6abd7118fe3 100644 --- a/examples/dgmulti_1d/elixir_euler_fdsbp_periodic.jl +++ b/examples/dgmulti_1d/elixir_euler_fdsbp_periodic.jl @@ -2,8 +2,10 @@ using Trixi, OrdinaryDiffEq dg = DGMulti(element_type = Line(), - approximation_type = periodic_derivative_operator( - derivative_order=1, accuracy_order=4, xmin=0.0, xmax=1.0, N=50), + approximation_type = periodic_derivative_operator(derivative_order = 1, + accuracy_order = 4, + xmin = 0.0, xmax = 1.0, + N = 50), surface_flux = flux_hll, volume_integral = VolumeIntegralWeakForm()) @@ -11,8 +13,8 @@ equations = CompressibleEulerEquations1D(1.4) initial_condition = initial_condition_convergence_test source_terms = source_terms_convergence_test -mesh = DGMultiMesh(dg, coordinates_min=(-1.0,), - coordinates_max=( 1.0,)) +mesh = DGMultiMesh(dg, coordinates_min = (-1.0,), + coordinates_max = (1.0,)) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, dg, source_terms = source_terms) @@ -21,15 +23,16 @@ tspan = (0.0, 0.4) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) -stepsize_callback = StepsizeCallback(cfl=1.0) -callbacks = CallbackSet(summary_callback, alive_callback, stepsize_callback, analysis_callback) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) +stepsize_callback = StepsizeCallback(cfl = 1.0) +callbacks = CallbackSet(summary_callback, alive_callback, stepsize_callback, + analysis_callback) ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt = 0.5 * estimate_dt(mesh, dg), save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 0.5 * estimate_dt(mesh, dg), save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/dgmulti_1d/elixir_euler_flux_diff.jl b/examples/dgmulti_1d/elixir_euler_flux_diff.jl index 489b23e37b2..56a24d25d07 100644 --- a/examples/dgmulti_1d/elixir_euler_flux_diff.jl +++ b/examples/dgmulti_1d/elixir_euler_flux_diff.jl @@ -13,17 +13,17 @@ source_terms = source_terms_convergence_test cells_per_dimension = (8,) mesh = DGMultiMesh(dg, cells_per_dimension, - coordinates_min=(-1.0,), coordinates_max=(1.0,), periodicity=true) + coordinates_min = (-1.0,), coordinates_max = (1.0,), periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, dg; - source_terms=source_terms) + source_terms = source_terms) tspan = (0.0, 1.1) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) @@ -31,7 +31,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt = 0.5 * estimate_dt(mesh, dg), save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 0.5 * estimate_dt(mesh, dg), save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/dgmulti_2d/elixir_advection_diffusion.jl b/examples/dgmulti_2d/elixir_advection_diffusion.jl index 8a79e9700ac..ce7b0e745a4 100644 --- a/examples/dgmulti_2d/elixir_advection_diffusion.jl +++ b/examples/dgmulti_2d/elixir_advection_diffusion.jl @@ -11,48 +11,52 @@ initial_condition_zero(x, t, equations::LinearScalarAdvectionEquation2D) = SVect initial_condition = initial_condition_zero # tag different boundary segments -left(x, tol=50*eps()) = abs(x[1] + 1) < tol -right(x, tol=50*eps()) = abs(x[1] - 1) < tol -bottom(x, tol=50*eps()) = abs(x[2] + 1) < tol -top(x, tol=50*eps()) = abs(x[2] - 1) < tol +left(x, tol = 50 * eps()) = abs(x[1] + 1) < tol +right(x, tol = 50 * eps()) = abs(x[1] - 1) < tol +bottom(x, tol = 50 * eps()) = abs(x[2] + 1) < tol +top(x, tol = 50 * eps()) = abs(x[2] - 1) < tol is_on_boundary = Dict(:left => left, :right => right, :top => top, :bottom => bottom) cells_per_dimension = (16, 16) mesh = DGMultiMesh(dg, cells_per_dimension; is_on_boundary) # BC types -boundary_condition_left = BoundaryConditionDirichlet((x, t, equations) -> SVector(1 + 0.1 * x[2])) +boundary_condition_left = BoundaryConditionDirichlet((x, t, equations) -> SVector(1 + + 0.1 * + x[2])) boundary_condition_zero = BoundaryConditionDirichlet((x, t, equations) -> SVector(0.0)) boundary_condition_neumann_zero = BoundaryConditionNeumann((x, t, equations) -> SVector(0.0)) # define inviscid boundary conditions boundary_conditions = (; :left => boundary_condition_left, - :bottom => boundary_condition_zero, - :top => boundary_condition_do_nothing, - :right => boundary_condition_do_nothing) + :bottom => boundary_condition_zero, + :top => boundary_condition_do_nothing, + :right => boundary_condition_do_nothing) # define viscous boundary conditions boundary_conditions_parabolic = (; :left => boundary_condition_left, - :bottom => boundary_condition_zero, - :top => boundary_condition_zero, - :right => boundary_condition_neumann_zero) + :bottom => boundary_condition_zero, + :top => boundary_condition_zero, + :right => boundary_condition_neumann_zero) -semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, dg; - boundary_conditions=(boundary_conditions, boundary_conditions_parabolic)) +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, dg; + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic)) tspan = (0.0, 1.5) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) callbacks = CallbackSet(summary_callback, alive_callback) ############################################################################### # run the simulation time_int_tol = 1e-6 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary diff --git a/examples/dgmulti_2d/elixir_advection_diffusion_nonperiodic.jl b/examples/dgmulti_2d/elixir_advection_diffusion_nonperiodic.jl index 7e87d9f097d..d2f11f18507 100644 --- a/examples/dgmulti_2d/elixir_advection_diffusion_nonperiodic.jl +++ b/examples/dgmulti_2d/elixir_advection_diffusion_nonperiodic.jl @@ -16,61 +16,63 @@ equations_parabolic = LaplaceDiffusion2D(diffusivity(), equations) # to numerical partial differential equations. # [DOI](https://doi.org/10.1007/978-3-319-41640-3_6). function initial_condition_erikkson_johnson(x, t, equations) - l = 4 - epsilon = diffusivity() # Note: this requires epsilon < 0.6 due to the sqrt - lambda_1 = (-1 + sqrt(1 - 4 * epsilon * l)) / (-2 * epsilon) - lambda_2 = (-1 - sqrt(1 - 4 * epsilon * l)) / (-2 * epsilon) - r1 = (1 + sqrt(1 + 4 * pi^2 * epsilon^2)) / (2 * epsilon) - s1 = (1 - sqrt(1 + 4 * pi^2 * epsilon^2)) / (2 * epsilon) - u = exp(-l * t) * (exp(lambda_1 * x[1]) - exp(lambda_2 * x[1])) + - cos(pi * x[2]) * (exp(s1 * x[1]) - exp(r1 * x[1])) / (exp(-s1) - exp(-r1)) - return SVector{1}(u) + l = 4 + epsilon = diffusivity() # Note: this requires epsilon < 0.6 due to the sqrt + lambda_1 = (-1 + sqrt(1 - 4 * epsilon * l)) / (-2 * epsilon) + lambda_2 = (-1 - sqrt(1 - 4 * epsilon * l)) / (-2 * epsilon) + r1 = (1 + sqrt(1 + 4 * pi^2 * epsilon^2)) / (2 * epsilon) + s1 = (1 - sqrt(1 + 4 * pi^2 * epsilon^2)) / (2 * epsilon) + u = exp(-l * t) * (exp(lambda_1 * x[1]) - exp(lambda_2 * x[1])) + + cos(pi * x[2]) * (exp(s1 * x[1]) - exp(r1 * x[1])) / (exp(-s1) - exp(-r1)) + return SVector{1}(u) end initial_condition = initial_condition_erikkson_johnson # tag different boundary segments -left(x, tol=50*eps()) = abs(x[1] + 1) < tol -right(x, tol=50*eps()) = abs(x[1]) < tol -bottom(x, tol=50*eps()) = abs(x[2] + 0.5) < tol -top(x, tol=50*eps()) = abs(x[2] - 0.5) < tol -entire_boundary(x, tol=50*eps()) = true +left(x, tol = 50 * eps()) = abs(x[1] + 1) < tol +right(x, tol = 50 * eps()) = abs(x[1]) < tol +bottom(x, tol = 50 * eps()) = abs(x[2] + 0.5) < tol +top(x, tol = 50 * eps()) = abs(x[2] - 0.5) < tol +entire_boundary(x, tol = 50 * eps()) = true is_on_boundary = Dict(:left => left, :right => right, :top => top, :bottom => bottom, :entire_boundary => entire_boundary) cells_per_dimension = (16, 16) mesh = DGMultiMesh(dg, cells_per_dimension; - coordinates_min=(-1.0, -0.5), - coordinates_max=(0.0, 0.5), + coordinates_min = (-1.0, -0.5), + coordinates_max = (0.0, 0.5), is_on_boundary) # BC types boundary_condition = BoundaryConditionDirichlet(initial_condition) # define inviscid boundary conditions, enforce "do nothing" boundary condition at the outflow -boundary_conditions = (; :left => boundary_condition, - :top => boundary_condition, - :bottom => boundary_condition, - :right => boundary_condition_do_nothing) +boundary_conditions = (; :left => boundary_condition, + :top => boundary_condition, + :bottom => boundary_condition, + :right => boundary_condition_do_nothing) # define viscous boundary conditions boundary_conditions_parabolic = (; :entire_boundary => boundary_condition) -semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, dg; - boundary_conditions=(boundary_conditions, boundary_conditions_parabolic)) +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, dg; + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic)) tspan = (0.0, 1.5) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) callbacks = CallbackSet(summary_callback, alive_callback) ############################################################################### # run the simulation time_int_tol = 1e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary diff --git a/examples/dgmulti_2d/elixir_advection_diffusion_periodic.jl b/examples/dgmulti_2d/elixir_advection_diffusion_periodic.jl index 76512f1e39f..c498e5468d3 100644 --- a/examples/dgmulti_2d/elixir_advection_diffusion_periodic.jl +++ b/examples/dgmulti_2d/elixir_advection_diffusion_periodic.jl @@ -8,12 +8,12 @@ equations = LinearScalarAdvectionEquation2D(0.0, 0.0) equations_parabolic = LaplaceDiffusion2D(5.0e-1, equations) function initial_condition_sharp_gaussian(x, t, equations::LinearScalarAdvectionEquation2D) - return SVector(exp(-100 * (x[1]^2 + x[2]^2))) + return SVector(exp(-100 * (x[1]^2 + x[2]^2))) end initial_condition = initial_condition_sharp_gaussian cells_per_dimension = (16, 16) -mesh = DGMultiMesh(dg, cells_per_dimension, periodicity=true) +mesh = DGMultiMesh(dg, cells_per_dimension, periodicity = true) semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, dg) @@ -21,16 +21,16 @@ tspan = (0.0, 0.1) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) ############################################################################### # run the simulation time_int_tol = 1e-6 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - dt = time_int_tol, ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + dt = time_int_tol, ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary diff --git a/examples/dgmulti_2d/elixir_euler_bilinear.jl b/examples/dgmulti_2d/elixir_euler_bilinear.jl index bdd582610ea..cd498bf39b8 100644 --- a/examples/dgmulti_2d/elixir_euler_bilinear.jl +++ b/examples/dgmulti_2d/elixir_euler_bilinear.jl @@ -10,27 +10,28 @@ initial_condition = initial_condition_convergence_test source_terms = source_terms_convergence_test # example where we tag two separate boundary segments of the mesh -top_boundary(x, tol=50*eps()) = abs(x[2]-1) top_boundary, :rest => rest_of_boundary) function mapping(xi, eta) - x = xi + 0.1 * sin(pi * xi) * sin(pi * eta) - y = eta + 0.1 * sin(pi * xi) * sin(pi * eta) - return SVector(x, y) + x = xi + 0.1 * sin(pi * xi) * sin(pi * eta) + y = eta + 0.1 * sin(pi * xi) * sin(pi * eta) + return SVector(x, y) end cells_per_dimension = (16, 16) -vertex_coordinates, EToV = StartUpDG.uniform_mesh(dg.basis.element_type, cells_per_dimension...) +vertex_coordinates, EToV = StartUpDG.uniform_mesh(dg.basis.element_type, + cells_per_dimension...) for i in eachindex(vertex_coordinates[1]) - vx, vy = getindex.(vertex_coordinates, i) - setindex!.(vertex_coordinates, mapping(vx, vy), i) + vx, vy = getindex.(vertex_coordinates, i) + setindex!.(vertex_coordinates, mapping(vx, vy), i) end -mesh = DGMultiMesh(dg, vertex_coordinates, EToV, is_on_boundary=is_on_boundary) +mesh = DGMultiMesh(dg, vertex_coordinates, EToV, is_on_boundary = is_on_boundary) boundary_condition_convergence_test = BoundaryConditionDirichlet(initial_condition) boundary_conditions = (; :top => boundary_condition_convergence_test, - :rest => boundary_condition_convergence_test) + :rest => boundary_condition_convergence_test) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, dg, source_terms = source_terms, @@ -40,15 +41,15 @@ tspan = (0.0, 0.4) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) ############################################################################### # run the simulation -sol = solve(ode, RDPK3SpFSAL49(); abstol=1.0e-6, reltol=1.0e-6, - ode_default_options()..., callback=callbacks); +sol = solve(ode, RDPK3SpFSAL49(); abstol = 1.0e-6, reltol = 1.0e-6, + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/dgmulti_2d/elixir_euler_brown_minion_vortex.jl b/examples/dgmulti_2d/elixir_euler_brown_minion_vortex.jl index 4bb05c0b062..e7830c4736b 100644 --- a/examples/dgmulti_2d/elixir_euler_brown_minion_vortex.jl +++ b/examples/dgmulti_2d/elixir_euler_brown_minion_vortex.jl @@ -1,6 +1,6 @@ using Trixi, OrdinaryDiffEq -dg = DGMulti(polydeg=4, element_type = Quad(), approximation_type = Polynomial(), +dg = DGMulti(polydeg = 4, element_type = Quad(), approximation_type = Polynomial(), surface_integral = SurfaceIntegralWeakForm(FluxLaxFriedrichs()), volume_integral = VolumeIntegralFluxDifferencing(flux_ranocha)) @@ -16,38 +16,38 @@ incompressible version. [DOI: 10.1006/jcph.1995.1205](https://doi.org/10.1006/jcph.1995.1205) """ function initial_condition_BM_vortex(x, t, equations::CompressibleEulerEquations2D) - pbar = 9.0 / equations.gamma - delta = 0.05 - epsilon = 30 - H = (x[2] < 0) ? tanh(epsilon * (x[2] + 0.25)) : tanh(epsilon * (0.25 - x[2])) - rho = 1.0 - v1 = H - v2 = delta * cos(2.0 * pi * x[1]) - p = pbar - return prim2cons(SVector(rho, v1, v2, p), equations) + pbar = 9.0 / equations.gamma + delta = 0.05 + epsilon = 30 + H = (x[2] < 0) ? tanh(epsilon * (x[2] + 0.25)) : tanh(epsilon * (0.25 - x[2])) + rho = 1.0 + v1 = H + v2 = delta * cos(2.0 * pi * x[1]) + p = pbar + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_BM_vortex cells_per_dimension = (16, 16) mesh = DGMultiMesh(dg, cells_per_dimension, - coordinates_min=(-0.5, -0.5), coordinates_max=(0.5, 0.5), - periodicity=true) + coordinates_min = (-0.5, -0.5), coordinates_max = (0.5, 0.5), + periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, dg) tspan = (0.0, 1.0) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) ############################################################################### # run the simulation tol = 1.0e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol=tol, reltol=tol, - ode_default_options()..., callback=callbacks); +sol = solve(ode, RDPK3SpFSAL49(); abstol = tol, reltol = tol, + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/dgmulti_2d/elixir_euler_curved.jl b/examples/dgmulti_2d/elixir_euler_curved.jl index 39e3a0a0360..48662f4b12b 100644 --- a/examples/dgmulti_2d/elixir_euler_curved.jl +++ b/examples/dgmulti_2d/elixir_euler_curved.jl @@ -10,21 +10,21 @@ initial_condition = initial_condition_convergence_test source_terms = source_terms_convergence_test # example where we tag two separate boundary segments of the mesh -top_boundary(x, tol=50*eps()) = abs(x[2]-1) top_boundary, :rest => rest_of_boundary) function mapping(xi, eta) - x = xi + 0.1 * sin(pi * xi) * sin(pi * eta) - y = eta + 0.1 * sin(pi * xi) * sin(pi * eta) - return SVector(x, y) + x = xi + 0.1 * sin(pi * xi) * sin(pi * eta) + y = eta + 0.1 * sin(pi * xi) * sin(pi * eta) + return SVector(x, y) end cells_per_dimension = (16, 16) -mesh = DGMultiMesh(dg, cells_per_dimension, mapping, is_on_boundary=is_on_boundary) +mesh = DGMultiMesh(dg, cells_per_dimension, mapping, is_on_boundary = is_on_boundary) boundary_condition_convergence_test = BoundaryConditionDirichlet(initial_condition) boundary_conditions = (; :top => boundary_condition_convergence_test, - :rest => boundary_condition_convergence_test) + :rest => boundary_condition_convergence_test) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, dg, source_terms = source_terms, @@ -34,16 +34,16 @@ tspan = (0.0, 0.4) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) ############################################################################### # run the simulation alg = RDPK3SpFSAL49() -sol = solve(ode, alg; abstol=1.0e-6, reltol=1.0e-6, - ode_default_options()..., callback=callbacks); +sol = solve(ode, alg; abstol = 1.0e-6, reltol = 1.0e-6, + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/dgmulti_2d/elixir_euler_fdsbp_periodic.jl b/examples/dgmulti_2d/elixir_euler_fdsbp_periodic.jl index d41ca2c5b34..3a73089b566 100644 --- a/examples/dgmulti_2d/elixir_euler_fdsbp_periodic.jl +++ b/examples/dgmulti_2d/elixir_euler_fdsbp_periodic.jl @@ -2,8 +2,10 @@ using Trixi, OrdinaryDiffEq dg = DGMulti(element_type = Quad(), - approximation_type = periodic_derivative_operator( - derivative_order=1, accuracy_order=4, xmin=0.0, xmax=1.0, N=50), + approximation_type = periodic_derivative_operator(derivative_order = 1, + accuracy_order = 4, + xmin = 0.0, xmax = 1.0, + N = 50), surface_flux = flux_hll, volume_integral = VolumeIntegralWeakForm()) @@ -11,8 +13,8 @@ equations = CompressibleEulerEquations2D(1.4) initial_condition = initial_condition_convergence_test source_terms = source_terms_convergence_test -mesh = DGMultiMesh(dg, coordinates_min=(-1.0, -1.0), - coordinates_max=( 1.0, 1.0)) +mesh = DGMultiMesh(dg, coordinates_min = (-1.0, -1.0), + coordinates_max = (1.0, 1.0)) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, dg, source_terms = source_terms) @@ -21,15 +23,16 @@ tspan = (0.0, 0.4) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) -stepsize_callback = StepsizeCallback(cfl=1.0) -callbacks = CallbackSet(summary_callback, alive_callback, stepsize_callback, analysis_callback) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) +stepsize_callback = StepsizeCallback(cfl = 1.0) +callbacks = CallbackSet(summary_callback, alive_callback, stepsize_callback, + analysis_callback) ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt = 0.5 * estimate_dt(mesh, dg), save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 0.5 * estimate_dt(mesh, dg), save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/dgmulti_2d/elixir_euler_hohqmesh.jl b/examples/dgmulti_2d/elixir_euler_hohqmesh.jl index b9a24dc2450..f534b5bc8ad 100644 --- a/examples/dgmulti_2d/elixir_euler_hohqmesh.jl +++ b/examples/dgmulti_2d/elixir_euler_hohqmesh.jl @@ -15,11 +15,11 @@ initial_condition = initial_condition_convergence_test source_terms = source_terms_convergence_test boundary_condition_convergence_test = BoundaryConditionDirichlet(initial_condition) -boundary_conditions = (; :Slant => boundary_condition_convergence_test, - :Bezier => boundary_condition_convergence_test, - :Right => boundary_condition_convergence_test, - :Bottom => boundary_condition_convergence_test, - :Top => boundary_condition_convergence_test ) +boundary_conditions = (; :Slant => boundary_condition_convergence_test, + :Bezier => boundary_condition_convergence_test, + :Right => boundary_condition_convergence_test, + :Bottom => boundary_condition_convergence_test, + :Top => boundary_condition_convergence_test) ############################################################################### # Get the DG approximation space @@ -32,8 +32,9 @@ dg = DGMulti(polydeg = 8, element_type = Quad(), approximation_type = SBP(), # Get the curved quad mesh from a file (downloads the file if not available locally) default_mesh_file = joinpath(@__DIR__, "mesh_trixi_unstructured_mesh_docs.mesh") -isfile(default_mesh_file) || download("https://gist.githubusercontent.com/andrewwinters5000/52056f1487853fab63b7f4ed7f171c80/raw/9d573387dfdbb8bce2a55db7246f4207663ac07f/mesh_trixi_unstructured_mesh_docs.mesh", - default_mesh_file) +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/52056f1487853fab63b7f4ed7f171c80/raw/9d573387dfdbb8bce2a55db7246f4207663ac07f/mesh_trixi_unstructured_mesh_docs.mesh", + default_mesh_file) mesh_file = default_mesh_file mesh = DGMultiMesh(dg, mesh_file) @@ -42,8 +43,8 @@ mesh = DGMultiMesh(dg, mesh_file) # create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, dg, - source_terms=source_terms, - boundary_conditions=boundary_conditions) + source_terms = source_terms, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -54,9 +55,9 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -66,7 +67,7 @@ callbacks = CallbackSet(summary_callback, # run the simulation time_int_tol = 1e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - dt = time_int_tol, ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + dt = time_int_tol, ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary diff --git a/examples/dgmulti_2d/elixir_euler_kelvin_helmholtz_instability.jl b/examples/dgmulti_2d/elixir_euler_kelvin_helmholtz_instability.jl index 39e98d1a2c5..14de0bf0e8b 100644 --- a/examples/dgmulti_2d/elixir_euler_kelvin_helmholtz_instability.jl +++ b/examples/dgmulti_2d/elixir_euler_kelvin_helmholtz_instability.jl @@ -15,23 +15,24 @@ A version of the classical Kelvin-Helmholtz instability based on of the Euler Equations [arXiv: 2102.06017](https://arxiv.org/abs/2102.06017) """ -function initial_condition_kelvin_helmholtz_instability(x, t, equations::CompressibleEulerEquations2D) - # change discontinuity to tanh - # typical resolution 128^2, 256^2 - # domain size is [-1,+1]^2 - slope = 15 - amplitude = 0.02 - B = tanh(slope * x[2] + 7.5) - tanh(slope * x[2] - 7.5) - rho = 0.5 + 0.75 * B - v1 = 0.5 * (B - 1) - v2 = 0.1 * sin(2 * pi * x[1]) - p = 1.0 - return prim2cons(SVector(rho, v1, v2, p), equations) +function initial_condition_kelvin_helmholtz_instability(x, t, + equations::CompressibleEulerEquations2D) + # change discontinuity to tanh + # typical resolution 128^2, 256^2 + # domain size is [-1,+1]^2 + slope = 15 + amplitude = 0.02 + B = tanh(slope * x[2] + 7.5) - tanh(slope * x[2] - 7.5) + rho = 0.5 + 0.75 * B + v1 = 0.5 * (B - 1) + v2 = 0.1 * sin(2 * pi * x[1]) + p = 1.0 + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_kelvin_helmholtz_instability cells_per_dimension = (32, 32) -mesh = DGMultiMesh(dg, cells_per_dimension; periodicity=true) +mesh = DGMultiMesh(dg, cells_per_dimension; periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, dg) @@ -39,9 +40,9 @@ tspan = (0.0, 1.0) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) @@ -49,7 +50,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt = estimate_dt(mesh, dg), save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = estimate_dt(mesh, dg), save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/dgmulti_2d/elixir_euler_rayleigh_taylor_instability.jl b/examples/dgmulti_2d/elixir_euler_rayleigh_taylor_instability.jl index f5adc7bf83c..49c8b28eaf8 100644 --- a/examples/dgmulti_2d/elixir_euler_rayleigh_taylor_instability.jl +++ b/examples/dgmulti_2d/elixir_euler_rayleigh_taylor_instability.jl @@ -29,34 +29,34 @@ defined below. """ @inline function initial_condition_rayleigh_taylor_instability(x, t, equations::CompressibleEulerEquations2D, - slope=1000) - tol = 1e2*eps() - - if x[2] < 0.5 - p = 2*x[2] + 1 - else - p = x[2] + 3/2 - end - - # smooth the discontinuity to avoid ambiguity at element interfaces - smoothed_heaviside(x, left, right) = left + 0.5*(1 + tanh(slope * x)) * (right-left) - rho = smoothed_heaviside(x[2] - 0.5, 2.0, 1.0) - - c = sqrt(equations.gamma * p / rho) - # the velocity is multiplied by sin(pi*y)^6 as in Remacle et al. 2003 to ensure that the - # initial condition satisfies reflective boundary conditions at the top/bottom boundaries. - v = -0.025 * c * cos(8*pi*x[1]) * sin(pi*x[2])^6 - u = 0.0 - - return prim2cons(SVector(rho, u, v, p), equations) + slope = 1000) + tol = 1e2 * eps() + + if x[2] < 0.5 + p = 2 * x[2] + 1 + else + p = x[2] + 3 / 2 + end + + # smooth the discontinuity to avoid ambiguity at element interfaces + smoothed_heaviside(x, left, right) = left + 0.5 * (1 + tanh(slope * x)) * (right - left) + rho = smoothed_heaviside(x[2] - 0.5, 2.0, 1.0) + + c = sqrt(equations.gamma * p / rho) + # the velocity is multiplied by sin(pi*y)^6 as in Remacle et al. 2003 to ensure that the + # initial condition satisfies reflective boundary conditions at the top/bottom boundaries. + v = -0.025 * c * cos(8 * pi * x[1]) * sin(pi * x[2])^6 + u = 0.0 + + return prim2cons(SVector(rho, u, v, p), equations) end @inline function source_terms_rayleigh_taylor_instability(u, x, t, equations::CompressibleEulerEquations2D) - g = 1.0 - rho, rho_v1, rho_v2, rho_e = u + g = 1.0 + rho, rho_v1, rho_v2, rho_e = u - return SVector(0.0, 0.0, g*rho, g*rho_v2) + return SVector(0.0, 0.0, g * rho, g * rho_v2) end # numerical parameters @@ -67,8 +67,8 @@ dg = DGMulti(polydeg = 3, element_type = Quad(), approximation_type = Polynomial num_elements = 16 cells_per_dimension = (num_elements, 4 * num_elements) mesh = DGMultiMesh(dg, cells_per_dimension, - coordinates_min=(0.0, 0.0), coordinates_max=(0.25, 1.0), - periodicity=(true, false)) + coordinates_min = (0.0, 0.0), coordinates_max = (0.25, 1.0), + periodicity = (true, false)) initial_condition = initial_condition_rayleigh_taylor_instability boundary_conditions = (; :entire_boundary => boundary_condition_slip_wall) @@ -86,9 +86,9 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -97,7 +97,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, RDPK3SpFSAL49(); abstol=1.0e-6, reltol=1.0e-6, - ode_default_options()..., callback=callbacks); +sol = solve(ode, RDPK3SpFSAL49(); abstol = 1.0e-6, reltol = 1.0e-6, + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/dgmulti_2d/elixir_euler_shockcapturing.jl b/examples/dgmulti_2d/elixir_euler_shockcapturing.jl index 4b2a408c757..36494b268d6 100644 --- a/examples/dgmulti_2d/elixir_euler_shockcapturing.jl +++ b/examples/dgmulti_2d/elixir_euler_shockcapturing.jl @@ -10,25 +10,25 @@ equations = CompressibleEulerEquations2D(1.4) initial_condition = initial_condition_weak_blast_wave surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha +volume_flux = flux_ranocha polydeg = 3 -basis = DGMultiBasis(Quad(), polydeg, approximation_type=GaussSBP()) +basis = DGMultiBasis(Quad(), polydeg, approximation_type = GaussSBP()) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) dg = DGMulti(basis, surface_integral = SurfaceIntegralWeakForm(surface_flux), volume_integral = volume_integral) cells_per_dimension = (8, 8) -mesh = DGMultiMesh(dg, cells_per_dimension, periodicity=true) +mesh = DGMultiMesh(dg, cells_per_dimension, periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, dg) @@ -36,16 +36,15 @@ tspan = (0.0, 0.15) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) ############################################################################### # run the simulation -sol = solve(ode, RDPK3SpFSAL49(); abstol=1.0e-6, reltol=1.0e-6, - ode_default_options()..., callback=callbacks); +sol = solve(ode, RDPK3SpFSAL49(); abstol = 1.0e-6, reltol = 1.0e-6, + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary - diff --git a/examples/dgmulti_2d/elixir_euler_shockcapturing_curved.jl b/examples/dgmulti_2d/elixir_euler_shockcapturing_curved.jl index dad898b99b6..5e8d9e6c8e4 100644 --- a/examples/dgmulti_2d/elixir_euler_shockcapturing_curved.jl +++ b/examples/dgmulti_2d/elixir_euler_shockcapturing_curved.jl @@ -10,27 +10,27 @@ equations = CompressibleEulerEquations2D(1.4) initial_condition = initial_condition_weak_blast_wave surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha +volume_flux = flux_ranocha polydeg = 3 -basis = DGMultiBasis(Quad(), polydeg, approximation_type=GaussSBP()) +basis = DGMultiBasis(Quad(), polydeg, approximation_type = GaussSBP()) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) dg = DGMulti(basis, surface_integral = SurfaceIntegralWeakForm(surface_flux), volume_integral = volume_integral) function mapping(xi, eta) - x = xi + 0.1 * sin(pi * xi) * sin(pi * eta) - y = eta + 0.1 * sin(pi * xi) * sin(pi * eta) - return SVector(x, y) + x = xi + 0.1 * sin(pi * xi) * sin(pi * eta) + y = eta + 0.1 * sin(pi * xi) * sin(pi * eta) + return SVector(x, y) end cells_per_dimension = (16, 16) mesh = DGMultiMesh(dg, cells_per_dimension, mapping) @@ -41,16 +41,15 @@ tspan = (0.0, 0.15) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) ############################################################################### # run the simulation -sol = solve(ode, RDPK3SpFSAL49(); abstol=1.0e-6, reltol=1.0e-6, - ode_default_options()..., callback=callbacks); +sol = solve(ode, RDPK3SpFSAL49(); abstol = 1.0e-6, reltol = 1.0e-6, + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary - diff --git a/examples/dgmulti_2d/elixir_euler_triangulate_pkg_mesh.jl b/examples/dgmulti_2d/elixir_euler_triangulate_pkg_mesh.jl index c10b5e46a14..53661af259a 100644 --- a/examples/dgmulti_2d/elixir_euler_triangulate_pkg_mesh.jl +++ b/examples/dgmulti_2d/elixir_euler_triangulate_pkg_mesh.jl @@ -13,11 +13,11 @@ meshIO = StartUpDG.triangulate_domain(StartUpDG.RectangularDomainWithHole()) # the pre-defined Triangulate geometry in StartUpDG has integer boundary tags. this routine # assigns boundary faces based on these integer boundary tags. -mesh = DGMultiMesh(dg, meshIO, Dict(:outer_boundary=>1, :inner_boundary=>2)) +mesh = DGMultiMesh(dg, meshIO, Dict(:outer_boundary => 1, :inner_boundary => 2)) boundary_condition_convergence_test = BoundaryConditionDirichlet(initial_condition) boundary_conditions = (; :outer_boundary => boundary_condition_convergence_test, - :inner_boundary => boundary_condition_convergence_test) + :inner_boundary => boundary_condition_convergence_test) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, dg, source_terms = source_terms, @@ -27,14 +27,14 @@ tspan = (0.0, 0.2) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt = 0.5 * estimate_dt(mesh, dg), save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 0.5 * estimate_dt(mesh, dg), save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/dgmulti_2d/elixir_euler_weakform.jl b/examples/dgmulti_2d/elixir_euler_weakform.jl index 486a30b37f1..ecf5e94a86b 100644 --- a/examples/dgmulti_2d/elixir_euler_weakform.jl +++ b/examples/dgmulti_2d/elixir_euler_weakform.jl @@ -10,16 +10,16 @@ initial_condition = initial_condition_convergence_test source_terms = source_terms_convergence_test # example where we tag two separate boundary segments of the mesh -top_boundary(x, tol=50*eps()) = abs(x[2]-1) top_boundary, :rest => rest_of_boundary) cells_per_dimension = (8, 8) -mesh = DGMultiMesh(dg, cells_per_dimension, is_on_boundary=is_on_boundary) +mesh = DGMultiMesh(dg, cells_per_dimension, is_on_boundary = is_on_boundary) boundary_condition_convergence_test = BoundaryConditionDirichlet(initial_condition) boundary_conditions = (; :top => boundary_condition_convergence_test, - :rest => boundary_condition_convergence_test) + :rest => boundary_condition_convergence_test) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, dg, source_terms = source_terms, @@ -29,15 +29,16 @@ tspan = (0.0, 0.4) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) -stepsize_callback = StepsizeCallback(cfl=1.5) -callbacks = CallbackSet(summary_callback, alive_callback, stepsize_callback, analysis_callback) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) +stepsize_callback = StepsizeCallback(cfl = 1.5) +callbacks = CallbackSet(summary_callback, alive_callback, stepsize_callback, + analysis_callback) ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt = 0.5 * estimate_dt(mesh, dg), save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 0.5 * estimate_dt(mesh, dg), save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/dgmulti_2d/elixir_euler_weakform_periodic.jl b/examples/dgmulti_2d/elixir_euler_weakform_periodic.jl index c4c83fff642..307bf5cbf4a 100644 --- a/examples/dgmulti_2d/elixir_euler_weakform_periodic.jl +++ b/examples/dgmulti_2d/elixir_euler_weakform_periodic.jl @@ -10,7 +10,7 @@ initial_condition = initial_condition_convergence_test source_terms = source_terms_convergence_test cells_per_dimension = (4, 4) -mesh = DGMultiMesh(dg, cells_per_dimension, periodicity=true) +mesh = DGMultiMesh(dg, cells_per_dimension, periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, dg, source_terms = source_terms) @@ -18,14 +18,14 @@ tspan = (0.0, 0.4) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt = 0.5 * estimate_dt(mesh, dg), save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 0.5 * estimate_dt(mesh, dg), save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/dgmulti_2d/elixir_mhd_reflective_wall.jl b/examples/dgmulti_2d/elixir_mhd_reflective_wall.jl index a1351cf8244..11670288526 100644 --- a/examples/dgmulti_2d/elixir_mhd_reflective_wall.jl +++ b/examples/dgmulti_2d/elixir_mhd_reflective_wall.jl @@ -8,70 +8,72 @@ using LinearAlgebra: norm, dot # for use in the MHD boundary condition equations = IdealGlmMhdEquations2D(1.4) function initial_condition_perturbation(x, t, equations::IdealGlmMhdEquations2D) - # pressure perturbation in a vertically magnetized field on the domain [-1, 1]^2 + # pressure perturbation in a vertically magnetized field on the domain [-1, 1]^2 - r2 = (x[1] + 0.25)^2 + (x[2] + 0.25)^2 + r2 = (x[1] + 0.25)^2 + (x[2] + 0.25)^2 - rho = 1.0 - v1 = 0.0 - v2 = 0.0 - v3 = 0.0 - p = 1 + 0.5 * exp(-100 * r2) + rho = 1.0 + v1 = 0.0 + v2 = 0.0 + v3 = 0.0 + p = 1 + 0.5 * exp(-100 * r2) - # the pressure and magnetic field are chosen to be strongly - # magnetized, such that p / ||B||^2 ≈ 0.01. - B1 = 0.0 - B2 = 40.0 / sqrt(4.0 * pi) - B3 = 0.0 + # the pressure and magnetic field are chosen to be strongly + # magnetized, such that p / ||B||^2 ≈ 0.01. + B1 = 0.0 + B2 = 40.0 / sqrt(4.0 * pi) + B3 = 0.0 - psi = 0.0 - return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3, psi), equations) + psi = 0.0 + return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3, psi), equations) end initial_condition = initial_condition_perturbation surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell) -volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) +volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) -solver = DGMulti(polydeg=3, element_type = Quad(), approximation_type = GaussSBP(), +solver = DGMulti(polydeg = 3, element_type = Quad(), approximation_type = GaussSBP(), surface_integral = SurfaceIntegralWeakForm(surface_flux), volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) -x_neg(x, tol=50*eps()) = abs(x[1] + 1) < tol -x_pos(x, tol=50*eps()) = abs(x[1] - 1) < tol -y_neg(x, tol=50*eps()) = abs(x[2] + 1) < tol -y_pos(x, tol=50*eps()) = abs(x[2] - 1) < tol +x_neg(x, tol = 50 * eps()) = abs(x[1] + 1) < tol +x_pos(x, tol = 50 * eps()) = abs(x[1] - 1) < tol +y_neg(x, tol = 50 * eps()) = abs(x[2] + 1) < tol +y_pos(x, tol = 50 * eps()) = abs(x[2] - 1) < tol is_on_boundary = Dict(:x_neg => x_neg, :x_pos => x_pos, :y_neg => y_neg, :y_pos => y_pos) cells_per_dimension = (16, 16) -mesh = DGMultiMesh(solver, cells_per_dimension; periodicity=(false, false), is_on_boundary) +mesh = DGMultiMesh(solver, cells_per_dimension; periodicity = (false, false), + is_on_boundary) # Create a "reflective-like" boundary condition by mirroring the velocity but leaving the magnetic field alone. # Note that this boundary condition is probably not entropy stable. -function boundary_condition_velocity_slip_wall(u_inner, normal_direction::AbstractVector, x, t, - surface_flux_function, equations::IdealGlmMhdEquations2D) +function boundary_condition_velocity_slip_wall(u_inner, normal_direction::AbstractVector, + x, t, surface_flux_function, + equations::IdealGlmMhdEquations2D) - # Normalize the vector without using `normalize` since we need to multiply by the `norm_` later - norm_ = norm(normal_direction) - normal = normal_direction / norm_ + # Normalize the vector without using `normalize` since we need to multiply by the `norm_` later + norm_ = norm(normal_direction) + normal = normal_direction / norm_ - # compute the primitive variables - rho, v1, v2, v3, p, B1, B2, B3, psi = cons2prim(u_inner, equations) + # compute the primitive variables + rho, v1, v2, v3, p, B1, B2, B3, psi = cons2prim(u_inner, equations) - v_normal = dot(normal, SVector(v1, v2)) - u_mirror = prim2cons(SVector(rho, v1 - 2 * v_normal * normal[1], - v2 - 2 * v_normal * normal[2], - v3, p, B1, B2, B3, psi), equations) + v_normal = dot(normal, SVector(v1, v2)) + u_mirror = prim2cons(SVector(rho, v1 - 2 * v_normal * normal[1], + v2 - 2 * v_normal * normal[2], + v3, p, B1, B2, B3, psi), equations) - return surface_flux_function(u_inner, u_mirror, normal, equations) * norm_ + return surface_flux_function(u_inner, u_mirror, normal, equations) * norm_ end -boundary_conditions = (; x_neg=boundary_condition_velocity_slip_wall, - x_pos=boundary_condition_velocity_slip_wall, - y_neg=boundary_condition_do_nothing, - y_pos=BoundaryConditionDirichlet(initial_condition)) +boundary_conditions = (; x_neg = boundary_condition_velocity_slip_wall, + x_pos = boundary_condition_velocity_slip_wall, + y_neg = boundary_condition_do_nothing, + y_pos = BoundaryConditionDirichlet(initial_condition)) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver; - boundary_conditions=boundary_conditions) + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -82,12 +84,13 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(solver)) -alive_callback = AliveCallback(alive_interval=10) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + uEltype = real(solver)) +alive_callback = AliveCallback(alive_interval = 10) cfl = 0.5 -stepsize_callback = StepsizeCallback(cfl=cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -98,8 +101,8 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1e-5, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1e-5, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/dgmulti_2d/elixir_mhd_weak_blast_wave.jl b/examples/dgmulti_2d/elixir_mhd_weak_blast_wave.jl index bf5045ce8b0..663301e189f 100644 --- a/examples/dgmulti_2d/elixir_mhd_weak_blast_wave.jl +++ b/examples/dgmulti_2d/elixir_mhd_weak_blast_wave.jl @@ -11,14 +11,14 @@ initial_condition = initial_condition_weak_blast_wave surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell) volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) -dg = DGMulti(polydeg=3, element_type = Quad(), approximation_type = Polynomial(), +dg = DGMulti(polydeg = 3, element_type = Quad(), approximation_type = Polynomial(), surface_integral = SurfaceIntegralWeakForm(surface_flux), volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) cells_per_dimension = (16, 16) mesh = DGMultiMesh(dg, cells_per_dimension, - coordinates_min=(-2.0, -2.0), coordinates_max=(2.0, 2.0), - periodicity=true) + coordinates_min = (-2.0, -2.0), coordinates_max = (2.0, 2.0), + periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, dg) ############################################################################### @@ -30,13 +30,13 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) +alive_callback = AliveCallback(analysis_interval = analysis_interval) cfl = 1.0 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -47,8 +47,8 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/dgmulti_2d/elixir_mhd_weak_blast_wave_SBP.jl b/examples/dgmulti_2d/elixir_mhd_weak_blast_wave_SBP.jl index 9c8dfcb3801..3dc070a7296 100644 --- a/examples/dgmulti_2d/elixir_mhd_weak_blast_wave_SBP.jl +++ b/examples/dgmulti_2d/elixir_mhd_weak_blast_wave_SBP.jl @@ -15,13 +15,13 @@ initial_condition = initial_condition_weak_blast_wave surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell) volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) -dg = DGMulti(polydeg=3, element_type = Quad(), approximation_type = SBP(), +dg = DGMulti(polydeg = 3, element_type = Quad(), approximation_type = SBP(), surface_integral = SurfaceIntegralWeakForm(surface_flux), volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) mesh = DGMultiMesh(dg, cells_per_dimension, - coordinates_min=(-2.0, -2.0), coordinates_max=(2.0, 2.0), - periodicity=true) + coordinates_min = (-2.0, -2.0), coordinates_max = (2.0, 2.0), + periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, dg) ############################################################################### @@ -33,8 +33,8 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) +alive_callback = AliveCallback(analysis_interval = analysis_interval) # See comment above and https://github.com/trixi-framework/Trixi.jl/issues/881 # DGMulti uses a conservative timestep estimate, so we can use a large CFL here. @@ -46,8 +46,7 @@ alive_callback = AliveCallback(analysis_interval=analysis_interval) callbacks = CallbackSet(summary_callback, analysis_callback, #stepsize_callback, - alive_callback, - #=glm_speed_callback=#) + alive_callback) #=glm_speed_callback=# ############################################################################### # run the simulation @@ -56,7 +55,7 @@ callbacks = CallbackSet(summary_callback, # sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), # dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback # save_everystep=false, callback=callbacks); -sol = solve(ode, RDPK3SpFSAL49(); abstol=1.0e-8, reltol=1.0e-8, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = 1.0e-8, reltol = 1.0e-8, + ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary diff --git a/examples/dgmulti_2d/elixir_navierstokes_convergence.jl b/examples/dgmulti_2d/elixir_navierstokes_convergence.jl index 23c9c2e8ed4..38cf3d7984b 100644 --- a/examples/dgmulti_2d/elixir_navierstokes_convergence.jl +++ b/examples/dgmulti_2d/elixir_navierstokes_convergence.jl @@ -10,169 +10,180 @@ mu() = 0.01 equations = CompressibleEulerEquations2D(1.4) # Note: If you change the Navier-Stokes parameters here, also change them in the initial condition # I really do not like this structure but it should work for now -equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu=mu(), Prandtl=prandtl_number(), - gradient_variables=GradientVariablesPrimitive()) +equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu = mu(), + Prandtl = prandtl_number(), + gradient_variables = GradientVariablesPrimitive()) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux dg = DGMulti(polydeg = 3, element_type = Tri(), approximation_type = Polynomial(), surface_integral = SurfaceIntegralWeakForm(flux_lax_friedrichs), volume_integral = VolumeIntegralWeakForm()) -top_bottom(x, tol=50*eps()) = abs(abs(x[2]) - 1) < tol +top_bottom(x, tol = 50 * eps()) = abs(abs(x[2]) - 1) < tol is_on_boundary = Dict(:top_bottom => top_bottom) cells_per_dimension = (16, 16) -mesh = DGMultiMesh(dg, cells_per_dimension; periodicity=(true, false), is_on_boundary) +mesh = DGMultiMesh(dg, cells_per_dimension; periodicity = (true, false), is_on_boundary) # Note: the initial condition cannot be specialized to `CompressibleNavierStokesDiffusion2D` # since it is called by both the parabolic solver (which passes in `CompressibleNavierStokesDiffusion2D`) # and by the initial condition (which passes in `CompressibleEulerEquations2D`). # This convergence test setup was originally derived by Andrew Winters (@andrewwinters5000) function initial_condition_navier_stokes_convergence_test(x, t, equations) - # Amplitude and shift - A = 0.5 - c = 2.0 + # Amplitude and shift + A = 0.5 + c = 2.0 - # convenience values for trig. functions - pi_x = pi * x[1] - pi_y = pi * x[2] - pi_t = pi * t + # convenience values for trig. functions + pi_x = pi * x[1] + pi_y = pi * x[2] + pi_t = pi * t - rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t) - v1 = sin(pi_x) * log(x[2] + 2.0) * (1.0 - exp(-A * (x[2] - 1.0)) ) * cos(pi_t) - v2 = v1 - p = rho^2 + rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t) + v1 = sin(pi_x) * log(x[2] + 2.0) * (1.0 - exp(-A * (x[2] - 1.0))) * cos(pi_t) + v2 = v1 + p = rho^2 - return prim2cons(SVector(rho, v1, v2, p), equations) + return prim2cons(SVector(rho, v1, v2, p), equations) end @inline function source_terms_navier_stokes_convergence_test(u, x, t, equations) - y = x[2] - - # TODO: parabolic - # we currently need to hardcode these parameters until we fix the "combined equation" issue - # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 - inv_gamma_minus_one = inv(equations.gamma - 1) - Pr = prandtl_number() - mu_ = mu() - - # Same settings as in `initial_condition` - # Amplitude and shift - A = 0.5 - c = 2.0 - - # convenience values for trig. functions - pi_x = pi * x[1] - pi_y = pi * x[2] - pi_t = pi * t - - # compute the manufactured solution and all necessary derivatives - rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t) - rho_t = -pi * A * sin(pi_x) * cos(pi_y) * sin(pi_t) - rho_x = pi * A * cos(pi_x) * cos(pi_y) * cos(pi_t) - rho_y = -pi * A * sin(pi_x) * sin(pi_y) * cos(pi_t) - rho_xx = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t) - rho_yy = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t) - - v1 = sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) - v1_t = -pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * sin(pi_t) - v1_x = pi * cos(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) - v1_y = sin(pi_x) * (A * log(y + 2.0) * exp(-A * (y - 1.0)) + (1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t) - v1_xx = -pi * pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) - v1_xy = pi * cos(pi_x) * (A * log(y + 2.0) * exp(-A * (y - 1.0)) + (1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t) - v1_yy = (sin(pi_x) * ( 2.0 * A * exp(-A * (y - 1.0)) / (y + 2.0) - - A * A * log(y + 2.0) * exp(-A * (y - 1.0)) - - (1.0 - exp(-A * (y - 1.0))) / ((y + 2.0) * (y + 2.0))) * cos(pi_t)) - v2 = v1 - v2_t = v1_t - v2_x = v1_x - v2_y = v1_y - v2_xx = v1_xx - v2_xy = v1_xy - v2_yy = v1_yy - - p = rho * rho - p_t = 2.0 * rho * rho_t - p_x = 2.0 * rho * rho_x - p_y = 2.0 * rho * rho_y - p_xx = 2.0 * rho * rho_xx + 2.0 * rho_x * rho_x - p_yy = 2.0 * rho * rho_yy + 2.0 * rho_y * rho_y - - # Note this simplifies slightly because the ansatz assumes that v1 = v2 - E = p * inv_gamma_minus_one + 0.5 * rho * (v1^2 + v2^2) - E_t = p_t * inv_gamma_minus_one + rho_t * v1^2 + 2.0 * rho * v1 * v1_t - E_x = p_x * inv_gamma_minus_one + rho_x * v1^2 + 2.0 * rho * v1 * v1_x - E_y = p_y * inv_gamma_minus_one + rho_y * v1^2 + 2.0 * rho * v1 * v1_y - - # Some convenience constants - T_const = equations.gamma * inv_gamma_minus_one / Pr - inv_rho_cubed = 1.0 / (rho^3) - - # compute the source terms - # density equation - du1 = rho_t + rho_x * v1 + rho * v1_x + rho_y * v2 + rho * v2_y - - # x-momentum equation - du2 = ( rho_t * v1 + rho * v1_t + p_x + rho_x * v1^2 - + 2.0 * rho * v1 * v1_x - + rho_y * v1 * v2 - + rho * v1_y * v2 - + rho * v1 * v2_y - # stress tensor from x-direction - - 4.0 / 3.0 * v1_xx * mu_ - + 2.0 / 3.0 * v2_xy * mu_ - - v1_yy * mu_ - - v2_xy * mu_ ) - # y-momentum equation - du3 = ( rho_t * v2 + rho * v2_t + p_y + rho_x * v1 * v2 - + rho * v1_x * v2 - + rho * v1 * v2_x - + rho_y * v2^2 - + 2.0 * rho * v2 * v2_y - # stress tensor from y-direction - - v1_xy * mu_ - - v2_xx * mu_ - - 4.0 / 3.0 * v2_yy * mu_ - + 2.0 / 3.0 * v1_xy * mu_ ) - # total energy equation - du4 = ( E_t + v1_x * (E + p) + v1 * (E_x + p_x) - + v2_y * (E + p) + v2 * (E_y + p_y) - # stress tensor and temperature gradient terms from x-direction - - 4.0 / 3.0 * v1_xx * v1 * mu_ - + 2.0 / 3.0 * v2_xy * v1 * mu_ - - 4.0 / 3.0 * v1_x * v1_x * mu_ - + 2.0 / 3.0 * v2_y * v1_x * mu_ - - v1_xy * v2 * mu_ - - v2_xx * v2 * mu_ - - v1_y * v2_x * mu_ - - v2_x * v2_x * mu_ - - T_const * inv_rho_cubed * ( p_xx * rho * rho - - 2.0 * p_x * rho * rho_x - + 2.0 * p * rho_x * rho_x - - p * rho * rho_xx ) * mu_ - # stress tensor and temperature gradient terms from y-direction - - v1_yy * v1 * mu_ - - v2_xy * v1 * mu_ - - v1_y * v1_y * mu_ - - v2_x * v1_y * mu_ - - 4.0 / 3.0 * v2_yy * v2 * mu_ - + 2.0 / 3.0 * v1_xy * v2 * mu_ - - 4.0 / 3.0 * v2_y * v2_y * mu_ - + 2.0 / 3.0 * v1_x * v2_y * mu_ - - T_const * inv_rho_cubed * ( p_yy * rho * rho - - 2.0 * p_y * rho * rho_y - + 2.0 * p * rho_y * rho_y - - p * rho * rho_yy ) * mu_ ) - - return SVector(du1, du2, du3, du4) + y = x[2] + + # TODO: parabolic + # we currently need to hardcode these parameters until we fix the "combined equation" issue + # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 + inv_gamma_minus_one = inv(equations.gamma - 1) + Pr = prandtl_number() + mu_ = mu() + + # Same settings as in `initial_condition` + # Amplitude and shift + A = 0.5 + c = 2.0 + + # convenience values for trig. functions + pi_x = pi * x[1] + pi_y = pi * x[2] + pi_t = pi * t + + # compute the manufactured solution and all necessary derivatives + rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t) + rho_t = -pi * A * sin(pi_x) * cos(pi_y) * sin(pi_t) + rho_x = pi * A * cos(pi_x) * cos(pi_y) * cos(pi_t) + rho_y = -pi * A * sin(pi_x) * sin(pi_y) * cos(pi_t) + rho_xx = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t) + rho_yy = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t) + + v1 = sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) + v1_t = -pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * sin(pi_t) + v1_x = pi * cos(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) + v1_y = sin(pi_x) * + (A * log(y + 2.0) * exp(-A * (y - 1.0)) + + (1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t) + v1_xx = -pi * pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) + v1_xy = pi * cos(pi_x) * + (A * log(y + 2.0) * exp(-A * (y - 1.0)) + + (1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t) + v1_yy = (sin(pi_x) * + (2.0 * A * exp(-A * (y - 1.0)) / (y + 2.0) - + A * A * log(y + 2.0) * exp(-A * (y - 1.0)) - + (1.0 - exp(-A * (y - 1.0))) / ((y + 2.0) * (y + 2.0))) * cos(pi_t)) + v2 = v1 + v2_t = v1_t + v2_x = v1_x + v2_y = v1_y + v2_xx = v1_xx + v2_xy = v1_xy + v2_yy = v1_yy + + p = rho * rho + p_t = 2.0 * rho * rho_t + p_x = 2.0 * rho * rho_x + p_y = 2.0 * rho * rho_y + p_xx = 2.0 * rho * rho_xx + 2.0 * rho_x * rho_x + p_yy = 2.0 * rho * rho_yy + 2.0 * rho_y * rho_y + + # Note this simplifies slightly because the ansatz assumes that v1 = v2 + E = p * inv_gamma_minus_one + 0.5 * rho * (v1^2 + v2^2) + E_t = p_t * inv_gamma_minus_one + rho_t * v1^2 + 2.0 * rho * v1 * v1_t + E_x = p_x * inv_gamma_minus_one + rho_x * v1^2 + 2.0 * rho * v1 * v1_x + E_y = p_y * inv_gamma_minus_one + rho_y * v1^2 + 2.0 * rho * v1 * v1_y + + # Some convenience constants + T_const = equations.gamma * inv_gamma_minus_one / Pr + inv_rho_cubed = 1.0 / (rho^3) + + # compute the source terms + # density equation + du1 = rho_t + rho_x * v1 + rho * v1_x + rho_y * v2 + rho * v2_y + + # x-momentum equation + du2 = (rho_t * v1 + rho * v1_t + p_x + rho_x * v1^2 + + 2.0 * rho * v1 * v1_x + + rho_y * v1 * v2 + + rho * v1_y * v2 + + rho * v1 * v2_y - + # stress tensor from x-direction + 4.0 / 3.0 * v1_xx * mu_ + + 2.0 / 3.0 * v2_xy * mu_ - + v1_yy * mu_ - + v2_xy * mu_) + # y-momentum equation + du3 = (rho_t * v2 + rho * v2_t + p_y + rho_x * v1 * v2 + + rho * v1_x * v2 + + rho * v1 * v2_x + + rho_y * v2^2 + + 2.0 * rho * v2 * v2_y - + # stress tensor from y-direction + v1_xy * mu_ - + v2_xx * mu_ - + 4.0 / 3.0 * v2_yy * mu_ + + 2.0 / 3.0 * v1_xy * mu_) + # total energy equation + du4 = (E_t + v1_x * (E + p) + v1 * (E_x + p_x) + + v2_y * (E + p) + v2 * (E_y + p_y) - + # stress tensor and temperature gradient terms from x-direction + 4.0 / 3.0 * v1_xx * v1 * mu_ + + 2.0 / 3.0 * v2_xy * v1 * mu_ - + 4.0 / 3.0 * v1_x * v1_x * mu_ + + 2.0 / 3.0 * v2_y * v1_x * mu_ - + v1_xy * v2 * mu_ - + v2_xx * v2 * mu_ - + v1_y * v2_x * mu_ - + v2_x * v2_x * mu_ - + T_const * inv_rho_cubed * + (p_xx * rho * rho - + 2.0 * p_x * rho * rho_x + + 2.0 * p * rho_x * rho_x - + p * rho * rho_xx) * mu_ - + # stress tensor and temperature gradient terms from y-direction + v1_yy * v1 * mu_ - + v2_xy * v1 * mu_ - + v1_y * v1_y * mu_ - + v2_x * v1_y * mu_ - + 4.0 / 3.0 * v2_yy * v2 * mu_ + + 2.0 / 3.0 * v1_xy * v2 * mu_ - + 4.0 / 3.0 * v2_y * v2_y * mu_ + + 2.0 / 3.0 * v1_x * v2_y * mu_ - + T_const * inv_rho_cubed * + (p_yy * rho * rho - + 2.0 * p_y * rho * rho_y + + 2.0 * p * rho_y * rho_y - + p * rho * rho_yy) * mu_) + + return SVector(du1, du2, du3, du4) end initial_condition = initial_condition_navier_stokes_convergence_test # BC types -velocity_bc_top_bottom = NoSlip((x, t, equations) -> initial_condition_navier_stokes_convergence_test(x, t, equations)[2:3]) +velocity_bc_top_bottom = NoSlip((x, t, equations) -> initial_condition_navier_stokes_convergence_test(x, + t, + equations)[2:3]) heat_bc_top_bottom = Adiabatic((x, t, equations) -> 0.0) -boundary_condition_top_bottom = BoundaryConditionNavierStokesWall(velocity_bc_top_bottom, heat_bc_top_bottom) +boundary_condition_top_bottom = BoundaryConditionNavierStokesWall(velocity_bc_top_bottom, + heat_bc_top_bottom) # define inviscid boundary conditions boundary_conditions = (; :top_bottom => boundary_condition_slip_wall) @@ -180,10 +191,11 @@ boundary_conditions = (; :top_bottom => boundary_condition_slip_wall) # define viscous boundary conditions boundary_conditions_parabolic = (; :top_bottom => boundary_condition_top_bottom) -semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, dg; - boundary_conditions=(boundary_conditions, boundary_conditions_parabolic), - source_terms=source_terms_navier_stokes_convergence_test) - +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, dg; + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic), + source_terms = source_terms_navier_stokes_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -193,15 +205,15 @@ tspan = (0.0, 0.5) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) callbacks = CallbackSet(summary_callback, alive_callback) ############################################################################### # run the simulation time_int_tol = 1e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary diff --git a/examples/dgmulti_2d/elixir_navierstokes_convergence_curved.jl b/examples/dgmulti_2d/elixir_navierstokes_convergence_curved.jl index 86b5ae64348..87ffd0e0995 100644 --- a/examples/dgmulti_2d/elixir_navierstokes_convergence_curved.jl +++ b/examples/dgmulti_2d/elixir_navierstokes_convergence_curved.jl @@ -10,24 +10,26 @@ mu() = 0.01 equations = CompressibleEulerEquations2D(1.4) # Note: If you change the Navier-Stokes parameters here, also change them in the initial condition # I really do not like this structure but it should work for now -equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu=mu(), Prandtl=prandtl_number(), - gradient_variables=GradientVariablesPrimitive()) +equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu = mu(), + Prandtl = prandtl_number(), + gradient_variables = GradientVariablesPrimitive()) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux dg = DGMulti(polydeg = 3, element_type = Tri(), approximation_type = Polynomial(), surface_integral = SurfaceIntegralWeakForm(flux_lax_friedrichs), volume_integral = VolumeIntegralWeakForm()) -top_bottom(x, tol=50*eps()) = abs(abs(x[2]) - 1) < tol +top_bottom(x, tol = 50 * eps()) = abs(abs(x[2]) - 1) < tol is_on_boundary = Dict(:top_bottom => top_bottom) function mapping(xi, eta) - x = xi + 0.1 * sin(pi * xi) * sin(pi * eta) - y = eta + 0.1 * sin(pi * xi) * sin(pi * eta) - return SVector(x, y) + x = xi + 0.1 * sin(pi * xi) * sin(pi * eta) + y = eta + 0.1 * sin(pi * xi) * sin(pi * eta) + return SVector(x, y) end cells_per_dimension = (16, 16) -mesh = DGMultiMesh(dg, cells_per_dimension, mapping; periodicity=(true, false), is_on_boundary) +mesh = DGMultiMesh(dg, cells_per_dimension, mapping; periodicity = (true, false), + is_on_boundary) # This initial condition is taken from `examples/dgmulti_2d/elixir_navierstokes_convergence.jl` @@ -36,150 +38,160 @@ mesh = DGMultiMesh(dg, cells_per_dimension, mapping; periodicity=(true, false), # and by the initial condition (which passes in `CompressibleEulerEquations2D`). # This convergence test setup was originally derived by Andrew Winters (@andrewwinters5000) function initial_condition_navier_stokes_convergence_test(x, t, equations) - # Amplitude and shift - A = 0.5 - c = 2.0 + # Amplitude and shift + A = 0.5 + c = 2.0 - # convenience values for trig. functions - pi_x = pi * x[1] - pi_y = pi * x[2] - pi_t = pi * t + # convenience values for trig. functions + pi_x = pi * x[1] + pi_y = pi * x[2] + pi_t = pi * t - rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t) - v1 = sin(pi_x) * log(x[2] + 2.0) * (1.0 - exp(-A * (x[2] - 1.0)) ) * cos(pi_t) - v2 = v1 - p = rho^2 + rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t) + v1 = sin(pi_x) * log(x[2] + 2.0) * (1.0 - exp(-A * (x[2] - 1.0))) * cos(pi_t) + v2 = v1 + p = rho^2 - return prim2cons(SVector(rho, v1, v2, p), equations) + return prim2cons(SVector(rho, v1, v2, p), equations) end @inline function source_terms_navier_stokes_convergence_test(u, x, t, equations) - y = x[2] - - # TODO: parabolic - # we currently need to hardcode these parameters until we fix the "combined equation" issue - # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 - inv_gamma_minus_one = inv(equations.gamma - 1) - Pr = prandtl_number() - mu_ = mu() - - # Same settings as in `initial_condition` - # Amplitude and shift - A = 0.5 - c = 2.0 - - # convenience values for trig. functions - pi_x = pi * x[1] - pi_y = pi * x[2] - pi_t = pi * t - - # compute the manufactured solution and all necessary derivatives - rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t) - rho_t = -pi * A * sin(pi_x) * cos(pi_y) * sin(pi_t) - rho_x = pi * A * cos(pi_x) * cos(pi_y) * cos(pi_t) - rho_y = -pi * A * sin(pi_x) * sin(pi_y) * cos(pi_t) - rho_xx = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t) - rho_yy = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t) - - v1 = sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) - v1_t = -pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * sin(pi_t) - v1_x = pi * cos(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) - v1_y = sin(pi_x) * (A * log(y + 2.0) * exp(-A * (y - 1.0)) + (1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t) - v1_xx = -pi * pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) - v1_xy = pi * cos(pi_x) * (A * log(y + 2.0) * exp(-A * (y - 1.0)) + (1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t) - v1_yy = (sin(pi_x) * ( 2.0 * A * exp(-A * (y - 1.0)) / (y + 2.0) - - A * A * log(y + 2.0) * exp(-A * (y - 1.0)) - - (1.0 - exp(-A * (y - 1.0))) / ((y + 2.0) * (y + 2.0))) * cos(pi_t)) - v2 = v1 - v2_t = v1_t - v2_x = v1_x - v2_y = v1_y - v2_xx = v1_xx - v2_xy = v1_xy - v2_yy = v1_yy - - p = rho * rho - p_t = 2.0 * rho * rho_t - p_x = 2.0 * rho * rho_x - p_y = 2.0 * rho * rho_y - p_xx = 2.0 * rho * rho_xx + 2.0 * rho_x * rho_x - p_yy = 2.0 * rho * rho_yy + 2.0 * rho_y * rho_y - - # Note this simplifies slightly because the ansatz assumes that v1 = v2 - E = p * inv_gamma_minus_one + 0.5 * rho * (v1^2 + v2^2) - E_t = p_t * inv_gamma_minus_one + rho_t * v1^2 + 2.0 * rho * v1 * v1_t - E_x = p_x * inv_gamma_minus_one + rho_x * v1^2 + 2.0 * rho * v1 * v1_x - E_y = p_y * inv_gamma_minus_one + rho_y * v1^2 + 2.0 * rho * v1 * v1_y - - # Some convenience constants - T_const = equations.gamma * inv_gamma_minus_one / Pr - inv_rho_cubed = 1.0 / (rho^3) - - # compute the source terms - # density equation - du1 = rho_t + rho_x * v1 + rho * v1_x + rho_y * v2 + rho * v2_y - - # x-momentum equation - du2 = ( rho_t * v1 + rho * v1_t + p_x + rho_x * v1^2 - + 2.0 * rho * v1 * v1_x - + rho_y * v1 * v2 - + rho * v1_y * v2 - + rho * v1 * v2_y - # stress tensor from x-direction - - 4.0 / 3.0 * v1_xx * mu_ - + 2.0 / 3.0 * v2_xy * mu_ - - v1_yy * mu_ - - v2_xy * mu_ ) - # y-momentum equation - du3 = ( rho_t * v2 + rho * v2_t + p_y + rho_x * v1 * v2 - + rho * v1_x * v2 - + rho * v1 * v2_x - + rho_y * v2^2 - + 2.0 * rho * v2 * v2_y - # stress tensor from y-direction - - v1_xy * mu_ - - v2_xx * mu_ - - 4.0 / 3.0 * v2_yy * mu_ - + 2.0 / 3.0 * v1_xy * mu_ ) - # total energy equation - du4 = ( E_t + v1_x * (E + p) + v1 * (E_x + p_x) - + v2_y * (E + p) + v2 * (E_y + p_y) - # stress tensor and temperature gradient terms from x-direction - - 4.0 / 3.0 * v1_xx * v1 * mu_ - + 2.0 / 3.0 * v2_xy * v1 * mu_ - - 4.0 / 3.0 * v1_x * v1_x * mu_ - + 2.0 / 3.0 * v2_y * v1_x * mu_ - - v1_xy * v2 * mu_ - - v2_xx * v2 * mu_ - - v1_y * v2_x * mu_ - - v2_x * v2_x * mu_ - - T_const * inv_rho_cubed * ( p_xx * rho * rho - - 2.0 * p_x * rho * rho_x - + 2.0 * p * rho_x * rho_x - - p * rho * rho_xx ) * mu_ - # stress tensor and temperature gradient terms from y-direction - - v1_yy * v1 * mu_ - - v2_xy * v1 * mu_ - - v1_y * v1_y * mu_ - - v2_x * v1_y * mu_ - - 4.0 / 3.0 * v2_yy * v2 * mu_ - + 2.0 / 3.0 * v1_xy * v2 * mu_ - - 4.0 / 3.0 * v2_y * v2_y * mu_ - + 2.0 / 3.0 * v1_x * v2_y * mu_ - - T_const * inv_rho_cubed * ( p_yy * rho * rho - - 2.0 * p_y * rho * rho_y - + 2.0 * p * rho_y * rho_y - - p * rho * rho_yy ) * mu_ ) - - return SVector(du1, du2, du3, du4) + y = x[2] + + # TODO: parabolic + # we currently need to hardcode these parameters until we fix the "combined equation" issue + # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 + inv_gamma_minus_one = inv(equations.gamma - 1) + Pr = prandtl_number() + mu_ = mu() + + # Same settings as in `initial_condition` + # Amplitude and shift + A = 0.5 + c = 2.0 + + # convenience values for trig. functions + pi_x = pi * x[1] + pi_y = pi * x[2] + pi_t = pi * t + + # compute the manufactured solution and all necessary derivatives + rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t) + rho_t = -pi * A * sin(pi_x) * cos(pi_y) * sin(pi_t) + rho_x = pi * A * cos(pi_x) * cos(pi_y) * cos(pi_t) + rho_y = -pi * A * sin(pi_x) * sin(pi_y) * cos(pi_t) + rho_xx = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t) + rho_yy = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t) + + v1 = sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) + v1_t = -pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * sin(pi_t) + v1_x = pi * cos(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) + v1_y = sin(pi_x) * + (A * log(y + 2.0) * exp(-A * (y - 1.0)) + + (1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t) + v1_xx = -pi * pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) + v1_xy = pi * cos(pi_x) * + (A * log(y + 2.0) * exp(-A * (y - 1.0)) + + (1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t) + v1_yy = (sin(pi_x) * + (2.0 * A * exp(-A * (y - 1.0)) / (y + 2.0) - + A * A * log(y + 2.0) * exp(-A * (y - 1.0)) - + (1.0 - exp(-A * (y - 1.0))) / ((y + 2.0) * (y + 2.0))) * cos(pi_t)) + v2 = v1 + v2_t = v1_t + v2_x = v1_x + v2_y = v1_y + v2_xx = v1_xx + v2_xy = v1_xy + v2_yy = v1_yy + + p = rho * rho + p_t = 2.0 * rho * rho_t + p_x = 2.0 * rho * rho_x + p_y = 2.0 * rho * rho_y + p_xx = 2.0 * rho * rho_xx + 2.0 * rho_x * rho_x + p_yy = 2.0 * rho * rho_yy + 2.0 * rho_y * rho_y + + # Note this simplifies slightly because the ansatz assumes that v1 = v2 + E = p * inv_gamma_minus_one + 0.5 * rho * (v1^2 + v2^2) + E_t = p_t * inv_gamma_minus_one + rho_t * v1^2 + 2.0 * rho * v1 * v1_t + E_x = p_x * inv_gamma_minus_one + rho_x * v1^2 + 2.0 * rho * v1 * v1_x + E_y = p_y * inv_gamma_minus_one + rho_y * v1^2 + 2.0 * rho * v1 * v1_y + + # Some convenience constants + T_const = equations.gamma * inv_gamma_minus_one / Pr + inv_rho_cubed = 1.0 / (rho^3) + + # compute the source terms + # density equation + du1 = rho_t + rho_x * v1 + rho * v1_x + rho_y * v2 + rho * v2_y + + # x-momentum equation + du2 = (rho_t * v1 + rho * v1_t + p_x + rho_x * v1^2 + + 2.0 * rho * v1 * v1_x + + rho_y * v1 * v2 + + rho * v1_y * v2 + + rho * v1 * v2_y - + # stress tensor from x-direction + 4.0 / 3.0 * v1_xx * mu_ + + 2.0 / 3.0 * v2_xy * mu_ - + v1_yy * mu_ - + v2_xy * mu_) + # y-momentum equation + du3 = (rho_t * v2 + rho * v2_t + p_y + rho_x * v1 * v2 + + rho * v1_x * v2 + + rho * v1 * v2_x + + rho_y * v2^2 + + 2.0 * rho * v2 * v2_y - + # stress tensor from y-direction + v1_xy * mu_ - + v2_xx * mu_ - + 4.0 / 3.0 * v2_yy * mu_ + + 2.0 / 3.0 * v1_xy * mu_) + # total energy equation + du4 = (E_t + v1_x * (E + p) + v1 * (E_x + p_x) + + v2_y * (E + p) + v2 * (E_y + p_y) - + # stress tensor and temperature gradient terms from x-direction + 4.0 / 3.0 * v1_xx * v1 * mu_ + + 2.0 / 3.0 * v2_xy * v1 * mu_ - + 4.0 / 3.0 * v1_x * v1_x * mu_ + + 2.0 / 3.0 * v2_y * v1_x * mu_ - + v1_xy * v2 * mu_ - + v2_xx * v2 * mu_ - + v1_y * v2_x * mu_ - + v2_x * v2_x * mu_ - + T_const * inv_rho_cubed * + (p_xx * rho * rho - + 2.0 * p_x * rho * rho_x + + 2.0 * p * rho_x * rho_x - + p * rho * rho_xx) * mu_ - + # stress tensor and temperature gradient terms from y-direction + v1_yy * v1 * mu_ - + v2_xy * v1 * mu_ - + v1_y * v1_y * mu_ - + v2_x * v1_y * mu_ - + 4.0 / 3.0 * v2_yy * v2 * mu_ + + 2.0 / 3.0 * v1_xy * v2 * mu_ - + 4.0 / 3.0 * v2_y * v2_y * mu_ + + 2.0 / 3.0 * v1_x * v2_y * mu_ - + T_const * inv_rho_cubed * + (p_yy * rho * rho - + 2.0 * p_y * rho * rho_y + + 2.0 * p * rho_y * rho_y - + p * rho * rho_yy) * mu_) + + return SVector(du1, du2, du3, du4) end initial_condition = initial_condition_navier_stokes_convergence_test # BC types -velocity_bc_top_bottom = NoSlip((x, t, equations) -> initial_condition_navier_stokes_convergence_test(x, t, equations)[2:3]) +velocity_bc_top_bottom = NoSlip((x, t, equations) -> initial_condition_navier_stokes_convergence_test(x, + t, + equations)[2:3]) heat_bc_top_bottom = Adiabatic((x, t, equations) -> 0.0) -boundary_condition_top_bottom = BoundaryConditionNavierStokesWall(velocity_bc_top_bottom, heat_bc_top_bottom) +boundary_condition_top_bottom = BoundaryConditionNavierStokesWall(velocity_bc_top_bottom, + heat_bc_top_bottom) # define inviscid boundary conditions boundary_conditions = (; :top_bottom => boundary_condition_slip_wall) @@ -187,10 +199,11 @@ boundary_conditions = (; :top_bottom => boundary_condition_slip_wall) # define viscous boundary conditions boundary_conditions_parabolic = (; :top_bottom => boundary_condition_top_bottom) -semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, dg; - boundary_conditions=(boundary_conditions, boundary_conditions_parabolic), - source_terms=source_terms_navier_stokes_convergence_test) - +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, dg; + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic), + source_terms = source_terms_navier_stokes_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -200,15 +213,15 @@ tspan = (0.0, 0.5) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) callbacks = CallbackSet(summary_callback, alive_callback) ############################################################################### # run the simulation time_int_tol = 1e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary diff --git a/examples/dgmulti_2d/elixir_navierstokes_lid_driven_cavity.jl b/examples/dgmulti_2d/elixir_navierstokes_lid_driven_cavity.jl index 97b779ebaf9..7c55cbf0ccf 100644 --- a/examples/dgmulti_2d/elixir_navierstokes_lid_driven_cavity.jl +++ b/examples/dgmulti_2d/elixir_navierstokes_lid_driven_cavity.jl @@ -9,28 +9,27 @@ prandtl_number() = 0.72 mu() = 0.001 equations = CompressibleEulerEquations2D(1.4) -equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu=mu(), - Prandtl=prandtl_number()) - +equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu = mu(), + Prandtl = prandtl_number()) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux dg = DGMulti(polydeg = 3, element_type = Quad(), approximation_type = GaussSBP(), surface_integral = SurfaceIntegralWeakForm(flux_lax_friedrichs), volume_integral = VolumeIntegralFluxDifferencing(flux_ranocha)) -top(x, tol=50*eps()) = abs(x[2] - 1) < tol -rest_of_boundary(x, tol=50*eps()) = !top(x, tol) +top(x, tol = 50 * eps()) = abs(x[2] - 1) < tol +rest_of_boundary(x, tol = 50 * eps()) = !top(x, tol) is_on_boundary = Dict(:top => top, :rest_of_boundary => rest_of_boundary) cells_per_dimension = (16, 16) mesh = DGMultiMesh(dg, cells_per_dimension; is_on_boundary) function initial_condition_cavity(x, t, equations::CompressibleEulerEquations2D) - Ma = 0.1 - rho = 1.0 - u, v = 0.0, 0.0 - p = 1.0 / (Ma^2 * equations.gamma) - return prim2cons(SVector(rho, u, v, p), equations) + Ma = 0.1 + rho = 1.0 + u, v = 0.0, 0.0 + p = 1.0 / (Ma^2 * equations.gamma) + return prim2cons(SVector(rho, u, v, p), equations) end initial_condition = initial_condition_cavity @@ -43,15 +42,16 @@ boundary_condition_cavity = BoundaryConditionNavierStokesWall(velocity_bc_cavity # define inviscid boundary conditions boundary_conditions = (; :top => boundary_condition_slip_wall, - :rest_of_boundary => boundary_condition_slip_wall) + :rest_of_boundary => boundary_condition_slip_wall) # define viscous boundary conditions boundary_conditions_parabolic = (; :top => boundary_condition_lid, - :rest_of_boundary => boundary_condition_cavity) - -semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, dg; - boundary_conditions=(boundary_conditions, boundary_conditions_parabolic)) + :rest_of_boundary => boundary_condition_cavity) +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, dg; + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic)) ############################################################################### # ODE solvers, callbacks etc. @@ -61,15 +61,15 @@ tspan = (0.0, 10.0) ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) callbacks = CallbackSet(summary_callback, alive_callback) ############################################################################### # run the simulation time_int_tol = 1e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary diff --git a/examples/dgmulti_2d/elixir_shallowwater_source_terms.jl b/examples/dgmulti_2d/elixir_shallowwater_source_terms.jl index 3551c863ff2..f7120d8091b 100644 --- a/examples/dgmulti_2d/elixir_shallowwater_source_terms.jl +++ b/examples/dgmulti_2d/elixir_shallowwater_source_terms.jl @@ -4,24 +4,23 @@ using Trixi ############################################################################### # semidiscretization of the shallow water equations -equations = ShallowWaterEquations2D(gravity_constant=9.81) +equations = ShallowWaterEquations2D(gravity_constant = 9.81) initial_condition = initial_condition_convergence_test volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) surface_flux = (flux_lax_friedrichs, flux_nonconservative_fjordholm_etal) -dg = DGMulti(polydeg=3, element_type = Quad(), approximation_type = SBP(), +dg = DGMulti(polydeg = 3, element_type = Quad(), approximation_type = SBP(), surface_integral = SurfaceIntegralWeakForm(surface_flux), volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) cells_per_dimension = (8, 8) mesh = DGMultiMesh(dg, cells_per_dimension, - coordinates_min=(0.0, 0.0), coordinates_max=(sqrt(2), sqrt(2)), - periodicity=true) - + coordinates_min = (0.0, 0.0), coordinates_max = (sqrt(2), sqrt(2)), + periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, dg; - source_terms=source_terms_convergence_test) + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -32,8 +31,8 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) +alive_callback = AliveCallback(analysis_interval = analysis_interval) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -42,7 +41,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, RDPK3SpFSAL49(); abstol=1.0e-7, reltol=1.0e-7, - ode_default_options()..., callback=callbacks); +sol = solve(ode, RDPK3SpFSAL49(); abstol = 1.0e-7, reltol = 1.0e-7, + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/dgmulti_3d/elixir_advection_tensor_wedge.jl b/examples/dgmulti_3d/elixir_advection_tensor_wedge.jl index 4f43f2571a3..e877e602547 100644 --- a/examples/dgmulti_3d/elixir_advection_tensor_wedge.jl +++ b/examples/dgmulti_3d/elixir_advection_tensor_wedge.jl @@ -16,17 +16,15 @@ dg = DGMulti(element_type = Wedge(), surface_flux = flux_lax_friedrichs, polydeg = tensor_polydeg) - cells_per_dimension = (8, 8, 8) -mesh = DGMultiMesh(dg, +mesh = DGMultiMesh(dg, cells_per_dimension, - coordinates_min = (-1.0, -1.0, -1.0), + coordinates_min = (-1.0, -1.0, -1.0), coordinates_max = (1.0, 1.0, 1.0), periodicity = true) - semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, dg, - boundary_conditions=boundary_condition_periodic) + boundary_conditions = boundary_condition_periodic) ############################################################################### # ODE solvers, callbacks etc. @@ -37,20 +35,20 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.0) - -callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, stepsize_callback) +stepsize_callback = StepsizeCallback(cfl = 1.0) +callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, + stepsize_callback) ############################################################################### # run the simulation sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), dt = 1.0, - save_everystep=false, callback=callbacks); + save_everystep = false, callback = callbacks); -summary_callback() # print the timer summary \ No newline at end of file +summary_callback() # print the timer summary diff --git a/examples/dgmulti_3d/elixir_euler_curved.jl b/examples/dgmulti_3d/elixir_euler_curved.jl index d8c4df5dd64..67c84b50974 100644 --- a/examples/dgmulti_3d/elixir_euler_curved.jl +++ b/examples/dgmulti_3d/elixir_euler_curved.jl @@ -1,7 +1,7 @@ using Trixi, OrdinaryDiffEq -dg = DGMulti(polydeg = 3, element_type = Hex(), approximation_type=SBP(), +dg = DGMulti(polydeg = 3, element_type = Hex(), approximation_type = SBP(), surface_integral = SurfaceIntegralWeakForm(flux_hll), volume_integral = VolumeIntegralFluxDifferencing(flux_ranocha)) @@ -10,22 +10,22 @@ initial_condition = initial_condition_convergence_test source_terms = source_terms_convergence_test # example where we tag two separate boundary segments of the mesh -top_boundary(x, tol=50*eps()) = abs(x[2] - 1) < tol -rest_of_boundary(x, tol=50*eps()) = !top_boundary(x, tol) +top_boundary(x, tol = 50 * eps()) = abs(x[2] - 1) < tol +rest_of_boundary(x, tol = 50 * eps()) = !top_boundary(x, tol) is_on_boundary = Dict(:top => top_boundary, :rest => rest_of_boundary) function mapping(xi, eta, zeta) - x = xi + 0.1 * sin(pi * xi) * sin(pi * eta) - y = eta + 0.1 * sin(pi * xi) * sin(pi * eta) - z = zeta + 0.1 * sin(pi * xi) * sin(pi * eta) - return SVector(x, y, z) + x = xi + 0.1 * sin(pi * xi) * sin(pi * eta) + y = eta + 0.1 * sin(pi * xi) * sin(pi * eta) + z = zeta + 0.1 * sin(pi * xi) * sin(pi * eta) + return SVector(x, y, z) end cells_per_dimension = (4, 4, 4) -mesh = DGMultiMesh(dg, cells_per_dimension, mapping, is_on_boundary=is_on_boundary) +mesh = DGMultiMesh(dg, cells_per_dimension, mapping, is_on_boundary = is_on_boundary) boundary_condition_convergence_test = BoundaryConditionDirichlet(initial_condition) boundary_conditions = (; :top => boundary_condition_convergence_test, - :rest => boundary_condition_convergence_test) + :rest => boundary_condition_convergence_test) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, dg, source_terms = source_terms, @@ -35,14 +35,14 @@ tspan = (0.0, 0.1) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt = 0.5 * estimate_dt(mesh, dg), save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 0.5 * estimate_dt(mesh, dg), save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/dgmulti_3d/elixir_euler_fdsbp_periodic.jl b/examples/dgmulti_3d/elixir_euler_fdsbp_periodic.jl index 35f7aee8795..0eb38674689 100644 --- a/examples/dgmulti_3d/elixir_euler_fdsbp_periodic.jl +++ b/examples/dgmulti_3d/elixir_euler_fdsbp_periodic.jl @@ -10,19 +10,20 @@ equations = CompressibleEulerEquations3D(1.4) initial_condition = initial_condition_convergence_test source_terms = source_terms_convergence_test -volume_flux = flux_ranocha +volume_flux = flux_ranocha solver = DGMulti(element_type = Hex(), - approximation_type = periodic_derivative_operator( - derivative_order=1, accuracy_order=4, xmin=0.0, xmax=1.0, N=20), + approximation_type = periodic_derivative_operator(derivative_order = 1, + accuracy_order = 4, + xmin = 0.0, xmax = 1.0, + N = 20), surface_flux = flux_lax_friedrichs, volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) -mesh = DGMultiMesh(solver, coordinates_min=(-1.0, -1.0, -1.0), - coordinates_max=( 1.0, 1.0, 1.0)) +mesh = DGMultiMesh(solver, coordinates_min = (-1.0, -1.0, -1.0), + coordinates_max = (1.0, 1.0, 1.0)) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver; - source_terms=source_terms) - + source_terms = source_terms) ############################################################################### # ODE solvers, callbacks etc. @@ -33,14 +34,14 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(solver)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + uEltype = real(solver)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) - ############################################################################### # run the simulation diff --git a/examples/dgmulti_3d/elixir_euler_taylor_green_vortex.jl b/examples/dgmulti_3d/elixir_euler_taylor_green_vortex.jl index 253d2486468..fea43ad4d26 100644 --- a/examples/dgmulti_3d/elixir_euler_taylor_green_vortex.jl +++ b/examples/dgmulti_3d/elixir_euler_taylor_green_vortex.jl @@ -12,35 +12,38 @@ equations = CompressibleEulerEquations3D(1.4) The classical inviscid Taylor-Green vortex. """ -function initial_condition_taylor_green_vortex(x, t, equations::CompressibleEulerEquations3D) - A = 1.0 # magnitude of speed - Ms = 0.1 # maximum Mach number - - rho = 1.0 - v1 = A * sin(x[1]) * cos(x[2]) * cos(x[3]) - v2 = -A * cos(x[1]) * sin(x[2]) * cos(x[3]) - v3 = 0.0 - p = (A / Ms)^2 * rho / equations.gamma # scaling to get Ms - p = p + 1.0/16.0 * A^2 * rho * (cos(2*x[1])*cos(2*x[3]) + 2*cos(2*x[2]) + 2*cos(2*x[1]) + cos(2*x[2])*cos(2*x[3])) - - return prim2cons(SVector(rho, v1, v2, v3, p), equations) +function initial_condition_taylor_green_vortex(x, t, + equations::CompressibleEulerEquations3D) + A = 1.0 # magnitude of speed + Ms = 0.1 # maximum Mach number + + rho = 1.0 + v1 = A * sin(x[1]) * cos(x[2]) * cos(x[3]) + v2 = -A * cos(x[1]) * sin(x[2]) * cos(x[3]) + v3 = 0.0 + p = (A / Ms)^2 * rho / equations.gamma # scaling to get Ms + p = p + + 1.0 / 16.0 * A^2 * rho * + (cos(2 * x[1]) * cos(2 * x[3]) + 2 * cos(2 * x[2]) + 2 * cos(2 * x[1]) + + cos(2 * x[2]) * cos(2 * x[3])) + + return prim2cons(SVector(rho, v1, v2, v3, p), equations) end initial_condition = initial_condition_taylor_green_vortex -volume_flux = flux_ranocha +volume_flux = flux_ranocha surface_flux = flux_lax_friedrichs solver = DGMulti(polydeg = 3, element_type = Hex(), approximation_type = Polynomial(), - surface_integral= SurfaceIntegralWeakForm(surface_flux), - volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) + surface_integral = SurfaceIntegralWeakForm(surface_flux), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) cells_per_dimension = (8, 8, 8) mesh = DGMultiMesh(solver, cells_per_dimension, - coordinates_min=(-pi, -pi, -pi), coordinates_max=(pi, pi, pi), - periodicity=true) + coordinates_min = (-pi, -pi, -pi), coordinates_max = (pi, pi, pi), + periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -50,14 +53,14 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(solver)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + uEltype = real(solver)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) - ############################################################################### # run the simulation diff --git a/examples/dgmulti_3d/elixir_euler_weakform.jl b/examples/dgmulti_3d/elixir_euler_weakform.jl index b167377af51..6e06b35c4f6 100644 --- a/examples/dgmulti_3d/elixir_euler_weakform.jl +++ b/examples/dgmulti_3d/elixir_euler_weakform.jl @@ -10,16 +10,16 @@ initial_condition = initial_condition_convergence_test source_terms = source_terms_convergence_test # example where we tag two separate boundary segments of the mesh -top_boundary(x, tol=50*eps()) = abs(x[2] - 1) < tol -rest_of_boundary(x, tol=50*eps()) = !top_boundary(x, tol) +top_boundary(x, tol = 50 * eps()) = abs(x[2] - 1) < tol +rest_of_boundary(x, tol = 50 * eps()) = !top_boundary(x, tol) is_on_boundary = Dict(:top => top_boundary, :rest => rest_of_boundary) cells_per_dimension = (4, 4, 4) -mesh = DGMultiMesh(dg, cells_per_dimension, is_on_boundary=is_on_boundary) +mesh = DGMultiMesh(dg, cells_per_dimension, is_on_boundary = is_on_boundary) boundary_condition_convergence_test = BoundaryConditionDirichlet(initial_condition) boundary_conditions = (; :top => boundary_condition_convergence_test, - :rest => boundary_condition_convergence_test) + :rest => boundary_condition_convergence_test) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, dg, source_terms = source_terms, @@ -29,14 +29,14 @@ tspan = (0.0, 0.1) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt = 0.5 * estimate_dt(mesh, dg), save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 0.5 * estimate_dt(mesh, dg), save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/dgmulti_3d/elixir_euler_weakform_periodic.jl b/examples/dgmulti_3d/elixir_euler_weakform_periodic.jl index 6b17d4bba65..bc963a3a2fd 100644 --- a/examples/dgmulti_3d/elixir_euler_weakform_periodic.jl +++ b/examples/dgmulti_3d/elixir_euler_weakform_periodic.jl @@ -10,7 +10,7 @@ initial_condition = initial_condition_convergence_test source_terms = source_terms_convergence_test cells_per_dimension = (4, 4, 4) -mesh = DGMultiMesh(dg, cells_per_dimension, periodicity=true) +mesh = DGMultiMesh(dg, cells_per_dimension, periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, dg, source_terms = source_terms) @@ -19,14 +19,14 @@ tspan = (0.0, 0.1) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt = 0.5 * estimate_dt(mesh, dg), save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 0.5 * estimate_dt(mesh, dg), save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/dgmulti_3d/elixir_navierstokes_convergence.jl b/examples/dgmulti_3d/elixir_navierstokes_convergence.jl index 9a237b2d2fc..5fa0ad7ce60 100644 --- a/examples/dgmulti_3d/elixir_navierstokes_convergence.jl +++ b/examples/dgmulti_3d/elixir_navierstokes_convergence.jl @@ -8,219 +8,225 @@ prandtl_number() = 0.72 mu() = 0.01 equations = CompressibleEulerEquations3D(1.4) -equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu=mu(), Prandtl=prandtl_number(), - gradient_variables=GradientVariablesPrimitive()) +equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu = mu(), + Prandtl = prandtl_number(), + gradient_variables = GradientVariablesPrimitive()) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux dg = DGMulti(polydeg = 3, element_type = Hex(), approximation_type = Polynomial(), surface_integral = SurfaceIntegralWeakForm(flux_lax_friedrichs), volume_integral = VolumeIntegralWeakForm()) -top_bottom(x, tol=50*eps()) = abs(abs(x[2]) - 1) < tol +top_bottom(x, tol = 50 * eps()) = abs(abs(x[2]) - 1) < tol is_on_boundary = Dict(:top_bottom => top_bottom) cells_per_dimension = (8, 8, 8) -mesh = DGMultiMesh(dg, cells_per_dimension; periodicity=(true, false, true), is_on_boundary) +mesh = DGMultiMesh(dg, cells_per_dimension; periodicity = (true, false, true), + is_on_boundary) # Note: the initial condition cannot be specialized to `CompressibleNavierStokesDiffusion3D` # since it is called by both the parabolic solver (which passes in `CompressibleNavierStokesDiffusion3D`) # and by the initial condition (which passes in `CompressibleEulerEquations3D`). # This convergence test setup was originally derived by Andrew Winters (@andrewwinters5000) function initial_condition_navier_stokes_convergence_test(x, t, equations) - # Constants. OBS! Must match those in `source_terms_navier_stokes_convergence_test` - c = 2.0 - A1 = 0.5 - A2 = 1.0 - A3 = 0.5 - - # Convenience values for trig. functions - pi_x = pi * x[1] - pi_y = pi * x[2] - pi_z = pi * x[3] - pi_t = pi * t - - rho = c + A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) - v1 = A2 * sin(pi_x) * log(x[2] + 2.0) * (1.0 - exp(-A3 * (x[2] - 1.0))) * sin(pi_z) * cos(pi_t) - v2 = v1 - v3 = v1 - p = rho^2 - - return prim2cons(SVector(rho, v1, v2, v3, p), equations) + # Constants. OBS! Must match those in `source_terms_navier_stokes_convergence_test` + c = 2.0 + A1 = 0.5 + A2 = 1.0 + A3 = 0.5 + + # Convenience values for trig. functions + pi_x = pi * x[1] + pi_y = pi * x[2] + pi_z = pi * x[3] + pi_t = pi * t + + rho = c + A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) + v1 = A2 * sin(pi_x) * log(x[2] + 2.0) * (1.0 - exp(-A3 * (x[2] - 1.0))) * sin(pi_z) * + cos(pi_t) + v2 = v1 + v3 = v1 + p = rho^2 + + return prim2cons(SVector(rho, v1, v2, v3, p), equations) end @inline function source_terms_navier_stokes_convergence_test(u, x, t, equations) - # TODO: parabolic - # we currently need to hardcode these parameters until we fix the "combined equation" issue - # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 - inv_gamma_minus_one = inv(equations.gamma - 1) - Pr = prandtl_number() - mu_ = mu() - - # Constants. OBS! Must match those in `initial_condition_navier_stokes_convergence_test` - c = 2.0 - A1 = 0.5 - A2 = 1.0 - A3 = 0.5 - - # Convenience values for trig. functions - pi_x = pi * x[1] - pi_y = pi * x[2] - pi_z = pi * x[3] - pi_t = pi * t - - # Define auxiliary functions for the strange function of the y variable - # to make expressions easier to read - g = log(x[2] + 2.0) * (1.0 - exp(-A3 * (x[2] - 1.0))) - g_y = ( A3 * log(x[2] + 2.0) * exp(-A3 * (x[2] - 1.0)) - + (1.0 - exp(-A3 * (x[2] - 1.0))) / (x[2] + 2.0) ) - g_yy = ( 2.0 * A3 * exp(-A3 * (x[2] - 1.0)) / (x[2] + 2.0) - - (1.0 - exp(-A3 * (x[2] - 1.0))) / ((x[2] + 2.0)^2) - - A3^2 * log(x[2] + 2.0) * exp(-A3 * (x[2] - 1.0)) ) - - # Density and its derivatives - rho = c + A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) - rho_t = -pi * A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * sin(pi_t) - rho_x = pi * A1 * cos(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) - rho_y = -pi * A1 * sin(pi_x) * sin(pi_y) * sin(pi_z) * cos(pi_t) - rho_z = pi * A1 * sin(pi_x) * cos(pi_y) * cos(pi_z) * cos(pi_t) - rho_xx = -pi^2 * (rho - c) - rho_yy = -pi^2 * (rho - c) - rho_zz = -pi^2 * (rho - c) - - # Velocities and their derivatives - # v1 terms - v1 = A2 * sin(pi_x) * g * sin(pi_z) * cos(pi_t) - v1_t = -pi * A2 * sin(pi_x) * g * sin(pi_z) * sin(pi_t) - v1_x = pi * A2 * cos(pi_x) * g * sin(pi_z) * cos(pi_t) - v1_y = A2 * sin(pi_x) * g_y * sin(pi_z) * cos(pi_t) - v1_z = pi * A2 * sin(pi_x) * g * cos(pi_z) * cos(pi_t) - v1_xx = -pi^2 * v1 - v1_yy = A2 * sin(pi_x) * g_yy * sin(pi_z) * cos(pi_t) - v1_zz = -pi^2 * v1 - v1_xy = pi * A2 * cos(pi_x) * g_y * sin(pi_z) * cos(pi_t) - v1_xz = pi^2 * A2 * cos(pi_x) * g * cos(pi_z) * cos(pi_t) - v1_yz = pi * A2 * sin(pi_x) * g_y * cos(pi_z) * cos(pi_t) - # v2 terms (simplifies from ansatz) - v2 = v1 - v2_t = v1_t - v2_x = v1_x - v2_y = v1_y - v2_z = v1_z - v2_xx = v1_xx - v2_yy = v1_yy - v2_zz = v1_zz - v2_xy = v1_xy - v2_yz = v1_yz - # v3 terms (simplifies from ansatz) - v3 = v1 - v3_t = v1_t - v3_x = v1_x - v3_y = v1_y - v3_z = v1_z - v3_xx = v1_xx - v3_yy = v1_yy - v3_zz = v1_zz - v3_xz = v1_xz - v3_yz = v1_yz - - # Pressure and its derivatives - p = rho^2 - p_t = 2.0 * rho * rho_t - p_x = 2.0 * rho * rho_x - p_y = 2.0 * rho * rho_y - p_z = 2.0 * rho * rho_z - - # Total energy and its derivatives; simiplifies from ansatz that v2 = v1 and v3 = v1 - E = p * inv_gamma_minus_one + 1.5 * rho * v1^2 - E_t = p_t * inv_gamma_minus_one + 1.5 * rho_t * v1^2 + 3.0 * rho * v1 * v1_t - E_x = p_x * inv_gamma_minus_one + 1.5 * rho_x * v1^2 + 3.0 * rho * v1 * v1_x - E_y = p_y * inv_gamma_minus_one + 1.5 * rho_y * v1^2 + 3.0 * rho * v1 * v1_y - E_z = p_z * inv_gamma_minus_one + 1.5 * rho_z * v1^2 + 3.0 * rho * v1 * v1_z - - # Divergence of Fick's law ∇⋅∇q = kappa ∇⋅∇T; simplifies because p = rho², so T = p/rho = rho - kappa = equations.gamma * inv_gamma_minus_one / Pr - q_xx = kappa * rho_xx # kappa T_xx - q_yy = kappa * rho_yy # kappa T_yy - q_zz = kappa * rho_zz # kappa T_zz - - # Stress tensor and its derivatives (exploit symmetry) - tau11 = 4.0 / 3.0 * v1_x - 2.0 / 3.0 * (v2_y + v3_z) - tau12 = v1_y + v2_x - tau13 = v1_z + v3_x - tau22 = 4.0 / 3.0 * v2_y - 2.0 / 3.0 * (v1_x + v3_z) - tau23 = v2_z + v3_y - tau33 = 4.0 / 3.0 * v3_z - 2.0 / 3.0 * (v1_x + v2_y) - - tau11_x = 4.0 / 3.0 * v1_xx - 2.0 / 3.0 * (v2_xy + v3_xz) - tau12_x = v1_xy + v2_xx - tau13_x = v1_xz + v3_xx - - tau12_y = v1_yy + v2_xy - tau22_y = 4.0 / 3.0 * v2_yy - 2.0 / 3.0 * (v1_xy + v3_yz) - tau23_y = v2_yz + v3_yy - - tau13_z = v1_zz + v3_xz - tau23_z = v2_zz + v3_yz - tau33_z = 4.0 / 3.0 * v3_zz - 2.0 / 3.0 * (v1_xz + v2_yz) - - # Compute the source terms - # Density equation - du1 = ( rho_t + rho_x * v1 + rho * v1_x - + rho_y * v2 + rho * v2_y - + rho_z * v3 + rho * v3_z ) - # x-momentum equation - du2 = ( rho_t * v1 + rho * v1_t + p_x + rho_x * v1^2 - + 2.0 * rho * v1 * v1_x - + rho_y * v1 * v2 - + rho * v1_y * v2 - + rho * v1 * v2_y - + rho_z * v1 * v3 - + rho * v1_z * v3 - + rho * v1 * v3_z - - mu_ * (tau11_x + tau12_y + tau13_z) ) - # y-momentum equation - du3 = ( rho_t * v2 + rho * v2_t + p_y + rho_x * v1 * v2 - + rho * v1_x * v2 - + rho * v1 * v2_x - + rho_y * v2^2 - + 2.0 * rho * v2 * v2_y - + rho_z * v2 * v3 - + rho * v2_z * v3 - + rho * v2 * v3_z - - mu_ * (tau12_x + tau22_y + tau23_z) ) - # z-momentum equation - du4 = ( rho_t * v3 + rho * v3_t + p_z + rho_x * v1 * v3 - + rho * v1_x * v3 - + rho * v1 * v3_x - + rho_y * v2 * v3 - + rho * v2_y * v3 - + rho * v2 * v3_y - + rho_z * v3^2 - + 2.0 * rho * v3 * v3_z - - mu_ * (tau13_x + tau23_y + tau33_z) ) - # Total energy equation - du5 = ( E_t + v1_x * (E + p) + v1 * (E_x + p_x) - + v2_y * (E + p) + v2 * (E_y + p_y) - + v3_z * (E + p) + v3 * (E_z + p_z) - # stress tensor and temperature gradient from x-direction - - mu_ * ( q_xx + v1_x * tau11 + v2_x * tau12 + v3_x * tau13 - + v1 * tau11_x + v2 * tau12_x + v3 * tau13_x) - # stress tensor and temperature gradient terms from y-direction - - mu_ * ( q_yy + v1_y * tau12 + v2_y * tau22 + v3_y * tau23 - + v1 * tau12_y + v2 * tau22_y + v3 * tau23_y) - # stress tensor and temperature gradient terms from z-direction - - mu_ * ( q_zz + v1_z * tau13 + v2_z * tau23 + v3_z * tau33 - + v1 * tau13_z + v2 * tau23_z + v3 * tau33_z) ) - - return SVector(du1, du2, du3, du4, du5) + # TODO: parabolic + # we currently need to hardcode these parameters until we fix the "combined equation" issue + # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 + inv_gamma_minus_one = inv(equations.gamma - 1) + Pr = prandtl_number() + mu_ = mu() + + # Constants. OBS! Must match those in `initial_condition_navier_stokes_convergence_test` + c = 2.0 + A1 = 0.5 + A2 = 1.0 + A3 = 0.5 + + # Convenience values for trig. functions + pi_x = pi * x[1] + pi_y = pi * x[2] + pi_z = pi * x[3] + pi_t = pi * t + + # Define auxiliary functions for the strange function of the y variable + # to make expressions easier to read + g = log(x[2] + 2.0) * (1.0 - exp(-A3 * (x[2] - 1.0))) + g_y = (A3 * log(x[2] + 2.0) * exp(-A3 * (x[2] - 1.0)) + + (1.0 - exp(-A3 * (x[2] - 1.0))) / (x[2] + 2.0)) + g_yy = (2.0 * A3 * exp(-A3 * (x[2] - 1.0)) / (x[2] + 2.0) - + (1.0 - exp(-A3 * (x[2] - 1.0))) / ((x[2] + 2.0)^2) - + A3^2 * log(x[2] + 2.0) * exp(-A3 * (x[2] - 1.0))) + + # Density and its derivatives + rho = c + A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) + rho_t = -pi * A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * sin(pi_t) + rho_x = pi * A1 * cos(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) + rho_y = -pi * A1 * sin(pi_x) * sin(pi_y) * sin(pi_z) * cos(pi_t) + rho_z = pi * A1 * sin(pi_x) * cos(pi_y) * cos(pi_z) * cos(pi_t) + rho_xx = -pi^2 * (rho - c) + rho_yy = -pi^2 * (rho - c) + rho_zz = -pi^2 * (rho - c) + + # Velocities and their derivatives + # v1 terms + v1 = A2 * sin(pi_x) * g * sin(pi_z) * cos(pi_t) + v1_t = -pi * A2 * sin(pi_x) * g * sin(pi_z) * sin(pi_t) + v1_x = pi * A2 * cos(pi_x) * g * sin(pi_z) * cos(pi_t) + v1_y = A2 * sin(pi_x) * g_y * sin(pi_z) * cos(pi_t) + v1_z = pi * A2 * sin(pi_x) * g * cos(pi_z) * cos(pi_t) + v1_xx = -pi^2 * v1 + v1_yy = A2 * sin(pi_x) * g_yy * sin(pi_z) * cos(pi_t) + v1_zz = -pi^2 * v1 + v1_xy = pi * A2 * cos(pi_x) * g_y * sin(pi_z) * cos(pi_t) + v1_xz = pi^2 * A2 * cos(pi_x) * g * cos(pi_z) * cos(pi_t) + v1_yz = pi * A2 * sin(pi_x) * g_y * cos(pi_z) * cos(pi_t) + # v2 terms (simplifies from ansatz) + v2 = v1 + v2_t = v1_t + v2_x = v1_x + v2_y = v1_y + v2_z = v1_z + v2_xx = v1_xx + v2_yy = v1_yy + v2_zz = v1_zz + v2_xy = v1_xy + v2_yz = v1_yz + # v3 terms (simplifies from ansatz) + v3 = v1 + v3_t = v1_t + v3_x = v1_x + v3_y = v1_y + v3_z = v1_z + v3_xx = v1_xx + v3_yy = v1_yy + v3_zz = v1_zz + v3_xz = v1_xz + v3_yz = v1_yz + + # Pressure and its derivatives + p = rho^2 + p_t = 2.0 * rho * rho_t + p_x = 2.0 * rho * rho_x + p_y = 2.0 * rho * rho_y + p_z = 2.0 * rho * rho_z + + # Total energy and its derivatives; simiplifies from ansatz that v2 = v1 and v3 = v1 + E = p * inv_gamma_minus_one + 1.5 * rho * v1^2 + E_t = p_t * inv_gamma_minus_one + 1.5 * rho_t * v1^2 + 3.0 * rho * v1 * v1_t + E_x = p_x * inv_gamma_minus_one + 1.5 * rho_x * v1^2 + 3.0 * rho * v1 * v1_x + E_y = p_y * inv_gamma_minus_one + 1.5 * rho_y * v1^2 + 3.0 * rho * v1 * v1_y + E_z = p_z * inv_gamma_minus_one + 1.5 * rho_z * v1^2 + 3.0 * rho * v1 * v1_z + + # Divergence of Fick's law ∇⋅∇q = kappa ∇⋅∇T; simplifies because p = rho², so T = p/rho = rho + kappa = equations.gamma * inv_gamma_minus_one / Pr + q_xx = kappa * rho_xx # kappa T_xx + q_yy = kappa * rho_yy # kappa T_yy + q_zz = kappa * rho_zz # kappa T_zz + + # Stress tensor and its derivatives (exploit symmetry) + tau11 = 4.0 / 3.0 * v1_x - 2.0 / 3.0 * (v2_y + v3_z) + tau12 = v1_y + v2_x + tau13 = v1_z + v3_x + tau22 = 4.0 / 3.0 * v2_y - 2.0 / 3.0 * (v1_x + v3_z) + tau23 = v2_z + v3_y + tau33 = 4.0 / 3.0 * v3_z - 2.0 / 3.0 * (v1_x + v2_y) + + tau11_x = 4.0 / 3.0 * v1_xx - 2.0 / 3.0 * (v2_xy + v3_xz) + tau12_x = v1_xy + v2_xx + tau13_x = v1_xz + v3_xx + + tau12_y = v1_yy + v2_xy + tau22_y = 4.0 / 3.0 * v2_yy - 2.0 / 3.0 * (v1_xy + v3_yz) + tau23_y = v2_yz + v3_yy + + tau13_z = v1_zz + v3_xz + tau23_z = v2_zz + v3_yz + tau33_z = 4.0 / 3.0 * v3_zz - 2.0 / 3.0 * (v1_xz + v2_yz) + + # Compute the source terms + # Density equation + du1 = (rho_t + rho_x * v1 + rho * v1_x + + rho_y * v2 + rho * v2_y + + rho_z * v3 + rho * v3_z) + # x-momentum equation + du2 = (rho_t * v1 + rho * v1_t + p_x + rho_x * v1^2 + + 2.0 * rho * v1 * v1_x + + rho_y * v1 * v2 + + rho * v1_y * v2 + + rho * v1 * v2_y + + rho_z * v1 * v3 + + rho * v1_z * v3 + + rho * v1 * v3_z - + mu_ * (tau11_x + tau12_y + tau13_z)) + # y-momentum equation + du3 = (rho_t * v2 + rho * v2_t + p_y + rho_x * v1 * v2 + + rho * v1_x * v2 + + rho * v1 * v2_x + + rho_y * v2^2 + + 2.0 * rho * v2 * v2_y + + rho_z * v2 * v3 + + rho * v2_z * v3 + + rho * v2 * v3_z - + mu_ * (tau12_x + tau22_y + tau23_z)) + # z-momentum equation + du4 = (rho_t * v3 + rho * v3_t + p_z + rho_x * v1 * v3 + + rho * v1_x * v3 + + rho * v1 * v3_x + + rho_y * v2 * v3 + + rho * v2_y * v3 + + rho * v2 * v3_y + + rho_z * v3^2 + + 2.0 * rho * v3 * v3_z - + mu_ * (tau13_x + tau23_y + tau33_z)) + # Total energy equation + du5 = (E_t + v1_x * (E + p) + v1 * (E_x + p_x) + + v2_y * (E + p) + v2 * (E_y + p_y) + + v3_z * (E + p) + v3 * (E_z + p_z) - + # stress tensor and temperature gradient from x-direction + mu_ * (q_xx + v1_x * tau11 + v2_x * tau12 + v3_x * tau13 + + v1 * tau11_x + v2 * tau12_x + v3 * tau13_x) - + # stress tensor and temperature gradient terms from y-direction + mu_ * (q_yy + v1_y * tau12 + v2_y * tau22 + v3_y * tau23 + + v1 * tau12_y + v2 * tau22_y + v3 * tau23_y) - + # stress tensor and temperature gradient terms from z-direction + mu_ * (q_zz + v1_z * tau13 + v2_z * tau23 + v3_z * tau33 + + v1 * tau13_z + v2 * tau23_z + v3 * tau33_z)) + + return SVector(du1, du2, du3, du4, du5) end initial_condition = initial_condition_navier_stokes_convergence_test # BC types -velocity_bc_top_bottom = NoSlip((x, t, equations) -> initial_condition_navier_stokes_convergence_test(x, t, equations)[2:4]) +velocity_bc_top_bottom = NoSlip((x, t, equations) -> initial_condition_navier_stokes_convergence_test(x, + t, + equations)[2:4]) heat_bc_top_bottom = Adiabatic((x, t, equations) -> 0.0) -boundary_condition_top_bottom = BoundaryConditionNavierStokesWall(velocity_bc_top_bottom, heat_bc_top_bottom) +boundary_condition_top_bottom = BoundaryConditionNavierStokesWall(velocity_bc_top_bottom, + heat_bc_top_bottom) # define inviscid boundary conditions boundary_conditions = (; :top_bottom => boundary_condition_slip_wall) @@ -228,10 +234,11 @@ boundary_conditions = (; :top_bottom => boundary_condition_slip_wall) # define viscous boundary conditions boundary_conditions_parabolic = (; :top_bottom => boundary_condition_top_bottom) -semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, dg; - boundary_conditions=(boundary_conditions, boundary_conditions_parabolic), - source_terms=source_terms_navier_stokes_convergence_test) - +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, dg; + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic), + source_terms = source_terms_navier_stokes_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -241,15 +248,15 @@ tspan = (0.0, 1.0) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) ############################################################################### # run the simulation time_int_tol = 1e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary diff --git a/examples/dgmulti_3d/elixir_navierstokes_convergence_curved.jl b/examples/dgmulti_3d/elixir_navierstokes_convergence_curved.jl index c14d6620803..c58d78d2581 100644 --- a/examples/dgmulti_3d/elixir_navierstokes_convergence_curved.jl +++ b/examples/dgmulti_3d/elixir_navierstokes_convergence_curved.jl @@ -8,25 +8,27 @@ prandtl_number() = 0.72 mu() = 0.01 equations = CompressibleEulerEquations3D(1.4) -equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu=mu(), Prandtl=prandtl_number(), - gradient_variables=GradientVariablesPrimitive()) +equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu = mu(), + Prandtl = prandtl_number(), + gradient_variables = GradientVariablesPrimitive()) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux dg = DGMulti(polydeg = 3, element_type = Hex(), approximation_type = Polynomial(), surface_integral = SurfaceIntegralWeakForm(flux_lax_friedrichs), volume_integral = VolumeIntegralWeakForm()) -top_bottom(x, tol=50*eps()) = abs(abs(x[2]) - 1) < tol +top_bottom(x, tol = 50 * eps()) = abs(abs(x[2]) - 1) < tol is_on_boundary = Dict(:top_bottom => top_bottom) function mapping(xi, eta, zeta) - x = xi + 0.1 * sin(pi * xi) * sin(pi * eta) - y = eta + 0.1 * sin(pi * xi) * sin(pi * eta) - z = zeta + 0.1 * sin(pi * xi) * sin(pi * eta) - return SVector(x, y, z) + x = xi + 0.1 * sin(pi * xi) * sin(pi * eta) + y = eta + 0.1 * sin(pi * xi) * sin(pi * eta) + z = zeta + 0.1 * sin(pi * xi) * sin(pi * eta) + return SVector(x, y, z) end cells_per_dimension = (8, 8, 8) -mesh = DGMultiMesh(dg, cells_per_dimension, mapping; periodicity=(true, false, true), is_on_boundary) +mesh = DGMultiMesh(dg, cells_per_dimension, mapping; periodicity = (true, false, true), + is_on_boundary) # This initial condition is taken from `examples/dgmulti_3d/elixir_navierstokes_convergence.jl` @@ -35,200 +37,204 @@ mesh = DGMultiMesh(dg, cells_per_dimension, mapping; periodicity=(true, false, t # and by the initial condition (which passes in `CompressibleEulerEquations3D`). # This convergence test setup was originally derived by Andrew Winters (@andrewwinters5000) function initial_condition_navier_stokes_convergence_test(x, t, equations) - # Constants. OBS! Must match those in `source_terms_navier_stokes_convergence_test` - c = 2.0 - A1 = 0.5 - A2 = 1.0 - A3 = 0.5 - - # Convenience values for trig. functions - pi_x = pi * x[1] - pi_y = pi * x[2] - pi_z = pi * x[3] - pi_t = pi * t - - rho = c + A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) - v1 = A2 * sin(pi_x) * log(x[2] + 2.0) * (1.0 - exp(-A3 * (x[2] - 1.0))) * sin(pi_z) * cos(pi_t) - v2 = v1 - v3 = v1 - p = rho^2 - - return prim2cons(SVector(rho, v1, v2, v3, p), equations) + # Constants. OBS! Must match those in `source_terms_navier_stokes_convergence_test` + c = 2.0 + A1 = 0.5 + A2 = 1.0 + A3 = 0.5 + + # Convenience values for trig. functions + pi_x = pi * x[1] + pi_y = pi * x[2] + pi_z = pi * x[3] + pi_t = pi * t + + rho = c + A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) + v1 = A2 * sin(pi_x) * log(x[2] + 2.0) * (1.0 - exp(-A3 * (x[2] - 1.0))) * sin(pi_z) * + cos(pi_t) + v2 = v1 + v3 = v1 + p = rho^2 + + return prim2cons(SVector(rho, v1, v2, v3, p), equations) end @inline function source_terms_navier_stokes_convergence_test(u, x, t, equations) - # TODO: parabolic - # we currently need to hardcode these parameters until we fix the "combined equation" issue - # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 - inv_gamma_minus_one = inv(equations.gamma - 1) - Pr = prandtl_number() - mu_ = mu() - - # Constants. OBS! Must match those in `initial_condition_navier_stokes_convergence_test` - c = 2.0 - A1 = 0.5 - A2 = 1.0 - A3 = 0.5 - - # Convenience values for trig. functions - pi_x = pi * x[1] - pi_y = pi * x[2] - pi_z = pi * x[3] - pi_t = pi * t - - # Define auxiliary functions for the strange function of the y variable - # to make expressions easier to read - g = log(x[2] + 2.0) * (1.0 - exp(-A3 * (x[2] - 1.0))) - g_y = ( A3 * log(x[2] + 2.0) * exp(-A3 * (x[2] - 1.0)) - + (1.0 - exp(-A3 * (x[2] - 1.0))) / (x[2] + 2.0) ) - g_yy = ( 2.0 * A3 * exp(-A3 * (x[2] - 1.0)) / (x[2] + 2.0) - - (1.0 - exp(-A3 * (x[2] - 1.0))) / ((x[2] + 2.0)^2) - - A3^2 * log(x[2] + 2.0) * exp(-A3 * (x[2] - 1.0)) ) - - # Density and its derivatives - rho = c + A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) - rho_t = -pi * A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * sin(pi_t) - rho_x = pi * A1 * cos(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) - rho_y = -pi * A1 * sin(pi_x) * sin(pi_y) * sin(pi_z) * cos(pi_t) - rho_z = pi * A1 * sin(pi_x) * cos(pi_y) * cos(pi_z) * cos(pi_t) - rho_xx = -pi^2 * (rho - c) - rho_yy = -pi^2 * (rho - c) - rho_zz = -pi^2 * (rho - c) - - # Velocities and their derivatives - # v1 terms - v1 = A2 * sin(pi_x) * g * sin(pi_z) * cos(pi_t) - v1_t = -pi * A2 * sin(pi_x) * g * sin(pi_z) * sin(pi_t) - v1_x = pi * A2 * cos(pi_x) * g * sin(pi_z) * cos(pi_t) - v1_y = A2 * sin(pi_x) * g_y * sin(pi_z) * cos(pi_t) - v1_z = pi * A2 * sin(pi_x) * g * cos(pi_z) * cos(pi_t) - v1_xx = -pi^2 * v1 - v1_yy = A2 * sin(pi_x) * g_yy * sin(pi_z) * cos(pi_t) - v1_zz = -pi^2 * v1 - v1_xy = pi * A2 * cos(pi_x) * g_y * sin(pi_z) * cos(pi_t) - v1_xz = pi^2 * A2 * cos(pi_x) * g * cos(pi_z) * cos(pi_t) - v1_yz = pi * A2 * sin(pi_x) * g_y * cos(pi_z) * cos(pi_t) - # v2 terms (simplifies from ansatz) - v2 = v1 - v2_t = v1_t - v2_x = v1_x - v2_y = v1_y - v2_z = v1_z - v2_xx = v1_xx - v2_yy = v1_yy - v2_zz = v1_zz - v2_xy = v1_xy - v2_yz = v1_yz - # v3 terms (simplifies from ansatz) - v3 = v1 - v3_t = v1_t - v3_x = v1_x - v3_y = v1_y - v3_z = v1_z - v3_xx = v1_xx - v3_yy = v1_yy - v3_zz = v1_zz - v3_xz = v1_xz - v3_yz = v1_yz - - # Pressure and its derivatives - p = rho^2 - p_t = 2.0 * rho * rho_t - p_x = 2.0 * rho * rho_x - p_y = 2.0 * rho * rho_y - p_z = 2.0 * rho * rho_z - - # Total energy and its derivatives; simiplifies from ansatz that v2 = v1 and v3 = v1 - E = p * inv_gamma_minus_one + 1.5 * rho * v1^2 - E_t = p_t * inv_gamma_minus_one + 1.5 * rho_t * v1^2 + 3.0 * rho * v1 * v1_t - E_x = p_x * inv_gamma_minus_one + 1.5 * rho_x * v1^2 + 3.0 * rho * v1 * v1_x - E_y = p_y * inv_gamma_minus_one + 1.5 * rho_y * v1^2 + 3.0 * rho * v1 * v1_y - E_z = p_z * inv_gamma_minus_one + 1.5 * rho_z * v1^2 + 3.0 * rho * v1 * v1_z - - # Divergence of Fick's law ∇⋅∇q = kappa ∇⋅∇T; simplifies because p = rho², so T = p/rho = rho - kappa = equations.gamma * inv_gamma_minus_one / Pr - q_xx = kappa * rho_xx # kappa T_xx - q_yy = kappa * rho_yy # kappa T_yy - q_zz = kappa * rho_zz # kappa T_zz - - # Stress tensor and its derivatives (exploit symmetry) - tau11 = 4.0 / 3.0 * v1_x - 2.0 / 3.0 * (v2_y + v3_z) - tau12 = v1_y + v2_x - tau13 = v1_z + v3_x - tau22 = 4.0 / 3.0 * v2_y - 2.0 / 3.0 * (v1_x + v3_z) - tau23 = v2_z + v3_y - tau33 = 4.0 / 3.0 * v3_z - 2.0 / 3.0 * (v1_x + v2_y) - - tau11_x = 4.0 / 3.0 * v1_xx - 2.0 / 3.0 * (v2_xy + v3_xz) - tau12_x = v1_xy + v2_xx - tau13_x = v1_xz + v3_xx - - tau12_y = v1_yy + v2_xy - tau22_y = 4.0 / 3.0 * v2_yy - 2.0 / 3.0 * (v1_xy + v3_yz) - tau23_y = v2_yz + v3_yy - - tau13_z = v1_zz + v3_xz - tau23_z = v2_zz + v3_yz - tau33_z = 4.0 / 3.0 * v3_zz - 2.0 / 3.0 * (v1_xz + v2_yz) - - # Compute the source terms - # Density equation - du1 = ( rho_t + rho_x * v1 + rho * v1_x - + rho_y * v2 + rho * v2_y - + rho_z * v3 + rho * v3_z ) - # x-momentum equation - du2 = ( rho_t * v1 + rho * v1_t + p_x + rho_x * v1^2 - + 2.0 * rho * v1 * v1_x - + rho_y * v1 * v2 - + rho * v1_y * v2 - + rho * v1 * v2_y - + rho_z * v1 * v3 - + rho * v1_z * v3 - + rho * v1 * v3_z - - mu_ * (tau11_x + tau12_y + tau13_z) ) - # y-momentum equation - du3 = ( rho_t * v2 + rho * v2_t + p_y + rho_x * v1 * v2 - + rho * v1_x * v2 - + rho * v1 * v2_x - + rho_y * v2^2 - + 2.0 * rho * v2 * v2_y - + rho_z * v2 * v3 - + rho * v2_z * v3 - + rho * v2 * v3_z - - mu_ * (tau12_x + tau22_y + tau23_z) ) - # z-momentum equation - du4 = ( rho_t * v3 + rho * v3_t + p_z + rho_x * v1 * v3 - + rho * v1_x * v3 - + rho * v1 * v3_x - + rho_y * v2 * v3 - + rho * v2_y * v3 - + rho * v2 * v3_y - + rho_z * v3^2 - + 2.0 * rho * v3 * v3_z - - mu_ * (tau13_x + tau23_y + tau33_z) ) - # Total energy equation - du5 = ( E_t + v1_x * (E + p) + v1 * (E_x + p_x) - + v2_y * (E + p) + v2 * (E_y + p_y) - + v3_z * (E + p) + v3 * (E_z + p_z) - # stress tensor and temperature gradient from x-direction - - mu_ * ( q_xx + v1_x * tau11 + v2_x * tau12 + v3_x * tau13 - + v1 * tau11_x + v2 * tau12_x + v3 * tau13_x) - # stress tensor and temperature gradient terms from y-direction - - mu_ * ( q_yy + v1_y * tau12 + v2_y * tau22 + v3_y * tau23 - + v1 * tau12_y + v2 * tau22_y + v3 * tau23_y) - # stress tensor and temperature gradient terms from z-direction - - mu_ * ( q_zz + v1_z * tau13 + v2_z * tau23 + v3_z * tau33 - + v1 * tau13_z + v2 * tau23_z + v3 * tau33_z) ) - - return SVector(du1, du2, du3, du4, du5) + # TODO: parabolic + # we currently need to hardcode these parameters until we fix the "combined equation" issue + # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 + inv_gamma_minus_one = inv(equations.gamma - 1) + Pr = prandtl_number() + mu_ = mu() + + # Constants. OBS! Must match those in `initial_condition_navier_stokes_convergence_test` + c = 2.0 + A1 = 0.5 + A2 = 1.0 + A3 = 0.5 + + # Convenience values for trig. functions + pi_x = pi * x[1] + pi_y = pi * x[2] + pi_z = pi * x[3] + pi_t = pi * t + + # Define auxiliary functions for the strange function of the y variable + # to make expressions easier to read + g = log(x[2] + 2.0) * (1.0 - exp(-A3 * (x[2] - 1.0))) + g_y = (A3 * log(x[2] + 2.0) * exp(-A3 * (x[2] - 1.0)) + + (1.0 - exp(-A3 * (x[2] - 1.0))) / (x[2] + 2.0)) + g_yy = (2.0 * A3 * exp(-A3 * (x[2] - 1.0)) / (x[2] + 2.0) - + (1.0 - exp(-A3 * (x[2] - 1.0))) / ((x[2] + 2.0)^2) - + A3^2 * log(x[2] + 2.0) * exp(-A3 * (x[2] - 1.0))) + + # Density and its derivatives + rho = c + A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) + rho_t = -pi * A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * sin(pi_t) + rho_x = pi * A1 * cos(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) + rho_y = -pi * A1 * sin(pi_x) * sin(pi_y) * sin(pi_z) * cos(pi_t) + rho_z = pi * A1 * sin(pi_x) * cos(pi_y) * cos(pi_z) * cos(pi_t) + rho_xx = -pi^2 * (rho - c) + rho_yy = -pi^2 * (rho - c) + rho_zz = -pi^2 * (rho - c) + + # Velocities and their derivatives + # v1 terms + v1 = A2 * sin(pi_x) * g * sin(pi_z) * cos(pi_t) + v1_t = -pi * A2 * sin(pi_x) * g * sin(pi_z) * sin(pi_t) + v1_x = pi * A2 * cos(pi_x) * g * sin(pi_z) * cos(pi_t) + v1_y = A2 * sin(pi_x) * g_y * sin(pi_z) * cos(pi_t) + v1_z = pi * A2 * sin(pi_x) * g * cos(pi_z) * cos(pi_t) + v1_xx = -pi^2 * v1 + v1_yy = A2 * sin(pi_x) * g_yy * sin(pi_z) * cos(pi_t) + v1_zz = -pi^2 * v1 + v1_xy = pi * A2 * cos(pi_x) * g_y * sin(pi_z) * cos(pi_t) + v1_xz = pi^2 * A2 * cos(pi_x) * g * cos(pi_z) * cos(pi_t) + v1_yz = pi * A2 * sin(pi_x) * g_y * cos(pi_z) * cos(pi_t) + # v2 terms (simplifies from ansatz) + v2 = v1 + v2_t = v1_t + v2_x = v1_x + v2_y = v1_y + v2_z = v1_z + v2_xx = v1_xx + v2_yy = v1_yy + v2_zz = v1_zz + v2_xy = v1_xy + v2_yz = v1_yz + # v3 terms (simplifies from ansatz) + v3 = v1 + v3_t = v1_t + v3_x = v1_x + v3_y = v1_y + v3_z = v1_z + v3_xx = v1_xx + v3_yy = v1_yy + v3_zz = v1_zz + v3_xz = v1_xz + v3_yz = v1_yz + + # Pressure and its derivatives + p = rho^2 + p_t = 2.0 * rho * rho_t + p_x = 2.0 * rho * rho_x + p_y = 2.0 * rho * rho_y + p_z = 2.0 * rho * rho_z + + # Total energy and its derivatives; simiplifies from ansatz that v2 = v1 and v3 = v1 + E = p * inv_gamma_minus_one + 1.5 * rho * v1^2 + E_t = p_t * inv_gamma_minus_one + 1.5 * rho_t * v1^2 + 3.0 * rho * v1 * v1_t + E_x = p_x * inv_gamma_minus_one + 1.5 * rho_x * v1^2 + 3.0 * rho * v1 * v1_x + E_y = p_y * inv_gamma_minus_one + 1.5 * rho_y * v1^2 + 3.0 * rho * v1 * v1_y + E_z = p_z * inv_gamma_minus_one + 1.5 * rho_z * v1^2 + 3.0 * rho * v1 * v1_z + + # Divergence of Fick's law ∇⋅∇q = kappa ∇⋅∇T; simplifies because p = rho², so T = p/rho = rho + kappa = equations.gamma * inv_gamma_minus_one / Pr + q_xx = kappa * rho_xx # kappa T_xx + q_yy = kappa * rho_yy # kappa T_yy + q_zz = kappa * rho_zz # kappa T_zz + + # Stress tensor and its derivatives (exploit symmetry) + tau11 = 4.0 / 3.0 * v1_x - 2.0 / 3.0 * (v2_y + v3_z) + tau12 = v1_y + v2_x + tau13 = v1_z + v3_x + tau22 = 4.0 / 3.0 * v2_y - 2.0 / 3.0 * (v1_x + v3_z) + tau23 = v2_z + v3_y + tau33 = 4.0 / 3.0 * v3_z - 2.0 / 3.0 * (v1_x + v2_y) + + tau11_x = 4.0 / 3.0 * v1_xx - 2.0 / 3.0 * (v2_xy + v3_xz) + tau12_x = v1_xy + v2_xx + tau13_x = v1_xz + v3_xx + + tau12_y = v1_yy + v2_xy + tau22_y = 4.0 / 3.0 * v2_yy - 2.0 / 3.0 * (v1_xy + v3_yz) + tau23_y = v2_yz + v3_yy + + tau13_z = v1_zz + v3_xz + tau23_z = v2_zz + v3_yz + tau33_z = 4.0 / 3.0 * v3_zz - 2.0 / 3.0 * (v1_xz + v2_yz) + + # Compute the source terms + # Density equation + du1 = (rho_t + rho_x * v1 + rho * v1_x + + rho_y * v2 + rho * v2_y + + rho_z * v3 + rho * v3_z) + # x-momentum equation + du2 = (rho_t * v1 + rho * v1_t + p_x + rho_x * v1^2 + + 2.0 * rho * v1 * v1_x + + rho_y * v1 * v2 + + rho * v1_y * v2 + + rho * v1 * v2_y + + rho_z * v1 * v3 + + rho * v1_z * v3 + + rho * v1 * v3_z - + mu_ * (tau11_x + tau12_y + tau13_z)) + # y-momentum equation + du3 = (rho_t * v2 + rho * v2_t + p_y + rho_x * v1 * v2 + + rho * v1_x * v2 + + rho * v1 * v2_x + + rho_y * v2^2 + + 2.0 * rho * v2 * v2_y + + rho_z * v2 * v3 + + rho * v2_z * v3 + + rho * v2 * v3_z - + mu_ * (tau12_x + tau22_y + tau23_z)) + # z-momentum equation + du4 = (rho_t * v3 + rho * v3_t + p_z + rho_x * v1 * v3 + + rho * v1_x * v3 + + rho * v1 * v3_x + + rho_y * v2 * v3 + + rho * v2_y * v3 + + rho * v2 * v3_y + + rho_z * v3^2 + + 2.0 * rho * v3 * v3_z - + mu_ * (tau13_x + tau23_y + tau33_z)) + # Total energy equation + du5 = (E_t + v1_x * (E + p) + v1 * (E_x + p_x) + + v2_y * (E + p) + v2 * (E_y + p_y) + + v3_z * (E + p) + v3 * (E_z + p_z) - + # stress tensor and temperature gradient from x-direction + mu_ * (q_xx + v1_x * tau11 + v2_x * tau12 + v3_x * tau13 + + v1 * tau11_x + v2 * tau12_x + v3 * tau13_x) - + # stress tensor and temperature gradient terms from y-direction + mu_ * (q_yy + v1_y * tau12 + v2_y * tau22 + v3_y * tau23 + + v1 * tau12_y + v2 * tau22_y + v3 * tau23_y) - + # stress tensor and temperature gradient terms from z-direction + mu_ * (q_zz + v1_z * tau13 + v2_z * tau23 + v3_z * tau33 + + v1 * tau13_z + v2 * tau23_z + v3 * tau33_z)) + + return SVector(du1, du2, du3, du4, du5) end initial_condition = initial_condition_navier_stokes_convergence_test # BC types -velocity_bc_top_bottom = NoSlip((x, t, equations) -> initial_condition_navier_stokes_convergence_test(x, t, equations)[2:4]) +velocity_bc_top_bottom = NoSlip((x, t, equations) -> initial_condition_navier_stokes_convergence_test(x, + t, + equations)[2:4]) heat_bc_top_bottom = Adiabatic((x, t, equations) -> 0.0) -boundary_condition_top_bottom = BoundaryConditionNavierStokesWall(velocity_bc_top_bottom, heat_bc_top_bottom) +boundary_condition_top_bottom = BoundaryConditionNavierStokesWall(velocity_bc_top_bottom, + heat_bc_top_bottom) # define inviscid boundary conditions boundary_conditions = (; :top_bottom => boundary_condition_slip_wall) @@ -236,10 +242,11 @@ boundary_conditions = (; :top_bottom => boundary_condition_slip_wall) # define viscous boundary conditions boundary_conditions_parabolic = (; :top_bottom => boundary_condition_top_bottom) -semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, dg; - boundary_conditions=(boundary_conditions, boundary_conditions_parabolic), - source_terms=source_terms_navier_stokes_convergence_test) - +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, dg; + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic), + source_terms = source_terms_navier_stokes_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -249,15 +256,15 @@ tspan = (0.0, 1.0) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg)) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) ############################################################################### # run the simulation time_int_tol = 1e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary diff --git a/examples/dgmulti_3d/elixir_navierstokes_taylor_green_vortex.jl b/examples/dgmulti_3d/elixir_navierstokes_taylor_green_vortex.jl index 7953838afeb..dedd8267a3b 100644 --- a/examples/dgmulti_3d/elixir_navierstokes_taylor_green_vortex.jl +++ b/examples/dgmulti_3d/elixir_navierstokes_taylor_green_vortex.jl @@ -10,26 +10,30 @@ prandtl_number() = 0.72 mu() = 6.25e-4 # equivalent to Re = 1600 equations = CompressibleEulerEquations3D(1.4) -equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu=mu(), - Prandtl=prandtl_number()) +equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu = mu(), + Prandtl = prandtl_number()) """ initial_condition_taylor_green_vortex(x, t, equations::CompressibleEulerEquations3D) The classical inviscid Taylor-Green vortex. """ -function initial_condition_taylor_green_vortex(x, t, equations::CompressibleEulerEquations3D) - A = 1.0 # magnitude of speed - Ms = 0.1 # maximum Mach number - - rho = 1.0 - v1 = A * sin(x[1]) * cos(x[2]) * cos(x[3]) - v2 = -A * cos(x[1]) * sin(x[2]) * cos(x[3]) - v3 = 0.0 - p = (A / Ms)^2 * rho / equations.gamma # scaling to get Ms - p = p + 1.0/16.0 * A^2 * rho * (cos(2*x[1])*cos(2*x[3]) + 2*cos(2*x[2]) + 2*cos(2*x[1]) + cos(2*x[2])*cos(2*x[3])) - - return prim2cons(SVector(rho, v1, v2, v3, p), equations) +function initial_condition_taylor_green_vortex(x, t, + equations::CompressibleEulerEquations3D) + A = 1.0 # magnitude of speed + Ms = 0.1 # maximum Mach number + + rho = 1.0 + v1 = A * sin(x[1]) * cos(x[2]) * cos(x[3]) + v2 = -A * cos(x[1]) * sin(x[2]) * cos(x[3]) + v3 = 0.0 + p = (A / Ms)^2 * rho / equations.gamma # scaling to get Ms + p = p + + 1.0 / 16.0 * A^2 * rho * + (cos(2 * x[1]) * cos(2 * x[3]) + 2 * cos(2 * x[2]) + 2 * cos(2 * x[1]) + + cos(2 * x[2]) * cos(2 * x[3])) + + return prim2cons(SVector(rho, v1, v2, v3, p), equations) end initial_condition = initial_condition_taylor_green_vortex @@ -39,11 +43,11 @@ dg = DGMulti(polydeg = 3, element_type = Hex(), approximation_type = GaussSBP(), volume_integral = VolumeIntegralFluxDifferencing(flux_ranocha)) coordinates_min = (-1.0, -1.0, -1.0) .* pi -coordinates_max = ( 1.0, 1.0, 1.0) .* pi +coordinates_max = (1.0, 1.0, 1.0) .* pi cells_per_dimension = (8, 8, 8) mesh = DGMultiMesh(dg, cells_per_dimension; coordinates_min, coordinates_max, - periodicity=(true, true, true)) + periodicity = (true, true, true)) semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, dg) @@ -55,18 +59,18 @@ tspan = (0.0, 10.0) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, uEltype=real(dg), - extra_analysis_integrals=(energy_kinetic, - energy_internal, - enstrophy)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, uEltype = real(dg), + extra_analysis_integrals = (energy_kinetic, + energy_internal, + enstrophy)) callbacks = CallbackSet(summary_callback, alive_callback) ############################################################################### # run the simulation time_int_tol = 1e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary diff --git a/examples/p4est_2d_dgsem/elixir_advection_amr_solution_independent.jl b/examples/p4est_2d_dgsem/elixir_advection_amr_solution_independent.jl index 841a080947e..5a2537be4e6 100644 --- a/examples/p4est_2d_dgsem/elixir_advection_amr_solution_independent.jl +++ b/examples/p4est_2d_dgsem/elixir_advection_amr_solution_independent.jl @@ -7,74 +7,73 @@ module TrixiExtension using Trixi -struct IndicatorSolutionIndependent{Cache<:NamedTuple} <: Trixi.AbstractIndicator - cache::Cache +struct IndicatorSolutionIndependent{Cache <: NamedTuple} <: Trixi.AbstractIndicator + cache::Cache end function IndicatorSolutionIndependent(semi) - basis = semi.solver.basis - alpha = Vector{real(basis)}() - cache = (; semi.mesh, alpha) - return IndicatorSolutionIndependent{typeof(cache)}(cache) + basis = semi.solver.basis + alpha = Vector{real(basis)}() + cache = (; semi.mesh, alpha) + return IndicatorSolutionIndependent{typeof(cache)}(cache) end -function (indicator::IndicatorSolutionIndependent)(u::AbstractArray{<:Any,4}, +function (indicator::IndicatorSolutionIndependent)(u::AbstractArray{<:Any, 4}, mesh, equations, dg, cache; t, kwargs...) - - mesh = indicator.cache.mesh - alpha = indicator.cache.alpha - resize!(alpha, nelements(dg, cache)) - - #Predict the theoretical center. - advection_velocity = (0.2, -0.7) - center = t.*advection_velocity - - inner_distance = 1 - outer_distance = 1.85 - - #Iterate over all elements - for element in 1:length(alpha) - # Calculate periodic distance between cell and center. - # This requires an uncurved mesh! - coordinates = SVector(0.5 * (cache.elements.node_coordinates[1, 1, 1, element] + - cache.elements.node_coordinates[1, end, 1, element]), - 0.5 * (cache.elements.node_coordinates[2, 1, 1, element] + - cache.elements.node_coordinates[2, 1, end, element])) - - #The geometric shape of the amr should be preserved when the base_level is increased. - #This is done by looking at the original coordinates of each cell. - cell_coordinates = original_coordinates(coordinates, 5/8) - cell_distance = periodic_distance_2d(cell_coordinates, center, 10) - if cell_distance < (inner_distance+outer_distance)/2 - cell_coordinates = original_coordinates(coordinates, 5/16) - cell_distance = periodic_distance_2d(cell_coordinates, center, 10) + mesh = indicator.cache.mesh + alpha = indicator.cache.alpha + resize!(alpha, nelements(dg, cache)) + + #Predict the theoretical center. + advection_velocity = (0.2, -0.7) + center = t .* advection_velocity + + inner_distance = 1 + outer_distance = 1.85 + + #Iterate over all elements + for element in 1:length(alpha) + # Calculate periodic distance between cell and center. + # This requires an uncurved mesh! + coordinates = SVector(0.5 * (cache.elements.node_coordinates[1, 1, 1, element] + + cache.elements.node_coordinates[1, end, 1, element]), + 0.5 * (cache.elements.node_coordinates[2, 1, 1, element] + + cache.elements.node_coordinates[2, 1, end, element])) + + #The geometric shape of the amr should be preserved when the base_level is increased. + #This is done by looking at the original coordinates of each cell. + cell_coordinates = original_coordinates(coordinates, 5 / 8) + cell_distance = periodic_distance_2d(cell_coordinates, center, 10) + if cell_distance < (inner_distance + outer_distance) / 2 + cell_coordinates = original_coordinates(coordinates, 5 / 16) + cell_distance = periodic_distance_2d(cell_coordinates, center, 10) + end + + #Set alpha according to cells position inside the circles. + target_level = (cell_distance < inner_distance) + (cell_distance < outer_distance) + alpha[element] = target_level / 2 end - - #Set alpha according to cells position inside the circles. - target_level = (cell_distance < inner_distance) + (cell_distance < outer_distance) - alpha[element] = target_level/2 - end - return alpha + return alpha end # For periodic domains, distance between two points must take into account # periodic extensions of the domain function periodic_distance_2d(coordinates, center, domain_length) - dx = coordinates .- center - dx_shifted = abs.(dx .% domain_length) - dx_periodic = min.(dx_shifted, domain_length .- dx_shifted) - return sqrt(sum(dx_periodic.^2)) + dx = coordinates .- center + dx_shifted = abs.(dx .% domain_length) + dx_periodic = min.(dx_shifted, domain_length .- dx_shifted) + return sqrt(sum(dx_periodic .^ 2)) end #This takes a cells coordinates and transforms them into the coordinates of a parent-cell it originally refined from. #It does it so that the parent-cell has given cell_length. function original_coordinates(coordinates, cell_length) - offset = coordinates .% cell_length - offset_sign = sign.(offset) - border = coordinates - offset - center = border + (offset_sign .* cell_length/2) - return center + offset = coordinates .% cell_length + offset_sign = sign.(offset) + border = coordinates - offset + center = border + (offset_sign .* cell_length / 2) + return center end end # module TrixiExtension @@ -88,21 +87,19 @@ equations = LinearScalarAdvectionEquation2D(advection_velocity) initial_condition = initial_condition_gauss -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-5.0, -5.0) -coordinates_max = ( 5.0, 5.0) +coordinates_max = (5.0, 5.0) trees_per_dimension = (1, 1) -mesh = P4estMesh(trees_per_dimension, polydeg=3, - coordinates_min=coordinates_min, coordinates_max=coordinates_max, - initial_refinement_level=4) - +mesh = P4estMesh(trees_per_dimension, polydeg = 3, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + initial_refinement_level = 4) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -112,38 +109,38 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -amr_controller = ControllerThreeLevel(semi, TrixiExtension.IndicatorSolutionIndependent(semi), - base_level=4, - med_level=5, med_threshold=0.1, - max_level=6, max_threshold=0.6) +amr_controller = ControllerThreeLevel(semi, + TrixiExtension.IndicatorSolutionIndependent(semi), + base_level = 4, + med_level = 5, med_threshold = 0.1, + max_level = 6, max_threshold = 0.6) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, amr_callback, stepsize_callback); - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/p4est_2d_dgsem/elixir_advection_amr_unstructured_flag.jl b/examples/p4est_2d_dgsem/elixir_advection_amr_unstructured_flag.jl index 7e6d99c83b1..0a50b3644f0 100644 --- a/examples/p4est_2d_dgsem/elixir_advection_amr_unstructured_flag.jl +++ b/examples/p4est_2d_dgsem/elixir_advection_amr_unstructured_flag.jl @@ -12,18 +12,16 @@ equations = LinearScalarAdvectionEquation2D(advection_velocity) initial_condition = initial_condition_gauss boundary_condition = BoundaryConditionDirichlet(initial_condition) -boundary_conditions = Dict( - :all => boundary_condition -) +boundary_conditions = Dict(:all => boundary_condition) -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) # Deformed rectangle that looks like a waving flag, # lower and upper faces are sinus curves, left and right are vertical lines. f1(s) = SVector(-5.0, 5 * s - 5.0) -f2(s) = SVector( 5.0, 5 * s + 5.0) +f2(s) = SVector(5.0, 5 * s + 5.0) f3(s) = SVector(5 * s, -5.0 + 5 * sin(0.5 * pi * s)) -f4(s) = SVector(5 * s, 5.0 + 5 * sin(0.5 * pi * s)) +f4(s) = SVector(5 * s, 5.0 + 5 * sin(0.5 * pi * s)) faces = (f1, f2, f3, f4) # This creates a mapping that transforms [-1, 1]^2 to the domain with the faces defined above. @@ -34,17 +32,16 @@ mapping_flag = Trixi.transfinite_mapping(faces) # Unstructured mesh with 24 cells of the square domain [-1, 1]^n mesh_file = joinpath(@__DIR__, "square_unstructured_2.inp") -isfile(mesh_file) || download("https://gist.githubusercontent.com/efaulhaber/63ff2ea224409e55ee8423b3a33e316a/raw/7db58af7446d1479753ae718930741c47a3b79b7/square_unstructured_2.inp", - mesh_file) - -mesh = P4estMesh{2}(mesh_file, polydeg=3, - mapping=mapping_flag, - initial_refinement_level=1) +isfile(mesh_file) || + download("https://gist.githubusercontent.com/efaulhaber/63ff2ea224409e55ee8423b3a33e316a/raw/7db58af7446d1479753ae718930741c47a3b79b7/square_unstructured_2.inp", + mesh_file) +mesh = P4estMesh{2}(mesh_file, polydeg = 3, + mapping = mapping_flag, + initial_refinement_level = 1) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -55,41 +52,40 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable=first), - base_level=1, - med_level=2, med_threshold=0.1, - max_level=3, max_threshold=0.6) +amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable = first), + base_level = 1, + med_level = 2, med_threshold = 0.1, + max_level = 3, max_threshold = 0.6) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=0.7) +stepsize_callback = StepsizeCallback(cfl = 0.7) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_restart, save_solution, amr_callback, stepsize_callback); - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/p4est_2d_dgsem/elixir_advection_basic.jl b/examples/p4est_2d_dgsem/elixir_advection_basic.jl index 0b2de85da48..ed235bf839c 100644 --- a/examples/p4est_2d_dgsem/elixir_advection_basic.jl +++ b/examples/p4est_2d_dgsem/elixir_advection_basic.jl @@ -11,21 +11,21 @@ advection_velocity = (0.2, -0.7) equations = LinearScalarAdvectionEquation2D(advection_velocity) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-1.0, -1.0) # minimum coordinates (min(x), min(y)) -coordinates_max = ( 1.0, 1.0) # maximum coordinates (max(x), max(y)) +coordinates_max = (1.0, 1.0) # maximum coordinates (max(x), max(y)) trees_per_dimension = (8, 8) # Create P4estMesh with 8 x 8 trees and 16 x 16 elements -mesh = P4estMesh(trees_per_dimension, polydeg=3, - coordinates_min=coordinates_min, coordinates_max=coordinates_max, - initial_refinement_level=1) +mesh = P4estMesh(trees_per_dimension, polydeg = 3, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + initial_refinement_level = 1) # A semidiscretization collects data structures and functions for the spatial discretization -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, solver) - +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, + solver) ############################################################################### # ODE solvers, callbacks etc. @@ -38,26 +38,26 @@ ode = semidiscretize(semi, (0.0, 1.0)); summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); # Print the timer summary summary_callback() diff --git a/examples/p4est_2d_dgsem/elixir_advection_diffusion_nonperiodic_amr.jl b/examples/p4est_2d_dgsem/elixir_advection_diffusion_nonperiodic_amr.jl new file mode 100644 index 00000000000..f87c0e056ca --- /dev/null +++ b/examples/p4est_2d_dgsem/elixir_advection_diffusion_nonperiodic_amr.jl @@ -0,0 +1,98 @@ +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the linear advection-diffusion equation + +diffusivity() = 5.0e-2 +advection_velocity = (1.0, 0.0) +equations = LinearScalarAdvectionEquation2D(advection_velocity) +equations_parabolic = LaplaceDiffusion2D(diffusivity(), equations) + +# Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) + +coordinates_min = (-1.0, -0.5) # minimum coordinates (min(x), min(y)) +coordinates_max = (0.0, 0.5) # maximum coordinates (max(x), max(y)) + +trees_per_dimension = (4, 4) +mesh = P4estMesh(trees_per_dimension, + polydeg = 3, initial_refinement_level = 2, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + periodicity = false) + +# Example setup taken from +# - Truman Ellis, Jesse Chan, and Leszek Demkowicz (2016). +# Robust DPG methods for transient convection-diffusion. +# In: Building bridges: connections and challenges in modern approaches +# to numerical partial differential equations. +# [DOI](https://doi.org/10.1007/978-3-319-41640-3_6). +function initial_condition_eriksson_johnson(x, t, equations) + l = 4 + epsilon = diffusivity() # TODO: this requires epsilon < .6 due to sqrt + lambda_1 = (-1 + sqrt(1 - 4 * epsilon * l)) / (-2 * epsilon) + lambda_2 = (-1 - sqrt(1 - 4 * epsilon * l)) / (-2 * epsilon) + r1 = (1 + sqrt(1 + 4 * pi^2 * epsilon^2)) / (2 * epsilon) + s1 = (1 - sqrt(1 + 4 * pi^2 * epsilon^2)) / (2 * epsilon) + u = exp(-l * t) * (exp(lambda_1 * x[1]) - exp(lambda_2 * x[1])) + + cos(pi * x[2]) * (exp(s1 * x[1]) - exp(r1 * x[1])) / (exp(-s1) - exp(-r1)) + return SVector{1}(u) +end +initial_condition = initial_condition_eriksson_johnson + +boundary_conditions = Dict(:x_neg => BoundaryConditionDirichlet(initial_condition), + :y_neg => BoundaryConditionDirichlet(initial_condition), + :y_pos => BoundaryConditionDirichlet(initial_condition), + :x_pos => boundary_condition_do_nothing) + +boundary_conditions_parabolic = Dict(:x_neg => BoundaryConditionDirichlet(initial_condition), + :x_pos => BoundaryConditionDirichlet(initial_condition), + :y_neg => BoundaryConditionDirichlet(initial_condition), + :y_pos => BoundaryConditionDirichlet(initial_condition)) + +# A semidiscretization collects data structures and functions for the spatial discretization +semi = SemidiscretizationHyperbolicParabolic(mesh, + (equations, equations_parabolic), + initial_condition, solver; + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic)) + +############################################################################### +# ODE solvers, callbacks etc. + +# Create ODE problem with time span `tspan` +tspan = (0.0, 0.5) +ode = semidiscretize(semi, tspan) + +# At the beginning of the main loop, the SummaryCallback prints a summary of the simulation setup +# and resets the timers +summary_callback = SummaryCallback() + +# The AnalysisCallback allows to analyse the solution in regular intervals and prints the results +analysis_interval = 1000 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + +# The AliveCallback prints short status information in regular intervals +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable = first), + base_level = 1, + med_level = 2, med_threshold = 0.9, + max_level = 3, max_threshold = 1.0) + +amr_callback = AMRCallback(semi, amr_controller, + interval = 50) + +# Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver +callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, amr_callback) + +############################################################################### +# run the simulation + +# OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks +time_int_tol = 1.0e-11 +sol = solve(ode, dt = 1e-7, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) + +# Print the timer summary +summary_callback() diff --git a/examples/p4est_2d_dgsem/elixir_advection_diffusion_nonperiodic_curved.jl b/examples/p4est_2d_dgsem/elixir_advection_diffusion_nonperiodic_curved.jl index 55682f73fce..5497f13aa65 100644 --- a/examples/p4est_2d_dgsem/elixir_advection_diffusion_nonperiodic_curved.jl +++ b/examples/p4est_2d_dgsem/elixir_advection_diffusion_nonperiodic_curved.jl @@ -16,15 +16,15 @@ equations_parabolic = LaplaceDiffusion2D(diffusivity(), equations) # to numerical partial differential equations. # [DOI](https://doi.org/10.1007/978-3-319-41640-3_6). function initial_condition_eriksson_johnson(x, t, equations) - l = 4 - epsilon = diffusivity() # TODO: this requires epsilon < .6 due to sqrt - lambda_1 = (-1 + sqrt(1 - 4 * epsilon * l)) / (-2 * epsilon) - lambda_2 = (-1 - sqrt(1 - 4 * epsilon * l)) / (-2 * epsilon) - r1 = (1 + sqrt(1 + 4 * pi^2 * epsilon^2)) / (2 * epsilon) - s1 = (1 - sqrt(1 + 4 * pi^2 * epsilon^2)) / (2 * epsilon) - u = exp(-l * t) * (exp(lambda_1 * x[1]) - exp(lambda_2 * x[1])) + - cos(pi * x[2]) * (exp(s1 * x[1]) - exp(r1 * x[1])) / (exp(-s1) - exp(-r1)) - return SVector{1}(u) + l = 4 + epsilon = diffusivity() # TODO: this requires epsilon < .6 due to sqrt + lambda_1 = (-1 + sqrt(1 - 4 * epsilon * l)) / (-2 * epsilon) + lambda_2 = (-1 - sqrt(1 - 4 * epsilon * l)) / (-2 * epsilon) + r1 = (1 + sqrt(1 + 4 * pi^2 * epsilon^2)) / (2 * epsilon) + s1 = (1 - sqrt(1 + 4 * pi^2 * epsilon^2)) / (2 * epsilon) + u = exp(-l * t) * (exp(lambda_1 * x[1]) - exp(lambda_2 * x[1])) + + cos(pi * x[2]) * (exp(s1 * x[1]) - exp(r1 * x[1])) / (exp(-s1) - exp(-r1)) + return SVector{1}(u) end initial_condition = initial_condition_eriksson_johnson @@ -33,34 +33,35 @@ boundary_conditions = Dict(:x_neg => BoundaryConditionDirichlet(initial_conditio :y_pos => BoundaryConditionDirichlet(initial_condition), :x_pos => boundary_condition_do_nothing) -boundary_conditions_parabolic = Dict(:x_neg => BoundaryConditionDirichlet(initial_condition), - :x_pos => BoundaryConditionDirichlet(initial_condition), - :y_neg => BoundaryConditionDirichlet(initial_condition), +boundary_conditions_parabolic = Dict(:x_neg => BoundaryConditionDirichlet(initial_condition), + :x_pos => BoundaryConditionDirichlet(initial_condition), + :y_neg => BoundaryConditionDirichlet(initial_condition), :y_pos => BoundaryConditionDirichlet(initial_condition)) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) -coordinates_min = (-1.0, -0.5) -coordinates_max = ( 0.0, 0.5) +coordinates_min = (-1.0, -0.5) +coordinates_max = (0.0, 0.5) # This maps the domain [-1, 1]^2 to [-1, 0] x [-0.5, 0.5] while also # introducing a curved warping to interior nodes. function mapping(xi, eta) - x = xi + 0.1 * sin(pi * xi) * sin(pi * eta) + x = xi + 0.1 * sin(pi * xi) * sin(pi * eta) y = eta + 0.1 * sin(pi * xi) * sin(pi * eta) return SVector(0.5 * (1 + x) - 1, 0.5 * y) -end +end trees_per_dimension = (4, 4) mesh = P4estMesh(trees_per_dimension, - polydeg=3, initial_refinement_level=2, - mapping=mapping, periodicity=(false, false)) + polydeg = 3, initial_refinement_level = 2, + mapping = mapping, periodicity = (false, false)) # A semidiscretization collects data structures and functions for the spatial discretization -semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver, - boundary_conditions = (boundary_conditions, boundary_conditions_parabolic)) - +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, solver, + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic)) ############################################################################### # ODE solvers, callbacks etc. @@ -75,22 +76,21 @@ summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) # The AliveCallback prints short status information in regular intervals -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) - ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks time_int_tol = 1.0e-11 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) # Print the timer summary summary_callback() diff --git a/examples/p4est_2d_dgsem/elixir_advection_diffusion_periodic.jl b/examples/p4est_2d_dgsem/elixir_advection_diffusion_periodic.jl index 1cd075e84ea..0b5129e3c0f 100644 --- a/examples/p4est_2d_dgsem/elixir_advection_diffusion_periodic.jl +++ b/examples/p4est_2d_dgsem/elixir_advection_diffusion_periodic.jl @@ -9,19 +9,21 @@ advection_velocity = (1.0, 0.0) equations = LinearScalarAdvectionEquation2D(advection_velocity) equations_parabolic = LaplaceDiffusion2D(diffusivity(), equations) -function x_trans_periodic(x, domain_length=SVector(2 * pi), center=SVector(0.0)) +function x_trans_periodic(x, domain_length = SVector(2 * pi), center = SVector(0.0)) x_normalized = x .- center x_shifted = x_normalized .% domain_length - x_offset = ((x_shifted .< -0.5 * domain_length) - (x_shifted .> 0.5 * domain_length)) .* domain_length + x_offset = ((x_shifted .< -0.5 * domain_length) - (x_shifted .> 0.5 * domain_length)) .* + domain_length return center + x_shifted + x_offset end # Define initial condition (copied from "examples/tree_1d_dgsem/elixir_advection_diffusion.jl") -function initial_condition_diffusive_convergence_test(x, t, equation::LinearScalarAdvectionEquation2D) +function initial_condition_diffusive_convergence_test(x, t, + equation::LinearScalarAdvectionEquation2D) # Store translated coordinate for easy use of exact solution # Assumes that advection_velocity[2] = 0 (effectively that we are solving a 1D equation) x_trans = x_trans_periodic(x[1] - equation.advection_velocity[1] * t) - + nu = diffusivity() c = 0.0 A = 1.0 @@ -32,23 +34,22 @@ end initial_condition = initial_condition_diffusive_convergence_test # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-pi, -pi) # minimum coordinates (min(x), min(y)) -coordinates_max = ( pi, pi) # maximum coordinates (max(x), max(y)) +coordinates_max = (pi, pi) # maximum coordinates (max(x), max(y)) trees_per_dimension = (4, 4) mesh = P4estMesh(trees_per_dimension, - polydeg=3, initial_refinement_level=2, - coordinates_min=coordinates_min, coordinates_max=coordinates_max, - periodicity=true) + polydeg = 3, initial_refinement_level = 2, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + periodicity = true) # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -62,22 +63,21 @@ summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) # The AliveCallback prints short status information in regular intervals -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) - ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks time_int_tol = 1.0e-11 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) # Print the timer summary summary_callback() diff --git a/examples/p4est_2d_dgsem/elixir_advection_diffusion_periodic_amr.jl b/examples/p4est_2d_dgsem/elixir_advection_diffusion_periodic_amr.jl new file mode 100644 index 00000000000..fdecb05f7bd --- /dev/null +++ b/examples/p4est_2d_dgsem/elixir_advection_diffusion_periodic_amr.jl @@ -0,0 +1,83 @@ +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the linear advection-diffusion equation + +advection_velocity = (1.5, 1.0) +equations = LinearScalarAdvectionEquation2D(advection_velocity) +diffusivity() = 5.0e-2 +equations_parabolic = LaplaceDiffusion2D(diffusivity(), equations) + +# Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) + +coordinates_min = (-1.0, -1.0) # minimum coordinates (min(x), min(y)) +coordinates_max = (1.0, 1.0) # maximum coordinates (max(x), max(y)) + +trees_per_dimension = (4, 4) +mesh = P4estMesh(trees_per_dimension, + polydeg = 3, initial_refinement_level = 1, + coordinates_min = coordinates_min, coordinates_max = coordinates_max) + +# Define initial condition +function initial_condition_diffusive_convergence_test(x, t, + equation::LinearScalarAdvectionEquation2D) + # Store translated coordinate for easy use of exact solution + x_trans = x - equation.advection_velocity * t + + nu = diffusivity() + c = 1.0 + A = 0.5 + L = 2 + f = 1 / L + omega = 2 * pi * f + scalar = c + A * sin(omega * sum(x_trans)) * exp(-2 * nu * omega^2 * t) + return SVector(scalar) +end +initial_condition = initial_condition_diffusive_convergence_test + +# A semidiscretization collects data structures and functions for the spatial discretization +semi = SemidiscretizationHyperbolicParabolic(mesh, + (equations, equations_parabolic), + initial_condition, solver) + +############################################################################### +# ODE solvers, callbacks etc. + +# Create ODE problem with time span `tspan` +tspan = (0.0, 0.5) +ode = semidiscretize(semi, tspan); + +# At the beginning of the main loop, the SummaryCallback prints a summary of the simulation setup +# and resets the timers +summary_callback = SummaryCallback() + +# The AnalysisCallback allows to analyse the solution in regular intervals and prints the results +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + +# The AliveCallback prints short status information in regular intervals +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable = first), + base_level = 1, + med_level = 2, med_threshold = 1.25, + max_level = 3, max_threshold = 1.45) + +amr_callback = AMRCallback(semi, amr_controller, + interval = 20) + +# Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver +callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, amr_callback) + +############################################################################### +# run the simulation + +# OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks +time_int_tol = 1.0e-11 +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) + +# Print the timer summary +summary_callback() diff --git a/examples/p4est_2d_dgsem/elixir_advection_diffusion_periodic_curved.jl b/examples/p4est_2d_dgsem/elixir_advection_diffusion_periodic_curved.jl index b438fb8a29c..130def37997 100644 --- a/examples/p4est_2d_dgsem/elixir_advection_diffusion_periodic_curved.jl +++ b/examples/p4est_2d_dgsem/elixir_advection_diffusion_periodic_curved.jl @@ -9,19 +9,21 @@ advection_velocity = (1.0, 0.0) equations = LinearScalarAdvectionEquation2D(advection_velocity) equations_parabolic = LaplaceDiffusion2D(diffusivity(), equations) -function x_trans_periodic(x, domain_length=SVector(2 * pi), center=SVector(0.0)) +function x_trans_periodic(x, domain_length = SVector(2 * pi), center = SVector(0.0)) x_normalized = x .- center x_shifted = x_normalized .% domain_length - x_offset = ((x_shifted .< -0.5 * domain_length) - (x_shifted .> 0.5 * domain_length)) .* domain_length + x_offset = ((x_shifted .< -0.5 * domain_length) - (x_shifted .> 0.5 * domain_length)) .* + domain_length return center + x_shifted + x_offset end # Define initial condition (copied from "examples/tree_1d_dgsem/elixir_advection_diffusion.jl") -function initial_condition_diffusive_convergence_test(x, t, equation::LinearScalarAdvectionEquation2D) +function initial_condition_diffusive_convergence_test(x, t, + equation::LinearScalarAdvectionEquation2D) # Store translated coordinate for easy use of exact solution # Assumes that advection_velocity[2] = 0 (effectively that we are solving a 1D equation) x_trans = x_trans_periodic(x[1] - equation.advection_velocity[1] * t) - + nu = diffusivity() c = 0.0 A = 1.0 @@ -32,28 +34,27 @@ end initial_condition = initial_condition_diffusive_convergence_test # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) # This maps the domain [-1, 1]^2 to [-pi, pi]^2 while also # introducing a curved warping to interior nodes. function mapping(xi, eta) - x = xi + 0.1 * sin(pi * xi) * sin(pi * eta) - y = eta + 0.1 * sin(pi * xi) * sin(pi * eta) - return pi * SVector(x, y) + x = xi + 0.1 * sin(pi * xi) * sin(pi * eta) + y = eta + 0.1 * sin(pi * xi) * sin(pi * eta) + return pi * SVector(x, y) end trees_per_dimension = (4, 4) mesh = P4estMesh(trees_per_dimension, - polydeg=3, initial_refinement_level=2, - mapping=mapping, - periodicity=true) + polydeg = 3, initial_refinement_level = 2, + mapping = mapping, + periodicity = true) # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -67,22 +68,21 @@ summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) # The AliveCallback prints short status information in regular intervals -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) - ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks time_int_tol = 1.0e-11 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) # Print the timer summary summary_callback() diff --git a/examples/p4est_2d_dgsem/elixir_advection_extended.jl b/examples/p4est_2d_dgsem/elixir_advection_extended.jl index 6d8e7030ac0..66a5b7e0f5b 100644 --- a/examples/p4est_2d_dgsem/elixir_advection_extended.jl +++ b/examples/p4est_2d_dgsem/elixir_advection_extended.jl @@ -12,31 +12,28 @@ initial_condition = initial_condition_convergence_test # BCs must be passed as Dict boundary_condition = BoundaryConditionDirichlet(initial_condition) -boundary_conditions = Dict( - :x_neg => boundary_condition, - :x_pos => boundary_condition, - :y_neg => boundary_condition, - :y_pos => boundary_condition -) +boundary_conditions = Dict(:x_neg => boundary_condition, + :x_pos => boundary_condition, + :y_neg => boundary_condition, + :y_pos => boundary_condition) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) # The initial condition is 2-periodic coordinates_min = (-1.5, 1.3) # minimum coordinates (min(x), min(y)) -coordinates_max = ( 0.5, 5.3) # maximum coordinates (max(x), max(y)) +coordinates_max = (0.5, 5.3) # maximum coordinates (max(x), max(y)) trees_per_dimension = (19, 37) # Create curved mesh with 19 x 37 elements -mesh = P4estMesh(trees_per_dimension, polydeg=3, - coordinates_min=coordinates_min, coordinates_max=coordinates_max, - periodicity=false) +mesh = P4estMesh(trees_per_dimension, polydeg = 3, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + periodicity = false) # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -51,24 +48,24 @@ summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy, energy_total)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy, energy_total)) # The AliveCallback prints short status information in regular intervals -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) # The SaveRestartCallback allows to save a file from which a Trixi.jl simulation can be restarted -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver callbacks = CallbackSet(summary_callback, @@ -76,14 +73,13 @@ callbacks = CallbackSet(summary_callback, save_restart, save_solution, stepsize_callback) - ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); # Print the timer summary summary_callback() diff --git a/examples/p4est_2d_dgsem/elixir_advection_nonconforming_flag.jl b/examples/p4est_2d_dgsem/elixir_advection_nonconforming_flag.jl index 0e6e314ebd7..b47b0d61192 100644 --- a/examples/p4est_2d_dgsem/elixir_advection_nonconforming_flag.jl +++ b/examples/p4est_2d_dgsem/elixir_advection_nonconforming_flag.jl @@ -2,7 +2,6 @@ using OrdinaryDiffEq using Trixi - ############################################################################### # semidiscretization of the linear advection equation @@ -10,42 +9,44 @@ advection_velocity = (0.2, -0.7) equations = LinearScalarAdvectionEquation2D(advection_velocity) # Create DG solver with polynomial degree = 4 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=4, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 4, surface_flux = flux_lax_friedrichs) # Deformed rectangle that looks like a waving flag, # lower and upper faces are sinus curves, left and right are vertical lines. f1(s) = SVector(-1.0, s - 1.0) -f2(s) = SVector( 1.0, s + 1.0) +f2(s) = SVector(1.0, s + 1.0) f3(s) = SVector(s, -1.0 + sin(0.5 * pi * s)) -f4(s) = SVector(s, 1.0 + sin(0.5 * pi * s)) +f4(s) = SVector(s, 1.0 + sin(0.5 * pi * s)) # Create P4estMesh with 3 x 2 trees and 6 x 4 elements, # approximate the geometry with a smaller polydeg for testing. trees_per_dimension = (3, 2) -mesh = P4estMesh(trees_per_dimension, polydeg=3, - faces=(f1, f2, f3, f4), - initial_refinement_level=1) +mesh = P4estMesh(trees_per_dimension, polydeg = 3, + faces = (f1, f2, f3, f4), + initial_refinement_level = 1) # Refine bottom left quadrant of each tree to level 4 function refine_fn(p4est, which_tree, quadrant) - quadrant_obj = unsafe_load(quadrant) - if quadrant_obj.x == 0 && quadrant_obj.y == 0 && quadrant_obj.level < 4 - # return true (refine) - return Cint(1) - else - # return false (don't refine) - return Cint(0) - end + quadrant_obj = unsafe_load(quadrant) + if quadrant_obj.x == 0 && quadrant_obj.y == 0 && quadrant_obj.level < 4 + # return true (refine) + return Cint(1) + else + # return false (don't refine) + return Cint(0) + end end # Refine recursively until each bottom left quadrant of a tree has level 4 # The mesh will be rebalanced before the simulation starts -refine_fn_c = @cfunction(refine_fn, Cint, (Ptr{Trixi.p4est_t}, Ptr{Trixi.p4est_topidx_t}, Ptr{Trixi.p4est_quadrant_t})) +refine_fn_c = @cfunction(refine_fn, Cint, + (Ptr{Trixi.p4est_t}, Ptr{Trixi.p4est_topidx_t}, + Ptr{Trixi.p4est_quadrant_t})) Trixi.refine_p4est!(mesh.p4est, true, refine_fn_c, C_NULL) # A semidiscretization collects data structures and functions for the spatial discretization -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, solver) - +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, + solver) ############################################################################### # ODE solvers, callbacks etc. @@ -58,26 +59,26 @@ ode = semidiscretize(semi, (0.0, 0.2)); summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); # Print the timer summary summary_callback() diff --git a/examples/p4est_2d_dgsem/elixir_advection_restart.jl b/examples/p4est_2d_dgsem/elixir_advection_restart.jl index 79a35199b83..0f573714c1f 100644 --- a/examples/p4est_2d_dgsem/elixir_advection_restart.jl +++ b/examples/p4est_2d_dgsem/elixir_advection_restart.jl @@ -10,7 +10,6 @@ restart_file = "restart_000021.h5" trixi_include(@__MODULE__, joinpath(@__DIR__, elixir_file)) - ############################################################################### # adapt the parameters that have changed compared to "elixir_advection_extended.jl" @@ -21,7 +20,7 @@ restart_filename = joinpath("out", restart_file) mesh = load_mesh(restart_filename) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) + boundary_conditions = boundary_conditions) tspan = (load_time(restart_filename), 2.0) dt = load_dt(restart_filename) @@ -30,14 +29,12 @@ ode = semidiscretize(semi, tspan, restart_filename); # Do not overwrite the initial snapshot written by elixir_advection_extended.jl. save_solution.condition.save_initial_solution = false -integrator = init(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=dt, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +integrator = init(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = dt, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks, maxiters = 100_000); # Get the last time index and work with that. -integrator.iter = load_timestep(restart_filename) -integrator.stats.naccept = integrator.iter - +load_timestep!(integrator, restart_filename) ############################################################################### # run the simulation diff --git a/examples/p4est_2d_dgsem/elixir_advection_unstructured_flag.jl b/examples/p4est_2d_dgsem/elixir_advection_unstructured_flag.jl index 9f5b813639f..37fcc547f60 100644 --- a/examples/p4est_2d_dgsem/elixir_advection_unstructured_flag.jl +++ b/examples/p4est_2d_dgsem/elixir_advection_unstructured_flag.jl @@ -3,7 +3,6 @@ using Downloads: download using OrdinaryDiffEq using Trixi - ############################################################################### # semidiscretization of the linear advection equation @@ -13,19 +12,17 @@ equations = LinearScalarAdvectionEquation2D(advection_velocity) initial_condition = initial_condition_convergence_test boundary_condition = BoundaryConditionDirichlet(initial_condition) -boundary_conditions = Dict( - :all => boundary_condition -) +boundary_conditions = Dict(:all => boundary_condition) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) # Deformed rectangle that looks like a waving flag, # lower and upper faces are sinus curves, left and right are vertical lines. f1(s) = SVector(-1.0, s - 1.0) -f2(s) = SVector( 1.0, s + 1.0) +f2(s) = SVector(1.0, s + 1.0) f3(s) = SVector(s, -1.0 + sin(0.5 * pi * s)) -f4(s) = SVector(s, 1.0 + sin(0.5 * pi * s)) +f4(s) = SVector(s, 1.0 + sin(0.5 * pi * s)) faces = (f1, f2, f3, f4) Trixi.validate_faces(faces) @@ -33,16 +30,17 @@ mapping_flag = Trixi.transfinite_mapping(faces) # Unstructured mesh with 24 cells of the square domain [-1, 1]^n mesh_file = joinpath(@__DIR__, "square_unstructured_2.inp") -isfile(mesh_file) || download("https://gist.githubusercontent.com/efaulhaber/63ff2ea224409e55ee8423b3a33e316a/raw/7db58af7446d1479753ae718930741c47a3b79b7/square_unstructured_2.inp", - mesh_file) +isfile(mesh_file) || + download("https://gist.githubusercontent.com/efaulhaber/63ff2ea224409e55ee8423b3a33e316a/raw/7db58af7446d1479753ae718930741c47a3b79b7/square_unstructured_2.inp", + mesh_file) -mesh = P4estMesh{2}(mesh_file, polydeg=3, - mapping=mapping_flag, - initial_refinement_level=2) +mesh = P4estMesh{2}(mesh_file, polydeg = 3, + mapping = mapping_flag, + initial_refinement_level = 2) # A semidiscretization collects data structures and functions for the spatial discretization -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, boundary_conditions=boundary_conditions) - +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -56,26 +54,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.4) +stepsize_callback = StepsizeCallback(cfl = 1.4) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); # Print the timer summary summary_callback() diff --git a/examples/p4est_2d_dgsem/elixir_euler_blast_wave_amr.jl b/examples/p4est_2d_dgsem/elixir_euler_blast_wave_amr.jl index e3f33fb0d28..0ca4fdc2eb7 100644 --- a/examples/p4est_2d_dgsem/elixir_euler_blast_wave_amr.jl +++ b/examples/p4est_2d_dgsem/elixir_euler_blast_wave_amr.jl @@ -17,49 +17,48 @@ A medium blast wave taken from [arXiv: 2008.12044](https://arxiv.org/abs/2008.12044) """ function initial_condition_blast_wave(x, t, equations::CompressibleEulerEquations2D) - # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" - # Set up polar coordinates - inicenter = SVector(0.0, 0.0) - x_norm = x[1] - inicenter[1] - y_norm = x[2] - inicenter[2] - r = sqrt(x_norm^2 + y_norm^2) - phi = atan(y_norm, x_norm) - sin_phi, cos_phi = sincos(phi) - - # Calculate primitive variables - rho = r > 0.5 ? 1.0 : 1.1691 - v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi - v2 = r > 0.5 ? 0.0 : 0.1882 * sin_phi - p = r > 0.5 ? 1.0E-3 : 1.245 - - return prim2cons(SVector(rho, v1, v2, p), equations) + # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" + # Set up polar coordinates + inicenter = SVector(0.0, 0.0) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + phi = atan(y_norm, x_norm) + sin_phi, cos_phi = sincos(phi) + + # Calculate primitive variables + rho = r > 0.5 ? 1.0 : 1.1691 + v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi + v2 = r > 0.5 ? 0.0 : 0.1882 * sin_phi + p = r > 0.5 ? 1.0E-3 : 1.245 + + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_blast_wave surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha +volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) # Unstructured mesh with 48 cells of the square domain [-1, 1]^n mesh_file = joinpath(@__DIR__, "square_unstructured_1.inp") -isfile(mesh_file) || download("https://gist.githubusercontent.com/efaulhaber/a075f8ec39a67fa9fad8f6f84342cbca/raw/a7206a02ed3a5d3cadacd8d9694ac154f9151db7/square_unstructured_1.inp", - mesh_file) +isfile(mesh_file) || + download("https://gist.githubusercontent.com/efaulhaber/a075f8ec39a67fa9fad8f6f84342cbca/raw/a7206a02ed3a5d3cadacd8d9694ac154f9151db7/square_unstructured_1.inp", + mesh_file) -mesh = P4estMesh{2}(mesh_file, polydeg=3, initial_refinement_level=1) +mesh = P4estMesh{2}(mesh_file, polydeg = 3, initial_refinement_level = 1) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=Dict( - :all => BoundaryConditionDirichlet(initial_condition) - )) + boundary_conditions = Dict(:all => BoundaryConditionDirichlet(initial_condition))) ############################################################################### # ODE solvers, callbacks etc. @@ -70,40 +69,39 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_indicator = IndicatorHennemannGassner(semi, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=1, - max_level =3, max_threshold=0.01) + base_level = 1, + max_level = 3, max_threshold = 0.01) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=0.9) +stepsize_callback = StepsizeCallback(cfl = 0.9) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, amr_callback, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/p4est_2d_dgsem/elixir_euler_double_mach_amr.jl b/examples/p4est_2d_dgsem/elixir_euler_double_mach_amr.jl index 6d00aa91ba3..92928146d7b 100644 --- a/examples/p4est_2d_dgsem/elixir_euler_double_mach_amr.jl +++ b/examples/p4est_2d_dgsem/elixir_euler_double_mach_amr.jl @@ -21,64 +21,66 @@ See Section IV c on the paper below for details. The Numerical Simulation of Two-Dimensional Fluid Flows with Strong Shocks. [DOI: 10.1016/0021-9991(84)90142-6](https://doi.org/10.1016/0021-9991(84)90142-6) """ -@inline function initial_condition_double_mach_reflection(x, t, equations::CompressibleEulerEquations2D) - - if x[1] < 1 / 6 + (x[2] + 20 * t) / sqrt(3) - phi = pi / 6 - sin_phi, cos_phi = sincos(phi) - - rho = 8 - v1 = 8.25 * cos_phi - v2 = -8.25 * sin_phi - p = 116.5 - else - rho = 1.4 - v1 = 0 - v2 = 0 - p = 1 - end - - prim = SVector(rho, v1, v2, p) - return prim2cons(prim, equations) +@inline function initial_condition_double_mach_reflection(x, t, + equations::CompressibleEulerEquations2D) + if x[1] < 1 / 6 + (x[2] + 20 * t) / sqrt(3) + phi = pi / 6 + sin_phi, cos_phi = sincos(phi) + + rho = 8.0 + v1 = 8.25 * cos_phi + v2 = -8.25 * sin_phi + p = 116.5 + else + rho = 1.4 + v1 = 0.0 + v2 = 0.0 + p = 1.0 + end + + prim = SVector(rho, v1, v2, p) + return prim2cons(prim, equations) end initial_condition = initial_condition_double_mach_reflection - boundary_condition_inflow = BoundaryConditionDirichlet(initial_condition_double_mach_reflection) # Supersonic outflow boundary condition. Solution is taken entirely from the internal state. # See `examples/p4est_2d_dgsem/elixir_euler_forward_step_amr.jl` for complete documentation. @inline function boundary_condition_outflow(u_inner, normal_direction::AbstractVector, x, t, - surface_flux_function, equations::CompressibleEulerEquations2D) - # NOTE: Only for the supersonic outflow is this strategy valid - # Calculate the boundary flux entirely from the internal solution state - return flux(u_inner, normal_direction, equations) + surface_flux_function, + equations::CompressibleEulerEquations2D) + # NOTE: Only for the supersonic outflow is this strategy valid + # Calculate the boundary flux entirely from the internal solution state + return flux(u_inner, normal_direction, equations) end # Special mixed boundary condition type for the :Bottom of the domain. # It is Dirichlet when x < 1/6 and a slip wall when x >= 1/6 -@inline function boundary_condition_mixed_dirichlet_wall(u_inner, normal_direction::AbstractVector, +@inline function boundary_condition_mixed_dirichlet_wall(u_inner, + normal_direction::AbstractVector, x, t, surface_flux_function, equations::CompressibleEulerEquations2D) - if x[1] < 1 / 6 - # From the BoundaryConditionDirichlet - # get the external value of the solution - u_boundary = initial_condition_double_mach_reflection(x, t, equations) - # Calculate boundary flux - flux = surface_flux_function(u_inner, u_boundary, normal_direction, equations) - else # x[1] >= 1 / 6 - # Use the free slip wall BC otherwise - flux = boundary_condition_slip_wall(u_inner, normal_direction, x, t, surface_flux_function, equations) - end - - return flux + if x[1] < 1 / 6 + # From the BoundaryConditionDirichlet + # get the external value of the solution + u_boundary = initial_condition_double_mach_reflection(x, t, equations) + # Calculate boundary flux + flux = surface_flux_function(u_inner, u_boundary, normal_direction, equations) + else # x[1] >= 1 / 6 + # Use the free slip wall BC otherwise + flux = boundary_condition_slip_wall(u_inner, normal_direction, x, t, + surface_flux_function, equations) + end + + return flux end -boundary_conditions = Dict( :Bottom => boundary_condition_mixed_dirichlet_wall, - :Top => boundary_condition_inflow, - :Right => boundary_condition_outflow, - :Left => boundary_condition_inflow ) +boundary_conditions = Dict(:Bottom => boundary_condition_mixed_dirichlet_wall, + :Top => boundary_condition_inflow, + :Right => boundary_condition_outflow, + :Left => boundary_condition_inflow) volume_flux = flux_ranocha surface_flux = flux_lax_friedrichs @@ -86,25 +88,27 @@ surface_flux = flux_lax_friedrichs polydeg = 4 basis = LobattoLegendreBasis(polydeg) shock_indicator = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(shock_indicator; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) -solver = DGSEM(polydeg=polydeg, surface_flux=surface_flux, volume_integral=volume_integral) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) +solver = DGSEM(polydeg = polydeg, surface_flux = surface_flux, + volume_integral = volume_integral) # Get the unstructured quad mesh from a file (downloads the file if not available locally) default_mesh_file = joinpath(@__DIR__, "abaqus_double_mach.inp") -isfile(default_mesh_file) || download("https://gist.githubusercontent.com/andrewwinters5000/a0806ef0d03cf5ea221af523167b6e32/raw/61ed0eb017eb432d996ed119a52fb041fe363e8c/abaqus_double_mach.inp", - default_mesh_file) +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/a0806ef0d03cf5ea221af523167b6e32/raw/61ed0eb017eb432d996ed119a52fb041fe363e8c/abaqus_double_mach.inp", + default_mesh_file) mesh_file = default_mesh_file mesh = P4estMesh{2}(mesh_file) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -115,27 +119,27 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -amr_indicator = IndicatorLöhner(semi, variable=Trixi.density) +amr_indicator = IndicatorLöhner(semi, variable = Trixi.density) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=0, - med_level=3, med_threshold=0.05, - max_level=6, max_threshold=0.1) + base_level = 0, + med_level = 3, med_threshold = 0.05, + max_level = 6, max_threshold = 0.1) amr_callback = AMRCallback(semi, amr_controller, - interval=1, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 1, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -143,11 +147,11 @@ callbacks = CallbackSet(summary_callback, amr_callback) # positivity limiter necessary for this example with strong shocks -stage_limiter! = PositivityPreservingLimiterZhangShu(thresholds=(5.0e-6, 5.0e-6), - variables=(Trixi.density, pressure)) +stage_limiter! = PositivityPreservingLimiterZhangShu(thresholds = (5.0e-6, 5.0e-6), + variables = (Trixi.density, pressure)) ############################################################################### # run the simulation sol = solve(ode, SSPRK43(stage_limiter!); - ode_default_options()..., callback=callbacks); + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/p4est_2d_dgsem/elixir_euler_forward_step_amr.jl b/examples/p4est_2d_dgsem/elixir_euler_forward_step_amr.jl index 667834ea108..0ec9fc222f2 100644 --- a/examples/p4est_2d_dgsem/elixir_euler_forward_step_amr.jl +++ b/examples/p4est_2d_dgsem/elixir_euler_forward_step_amr.jl @@ -20,19 +20,18 @@ See Section IV b on the paper below for details. [DOI: 10.1016/0021-9991(84)90142-6](https://doi.org/10.1016/0021-9991(84)90142-6) """ @inline function initial_condition_mach3_flow(x, t, equations::CompressibleEulerEquations2D) - # set the freestream flow parameters - rho_freestream = 1.4 - v1 = 3.0 - v2 = 0.0 - p_freestream = 1.0 - - prim = SVector(rho_freestream, v1, v2, p_freestream) - return prim2cons(prim, equations) + # set the freestream flow parameters + rho_freestream = 1.4 + v1 = 3.0 + v2 = 0.0 + p_freestream = 1.0 + + prim = SVector(rho_freestream, v1, v2, p_freestream) + return prim2cons(prim, equations) end initial_condition = initial_condition_mach3_flow - boundary_condition_inflow = BoundaryConditionDirichlet(initial_condition_mach3_flow) # Outflow boundary condition. @@ -46,46 +45,47 @@ boundary_condition_inflow = BoundaryConditionDirichlet(initial_condition_mach3_f # Inflow/Outflow Boundary Conditions with Application to FUN3D. # [NASA TM 20110022658](https://ntrs.nasa.gov/citations/20110022658) @inline function boundary_condition_outflow(u_inner, normal_direction::AbstractVector, x, t, - surface_flux_function, equations::CompressibleEulerEquations2D) - # # This would be for the general case where we need to check the magnitude of the local Mach number - # norm_ = norm(normal_direction) - # # Normalize the vector without using `normalize` since we need to multiply by the `norm_` later - # normal = normal_direction / norm_ - - # # Rotate the internal solution state - # u_local = Trixi.rotate_to_x(u_inner, normal, equations) - - # # Compute the primitive variables - # rho_local, v_normal, v_tangent, p_local = cons2prim(u_local, equations) - - # # Compute local Mach number - # a_local = sqrt( equations.gamma * p_local / rho_local ) - # Mach_local = abs( v_normal / a_local ) - # if Mach_local <= 1.0 - # p_local = # Set to the external reference pressure value (somehow? maybe stored in `equations`) - # end - - # # Create the `u_surface` solution state where the local pressure is possibly set from an external value - # prim = SVector(rho_local, v_normal, v_tangent, p_local) - # u_boundary = prim2cons(prim, equations) - # u_surface = Trixi.rotate_from_x(u_boundary, normal, equations) - - # Compute the flux using the appropriate mixture of internal / external solution states - # flux = Trixi.flux(u_surface, normal_direction, equations) - - # NOTE: Only for the supersonic outflow is this strategy valid - # Calculate the boundary flux entirely from the internal solution state - flux = Trixi.flux(u_inner, normal_direction, equations) - - return flux + surface_flux_function, + equations::CompressibleEulerEquations2D) + # # This would be for the general case where we need to check the magnitude of the local Mach number + # norm_ = norm(normal_direction) + # # Normalize the vector without using `normalize` since we need to multiply by the `norm_` later + # normal = normal_direction / norm_ + + # # Rotate the internal solution state + # u_local = Trixi.rotate_to_x(u_inner, normal, equations) + + # # Compute the primitive variables + # rho_local, v_normal, v_tangent, p_local = cons2prim(u_local, equations) + + # # Compute local Mach number + # a_local = sqrt( equations.gamma * p_local / rho_local ) + # Mach_local = abs( v_normal / a_local ) + # if Mach_local <= 1.0 + # p_local = # Set to the external reference pressure value (somehow? maybe stored in `equations`) + # end + + # # Create the `u_surface` solution state where the local pressure is possibly set from an external value + # prim = SVector(rho_local, v_normal, v_tangent, p_local) + # u_boundary = prim2cons(prim, equations) + # u_surface = Trixi.rotate_from_x(u_boundary, normal, equations) + + # Compute the flux using the appropriate mixture of internal / external solution states + # flux = Trixi.flux(u_surface, normal_direction, equations) + + # NOTE: Only for the supersonic outflow is this strategy valid + # Calculate the boundary flux entirely from the internal solution state + flux = Trixi.flux(u_inner, normal_direction, equations) + + return flux end -boundary_conditions = Dict( :Bottom => boundary_condition_slip_wall, - :Step_Front => boundary_condition_slip_wall, - :Step_Top => boundary_condition_slip_wall, - :Top => boundary_condition_slip_wall, - :Right => boundary_condition_outflow, - :Left => boundary_condition_inflow ) +boundary_conditions = Dict(:Bottom => boundary_condition_slip_wall, + :Step_Front => boundary_condition_slip_wall, + :Step_Top => boundary_condition_slip_wall, + :Top => boundary_condition_slip_wall, + :Right => boundary_condition_outflow, + :Left => boundary_condition_inflow) volume_flux = flux_ranocha surface_flux = flux_lax_friedrichs @@ -93,25 +93,27 @@ surface_flux = flux_lax_friedrichs polydeg = 4 basis = LobattoLegendreBasis(polydeg) shock_indicator = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(shock_indicator; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) -solver = DGSEM(polydeg=polydeg, surface_flux=surface_flux, volume_integral=volume_integral) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) +solver = DGSEM(polydeg = polydeg, surface_flux = surface_flux, + volume_integral = volume_integral) # Get the unstructured quad mesh from a file (downloads the file if not available locally) default_mesh_file = joinpath(@__DIR__, "abaqus_forward_step.inp") -isfile(default_mesh_file) || download("https://gist.githubusercontent.com/andrewwinters5000/b346ee6aa5446687f128eab8b37d52a7/raw/cd1e1d43bebd8d2631a07caec45585ec8456ca4c/abaqus_forward_step.inp", - default_mesh_file) +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/b346ee6aa5446687f128eab8b37d52a7/raw/cd1e1d43bebd8d2631a07caec45585ec8456ca4c/abaqus_forward_step.inp", + default_mesh_file) mesh_file = default_mesh_file mesh = P4estMesh{2}(mesh_file) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -122,27 +124,27 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=2000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 2000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -amr_indicator = IndicatorLöhner(semi, variable=Trixi.density) +amr_indicator = IndicatorLöhner(semi, variable = Trixi.density) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=0, - med_level=2, med_threshold=0.05, - max_level=5, max_threshold=0.1) + base_level = 0, + med_level = 2, med_threshold = 0.05, + max_level = 5, max_threshold = 0.1) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -150,12 +152,12 @@ callbacks = CallbackSet(summary_callback, amr_callback) # positivity limiter necessary for this example with strong shocks -stage_limiter! = PositivityPreservingLimiterZhangShu(thresholds=(5.0e-6, 5.0e-6), - variables=(Trixi.density, pressure)) +stage_limiter! = PositivityPreservingLimiterZhangShu(thresholds = (5.0e-6, 5.0e-6), + variables = (Trixi.density, pressure)) ############################################################################### # run the simulation sol = solve(ode, SSPRK43(stage_limiter!); - maxiters=999999, ode_default_options()..., - callback=callbacks); + maxiters = 999999, ode_default_options()..., + callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/p4est_2d_dgsem/elixir_euler_free_stream.jl b/examples/p4est_2d_dgsem/elixir_euler_free_stream.jl index e88baa2223d..38307a7d781 100644 --- a/examples/p4est_2d_dgsem/elixir_euler_free_stream.jl +++ b/examples/p4est_2d_dgsem/elixir_euler_free_stream.jl @@ -10,21 +10,21 @@ equations = CompressibleEulerEquations2D(1.4) initial_condition = initial_condition_constant -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) # Mapping as described in https://arxiv.org/abs/2012.12040 but reduced to 2D function mapping(xi_, eta_) - # Transform input variables between -1 and 1 onto [0,3] - xi = 1.5 * xi_ + 1.5 - eta = 1.5 * eta_ + 1.5 + # Transform input variables between -1 and 1 onto [0,3] + xi = 1.5 * xi_ + 1.5 + eta = 1.5 * eta_ + 1.5 - y = eta + 3/8 * (cos(1.5 * pi * (2 * xi - 3)/3) * - cos(0.5 * pi * (2 * eta - 3)/3)) + y = eta + 3 / 8 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3)) - x = xi + 3/8 * (cos(0.5 * pi * (2 * xi - 3)/3) * - cos(2 * pi * (2 * y - 3)/3)) + x = xi + 3 / 8 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3)) - return SVector(x, y) + return SVector(x, y) end ############################################################################### @@ -32,34 +32,34 @@ end # Unstructured mesh with 48 cells of the square domain [-1, 1]^n mesh_file = joinpath(@__DIR__, "square_unstructured_1.inp") -isfile(mesh_file) || download("https://gist.githubusercontent.com/efaulhaber/a075f8ec39a67fa9fad8f6f84342cbca/raw/a7206a02ed3a5d3cadacd8d9694ac154f9151db7/square_unstructured_1.inp", - mesh_file) +isfile(mesh_file) || + download("https://gist.githubusercontent.com/efaulhaber/a075f8ec39a67fa9fad8f6f84342cbca/raw/a7206a02ed3a5d3cadacd8d9694ac154f9151db7/square_unstructured_1.inp", + mesh_file) # Map the unstructured mesh with the mapping above -mesh = P4estMesh{2}(mesh_file, polydeg=3, mapping=mapping, initial_refinement_level=1) +mesh = P4estMesh{2}(mesh_file, polydeg = 3, mapping = mapping, initial_refinement_level = 1) # Refine bottom left quadrant of each tree to level 2 function refine_fn(p4est, which_tree, quadrant) - quadrant_obj = unsafe_load(quadrant) - if quadrant_obj.x == 0 && quadrant_obj.y == 0 && quadrant_obj.level < 3 - # return true (refine) - return Cint(1) - else - # return false (don't refine) - return Cint(0) - end + quadrant_obj = unsafe_load(quadrant) + if quadrant_obj.x == 0 && quadrant_obj.y == 0 && quadrant_obj.level < 3 + # return true (refine) + return Cint(1) + else + # return false (don't refine) + return Cint(0) + end end # Refine recursively until each bottom left quadrant of a tree has level 2. # The mesh will be rebalanced before the simulation starts. -refine_fn_c = @cfunction(refine_fn, Cint, (Ptr{Trixi.p4est_t}, Ptr{Trixi.p4est_topidx_t}, Ptr{Trixi.p4est_quadrant_t})) +refine_fn_c = @cfunction(refine_fn, Cint, + (Ptr{Trixi.p4est_t}, Ptr{Trixi.p4est_topidx_t}, + Ptr{Trixi.p4est_quadrant_t})) Trixi.refine_p4est!(mesh.p4est, true, refine_fn_c, C_NULL) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=Dict( - :all => BoundaryConditionDirichlet(initial_condition) - )) - + boundary_conditions = Dict(:all => BoundaryConditionDirichlet(initial_condition))) ############################################################################### # ODE solvers, callbacks etc. @@ -70,16 +70,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=2.0) +stepsize_callback = StepsizeCallback(cfl = 2.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -89,7 +89,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/p4est_2d_dgsem/elixir_euler_sedov.jl b/examples/p4est_2d_dgsem/elixir_euler_sedov.jl index d5d8e0c78bf..539ddb45395 100644 --- a/examples/p4est_2d_dgsem/elixir_euler_sedov.jl +++ b/examples/p4est_2d_dgsem/elixir_euler_sedov.jl @@ -14,25 +14,25 @@ The Sedov blast wave setup based on Flash - https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 """ function initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEquations2D) - # Set up polar coordinates - inicenter = SVector(0.0, 0.0) - x_norm = x[1] - inicenter[1] - y_norm = x[2] - inicenter[2] - r = sqrt(x_norm^2 + y_norm^2) - - # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 - r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) - E = 1.0 - p0_inner = 3 * (equations.gamma - 1) * E / (3 * pi * r0^2) - p0_outer = 1.0e-5 # = true Sedov setup - - # Calculate primitive variables - rho = 1.0 - v1 = 0.0 - v2 = 0.0 - p = r > r0 ? p0_outer : p0_inner - - return prim2cons(SVector(rho, v1, v2, p), equations) + # Set up polar coordinates + inicenter = SVector(0.0, 0.0) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + + # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 + r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) + E = 1.0 + p0_inner = 3 * (equations.gamma - 1) * E / (3 * pi * r0^2) + p0_outer = 1.0e-5 # = true Sedov setup + + # Calculate primitive variables + rho = 1.0 + v1 = 0.0 + v2 = 0.0 + p = r > r0 ? p0_outer : p0_inner + + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_sedov_blast_wave @@ -43,26 +43,27 @@ volume_flux = flux_ranocha polydeg = 4 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=1.0, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 1.0, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) -solver = DGSEM(polydeg=polydeg, surface_flux=surface_flux, volume_integral=volume_integral) +solver = DGSEM(polydeg = polydeg, surface_flux = surface_flux, + volume_integral = volume_integral) ############################################################################### coordinates_min = (-1.0, -1.0) -coordinates_max = ( 1.0, 1.0) +coordinates_max = (1.0, 1.0) trees_per_dimension = (4, 4) mesh = P4estMesh(trees_per_dimension, - polydeg=4, initial_refinement_level=2, - coordinates_min=coordinates_min, coordinates_max=coordinates_max, - periodicity=true) + polydeg = 4, initial_refinement_level = 2, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -75,15 +76,15 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 300 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=300, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 300, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -94,7 +95,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/p4est_2d_dgsem/elixir_euler_shockcapturing_ec.jl b/examples/p4est_2d_dgsem/elixir_euler_shockcapturing_ec.jl index 6ef551c486f..0cb18526f8d 100644 --- a/examples/p4est_2d_dgsem/elixir_euler_shockcapturing_ec.jl +++ b/examples/p4est_2d_dgsem/elixir_euler_shockcapturing_ec.jl @@ -14,30 +14,30 @@ volume_flux = flux_ranocha polydeg = 4 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=1.0, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 1.0, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) -solver = DGSEM(polydeg=polydeg, surface_flux=surface_flux, volume_integral=volume_integral) +solver = DGSEM(polydeg = polydeg, surface_flux = surface_flux, + volume_integral = volume_integral) ############################################################################### coordinates_min = (-1.0, -1.0) -coordinates_max = ( 1.0, 1.0) +coordinates_max = (1.0, 1.0) trees_per_dimension = (4, 4) mesh = P4estMesh(trees_per_dimension, - polydeg=4, initial_refinement_level=2, - coordinates_min=coordinates_min, coordinates_max=coordinates_max, - periodicity=true) + polydeg = 4, initial_refinement_level = 2, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -47,16 +47,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -66,7 +66,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/p4est_2d_dgsem/elixir_euler_source_terms_nonconforming_unstructured_flag.jl b/examples/p4est_2d_dgsem/elixir_euler_source_terms_nonconforming_unstructured_flag.jl index d9a322b065a..09d018309a6 100644 --- a/examples/p4est_2d_dgsem/elixir_euler_source_terms_nonconforming_unstructured_flag.jl +++ b/examples/p4est_2d_dgsem/elixir_euler_source_terms_nonconforming_unstructured_flag.jl @@ -14,18 +14,16 @@ source_terms = source_terms_convergence_test # BCs must be passed as Dict boundary_condition = BoundaryConditionDirichlet(initial_condition) -boundary_conditions = Dict( - :all => boundary_condition -) +boundary_conditions = Dict(:all => boundary_condition) -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) # Deformed rectangle that looks like a waving flag, # lower and upper faces are sinus curves, left and right are vertical lines. f1(s) = SVector(-1.0, s - 1.0) -f2(s) = SVector( 1.0, s + 1.0) +f2(s) = SVector(1.0, s + 1.0) f3(s) = SVector(s, -1.0 + sin(0.5 * pi * s)) -f4(s) = SVector(s, 1.0 + sin(0.5 * pi * s)) +f4(s) = SVector(s, 1.0 + sin(0.5 * pi * s)) faces = (f1, f2, f3, f4) Trixi.validate_faces(faces) @@ -34,34 +32,36 @@ mapping_flag = Trixi.transfinite_mapping(faces) # Get the uncurved mesh from a file (downloads the file if not available locally) # Unstructured mesh with 24 cells of the square domain [-1, 1]^n mesh_file = joinpath(@__DIR__, "square_unstructured_2.inp") -isfile(mesh_file) || download("https://gist.githubusercontent.com/efaulhaber/63ff2ea224409e55ee8423b3a33e316a/raw/7db58af7446d1479753ae718930741c47a3b79b7/square_unstructured_2.inp", - mesh_file) +isfile(mesh_file) || + download("https://gist.githubusercontent.com/efaulhaber/63ff2ea224409e55ee8423b3a33e316a/raw/7db58af7446d1479753ae718930741c47a3b79b7/square_unstructured_2.inp", + mesh_file) -mesh = P4estMesh{2}(mesh_file, polydeg=3, - mapping=mapping_flag, - initial_refinement_level=1) +mesh = P4estMesh{2}(mesh_file, polydeg = 3, + mapping = mapping_flag, + initial_refinement_level = 1) # Refine bottom left quadrant of each tree to level 2 function refine_fn(p4est, which_tree, quadrant) - quadrant_obj = unsafe_load(quadrant) - if quadrant_obj.x == 0 && quadrant_obj.y == 0 && quadrant_obj.level < 2 - # return true (refine) - return Cint(1) - else - # return false (don't refine) - return Cint(0) - end + quadrant_obj = unsafe_load(quadrant) + if quadrant_obj.x == 0 && quadrant_obj.y == 0 && quadrant_obj.level < 2 + # return true (refine) + return Cint(1) + else + # return false (don't refine) + return Cint(0) + end end # Refine recursively until each bottom left quadrant of a tree has level 2 # The mesh will be rebalanced before the simulation starts -refine_fn_c = @cfunction(refine_fn, Cint, (Ptr{Trixi.p4est_t}, Ptr{Trixi.p4est_topidx_t}, Ptr{Trixi.p4est_quadrant_t})) +refine_fn_c = @cfunction(refine_fn, Cint, + (Ptr{Trixi.p4est_t}, Ptr{Trixi.p4est_topidx_t}, + Ptr{Trixi.p4est_quadrant_t})) Trixi.refine_p4est!(mesh.p4est, true, refine_fn_c, C_NULL) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms, - boundary_conditions=boundary_conditions) - + source_terms = source_terms, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -72,19 +72,19 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -93,7 +93,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/p4est_2d_dgsem/elixir_euler_supersonic_cylinder.jl b/examples/p4est_2d_dgsem/elixir_euler_supersonic_cylinder.jl index 366be700f9f..36c5624ba97 100644 --- a/examples/p4est_2d_dgsem/elixir_euler_supersonic_cylinder.jl +++ b/examples/p4est_2d_dgsem/elixir_euler_supersonic_cylinder.jl @@ -23,14 +23,14 @@ using Trixi equations = CompressibleEulerEquations2D(1.4) @inline function initial_condition_mach3_flow(x, t, equations::CompressibleEulerEquations2D) - # set the freestream flow parameters - rho_freestream = 1.4 - v1 = 3.0 - v2 = 0.0 - p_freestream = 1.0 - - prim = SVector(rho_freestream, v1, v2, p_freestream) - return prim2cons(prim, equations) + # set the freestream flow parameters + rho_freestream = 1.4 + v1 = 3.0 + v2 = 0.0 + p_freestream = 1.0 + + prim = SVector(rho_freestream, v1, v2, p_freestream) + return prim2cons(prim, equations) end initial_condition = initial_condition_mach3_flow @@ -38,30 +38,32 @@ initial_condition = initial_condition_mach3_flow # Supersonic inflow boundary condition. # Calculate the boundary flux entirely from the external solution state, i.e., set # external solution state values for everything entering the domain. -@inline function boundary_condition_supersonic_inflow(u_inner, normal_direction::AbstractVector, x, t, - surface_flux_function, equations::CompressibleEulerEquations2D) - u_boundary = initial_condition_mach3_flow(x, t, equations) - flux = Trixi.flux(u_boundary, normal_direction, equations) - - return flux +@inline function boundary_condition_supersonic_inflow(u_inner, + normal_direction::AbstractVector, + x, t, surface_flux_function, + equations::CompressibleEulerEquations2D) + u_boundary = initial_condition_mach3_flow(x, t, equations) + flux = Trixi.flux(u_boundary, normal_direction, equations) + + return flux end - # Supersonic outflow boundary condition. # Calculate the boundary flux entirely from the internal solution state. Analogous to supersonic inflow # except all the solution state values are set from the internal solution as everything leaves the domain @inline function boundary_condition_outflow(u_inner, normal_direction::AbstractVector, x, t, - surface_flux_function, equations::CompressibleEulerEquations2D) - flux = Trixi.flux(u_inner, normal_direction, equations) + surface_flux_function, + equations::CompressibleEulerEquations2D) + flux = Trixi.flux(u_inner, normal_direction, equations) - return flux + return flux end -boundary_conditions = Dict( :Bottom => boundary_condition_slip_wall, - :Circle => boundary_condition_slip_wall, - :Top => boundary_condition_slip_wall, - :Right => boundary_condition_outflow, - :Left => boundary_condition_supersonic_inflow ) +boundary_conditions = Dict(:Bottom => boundary_condition_slip_wall, + :Circle => boundary_condition_slip_wall, + :Top => boundary_condition_slip_wall, + :Right => boundary_condition_outflow, + :Left => boundary_condition_supersonic_inflow) volume_flux = flux_ranocha_turbo surface_flux = flux_lax_friedrichs @@ -69,25 +71,27 @@ surface_flux = flux_lax_friedrichs polydeg = 3 basis = LobattoLegendreBasis(polydeg) shock_indicator = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(shock_indicator; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) -solver = DGSEM(polydeg=polydeg, surface_flux=surface_flux, volume_integral=volume_integral) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) +solver = DGSEM(polydeg = polydeg, surface_flux = surface_flux, + volume_integral = volume_integral) # Get the unstructured quad mesh from a file (downloads the file if not available locally) default_mesh_file = joinpath(@__DIR__, "abaqus_cylinder_in_channel.inp") -isfile(default_mesh_file) || download("https://gist.githubusercontent.com/andrewwinters5000/a08f78f6b185b63c3baeff911a63f628/raw/addac716ea0541f588b9d2bd3f92f643eb27b88f/abaqus_cylinder_in_channel.inp", - default_mesh_file) +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/a08f78f6b185b63c3baeff911a63f628/raw/addac716ea0541f588b9d2bd3f92f643eb27b88f/abaqus_cylinder_in_channel.inp", + default_mesh_file) mesh_file = default_mesh_file mesh = P4estMesh{2}(mesh_file) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers @@ -100,26 +104,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -amr_indicator = IndicatorLöhner(semi, variable=Trixi.density) +amr_indicator = IndicatorLöhner(semi, variable = Trixi.density) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=0, - med_level=3, med_threshold=0.05, - max_level=5, max_threshold=0.1) + base_level = 0, + med_level = 3, med_threshold = 0.05, + max_level = 5, max_threshold = 0.1) amr_callback = AMRCallback(semi, amr_controller, - interval=1, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 1, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -128,11 +132,11 @@ callbacks = CallbackSet(summary_callback, # positivity limiter necessary for this example with strong shocks. Very sensitive # to the order of the limiter variables, pressure must come first. -stage_limiter! = PositivityPreservingLimiterZhangShu(thresholds=(5.0e-7, 1.0e-6), - variables=(pressure, Trixi.density)) +stage_limiter! = PositivityPreservingLimiterZhangShu(thresholds = (5.0e-7, 1.0e-6), + variables = (pressure, Trixi.density)) ############################################################################### # run the simulation sol = solve(ode, SSPRK43(stage_limiter!); - ode_default_options()..., callback=callbacks); + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/p4est_2d_dgsem/elixir_euler_wall_bc_amr.jl b/examples/p4est_2d_dgsem/elixir_euler_wall_bc_amr.jl index 7c7896ce372..8b8d05bade8 100644 --- a/examples/p4est_2d_dgsem/elixir_euler_wall_bc_amr.jl +++ b/examples/p4est_2d_dgsem/elixir_euler_wall_bc_amr.jl @@ -9,45 +9,46 @@ using Trixi equations = CompressibleEulerEquations2D(1.4) @inline function uniform_flow_state(x, t, equations::CompressibleEulerEquations2D) - # set the freestream flow parameters - rho_freestream = 1.0 - u_freestream = 0.3 - p_freestream = inv(equations.gamma) - - theta = pi / 90.0 # analogous with a two degree angle of attack - si, co = sincos(theta) - v1 = u_freestream * co - v2 = u_freestream * si - - prim = SVector(rho_freestream, v1, v2, p_freestream) - return prim2cons(prim, equations) + # set the freestream flow parameters + rho_freestream = 1.0 + u_freestream = 0.3 + p_freestream = inv(equations.gamma) + + theta = pi / 90.0 # analogous with a two degree angle of attack + si, co = sincos(theta) + v1 = u_freestream * co + v2 = u_freestream * si + + prim = SVector(rho_freestream, v1, v2, p_freestream) + return prim2cons(prim, equations) end initial_condition = uniform_flow_state boundary_condition_uniform_flow = BoundaryConditionDirichlet(uniform_flow_state) -boundary_conditions = Dict( :Body => boundary_condition_uniform_flow, - :Button1 => boundary_condition_slip_wall, - :Button2 => boundary_condition_slip_wall, - :Eye1 => boundary_condition_slip_wall, - :Eye2 => boundary_condition_slip_wall, - :Smile => boundary_condition_slip_wall, - :Bowtie => boundary_condition_slip_wall ) +boundary_conditions = Dict(:Body => boundary_condition_uniform_flow, + :Button1 => boundary_condition_slip_wall, + :Button2 => boundary_condition_slip_wall, + :Eye1 => boundary_condition_slip_wall, + :Eye2 => boundary_condition_slip_wall, + :Smile => boundary_condition_slip_wall, + :Bowtie => boundary_condition_slip_wall) volume_flux = flux_ranocha -solver = DGSEM(polydeg=5, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 5, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) # Get the unstructured quad mesh from a file (downloads the file if not available locally) default_mesh_file = joinpath(@__DIR__, "abaqus_gingerbread_man.inp") -isfile(default_mesh_file) || download("https://gist.githubusercontent.com/andrewwinters5000/0e9e990a04b5105d1d2e3096a6e41272/raw/0d924b1d7e7d3cc1070a6cc22fe1d501687aa6dd/abaqus_gingerbread_man.inp", - default_mesh_file) +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/0e9e990a04b5105d1d2e3096a6e41272/raw/0d924b1d7e7d3cc1070a6cc22fe1d501687aa6dd/abaqus_gingerbread_man.inp", + default_mesh_file) mesh_file = default_mesh_file mesh = P4estMesh{2}(mesh_file) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -58,36 +59,35 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -amr_indicator = IndicatorLöhner(semi, variable=density) +amr_indicator = IndicatorLöhner(semi, variable = density) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=0, - med_level=1, med_threshold=0.05, - max_level=3, max_threshold=0.1) + base_level = 0, + med_level = 1, med_threshold = 0.05, + max_level = 3, max_threshold = 0.1) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, amr_callback) - ############################################################################### # run the simulation -sol = solve(ode, RDPK3SpFSAL49(); abstol=1.0e-7, reltol=1.0e-7, - ode_default_options()..., callback=callbacks); +sol = solve(ode, RDPK3SpFSAL49(); abstol = 1.0e-7, reltol = 1.0e-7, + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/p4est_2d_dgsem/elixir_eulergravity_convergence.jl b/examples/p4est_2d_dgsem/elixir_eulergravity_convergence.jl index b34c73d2a4e..d55a59ca5ce 100644 --- a/examples/p4est_2d_dgsem/elixir_eulergravity_convergence.jl +++ b/examples/p4est_2d_dgsem/elixir_eulergravity_convergence.jl @@ -2,10 +2,8 @@ using OrdinaryDiffEq using Trixi - initial_condition = initial_condition_eoc_test_coupled_euler_gravity - ############################################################################### # semidiscretization of the compressible Euler equations gamma = 2.0 @@ -18,13 +16,13 @@ coordinates_min = (0.0, 0.0) coordinates_max = (2.0, 2.0) trees_per_dimension = (1, 1) -mesh = P4estMesh(trees_per_dimension, polydeg=1, - coordinates_min=coordinates_min, coordinates_max=coordinates_max, - initial_refinement_level=2) - -semi_euler = SemidiscretizationHyperbolic(mesh, equations_euler, initial_condition, solver_euler, - source_terms=source_terms_eoc_test_coupled_euler_gravity) +mesh = P4estMesh(trees_per_dimension, polydeg = 1, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + initial_refinement_level = 2) +semi_euler = SemidiscretizationHyperbolic(mesh, equations_euler, initial_condition, + solver_euler, + source_terms = source_terms_eoc_test_coupled_euler_gravity) ############################################################################### # semidiscretization of the hyperbolic diffusion equations @@ -32,24 +30,23 @@ equations_gravity = HyperbolicDiffusionEquations2D() solver_gravity = DGSEM(polydeg, flux_lax_friedrichs) -semi_gravity = SemidiscretizationHyperbolic(mesh, equations_gravity, initial_condition, solver_gravity, - source_terms=source_terms_harmonic) - +semi_gravity = SemidiscretizationHyperbolic(mesh, equations_gravity, initial_condition, + solver_gravity, + source_terms = source_terms_harmonic) ############################################################################### # combining both semidiscretizations for Euler + self-gravity -parameters = ParametersEulerGravity(background_density=2.0, # aka rho0 +parameters = ParametersEulerGravity(background_density = 2.0, # aka rho0 # rho0 is (ab)used to add a "+8π" term to the source terms # for the manufactured solution - gravitational_constant=1.0, # aka G - cfl=1.1, - resid_tol=1.0e-10, - n_iterations_max=1000, - timestep_gravity=timestep_gravity_erk52_3Sstar!) + gravitational_constant = 1.0, # aka G + cfl = 1.1, + resid_tol = 1.0e-10, + n_iterations_max = 1000, + timestep_gravity = timestep_gravity_erk52_3Sstar!) semi = SemidiscretizationEulerGravity(semi_euler, semi_gravity, parameters) - ############################################################################### # ODE solvers, callbacks etc. tspan = (0.0, 0.5) @@ -57,31 +54,30 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) -save_solution = SaveSolutionCallback(interval=10, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 10, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) analysis_interval = 100 -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -analysis_callback = AnalysisCallback(semi_euler, interval=analysis_interval, - save_analysis=true) +analysis_callback = AnalysisCallback(semi_euler, interval = analysis_interval, + save_analysis = true) callbacks = CallbackSet(summary_callback, stepsize_callback, save_restart, save_solution, analysis_callback, alive_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary println("Number of gravity subcycles: ", semi.gravity_counter.ncalls_since_readout) diff --git a/examples/p4est_2d_dgsem/elixir_linearizedeuler_gaussian_source.jl b/examples/p4est_2d_dgsem/elixir_linearizedeuler_gaussian_source.jl index ba2ec827778..364e0296449 100644 --- a/examples/p4est_2d_dgsem/elixir_linearizedeuler_gaussian_source.jl +++ b/examples/p4est_2d_dgsem/elixir_linearizedeuler_gaussian_source.jl @@ -8,20 +8,22 @@ using Trixi # Oscillating Gaussian-shaped source terms function source_terms_gauss(u, x, t, equations::LinearizedEulerEquations2D) - r = 0.1 - A = 1.0 - f = 2.0 + r = 0.1 + A = 1.0 + f = 2.0 - # Velocity sources - s2 = 0.0 - s3 = 0.0 - # Density and pressure source - s1 = s4 = exp(-(x[1]^2 + x[2]^2) / (2 * r^2)) * A * sin(2 * pi * f * t) + # Velocity sources + s2 = 0.0 + s3 = 0.0 + # Density and pressure source + s1 = s4 = exp(-(x[1]^2 + x[2]^2) / (2 * r^2)) * A * sin(2 * pi * f * t) - return SVector(s1, s2, s3, s4) + return SVector(s1, s2, s3, s4) end -initial_condition_zero(x, t, equations::LinearizedEulerEquations2D) = SVector(0.0, 0.0, 0.0, 0.0) +function initial_condition_zero(x, t, equations::LinearizedEulerEquations2D) + SVector(0.0, 0.0, 0.0, 0.0) +end ############################################################################### # semidiscretization of the linearized Euler equations @@ -30,28 +32,27 @@ initial_condition_zero(x, t, equations::LinearizedEulerEquations2D) = SVector(0. c = cospi(2 * 30.0 / 360.0) s = sinpi(2 * 30.0 / 360.0) rot_mat = Trixi.SMatrix{2, 2}([c -s; s c]) -mapping(xi, eta) = rot_mat * SVector(3.0*xi, 3.0*eta) +mapping(xi, eta) = rot_mat * SVector(3.0 * xi, 3.0 * eta) # Mean density and speed of sound are slightly off from 1.0 to allow proper verification of # curved LEE implementation using this elixir (some things in the LEE cancel if both are 1.0) -equations = LinearizedEulerEquations2D(v_mean_global=Tuple(rot_mat * SVector(-0.5, 0.25)), - c_mean_global=1.02, rho_mean_global=1.01) +equations = LinearizedEulerEquations2D(v_mean_global = Tuple(rot_mat * SVector(-0.5, 0.25)), + c_mean_global = 1.02, rho_mean_global = 1.01) initial_condition = initial_condition_zero # Create DG solver with polynomial degree = 3 and upwind flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_godunov) +solver = DGSEM(polydeg = 3, surface_flux = flux_godunov) # Create a uniformly refined mesh with periodic boundaries trees_per_dimension = (4, 4) -mesh = P4estMesh(trees_per_dimension, polydeg=1, - mapping=mapping, - periodicity=true, initial_refinement_level=2) +mesh = P4estMesh(trees_per_dimension, polydeg = 1, + mapping = mapping, + periodicity = true, initial_refinement_level = 2) # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_gauss) - + source_terms = source_terms_gauss) ############################################################################### # ODE solvers, callbacks etc. @@ -65,25 +66,25 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100) +save_solution = SaveSolutionCallback(interval = 100) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); # Print the timer summary summary_callback() diff --git a/examples/p4est_2d_dgsem/elixir_mhd_alfven_wave.jl b/examples/p4est_2d_dgsem/elixir_mhd_alfven_wave.jl index 66bce781f60..b2b402a25f6 100644 --- a/examples/p4est_2d_dgsem/elixir_mhd_alfven_wave.jl +++ b/examples/p4est_2d_dgsem/elixir_mhd_alfven_wave.jl @@ -2,28 +2,29 @@ using OrdinaryDiffEq using Trixi - ############################################################################### # semidiscretization of the compressible ideal GLM-MHD equations -gamma = 5/3 +gamma = 5 / 3 equations = IdealGlmMhdEquations2D(gamma) initial_condition = initial_condition_convergence_test # Get the DG approximation space volume_flux = (flux_central, flux_nonconservative_powell) -solver = DGSEM(polydeg=4, surface_flux=(flux_hll, flux_nonconservative_powell), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 4, + surface_flux = (flux_hlle, + flux_nonconservative_powell), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) -coordinates_min = (0.0 , 0.0 ) +coordinates_min = (0.0, 0.0) coordinates_max = (sqrt(2.0), sqrt(2.0)) trees_per_dimension = (8, 8) mesh = P4estMesh(trees_per_dimension, - polydeg=3, initial_refinement_level=0, - coordinates_min=coordinates_min, coordinates_max=coordinates_max, - periodicity=true) + polydeg = 3, initial_refinement_level = 0, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -36,14 +37,14 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) cfl = 0.9 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -54,7 +55,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/p4est_2d_dgsem/elixir_mhd_rotor.jl b/examples/p4est_2d_dgsem/elixir_mhd_rotor.jl index 58915a8f6a7..380db487356 100644 --- a/examples/p4est_2d_dgsem/elixir_mhd_rotor.jl +++ b/examples/p4est_2d_dgsem/elixir_mhd_rotor.jl @@ -16,74 +16,74 @@ The classical MHD rotor test case. Here, the setup is taken from [doi: 10.1365/s13291-018-0178-9](https://doi.org/10.1365/s13291-018-0178-9) """ function initial_condition_rotor(x, t, equations::IdealGlmMhdEquations2D) - # setup taken from Derigs et al. DMV article (2018) - # domain must be [0, 1] x [0, 1], γ = 1.4 - dx = x[1] - 0.5 - dy = x[2] - 0.5 - r = sqrt(dx^2 + dy^2) - f = (0.115 - r)/0.015 - if r <= 0.1 - rho = 10.0 - v1 = -20.0*dy - v2 = 20.0*dx - elseif r >= 0.115 - rho = 1.0 - v1 = 0.0 - v2 = 0.0 - else - rho = 1.0 + 9.0*f - v1 = -20.0*f*dy - v2 = 20.0*f*dx - end - v3 = 0.0 - p = 1.0 - B1 = 5.0/sqrt(4.0*pi) - B2 = 0.0 - B3 = 0.0 - psi = 0.0 - return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3, psi), equations) + # setup taken from Derigs et al. DMV article (2018) + # domain must be [0, 1] x [0, 1], γ = 1.4 + dx = x[1] - 0.5 + dy = x[2] - 0.5 + r = sqrt(dx^2 + dy^2) + f = (0.115 - r) / 0.015 + if r <= 0.1 + rho = 10.0 + v1 = -20.0 * dy + v2 = 20.0 * dx + elseif r >= 0.115 + rho = 1.0 + v1 = 0.0 + v2 = 0.0 + else + rho = 1.0 + 9.0 * f + v1 = -20.0 * f * dy + v2 = 20.0 * f * dx + end + v3 = 0.0 + p = 1.0 + B1 = 5.0 / sqrt(4.0 * pi) + B2 = 0.0 + B3 = 0.0 + psi = 0.0 + return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3, psi), equations) end initial_condition = initial_condition_rotor surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell) -volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) +volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) polydeg = 4 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) # Affine type mapping to take the [-1,1]^2 domain from the mesh file # and put it onto the rotor domain [0,1]^2 and then warp it with a mapping # as described in https://arxiv.org/abs/2012.12040 function mapping_twist(xi, eta) - y = 0.5 * (eta + 1.0) + 0.05 * cos(1.5 * pi * (2.0 * xi - 1.0)) * cos(0.5 * pi * (2.0 * eta - 1.0)) - x = 0.5 * (xi + 1.0) + 0.05 * cos(0.5 * pi * (2.0 * xi - 1.0)) * cos(2.0 * pi * y) - return SVector(x, y) + y = 0.5 * (eta + 1.0) + + 0.05 * cos(1.5 * pi * (2.0 * xi - 1.0)) * cos(0.5 * pi * (2.0 * eta - 1.0)) + x = 0.5 * (xi + 1.0) + 0.05 * cos(0.5 * pi * (2.0 * xi - 1.0)) * cos(2.0 * pi * y) + return SVector(x, y) end - mesh_file = joinpath(@__DIR__, "square_unstructured_2.inp") -isfile(mesh_file) || download("https://gist.githubusercontent.com/efaulhaber/63ff2ea224409e55ee8423b3a33e316a/raw/7db58af7446d1479753ae718930741c47a3b79b7/square_unstructured_2.inp", - mesh_file) +isfile(mesh_file) || + download("https://gist.githubusercontent.com/efaulhaber/63ff2ea224409e55ee8423b3a33e316a/raw/7db58af7446d1479753ae718930741c47a3b79b7/square_unstructured_2.inp", + mesh_file) mesh = P4estMesh{2}(mesh_file, - polydeg=4, - mapping=mapping_twist, - initial_refinement_level=1) + polydeg = 4, + mapping = mapping_twist, + initial_refinement_level = 1) boundary_condition = BoundaryConditionDirichlet(initial_condition) -boundary_conditions = Dict( :all => boundary_condition ) +boundary_conditions = Dict(:all => boundary_condition) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -94,31 +94,31 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_indicator = IndicatorLöhner(semi, - variable=density_pressure) + variable = density_pressure) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=1, - med_level =3, med_threshold=0.05, - max_level =5, max_threshold=0.1) + base_level = 1, + med_level = 3, med_threshold = 0.05, + max_level = 5, max_threshold = 0.1) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) cfl = 0.5 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -131,7 +131,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/p4est_2d_dgsem/elixir_navierstokes_convergence.jl b/examples/p4est_2d_dgsem/elixir_navierstokes_convergence.jl index 8111df8251a..54ec09d2be8 100644 --- a/examples/p4est_2d_dgsem/elixir_navierstokes_convergence.jl +++ b/examples/p4est_2d_dgsem/elixir_navierstokes_convergence.jl @@ -8,171 +8,183 @@ prandtl_number() = 0.72 mu() = 0.01 equations = CompressibleEulerEquations2D(1.4) -equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu=mu(), Prandtl=prandtl_number(), - gradient_variables=GradientVariablesPrimitive()) +equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu = mu(), + Prandtl = prandtl_number(), + gradient_variables = GradientVariablesPrimitive()) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralWeakForm()) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralWeakForm()) coordinates_min = (-1.0, -1.0) # minimum coordinates (min(x), min(y)) -coordinates_max = ( 1.0, 1.0) # maximum coordinates (max(x), max(y)) +coordinates_max = (1.0, 1.0) # maximum coordinates (max(x), max(y)) trees_per_dimension = (4, 4) mesh = P4estMesh(trees_per_dimension, - polydeg=3, initial_refinement_level=2, - coordinates_min=coordinates_min, coordinates_max=coordinates_max, - periodicity=(true, false)) + polydeg = 3, initial_refinement_level = 2, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + periodicity = (true, false)) # Note: the initial condition cannot be specialized to `CompressibleNavierStokesDiffusion2D` # since it is called by both the parabolic solver (which passes in `CompressibleNavierStokesDiffusion2D`) # and by the initial condition (which passes in `CompressibleEulerEquations2D`). # This convergence test setup was originally derived by Andrew Winters (@andrewwinters5000) function initial_condition_navier_stokes_convergence_test(x, t, equations) - # Amplitude and shift - A = 0.5 - c = 2.0 + # Amplitude and shift + A = 0.5 + c = 2.0 - # convenience values for trig. functions - pi_x = pi * x[1] - pi_y = pi * x[2] - pi_t = pi * t + # convenience values for trig. functions + pi_x = pi * x[1] + pi_y = pi * x[2] + pi_t = pi * t - rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t) - v1 = sin(pi_x) * log(x[2] + 2.0) * (1.0 - exp(-A * (x[2] - 1.0)) ) * cos(pi_t) - v2 = v1 - p = rho^2 + rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t) + v1 = sin(pi_x) * log(x[2] + 2.0) * (1.0 - exp(-A * (x[2] - 1.0))) * cos(pi_t) + v2 = v1 + p = rho^2 - return prim2cons(SVector(rho, v1, v2, p), equations) + return prim2cons(SVector(rho, v1, v2, p), equations) end @inline function source_terms_navier_stokes_convergence_test(u, x, t, equations) - y = x[2] - - # TODO: parabolic - # we currently need to hardcode these parameters until we fix the "combined equation" issue - # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 - inv_gamma_minus_one = inv(equations.gamma - 1) - Pr = prandtl_number() - mu_ = mu() - - # Same settings as in `initial_condition` - # Amplitude and shift - A = 0.5 - c = 2.0 - - # convenience values for trig. functions - pi_x = pi * x[1] - pi_y = pi * x[2] - pi_t = pi * t - - # compute the manufactured solution and all necessary derivatives - rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t) - rho_t = -pi * A * sin(pi_x) * cos(pi_y) * sin(pi_t) - rho_x = pi * A * cos(pi_x) * cos(pi_y) * cos(pi_t) - rho_y = -pi * A * sin(pi_x) * sin(pi_y) * cos(pi_t) - rho_xx = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t) - rho_yy = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t) - - v1 = sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) - v1_t = -pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * sin(pi_t) - v1_x = pi * cos(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) - v1_y = sin(pi_x) * (A * log(y + 2.0) * exp(-A * (y - 1.0)) + (1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t) - v1_xx = -pi * pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) - v1_xy = pi * cos(pi_x) * (A * log(y + 2.0) * exp(-A * (y - 1.0)) + (1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t) - v1_yy = (sin(pi_x) * ( 2.0 * A * exp(-A * (y - 1.0)) / (y + 2.0) - - A * A * log(y + 2.0) * exp(-A * (y - 1.0)) - - (1.0 - exp(-A * (y - 1.0))) / ((y + 2.0) * (y + 2.0))) * cos(pi_t)) - v2 = v1 - v2_t = v1_t - v2_x = v1_x - v2_y = v1_y - v2_xx = v1_xx - v2_xy = v1_xy - v2_yy = v1_yy - - p = rho * rho - p_t = 2.0 * rho * rho_t - p_x = 2.0 * rho * rho_x - p_y = 2.0 * rho * rho_y - p_xx = 2.0 * rho * rho_xx + 2.0 * rho_x * rho_x - p_yy = 2.0 * rho * rho_yy + 2.0 * rho_y * rho_y - - # Note this simplifies slightly because the ansatz assumes that v1 = v2 - E = p * inv_gamma_minus_one + 0.5 * rho * (v1^2 + v2^2) - E_t = p_t * inv_gamma_minus_one + rho_t * v1^2 + 2.0 * rho * v1 * v1_t - E_x = p_x * inv_gamma_minus_one + rho_x * v1^2 + 2.0 * rho * v1 * v1_x - E_y = p_y * inv_gamma_minus_one + rho_y * v1^2 + 2.0 * rho * v1 * v1_y - - # Some convenience constants - T_const = equations.gamma * inv_gamma_minus_one / Pr - inv_rho_cubed = 1.0 / (rho^3) - - # compute the source terms - # density equation - du1 = rho_t + rho_x * v1 + rho * v1_x + rho_y * v2 + rho * v2_y - - # x-momentum equation - du2 = ( rho_t * v1 + rho * v1_t + p_x + rho_x * v1^2 - + 2.0 * rho * v1 * v1_x - + rho_y * v1 * v2 - + rho * v1_y * v2 - + rho * v1 * v2_y - # stress tensor from x-direction - - 4.0 / 3.0 * v1_xx * mu_ - + 2.0 / 3.0 * v2_xy * mu_ - - v1_yy * mu_ - - v2_xy * mu_ ) - # y-momentum equation - du3 = ( rho_t * v2 + rho * v2_t + p_y + rho_x * v1 * v2 - + rho * v1_x * v2 - + rho * v1 * v2_x - + rho_y * v2^2 - + 2.0 * rho * v2 * v2_y - # stress tensor from y-direction - - v1_xy * mu_ - - v2_xx * mu_ - - 4.0 / 3.0 * v2_yy * mu_ - + 2.0 / 3.0 * v1_xy * mu_ ) - # total energy equation - du4 = ( E_t + v1_x * (E + p) + v1 * (E_x + p_x) - + v2_y * (E + p) + v2 * (E_y + p_y) - # stress tensor and temperature gradient terms from x-direction - - 4.0 / 3.0 * v1_xx * v1 * mu_ - + 2.0 / 3.0 * v2_xy * v1 * mu_ - - 4.0 / 3.0 * v1_x * v1_x * mu_ - + 2.0 / 3.0 * v2_y * v1_x * mu_ - - v1_xy * v2 * mu_ - - v2_xx * v2 * mu_ - - v1_y * v2_x * mu_ - - v2_x * v2_x * mu_ - - T_const * inv_rho_cubed * ( p_xx * rho * rho - - 2.0 * p_x * rho * rho_x - + 2.0 * p * rho_x * rho_x - - p * rho * rho_xx ) * mu_ - # stress tensor and temperature gradient terms from y-direction - - v1_yy * v1 * mu_ - - v2_xy * v1 * mu_ - - v1_y * v1_y * mu_ - - v2_x * v1_y * mu_ - - 4.0 / 3.0 * v2_yy * v2 * mu_ - + 2.0 / 3.0 * v1_xy * v2 * mu_ - - 4.0 / 3.0 * v2_y * v2_y * mu_ - + 2.0 / 3.0 * v1_x * v2_y * mu_ - - T_const * inv_rho_cubed * ( p_yy * rho * rho - - 2.0 * p_y * rho * rho_y - + 2.0 * p * rho_y * rho_y - - p * rho * rho_yy ) * mu_ ) - - return SVector(du1, du2, du3, du4) + y = x[2] + + # TODO: parabolic + # we currently need to hardcode these parameters until we fix the "combined equation" issue + # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 + inv_gamma_minus_one = inv(equations.gamma - 1) + Pr = prandtl_number() + mu_ = mu() + + # Same settings as in `initial_condition` + # Amplitude and shift + A = 0.5 + c = 2.0 + + # convenience values for trig. functions + pi_x = pi * x[1] + pi_y = pi * x[2] + pi_t = pi * t + + # compute the manufactured solution and all necessary derivatives + rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t) + rho_t = -pi * A * sin(pi_x) * cos(pi_y) * sin(pi_t) + rho_x = pi * A * cos(pi_x) * cos(pi_y) * cos(pi_t) + rho_y = -pi * A * sin(pi_x) * sin(pi_y) * cos(pi_t) + rho_xx = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t) + rho_yy = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t) + + v1 = sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) + v1_t = -pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * sin(pi_t) + v1_x = pi * cos(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) + v1_y = sin(pi_x) * + (A * log(y + 2.0) * exp(-A * (y - 1.0)) + + (1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t) + v1_xx = -pi * pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) + v1_xy = pi * cos(pi_x) * + (A * log(y + 2.0) * exp(-A * (y - 1.0)) + + (1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t) + v1_yy = (sin(pi_x) * + (2.0 * A * exp(-A * (y - 1.0)) / (y + 2.0) - + A * A * log(y + 2.0) * exp(-A * (y - 1.0)) - + (1.0 - exp(-A * (y - 1.0))) / ((y + 2.0) * (y + 2.0))) * cos(pi_t)) + v2 = v1 + v2_t = v1_t + v2_x = v1_x + v2_y = v1_y + v2_xx = v1_xx + v2_xy = v1_xy + v2_yy = v1_yy + + p = rho * rho + p_t = 2.0 * rho * rho_t + p_x = 2.0 * rho * rho_x + p_y = 2.0 * rho * rho_y + p_xx = 2.0 * rho * rho_xx + 2.0 * rho_x * rho_x + p_yy = 2.0 * rho * rho_yy + 2.0 * rho_y * rho_y + + # Note this simplifies slightly because the ansatz assumes that v1 = v2 + E = p * inv_gamma_minus_one + 0.5 * rho * (v1^2 + v2^2) + E_t = p_t * inv_gamma_minus_one + rho_t * v1^2 + 2.0 * rho * v1 * v1_t + E_x = p_x * inv_gamma_minus_one + rho_x * v1^2 + 2.0 * rho * v1 * v1_x + E_y = p_y * inv_gamma_minus_one + rho_y * v1^2 + 2.0 * rho * v1 * v1_y + + # Some convenience constants + T_const = equations.gamma * inv_gamma_minus_one / Pr + inv_rho_cubed = 1.0 / (rho^3) + + # compute the source terms + # density equation + du1 = rho_t + rho_x * v1 + rho * v1_x + rho_y * v2 + rho * v2_y + + # x-momentum equation + du2 = (rho_t * v1 + rho * v1_t + p_x + rho_x * v1^2 + + 2.0 * rho * v1 * v1_x + + rho_y * v1 * v2 + + rho * v1_y * v2 + + rho * v1 * v2_y - + # stress tensor from x-direction + 4.0 / 3.0 * v1_xx * mu_ + + 2.0 / 3.0 * v2_xy * mu_ - + v1_yy * mu_ - + v2_xy * mu_) + # y-momentum equation + du3 = (rho_t * v2 + rho * v2_t + p_y + rho_x * v1 * v2 + + rho * v1_x * v2 + + rho * v1 * v2_x + + rho_y * v2^2 + + 2.0 * rho * v2 * v2_y - + # stress tensor from y-direction + v1_xy * mu_ - + v2_xx * mu_ - + 4.0 / 3.0 * v2_yy * mu_ + + 2.0 / 3.0 * v1_xy * mu_) + # total energy equation + du4 = (E_t + v1_x * (E + p) + v1 * (E_x + p_x) + + v2_y * (E + p) + v2 * (E_y + p_y) - + # stress tensor and temperature gradient terms from x-direction + 4.0 / 3.0 * v1_xx * v1 * mu_ + + 2.0 / 3.0 * v2_xy * v1 * mu_ - + 4.0 / 3.0 * v1_x * v1_x * mu_ + + 2.0 / 3.0 * v2_y * v1_x * mu_ - + v1_xy * v2 * mu_ - + v2_xx * v2 * mu_ - + v1_y * v2_x * mu_ - + v2_x * v2_x * mu_ - + T_const * inv_rho_cubed * + (p_xx * rho * rho - + 2.0 * p_x * rho * rho_x + + 2.0 * p * rho_x * rho_x - + p * rho * rho_xx) * mu_ - + # stress tensor and temperature gradient terms from y-direction + v1_yy * v1 * mu_ - + v2_xy * v1 * mu_ - + v1_y * v1_y * mu_ - + v2_x * v1_y * mu_ - + 4.0 / 3.0 * v2_yy * v2 * mu_ + + 2.0 / 3.0 * v1_xy * v2 * mu_ - + 4.0 / 3.0 * v2_y * v2_y * mu_ + + 2.0 / 3.0 * v1_x * v2_y * mu_ - + T_const * inv_rho_cubed * + (p_yy * rho * rho - + 2.0 * p_y * rho * rho_y + + 2.0 * p * rho_y * rho_y - + p * rho * rho_yy) * mu_) + + return SVector(du1, du2, du3, du4) end initial_condition = initial_condition_navier_stokes_convergence_test # BC types -velocity_bc_top_bottom = NoSlip((x, t, equations) -> initial_condition_navier_stokes_convergence_test(x, t, equations)[2:3]) +velocity_bc_top_bottom = NoSlip() do x, t, equations + u = initial_condition_navier_stokes_convergence_test(x, t, equations) + return SVector(u[2], u[3]) +end heat_bc_top_bottom = Adiabatic((x, t, equations) -> 0.0) -boundary_condition_top_bottom = BoundaryConditionNavierStokesWall(velocity_bc_top_bottom, heat_bc_top_bottom) +boundary_condition_top_bottom = BoundaryConditionNavierStokesWall(velocity_bc_top_bottom, + heat_bc_top_bottom) # define inviscid boundary conditions boundary_conditions = Dict(:y_neg => boundary_condition_slip_wall, @@ -182,9 +194,11 @@ boundary_conditions = Dict(:y_neg => boundary_condition_slip_wall, boundary_conditions_parabolic = Dict(:y_neg => boundary_condition_top_bottom, :y_pos => boundary_condition_top_bottom) -semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver; - boundary_conditions=(boundary_conditions, boundary_conditions_parabolic), - source_terms=source_terms_navier_stokes_convergence_test) +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, solver; + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic), + source_terms = source_terms_navier_stokes_convergence_test) # ############################################################################### # # ODE solvers, callbacks etc. @@ -194,16 +208,15 @@ tspan = (0.0, 0.5) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) ############################################################################### # run the simulation time_int_tol = 1e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, dt = 1e-5, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, dt = 1e-5, + ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary - diff --git a/examples/p4est_2d_dgsem/elixir_navierstokes_convergence_nonperiodic.jl b/examples/p4est_2d_dgsem/elixir_navierstokes_convergence_nonperiodic.jl new file mode 100644 index 00000000000..b4177fe8538 --- /dev/null +++ b/examples/p4est_2d_dgsem/elixir_navierstokes_convergence_nonperiodic.jl @@ -0,0 +1,227 @@ +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the ideal compressible Navier-Stokes equations + +prandtl_number() = 0.72 +mu() = 0.01 + +equations = CompressibleEulerEquations2D(1.4) +equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu = mu(), + Prandtl = prandtl_number(), + gradient_variables = GradientVariablesPrimitive()) + +# Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralWeakForm()) + +coordinates_min = (-1.0, -1.0) # minimum coordinates (min(x), min(y)) +coordinates_max = (1.0, 1.0) # maximum coordinates (max(x), max(y)) + +trees_per_dimension = (4, 4) +mesh = P4estMesh(trees_per_dimension, + polydeg = 3, initial_refinement_level = 2, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + periodicity = (false, false)) + +# Note: the initial condition cannot be specialized to `CompressibleNavierStokesDiffusion2D` +# since it is called by both the parabolic solver (which passes in `CompressibleNavierStokesDiffusion2D`) +# and by the initial condition (which passes in `CompressibleEulerEquations2D`). +# This convergence test setup was originally derived by Andrew Winters (@andrewwinters5000) +function initial_condition_navier_stokes_convergence_test(x, t, equations) + # Amplitude and shift + A = 0.5 + c = 2.0 + + # convenience values for trig. functions + pi_x = pi * x[1] + pi_y = pi * x[2] + pi_t = pi * t + + rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t) + v1 = sin(pi_x) * log(x[2] + 2.0) * (1.0 - exp(-A * (x[2] - 1.0))) * cos(pi_t) + v2 = v1 + p = rho^2 + + return prim2cons(SVector(rho, v1, v2, p), equations) +end + +@inline function source_terms_navier_stokes_convergence_test(u, x, t, equations) + y = x[2] + + # TODO: parabolic + # we currently need to hardcode these parameters until we fix the "combined equation" issue + # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 + inv_gamma_minus_one = inv(equations.gamma - 1) + Pr = prandtl_number() + mu_ = mu() + + # Same settings as in `initial_condition` + # Amplitude and shift + A = 0.5 + c = 2.0 + + # convenience values for trig. functions + pi_x = pi * x[1] + pi_y = pi * x[2] + pi_t = pi * t + + # compute the manufactured solution and all necessary derivatives + rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t) + rho_t = -pi * A * sin(pi_x) * cos(pi_y) * sin(pi_t) + rho_x = pi * A * cos(pi_x) * cos(pi_y) * cos(pi_t) + rho_y = -pi * A * sin(pi_x) * sin(pi_y) * cos(pi_t) + rho_xx = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t) + rho_yy = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t) + + v1 = sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) + v1_t = -pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * sin(pi_t) + v1_x = pi * cos(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) + v1_y = sin(pi_x) * + (A * log(y + 2.0) * exp(-A * (y - 1.0)) + + (1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t) + v1_xx = -pi * pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) + v1_xy = pi * cos(pi_x) * + (A * log(y + 2.0) * exp(-A * (y - 1.0)) + + (1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t) + v1_yy = (sin(pi_x) * + (2.0 * A * exp(-A * (y - 1.0)) / (y + 2.0) - + A * A * log(y + 2.0) * exp(-A * (y - 1.0)) - + (1.0 - exp(-A * (y - 1.0))) / ((y + 2.0) * (y + 2.0))) * cos(pi_t)) + v2 = v1 + v2_t = v1_t + v2_x = v1_x + v2_y = v1_y + v2_xx = v1_xx + v2_xy = v1_xy + v2_yy = v1_yy + + p = rho * rho + p_t = 2.0 * rho * rho_t + p_x = 2.0 * rho * rho_x + p_y = 2.0 * rho * rho_y + p_xx = 2.0 * rho * rho_xx + 2.0 * rho_x * rho_x + p_yy = 2.0 * rho * rho_yy + 2.0 * rho_y * rho_y + + # Note this simplifies slightly because the ansatz assumes that v1 = v2 + E = p * inv_gamma_minus_one + 0.5 * rho * (v1^2 + v2^2) + E_t = p_t * inv_gamma_minus_one + rho_t * v1^2 + 2.0 * rho * v1 * v1_t + E_x = p_x * inv_gamma_minus_one + rho_x * v1^2 + 2.0 * rho * v1 * v1_x + E_y = p_y * inv_gamma_minus_one + rho_y * v1^2 + 2.0 * rho * v1 * v1_y + + # Some convenience constants + T_const = equations.gamma * inv_gamma_minus_one / Pr + inv_rho_cubed = 1.0 / (rho^3) + + # compute the source terms + # density equation + du1 = rho_t + rho_x * v1 + rho * v1_x + rho_y * v2 + rho * v2_y + + # x-momentum equation + du2 = (rho_t * v1 + rho * v1_t + p_x + rho_x * v1^2 + + 2.0 * rho * v1 * v1_x + + rho_y * v1 * v2 + + rho * v1_y * v2 + + rho * v1 * v2_y - + # stress tensor from x-direction + 4.0 / 3.0 * v1_xx * mu_ + + 2.0 / 3.0 * v2_xy * mu_ - + v1_yy * mu_ - + v2_xy * mu_) + # y-momentum equation + du3 = (rho_t * v2 + rho * v2_t + p_y + rho_x * v1 * v2 + + rho * v1_x * v2 + + rho * v1 * v2_x + + rho_y * v2^2 + + 2.0 * rho * v2 * v2_y - + # stress tensor from y-direction + v1_xy * mu_ - + v2_xx * mu_ - + 4.0 / 3.0 * v2_yy * mu_ + + 2.0 / 3.0 * v1_xy * mu_) + # total energy equation + du4 = (E_t + v1_x * (E + p) + v1 * (E_x + p_x) + + v2_y * (E + p) + v2 * (E_y + p_y) - + # stress tensor and temperature gradient terms from x-direction + 4.0 / 3.0 * v1_xx * v1 * mu_ + + 2.0 / 3.0 * v2_xy * v1 * mu_ - + 4.0 / 3.0 * v1_x * v1_x * mu_ + + 2.0 / 3.0 * v2_y * v1_x * mu_ - + v1_xy * v2 * mu_ - + v2_xx * v2 * mu_ - + v1_y * v2_x * mu_ - + v2_x * v2_x * mu_ - + T_const * inv_rho_cubed * + (p_xx * rho * rho - + 2.0 * p_x * rho * rho_x + + 2.0 * p * rho_x * rho_x - + p * rho * rho_xx) * mu_ - + # stress tensor and temperature gradient terms from y-direction + v1_yy * v1 * mu_ - + v2_xy * v1 * mu_ - + v1_y * v1_y * mu_ - + v2_x * v1_y * mu_ - + 4.0 / 3.0 * v2_yy * v2 * mu_ + + 2.0 / 3.0 * v1_xy * v2 * mu_ - + 4.0 / 3.0 * v2_y * v2_y * mu_ + + 2.0 / 3.0 * v1_x * v2_y * mu_ - + T_const * inv_rho_cubed * + (p_yy * rho * rho - + 2.0 * p_y * rho * rho_y + + 2.0 * p * rho_y * rho_y - + p * rho * rho_yy) * mu_) + + return SVector(du1, du2, du3, du4) +end + +initial_condition = initial_condition_navier_stokes_convergence_test + +# BC types +velocity_bc_top_bottom = NoSlip((x, t, equations) -> initial_condition_navier_stokes_convergence_test(x, + t, + equations)[2:3]) +heat_bc_top_bottom = Adiabatic((x, t, equations) -> 0.0) +boundary_condition_top_bottom = BoundaryConditionNavierStokesWall(velocity_bc_top_bottom, + heat_bc_top_bottom) + +boundary_condition_left_right = BoundaryConditionDirichlet(initial_condition_navier_stokes_convergence_test) + +# define inviscid boundary conditions +boundary_conditions = Dict(:x_neg => boundary_condition_left_right, + :x_pos => boundary_condition_left_right, + :y_neg => boundary_condition_slip_wall, + :y_pos => boundary_condition_slip_wall) + +# define viscous boundary conditions +boundary_conditions_parabolic = Dict(:x_neg => boundary_condition_left_right, + :x_pos => boundary_condition_left_right, + :y_neg => boundary_condition_top_bottom, + :y_pos => boundary_condition_top_bottom) + +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, solver; + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic), + source_terms = source_terms_navier_stokes_convergence_test) + +# ############################################################################### +# # ODE solvers, callbacks etc. + +# Create ODE problem with time span `tspan` +tspan = (0.0, 0.5) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() +alive_callback = AliveCallback(alive_interval = 10) +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) +callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) + +############################################################################### +# run the simulation + +time_int_tol = 1e-8 +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, dt = 1e-5, + ode_default_options()..., callback = callbacks) +summary_callback() # print the timer summary diff --git a/examples/p4est_2d_dgsem/elixir_navierstokes_lid_driven_cavity.jl b/examples/p4est_2d_dgsem/elixir_navierstokes_lid_driven_cavity.jl index 051f4defe54..bc28ae6ffb3 100644 --- a/examples/p4est_2d_dgsem/elixir_navierstokes_lid_driven_cavity.jl +++ b/examples/p4est_2d_dgsem/elixir_navierstokes_lid_driven_cavity.jl @@ -9,28 +9,28 @@ prandtl_number() = 0.72 mu() = 0.001 equations = CompressibleEulerEquations2D(1.4) -equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu=mu(), - Prandtl=prandtl_number()) +equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu = mu(), + Prandtl = prandtl_number()) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-1.0, -1.0) # minimum coordinates (min(x), min(y)) -coordinates_max = ( 1.0, 1.0) # maximum coordinates (max(x), max(y)) +coordinates_max = (1.0, 1.0) # maximum coordinates (max(x), max(y)) # Create a uniformly refined mesh trees_per_dimension = (4, 4) mesh = P4estMesh(trees_per_dimension, - polydeg=3, initial_refinement_level=2, - coordinates_min=coordinates_min, coordinates_max=coordinates_max, - periodicity=(false, false)) + polydeg = 3, initial_refinement_level = 2, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + periodicity = (false, false)) function initial_condition_cavity(x, t, equations::CompressibleEulerEquations2D) - Ma = 0.1 - rho = 1.0 - u, v = 0.0, 0.0 - p = 1.0 / (Ma^2 * equations.gamma) - return prim2cons(SVector(rho, u, v, p), equations) + Ma = 0.1 + rho = 1.0 + u, v = 0.0, 0.0 + p = 1.0 / (Ma^2 * equations.gamma) + return prim2cons(SVector(rho, u, v, p), equations) end initial_condition = initial_condition_cavity @@ -41,22 +41,21 @@ heat_bc = Adiabatic((x, t, equations) -> 0.0) boundary_condition_lid = BoundaryConditionNavierStokesWall(velocity_bc_lid, heat_bc) boundary_condition_cavity = BoundaryConditionNavierStokesWall(velocity_bc_cavity, heat_bc) -# define periodic boundary conditions everywhere -boundary_conditions = Dict( :x_neg => boundary_condition_slip_wall, - :y_neg => boundary_condition_slip_wall, - :y_pos => boundary_condition_slip_wall, - :x_pos => boundary_condition_slip_wall) +boundary_conditions = Dict(:x_neg => boundary_condition_slip_wall, + :y_neg => boundary_condition_slip_wall, + :y_pos => boundary_condition_slip_wall, + :x_pos => boundary_condition_slip_wall) -boundary_conditions_parabolic = Dict( :x_neg => boundary_condition_cavity, - :y_neg => boundary_condition_cavity, - :y_pos => boundary_condition_lid, - :x_pos => boundary_condition_cavity) +boundary_conditions_parabolic = Dict(:x_neg => boundary_condition_cavity, + :y_neg => boundary_condition_cavity, + :y_pos => boundary_condition_lid, + :x_pos => boundary_condition_cavity) # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver; - boundary_conditions=(boundary_conditions, - boundary_conditions_parabolic)) + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic)) ############################################################################### # ODE solvers, callbacks etc. @@ -66,17 +65,15 @@ tspan = (0.0, 25.0) ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=100) +alive_callback = AliveCallback(alive_interval = 100) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) callbacks = CallbackSet(summary_callback, alive_callback) ############################################################################### # run the simulation time_int_tol = 1e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary - - diff --git a/examples/p4est_2d_dgsem/elixir_navierstokes_lid_driven_cavity_amr.jl b/examples/p4est_2d_dgsem/elixir_navierstokes_lid_driven_cavity_amr.jl new file mode 100644 index 00000000000..898366969a4 --- /dev/null +++ b/examples/p4est_2d_dgsem/elixir_navierstokes_lid_driven_cavity_amr.jl @@ -0,0 +1,94 @@ +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the ideal compressible Navier-Stokes equations + +# TODO: parabolic; unify names of these accessor functions +prandtl_number() = 0.72 +mu() = 0.001 + +equations = CompressibleEulerEquations2D(1.4) +equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu = mu(), + Prandtl = prandtl_number()) + +# Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) + +coordinates_min = (-1.0, -1.0) # minimum coordinates (min(x), min(y)) +coordinates_max = (1.0, 1.0) # maximum coordinates (max(x), max(y)) + +# Create a uniformly refined mesh +trees_per_dimension = (6, 6) +mesh = P4estMesh(trees_per_dimension, + polydeg = 3, initial_refinement_level = 2, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + periodicity = (false, false)) + +function initial_condition_cavity(x, t, equations::CompressibleEulerEquations2D) + Ma = 0.1 + rho = 1.0 + u, v = 0.0, 0.0 + p = 1.0 / (Ma^2 * equations.gamma) + return prim2cons(SVector(rho, u, v, p), equations) +end +initial_condition = initial_condition_cavity + +# BC types +velocity_bc_lid = NoSlip((x, t, equations) -> SVector(1.0, 0.0)) +velocity_bc_cavity = NoSlip((x, t, equations) -> SVector(0.0, 0.0)) +heat_bc = Adiabatic((x, t, equations) -> 0.0) +boundary_condition_lid = BoundaryConditionNavierStokesWall(velocity_bc_lid, heat_bc) +boundary_condition_cavity = BoundaryConditionNavierStokesWall(velocity_bc_cavity, heat_bc) + +boundary_conditions = Dict(:x_neg => boundary_condition_slip_wall, + :y_neg => boundary_condition_slip_wall, + :y_pos => boundary_condition_slip_wall, + :x_pos => boundary_condition_slip_wall) + +boundary_conditions_parabolic = Dict(:x_neg => boundary_condition_cavity, + :y_neg => boundary_condition_cavity, + :y_pos => boundary_condition_lid, + :x_pos => boundary_condition_cavity) + +# A semidiscretization collects data structures and functions for the spatial discretization +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, solver; + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic)) + +############################################################################### +# ODE solvers, callbacks etc. + +# Create ODE problem with time span `tspan` +tspan = (0.0, 25.0) +ode = semidiscretize(semi, tspan); + +summary_callback = SummaryCallback() +alive_callback = AliveCallback(alive_interval = 2000) +analysis_interval = 2000 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + +amr_indicator = IndicatorLöhner(semi, variable = Trixi.density) + +amr_controller = ControllerThreeLevel(semi, amr_indicator, + base_level = 0, + med_level = 1, med_threshold = 0.005, + max_level = 2, max_threshold = 0.01) + +amr_callback = AMRCallback(semi, amr_controller, + interval = 50, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) + +callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback, amr_callback) +# callbacks = CallbackSet(summary_callback, alive_callback) + +############################################################################### +# run the simulation + +time_int_tol = 1e-8 +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) + +summary_callback() # print the timer summary diff --git a/examples/p4est_2d_dgsem/elixir_shallowwater_source_terms.jl b/examples/p4est_2d_dgsem/elixir_shallowwater_source_terms.jl index b185a8ce39d..c7922fd3b75 100644 --- a/examples/p4est_2d_dgsem/elixir_shallowwater_source_terms.jl +++ b/examples/p4est_2d_dgsem/elixir_shallowwater_source_terms.jl @@ -5,17 +5,17 @@ using Trixi ############################################################################### # semidiscretization of the shallow water equations -equations = ShallowWaterEquations2D(gravity_constant=9.81) +equations = ShallowWaterEquations2D(gravity_constant = 9.81) initial_condition = initial_condition_convergence_test # MMS EOC test - ############################################################################### # Get the DG approximation space volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -solver = DGSEM(polydeg=3, surface_flux=(flux_lax_friedrichs, flux_nonconservative_fjordholm_etal), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, + surface_flux = (flux_lax_friedrichs, flux_nonconservative_fjordholm_etal), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### # Get the P4estMesh and setup a periodic mesh @@ -25,14 +25,13 @@ coordinates_max = (sqrt(2.0), sqrt(2.0)) # maximum coordinates (max(x), max(y)) # Create P4estMesh with 8 x 8 trees and 16 x 16 elements trees_per_dimension = (8, 8) -mesh = P4estMesh(trees_per_dimension, polydeg=3, - coordinates_min=coordinates_min, coordinates_max=coordinates_max, - initial_refinement_level=1) +mesh = P4estMesh(trees_per_dimension, polydeg = 3, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + initial_refinement_level = 1) # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -44,13 +43,13 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 500 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=200, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 200, + save_initial_solution = true, + save_final_solution = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) @@ -58,6 +57,6 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav # run the simulation # use a Runge-Kutta method with automatic (error based) time step size control -sol = solve(ode, RDPK3SpFSAL49(); abstol=1.0e-8, reltol=1.0e-8, - ode_default_options()..., callback=callbacks); +sol = solve(ode, RDPK3SpFSAL49(); abstol = 1.0e-8, reltol = 1.0e-8, + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/p4est_3d_dgsem/elixir_advection_amr.jl b/examples/p4est_3d_dgsem/elixir_advection_amr.jl index 0473fd2b23a..d56ecc233ff 100644 --- a/examples/p4est_3d_dgsem/elixir_advection_amr.jl +++ b/examples/p4est_3d_dgsem/elixir_advection_amr.jl @@ -11,23 +11,21 @@ advection_velocity = (0.2, -0.7, 0.5) equations = LinearScalarAdvectionEquation3D(advection_velocity) initial_condition = initial_condition_gauss -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-5.0, -5.0, -5.0) -coordinates_max = ( 5.0, 5.0, 5.0) +coordinates_max = (5.0, 5.0, 5.0) trees_per_dimension = (1, 1, 1) # Note that it is not necessary to use mesh polydeg lower than the solver polydeg # on a Cartesian mesh. # See https://doi.org/10.1007/s10915-018-00897-9, Section 6. -mesh = P4estMesh(trees_per_dimension, polydeg=1, - coordinates_min=coordinates_min, coordinates_max=coordinates_max, - initial_refinement_level=4) - +mesh = P4estMesh(trees_per_dimension, polydeg = 1, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + initial_refinement_level = 4) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -37,26 +35,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable=first), - base_level=4, - med_level=5, med_threshold=0.1, - max_level=6, max_threshold=0.6) +amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable = first), + base_level = 4, + med_level = 5, med_threshold = 0.1, + max_level = 6, max_threshold = 0.6) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=1.2) +stepsize_callback = StepsizeCallback(cfl = 1.2) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -68,7 +66,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/p4est_3d_dgsem/elixir_advection_amr_unstructured_curved.jl b/examples/p4est_3d_dgsem/elixir_advection_amr_unstructured_curved.jl index fb87c361c18..cd280cf5bf6 100644 --- a/examples/p4est_3d_dgsem/elixir_advection_amr_unstructured_curved.jl +++ b/examples/p4est_3d_dgsem/elixir_advection_amr_unstructured_curved.jl @@ -12,54 +12,55 @@ equations = LinearScalarAdvectionEquation3D(advection_velocity) # Solver with polydeg=4 to ensure free stream preservation (FSP) on non-conforming meshes. # The polydeg of the solver must be at least twice as big as the polydeg of the mesh. # See https://doi.org/10.1007/s10915-018-00897-9, Section 6. -solver = DGSEM(polydeg=4, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 4, surface_flux = flux_lax_friedrichs) initial_condition = initial_condition_gauss boundary_condition = BoundaryConditionDirichlet(initial_condition) -boundary_conditions = Dict( - :all => boundary_condition -) +boundary_conditions = Dict(:all => boundary_condition) # Mapping as described in https://arxiv.org/abs/2012.12040 but with less warping. # The mapping will be interpolated at tree level, and then refined without changing # the geometry interpolant. The original mapping applied to this unstructured mesh # causes some Jacobians to be negative, which makes the mesh invalid. function mapping(xi, eta, zeta) - # Don't transform input variables between -1 and 1 onto [0,3] to obtain curved boundaries - # xi = 1.5 * xi_ + 1.5 - # eta = 1.5 * eta_ + 1.5 - # zeta = 1.5 * zeta_ + 1.5 - - y = eta + 1/4 * (cos(1.5 * pi * (2 * xi - 3)/3) * - cos(0.5 * pi * (2 * eta - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - x = xi + 1/4 * (cos(0.5 * pi * (2 * xi - 3)/3) * - cos(2 * pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - z = zeta + 1/4 * (cos(0.5 * pi * (2 * x - 3)/3) * - cos(pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - # Transform the weird deformed cube to be approximately the size of [-5,5]^3 to match IC - return SVector(5 * x, 5 * y, 5 * z) + # Don't transform input variables between -1 and 1 onto [0,3] to obtain curved boundaries + # xi = 1.5 * xi_ + 1.5 + # eta = 1.5 * eta_ + 1.5 + # zeta = 1.5 * zeta_ + 1.5 + + y = eta + + 1 / 4 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + x = xi + + 1 / 4 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + z = zeta + + 1 / 4 * (cos(0.5 * pi * (2 * x - 3) / 3) * + cos(pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + # Transform the weird deformed cube to be approximately the size of [-5,5]^3 to match IC + return SVector(5 * x, 5 * y, 5 * z) end # Unstructured mesh with 48 cells of the cube domain [-1, 1]^3 mesh_file = joinpath(@__DIR__, "cube_unstructured_2.inp") -isfile(mesh_file) || download("https://gist.githubusercontent.com/efaulhaber/b8df0033798e4926dec515fc045e8c2c/raw/b9254cde1d1fb64b6acc8416bc5ccdd77a240227/cube_unstructured_2.inp", - mesh_file) +isfile(mesh_file) || + download("https://gist.githubusercontent.com/efaulhaber/b8df0033798e4926dec515fc045e8c2c/raw/b9254cde1d1fb64b6acc8416bc5ccdd77a240227/cube_unstructured_2.inp", + mesh_file) # Mesh polydeg of 2 (half the solver polydeg) to ensure FSP (see above). -mesh = P4estMesh{3}(mesh_file, polydeg=2, - mapping=mapping, - initial_refinement_level=1) - - -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, boundary_conditions=boundary_conditions) +mesh = P4estMesh{3}(mesh_file, polydeg = 2, + mapping = mapping, + initial_refinement_level = 1) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -70,29 +71,29 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable=first), - base_level=1, - med_level=2, med_threshold=0.1, - max_level=3, max_threshold=0.6) +amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable = first), + base_level = 1, + med_level = 2, med_threshold = 0.1, + max_level = 3, max_threshold = 0.6) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=1.2) +stepsize_callback = StepsizeCallback(cfl = 1.2) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -105,7 +106,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/p4est_3d_dgsem/elixir_advection_basic.jl b/examples/p4est_3d_dgsem/elixir_advection_basic.jl index a165d1ff132..02ffa5c7aff 100644 --- a/examples/p4est_3d_dgsem/elixir_advection_basic.jl +++ b/examples/p4est_3d_dgsem/elixir_advection_basic.jl @@ -11,19 +11,20 @@ advection_velocity = (0.2, -0.7, 0.5) equations = LinearScalarAdvectionEquation3D(advection_velocity) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-1.0, -1.0, -1.0) # minimum coordinates (min(x), min(y), min(z)) -coordinates_max = ( 1.0, 1.0, 1.0) # maximum coordinates (max(x), max(y), max(z)) +coordinates_max = (1.0, 1.0, 1.0) # maximum coordinates (max(x), max(y), max(z)) # Create P4estMesh with 8 x 8 x 8 elements (note `refinement_level=1`) trees_per_dimension = (4, 4, 4) -mesh = P4estMesh(trees_per_dimension, polydeg=3, - coordinates_min=coordinates_min, coordinates_max=coordinates_max, - initial_refinement_level=1) +mesh = P4estMesh(trees_per_dimension, polydeg = 3, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + initial_refinement_level = 1) # A semidiscretization collects data structures and functions for the spatial discretization -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, solver) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, + solver) ############################################################################### # ODE solvers, callbacks etc. @@ -37,30 +38,30 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveRestartCallback allows to save a file from which a Trixi.jl simulation can be restarted -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.2) +stepsize_callback = StepsizeCallback(cfl = 1.2) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_restart, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_restart, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); # Print the timer summary summary_callback() diff --git a/examples/p4est_3d_dgsem/elixir_advection_cubed_sphere.jl b/examples/p4est_3d_dgsem/elixir_advection_cubed_sphere.jl index 07a8b36bb4c..cd641ca4af7 100644 --- a/examples/p4est_3d_dgsem/elixir_advection_cubed_sphere.jl +++ b/examples/p4est_3d_dgsem/elixir_advection_cubed_sphere.jl @@ -9,21 +9,20 @@ advection_velocity = (0.2, -0.7, 0.5) equations = LinearScalarAdvectionEquation3D(advection_velocity) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) initial_condition = initial_condition_convergence_test boundary_condition = BoundaryConditionDirichlet(initial_condition) -boundary_conditions = Dict( - :inside => boundary_condition, - :outside => boundary_condition, -) +boundary_conditions = Dict(:inside => boundary_condition, + :outside => boundary_condition) mesh = Trixi.P4estMeshCubedSphere(5, 3, 0.5, 0.5, - polydeg=3, initial_refinement_level=0) + polydeg = 3, initial_refinement_level = 0) # A semidiscretization collects data structures and functions for the spatial discretization -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, boundary_conditions=boundary_conditions) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -37,26 +36,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.2) +stepsize_callback = StepsizeCallback(cfl = 1.2) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); # Print the timer summary summary_callback() diff --git a/examples/p4est_3d_dgsem/elixir_advection_nonconforming.jl b/examples/p4est_3d_dgsem/elixir_advection_nonconforming.jl index 93ff17c7842..34b0e95834d 100644 --- a/examples/p4est_3d_dgsem/elixir_advection_nonconforming.jl +++ b/examples/p4est_3d_dgsem/elixir_advection_nonconforming.jl @@ -2,7 +2,6 @@ using OrdinaryDiffEq using Trixi - ############################################################################### # semidiscretization of the linear advection equation @@ -10,39 +9,42 @@ advection_velocity = (0.2, -0.7, 0.5) equations = LinearScalarAdvectionEquation3D(advection_velocity) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-1.0, -1.0, -1.0) # minimum coordinates (min(x), min(y), min(z)) -coordinates_max = ( 1.0, 1.0, 1.0) # maximum coordinates (max(x), max(y), max(z)) +coordinates_max = (1.0, 1.0, 1.0) # maximum coordinates (max(x), max(y), max(z)) trees_per_dimension = (1, 1, 1) # Note that it is not necessary to use mesh polydeg lower than the solver polydeg # on a Cartesian mesh. # See https://doi.org/10.1007/s10915-018-00897-9, Section 6. -mesh = P4estMesh(trees_per_dimension, polydeg=3, - coordinates_min=coordinates_min, coordinates_max=coordinates_max, - initial_refinement_level=2) +mesh = P4estMesh(trees_per_dimension, polydeg = 3, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + initial_refinement_level = 2) # Refine bottom left quadrant of each tree to level 3 function refine_fn(p8est, which_tree, quadrant) - quadrant_obj = unsafe_load(quadrant) - if quadrant_obj.x == 0 && quadrant_obj.y == 0 && quadrant_obj.z == 0 && quadrant_obj.level < 3 - # return true (refine) - return Cint(1) - else - # return false (don't refine) - return Cint(0) - end + quadrant_obj = unsafe_load(quadrant) + if quadrant_obj.x == 0 && quadrant_obj.y == 0 && quadrant_obj.z == 0 && + quadrant_obj.level < 3 + # return true (refine) + return Cint(1) + else + # return false (don't refine) + return Cint(0) + end end # Refine recursively until each bottom left quadrant of a tree has level 3 # The mesh will be rebalanced before the simulation starts -refine_fn_c = @cfunction(refine_fn, Cint, (Ptr{Trixi.p8est_t}, Ptr{Trixi.p4est_topidx_t}, Ptr{Trixi.p8est_quadrant_t})) +refine_fn_c = @cfunction(refine_fn, Cint, + (Ptr{Trixi.p8est_t}, Ptr{Trixi.p4est_topidx_t}, + Ptr{Trixi.p8est_quadrant_t})) Trixi.refine_p4est!(mesh.p4est, true, refine_fn_c, C_NULL) # A semidiscretization collects data structures and functions for the spatial discretization -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, solver) - +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, + solver) ############################################################################### # ODE solvers, callbacks etc. @@ -56,26 +58,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); # Print the timer summary summary_callback() diff --git a/examples/p4est_3d_dgsem/elixir_advection_restart.jl b/examples/p4est_3d_dgsem/elixir_advection_restart.jl index b27eaab62e2..b3dead42399 100644 --- a/examples/p4est_3d_dgsem/elixir_advection_restart.jl +++ b/examples/p4est_3d_dgsem/elixir_advection_restart.jl @@ -6,8 +6,7 @@ using Trixi # create a restart file trixi_include(@__MODULE__, joinpath(@__DIR__, "elixir_advection_basic.jl"), - trees_per_dimension=(2, 2, 2)) - + trees_per_dimension = (2, 2, 2)) ############################################################################### # adapt the parameters that have changed compared to "elixir_advection_extended.jl" @@ -18,7 +17,8 @@ trixi_include(@__MODULE__, joinpath(@__DIR__, "elixir_advection_basic.jl"), restart_filename = joinpath("out", "restart_000010.h5") mesh = load_mesh(restart_filename) -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, solver) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, + solver) tspan = (load_time(restart_filename), 2.0) dt = load_dt(restart_filename) @@ -27,14 +27,12 @@ ode = semidiscretize(semi, tspan, restart_filename); # Do not overwrite the initial snapshot written by elixir_advection_extended.jl. save_solution.condition.save_initial_solution = false -integrator = init(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=dt, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +integrator = init(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = dt, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks, maxiters = 100_000); # Get the last time index and work with that. -integrator.iter = load_timestep(restart_filename) -integrator.stats.naccept = integrator.iter - +load_timestep!(integrator, restart_filename) ############################################################################### # run the simulation diff --git a/examples/p4est_3d_dgsem/elixir_advection_unstructured_curved.jl b/examples/p4est_3d_dgsem/elixir_advection_unstructured_curved.jl index 85fd0b9a2cf..6df9ac0b16a 100644 --- a/examples/p4est_3d_dgsem/elixir_advection_unstructured_curved.jl +++ b/examples/p4est_3d_dgsem/elixir_advection_unstructured_curved.jl @@ -10,51 +10,54 @@ advection_velocity = (0.2, -0.7, 0.5) equations = LinearScalarAdvectionEquation3D(advection_velocity) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) initial_condition = initial_condition_convergence_test boundary_condition = BoundaryConditionDirichlet(initial_condition) -boundary_conditions = Dict( - :all => boundary_condition -) +boundary_conditions = Dict(:all => boundary_condition) # Mapping as described in https://arxiv.org/abs/2012.12040 but with less warping. # The mapping will be interpolated at tree level, and then refined without changing # the geometry interpolant. The original mapping applied to this unstructured mesh # causes some Jacobians to be negative, which makes the mesh invalid. function mapping(xi, eta, zeta) - # Don't transform input variables between -1 and 1 onto [0,3] to obtain curved boundaries - # xi = 1.5 * xi_ + 1.5 - # eta = 1.5 * eta_ + 1.5 - # zeta = 1.5 * zeta_ + 1.5 - - y = eta + 1/6 * (cos(1.5 * pi * (2 * xi - 3)/3) * - cos(0.5 * pi * (2 * eta - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - x = xi + 1/6 * (cos(0.5 * pi * (2 * xi - 3)/3) * - cos(2 * pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - z = zeta + 1/6 * (cos(0.5 * pi * (2 * x - 3)/3) * - cos(pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - return SVector(x, y, z) + # Don't transform input variables between -1 and 1 onto [0,3] to obtain curved boundaries + # xi = 1.5 * xi_ + 1.5 + # eta = 1.5 * eta_ + 1.5 + # zeta = 1.5 * zeta_ + 1.5 + + y = eta + + 1 / 6 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + x = xi + + 1 / 6 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + z = zeta + + 1 / 6 * (cos(0.5 * pi * (2 * x - 3) / 3) * + cos(pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + return SVector(x, y, z) end # Unstructured mesh with 68 cells of the cube domain [-1, 1]^3 mesh_file = joinpath(@__DIR__, "cube_unstructured_1.inp") -isfile(mesh_file) || download("https://gist.githubusercontent.com/efaulhaber/d45c8ac1e248618885fa7cc31a50ab40/raw/37fba24890ab37cfa49c39eae98b44faf4502882/cube_unstructured_1.inp", - mesh_file) +isfile(mesh_file) || + download("https://gist.githubusercontent.com/efaulhaber/d45c8ac1e248618885fa7cc31a50ab40/raw/37fba24890ab37cfa49c39eae98b44faf4502882/cube_unstructured_1.inp", + mesh_file) -mesh = P4estMesh{3}(mesh_file, polydeg=3, - mapping=mapping, - initial_refinement_level=2) +mesh = P4estMesh{3}(mesh_file, polydeg = 3, + mapping = mapping, + initial_refinement_level = 2) # A semidiscretization collects data structures and functions for the spatial discretization -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, boundary_conditions=boundary_conditions) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -68,32 +71,32 @@ summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) # The SaveRestartCallback allows to save a file from which a Trixi.jl simulation can be restarted -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.2) +stepsize_callback = StepsizeCallback(cfl = 1.2) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_restart, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_restart, + save_solution, stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); # Print the timer summary summary_callback() diff --git a/examples/p4est_3d_dgsem/elixir_euler_baroclinic_instability.jl b/examples/p4est_3d_dgsem/elixir_euler_baroclinic_instability.jl index 27c8ceb130c..0274a89aec7 100644 --- a/examples/p4est_3d_dgsem/elixir_euler_baroclinic_instability.jl +++ b/examples/p4est_3d_dgsem/elixir_euler_baroclinic_instability.jl @@ -22,190 +22,194 @@ equations = CompressibleEulerEquations3D(gamma) # Initial condition for an idealized baroclinic instability test # https://doi.org/10.1002/qj.2241, Section 3.2 and Appendix A -function initial_condition_baroclinic_instability(x, t, equations::CompressibleEulerEquations3D) - lon, lat, r = cartesian_to_sphere(x) - radius_earth = 6.371229e6 - # Make sure that the r is not smaller than radius_earth - z = max(r - radius_earth, 0.0) +function initial_condition_baroclinic_instability(x, t, + equations::CompressibleEulerEquations3D) + lon, lat, r = cartesian_to_sphere(x) + radius_earth = 6.371229e6 + # Make sure that the r is not smaller than radius_earth + z = max(r - radius_earth, 0.0) - # Unperturbed basic state - rho, u, p = basic_state_baroclinic_instability_longitudinal_velocity(lon, lat, z) + # Unperturbed basic state + rho, u, p = basic_state_baroclinic_instability_longitudinal_velocity(lon, lat, z) - # Stream function type perturbation - u_perturbation, v_perturbation = perturbation_stream_function(lon, lat, z) + # Stream function type perturbation + u_perturbation, v_perturbation = perturbation_stream_function(lon, lat, z) - u += u_perturbation - v = v_perturbation + u += u_perturbation + v = v_perturbation - # Convert spherical velocity to Cartesian - v1 = -sin(lon) * u - sin(lat) * cos(lon) * v - v2 = cos(lon) * u - sin(lat) * sin(lon) * v - v3 = cos(lat) * v + # Convert spherical velocity to Cartesian + v1 = -sin(lon) * u - sin(lat) * cos(lon) * v + v2 = cos(lon) * u - sin(lat) * sin(lon) * v + v3 = cos(lat) * v - return prim2cons(SVector(rho, v1, v2, v3, p), equations) + return prim2cons(SVector(rho, v1, v2, v3, p), equations) end # Steady state for RHS correction below function steady_state_baroclinic_instability(x, t, equations::CompressibleEulerEquations3D) - lon, lat, r = cartesian_to_sphere(x) - radius_earth = 6.371229e6 - # Make sure that the r is not smaller than radius_earth - z = max(r - radius_earth, 0.0) + lon, lat, r = cartesian_to_sphere(x) + radius_earth = 6.371229e6 + # Make sure that the r is not smaller than radius_earth + z = max(r - radius_earth, 0.0) - # Unperturbed basic state - rho, u, p = basic_state_baroclinic_instability_longitudinal_velocity(lon, lat, z) + # Unperturbed basic state + rho, u, p = basic_state_baroclinic_instability_longitudinal_velocity(lon, lat, z) - # Convert spherical velocity to Cartesian - v1 = -sin(lon) * u - v2 = cos(lon) * u - v3 = 0.0 + # Convert spherical velocity to Cartesian + v1 = -sin(lon) * u + v2 = cos(lon) * u + v3 = 0.0 - return prim2cons(SVector(rho, v1, v2, v3, p), equations) + return prim2cons(SVector(rho, v1, v2, v3, p), equations) end function cartesian_to_sphere(x) - r = norm(x) - lambda = atan(x[2], x[1]) - if lambda < 0 - lambda += 2 * pi - end - phi = asin(x[3] / r) - - return lambda, phi, r + r = norm(x) + lambda = atan(x[2], x[1]) + if lambda < 0 + lambda += 2 * pi + end + phi = asin(x[3] / r) + + return lambda, phi, r end # Unperturbed balanced steady-state. # Returns primitive variables with only the velocity in longitudinal direction (rho, u, p). # The other velocity components are zero. function basic_state_baroclinic_instability_longitudinal_velocity(lon, lat, z) - # Parameters from Table 1 in the paper - # Corresponding names in the paper are commented - radius_earth = 6.371229e6 # a - half_width_parameter = 2 # b - gravitational_acceleration = 9.80616 # g - k = 3 # k - surface_pressure = 1e5 # p₀ - gas_constant = 287 # R - surface_equatorial_temperature = 310.0 # T₀ᴱ - surface_polar_temperature = 240.0 # T₀ᴾ - lapse_rate = 0.005 # Γ - angular_velocity = 7.29212e-5 # Ω - - # Distance to the center of the Earth - r = z + radius_earth - - # In the paper: T₀ - temperature0 = 0.5 * (surface_equatorial_temperature + surface_polar_temperature) - # In the paper: A, B, C, H - const_a = 1 / lapse_rate - const_b = (temperature0 - surface_polar_temperature) / - (temperature0 * surface_polar_temperature) - const_c = 0.5 * (k + 2) * (surface_equatorial_temperature - surface_polar_temperature) / - (surface_equatorial_temperature * surface_polar_temperature) - const_h = gas_constant * temperature0 / gravitational_acceleration - - # In the paper: (r - a) / bH - scaled_z = z / (half_width_parameter * const_h) - - # Temporary variables - temp1 = exp(lapse_rate/temperature0 * z) - temp2 = exp(-scaled_z^2) - - # In the paper: ̃τ₁, ̃τ₂ - tau1 = const_a * lapse_rate / temperature0 * temp1 + const_b * (1 - 2 * scaled_z^2) * temp2 - tau2 = const_c * (1 - 2 * scaled_z^2) * temp2 - - # In the paper: ∫τ₁(r') dr', ∫τ₂(r') dr' - inttau1 = const_a * (temp1 - 1) + const_b * z * temp2 - inttau2 = const_c * z * temp2 - - # Temporary variables - temp3 = r/radius_earth * cos(lat) - temp4 = temp3^k - k/(k + 2) * temp3^(k+2) - - # In the paper: T - temperature = 1 / ((r/radius_earth)^2 * (tau1 - tau2 * temp4)) - - # In the paper: U, u (zonal wind, first component of spherical velocity) - big_u = gravitational_acceleration/radius_earth * k * temperature * inttau2 * (temp3^(k-1) - temp3^(k+1)) - temp5 = radius_earth * cos(lat) - u = -angular_velocity * temp5 + sqrt(angular_velocity^2 * temp5^2 + temp5 * big_u) - - # Hydrostatic pressure - p = surface_pressure * exp(-gravitational_acceleration/gas_constant * (inttau1 - inttau2 * temp4)) - - # Density (via ideal gas law) - rho = p / (gas_constant * temperature) - - return rho, u, p + # Parameters from Table 1 in the paper + # Corresponding names in the paper are commented + radius_earth = 6.371229e6 # a + half_width_parameter = 2 # b + gravitational_acceleration = 9.80616 # g + k = 3 # k + surface_pressure = 1e5 # p₀ + gas_constant = 287 # R + surface_equatorial_temperature = 310.0 # T₀ᴱ + surface_polar_temperature = 240.0 # T₀ᴾ + lapse_rate = 0.005 # Γ + angular_velocity = 7.29212e-5 # Ω + + # Distance to the center of the Earth + r = z + radius_earth + + # In the paper: T₀ + temperature0 = 0.5 * (surface_equatorial_temperature + surface_polar_temperature) + # In the paper: A, B, C, H + const_a = 1 / lapse_rate + const_b = (temperature0 - surface_polar_temperature) / + (temperature0 * surface_polar_temperature) + const_c = 0.5 * (k + 2) * (surface_equatorial_temperature - surface_polar_temperature) / + (surface_equatorial_temperature * surface_polar_temperature) + const_h = gas_constant * temperature0 / gravitational_acceleration + + # In the paper: (r - a) / bH + scaled_z = z / (half_width_parameter * const_h) + + # Temporary variables + temp1 = exp(lapse_rate / temperature0 * z) + temp2 = exp(-scaled_z^2) + + # In the paper: ̃τ₁, ̃τ₂ + tau1 = const_a * lapse_rate / temperature0 * temp1 + + const_b * (1 - 2 * scaled_z^2) * temp2 + tau2 = const_c * (1 - 2 * scaled_z^2) * temp2 + + # In the paper: ∫τ₁(r') dr', ∫τ₂(r') dr' + inttau1 = const_a * (temp1 - 1) + const_b * z * temp2 + inttau2 = const_c * z * temp2 + + # Temporary variables + temp3 = r / radius_earth * cos(lat) + temp4 = temp3^k - k / (k + 2) * temp3^(k + 2) + + # In the paper: T + temperature = 1 / ((r / radius_earth)^2 * (tau1 - tau2 * temp4)) + + # In the paper: U, u (zonal wind, first component of spherical velocity) + big_u = gravitational_acceleration / radius_earth * k * temperature * inttau2 * + (temp3^(k - 1) - temp3^(k + 1)) + temp5 = radius_earth * cos(lat) + u = -angular_velocity * temp5 + sqrt(angular_velocity^2 * temp5^2 + temp5 * big_u) + + # Hydrostatic pressure + p = surface_pressure * + exp(-gravitational_acceleration / gas_constant * (inttau1 - inttau2 * temp4)) + + # Density (via ideal gas law) + rho = p / (gas_constant * temperature) + + return rho, u, p end # Perturbation as in Equations 25 and 26 of the paper (analytical derivative) function perturbation_stream_function(lon, lat, z) - # Parameters from Table 1 in the paper - # Corresponding names in the paper are commented - perturbation_radius = 1/6 # d₀ / a - perturbed_wind_amplitude = 1.0 # Vₚ - perturbation_lon = pi/9 # Longitude of perturbation location - perturbation_lat = 2 * pi/9 # Latitude of perturbation location - pertz = 15000 # Perturbation height cap - - # Great circle distance (d in the paper) divided by a (radius of the Earth) - # because we never actually need d without dividing by a - great_circle_distance_by_a = acos(sin(perturbation_lat) * sin(lat) + - cos(perturbation_lat) * cos(lat) * - cos(lon - perturbation_lon)) - - # In the first case, the vertical taper function is per definition zero. - # In the second case, the stream function is per definition zero. - if z > pertz || great_circle_distance_by_a > perturbation_radius - return 0.0, 0.0 - end - - # Vertical tapering of stream function - perttaper = 1.0 - 3 * z^2 / pertz^2 + 2 * z^3 / pertz^3 - - # sin/cos(pi * d / (2 * d_0)) in the paper - sin_, cos_ = sincos(0.5 * pi * great_circle_distance_by_a / perturbation_radius) - - # Common factor for both u and v - factor = 16 / (3 * sqrt(3)) * perturbed_wind_amplitude * perttaper * cos_^3 * sin_ - - u_perturbation = -factor * (-sin(perturbation_lat) * cos(lat) + - cos(perturbation_lat) * sin(lat) * cos(lon - perturbation_lon) - ) / sin(great_circle_distance_by_a) - - v_perturbation = factor * cos(perturbation_lat) * sin(lon - perturbation_lon) / - sin(great_circle_distance_by_a) - - return u_perturbation, v_perturbation -end + # Parameters from Table 1 in the paper + # Corresponding names in the paper are commented + perturbation_radius = 1 / 6 # d₀ / a + perturbed_wind_amplitude = 1.0 # Vₚ + perturbation_lon = pi / 9 # Longitude of perturbation location + perturbation_lat = 2 * pi / 9 # Latitude of perturbation location + pertz = 15000 # Perturbation height cap + + # Great circle distance (d in the paper) divided by a (radius of the Earth) + # because we never actually need d without dividing by a + great_circle_distance_by_a = acos(sin(perturbation_lat) * sin(lat) + + cos(perturbation_lat) * cos(lat) * + cos(lon - perturbation_lon)) + + # In the first case, the vertical taper function is per definition zero. + # In the second case, the stream function is per definition zero. + if z > pertz || great_circle_distance_by_a > perturbation_radius + return 0.0, 0.0 + end + + # Vertical tapering of stream function + perttaper = 1.0 - 3 * z^2 / pertz^2 + 2 * z^3 / pertz^3 + + # sin/cos(pi * d / (2 * d_0)) in the paper + sin_, cos_ = sincos(0.5 * pi * great_circle_distance_by_a / perturbation_radius) + # Common factor for both u and v + factor = 16 / (3 * sqrt(3)) * perturbed_wind_amplitude * perttaper * cos_^3 * sin_ -@inline function source_terms_baroclinic_instability(u, x, t, equations::CompressibleEulerEquations3D) - radius_earth = 6.371229e6 # a - gravitational_acceleration = 9.80616 # g - angular_velocity = 7.29212e-5 # Ω + u_perturbation = -factor * (-sin(perturbation_lat) * cos(lat) + + cos(perturbation_lat) * sin(lat) * cos(lon - perturbation_lon)) / + sin(great_circle_distance_by_a) - r = norm(x) - # Make sure that r is not smaller than radius_earth - z = max(r - radius_earth, 0.0) - r = z + radius_earth + v_perturbation = factor * cos(perturbation_lat) * sin(lon - perturbation_lon) / + sin(great_circle_distance_by_a) - du1 = zero(eltype(u)) + return u_perturbation, v_perturbation +end + +@inline function source_terms_baroclinic_instability(u, x, t, + equations::CompressibleEulerEquations3D) + radius_earth = 6.371229e6 # a + gravitational_acceleration = 9.80616 # g + angular_velocity = 7.29212e-5 # Ω + + r = norm(x) + # Make sure that r is not smaller than radius_earth + z = max(r - radius_earth, 0.0) + r = z + radius_earth - # Gravity term - temp = -gravitational_acceleration * radius_earth^2 / r^3 - du2 = temp * u[1] * x[1] - du3 = temp * u[1] * x[2] - du4 = temp * u[1] * x[3] - du5 = temp * (u[2] * x[1] + u[3] * x[2] + u[4] * x[3]) + du1 = zero(eltype(u)) - # Coriolis term, -2Ω × ρv = -2 * angular_velocity * (0, 0, 1) × u[2:4] - du2 -= -2 * angular_velocity * u[3] - du3 -= 2 * angular_velocity * u[2] + # Gravity term + temp = -gravitational_acceleration * radius_earth^2 / r^3 + du2 = temp * u[1] * x[1] + du3 = temp * u[1] * x[2] + du4 = temp * u[1] * x[3] + du5 = temp * (u[2] * x[1] + u[3] * x[2] + u[4] * x[3]) - return SVector(du1, du2, du3, du4, du5) + # Coriolis term, -2Ω × ρv = -2 * angular_velocity * (0, 0, 1) × u[2:4] + du2 -= -2 * angular_velocity * u[3] + du3 -= 2 * angular_velocity * u[2] + + return SVector(du1, du2, du3, du4, du5) end ############################################################################### @@ -213,26 +217,24 @@ end initial_condition = initial_condition_baroclinic_instability -boundary_conditions = Dict( - :inside => boundary_condition_slip_wall, - :outside => boundary_condition_slip_wall, -) +boundary_conditions = Dict(:inside => boundary_condition_slip_wall, + :outside => boundary_condition_slip_wall) # This is a good estimate for the speed of sound in this example. # Other values between 300 and 400 should work as well. surface_flux = FluxLMARS(340) -volume_flux = flux_kennedy_gruber -solver = DGSEM(polydeg=5, surface_flux=surface_flux, volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +volume_flux = flux_kennedy_gruber +solver = DGSEM(polydeg = 5, surface_flux = surface_flux, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) # For optimal results, use (16, 8) here trees_per_cube_face = (8, 4) mesh = Trixi.P4estMeshCubedSphere(trees_per_cube_face..., 6.371229e6, 30000.0, - polydeg=5, initial_refinement_level=0) + polydeg = 5, initial_refinement_level = 0) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_baroclinic_instability, - boundary_conditions=boundary_conditions) - + source_terms = source_terms_baroclinic_instability, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -250,20 +252,20 @@ tspan = (0.0, 10 * 24 * 60 * 60.0) # time in seconds for 10 days u_steady_state = compute_coefficients(steady_state_baroclinic_instability, tspan[1], semi) # Use a `let` block for performance (otherwise du_steady_state will be a global variable) let du_steady_state = similar(u_steady_state) - # Save RHS of the steady state - Trixi.rhs!(du_steady_state, u_steady_state, semi, tspan[1]) - - global function corrected_rhs!(du, u, semi, t) - # Normal RHS evaluation - Trixi.rhs!(du, u, semi, t) - # Correct by subtracting the steady-state RHS - Trixi.@trixi_timeit Trixi.timer() "rhs correction" begin - # Use Trixi.@threaded for threaded performance - Trixi.@threaded for i in eachindex(du) - du[i] -= du_steady_state[i] - end + # Save RHS of the steady state + Trixi.rhs!(du_steady_state, u_steady_state, semi, tspan[1]) + + global function corrected_rhs!(du, u, semi, t) + # Normal RHS evaluation + Trixi.rhs!(du, u, semi, t) + # Correct by subtracting the steady-state RHS + Trixi.@trixi_timeit Trixi.timer() "rhs correction" begin + # Use Trixi.@threaded for threaded performance + Trixi.@threaded for i in eachindex(du) + du[i] -= du_steady_state[i] + end + end end - end end u0 = compute_coefficients(tspan[1], semi) ode = ODEProblem(corrected_rhs!, u0, tspan, semi) @@ -271,27 +273,27 @@ ode = ODEProblem(corrected_rhs!, u0, tspan, semi) summary_callback = SummaryCallback() analysis_interval = 5000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=5000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 5000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) - ############################################################################### # run the simulation # Use a Runge-Kutta method with automatic (error based) time step size control # Enable threading of the RK method for better performance on multiple threads -sol = solve(ode, RDPK3SpFSAL49(thread=OrdinaryDiffEq.True()); abstol=1.0e-6, reltol=1.0e-6, - ode_default_options()..., callback=callbacks); +sol = solve(ode, RDPK3SpFSAL49(thread = OrdinaryDiffEq.True()); abstol = 1.0e-6, + reltol = 1.0e-6, + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/p4est_3d_dgsem/elixir_euler_circular_wind_nonconforming.jl b/examples/p4est_3d_dgsem/elixir_euler_circular_wind_nonconforming.jl index 63e937620f0..34a43a5b534 100644 --- a/examples/p4est_3d_dgsem/elixir_euler_circular_wind_nonconforming.jl +++ b/examples/p4est_3d_dgsem/elixir_euler_circular_wind_nonconforming.jl @@ -14,78 +14,77 @@ using LinearAlgebra gamma = 1.4 equations = CompressibleEulerEquations3D(gamma) - function initial_condition_circular_wind(x, t, equations::CompressibleEulerEquations3D) - radius_earth = 6.371229e6 - p = 1e5 - rho = 1.0 - v1 = -10 * x[2] / radius_earth - v2 = 10 * x[1] / radius_earth - v3 = 0.0 - - return prim2cons(SVector(rho, v1, v2, v3, p), equations) + radius_earth = 6.371229e6 + p = 1e5 + rho = 1.0 + v1 = -10 * x[2] / radius_earth + v2 = 10 * x[1] / radius_earth + v3 = 0.0 + + return prim2cons(SVector(rho, v1, v2, v3, p), equations) end -@inline function source_terms_circular_wind(u, x, t, equations::CompressibleEulerEquations3D) - radius_earth = 6.371229e6 - rho = 1.0 +@inline function source_terms_circular_wind(u, x, t, + equations::CompressibleEulerEquations3D) + radius_earth = 6.371229e6 + rho = 1.0 - du1 = 0.0 - du2 = -rho * (10 / radius_earth) * (10 * x[1] / radius_earth) - du3 = -rho * (10 / radius_earth) * (10 * x[2] / radius_earth) - du4 = 0.0 - du5 = 0.0 + du1 = 0.0 + du2 = -rho * (10 / radius_earth) * (10 * x[1] / radius_earth) + du3 = -rho * (10 / radius_earth) * (10 * x[2] / radius_earth) + du4 = 0.0 + du5 = 0.0 - return SVector(du1, du2, du3, du4, du5) + return SVector(du1, du2, du3, du4, du5) end - -function indicator_test(u::AbstractArray{<:Any,5}, +function indicator_test(u::AbstractArray{<:Any, 5}, mesh, equations, dg::DGSEM, cache; kwargs...) - alpha = zeros(Int, nelements(dg, cache)) - - for element in eachelement(dg, cache) - for k in eachnode(dg), j in eachnode(dg), i in eachnode(dg) - x = Trixi.get_node_coords(cache.elements.node_coordinates, equations, dg, i, j, k, element) - lambda, phi, r = cart_to_sphere(x) - if 0.22 < lambda < 3.3 && 0.45 < phi < 1.3 - alpha[element] = 1 - end + alpha = zeros(Int, nelements(dg, cache)) + + for element in eachelement(dg, cache) + for k in eachnode(dg), j in eachnode(dg), i in eachnode(dg) + x = Trixi.get_node_coords(cache.elements.node_coordinates, equations, dg, i, j, + k, element) + lambda, phi, r = cart_to_sphere(x) + if 0.22 < lambda < 3.3 && 0.45 < phi < 1.3 + alpha[element] = 1 + end + end end - end - return alpha + return alpha end function cart_to_sphere(x) - r = norm(x) - lambda = atan(x[2], x[1]) - if lambda < 0 - lambda += 2 * pi - end - phi = asin(x[3] / r) - - return lambda, phi, r + r = norm(x) + lambda = atan(x[2], x[1]) + if lambda < 0 + lambda += 2 * pi + end + phi = asin(x[3] / r) + + return lambda, phi, r end -function Trixi.get_element_variables!(element_variables, indicator::typeof(indicator_test), ::AMRCallback) - return nothing +function Trixi.get_element_variables!(element_variables, indicator::typeof(indicator_test), + ::AMRCallback) + return nothing end initial_condition = initial_condition_circular_wind -boundary_conditions = Dict( - :inside => boundary_condition_slip_wall, - :outside => boundary_condition_slip_wall -) +boundary_conditions = Dict(:inside => boundary_condition_slip_wall, + :outside => boundary_condition_slip_wall) # The speed of sound in this example is 374 m/s. surface_flux = FluxLMARS(374) # Note that a free stream is not preserved if N < 2 * N_geo, where N is the # polydeg of the solver and N_geo is the polydeg of the mesh. # However, the FSP error is negligible in this example. -solver = DGSEM(polydeg=4, surface_flux=surface_flux) +solver = DGSEM(polydeg = 4, surface_flux = surface_flux) # Other mesh configurations to run this simulation on. # The cylinder allows to use a structured mesh, the face of the cubed sphere @@ -113,12 +112,11 @@ solver = DGSEM(polydeg=4, surface_flux=surface_flux) trees_per_cube_face = (6, 2) mesh = Trixi.P4estMeshCubedSphere(trees_per_cube_face..., 6.371229e6, 30000.0, - polydeg=4, initial_refinement_level=0) + polydeg = 4, initial_refinement_level = 0) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_circular_wind, - boundary_conditions=boundary_conditions) - + source_terms = source_terms_circular_wind, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -129,22 +127,22 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 5000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=5000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 5000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_controller = ControllerThreeLevel(semi, indicator_test, - base_level=0, - max_level=1, max_threshold=0.6) + base_level = 0, + max_level = 1, max_threshold = 0.6) amr_callback = AMRCallback(semi, amr_controller, - interval=0, # Only initial refinement - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 0, # Only initial refinement + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -152,13 +150,13 @@ callbacks = CallbackSet(summary_callback, save_solution, amr_callback) - ############################################################################### # run the simulation # Use a Runge-Kutta method with automatic (error based) time step size control # Enable threading of the RK method for better performance on multiple threads -sol = solve(ode, RDPK3SpFSAL49(thread=OrdinaryDiffEq.True()); abstol=1.0e-6, reltol=1.0e-6, - ode_default_options()..., callback=callbacks); +sol = solve(ode, RDPK3SpFSAL49(thread = OrdinaryDiffEq.True()); abstol = 1.0e-6, + reltol = 1.0e-6, + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/p4est_3d_dgsem/elixir_euler_ec.jl b/examples/p4est_3d_dgsem/elixir_euler_ec.jl index 463a26fca53..d9d774a7ffc 100644 --- a/examples/p4est_3d_dgsem/elixir_euler_ec.jl +++ b/examples/p4est_3d_dgsem/elixir_euler_ec.jl @@ -6,56 +6,59 @@ using Trixi ############################################################################### # semidiscretization of the compressible Euler equations -equations = CompressibleEulerEquations3D(5/3) +equations = CompressibleEulerEquations3D(5 / 3) initial_condition = initial_condition_weak_blast_wave -boundary_conditions = Dict( - :all => boundary_condition_slip_wall -) +boundary_conditions = Dict(:all => boundary_condition_slip_wall) # Get the DG approximation space volume_flux = flux_ranocha -solver = DGSEM(polydeg=5, surface_flux=flux_ranocha, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 5, surface_flux = flux_ranocha, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) # Get the curved quad mesh from a file # Mapping as described in https://arxiv.org/abs/2012.12040 function mapping(xi_, eta_, zeta_) - # Transform input variables between -1 and 1 onto [0,3] - xi = 1.5 * xi_ + 1.5 - eta = 1.5 * eta_ + 1.5 - zeta = 1.5 * zeta_ + 1.5 - - y = eta + 3/8 * (cos(1.5 * pi * (2 * xi - 3)/3) * - cos(0.5 * pi * (2 * eta - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - x = xi + 3/8 * (cos(0.5 * pi * (2 * xi - 3)/3) * - cos(2 * pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - z = zeta + 3/8 * (cos(0.5 * pi * (2 * x - 3)/3) * - cos(pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - return SVector(x, y, z) + # Transform input variables between -1 and 1 onto [0,3] + xi = 1.5 * xi_ + 1.5 + eta = 1.5 * eta_ + 1.5 + zeta = 1.5 * zeta_ + 1.5 + + y = eta + + 3 / 8 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + x = xi + + 3 / 8 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + z = zeta + + 3 / 8 * (cos(0.5 * pi * (2 * x - 3) / 3) * + cos(pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + return SVector(x, y, z) end # Unstructured mesh with 48 cells of the cube domain [-1, 1]^3 mesh_file = joinpath(@__DIR__, "cube_unstructured_2.inp") -isfile(mesh_file) || download("https://gist.githubusercontent.com/efaulhaber/b8df0033798e4926dec515fc045e8c2c/raw/b9254cde1d1fb64b6acc8416bc5ccdd77a240227/cube_unstructured_2.inp", - mesh_file) +isfile(mesh_file) || + download("https://gist.githubusercontent.com/efaulhaber/b8df0033798e4926dec515fc045e8c2c/raw/b9254cde1d1fb64b6acc8416bc5ccdd77a240227/cube_unstructured_2.inp", + mesh_file) -mesh = P4estMesh{3}(mesh_file, polydeg=5, - mapping=mapping, - initial_refinement_level=0) +mesh = P4estMesh{3}(mesh_file, polydeg = 5, + mapping = mapping, + initial_refinement_level = 0) # create the semidiscretization object -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, boundary_conditions=boundary_conditions) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -66,15 +69,15 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -85,7 +88,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/p4est_3d_dgsem/elixir_euler_free_stream.jl b/examples/p4est_3d_dgsem/elixir_euler_free_stream.jl index 3450adfe861..24a781ca59e 100644 --- a/examples/p4est_3d_dgsem/elixir_euler_free_stream.jl +++ b/examples/p4est_3d_dgsem/elixir_euler_free_stream.jl @@ -10,70 +10,75 @@ equations = CompressibleEulerEquations3D(1.4) initial_condition = initial_condition_constant -boundary_conditions = Dict( - :all => BoundaryConditionDirichlet(initial_condition) -) +boundary_conditions = Dict(:all => BoundaryConditionDirichlet(initial_condition)) # Solver with polydeg=4 to ensure free stream preservation (FSP) on non-conforming meshes. # The polydeg of the solver must be at least twice as big as the polydeg of the mesh. # See https://doi.org/10.1007/s10915-018-00897-9, Section 6. -solver = DGSEM(polydeg=4, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralWeakForm()) +solver = DGSEM(polydeg = 4, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralWeakForm()) # Mapping as described in https://arxiv.org/abs/2012.12040 but with less warping. # The mapping will be interpolated at tree level, and then refined without changing # the geometry interpolant. This can yield problematic geometries if the unrefined mesh # is not fine enough. function mapping(xi_, eta_, zeta_) - # Transform input variables between -1 and 1 onto [0,3] - xi = 1.5 * xi_ + 1.5 - eta = 1.5 * eta_ + 1.5 - zeta = 1.5 * zeta_ + 1.5 - - y = eta + 1/6 * (cos(1.5 * pi * (2 * xi - 3)/3) * - cos(0.5 * pi * (2 * eta - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - x = xi + 1/6 * (cos(0.5 * pi * (2 * xi - 3)/3) * - cos(2 * pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - z = zeta + 1/6 * (cos(0.5 * pi * (2 * x - 3)/3) * - cos(pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - return SVector(x, y, z) + # Transform input variables between -1 and 1 onto [0,3] + xi = 1.5 * xi_ + 1.5 + eta = 1.5 * eta_ + 1.5 + zeta = 1.5 * zeta_ + 1.5 + + y = eta + + 1 / 6 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + x = xi + + 1 / 6 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + z = zeta + + 1 / 6 * (cos(0.5 * pi * (2 * x - 3) / 3) * + cos(pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + return SVector(x, y, z) end # Unstructured mesh with 68 cells of the cube domain [-1, 1]^3 mesh_file = joinpath(@__DIR__, "cube_unstructured_1.inp") -isfile(mesh_file) || download("https://gist.githubusercontent.com/efaulhaber/d45c8ac1e248618885fa7cc31a50ab40/raw/37fba24890ab37cfa49c39eae98b44faf4502882/cube_unstructured_1.inp", - mesh_file) +isfile(mesh_file) || + download("https://gist.githubusercontent.com/efaulhaber/d45c8ac1e248618885fa7cc31a50ab40/raw/37fba24890ab37cfa49c39eae98b44faf4502882/cube_unstructured_1.inp", + mesh_file) # Mesh polydeg of 2 (half the solver polydeg) to ensure FSP (see above). -mesh = P4estMesh{3}(mesh_file, polydeg=2, - mapping=mapping, - initial_refinement_level=0) +mesh = P4estMesh{3}(mesh_file, polydeg = 2, + mapping = mapping, + initial_refinement_level = 0) # Refine bottom left quadrant of each second tree to level 2 function refine_fn(p8est, which_tree, quadrant) - quadrant_obj = unsafe_load(quadrant) - if iseven(convert(Int, which_tree)) && quadrant_obj.x == 0 && quadrant_obj.y == 0 && quadrant_obj.z == 0 && quadrant_obj.level < 2 - # return true (refine) - return Cint(1) - else - # return false (don't refine) - return Cint(0) - end + quadrant_obj = unsafe_load(quadrant) + if iseven(convert(Int, which_tree)) && quadrant_obj.x == 0 && quadrant_obj.y == 0 && + quadrant_obj.z == 0 && quadrant_obj.level < 2 + # return true (refine) + return Cint(1) + else + # return false (don't refine) + return Cint(0) + end end # Refine recursively until each bottom left quadrant of every second tree has level 2. # The mesh will be rebalanced before the simulation starts. -refine_fn_c = @cfunction(refine_fn, Cint, (Ptr{Trixi.p8est_t}, Ptr{Trixi.p4est_topidx_t}, Ptr{Trixi.p8est_quadrant_t})) +refine_fn_c = @cfunction(refine_fn, Cint, + (Ptr{Trixi.p8est_t}, Ptr{Trixi.p4est_topidx_t}, + Ptr{Trixi.p8est_quadrant_t})) Trixi.refine_p4est!(mesh.p4est, true, refine_fn_c, C_NULL) -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, boundary_conditions=boundary_conditions) - +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -84,27 +89,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.2) +stepsize_callback = StepsizeCallback(cfl = 1.2) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/p4est_3d_dgsem/elixir_euler_free_stream_extruded.jl b/examples/p4est_3d_dgsem/elixir_euler_free_stream_extruded.jl index 630a269b4a1..f56fe3a429d 100644 --- a/examples/p4est_3d_dgsem/elixir_euler_free_stream_extruded.jl +++ b/examples/p4est_3d_dgsem/elixir_euler_free_stream_extruded.jl @@ -10,12 +10,10 @@ equations = CompressibleEulerEquations3D(1.4) initial_condition = initial_condition_constant -boundary_conditions = Dict( - :all => BoundaryConditionDirichlet(initial_condition) -) +boundary_conditions = Dict(:all => BoundaryConditionDirichlet(initial_condition)) -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralWeakForm()) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralWeakForm()) # Mapping as described in https://arxiv.org/abs/2012.12040 but reduced to 2D. # This particular mesh is unstructured in the yz-plane, but extruded in x-direction. @@ -23,47 +21,52 @@ solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, # in x-direction to ensure free stream preservation on a non-conforming mesh. # See https://doi.org/10.1007/s10915-018-00897-9, Section 6. function mapping(xi, eta_, zeta_) - # Transform input variables between -1 and 1 onto [0,3] - eta = 1.5 * eta_ + 1.5 - zeta = 1.5 * zeta_ + 1.5 + # Transform input variables between -1 and 1 onto [0,3] + eta = 1.5 * eta_ + 1.5 + zeta = 1.5 * zeta_ + 1.5 - z = zeta + 1/6 * (cos(1.5 * pi * (2 * eta - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) + z = zeta + + 1 / 6 * (cos(1.5 * pi * (2 * eta - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) - y = eta + 1/6 * (cos(0.5 * pi * (2 * eta - 3)/3) * - cos(2 * pi * (2 * z - 3)/3)) + y = eta + 1 / 6 * (cos(0.5 * pi * (2 * eta - 3) / 3) * + cos(2 * pi * (2 * z - 3) / 3)) - return SVector(xi, y, z) + return SVector(xi, y, z) end # Unstructured mesh with 48 cells of the cube domain [-1, 1]^3 mesh_file = joinpath(@__DIR__, "cube_unstructured_2.inp") -isfile(mesh_file) || download("https://gist.githubusercontent.com/efaulhaber/b8df0033798e4926dec515fc045e8c2c/raw/b9254cde1d1fb64b6acc8416bc5ccdd77a240227/cube_unstructured_2.inp", - mesh_file) +isfile(mesh_file) || + download("https://gist.githubusercontent.com/efaulhaber/b8df0033798e4926dec515fc045e8c2c/raw/b9254cde1d1fb64b6acc8416bc5ccdd77a240227/cube_unstructured_2.inp", + mesh_file) -mesh = P4estMesh{3}(mesh_file, polydeg=3, - mapping=mapping, - initial_refinement_level=0) +mesh = P4estMesh{3}(mesh_file, polydeg = 3, + mapping = mapping, + initial_refinement_level = 0) # Refine quadrants in y-direction of each tree at one edge to level 2 function refine_fn(p8est, which_tree, quadrant) - quadrant_obj = unsafe_load(quadrant) - if convert(Int, which_tree) < 4 && quadrant_obj.x == 0 && quadrant_obj.y == 0 && quadrant_obj.level < 2 - # return true (refine) - return Cint(1) - else - # return false (don't refine) - return Cint(0) - end + quadrant_obj = unsafe_load(quadrant) + if convert(Int, which_tree) < 4 && quadrant_obj.x == 0 && quadrant_obj.y == 0 && + quadrant_obj.level < 2 + # return true (refine) + return Cint(1) + else + # return false (don't refine) + return Cint(0) + end end # Refine recursively until each desired quadrant has level 2. # The mesh will be rebalanced before the simulation starts. -refine_fn_c = @cfunction(refine_fn, Cint, (Ptr{Trixi.p8est_t}, Ptr{Trixi.p4est_topidx_t}, Ptr{Trixi.p8est_quadrant_t})) +refine_fn_c = @cfunction(refine_fn, Cint, + (Ptr{Trixi.p8est_t}, Ptr{Trixi.p4est_topidx_t}, + Ptr{Trixi.p8est_quadrant_t})) Trixi.refine_p4est!(mesh.p4est, true, refine_fn_c, C_NULL) -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, boundary_conditions=boundary_conditions) - +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -74,30 +77,29 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.2) +stepsize_callback = StepsizeCallback(cfl = 1.2) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_restart, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), #maxiters=1, - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), #maxiters=1, + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/p4est_3d_dgsem/elixir_euler_sedov.jl b/examples/p4est_3d_dgsem/elixir_euler_sedov.jl index 6fa285b5565..8df95a3cc21 100644 --- a/examples/p4est_3d_dgsem/elixir_euler_sedov.jl +++ b/examples/p4est_3d_dgsem/elixir_euler_sedov.jl @@ -14,28 +14,29 @@ The Sedov blast wave setup based on Flash - https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 with smaller strength of the initial discontinuity. """ -function initial_condition_medium_sedov_blast_wave(x, t, equations::CompressibleEulerEquations3D) - # Set up polar coordinates - inicenter = SVector(0.0, 0.0, 0.0) - x_norm = x[1] - inicenter[1] - y_norm = x[2] - inicenter[2] - z_norm = x[3] - inicenter[3] - r = sqrt(x_norm^2 + y_norm^2 + z_norm^2) - - # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 - r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) - E = 1.0 - p0_inner = 3 * (equations.gamma - 1) * E / (4 * pi * r0^2) - p0_outer = 1.0e-3 - - # Calculate primitive variables - rho = 1.0 - v1 = 0.0 - v2 = 0.0 - v3 = 0.0 - p = r > r0 ? p0_outer : p0_inner - - return prim2cons(SVector(rho, v1, v2, v3, p), equations) +function initial_condition_medium_sedov_blast_wave(x, t, + equations::CompressibleEulerEquations3D) + # Set up polar coordinates + inicenter = SVector(0.0, 0.0, 0.0) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + z_norm = x[3] - inicenter[3] + r = sqrt(x_norm^2 + y_norm^2 + z_norm^2) + + # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 + r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) + E = 1.0 + p0_inner = 3 * (equations.gamma - 1) * E / (4 * pi * r0^2) + p0_outer = 1.0e-3 + + # Calculate primitive variables + rho = 1.0 + v1 = 0.0 + v2 = 0.0 + v3 = 0.0 + p = r > r0 ? p0_outer : p0_inner + + return prim2cons(SVector(rho, v1, v2, v3, p), equations) end initial_condition = initial_condition_medium_sedov_blast_wave @@ -45,24 +46,25 @@ volume_flux = flux_ranocha polydeg = 5 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=1.0, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 1.0, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) -solver = DGSEM(polydeg=polydeg, surface_flux=surface_flux, volume_integral=volume_integral) +solver = DGSEM(polydeg = polydeg, surface_flux = surface_flux, + volume_integral = volume_integral) coordinates_min = (-1.0, -1.0, -1.0) -coordinates_max = ( 1.0, 1.0, 1.0) +coordinates_max = (1.0, 1.0, 1.0) trees_per_dimension = (4, 4, 4) mesh = P4estMesh(trees_per_dimension, - polydeg=4, initial_refinement_level=0, - coordinates_min=coordinates_min, coordinates_max=coordinates_max, - periodicity=true) + polydeg = 4, initial_refinement_level = 0, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + periodicity = true) # create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -76,15 +78,15 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -95,7 +97,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/p4est_3d_dgsem/elixir_euler_source_terms_nonconforming_earth.jl b/examples/p4est_3d_dgsem/elixir_euler_source_terms_nonconforming_earth.jl index c5e349934a2..28a300cd681 100644 --- a/examples/p4est_3d_dgsem/elixir_euler_source_terms_nonconforming_earth.jl +++ b/examples/p4est_3d_dgsem/elixir_euler_source_terms_nonconforming_earth.jl @@ -11,68 +11,68 @@ using LinearAlgebra gamma = 1.4 equations = CompressibleEulerEquations3D(gamma) +function initial_condition_convergence_test_sphere(x, t, + equations::CompressibleEulerEquations3D) + x_scaled = x / 6.371229e6 + t_scaled = t / 6.371229e6 -function initial_condition_convergence_test_sphere(x, t, equations::CompressibleEulerEquations3D) - x_scaled = x / 6.371229e6 - t_scaled = t / 6.371229e6 - - return initial_condition_convergence_test(x_scaled, t_scaled, equations) + return initial_condition_convergence_test(x_scaled, t_scaled, equations) end -@inline function source_terms_convergence_test_sphere(u, x, t, equations::CompressibleEulerEquations3D) - x_scaled = x / 6.371229e6 - t_scaled = t / 6.371229e6 +@inline function source_terms_convergence_test_sphere(u, x, t, + equations::CompressibleEulerEquations3D) + x_scaled = x / 6.371229e6 + t_scaled = t / 6.371229e6 - return source_terms_convergence_test(u, x_scaled, t_scaled, equations) / 6.371229e6 + return source_terms_convergence_test(u, x_scaled, t_scaled, equations) / 6.371229e6 end - -function indicator_test(u::AbstractArray{<:Any,5}, +function indicator_test(u::AbstractArray{<:Any, 5}, mesh, equations, dg::DGSEM, cache; kwargs...) - alpha = zeros(Int, nelements(dg, cache)) - - for element in eachelement(dg, cache) - for k in eachnode(dg), j in eachnode(dg), i in eachnode(dg) - x = Trixi.get_node_coords(cache.elements.node_coordinates, equations, dg, i, j, k, element) - lambda, phi, r = cart_to_sphere(x) - if 0.22 < lambda < 3.3 && 0.45 < phi < 1.3 - alpha[element] = 1 - end + alpha = zeros(Int, nelements(dg, cache)) + + for element in eachelement(dg, cache) + for k in eachnode(dg), j in eachnode(dg), i in eachnode(dg) + x = Trixi.get_node_coords(cache.elements.node_coordinates, equations, dg, i, j, + k, element) + lambda, phi, r = cart_to_sphere(x) + if 0.22 < lambda < 3.3 && 0.45 < phi < 1.3 + alpha[element] = 1 + end + end end - end - return alpha + return alpha end function cart_to_sphere(x) - r = norm(x) - lambda = atan(x[2], x[1]) - if lambda < 0 - lambda += 2 * pi - end - phi = asin(x[3] / r) - - return lambda, phi, r + r = norm(x) + lambda = atan(x[2], x[1]) + if lambda < 0 + lambda += 2 * pi + end + phi = asin(x[3] / r) + + return lambda, phi, r end -function Trixi.get_element_variables!(element_variables, indicator::typeof(indicator_test), ::AMRCallback) - return nothing +function Trixi.get_element_variables!(element_variables, indicator::typeof(indicator_test), + ::AMRCallback) + return nothing end initial_condition = initial_condition_convergence_test_sphere boundary_condition = BoundaryConditionDirichlet(initial_condition) -boundary_conditions = Dict( - :inside => boundary_condition, - :outside => boundary_condition -) +boundary_conditions = Dict(:inside => boundary_condition, + :outside => boundary_condition) surface_flux = flux_hll # Note that a free stream is not preserved if N < 2 * N_geo, where N is the # polydeg of the solver and N_geo is the polydeg of the mesh. # However, the FSP error is negligible in this example. -solver = DGSEM(polydeg=4, surface_flux=surface_flux) +solver = DGSEM(polydeg = 4, surface_flux = surface_flux) # For performance reasons, only one face of the cubed sphere can be used: @@ -87,12 +87,11 @@ solver = DGSEM(polydeg=4, surface_flux=surface_flux) trees_per_cube_face = (6, 2) mesh = Trixi.P4estMeshCubedSphere(trees_per_cube_face..., 6.371229e6, 30000.0, - polydeg=4, initial_refinement_level=0) + polydeg = 4, initial_refinement_level = 0) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test_sphere, - boundary_conditions=boundary_conditions) - + source_terms = source_terms_convergence_test_sphere, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -103,22 +102,22 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_controller = ControllerThreeLevel(semi, indicator_test, - base_level=0, - max_level=1, max_threshold=0.6) + base_level = 0, + max_level = 1, max_threshold = 0.6) amr_callback = AMRCallback(semi, amr_controller, - interval=0, # Only initial refinement - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 0, # Only initial refinement + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -126,12 +125,11 @@ callbacks = CallbackSet(summary_callback, save_solution, amr_callback) - ############################################################################### # run the simulation # Use a Runge-Kutta method with automatic (error based) time step size control -sol = solve(ode, RDPK3SpFSAL49(); abstol=1.0e-6, reltol=1.0e-6, - ode_default_options()..., callback=callbacks); +sol = solve(ode, RDPK3SpFSAL49(); abstol = 1.0e-6, reltol = 1.0e-6, + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/p4est_3d_dgsem/elixir_euler_source_terms_nonconforming_unstructured_curved.jl b/examples/p4est_3d_dgsem/elixir_euler_source_terms_nonconforming_unstructured_curved.jl index dd394091758..0de22eaea40 100644 --- a/examples/p4est_3d_dgsem/elixir_euler_source_terms_nonconforming_unstructured_curved.jl +++ b/examples/p4est_3d_dgsem/elixir_euler_source_terms_nonconforming_unstructured_curved.jl @@ -11,73 +11,77 @@ equations = CompressibleEulerEquations3D(1.4) initial_condition = initial_condition_convergence_test boundary_condition = BoundaryConditionDirichlet(initial_condition) -boundary_conditions = Dict( - :all => boundary_condition -) +boundary_conditions = Dict(:all => boundary_condition) # Solver with polydeg=4 to ensure free stream preservation (FSP) on non-conforming meshes. # The polydeg of the solver must be at least twice as big as the polydeg of the mesh. # See https://doi.org/10.1007/s10915-018-00897-9, Section 6. -solver = DGSEM(polydeg=4, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralWeakForm()) +solver = DGSEM(polydeg = 4, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralWeakForm()) # Mapping as described in https://arxiv.org/abs/2012.12040 but with less warping. # The mapping will be interpolated at tree level, and then refined without changing # the geometry interpolant. The original mapping applied to this unstructured mesh # causes some Jacobians to be negative, which makes the mesh invalid. function mapping(xi, eta, zeta) - # Don't transform input variables between -1 and 1 onto [0,3] to obtain curved boundaries - # xi = 1.5 * xi_ + 1.5 - # eta = 1.5 * eta_ + 1.5 - # zeta = 1.5 * zeta_ + 1.5 - - y = eta + 1/6 * (cos(1.5 * pi * (2 * xi - 3)/3) * - cos(0.5 * pi * (2 * eta - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - x = xi + 1/6 * (cos(0.5 * pi * (2 * xi - 3)/3) * - cos(2 * pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - z = zeta + 1/6 * (cos(0.5 * pi * (2 * x - 3)/3) * - cos(pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - # Transform the weird deformed cube to be approximately the cube [0,2]^3 - return SVector(x + 1, y + 1, z + 1) + # Don't transform input variables between -1 and 1 onto [0,3] to obtain curved boundaries + # xi = 1.5 * xi_ + 1.5 + # eta = 1.5 * eta_ + 1.5 + # zeta = 1.5 * zeta_ + 1.5 + + y = eta + + 1 / 6 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + x = xi + + 1 / 6 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + z = zeta + + 1 / 6 * (cos(0.5 * pi * (2 * x - 3) / 3) * + cos(pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + # Transform the weird deformed cube to be approximately the cube [0,2]^3 + return SVector(x + 1, y + 1, z + 1) end # Unstructured mesh with 68 cells of the cube domain [-1, 1]^3 mesh_file = joinpath(@__DIR__, "cube_unstructured_1.inp") -isfile(mesh_file) || download("https://gist.githubusercontent.com/efaulhaber/d45c8ac1e248618885fa7cc31a50ab40/raw/37fba24890ab37cfa49c39eae98b44faf4502882/cube_unstructured_1.inp", - mesh_file) +isfile(mesh_file) || + download("https://gist.githubusercontent.com/efaulhaber/d45c8ac1e248618885fa7cc31a50ab40/raw/37fba24890ab37cfa49c39eae98b44faf4502882/cube_unstructured_1.inp", + mesh_file) # Mesh polydeg of 2 (half the solver polydeg) to ensure FSP (see above). -mesh = P4estMesh{3}(mesh_file, polydeg=2, - mapping=mapping, - initial_refinement_level=0) +mesh = P4estMesh{3}(mesh_file, polydeg = 2, + mapping = mapping, + initial_refinement_level = 0) # Refine bottom left quadrant of each tree to level 2 function refine_fn(p8est, which_tree, quadrant) - quadrant_obj = unsafe_load(quadrant) - if quadrant_obj.x == 0 && quadrant_obj.y == 0 && quadrant_obj.z == 0 && quadrant_obj.level < 2 - # return true (refine) - return Cint(1) - else - # return false (don't refine) - return Cint(0) - end + quadrant_obj = unsafe_load(quadrant) + if quadrant_obj.x == 0 && quadrant_obj.y == 0 && quadrant_obj.z == 0 && + quadrant_obj.level < 2 + # return true (refine) + return Cint(1) + else + # return false (don't refine) + return Cint(0) + end end # Refine recursively until each bottom left quadrant of a tree has level 2 # The mesh will be rebalanced before the simulation starts -refine_fn_c = @cfunction(refine_fn, Cint, (Ptr{Trixi.p8est_t}, Ptr{Trixi.p4est_topidx_t}, Ptr{Trixi.p8est_quadrant_t})) +refine_fn_c = @cfunction(refine_fn, Cint, + (Ptr{Trixi.p8est_t}, Ptr{Trixi.p4est_topidx_t}, + Ptr{Trixi.p8est_quadrant_t})) Trixi.refine_p4est!(mesh.p4est, true, refine_fn_c, C_NULL) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test, - boundary_conditions=boundary_conditions) - + source_terms = source_terms_convergence_test, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -88,27 +92,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.6) +stepsize_callback = StepsizeCallback(cfl = 0.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/p4est_3d_dgsem/elixir_euler_source_terms_nonperiodic.jl b/examples/p4est_3d_dgsem/elixir_euler_source_terms_nonperiodic.jl index cd796c33e47..fc5e4da3ceb 100644 --- a/examples/p4est_3d_dgsem/elixir_euler_source_terms_nonperiodic.jl +++ b/examples/p4est_3d_dgsem/elixir_euler_source_terms_nonperiodic.jl @@ -10,31 +10,28 @@ equations = CompressibleEulerEquations3D(1.4) initial_condition = initial_condition_convergence_test boundary_condition = BoundaryConditionDirichlet(initial_condition) -boundary_conditions = Dict( - :x_neg => boundary_condition, - :x_pos => boundary_condition, - :y_neg => boundary_condition, - :y_pos => boundary_condition, - :z_neg => boundary_condition, - :z_pos => boundary_condition -) - -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralWeakForm()) +boundary_conditions = Dict(:x_neg => boundary_condition, + :x_pos => boundary_condition, + :y_neg => boundary_condition, + :y_pos => boundary_condition, + :z_neg => boundary_condition, + :z_pos => boundary_condition) + +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralWeakForm()) coordinates_min = (0.0, 0.0, 0.0) coordinates_max = (2.0, 2.0, 2.0) trees_per_dimension = (2, 2, 2) -mesh = P4estMesh(trees_per_dimension, polydeg=1, - coordinates_min=coordinates_min, coordinates_max=coordinates_max, - periodicity=false, initial_refinement_level=1) +mesh = P4estMesh(trees_per_dimension, polydeg = 1, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + periodicity = false, initial_refinement_level = 1) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test, - boundary_conditions=boundary_conditions) - + source_terms = source_terms_convergence_test, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -45,27 +42,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.6) +stepsize_callback = StepsizeCallback(cfl = 0.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/p4est_3d_dgsem/elixir_euler_source_terms_nonperiodic_hohqmesh.jl b/examples/p4est_3d_dgsem/elixir_euler_source_terms_nonperiodic_hohqmesh.jl index ff101bea8aa..0fa3a28fe8b 100644 --- a/examples/p4est_3d_dgsem/elixir_euler_source_terms_nonperiodic_hohqmesh.jl +++ b/examples/p4est_3d_dgsem/elixir_euler_source_terms_nonperiodic_hohqmesh.jl @@ -11,25 +11,25 @@ equations = CompressibleEulerEquations3D(1.4) initial_condition = initial_condition_convergence_test boundary_condition = BoundaryConditionDirichlet(initial_condition) -boundary_conditions = Dict( :Bottom => boundary_condition, - :Top => boundary_condition, - :Circle => boundary_condition, - :Cut => boundary_condition ) +boundary_conditions = Dict(:Bottom => boundary_condition, + :Top => boundary_condition, + :Circle => boundary_condition, + :Cut => boundary_condition) -solver = DGSEM(polydeg=4, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 4, surface_flux = flux_lax_friedrichs) # Unstructured 3D half circle mesh from HOHQMesh default_mesh_file = joinpath(@__DIR__, "abaqus_half_circle_3d.inp") -isfile(default_mesh_file) || download("https://gist.githubusercontent.com/andrewwinters5000/11461efbfb02c42e06aca338b3d0b645/raw/81deeb1ebc4945952c30af5bb75fe222a18d975c/abaqus_half_circle_3d.inp", - default_mesh_file) +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/11461efbfb02c42e06aca338b3d0b645/raw/81deeb1ebc4945952c30af5bb75fe222a18d975c/abaqus_half_circle_3d.inp", + default_mesh_file) mesh_file = default_mesh_file -mesh = P4estMesh{3}(mesh_file, initial_refinement_level=0) +mesh = P4estMesh{3}(mesh_file, initial_refinement_level = 0) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test, - boundary_conditions=boundary_conditions) - + source_terms = source_terms_convergence_test, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -40,17 +40,17 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=50, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 50, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -58,12 +58,11 @@ callbacks = CallbackSet(summary_callback, save_solution, stepsize_callback); - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/p4est_3d_dgsem/elixir_mhd_alfven_wave_nonconforming.jl b/examples/p4est_3d_dgsem/elixir_mhd_alfven_wave_nonconforming.jl index 8fe96ae3dec..12ddf9e4a5f 100644 --- a/examples/p4est_3d_dgsem/elixir_mhd_alfven_wave_nonconforming.jl +++ b/examples/p4est_3d_dgsem/elixir_mhd_alfven_wave_nonconforming.jl @@ -5,40 +5,45 @@ using Trixi ############################################################################### # semidiscretization of the compressible ideal GLM-MHD equations -equations = IdealGlmMhdEquations3D(5/3) +equations = IdealGlmMhdEquations3D(5 / 3) initial_condition = initial_condition_convergence_test volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) -solver = DGSEM(polydeg=3, surface_flux=(flux_hll, flux_nonconservative_powell), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, + surface_flux = (flux_hlle, + flux_nonconservative_powell), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-1.0, -1.0, -1.0) -coordinates_max = ( 1.0, 1.0, 1.0) +coordinates_max = (1.0, 1.0, 1.0) # Create P4estMesh with 2 x 2 x 2 trees trees_per_dimension = (2, 2, 2) mesh = P4estMesh(trees_per_dimension, - polydeg=3, initial_refinement_level=2, - coordinates_min=coordinates_min, coordinates_max=coordinates_max, - periodicity=true) + polydeg = 3, initial_refinement_level = 2, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + periodicity = true) # OBS! Workaround to add a refinement patch after mesh is constructed # Refine bottom left quadrant of each tree to level 4 function refine_fn(p8est, which_tree, quadrant) - quadrant_obj = unsafe_load(quadrant) - if quadrant_obj.x == 0 && quadrant_obj.y == 0 && quadrant_obj.z == 0 && quadrant_obj.level < 4 - # return true (refine) - return Cint(1) - else - # return false (don't refine) - return Cint(0) - end + quadrant_obj = unsafe_load(quadrant) + if quadrant_obj.x == 0 && quadrant_obj.y == 0 && quadrant_obj.z == 0 && + quadrant_obj.level < 4 + # return true (refine) + return Cint(1) + else + # return false (don't refine) + return Cint(0) + end end # Refine recursively until each bottom left quadrant of a tree has level 4 # The mesh will be rebalanced before the simulation starts -refine_fn_c = @cfunction(refine_fn, Cint, (Ptr{Trixi.p8est_t}, Ptr{Trixi.p4est_topidx_t}, Ptr{Trixi.p8est_quadrant_t})) +refine_fn_c = @cfunction(refine_fn, Cint, + (Ptr{Trixi.p8est_t}, Ptr{Trixi.p4est_topidx_t}, + Ptr{Trixi.p8est_quadrant_t})) Trixi.refine_p4est!(mesh.p4est, true, refine_fn_c, C_NULL) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -52,18 +57,18 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) cfl = 1.0 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -71,11 +76,10 @@ callbacks = CallbackSet(summary_callback, stepsize_callback, glm_speed_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/p4est_3d_dgsem/elixir_mhd_shockcapturing_amr.jl b/examples/p4est_3d_dgsem/elixir_mhd_shockcapturing_amr.jl index fc95d427abb..3941a40b2e4 100644 --- a/examples/p4est_3d_dgsem/elixir_mhd_shockcapturing_amr.jl +++ b/examples/p4est_3d_dgsem/elixir_mhd_shockcapturing_amr.jl @@ -17,71 +17,74 @@ Weak magnetic blast wave setup taken from Section 6.1 of the paper: [doi: 10.1016/j.jcp.2021.110580](https://doi.org/10.1016/j.jcp.2021.110580) """ function initial_condition_blast_wave(x, t, equations::IdealGlmMhdEquations3D) - # Center of the blast wave is selected for the domain [0, 3]^3 - inicenter = (1.5, 1.5, 1.5) - x_norm = x[1] - inicenter[1] - y_norm = x[2] - inicenter[2] - z_norm = x[3] - inicenter[3] - r = sqrt(x_norm^2 + y_norm^2 + z_norm^2) - - delta_0 = 0.1 - r_0 = 0.3 - lambda = exp(5.0 / delta_0 * (r - r_0)) - - prim_inner = SVector(1.2, 0.1, 0.0, 0.1, 0.9, 1.0, 1.0, 1.0, 0.0) - prim_outer = SVector(1.2, 0.2, -0.4, 0.2, 0.3, 1.0, 1.0, 1.0, 0.0) - prim_vars = (prim_inner + lambda * prim_outer) / (1.0 + lambda) - - return prim2cons(prim_vars, equations) + # Center of the blast wave is selected for the domain [0, 3]^3 + inicenter = (1.5, 1.5, 1.5) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + z_norm = x[3] - inicenter[3] + r = sqrt(x_norm^2 + y_norm^2 + z_norm^2) + + delta_0 = 0.1 + r_0 = 0.3 + lambda = exp(5.0 / delta_0 * (r - r_0)) + + prim_inner = SVector(1.2, 0.1, 0.0, 0.1, 0.9, 1.0, 1.0, 1.0, 0.0) + prim_outer = SVector(1.2, 0.2, -0.4, 0.2, 0.3, 1.0, 1.0, 1.0, 0.0) + prim_vars = (prim_inner + lambda * prim_outer) / (1.0 + lambda) + + return prim2cons(prim_vars, equations) end initial_condition = initial_condition_blast_wave surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell) -volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) +volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) - -solver = DGSEM(polydeg=polydeg, surface_flux=surface_flux, volume_integral=volume_integral) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) +solver = DGSEM(polydeg = polydeg, surface_flux = surface_flux, + volume_integral = volume_integral) # Mapping as described in https://arxiv.org/abs/2012.12040 but with slightly less warping. # The mapping will be interpolated at tree level, and then refined without changing # the geometry interpolant. function mapping(xi_, eta_, zeta_) - # Transform input variables between -1 and 1 onto [0,3] - xi = 1.5 * xi_ + 1.5 - eta = 1.5 * eta_ + 1.5 - zeta = 1.5 * zeta_ + 1.5 - - y = eta + 3/11 * (cos(1.5 * pi * (2 * xi - 3)/3) * - cos(0.5 * pi * (2 * eta - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - x = xi + 3/11 * (cos(0.5 * pi * (2 * xi - 3)/3) * - cos(2 * pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - z = zeta + 3/11 * (cos(0.5 * pi * (2 * x - 3)/3) * - cos(pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - return SVector(x, y, z) + # Transform input variables between -1 and 1 onto [0,3] + xi = 1.5 * xi_ + 1.5 + eta = 1.5 * eta_ + 1.5 + zeta = 1.5 * zeta_ + 1.5 + + y = eta + + 3 / 11 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + x = xi + + 3 / 11 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + z = zeta + + 3 / 11 * (cos(0.5 * pi * (2 * x - 3) / 3) * + cos(pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + return SVector(x, y, z) end trees_per_dimension = (2, 2, 2) mesh = P4estMesh(trees_per_dimension, - polydeg=3, - mapping=mapping, - initial_refinement_level=2, - periodicity=true) + polydeg = 3, + mapping = mapping, + initial_refinement_level = 2, + periodicity = true) # create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -95,24 +98,24 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) amr_indicator = IndicatorLöhner(semi, - variable=density_pressure) + variable = density_pressure) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=2, - max_level =4, max_threshold=0.15) + base_level = 2, + max_level = 4, max_threshold = 0.15) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) cfl = 1.4 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -121,11 +124,10 @@ callbacks = CallbackSet(summary_callback, stepsize_callback, glm_speed_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/p4est_3d_dgsem/elixir_navierstokes_convergence.jl b/examples/p4est_3d_dgsem/elixir_navierstokes_convergence.jl index c426fe95f5b..c640b255b05 100644 --- a/examples/p4est_3d_dgsem/elixir_navierstokes_convergence.jl +++ b/examples/p4est_3d_dgsem/elixir_navierstokes_convergence.jl @@ -8,237 +8,241 @@ prandtl_number() = 0.72 mu() = 0.01 equations = CompressibleEulerEquations3D(1.4) -equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu=mu(), Prandtl=prandtl_number(), - gradient_variables=GradientVariablesPrimitive()) +equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu = mu(), + Prandtl = prandtl_number(), + gradient_variables = GradientVariablesPrimitive()) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralWeakForm()) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralWeakForm()) coordinates_min = (-1.0, -1.0, -1.0) # minimum coordinates (min(x), min(y), min(z)) -coordinates_max = ( 1.0, 1.0, 1.0) # maximum coordinates (max(x), max(y), max(z)) +coordinates_max = (1.0, 1.0, 1.0) # maximum coordinates (max(x), max(y), max(z)) trees_per_dimension = (2, 2, 2) -mesh = P4estMesh(trees_per_dimension, polydeg=3, - coordinates_min=coordinates_min, coordinates_max=coordinates_max, - periodicity=(true, false, true), initial_refinement_level=2) +mesh = P4estMesh(trees_per_dimension, polydeg = 3, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + periodicity = (true, false, true), initial_refinement_level = 2) # Note: the initial condition cannot be specialized to `CompressibleNavierStokesDiffusion3D` # since it is called by both the parabolic solver (which passes in `CompressibleNavierStokesDiffusion3D`) # and by the initial condition (which passes in `CompressibleEulerEquations3D`). # This convergence test setup was originally derived by Andrew Winters (@andrewwinters5000) function initial_condition_navier_stokes_convergence_test(x, t, equations) - # Constants. OBS! Must match those in `source_terms_navier_stokes_convergence_test` - c = 2.0 - A1 = 0.5 - A2 = 1.0 - A3 = 0.5 - - # Convenience values for trig. functions - pi_x = pi * x[1] - pi_y = pi * x[2] - pi_z = pi * x[3] - pi_t = pi * t - - rho = c + A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) - v1 = A2 * sin(pi_x) * log(x[2] + 2.0) * (1.0 - exp(-A3 * (x[2] - 1.0))) * sin(pi_z) * cos(pi_t) - v2 = v1 - v3 = v1 - p = rho^2 - - return prim2cons(SVector(rho, v1, v2, v3, p), equations) + # Constants. OBS! Must match those in `source_terms_navier_stokes_convergence_test` + c = 2.0 + A1 = 0.5 + A2 = 1.0 + A3 = 0.5 + + # Convenience values for trig. functions + pi_x = pi * x[1] + pi_y = pi * x[2] + pi_z = pi * x[3] + pi_t = pi * t + + rho = c + A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) + v1 = A2 * sin(pi_x) * log(x[2] + 2.0) * (1.0 - exp(-A3 * (x[2] - 1.0))) * sin(pi_z) * + cos(pi_t) + v2 = v1 + v3 = v1 + p = rho^2 + + return prim2cons(SVector(rho, v1, v2, v3, p), equations) end @inline function source_terms_navier_stokes_convergence_test(u, x, t, equations) - # TODO: parabolic - # we currently need to hardcode these parameters until we fix the "combined equation" issue - # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 - inv_gamma_minus_one = inv(equations.gamma - 1) - Pr = prandtl_number() - mu_ = mu() - - # Constants. OBS! Must match those in `initial_condition_navier_stokes_convergence_test` - c = 2.0 - A1 = 0.5 - A2 = 1.0 - A3 = 0.5 - - # Convenience values for trig. functions - pi_x = pi * x[1] - pi_y = pi * x[2] - pi_z = pi * x[3] - pi_t = pi * t - - # Define auxiliary functions for the strange function of the y variable - # to make expressions easier to read - g = log(x[2] + 2.0) * (1.0 - exp(-A3 * (x[2] - 1.0))) - g_y = ( A3 * log(x[2] + 2.0) * exp(-A3 * (x[2] - 1.0)) - + (1.0 - exp(-A3 * (x[2] - 1.0))) / (x[2] + 2.0) ) - g_yy = ( 2.0 * A3 * exp(-A3 * (x[2] - 1.0)) / (x[2] + 2.0) - - (1.0 - exp(-A3 * (x[2] - 1.0))) / ((x[2] + 2.0)^2) - - A3^2 * log(x[2] + 2.0) * exp(-A3 * (x[2] - 1.0)) ) - - # Density and its derivatives - rho = c + A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) - rho_t = -pi * A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * sin(pi_t) - rho_x = pi * A1 * cos(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) - rho_y = -pi * A1 * sin(pi_x) * sin(pi_y) * sin(pi_z) * cos(pi_t) - rho_z = pi * A1 * sin(pi_x) * cos(pi_y) * cos(pi_z) * cos(pi_t) - rho_xx = -pi^2 * (rho - c) - rho_yy = -pi^2 * (rho - c) - rho_zz = -pi^2 * (rho - c) - - # Velocities and their derivatives - # v1 terms - v1 = A2 * sin(pi_x) * g * sin(pi_z) * cos(pi_t) - v1_t = -pi * A2 * sin(pi_x) * g * sin(pi_z) * sin(pi_t) - v1_x = pi * A2 * cos(pi_x) * g * sin(pi_z) * cos(pi_t) - v1_y = A2 * sin(pi_x) * g_y * sin(pi_z) * cos(pi_t) - v1_z = pi * A2 * sin(pi_x) * g * cos(pi_z) * cos(pi_t) - v1_xx = -pi^2 * v1 - v1_yy = A2 * sin(pi_x) * g_yy * sin(pi_z) * cos(pi_t) - v1_zz = -pi^2 * v1 - v1_xy = pi * A2 * cos(pi_x) * g_y * sin(pi_z) * cos(pi_t) - v1_xz = pi^2 * A2 * cos(pi_x) * g * cos(pi_z) * cos(pi_t) - v1_yz = pi * A2 * sin(pi_x) * g_y * cos(pi_z) * cos(pi_t) - # v2 terms (simplifies from ansatz) - v2 = v1 - v2_t = v1_t - v2_x = v1_x - v2_y = v1_y - v2_z = v1_z - v2_xx = v1_xx - v2_yy = v1_yy - v2_zz = v1_zz - v2_xy = v1_xy - v2_yz = v1_yz - # v3 terms (simplifies from ansatz) - v3 = v1 - v3_t = v1_t - v3_x = v1_x - v3_y = v1_y - v3_z = v1_z - v3_xx = v1_xx - v3_yy = v1_yy - v3_zz = v1_zz - v3_xz = v1_xz - v3_yz = v1_yz - - # Pressure and its derivatives - p = rho^2 - p_t = 2.0 * rho * rho_t - p_x = 2.0 * rho * rho_x - p_y = 2.0 * rho * rho_y - p_z = 2.0 * rho * rho_z - - # Total energy and its derivatives; simiplifies from ansatz that v2 = v1 and v3 = v1 - E = p * inv_gamma_minus_one + 1.5 * rho * v1^2 - E_t = p_t * inv_gamma_minus_one + 1.5 * rho_t * v1^2 + 3.0 * rho * v1 * v1_t - E_x = p_x * inv_gamma_minus_one + 1.5 * rho_x * v1^2 + 3.0 * rho * v1 * v1_x - E_y = p_y * inv_gamma_minus_one + 1.5 * rho_y * v1^2 + 3.0 * rho * v1 * v1_y - E_z = p_z * inv_gamma_minus_one + 1.5 * rho_z * v1^2 + 3.0 * rho * v1 * v1_z - - # Divergence of Fick's law ∇⋅∇q = kappa ∇⋅∇T; simplifies because p = rho², so T = p/rho = rho - kappa = equations.gamma * inv_gamma_minus_one / Pr - q_xx = kappa * rho_xx # kappa T_xx - q_yy = kappa * rho_yy # kappa T_yy - q_zz = kappa * rho_zz # kappa T_zz - - # Stress tensor and its derivatives (exploit symmetry) - tau11 = 4.0 / 3.0 * v1_x - 2.0 / 3.0 * (v2_y + v3_z) - tau12 = v1_y + v2_x - tau13 = v1_z + v3_x - tau22 = 4.0 / 3.0 * v2_y - 2.0 / 3.0 * (v1_x + v3_z) - tau23 = v2_z + v3_y - tau33 = 4.0 / 3.0 * v3_z - 2.0 / 3.0 * (v1_x + v2_y) - - tau11_x = 4.0 / 3.0 * v1_xx - 2.0 / 3.0 * (v2_xy + v3_xz) - tau12_x = v1_xy + v2_xx - tau13_x = v1_xz + v3_xx - - tau12_y = v1_yy + v2_xy - tau22_y = 4.0 / 3.0 * v2_yy - 2.0 / 3.0 * (v1_xy + v3_yz) - tau23_y = v2_yz + v3_yy - - tau13_z = v1_zz + v3_xz - tau23_z = v2_zz + v3_yz - tau33_z = 4.0 / 3.0 * v3_zz - 2.0 / 3.0 * (v1_xz + v2_yz) - - # Compute the source terms - # Density equation - du1 = ( rho_t + rho_x * v1 + rho * v1_x - + rho_y * v2 + rho * v2_y - + rho_z * v3 + rho * v3_z ) - # x-momentum equation - du2 = ( rho_t * v1 + rho * v1_t + p_x + rho_x * v1^2 - + 2.0 * rho * v1 * v1_x - + rho_y * v1 * v2 - + rho * v1_y * v2 - + rho * v1 * v2_y - + rho_z * v1 * v3 - + rho * v1_z * v3 - + rho * v1 * v3_z - - mu_ * (tau11_x + tau12_y + tau13_z) ) - # y-momentum equation - du3 = ( rho_t * v2 + rho * v2_t + p_y + rho_x * v1 * v2 - + rho * v1_x * v2 - + rho * v1 * v2_x - + rho_y * v2^2 - + 2.0 * rho * v2 * v2_y - + rho_z * v2 * v3 - + rho * v2_z * v3 - + rho * v2 * v3_z - - mu_ * (tau12_x + tau22_y + tau23_z) ) - # z-momentum equation - du4 = ( rho_t * v3 + rho * v3_t + p_z + rho_x * v1 * v3 - + rho * v1_x * v3 - + rho * v1 * v3_x - + rho_y * v2 * v3 - + rho * v2_y * v3 - + rho * v2 * v3_y - + rho_z * v3^2 - + 2.0 * rho * v3 * v3_z - - mu_ * (tau13_x + tau23_y + tau33_z) ) - # Total energy equation - du5 = ( E_t + v1_x * (E + p) + v1 * (E_x + p_x) - + v2_y * (E + p) + v2 * (E_y + p_y) - + v3_z * (E + p) + v3 * (E_z + p_z) - # stress tensor and temperature gradient from x-direction - - mu_ * ( q_xx + v1_x * tau11 + v2_x * tau12 + v3_x * tau13 - + v1 * tau11_x + v2 * tau12_x + v3 * tau13_x) - # stress tensor and temperature gradient terms from y-direction - - mu_ * ( q_yy + v1_y * tau12 + v2_y * tau22 + v3_y * tau23 - + v1 * tau12_y + v2 * tau22_y + v3 * tau23_y) - # stress tensor and temperature gradient terms from z-direction - - mu_ * ( q_zz + v1_z * tau13 + v2_z * tau23 + v3_z * tau33 - + v1 * tau13_z + v2 * tau23_z + v3 * tau33_z) ) - - return SVector(du1, du2, du3, du4, du5) + # TODO: parabolic + # we currently need to hardcode these parameters until we fix the "combined equation" issue + # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 + inv_gamma_minus_one = inv(equations.gamma - 1) + Pr = prandtl_number() + mu_ = mu() + + # Constants. OBS! Must match those in `initial_condition_navier_stokes_convergence_test` + c = 2.0 + A1 = 0.5 + A2 = 1.0 + A3 = 0.5 + + # Convenience values for trig. functions + pi_x = pi * x[1] + pi_y = pi * x[2] + pi_z = pi * x[3] + pi_t = pi * t + + # Define auxiliary functions for the strange function of the y variable + # to make expressions easier to read + g = log(x[2] + 2.0) * (1.0 - exp(-A3 * (x[2] - 1.0))) + g_y = (A3 * log(x[2] + 2.0) * exp(-A3 * (x[2] - 1.0)) + + (1.0 - exp(-A3 * (x[2] - 1.0))) / (x[2] + 2.0)) + g_yy = (2.0 * A3 * exp(-A3 * (x[2] - 1.0)) / (x[2] + 2.0) - + (1.0 - exp(-A3 * (x[2] - 1.0))) / ((x[2] + 2.0)^2) - + A3^2 * log(x[2] + 2.0) * exp(-A3 * (x[2] - 1.0))) + + # Density and its derivatives + rho = c + A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) + rho_t = -pi * A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * sin(pi_t) + rho_x = pi * A1 * cos(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) + rho_y = -pi * A1 * sin(pi_x) * sin(pi_y) * sin(pi_z) * cos(pi_t) + rho_z = pi * A1 * sin(pi_x) * cos(pi_y) * cos(pi_z) * cos(pi_t) + rho_xx = -pi^2 * (rho - c) + rho_yy = -pi^2 * (rho - c) + rho_zz = -pi^2 * (rho - c) + + # Velocities and their derivatives + # v1 terms + v1 = A2 * sin(pi_x) * g * sin(pi_z) * cos(pi_t) + v1_t = -pi * A2 * sin(pi_x) * g * sin(pi_z) * sin(pi_t) + v1_x = pi * A2 * cos(pi_x) * g * sin(pi_z) * cos(pi_t) + v1_y = A2 * sin(pi_x) * g_y * sin(pi_z) * cos(pi_t) + v1_z = pi * A2 * sin(pi_x) * g * cos(pi_z) * cos(pi_t) + v1_xx = -pi^2 * v1 + v1_yy = A2 * sin(pi_x) * g_yy * sin(pi_z) * cos(pi_t) + v1_zz = -pi^2 * v1 + v1_xy = pi * A2 * cos(pi_x) * g_y * sin(pi_z) * cos(pi_t) + v1_xz = pi^2 * A2 * cos(pi_x) * g * cos(pi_z) * cos(pi_t) + v1_yz = pi * A2 * sin(pi_x) * g_y * cos(pi_z) * cos(pi_t) + # v2 terms (simplifies from ansatz) + v2 = v1 + v2_t = v1_t + v2_x = v1_x + v2_y = v1_y + v2_z = v1_z + v2_xx = v1_xx + v2_yy = v1_yy + v2_zz = v1_zz + v2_xy = v1_xy + v2_yz = v1_yz + # v3 terms (simplifies from ansatz) + v3 = v1 + v3_t = v1_t + v3_x = v1_x + v3_y = v1_y + v3_z = v1_z + v3_xx = v1_xx + v3_yy = v1_yy + v3_zz = v1_zz + v3_xz = v1_xz + v3_yz = v1_yz + + # Pressure and its derivatives + p = rho^2 + p_t = 2.0 * rho * rho_t + p_x = 2.0 * rho * rho_x + p_y = 2.0 * rho * rho_y + p_z = 2.0 * rho * rho_z + + # Total energy and its derivatives; simiplifies from ansatz that v2 = v1 and v3 = v1 + E = p * inv_gamma_minus_one + 1.5 * rho * v1^2 + E_t = p_t * inv_gamma_minus_one + 1.5 * rho_t * v1^2 + 3.0 * rho * v1 * v1_t + E_x = p_x * inv_gamma_minus_one + 1.5 * rho_x * v1^2 + 3.0 * rho * v1 * v1_x + E_y = p_y * inv_gamma_minus_one + 1.5 * rho_y * v1^2 + 3.0 * rho * v1 * v1_y + E_z = p_z * inv_gamma_minus_one + 1.5 * rho_z * v1^2 + 3.0 * rho * v1 * v1_z + + # Divergence of Fick's law ∇⋅∇q = kappa ∇⋅∇T; simplifies because p = rho², so T = p/rho = rho + kappa = equations.gamma * inv_gamma_minus_one / Pr + q_xx = kappa * rho_xx # kappa T_xx + q_yy = kappa * rho_yy # kappa T_yy + q_zz = kappa * rho_zz # kappa T_zz + + # Stress tensor and its derivatives (exploit symmetry) + tau11 = 4.0 / 3.0 * v1_x - 2.0 / 3.0 * (v2_y + v3_z) + tau12 = v1_y + v2_x + tau13 = v1_z + v3_x + tau22 = 4.0 / 3.0 * v2_y - 2.0 / 3.0 * (v1_x + v3_z) + tau23 = v2_z + v3_y + tau33 = 4.0 / 3.0 * v3_z - 2.0 / 3.0 * (v1_x + v2_y) + + tau11_x = 4.0 / 3.0 * v1_xx - 2.0 / 3.0 * (v2_xy + v3_xz) + tau12_x = v1_xy + v2_xx + tau13_x = v1_xz + v3_xx + + tau12_y = v1_yy + v2_xy + tau22_y = 4.0 / 3.0 * v2_yy - 2.0 / 3.0 * (v1_xy + v3_yz) + tau23_y = v2_yz + v3_yy + + tau13_z = v1_zz + v3_xz + tau23_z = v2_zz + v3_yz + tau33_z = 4.0 / 3.0 * v3_zz - 2.0 / 3.0 * (v1_xz + v2_yz) + + # Compute the source terms + # Density equation + du1 = (rho_t + rho_x * v1 + rho * v1_x + + rho_y * v2 + rho * v2_y + + rho_z * v3 + rho * v3_z) + # x-momentum equation + du2 = (rho_t * v1 + rho * v1_t + p_x + rho_x * v1^2 + + 2.0 * rho * v1 * v1_x + + rho_y * v1 * v2 + + rho * v1_y * v2 + + rho * v1 * v2_y + + rho_z * v1 * v3 + + rho * v1_z * v3 + + rho * v1 * v3_z - + mu_ * (tau11_x + tau12_y + tau13_z)) + # y-momentum equation + du3 = (rho_t * v2 + rho * v2_t + p_y + rho_x * v1 * v2 + + rho * v1_x * v2 + + rho * v1 * v2_x + + rho_y * v2^2 + + 2.0 * rho * v2 * v2_y + + rho_z * v2 * v3 + + rho * v2_z * v3 + + rho * v2 * v3_z - + mu_ * (tau12_x + tau22_y + tau23_z)) + # z-momentum equation + du4 = (rho_t * v3 + rho * v3_t + p_z + rho_x * v1 * v3 + + rho * v1_x * v3 + + rho * v1 * v3_x + + rho_y * v2 * v3 + + rho * v2_y * v3 + + rho * v2 * v3_y + + rho_z * v3^2 + + 2.0 * rho * v3 * v3_z - + mu_ * (tau13_x + tau23_y + tau33_z)) + # Total energy equation + du5 = (E_t + v1_x * (E + p) + v1 * (E_x + p_x) + + v2_y * (E + p) + v2 * (E_y + p_y) + + v3_z * (E + p) + v3 * (E_z + p_z) - + # stress tensor and temperature gradient from x-direction + mu_ * (q_xx + v1_x * tau11 + v2_x * tau12 + v3_x * tau13 + + v1 * tau11_x + v2 * tau12_x + v3 * tau13_x) - + # stress tensor and temperature gradient terms from y-direction + mu_ * (q_yy + v1_y * tau12 + v2_y * tau22 + v3_y * tau23 + + v1 * tau12_y + v2 * tau22_y + v3 * tau23_y) - + # stress tensor and temperature gradient terms from z-direction + mu_ * (q_zz + v1_z * tau13 + v2_z * tau23 + v3_z * tau33 + + v1 * tau13_z + v2 * tau23_z + v3 * tau33_z)) + + return SVector(du1, du2, du3, du4, du5) end initial_condition = initial_condition_navier_stokes_convergence_test # BC types -velocity_bc_top_bottom = NoSlip((x, t, equations) -> initial_condition_navier_stokes_convergence_test(x, t, equations)[2:4]) +velocity_bc_top_bottom = NoSlip() do x, t, equations + u = initial_condition_navier_stokes_convergence_test(x, t, equations) + return SVector(u[2], u[3], u[4]) +end heat_bc_top_bottom = Adiabatic((x, t, equations) -> 0.0) -boundary_condition_top_bottom = BoundaryConditionNavierStokesWall(velocity_bc_top_bottom, heat_bc_top_bottom) +boundary_condition_top_bottom = BoundaryConditionNavierStokesWall(velocity_bc_top_bottom, + heat_bc_top_bottom) # define inviscid boundary conditions -boundary_conditions = Dict( - :y_neg => boundary_condition_slip_wall, - :y_pos => boundary_condition_slip_wall - ) +boundary_conditions = Dict(:y_neg => boundary_condition_slip_wall, + :y_pos => boundary_condition_slip_wall) # define viscous boundary conditions -boundary_conditions_parabolic = Dict( - :y_neg => boundary_condition_top_bottom, - :y_pos => boundary_condition_top_bottom - ) +boundary_conditions_parabolic = Dict(:y_neg => boundary_condition_top_bottom, + :y_pos => boundary_condition_top_bottom) -semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver; - boundary_conditions=(boundary_conditions, boundary_conditions_parabolic), - source_terms=source_terms_navier_stokes_convergence_test) +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, solver; + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic), + source_terms = source_terms_navier_stokes_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -248,16 +252,15 @@ tspan = (0.0, 0.2) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) ############################################################################### # run the simulation time_int_tol = 1e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, dt = 1e-5, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, dt = 1e-5, + ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary - diff --git a/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex.jl b/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex.jl index c5b9ccf2e38..d785013f5a9 100644 --- a/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex.jl +++ b/examples/p4est_3d_dgsem/elixir_navierstokes_taylor_green_vortex.jl @@ -10,42 +10,45 @@ prandtl_number() = 0.72 mu() = 6.25e-4 # equivalent to Re = 1600 equations = CompressibleEulerEquations3D(1.4) -equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu=mu(), - Prandtl=prandtl_number()) +equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu = mu(), + Prandtl = prandtl_number()) """ initial_condition_taylor_green_vortex(x, t, equations::CompressibleEulerEquations3D) The classical inviscid Taylor-Green vortex. """ -function initial_condition_taylor_green_vortex(x, t, equations::CompressibleEulerEquations3D) - A = 1.0 # magnitude of speed - Ms = 0.1 # maximum Mach number - - rho = 1.0 - v1 = A * sin(x[1]) * cos(x[2]) * cos(x[3]) - v2 = -A * cos(x[1]) * sin(x[2]) * cos(x[3]) - v3 = 0.0 - p = (A / Ms)^2 * rho / equations.gamma # scaling to get Ms - p = p + 1.0/16.0 * A^2 * rho * (cos(2*x[1])*cos(2*x[3]) + 2*cos(2*x[2]) + 2*cos(2*x[1]) + cos(2*x[2])*cos(2*x[3])) - - return prim2cons(SVector(rho, v1, v2, v3, p), equations) +function initial_condition_taylor_green_vortex(x, t, + equations::CompressibleEulerEquations3D) + A = 1.0 # magnitude of speed + Ms = 0.1 # maximum Mach number + + rho = 1.0 + v1 = A * sin(x[1]) * cos(x[2]) * cos(x[3]) + v2 = -A * cos(x[1]) * sin(x[2]) * cos(x[3]) + v3 = 0.0 + p = (A / Ms)^2 * rho / equations.gamma # scaling to get Ms + p = p + + 1.0 / 16.0 * A^2 * rho * + (cos(2 * x[1]) * cos(2 * x[3]) + 2 * cos(2 * x[2]) + 2 * cos(2 * x[1]) + + cos(2 * x[2]) * cos(2 * x[3])) + + return prim2cons(SVector(rho, v1, v2, v3, p), equations) end initial_condition = initial_condition_taylor_green_vortex volume_flux = flux_ranocha -solver = DGSEM(polydeg=3, surface_flux=flux_hll, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_hll, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-1.0, -1.0, -1.0) .* pi -coordinates_max = ( 1.0, 1.0, 1.0) .* pi +coordinates_max = (1.0, 1.0, 1.0) .* pi trees_per_dimension = (2, 2, 2) -mesh = P4estMesh(trees_per_dimension, polydeg=3, - coordinates_min=coordinates_min, coordinates_max=coordinates_max, - periodicity=(true, true, true), initial_refinement_level=2) - +mesh = P4estMesh(trees_per_dimension, polydeg = 3, + coordinates_min = coordinates_min, coordinates_max = coordinates_max, + periodicity = (true, true, true), initial_refinement_level = 2) semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver) @@ -59,24 +62,25 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 50 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=true, - extra_analysis_integrals=(energy_kinetic, - energy_internal, - enstrophy)) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) -alive_callback = AliveCallback(analysis_interval=analysis_interval,) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true, + extra_analysis_integrals = (energy_kinetic, + energy_internal, + enstrophy)) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) +alive_callback = AliveCallback(analysis_interval = analysis_interval) callbacks = CallbackSet(summary_callback, analysis_callback, - alive_callback,save_solution) + alive_callback, save_solution) ############################################################################### # run the simulation time_int_tol = 1e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary diff --git a/examples/paper_self_gravitating_gas_dynamics/elixir_euler_convergence.jl b/examples/paper_self_gravitating_gas_dynamics/elixir_euler_convergence.jl index 316f36adc9b..aabfce0f66b 100644 --- a/examples/paper_self_gravitating_gas_dynamics/elixir_euler_convergence.jl +++ b/examples/paper_self_gravitating_gas_dynamics/elixir_euler_convergence.jl @@ -8,18 +8,16 @@ equations = CompressibleEulerEquations2D(2.0) initial_condition = initial_condition_eoc_test_coupled_euler_gravity -solver = DGSEM(polydeg=3, surface_flux=flux_hll) +solver = DGSEM(polydeg = 3, surface_flux = flux_hll) coordinates_min = (0.0, 0.0) coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=10_000) - + initial_refinement_level = 2, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_eoc_test_euler) - + source_terms = source_terms_eoc_test_euler) ############################################################################### # ODE solvers, callbacks etc. @@ -29,26 +27,25 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) analysis_interval = 100 -alive_callback = AliveCallback(analysis_interval=analysis_interval) -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) callbacks = CallbackSet(summary_callback, stepsize_callback, save_solution, analysis_callback, alive_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/paper_self_gravitating_gas_dynamics/elixir_eulergravity_convergence.jl b/examples/paper_self_gravitating_gas_dynamics/elixir_eulergravity_convergence.jl index f2693c89583..ce1d2cd05bd 100644 --- a/examples/paper_self_gravitating_gas_dynamics/elixir_eulergravity_convergence.jl +++ b/examples/paper_self_gravitating_gas_dynamics/elixir_eulergravity_convergence.jl @@ -2,10 +2,8 @@ using OrdinaryDiffEq using Trixi - initial_condition = initial_condition_eoc_test_coupled_euler_gravity - ############################################################################### # semidiscretization of the compressible Euler equations gamma = 2.0 @@ -17,12 +15,12 @@ solver_euler = DGSEM(polydeg, flux_hll) coordinates_min = (0.0, 0.0) coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=10_000) - -semi_euler = SemidiscretizationHyperbolic(mesh, equations_euler, initial_condition, solver_euler, - source_terms=source_terms_eoc_test_coupled_euler_gravity) + initial_refinement_level = 2, + n_cells_max = 10_000) +semi_euler = SemidiscretizationHyperbolic(mesh, equations_euler, initial_condition, + solver_euler, + source_terms = source_terms_eoc_test_coupled_euler_gravity) ############################################################################### # semidiscretization of the hyperbolic diffusion equations @@ -30,24 +28,23 @@ equations_gravity = HyperbolicDiffusionEquations2D() solver_gravity = DGSEM(polydeg, flux_lax_friedrichs) -semi_gravity = SemidiscretizationHyperbolic(mesh, equations_gravity, initial_condition, solver_gravity, - source_terms=source_terms_harmonic) - +semi_gravity = SemidiscretizationHyperbolic(mesh, equations_gravity, initial_condition, + solver_gravity, + source_terms = source_terms_harmonic) ############################################################################### # combining both semidiscretizations for Euler + self-gravity -parameters = ParametersEulerGravity(background_density=2.0, # aka rho0 +parameters = ParametersEulerGravity(background_density = 2.0, # aka rho0 # rho0 is (ab)used to add a "+8π" term to the source terms # for the manufactured solution - gravitational_constant=1.0, # aka G - cfl=1.1, - resid_tol=1.0e-10, - n_iterations_max=1000, - timestep_gravity=timestep_gravity_erk52_3Sstar!) + gravitational_constant = 1.0, # aka G + cfl = 1.1, + resid_tol = 1.0e-10, + n_iterations_max = 1000, + timestep_gravity = timestep_gravity_erk52_3Sstar!) semi = SemidiscretizationEulerGravity(semi_euler, semi_gravity, parameters) - ############################################################################### # ODE solvers, callbacks etc. tspan = (0.0, 0.5) @@ -55,28 +52,27 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) -save_solution = SaveSolutionCallback(interval=10, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 10, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) analysis_interval = 100 -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -analysis_callback = AnalysisCallback(semi_euler, interval=analysis_interval, - save_analysis=true) +analysis_callback = AnalysisCallback(semi_euler, interval = analysis_interval, + save_analysis = true) callbacks = CallbackSet(summary_callback, stepsize_callback, save_solution, analysis_callback, alive_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary println("Number of gravity subcycles: ", semi.gravity_counter.ncalls_since_readout) diff --git a/examples/paper_self_gravitating_gas_dynamics/elixir_eulergravity_jeans_instability.jl b/examples/paper_self_gravitating_gas_dynamics/elixir_eulergravity_jeans_instability.jl index fb445616cd4..f081f6bb91a 100644 --- a/examples/paper_self_gravitating_gas_dynamics/elixir_eulergravity_jeans_instability.jl +++ b/examples/paper_self_gravitating_gas_dynamics/elixir_eulergravity_jeans_instability.jl @@ -2,7 +2,6 @@ using OrdinaryDiffEq using Trixi - """ initial_condition_jeans_instability(x, t, equations::Union{CompressibleEulerEquations2D, @@ -19,52 +18,51 @@ The classical Jeans instability taken from in CGS (centimeter, gram, second) units. """ function initial_condition_jeans_instability(x, t, - equations::CompressibleEulerEquations2D) - # Jeans gravitational instability test case - # see Derigs et al. https://arxiv.org/abs/1605.03572; Sec. 4.6 - # OBS! this uses cgs (centimeter, gram, second) units - # periodic boundaries - # domain size [0,L]^2 depends on the wave number chosen for the perturbation - # OBS! Be very careful here L must be chosen such that problem is periodic - # typical final time is T = 5 - # gamma = 5/3 - dens0 = 1.5e7 # g/cm^3 - pres0 = 1.5e7 # dyn/cm^2 - delta0 = 1e-3 - # set wave vector values for perturbation (units 1/cm) - # see FLASH manual: https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node189.html#SECTION010131000000000000000 - kx = 2.0*pi/0.5 # 2π/λ_x, λ_x = 0.5 - ky = 0.0 # 2π/λ_y, λ_y = 1e10 - k_dot_x = kx*x[1] + ky*x[2] - # perturb density and pressure away from reference states ρ_0 and p_0 - dens = dens0*(1.0 + delta0*cos(k_dot_x)) # g/cm^3 - pres = pres0*(1.0 + equations.gamma*delta0*cos(k_dot_x)) # dyn/cm^2 - # flow starts as stationary - velx = 0.0 # cm/s - vely = 0.0 # cm/s - return prim2cons((dens, velx, vely, pres), equations) + equations::CompressibleEulerEquations2D) + # Jeans gravitational instability test case + # see Derigs et al. https://arxiv.org/abs/1605.03572; Sec. 4.6 + # OBS! this uses cgs (centimeter, gram, second) units + # periodic boundaries + # domain size [0,L]^2 depends on the wave number chosen for the perturbation + # OBS! Be very careful here L must be chosen such that problem is periodic + # typical final time is T = 5 + # gamma = 5/3 + dens0 = 1.5e7 # g/cm^3 + pres0 = 1.5e7 # dyn/cm^2 + delta0 = 1e-3 + # set wave vector values for perturbation (units 1/cm) + # see FLASH manual: https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node189.html#SECTION010131000000000000000 + kx = 2.0 * pi / 0.5 # 2π/λ_x, λ_x = 0.5 + ky = 0.0 # 2π/λ_y, λ_y = 1e10 + k_dot_x = kx * x[1] + ky * x[2] + # perturb density and pressure away from reference states ρ_0 and p_0 + dens = dens0 * (1.0 + delta0 * cos(k_dot_x)) # g/cm^3 + pres = pres0 * (1.0 + equations.gamma * delta0 * cos(k_dot_x)) # dyn/cm^2 + # flow starts as stationary + velx = 0.0 # cm/s + vely = 0.0 # cm/s + return prim2cons((dens, velx, vely, pres), equations) end function initial_condition_jeans_instability(x, t, equations::HyperbolicDiffusionEquations2D) - # gravity equation: -Δϕ = -4πGρ - # Constants taken from the FLASH manual - # https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node189.html#SECTION010131000000000000000 - rho0 = 1.5e7 - delta0 = 1e-3 - - phi = rho0*delta0 # constant background perturbation magnitude - q1 = 0.0 - q2 = 0.0 - return (phi, q1, q2) + # gravity equation: -Δϕ = -4πGρ + # Constants taken from the FLASH manual + # https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node189.html#SECTION010131000000000000000 + rho0 = 1.5e7 + delta0 = 1e-3 + + phi = rho0 * delta0 # constant background perturbation magnitude + q1 = 0.0 + q2 = 0.0 + return (phi, q1, q2) end initial_condition = initial_condition_jeans_instability - ############################################################################### # semidiscretization of the compressible Euler equations -gamma = 5/3 +gamma = 5 / 3 equations_euler = CompressibleEulerEquations2D(gamma) polydeg = 3 @@ -73,11 +71,11 @@ solver_euler = DGSEM(polydeg, flux_hll) coordinates_min = (0.0, 0.0) coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) - -semi_euler = SemidiscretizationHyperbolic(mesh, equations_euler, initial_condition, solver_euler) + initial_refinement_level = 4, + n_cells_max = 10_000) +semi_euler = SemidiscretizationHyperbolic(mesh, equations_euler, initial_condition, + solver_euler) ############################################################################### # semidiscretization of the hyperbolic diffusion equations @@ -85,22 +83,21 @@ equations_gravity = HyperbolicDiffusionEquations2D() solver_gravity = DGSEM(polydeg, flux_lax_friedrichs) -semi_gravity = SemidiscretizationHyperbolic(mesh, equations_gravity, initial_condition, solver_gravity, - source_terms=source_terms_harmonic) - +semi_gravity = SemidiscretizationHyperbolic(mesh, equations_gravity, initial_condition, + solver_gravity, + source_terms = source_terms_harmonic) ############################################################################### # combining both semidiscretizations for Euler + self-gravity -parameters = ParametersEulerGravity(background_density=1.5e7, # aka rho0 - gravitational_constant=6.674e-8, # aka G - cfl=1.6, - resid_tol=1.0e-4, - n_iterations_max=1000, - timestep_gravity=timestep_gravity_carpenter_kennedy_erk54_2N!) +parameters = ParametersEulerGravity(background_density = 1.5e7, # aka rho0 + gravitational_constant = 6.674e-8, # aka G + cfl = 1.6, + resid_tol = 1.0e-4, + n_iterations_max = 1000, + timestep_gravity = timestep_gravity_carpenter_kennedy_erk54_2N!) semi = SemidiscretizationEulerGravity(semi_euler, semi_gravity, parameters) - ############################################################################### # ODE solvers, callbacks etc. tspan = (0.0, 5.0) @@ -108,51 +105,58 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) -save_solution = SaveSolutionCallback(interval=10, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 10, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) analysis_interval = 100 -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) Trixi.pretty_form_utf(::Val{:energy_potential}) = "∑e_potential" Trixi.pretty_form_ascii(::Val{:energy_potential}) = "e_potential" -function Trixi.analyze(::Val{:energy_potential}, du, u_euler, t, semi::SemidiscretizationEulerGravity) - - u_gravity = Trixi.wrap_array(semi.cache.u_ode, semi.semi_gravity) - - mesh, equations_euler, dg, cache = Trixi.mesh_equations_solver_cache(semi.semi_euler) - _, equations_gravity, _, _ = Trixi.mesh_equations_solver_cache(semi.semi_gravity) - - e_potential = Trixi.integrate_via_indices(u_euler, mesh, equations_euler, dg, cache, equations_gravity, u_gravity) do u, i, j, element, equations_euler, dg, equations_gravity, u_gravity - u_euler_local = Trixi.get_node_vars(u_euler, equations_euler, dg, i, j, element) - u_gravity_local = Trixi.get_node_vars(u_gravity, equations_gravity, dg, i, j, element) - # OBS! subtraction is specific to Jeans instability test where rho0 = 1.5e7 - return (u_euler_local[1] - 1.5e7) * u_gravity_local[1] - end - return e_potential +function Trixi.analyze(::Val{:energy_potential}, du, u_euler, t, + semi::SemidiscretizationEulerGravity) + u_gravity = Trixi.wrap_array(semi.cache.u_ode, semi.semi_gravity) + + mesh, equations_euler, dg, cache = Trixi.mesh_equations_solver_cache(semi.semi_euler) + _, equations_gravity, _, _ = Trixi.mesh_equations_solver_cache(semi.semi_gravity) + + e_potential = Trixi.integrate_via_indices(u_euler, mesh, equations_euler, dg, cache, + equations_gravity, + u_gravity) do u, i, j, element, + equations_euler, dg, + equations_gravity, u_gravity + u_euler_local = Trixi.get_node_vars(u_euler, equations_euler, dg, i, j, element) + u_gravity_local = Trixi.get_node_vars(u_gravity, equations_gravity, dg, i, j, + element) + # OBS! subtraction is specific to Jeans instability test where rho0 = 1.5e7 + return (u_euler_local[1] - 1.5e7) * u_gravity_local[1] + end + return e_potential end -analysis_callback = AnalysisCallback(semi_euler, interval=analysis_interval, - save_analysis=true, - extra_analysis_integrals=(energy_total, energy_kinetic, energy_internal, Val(:energy_potential))) +analysis_callback = AnalysisCallback(semi_euler, interval = analysis_interval, + save_analysis = true, + extra_analysis_integrals = (energy_total, + energy_kinetic, + energy_internal, + Val(:energy_potential))) callbacks = CallbackSet(summary_callback, stepsize_callback, save_restart, save_solution, analysis_callback, alive_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary println("Number of gravity subcycles: ", semi.gravity_counter.ncalls_since_readout) diff --git a/examples/paper_self_gravitating_gas_dynamics/elixir_eulergravity_sedov_blast_wave.jl b/examples/paper_self_gravitating_gas_dynamics/elixir_eulergravity_sedov_blast_wave.jl index 8933224a2c7..b7be2320228 100644 --- a/examples/paper_self_gravitating_gas_dynamics/elixir_eulergravity_sedov_blast_wave.jl +++ b/examples/paper_self_gravitating_gas_dynamics/elixir_eulergravity_sedov_blast_wave.jl @@ -19,33 +19,33 @@ based on Should be used together with [`boundary_condition_sedov_self_gravity`](@ref). """ function initial_condition_sedov_self_gravity(x, t, equations::CompressibleEulerEquations2D) - # Set up polar coordinates - r = sqrt(x[1]^2 + x[2]^2) - - # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114100000000000000 - r0 = 0.125 # = 4.0 * smallest dx (for domain length=8 and max-ref=8) - E = 1.0 - p_inner = (equations.gamma - 1) * E / (pi * r0^2) - p_ambient = 1e-5 # = true Sedov setup - - # Calculate primitive variables - # use a logistic function to transfer density value smoothly - L = 1.0 # maximum of function - x0 = 1.0 # center point of function - k = -150.0 # sharpness of transfer - logistic_function_rho = L/(1.0 + exp(-k*(r - x0))) - rho_ambient = 1e-5 - rho = max(logistic_function_rho, rho_ambient) # clip background density to not be so tiny - - # velocities are zero - v1 = 0.0 - v2 = 0.0 - - # use a logistic function to transfer pressure value smoothly - logistic_function_p = p_inner/(1.0 + exp(-k*(r - r0))) - p = max(logistic_function_p, p_ambient) - - return prim2cons(SVector(rho, v1, v2, p), equations) + # Set up polar coordinates + r = sqrt(x[1]^2 + x[2]^2) + + # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114100000000000000 + r0 = 0.125 # = 4.0 * smallest dx (for domain length=8 and max-ref=8) + E = 1.0 + p_inner = (equations.gamma - 1) * E / (pi * r0^2) + p_ambient = 1e-5 # = true Sedov setup + + # Calculate primitive variables + # use a logistic function to transfer density value smoothly + L = 1.0 # maximum of function + x0 = 1.0 # center point of function + k = -150.0 # sharpness of transfer + logistic_function_rho = L / (1.0 + exp(-k * (r - x0))) + rho_ambient = 1e-5 + rho = max(logistic_function_rho, rho_ambient) # clip background density to not be so tiny + + # velocities are zero + v1 = 0.0 + v2 = 0.0 + + # use a logistic function to transfer pressure value smoothly + logistic_function_p = p_inner / (1.0 + exp(-k * (r - r0))) + p = max(logistic_function_p, p_ambient) + + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_sedov_self_gravity @@ -65,50 +65,50 @@ Should be used together with [`initial_condition_sedov_self_gravity`](@ref). function boundary_condition_sedov_self_gravity(u_inner, orientation, direction, x, t, surface_flux_function, equations::CompressibleEulerEquations2D) - # velocities are zero, density/pressure are ambient values according to - # initial_condition_sedov_self_gravity - rho = 1e-5 - v1 = 0.0 - v2 = 0.0 - p = 1e-5 - - u_boundary = prim2cons(SVector(rho, v1, v2, p), equations) - - # Calculate boundary flux - if iseven(direction) # u_inner is "left" of boundary, u_boundary is "right" of boundary - flux = surface_flux_function(u_inner, u_boundary, orientation, equations) - else # u_boundary is "left" of boundary, u_inner is "right" of boundary - flux = surface_flux_function(u_boundary, u_inner, orientation, equations) - end - - return flux + # velocities are zero, density/pressure are ambient values according to + # initial_condition_sedov_self_gravity + rho = 1e-5 + v1 = 0.0 + v2 = 0.0 + p = 1e-5 + + u_boundary = prim2cons(SVector(rho, v1, v2, p), equations) + + # Calculate boundary flux + if iseven(direction) # u_inner is "left" of boundary, u_boundary is "right" of boundary + flux = surface_flux_function(u_inner, u_boundary, orientation, equations) + else # u_boundary is "left" of boundary, u_inner is "right" of boundary + flux = surface_flux_function(u_boundary, u_inner, orientation, equations) + end + + return flux end boundary_conditions = boundary_condition_sedov_self_gravity surface_flux = flux_hll -volume_flux = flux_chandrashekar +volume_flux = flux_chandrashekar polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations_euler, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver_euler = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-4, -4) -coordinates_max = ( 4, 4) +coordinates_max = (4, 4) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=100_000, - periodicity=false) - -semi_euler = SemidiscretizationHyperbolic(mesh, equations_euler, initial_condition, solver_euler, - boundary_conditions=boundary_conditions) + initial_refinement_level = 2, + n_cells_max = 100_000, + periodicity = false) +semi_euler = SemidiscretizationHyperbolic(mesh, equations_euler, initial_condition, + solver_euler, + boundary_conditions = boundary_conditions) ############################################################################### # semidiscretization of the hyperbolic diffusion equations @@ -125,12 +125,13 @@ based on - https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114100000000000000 Should be used together with [`boundary_condition_sedov_self_gravity`](@ref). """ -function initial_condition_sedov_self_gravity(x, t, equations::HyperbolicDiffusionEquations2D) - # for now just use constant initial condition for sedov blast wave (can likely be improved) - phi = 0.0 - q1 = 0.0 - q2 = 0.0 - return SVector(phi, q1, q2) +function initial_condition_sedov_self_gravity(x, t, + equations::HyperbolicDiffusionEquations2D) + # for now just use constant initial condition for sedov blast wave (can likely be improved) + phi = 0.0 + q1 = 0.0 + q2 = 0.0 + return SVector(phi, q1, q2) end """ @@ -147,39 +148,38 @@ based on Should be used together with [`initial_condition_sedov_self_gravity`](@ref). """ function boundary_condition_sedov_self_gravity(u_inner, orientation, direction, x, t, - surface_flux_function, - equations::HyperbolicDiffusionEquations2D) - u_boundary = initial_condition_sedov_self_gravity(x, t, equations) - - # Calculate boundary flux - if iseven(direction) # u_inner is "left" of boundary, u_boundary is "right" of boundary - flux = surface_flux_function(u_inner, u_boundary, orientation, equations) - else # u_boundary is "left" of boundary, u_inner is "right" of boundary - flux = surface_flux_function(u_boundary, u_inner, orientation, equations) - end - - return flux + surface_flux_function, + equations::HyperbolicDiffusionEquations2D) + u_boundary = initial_condition_sedov_self_gravity(x, t, equations) + + # Calculate boundary flux + if iseven(direction) # u_inner is "left" of boundary, u_boundary is "right" of boundary + flux = surface_flux_function(u_inner, u_boundary, orientation, equations) + else # u_boundary is "left" of boundary, u_inner is "right" of boundary + flux = surface_flux_function(u_boundary, u_inner, orientation, equations) + end + + return flux end solver_gravity = DGSEM(polydeg, flux_lax_friedrichs) -semi_gravity = SemidiscretizationHyperbolic(mesh, equations_gravity, initial_condition, solver_gravity, - boundary_conditions=boundary_conditions, - source_terms=source_terms_harmonic) - +semi_gravity = SemidiscretizationHyperbolic(mesh, equations_gravity, initial_condition, + solver_gravity, + boundary_conditions = boundary_conditions, + source_terms = source_terms_harmonic) ############################################################################### # combining both semidiscretizations for Euler + self-gravity -parameters = ParametersEulerGravity(background_density=0.0, # aka rho0 - gravitational_constant=6.674e-8, # aka G - cfl=2.4, - resid_tol=1.0e-4, - n_iterations_max=100, - timestep_gravity=timestep_gravity_erk52_3Sstar!) +parameters = ParametersEulerGravity(background_density = 0.0, # aka rho0 + gravitational_constant = 6.674e-8, # aka G + cfl = 2.4, + resid_tol = 1.0e-4, + n_iterations_max = 100, + timestep_gravity = timestep_gravity_erk52_3Sstar!) semi = SemidiscretizationEulerGravity(semi_euler, semi_gravity, parameters) - ############################################################################### # ODE solvers, callbacks etc. tspan = (0.0, 1.0) @@ -188,41 +188,42 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() amr_indicator = IndicatorHennemannGassner(semi, - alpha_max=1.0, - alpha_min=0.0, - alpha_smooth=false, - variable=density_pressure) + alpha_max = 1.0, + alpha_min = 0.0, + alpha_smooth = false, + variable = density_pressure) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=2, - max_level =8, max_threshold=0.0003) + base_level = 2, + max_level = 8, max_threshold = 0.0003) amr_callback = AMRCallback(semi, amr_controller, - interval=1, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 1, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) analysis_interval = 100 -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -analysis_callback = AnalysisCallback(semi_euler, interval=analysis_interval, - save_analysis=true, - extra_analysis_integrals=(energy_total, energy_kinetic, energy_internal)) +analysis_callback = AnalysisCallback(semi_euler, interval = analysis_interval, + save_analysis = true, + extra_analysis_integrals = (energy_total, + energy_kinetic, + energy_internal)) callbacks = CallbackSet(summary_callback, amr_callback, stepsize_callback, save_solution, analysis_callback, alive_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary println("Number of gravity subcycles: ", semi.gravity_counter.ncalls_since_readout) diff --git a/examples/paper_self_gravitating_gas_dynamics/elixir_hypdiff_convergence.jl b/examples/paper_self_gravitating_gas_dynamics/elixir_hypdiff_convergence.jl index 029c19380cf..df6e4e6349f 100644 --- a/examples/paper_self_gravitating_gas_dynamics/elixir_hypdiff_convergence.jl +++ b/examples/paper_self_gravitating_gas_dynamics/elixir_hypdiff_convergence.jl @@ -9,10 +9,10 @@ equations = HyperbolicDiffusionEquations2D() initial_condition = initial_condition_poisson_nonperiodic # 1 => -x, 2 => +x, 3 => -y, 4 => +y as usual for orientations -boundary_conditions = (x_neg=boundary_condition_poisson_nonperiodic, - x_pos=boundary_condition_poisson_nonperiodic, - y_neg=boundary_condition_periodic, - y_pos=boundary_condition_periodic) +boundary_conditions = (x_neg = boundary_condition_poisson_nonperiodic, + x_pos = boundary_condition_poisson_nonperiodic, + y_neg = boundary_condition_periodic, + y_pos = boundary_condition_periodic) polydeg = 3 surface_flux = flux_lax_friedrichs @@ -21,15 +21,13 @@ solver = DGSEM(polydeg, surface_flux) coordinates_min = (0.0, 0.0) coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=30_000, - periodicity=(false, true)) - + initial_refinement_level = 2, + n_cells_max = 30_000, + periodicity = (false, true)) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_poisson_nonperiodic, - boundary_conditions=boundary_conditions) - + source_terms = source_terms_poisson_nonperiodic, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -40,29 +38,28 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() resid_tol = 1.0e-10 -steady_state_callback = SteadyStateCallback(abstol=resid_tol, reltol=0.0) +steady_state_callback = SteadyStateCallback(abstol = resid_tol, reltol = 0.0) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) analysis_interval = 500 -alive_callback = AliveCallback(analysis_interval=analysis_interval) -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy, energy_total)) +alive_callback = AliveCallback(analysis_interval = analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy, energy_total)) callbacks = CallbackSet(summary_callback, steady_state_callback, stepsize_callback, save_solution, analysis_callback, alive_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/special_elixirs/elixir_euler_ad.jl b/examples/special_elixirs/elixir_euler_ad.jl index 48fd37cc9d4..3aa44f9a773 100644 --- a/examples/special_elixirs/elixir_euler_ad.jl +++ b/examples/special_elixirs/elixir_euler_ad.jl @@ -6,10 +6,10 @@ using Trixi, LinearAlgebra, ForwardDiff equations = CompressibleEulerEquations2D(1.4) mesh = TreeMesh((-1.0, -1.0), (1.0, 1.0), - initial_refinement_level=2, n_cells_max=10^5) + initial_refinement_level = 2, n_cells_max = 10^5) -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralFluxDifferencing(flux_ranocha)) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralFluxDifferencing(flux_ranocha)) """ initial_condition_isentropic_vortex(x, t, equations::CompressibleEulerEquations2D) @@ -21,43 +21,45 @@ The classical isentropic vortex test case of [NASA/CR-97-206253](https://ntrs.nasa.gov/citations/19980007543) """ function initial_condition_isentropic_vortex(x, t, equations::CompressibleEulerEquations2D) - # needs appropriate mesh size, e.g. [-10,-10]x[10,10] - # for error convergence: make sure that the end time is such that the vortex is back at the initial state!! - # for the current velocity and domain size: t_end should be a multiple of 20s - # initial center of the vortex - inicenter = SVector(0.0, 0.0) - # size and strength of the vortex - iniamplitude = 5.0 - # base flow - rho = 1.0 - v1 = 1.0 - v2 = 1.0 - vel = SVector(v1, v2) - p = 25.0 - rt = p / rho # ideal gas equation - t_loc = 0.0 - cent = inicenter + vel*t_loc # advection of center - # ATTENTION: handle periodic BC, but only for v1 = v2 = 1.0 (!!!!) - cent = x - cent # distance to center point - # cent = cross(iniaxis, cent) # distance to axis, tangent vector, length r - # cross product with iniaxis = [0, 0, 1] - cent = SVector(-cent[2], cent[1]) - r2 = cent[1]^2 + cent[2]^2 - du = iniamplitude / (2*π) * exp(0.5 * (1 - r2)) # vel. perturbation - dtemp = -(equations.gamma - 1) / (2 * equations.gamma * rt) * du^2 # isentropic - rho = rho * (1 + dtemp)^(1 / (equations.gamma - 1)) - vel = vel + du * cent - v1, v2 = vel - p = p * (1 + dtemp)^(equations.gamma / (equations.gamma - 1)) - prim = SVector(rho, v1, v2, p) - return prim2cons(prim, equations) + # needs appropriate mesh size, e.g. [-10,-10]x[10,10] + # for error convergence: make sure that the end time is such that the vortex is back at the initial state!! + # for the current velocity and domain size: t_end should be a multiple of 20s + # initial center of the vortex + inicenter = SVector(0.0, 0.0) + # size and strength of the vortex + iniamplitude = 5.0 + # base flow + rho = 1.0 + v1 = 1.0 + v2 = 1.0 + vel = SVector(v1, v2) + p = 25.0 + rt = p / rho # ideal gas equation + t_loc = 0.0 + cent = inicenter + vel * t_loc # advection of center + # ATTENTION: handle periodic BC, but only for v1 = v2 = 1.0 (!!!!) + cent = x - cent # distance to center point + # cent = cross(iniaxis, cent) # distance to axis, tangent vector, length r + # cross product with iniaxis = [0, 0, 1] + cent = SVector(-cent[2], cent[1]) + r2 = cent[1]^2 + cent[2]^2 + du = iniamplitude / (2 * π) * exp(0.5 * (1 - r2)) # vel. perturbation + dtemp = -(equations.gamma - 1) / (2 * equations.gamma * rt) * du^2 # isentropic + rho = rho * (1 + dtemp)^(1 / (equations.gamma - 1)) + vel = vel + du * cent + v1, v2 = vel + p = p * (1 + dtemp)^(equations.gamma / (equations.gamma - 1)) + prim = SVector(rho, v1, v2, p) + return prim2cons(prim, equations) end -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_isentropic_vortex, solver) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_isentropic_vortex, + solver) u0_ode = compute_coefficients(0.0, semi) J = ForwardDiff.jacobian((du_ode, γ) -> begin - equations_inner = CompressibleEulerEquations2D(first(γ)) - semi_inner = Trixi.remake(semi, equations=equations_inner, uEltype=eltype(γ)) - Trixi.rhs!(du_ode, u0_ode, semi_inner, 0.0) - end, similar(u0_ode), [1.4]); # γ needs to be an `AbstractArray` + equations_inner = CompressibleEulerEquations2D(first(γ)) + semi_inner = Trixi.remake(semi, equations = equations_inner, + uEltype = eltype(γ)) + Trixi.rhs!(du_ode, u0_ode, semi_inner, 0.0) + end, similar(u0_ode), [1.4]); # γ needs to be an `AbstractArray` diff --git a/examples/structured_1d_dgsem/elixir_advection_basic.jl b/examples/structured_1d_dgsem/elixir_advection_basic.jl index 82464f23964..cdabeb4c61a 100644 --- a/examples/structured_1d_dgsem/elixir_advection_basic.jl +++ b/examples/structured_1d_dgsem/elixir_advection_basic.jl @@ -11,7 +11,7 @@ advection_velocity = 1.0 equations = LinearScalarAdvectionEquation1D(advection_velocity) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-1.0,) # minimum coordinate coordinates_max = (1.0,) # maximum coordinate @@ -21,8 +21,8 @@ cells_per_dimension = (16,) mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max) # A semidiscretization collects data structures and functions for the spatial discretization -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, solver) - +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, + solver) ############################################################################### # ODE solvers, callbacks etc. @@ -35,26 +35,26 @@ ode = semidiscretize(semi, (0.0, 1.0)); summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); # Print the timer summary summary_callback() diff --git a/examples/structured_1d_dgsem/elixir_advection_nonperiodic.jl b/examples/structured_1d_dgsem/elixir_advection_nonperiodic.jl index e87e0b36b0a..1e0c579ffcf 100644 --- a/examples/structured_1d_dgsem/elixir_advection_nonperiodic.jl +++ b/examples/structured_1d_dgsem/elixir_advection_nonperiodic.jl @@ -11,18 +11,16 @@ equations = LinearScalarAdvectionEquation1D(advection_velocity) initial_condition = initial_condition_gauss boundary_conditions = BoundaryConditionDirichlet(initial_condition) -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (0.0,) coordinates_max = (5.0,) -mesh = StructuredMesh((16,), coordinates_min, coordinates_max, periodicity=false) - +mesh = StructuredMesh((16,), coordinates_min, coordinates_max, periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -33,31 +31,30 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_restart, save_solution, stepsize_callback); - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=stepsize_callback(ode), # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = stepsize_callback(ode), # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_1d_dgsem/elixir_advection_shockcapturing.jl b/examples/structured_1d_dgsem/elixir_advection_shockcapturing.jl index 313812fe08d..96566bc2373 100644 --- a/examples/structured_1d_dgsem/elixir_advection_shockcapturing.jl +++ b/examples/structured_1d_dgsem/elixir_advection_shockcapturing.jl @@ -17,30 +17,30 @@ Slight simplification from [DOI: 10.1006/jcph.1996.0130](https://doi.org/10.1006/jcph.1996.0130) """ function initial_condition_composite(x, t, equations::LinearScalarAdvectionEquation1D) - xmin, xmax = -1.0, 1.0 # Only works if the domain is [-1.0,1.0] - x_trans = x[1] - t - L = xmax - xmin - if x_trans > xmax - x_ = x_trans - L * floor((x_trans + xmin) / L) - elseif x_trans < xmin - x_ = x_trans + L * floor((xmax - x_trans) / L) - else - x_ = x_trans - end - - if x_ > -0.8 && x_ < -0.6 - value = exp(-log(2.0) * (x_ + 0.7)^2 / 0.0009) - elseif x_ > -0.4 && x_ < -0.2 - value = 1.0 - elseif x_ > 0.0 && x_ < 0.2 - value = 1.0 - abs(10.0 * (x_ - 0.1)) - elseif x_ > 0.4 && x_ < 0.6 - value = sqrt(1.0 - 100.0 * (x_ - 0.5)^2) - else - value = 0.0 - end - - return SVector(value) + xmin, xmax = -1.0, 1.0 # Only works if the domain is [-1.0,1.0] + x_trans = x[1] - t + L = xmax - xmin + if x_trans > xmax + x_ = x_trans - L * floor((x_trans + xmin) / L) + elseif x_trans < xmin + x_ = x_trans + L * floor((xmax - x_trans) / L) + else + x_ = x_trans + end + + if x_ > -0.8 && x_ < -0.6 + value = exp(-log(2.0) * (x_ + 0.7)^2 / 0.0009) + elseif x_ > -0.4 && x_ < -0.2 + value = 1.0 + elseif x_ > 0.0 && x_ < 0.2 + value = 1.0 - abs(10.0 * (x_ - 0.1)) + elseif x_ > 0.4 && x_ < 0.6 + value = sqrt(1.0 - 100.0 * (x_ - 0.5)^2) + else + value = 0.0 + end + + return SVector(value) end initial_condition = initial_condition_composite @@ -52,13 +52,13 @@ volume_flux = flux_central polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=Trixi.first) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = Trixi.first) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) # Create curved mesh @@ -66,12 +66,11 @@ cells_per_dimension = (120,) coordinates_min = (-1.0,) # minimum coordinate coordinates_max = (1.0,) # maximum coordinate mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max, - periodicity=true) + periodicity = true) # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -84,23 +83,23 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); -summary_callback() # print the timer summary \ No newline at end of file +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); +summary_callback() # print the timer summary diff --git a/examples/structured_1d_dgsem/elixir_euler_sedov.jl b/examples/structured_1d_dgsem/elixir_euler_sedov.jl index 9d7be21a5c1..4ffa100cc71 100644 --- a/examples/structured_1d_dgsem/elixir_euler_sedov.jl +++ b/examples/structured_1d_dgsem/elixir_euler_sedov.jl @@ -14,50 +14,50 @@ The Sedov blast wave setup based on Flash - https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 """ function initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEquations1D) - # Set up polar coordinates - inicenter = SVector(0.0) - x_norm = x[1] - inicenter[1] - r = abs(x_norm) - - # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 - r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) - # r0 = 0.5 # = more reasonable setup - E = 1.0 - p0_inner = 6 * (equations.gamma - 1) * E / (3 * pi * r0) - p0_outer = 1.0e-5 # = true Sedov setup - - # Calculate primitive variables - rho = 1.0 - v1 = 0.0 - p = r > r0 ? p0_outer : p0_inner - - return prim2cons(SVector(rho, v1, p), equations) + # Set up polar coordinates + inicenter = SVector(0.0) + x_norm = x[1] - inicenter[1] + r = abs(x_norm) + + # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 + r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) + # r0 = 0.5 # = more reasonable setup + E = 1.0 + p0_inner = 6 * (equations.gamma - 1) * E / (3 * pi * r0) + p0_outer = 1.0e-5 # = true Sedov setup + + # Calculate primitive variables + rho = 1.0 + v1 = 0.0 + p = r > r0 ? p0_outer : p0_inner + + return prim2cons(SVector(rho, v1, p), equations) end initial_condition = initial_condition_sedov_blast_wave surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha +volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) shock_indicator_variable = density_pressure indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=1.0, - alpha_min=0.001, - alpha_smooth=true, - variable=shock_indicator_variable) + alpha_max = 1.0, + alpha_min = 0.001, + alpha_smooth = true, + variable = shock_indicator_variable) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) cells_per_dimension = (64,) coordinates_min = (-2.0,) -coordinates_max = ( 2.0,) -mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max, periodicity=true) +coordinates_max = (2.0,) +mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max, + periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -67,16 +67,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -84,11 +84,10 @@ callbacks = CallbackSet(summary_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=stepsize_callback(ode), # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = stepsize_callback(ode), # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_1d_dgsem/elixir_euler_source_terms.jl b/examples/structured_1d_dgsem/elixir_euler_source_terms.jl index cbda7087052..97767f3e127 100644 --- a/examples/structured_1d_dgsem/elixir_euler_source_terms.jl +++ b/examples/structured_1d_dgsem/elixir_euler_source_terms.jl @@ -13,7 +13,7 @@ initial_condition = initial_condition_convergence_test # Note that the expected EOC of 5 is not reached with this flux. # Using flux_hll instead yields the expected EOC. -solver = DGSEM(polydeg=4, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 4, surface_flux = flux_lax_friedrichs) coordinates_min = (0.0,) coordinates_max = (2.0,) @@ -21,10 +21,8 @@ cells_per_dimension = (16,) mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max) - semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -35,29 +33,28 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_errors=(:l2_error_primitive, - :linf_error_primitive)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_errors = (:l2_error_primitive, + :linf_error_primitive)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_1d_dgsem/elixir_euler_source_terms_nonperiodic.jl b/examples/structured_1d_dgsem/elixir_euler_source_terms_nonperiodic.jl index 9aa5b7f4979..d5063838136 100644 --- a/examples/structured_1d_dgsem/elixir_euler_source_terms_nonperiodic.jl +++ b/examples/structured_1d_dgsem/elixir_euler_source_terms_nonperiodic.jl @@ -15,20 +15,18 @@ source_terms = source_terms_convergence_test # 1*ndims == 2 directions or you can pass a tuple containing BCs for # each direction boundary_condition = BoundaryConditionDirichlet(initial_condition) -boundary_conditions = (x_neg=boundary_condition, - x_pos=boundary_condition) +boundary_conditions = (x_neg = boundary_condition, + x_pos = boundary_condition) -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) f1() = SVector(0.0) f2() = SVector(2.0) -mesh = StructuredMesh((16,), (f1, f2), periodicity=false) - +mesh = StructuredMesh((16,), (f1, f2), periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms, - boundary_conditions=boundary_conditions) - + source_terms = source_terms, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -39,30 +37,29 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_restart, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_advection_basic.jl b/examples/structured_2d_dgsem/elixir_advection_basic.jl index 7d2e1f49276..1d7235fc214 100644 --- a/examples/structured_2d_dgsem/elixir_advection_basic.jl +++ b/examples/structured_2d_dgsem/elixir_advection_basic.jl @@ -11,10 +11,10 @@ advection_velocity = (0.2, -0.7) equations = LinearScalarAdvectionEquation2D(advection_velocity) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-1.0, -1.0) # minimum coordinates (min(x), min(y)) -coordinates_max = ( 1.0, 1.0) # maximum coordinates (max(x), max(y)) +coordinates_max = (1.0, 1.0) # maximum coordinates (max(x), max(y)) cells_per_dimension = (16, 16) @@ -22,8 +22,8 @@ cells_per_dimension = (16, 16) mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max) # A semidiscretization collects data structures and functions for the spatial discretization -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, solver) - +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, + solver) ############################################################################### # ODE solvers, callbacks etc. @@ -36,26 +36,26 @@ ode = semidiscretize(semi, (0.0, 1.0)); summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); # Print the timer summary summary_callback() diff --git a/examples/structured_2d_dgsem/elixir_advection_coupled.jl b/examples/structured_2d_dgsem/elixir_advection_coupled.jl index 1e54e411db6..2a56d23f4c0 100644 --- a/examples/structured_2d_dgsem/elixir_advection_coupled.jl +++ b/examples/structured_2d_dgsem/elixir_advection_coupled.jl @@ -1,7 +1,6 @@ using OrdinaryDiffEq using Trixi - ############################################################################### # Coupled semidiscretization of two linear advection systems, which are connected periodically # @@ -35,11 +34,11 @@ advection_velocity = (0.2, -0.7) equations = LinearScalarAdvectionEquation2D(advection_velocity) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) # First mesh is the left half of a [-1,1]^2 square coordinates_min1 = (-1.0, -1.0) # minimum coordinates (min(x), min(y)) -coordinates_max1 = ( 0.0, 1.0) # maximum coordinates (max(x), max(y)) +coordinates_max1 = (0.0, 1.0) # maximum coordinates (max(x), max(y)) # Define identical resolution as a variable such that it is easier to change from `trixi_include` cells_per_dimension = (8, 16) @@ -49,32 +48,45 @@ cells_per_dimension1 = cells_per_dimension mesh1 = StructuredMesh(cells_per_dimension1, coordinates_min1, coordinates_max1) # A semidiscretization collects data structures and functions for the spatial discretization -semi1 = SemidiscretizationHyperbolic(mesh1, equations, initial_condition_convergence_test, solver, - boundary_conditions=( - # Connect left boundary with right boundary of right mesh - x_neg=BoundaryConditionCoupled(2, (:end, :i_forward), Float64), - # Connect right boundary with left boundary of right mesh - x_pos=BoundaryConditionCoupled(2, (:begin, :i_forward), Float64), - y_neg=boundary_condition_periodic, - y_pos=boundary_condition_periodic)) - +semi1 = SemidiscretizationHyperbolic(mesh1, equations, initial_condition_convergence_test, + solver, + boundary_conditions = ( + # Connect left boundary with right boundary of right mesh + x_neg = BoundaryConditionCoupled(2, + (:end, + :i_forward), + Float64), + # Connect right boundary with left boundary of right mesh + x_pos = BoundaryConditionCoupled(2, + (:begin, + :i_forward), + Float64), + y_neg = boundary_condition_periodic, + y_pos = boundary_condition_periodic)) # Second mesh is the right half of a [-1,1]^2 square coordinates_min2 = (0.0, -1.0) # minimum coordinates (min(x), min(y)) -coordinates_max2 = (1.0, 1.0) # maximum coordinates (max(x), max(y)) +coordinates_max2 = (1.0, 1.0) # maximum coordinates (max(x), max(y)) cells_per_dimension2 = cells_per_dimension mesh2 = StructuredMesh(cells_per_dimension2, coordinates_min2, coordinates_max2) -semi2 = SemidiscretizationHyperbolic(mesh2, equations, initial_condition_convergence_test, solver, - boundary_conditions=( - # Connect left boundary with right boundary of left mesh - x_neg=BoundaryConditionCoupled(1, (:end, :i_forward), Float64), - # Connect right boundary with left boundary of left mesh - x_pos=BoundaryConditionCoupled(1, (:begin, :i_forward), Float64), - y_neg=boundary_condition_periodic, - y_pos=boundary_condition_periodic)) +semi2 = SemidiscretizationHyperbolic(mesh2, equations, initial_condition_convergence_test, + solver, + boundary_conditions = ( + # Connect left boundary with right boundary of left mesh + x_neg = BoundaryConditionCoupled(1, + (:end, + :i_forward), + Float64), + # Connect right boundary with left boundary of left mesh + x_pos = BoundaryConditionCoupled(1, + (:begin, + :i_forward), + Float64), + y_neg = boundary_condition_periodic, + y_pos = boundary_condition_periodic)) # Create a semidiscretization that bundles semi1 and semi2 semi = SemidiscretizationCoupled(semi1, semi2) @@ -90,28 +102,28 @@ ode = semidiscretize(semi, (0.0, 2.0)); summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback1 = AnalysisCallback(semi1, interval=100) -analysis_callback2 = AnalysisCallback(semi2, interval=100) +analysis_callback1 = AnalysisCallback(semi1, interval = 100) +analysis_callback2 = AnalysisCallback(semi2, interval = 100) analysis_callback = AnalysisCallbackCoupled(semi, analysis_callback1, analysis_callback2) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); # Print the timer summary summary_callback() diff --git a/examples/structured_2d_dgsem/elixir_advection_extended.jl b/examples/structured_2d_dgsem/elixir_advection_extended.jl index fbaa7783d99..df7e1f375a9 100644 --- a/examples/structured_2d_dgsem/elixir_advection_extended.jl +++ b/examples/structured_2d_dgsem/elixir_advection_extended.jl @@ -18,11 +18,11 @@ initial_condition = initial_condition_convergence_test boundary_conditions = boundary_condition_periodic # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) # The initial condition is 2-periodic coordinates_min = (-1.5, 1.3) # minimum coordinates (min(x), min(y)) -coordinates_max = ( 0.5, 5.3) # maximum coordinates (max(x), max(y)) +coordinates_max = (0.5, 5.3) # maximum coordinates (max(x), max(y)) cells_per_dimension = (19, 37) @@ -31,8 +31,7 @@ mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max) # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -47,24 +46,24 @@ summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy, energy_total)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy, energy_total)) # The AliveCallback prints short status information in regular intervals -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) # The SaveRestartCallback allows to save a file from which a Trixi.jl simulation can be restarted -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver callbacks = CallbackSet(summary_callback, @@ -72,14 +71,13 @@ callbacks = CallbackSet(summary_callback, save_restart, save_solution, stepsize_callback) - ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); # Print the timer summary summary_callback() diff --git a/examples/structured_2d_dgsem/elixir_advection_free_stream.jl b/examples/structured_2d_dgsem/elixir_advection_free_stream.jl index 155a2d19fc9..7785b4f9e18 100644 --- a/examples/structured_2d_dgsem/elixir_advection_free_stream.jl +++ b/examples/structured_2d_dgsem/elixir_advection_free_stream.jl @@ -11,21 +11,21 @@ equations = LinearScalarAdvectionEquation2D(advection_velocity) initial_condition = initial_condition_constant # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) # Mapping as described in https://arxiv.org/abs/2012.12040, but reduced to 2D function mapping(xi_, eta_) - # Transform input variables between -1 and 1 onto [0,3] - xi = 1.5 * xi_ + 1.5 - eta = 1.5 * eta_ + 1.5 + # Transform input variables between -1 and 1 onto [0,3] + xi = 1.5 * xi_ + 1.5 + eta = 1.5 * eta_ + 1.5 - y = eta + 3/8 * (cos(1.5 * pi * (2 * xi - 3)/3) * - cos(0.5 * pi * (2 * eta - 3)/3)) + y = eta + 3 / 8 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3)) - x = xi + 3/8 * (cos(0.5 * pi * (2 * xi - 3)/3) * - cos(2 * pi * (2 * y - 3)/3)) + x = xi + 3 / 8 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3)) - return SVector(x, y) + return SVector(x, y) end cells_per_dimension = (16, 16) @@ -36,7 +36,6 @@ mesh = StructuredMesh(cells_per_dimension, mapping) # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -48,30 +47,30 @@ ode = semidiscretize(semi, (0.0, 1.0)); summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The SaveRestartCallback allows to save a file from which a Trixi.jl simulation can be restarted -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=2.0) +stepsize_callback = StepsizeCallback(cfl = 2.0) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_restart, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_restart, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); # Print the timer summary summary_callback() diff --git a/examples/structured_2d_dgsem/elixir_advection_nonperiodic.jl b/examples/structured_2d_dgsem/elixir_advection_nonperiodic.jl index 2aad3a01566..e2e113b168d 100644 --- a/examples/structured_2d_dgsem/elixir_advection_nonperiodic.jl +++ b/examples/structured_2d_dgsem/elixir_advection_nonperiodic.jl @@ -13,16 +13,14 @@ initial_condition = initial_condition_gauss # you can either use a single function to impose the BCs weakly in all # 2*ndims == 4 directions or you can pass a tuple containing BCs for each direction boundary_conditions = BoundaryConditionDirichlet(initial_condition) -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-5.0, -5.0) -coordinates_max = ( 5.0, 5.0) -mesh = StructuredMesh((16, 16), coordinates_min, coordinates_max, periodicity=false) - +coordinates_max = (5.0, 5.0) +mesh = StructuredMesh((16, 16), coordinates_min, coordinates_max, periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -33,17 +31,17 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -52,7 +50,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=stepsize_callback(ode), # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = stepsize_callback(ode), # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_advection_parallelogram.jl b/examples/structured_2d_dgsem/elixir_advection_parallelogram.jl index b9a6d3f91ae..b70deb12318 100644 --- a/examples/structured_2d_dgsem/elixir_advection_parallelogram.jl +++ b/examples/structured_2d_dgsem/elixir_advection_parallelogram.jl @@ -7,24 +7,23 @@ using OrdinaryDiffEq using Trixi - # initial_condition_convergence_test transformed to the parallelogram function initial_condition_parallelogram(x, t, equation::LinearScalarAdvectionEquation2D) - # Transform back to unit square - x_transformed = SVector(x[1] - x[2], x[2]) - a = equation.advection_velocity - a_transformed = SVector(a[1] - a[2], a[2]) - - # Store translated coordinate for easy use of exact solution - x_translated = x_transformed - a_transformed * t - - c = 1.0 - A = 0.5 - L = 2 - f = 1/L - omega = 2 * pi * f - scalar = c + A * sin(omega * sum(x_translated)) - return SVector(scalar) + # Transform back to unit square + x_transformed = SVector(x[1] - x[2], x[2]) + a = equation.advection_velocity + a_transformed = SVector(a[1] - a[2], a[2]) + + # Store translated coordinate for easy use of exact solution + x_translated = x_transformed - a_transformed * t + + c = 1.0 + A = 0.5 + L = 2 + f = 1 / L + omega = 2 * pi * f + scalar = c + A * sin(omega * sum(x_translated)) + return SVector(scalar) end ############################################################################### @@ -35,7 +34,7 @@ advection_velocity = (-0.5, -0.7) equations = LinearScalarAdvectionEquation2D(advection_velocity) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) # Define faces for a parallelogram that looks like this # @@ -49,11 +48,11 @@ mapping(xi, eta) = SVector(xi + eta, eta) cells_per_dimension = (16, 16) # Create curved mesh with 16 x 16 elements, periodic in both dimensions -mesh = StructuredMesh(cells_per_dimension, mapping; periodicity=(true, true)) +mesh = StructuredMesh(cells_per_dimension, mapping; periodicity = (true, true)) # A semidiscretization collects data structures and functions for the spatial discretization -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_parallelogram, solver) - +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_parallelogram, + solver) ############################################################################### # ODE solvers, callbacks etc. @@ -66,26 +65,26 @@ ode = semidiscretize(semi, (0.0, 1.0)); summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); # Print the timer summary summary_callback() diff --git a/examples/structured_2d_dgsem/elixir_advection_restart.jl b/examples/structured_2d_dgsem/elixir_advection_restart.jl index 98c44fac71a..0accbdba702 100644 --- a/examples/structured_2d_dgsem/elixir_advection_restart.jl +++ b/examples/structured_2d_dgsem/elixir_advection_restart.jl @@ -10,7 +10,6 @@ restart_file = "restart_000021.h5" trixi_include(@__MODULE__, joinpath(@__DIR__, elixir_file)) - ############################################################################### # adapt the parameters that have changed compared to "elixir_advection_extended.jl" @@ -29,13 +28,12 @@ ode = semidiscretize(semi, tspan, restart_filename); # Do not overwrite the initial snapshot written by elixir_advection_extended.jl. save_solution.condition.save_initial_solution = false -integrator = init(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=dt, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +integrator = init(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = dt, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks, maxiters = 100_000); # Get the last time index and work with that. -integrator.iter = load_timestep(restart_filename) -integrator.stats.naccept = integrator.iter +load_timestep!(integrator, restart_filename) ############################################################################### # run the simulation diff --git a/examples/structured_2d_dgsem/elixir_advection_rotated.jl b/examples/structured_2d_dgsem/elixir_advection_rotated.jl index 7dfee23a067..826c7ebaacb 100644 --- a/examples/structured_2d_dgsem/elixir_advection_rotated.jl +++ b/examples/structured_2d_dgsem/elixir_advection_rotated.jl @@ -7,7 +7,6 @@ using OrdinaryDiffEq using Trixi - # Define new structs inside a module to allow re-evaluating the file. # This module name needs to be unique among all examples, otherwise Julia will throw warnings # if multiple test cases using the same module name are run in the same session. @@ -17,40 +16,41 @@ using Trixi # initial_condition_convergence_test transformed to the rotated rectangle struct InitialConditionConvergenceTestRotated - sin_alpha::Float64 - cos_alpha::Float64 + sin_alpha::Float64 + cos_alpha::Float64 end function InitialConditionConvergenceTestRotated(alpha) - sin_alpha, cos_alpha = sincos(alpha) + sin_alpha, cos_alpha = sincos(alpha) - InitialConditionConvergenceTestRotated(sin_alpha, cos_alpha) + InitialConditionConvergenceTestRotated(sin_alpha, cos_alpha) end -function (initial_condition::InitialConditionConvergenceTestRotated)(x, t, equation::LinearScalarAdvectionEquation2D) - sin_ = initial_condition.sin_alpha - cos_ = initial_condition.cos_alpha +function (initial_condition::InitialConditionConvergenceTestRotated)(x, t, + equation::LinearScalarAdvectionEquation2D) + sin_ = initial_condition.sin_alpha + cos_ = initial_condition.cos_alpha - # Rotate back to unit square + # Rotate back to unit square - # Clockwise rotation by α and translation by 1 - # Multiply with [ cos(α) sin(α); - # -sin(α) cos(α)] - x_rot = SVector(cos_ * x[1] + sin_ * x[2], -sin_ * x[1] + cos_ * x[2]) - a = equation.advection_velocity - a_rot = SVector(cos_ * a[1] + sin_ * a[2], -sin_ * a[1] + cos_ * a[2]) + # Clockwise rotation by α and translation by 1 + # Multiply with [ cos(α) sin(α); + # -sin(α) cos(α)] + x_rot = SVector(cos_ * x[1] + sin_ * x[2], -sin_ * x[1] + cos_ * x[2]) + a = equation.advection_velocity + a_rot = SVector(cos_ * a[1] + sin_ * a[2], -sin_ * a[1] + cos_ * a[2]) - # Store translated coordinate for easy use of exact solution - x_trans = x_rot - a_rot * t + # Store translated coordinate for easy use of exact solution + x_trans = x_rot - a_rot * t - c = 1.0 - A = 0.5 - L = 2 - f = 1/L - omega = 2 * pi * f - scalar = c + A * sin(omega * sum(x_trans)) + c = 1.0 + A = 0.5 + L = 2 + f = 1 / L + omega = 2 * pi * f + scalar = c + A * sin(omega * sum(x_trans)) - return SVector(scalar) + return SVector(scalar) end end # module TrixiExtensionAdvectionRotated @@ -70,7 +70,7 @@ advection_velocity = Tuple(T * [0.2, -0.7]) equations = LinearScalarAdvectionEquation2D(advection_velocity) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) mapping(xi, eta) = T * SVector(xi, eta) @@ -82,7 +82,6 @@ mesh = StructuredMesh(cells_per_dimension, mapping) # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -94,26 +93,26 @@ ode = semidiscretize(semi, (0.0, 1.0)); summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); # Print the timer summary summary_callback() diff --git a/examples/structured_2d_dgsem/elixir_advection_waving_flag.jl b/examples/structured_2d_dgsem/elixir_advection_waving_flag.jl index d0db19ea635..50393d50a19 100644 --- a/examples/structured_2d_dgsem/elixir_advection_waving_flag.jl +++ b/examples/structured_2d_dgsem/elixir_advection_waving_flag.jl @@ -11,14 +11,14 @@ equations = LinearScalarAdvectionEquation2D(advection_velocity) initial_condition = initial_condition_convergence_test # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) # Deformed rectangle that looks like a waving flag, # lower and upper faces are sinus curves, left and right are vertical lines. f1(s) = SVector(-1.0, s - 1.0) -f2(s) = SVector( 1.0, s + 1.0) +f2(s) = SVector(1.0, s + 1.0) f3(s) = SVector(s, -1.0 + sin(0.5 * pi * s)) -f4(s) = SVector(s, 1.0 + sin(0.5 * pi * s)) +f4(s) = SVector(s, 1.0 + sin(0.5 * pi * s)) cells_per_dimension = (16, 16) @@ -28,7 +28,6 @@ mesh = StructuredMesh(cells_per_dimension, (f1, f2, f3, f4)) # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -40,30 +39,30 @@ ode = semidiscretize(semi, (0.0, 1.0)); summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveRestartCallback allows to save a file from which a Trixi.jl simulation can be restarted -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.4) +stepsize_callback = StepsizeCallback(cfl = 1.4) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_restart, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_restart, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); # Print the timer summary summary_callback() diff --git a/examples/structured_2d_dgsem/elixir_euler_ec.jl b/examples/structured_2d_dgsem/elixir_euler_ec.jl index 2c91349ff98..29686bd3cb7 100644 --- a/examples/structured_2d_dgsem/elixir_euler_ec.jl +++ b/examples/structured_2d_dgsem/elixir_euler_ec.jl @@ -13,25 +13,25 @@ initial_condition = initial_condition_weak_blast_wave # Get the DG approximation space volume_flux = flux_ranocha -solver = DGSEM(polydeg=4, surface_flux=flux_ranocha, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 4, surface_flux = flux_ranocha, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### # Get the curved quad mesh from a mapping function # Mapping as described in https://arxiv.org/abs/2012.12040, but reduced to 2D function mapping(xi_, eta_) - # Transform input variables between -1 and 1 onto [0,3] - xi = 1.5 * xi_ + 1.5 - eta = 1.5 * eta_ + 1.5 + # Transform input variables between -1 and 1 onto [0,3] + xi = 1.5 * xi_ + 1.5 + eta = 1.5 * eta_ + 1.5 - y = eta + 3/8 * (cos(1.5 * pi * (2 * xi - 3)/3) * - cos(0.5 * pi * (2 * eta - 3)/3)) + y = eta + 3 / 8 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3)) - x = xi + 3/8 * (cos(0.5 * pi * (2 * xi - 3)/3) * - cos(2 * pi * (2 * y - 3)/3)) + x = xi + 3 / 8 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3)) - return SVector(x, y) + return SVector(x, y) end cells_per_dimension = (16, 16) @@ -53,15 +53,15 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -72,7 +72,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_euler_free_stream.jl b/examples/structured_2d_dgsem/elixir_euler_free_stream.jl index c4ddb887e5f..3aab4be979e 100644 --- a/examples/structured_2d_dgsem/elixir_euler_free_stream.jl +++ b/examples/structured_2d_dgsem/elixir_euler_free_stream.jl @@ -9,21 +9,21 @@ equations = CompressibleEulerEquations2D(1.4) initial_condition = initial_condition_constant -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) # Mapping as described in https://arxiv.org/abs/2012.12040, but reduced to 2D function mapping(xi_, eta_) - # Transform input variables between -1 and 1 onto [0,3] - xi = 1.5 * xi_ + 1.5 - eta = 1.5 * eta_ + 1.5 + # Transform input variables between -1 and 1 onto [0,3] + xi = 1.5 * xi_ + 1.5 + eta = 1.5 * eta_ + 1.5 - y = eta + 3/8 * (cos(1.5 * pi * (2 * xi - 3)/3) * - cos(0.5 * pi * (2 * eta - 3)/3)) + y = eta + 3 / 8 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3)) - x = xi + 3/8 * (cos(0.5 * pi * (2 * xi - 3)/3) * - cos(2 * pi * (2 * y - 3)/3)) + x = xi + 3 / 8 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3)) - return SVector(x, y) + return SVector(x, y) end cells_per_dimension = (16, 16) @@ -32,7 +32,6 @@ mesh = StructuredMesh(cells_per_dimension, mapping) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -42,16 +41,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=2.0) +stepsize_callback = StepsizeCallback(cfl = 2.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -61,7 +60,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_euler_rayleigh_taylor_instability.jl b/examples/structured_2d_dgsem/elixir_euler_rayleigh_taylor_instability.jl index bb5870ab9d5..6c254e8bd8b 100644 --- a/examples/structured_2d_dgsem/elixir_euler_rayleigh_taylor_instability.jl +++ b/examples/structured_2d_dgsem/elixir_euler_rayleigh_taylor_instability.jl @@ -29,40 +29,40 @@ defined below. """ @inline function initial_condition_rayleigh_taylor_instability(x, t, equations::CompressibleEulerEquations2D, - slope=1000) - tol = 1e2*eps() - - if x[2] < 0.5 - p = 2*x[2] + 1 - else - p = x[2] + 3/2 - end - - # smooth the discontinuity to avoid ambiguity at element interfaces - smoothed_heaviside(x, left, right) = left + 0.5*(1 + tanh(slope * x)) * (right-left) - rho = smoothed_heaviside(x[2] - 0.5, 2.0, 1.0) - - c = sqrt(equations.gamma * p / rho) - # the velocity is multiplied by sin(pi*y)^6 as in Remacle et al. 2003 to ensure that the - # initial condition satisfies reflective boundary conditions at the top/bottom boundaries. - v = -0.025 * c * cos(8*pi*x[1]) * sin(pi*x[2])^6 - u = 0.0 - - return prim2cons(SVector(rho, u, v, p), equations) + slope = 1000) + tol = 1e2 * eps() + + if x[2] < 0.5 + p = 2 * x[2] + 1 + else + p = x[2] + 3 / 2 + end + + # smooth the discontinuity to avoid ambiguity at element interfaces + smoothed_heaviside(x, left, right) = left + 0.5 * (1 + tanh(slope * x)) * (right - left) + rho = smoothed_heaviside(x[2] - 0.5, 2.0, 1.0) + + c = sqrt(equations.gamma * p / rho) + # the velocity is multiplied by sin(pi*y)^6 as in Remacle et al. 2003 to ensure that the + # initial condition satisfies reflective boundary conditions at the top/bottom boundaries. + v = -0.025 * c * cos(8 * pi * x[1]) * sin(pi * x[2])^6 + u = 0.0 + + return prim2cons(SVector(rho, u, v, p), equations) end @inline function source_terms_rayleigh_taylor_instability(u, x, t, equations::CompressibleEulerEquations2D) - g = 1.0 - rho, rho_v1, rho_v2, rho_e = u + g = 1.0 + rho, rho_v1, rho_v2, rho_e = u - return SVector(0.0, 0.0, g*rho, g*rho_v2) + return SVector(0.0, 0.0, g * rho, g * rho_v2) end # numerical parameters volume_flux = flux_ranocha -solver = DGSEM(polydeg=3, surface_flux=flux_hll, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_hll, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) # The domain is [0, 0.25] x [0, 1] mapping(xi, eta) = SVector(0.25 * 0.5 * (1.0 + xi), 0.5 * (1.0 + eta)) @@ -72,12 +72,10 @@ cells_per_dimension = (num_elements_per_dimension, num_elements_per_dimension * mesh = StructuredMesh(cells_per_dimension, mapping) initial_condition = initial_condition_rayleigh_taylor_instability -boundary_conditions = ( - x_neg=boundary_condition_slip_wall, - x_pos=boundary_condition_slip_wall, - y_neg=boundary_condition_slip_wall, - y_pos=boundary_condition_slip_wall, - ) +boundary_conditions = (x_neg = boundary_condition_slip_wall, + x_pos = boundary_condition_slip_wall, + y_neg = boundary_condition_slip_wall, + y_pos = boundary_condition_slip_wall) # # Alternative setup: left/right periodic BCs and Dirichlet BCs on the top/bottom. # boundary_conditions = ( @@ -88,8 +86,8 @@ boundary_conditions = ( # ) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver; - source_terms=source_terms_rayleigh_taylor_instability, - boundary_conditions=boundary_conditions) + source_terms = source_terms_rayleigh_taylor_instability, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -100,9 +98,9 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -111,7 +109,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, RDPK3SpFSAL49(); abstol=1.0e-6, reltol=1.0e-6, - ode_default_options()..., callback=callbacks); +sol = solve(ode, RDPK3SpFSAL49(); abstol = 1.0e-6, reltol = 1.0e-6, + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_euler_sedov.jl b/examples/structured_2d_dgsem/elixir_euler_sedov.jl index efc3b6627c0..42094d7191c 100644 --- a/examples/structured_2d_dgsem/elixir_euler_sedov.jl +++ b/examples/structured_2d_dgsem/elixir_euler_sedov.jl @@ -14,25 +14,25 @@ The Sedov blast wave setup based on Flash - https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 """ function initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEquations2D) - # Set up polar coordinates - inicenter = SVector(0.0, 0.0) - x_norm = x[1] - inicenter[1] - y_norm = x[2] - inicenter[2] - r = sqrt(x_norm^2 + y_norm^2) - - # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 - r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) - E = 1.0 - p0_inner = 3 * (equations.gamma - 1) * E / (3 * pi * r0^2) - p0_outer = 1.0e-5 # = true Sedov setup - - # Calculate primitive variables - rho = 1.0 - v1 = 0.0 - v2 = 0.0 - p = r > r0 ? p0_outer : p0_inner - - return prim2cons(SVector(rho, v1, v2, p), equations) + # Set up polar coordinates + inicenter = SVector(0.0, 0.0) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + + # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 + r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) + E = 1.0 + p0_inner = 3 * (equations.gamma - 1) * E / (3 * pi * r0^2) + p0_outer = 1.0e-5 # = true Sedov setup + + # Calculate primitive variables + rho = 1.0 + v1 = 0.0 + v2 = 0.0 + p = r > r0 ? p0_outer : p0_inner + + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_sedov_blast_wave @@ -43,29 +43,30 @@ volume_flux = flux_ranocha polydeg = 4 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=1.0, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 1.0, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) -solver = DGSEM(polydeg=polydeg, surface_flux=surface_flux, volume_integral=volume_integral) +solver = DGSEM(polydeg = polydeg, surface_flux = surface_flux, + volume_integral = volume_integral) # Get the curved quad mesh from a mapping function # Mapping as described in https://arxiv.org/abs/2012.12040 function mapping(xi, eta) - y = eta + 0.125 * (cos(1.5 * pi * xi) * cos(0.5 * pi * eta)) + y = eta + 0.125 * (cos(1.5 * pi * xi) * cos(0.5 * pi * eta)) - x = xi + 0.125 * (cos(0.5 * pi * xi) * cos(2 * pi * y)) + x = xi + 0.125 * (cos(0.5 * pi * xi) * cos(2 * pi * y)) - return SVector(x, y) + return SVector(x, y) end cells_per_dimension = (16, 16) -mesh = StructuredMesh(cells_per_dimension, mapping, periodicity=true) +mesh = StructuredMesh(cells_per_dimension, mapping, periodicity = true) # create the semidiscretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -79,15 +80,15 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 300 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=300, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 300, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -98,7 +99,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_euler_source_terms.jl b/examples/structured_2d_dgsem/elixir_euler_source_terms.jl index 70d3e060dd0..6827848e185 100644 --- a/examples/structured_2d_dgsem/elixir_euler_source_terms.jl +++ b/examples/structured_2d_dgsem/elixir_euler_source_terms.jl @@ -11,7 +11,7 @@ equations = CompressibleEulerEquations2D(1.4) initial_condition = initial_condition_convergence_test -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (0.0, 0.0) coordinates_max = (2.0, 2.0) @@ -20,10 +20,8 @@ cells_per_dimension = (16, 16) mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max) - semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -34,16 +32,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -53,7 +51,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_euler_source_terms_nonperiodic.jl b/examples/structured_2d_dgsem/elixir_euler_source_terms_nonperiodic.jl index 94537ecef0d..f42d223611a 100644 --- a/examples/structured_2d_dgsem/elixir_euler_source_terms_nonperiodic.jl +++ b/examples/structured_2d_dgsem/elixir_euler_source_terms_nonperiodic.jl @@ -12,21 +12,20 @@ initial_condition = initial_condition_convergence_test # you can either use a single function to impose the BCs weakly in all # 2*ndims == 4 directions or you can pass a tuple containing BCs for each direction boundary_condition = BoundaryConditionDirichlet(initial_condition) -boundary_conditions = (x_neg=boundary_condition, - x_pos=boundary_condition, - y_neg=boundary_condition, - y_pos=boundary_condition,) +boundary_conditions = (x_neg = boundary_condition, + x_pos = boundary_condition, + y_neg = boundary_condition, + y_pos = boundary_condition) -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (0.0, 0.0) coordinates_max = (2.0, 2.0) -mesh = StructuredMesh((16, 16), coordinates_min, coordinates_max, periodicity=false) +mesh = StructuredMesh((16, 16), coordinates_min, coordinates_max, periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test, - boundary_conditions=boundary_conditions) - + source_terms = source_terms_convergence_test, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -37,19 +36,19 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -58,7 +57,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_euler_source_terms_parallelogram.jl b/examples/structured_2d_dgsem/elixir_euler_source_terms_parallelogram.jl index a9c08049f41..5d6b0908389 100644 --- a/examples/structured_2d_dgsem/elixir_euler_source_terms_parallelogram.jl +++ b/examples/structured_2d_dgsem/elixir_euler_source_terms_parallelogram.jl @@ -9,7 +9,7 @@ equations = CompressibleEulerEquations2D(1.4) initial_condition = initial_condition_convergence_test -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) # Define faces for a parallelogram that looks like this # @@ -24,10 +24,8 @@ cells_per_dimension = (16, 16) mesh = StructuredMesh(cells_per_dimension, mapping) - semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -38,16 +36,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -57,7 +55,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_euler_source_terms_rotated.jl b/examples/structured_2d_dgsem/elixir_euler_source_terms_rotated.jl index fdd189ffb55..f2e3c448893 100644 --- a/examples/structured_2d_dgsem/elixir_euler_source_terms_rotated.jl +++ b/examples/structured_2d_dgsem/elixir_euler_source_terms_rotated.jl @@ -2,7 +2,6 @@ using OrdinaryDiffEq using Trixi - # Define new structs inside a module to allow re-evaluating the file. # This module name needs to be unique among all examples, otherwise Julia will throw warnings # if multiple test cases using the same module name are run in the same session. @@ -12,68 +11,69 @@ using Trixi # initial_condition_convergence_test transformed to the rotated rectangle struct InitialConditionSourceTermsRotated - sin_alpha::Float64 - cos_alpha::Float64 + sin_alpha::Float64 + cos_alpha::Float64 end function InitialConditionSourceTermsRotated(alpha) - sin_alpha, cos_alpha = sincos(alpha) + sin_alpha, cos_alpha = sincos(alpha) - InitialConditionSourceTermsRotated(sin_alpha, cos_alpha) + InitialConditionSourceTermsRotated(sin_alpha, cos_alpha) end -function (initial_condition::InitialConditionSourceTermsRotated)(x, t, equations::CompressibleEulerEquations2D) - sin_ = initial_condition.sin_alpha - cos_ = initial_condition.cos_alpha +function (initial_condition::InitialConditionSourceTermsRotated)(x, t, + equations::CompressibleEulerEquations2D) + sin_ = initial_condition.sin_alpha + cos_ = initial_condition.cos_alpha - # Rotate back to unit square and translate from [-1, 1]^2 to [0, 2]^2 + # Rotate back to unit square and translate from [-1, 1]^2 to [0, 2]^2 - # Clockwise rotation by α and translation by 1 - # Multiply with [ cos(α) sin(α); - # -sin(α) cos(α)] - x1 = cos_ * x[1] + sin_ * x[2] + 1 - x2 = -sin_ * x[1] + cos_ * x[2] + 1 + # Clockwise rotation by α and translation by 1 + # Multiply with [ cos(α) sin(α); + # -sin(α) cos(α)] + x1 = cos_ * x[1] + sin_ * x[2] + 1 + x2 = -sin_ * x[1] + cos_ * x[2] + 1 - rho, rho_v1, rho_v2, rho_e = initial_condition_convergence_test(SVector(x1, x2), t, equations) + rho, rho_v1, rho_v2, rho_e = initial_condition_convergence_test(SVector(x1, x2), t, + equations) - # Rotate velocity vector counterclockwise - # Multiply with [ cos(α) -sin(α); - # sin(α) cos(α)] - rho_v1_rot = cos_ * rho_v1 - sin_ * rho_v2 - rho_v2_rot = sin_ * rho_v1 + cos_ * rho_v2 + # Rotate velocity vector counterclockwise + # Multiply with [ cos(α) -sin(α); + # sin(α) cos(α)] + rho_v1_rot = cos_ * rho_v1 - sin_ * rho_v2 + rho_v2_rot = sin_ * rho_v1 + cos_ * rho_v2 - return SVector(rho, rho_v1_rot, rho_v2_rot, rho_e) + return SVector(rho, rho_v1_rot, rho_v2_rot, rho_e) end +@inline function (source_terms::InitialConditionSourceTermsRotated)(u, x, t, + equations::CompressibleEulerEquations2D) + sin_ = source_terms.sin_alpha + cos_ = source_terms.cos_alpha -@inline function (source_terms::InitialConditionSourceTermsRotated)(u, x, t, equations::CompressibleEulerEquations2D) - sin_ = source_terms.sin_alpha - cos_ = source_terms.cos_alpha - - # Rotate back to unit square and translate from [-1, 1]^2 to [0, 2]^2 + # Rotate back to unit square and translate from [-1, 1]^2 to [0, 2]^2 - # Clockwise rotation by α and translation by 1 - # Multiply with [ cos(α) sin(α); - # -sin(α) cos(α)] - x1 = cos_ * x[1] + sin_ * x[2] + 1 - x2 = -sin_ * x[1] + cos_ * x[2] + 1 + # Clockwise rotation by α and translation by 1 + # Multiply with [ cos(α) sin(α); + # -sin(α) cos(α)] + x1 = cos_ * x[1] + sin_ * x[2] + 1 + x2 = -sin_ * x[1] + cos_ * x[2] + 1 - du1, du2, du3, du4 = source_terms_convergence_test(u, SVector(x1, x2), t, equations) + du1, du2, du3, du4 = source_terms_convergence_test(u, SVector(x1, x2), t, equations) - # Rotate velocity vector counterclockwise - # Multiply with [ cos(α) -sin(α); - # sin(α) cos(α)] - du2_rotated = cos_ * du2 - sin_ * du3 - du3_rotated = sin_ * du2 + cos_ * du3 + # Rotate velocity vector counterclockwise + # Multiply with [ cos(α) -sin(α); + # sin(α) cos(α)] + du2_rotated = cos_ * du2 - sin_ * du3 + du3_rotated = sin_ * du2 + cos_ * du3 - return SVector(du1, du2_rotated, du3_rotated, du4) + return SVector(du1, du2_rotated, du3_rotated, du4) end end # module TrixiExtensionEulerRotated import .TrixiExtensionEulerRotated - ############################################################################### # semidiscretization of the compressible Euler equations @@ -85,8 +85,7 @@ sin_ = initial_condition_source_terms.sin_alpha cos_ = initial_condition_source_terms.cos_alpha T = [cos_ -sin_; sin_ cos_] - -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) mapping(xi, eta) = T * SVector(xi, eta) @@ -94,10 +93,8 @@ cells_per_dimension = (16, 16) mesh = StructuredMesh(cells_per_dimension, mapping) - semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_source_terms, solver, - source_terms=initial_condition_source_terms) - + source_terms = initial_condition_source_terms) ############################################################################### # ODE solvers, callbacks etc. @@ -108,16 +105,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -127,7 +124,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_euler_source_terms_waving_flag.jl b/examples/structured_2d_dgsem/elixir_euler_source_terms_waving_flag.jl index 505e28ecd8d..4a78b65ae0b 100644 --- a/examples/structured_2d_dgsem/elixir_euler_source_terms_waving_flag.jl +++ b/examples/structured_2d_dgsem/elixir_euler_source_terms_waving_flag.jl @@ -9,23 +9,21 @@ equations = CompressibleEulerEquations2D(1.4) initial_condition = initial_condition_convergence_test -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) # Deformed rectangle that looks like a waving flag, # lower and upper faces are sinus curves, left and right are vertical lines. f1(s) = SVector(-1.0, s - 1.0) -f2(s) = SVector( 1.0, s + 1.0) +f2(s) = SVector(1.0, s + 1.0) f3(s) = SVector(s, -1.0 + sin(0.5 * pi * s)) -f4(s) = SVector(s, 1.0 + sin(0.5 * pi * s)) +f4(s) = SVector(s, 1.0 + sin(0.5 * pi * s)) cells_per_dimension = (16, 16) mesh = StructuredMesh(cells_per_dimension, (f1, f2, f3, f4)) - semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -36,16 +34,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -55,7 +53,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_eulermulti_convergence_ec.jl b/examples/structured_2d_dgsem/elixir_eulermulti_convergence_ec.jl new file mode 100644 index 00000000000..95f71f38130 --- /dev/null +++ b/examples/structured_2d_dgsem/elixir_eulermulti_convergence_ec.jl @@ -0,0 +1,55 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler multicomponent equations +equations = CompressibleEulerMulticomponentEquations2D(gammas = (1.4, 1.4), + gas_constants = (0.4, 0.4)) + +initial_condition = initial_condition_convergence_test + +volume_flux = flux_ranocha +solver = DGSEM(polydeg = 3, surface_flux = flux_ranocha, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) + +cells_per_dimension = (16, 16) +coordinates_min = (-1.0, -1.0) +coordinates_max = (1.0, 1.0) +mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + source_terms = source_terms_convergence_test) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 0.4) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) + +stepsize_callback = StepsizeCallback(cfl = 0.5) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + save_solution, + stepsize_callback) + +############################################################################### +# run the simulation + +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); +summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_eulerpolytropic_convergence.jl b/examples/structured_2d_dgsem/elixir_eulerpolytropic_convergence.jl new file mode 100644 index 00000000000..4fc9281e7a0 --- /dev/null +++ b/examples/structured_2d_dgsem/elixir_eulerpolytropic_convergence.jl @@ -0,0 +1,63 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the polytropic Euler equations + +gamma = 1.4 +kappa = 0.5 # Scaling factor for the pressure. +equations = PolytropicEulerEquations2D(gamma, kappa) + +initial_condition = initial_condition_convergence_test + +volume_flux = flux_winters_etal +solver = DGSEM(polydeg = 3, surface_flux = flux_hll, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) + +coordinates_min = (0.0, 0.0) +coordinates_max = (1.0, 1.0) + +cells_per_dimension = (4, 4) + +mesh = StructuredMesh(cells_per_dimension, + coordinates_min, + coordinates_max) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + source_terms = source_terms_convergence_test) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 0.1) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_errors = (:l2_error_primitive, + :linf_error_primitive)) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) + +stepsize_callback = StepsizeCallback(cfl = 0.1) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + save_solution, + stepsize_callback) + +############################################################################### +# run the simulation + +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); +summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_eulerpolytropic_ec.jl b/examples/structured_2d_dgsem/elixir_eulerpolytropic_ec.jl new file mode 100644 index 00000000000..b96f1d3cd68 --- /dev/null +++ b/examples/structured_2d_dgsem/elixir_eulerpolytropic_ec.jl @@ -0,0 +1,80 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the polytropic Euler equations + +gamma = 1.4 +kappa = 0.5 # Scaling factor for the pressure. +equations = PolytropicEulerEquations2D(gamma, kappa) + +initial_condition = initial_condition_weak_blast_wave + +############################################################################### +# Get the DG approximation space + +volume_flux = flux_winters_etal +solver = DGSEM(polydeg = 4, surface_flux = flux_winters_etal, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) + +############################################################################### +# Get the curved quad mesh from a mapping function + +# Mapping as described in https://arxiv.org/abs/2012.12040, but reduced to 2D +function mapping(xi_, eta_) + # Transform input variables between -1 and 1 onto [0,3] + xi = 1.5 * xi_ + 1.5 + eta = 1.5 * eta_ + 1.5 + + y = eta + 3 / 8 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3)) + + x = xi + 3 / 8 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3)) + + return SVector(x, y) +end + +cells_per_dimension = (16, 16) + +# Create curved mesh with 16 x 16 elements +mesh = StructuredMesh(cells_per_dimension, mapping) + +############################################################################### +# create the semi discretization object + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 2.0) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true) + +stepsize_callback = StepsizeCallback(cfl = 1.0) + +callbacks = CallbackSet(summary_callback, + analysis_callback, + alive_callback, + save_solution, + stepsize_callback) + +############################################################################### +# run the simulation + +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); +summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_eulerpolytropic_isothermal_wave.jl b/examples/structured_2d_dgsem/elixir_eulerpolytropic_isothermal_wave.jl new file mode 100644 index 00000000000..4ab90957579 --- /dev/null +++ b/examples/structured_2d_dgsem/elixir_eulerpolytropic_isothermal_wave.jl @@ -0,0 +1,83 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the polytropic Euler equations + +gamma = 1.0 # With gamma = 1 the system is isothermal. +kappa = 1.0 # Scaling factor for the pressure. +equations = PolytropicEulerEquations2D(gamma, kappa) + +# Linear pressure wave in the negative x-direction. +function initial_condition_wave(x, t, equations::PolytropicEulerEquations2D) + rho = 1.0 + v1 = 0.0 + if x[1] > 0.0 + rho = ((1.0 + 0.01 * sin(x[1] * 2 * pi)) / equations.kappa)^(1 / equations.gamma) + v1 = ((0.01 * sin((x[1] - 1 / 2) * 2 * pi)) / equations.kappa) + end + v2 = 0.0 + + return prim2cons(SVector(rho, v1, v2), equations) +end +initial_condition = initial_condition_wave + +volume_flux = flux_winters_etal +solver = DGSEM(polydeg = 2, surface_flux = flux_hll, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) + +coordinates_min = (-2.0, -1.0) +coordinates_max = (2.0, 1.0) + +cells_per_dimension = (64, 32) + +boundary_conditions = (x_neg = boundary_condition_periodic, + x_pos = boundary_condition_periodic, + y_neg = boundary_condition_periodic, + y_pos = boundary_condition_periodic) + +mesh = StructuredMesh(cells_per_dimension, + coordinates_min, + coordinates_max) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_conditions) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 1.0) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 200 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 50, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) + +stepsize_callback = StepsizeCallback(cfl = 1.7) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + save_solution, + stepsize_callback) + +stage_limiter! = PositivityPreservingLimiterZhangShu(thresholds = (1.0e-4, 1.0e-4), + variables = (Trixi.density, pressure)) + +############################################################################### +# run the simulation + +sol = solve(ode, CarpenterKennedy2N54(stage_limiter!, williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); + +# Print the timer summary +summary_callback() diff --git a/examples/structured_2d_dgsem/elixir_eulerpolytropic_wave.jl b/examples/structured_2d_dgsem/elixir_eulerpolytropic_wave.jl new file mode 100644 index 00000000000..fd332b20aef --- /dev/null +++ b/examples/structured_2d_dgsem/elixir_eulerpolytropic_wave.jl @@ -0,0 +1,80 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the polytropic Euler equations + +gamma = 2.0 # Adiabatic monatomic gas in 2d. +kappa = 0.5 # Scaling factor for the pressure. +equations = PolytropicEulerEquations2D(gamma, kappa) + +# Linear pressure wave in the negative x-direction. +function initial_condition_wave(x, t, equations::PolytropicEulerEquations2D) + rho = 1.0 + v1 = 0.0 + if x[1] > 0.0 + rho = ((1.0 + 0.01 * sin(x[1] * 2 * pi)) / equations.kappa)^(1 / equations.gamma) + v1 = ((0.01 * sin((x[1] - 1 / 2) * 2 * pi)) / equations.kappa) + end + v2 = 0.0 + + return prim2cons(SVector(rho, v1, v2), equations) +end +initial_condition = initial_condition_wave + +volume_flux = flux_winters_etal +solver = DGSEM(polydeg = 2, surface_flux = flux_hll, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) + +coordinates_min = (-2.0, -1.0) +coordinates_max = (2.0, 1.0) + +cells_per_dimension = (64, 32) + +boundary_conditions = (x_neg = boundary_condition_periodic, + x_pos = boundary_condition_periodic, + y_neg = boundary_condition_periodic, + y_pos = boundary_condition_periodic) + +mesh = StructuredMesh(cells_per_dimension, + coordinates_min, + coordinates_max) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_conditions) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 1.0) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 200 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 50, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) + +stepsize_callback = StepsizeCallback(cfl = 1.7) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + save_solution, + stepsize_callback) + +############################################################################### +# run the simulation + +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); + +# Print the timer summary +summary_callback() diff --git a/examples/structured_2d_dgsem/elixir_hypdiff_harmonic_nonperiodic.jl b/examples/structured_2d_dgsem/elixir_hypdiff_harmonic_nonperiodic.jl index 6730b1c4beb..ccb74fa4b68 100644 --- a/examples/structured_2d_dgsem/elixir_hypdiff_harmonic_nonperiodic.jl +++ b/examples/structured_2d_dgsem/elixir_hypdiff_harmonic_nonperiodic.jl @@ -7,43 +7,42 @@ using Trixi equations = HyperbolicDiffusionEquations2D() -@inline function initial_condition_harmonic_nonperiodic(x, t, equations::HyperbolicDiffusionEquations2D) - # elliptic equation: -ν Δϕ = 0 in Ω, u = g on ∂Ω - if t == 0.0 - phi = 1.0 - q1 = 1.0 - q2 = 1.0 - else - C = inv(sinh(pi)) - sinpi_x1, cospi_x1 = sincos(pi*x[1]) - sinpi_x2, cospi_x2 = sincos(pi*x[2]) - sinh_pix1 = sinh(pi*x[1]) - cosh_pix1 = cosh(pi*x[1]) - sinh_pix2 = sinh(pi*x[2]) - cosh_pix2 = cosh(pi*x[2]) - phi = C * (sinh_pix1 * sinpi_x2 + sinh_pix2 * sinpi_x1) - q1 = C * pi * (cosh_pix1 * sinpi_x2 + sinh_pix2 * cospi_x1) - q2 = C * pi * (sinh_pix1 * cospi_x2 + cosh_pix2 * sinpi_x1) - end - return SVector(phi, q1, q2) +@inline function initial_condition_harmonic_nonperiodic(x, t, + equations::HyperbolicDiffusionEquations2D) + # elliptic equation: -ν Δϕ = 0 in Ω, u = g on ∂Ω + if t == 0.0 + phi = 1.0 + q1 = 1.0 + q2 = 1.0 + else + C = inv(sinh(pi)) + sinpi_x1, cospi_x1 = sincos(pi * x[1]) + sinpi_x2, cospi_x2 = sincos(pi * x[2]) + sinh_pix1 = sinh(pi * x[1]) + cosh_pix1 = cosh(pi * x[1]) + sinh_pix2 = sinh(pi * x[2]) + cosh_pix2 = cosh(pi * x[2]) + phi = C * (sinh_pix1 * sinpi_x2 + sinh_pix2 * sinpi_x1) + q1 = C * pi * (cosh_pix1 * sinpi_x2 + sinh_pix2 * cospi_x1) + q2 = C * pi * (sinh_pix1 * cospi_x2 + cosh_pix2 * sinpi_x1) + end + return SVector(phi, q1, q2) end initial_condition = initial_condition_harmonic_nonperiodic boundary_conditions = BoundaryConditionDirichlet(initial_condition) -solver = DGSEM(polydeg=4, surface_flux=flux_godunov) +solver = DGSEM(polydeg = 4, surface_flux = flux_godunov) coordinates_min = (0.0, 0.0) coordinates_max = (1.0, 1.0) cells_per_dimension = (8, 8) mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max, - periodicity=false) - + periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions, - source_terms=source_terms_harmonic) - + boundary_conditions = boundary_conditions, + source_terms = source_terms_harmonic) ############################################################################### # ODE solvers, callbacks etc. @@ -54,30 +53,29 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() resid_tol = 5.0e-12 -steady_state_callback = SteadyStateCallback(abstol=resid_tol, reltol=0.0) +steady_state_callback = SteadyStateCallback(abstol = resid_tol, reltol = 0.0) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, steady_state_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_hypdiff_nonperiodic.jl b/examples/structured_2d_dgsem/elixir_hypdiff_nonperiodic.jl index ba77dca9a99..681b3bd781b 100644 --- a/examples/structured_2d_dgsem/elixir_hypdiff_nonperiodic.jl +++ b/examples/structured_2d_dgsem/elixir_hypdiff_nonperiodic.jl @@ -9,40 +9,38 @@ equations = HyperbolicDiffusionEquations2D() initial_condition = initial_condition_poisson_nonperiodic -solver = DGSEM(polydeg=6, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 6, surface_flux = flux_lax_friedrichs) -boundary_conditions = (x_neg=boundary_condition_poisson_nonperiodic, - x_pos=boundary_condition_poisson_nonperiodic, - y_neg=boundary_condition_periodic, - y_pos=boundary_condition_periodic) +boundary_conditions = (x_neg = boundary_condition_poisson_nonperiodic, + x_pos = boundary_condition_poisson_nonperiodic, + y_neg = boundary_condition_periodic, + y_pos = boundary_condition_periodic) ############################################################################### # Get the curved quad mesh from a mapping function # # Mapping as described in https://arxiv.org/abs/2012.12040, but reduced to 2D function mapping(xi_, eta_) - # Transform input variables between -1 and 1 onto [0,3] - xi = 1.5 * xi_ + 1.5 - eta = 1.5 * eta_ + 1.5 + # Transform input variables between -1 and 1 onto [0,3] + xi = 1.5 * xi_ + 1.5 + eta = 1.5 * eta_ + 1.5 - y = eta + 3/8 * (cos(1.5 * pi * (2 * xi - 3)/3) * - cos(0.5 * pi * (2 * eta - 3)/3)) + y = eta + 3 / 8 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3)) - x = xi + 3/8 * (cos(0.5 * pi * (2 * xi - 3)/3) * - cos(2 * pi * (2 * y - 3)/3)) + x = xi + 3 / 8 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3)) - return SVector(x, y) + return SVector(x, y) end # Create curved mesh with 8 x 8 elements cells_per_dimension = (8, 8) -mesh = StructuredMesh(cells_per_dimension, mapping, periodicity=(false, true)) - +mesh = StructuredMesh(cells_per_dimension, mapping, periodicity = (false, true)) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_poisson_nonperiodic, - boundary_conditions=boundary_conditions) - + source_terms = source_terms_poisson_nonperiodic, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -53,31 +51,30 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() resid_tol = 5.0e-12 -steady_state_callback = SteadyStateCallback(abstol=resid_tol, reltol=0.0) +steady_state_callback = SteadyStateCallback(abstol = resid_tol, reltol = 0.0) analysis_interval = 4000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy, energy_total)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy, energy_total)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=4000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 4000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.9) +stepsize_callback = StepsizeCallback(cfl = 1.9) callbacks = CallbackSet(summary_callback, steady_state_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation sol = Trixi.solve(ode, Trixi.HypDiffN3Erk3Sstar52(), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_mhd_alfven_wave.jl b/examples/structured_2d_dgsem/elixir_mhd_alfven_wave.jl index 259875050c6..e8f2b2ecc3a 100644 --- a/examples/structured_2d_dgsem/elixir_mhd_alfven_wave.jl +++ b/examples/structured_2d_dgsem/elixir_mhd_alfven_wave.jl @@ -5,31 +5,34 @@ using Trixi ############################################################################### # semidiscretization of the compressible ideal GLM-MHD equations -gamma = 5/3 +gamma = 5 / 3 equations = IdealGlmMhdEquations2D(gamma) initial_condition = initial_condition_convergence_test # Get the DG approximation space volume_flux = (flux_central, flux_nonconservative_powell) -solver = DGSEM(polydeg=3, surface_flux=(flux_lax_friedrichs, flux_nonconservative_powell), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, + surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) # Get the curved quad mesh from a mapping function # Mapping as described in https://arxiv.org/abs/1809.01178 function mapping(xi_, eta_) - # Transform input variables between -1 and 1 onto [0, sqrt(2)] - # Note, we use the domain [0, sqrt(2)]^2 for the Alfvén wave convergence test case - xi = 0.5 * sqrt(2) * xi_ + 0.5 * sqrt(2) - eta = 0.5 * sqrt(2) * eta_ + 0.5 * sqrt(2) + # Transform input variables between -1 and 1 onto [0, sqrt(2)] + # Note, we use the domain [0, sqrt(2)]^2 for the Alfvén wave convergence test case + xi = 0.5 * sqrt(2) * xi_ + 0.5 * sqrt(2) + eta = 0.5 * sqrt(2) * eta_ + 0.5 * sqrt(2) - y = eta + sqrt(2)/12 * (cos(1.5 * pi * (2 * xi - sqrt(2))/sqrt(2)) * - cos(0.5 * pi * (2 * eta - sqrt(2))/sqrt(2))) + y = eta + + sqrt(2) / 12 * (cos(1.5 * pi * (2 * xi - sqrt(2)) / sqrt(2)) * + cos(0.5 * pi * (2 * eta - sqrt(2)) / sqrt(2))) - x = xi + sqrt(2)/12 * (cos(0.5 * pi * (2 * xi - sqrt(2))/sqrt(2)) * - cos(2 * pi * (2 * y - sqrt(2))/sqrt(2))) + x = xi + + sqrt(2) / 12 * (cos(0.5 * pi * (2 * xi - sqrt(2)) / sqrt(2)) * + cos(2 * pi * (2 * y - sqrt(2)) / sqrt(2))) - return SVector(x, y) + return SVector(x, y) end cells_per_dimension = (4, 4) @@ -47,21 +50,24 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=false, - extra_analysis_integrals=(entropy, energy_total, - energy_kinetic, energy_internal, - energy_magnetic, cross_helicity)) - -alive_callback = AliveCallback(analysis_interval=analysis_interval) - -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = false, + extra_analysis_integrals = (entropy, energy_total, + energy_kinetic, + energy_internal, + energy_magnetic, + cross_helicity)) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) cfl = 2.0 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -73,7 +79,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_mhd_ec.jl b/examples/structured_2d_dgsem/elixir_mhd_ec.jl index 634738e5c8b..a6c31744ca5 100644 --- a/examples/structured_2d_dgsem/elixir_mhd_ec.jl +++ b/examples/structured_2d_dgsem/elixir_mhd_ec.jl @@ -8,45 +8,46 @@ using Trixi equations = IdealGlmMhdEquations2D(1.4) function initial_condition_shifted_weak_blast_wave(x, t, equations::IdealGlmMhdEquations2D) - # Adapted MHD version of the weak blast wave from Hennemann & Gassner JCP paper 2020 (Sec. 6.3) - # Same discontinuity in the velocities but with magnetic fields - # Set up polar coordinates - inicenter = (1.5, 1.5) - x_norm = x[1] - inicenter[1] - y_norm = x[2] - inicenter[2] - r = sqrt(x_norm^2 + y_norm^2) - phi = atan(y_norm, x_norm) - - # Calculate primitive variables - rho = r > 0.5 ? 1.0 : 1.1691 - v1 = r > 0.5 ? 0.0 : 0.1882 * cos(phi) - v2 = r > 0.5 ? 0.0 : 0.1882 * sin(phi) - p = r > 0.5 ? 1.0 : 1.245 - - return prim2cons(SVector(rho, v1, v2, 0.0, p, 1.0, 1.0, 1.0, 0.0), equations) + # Adapted MHD version of the weak blast wave from Hennemann & Gassner JCP paper 2020 (Sec. 6.3) + # Same discontinuity in the velocities but with magnetic fields + # Set up polar coordinates + inicenter = (1.5, 1.5) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + phi = atan(y_norm, x_norm) + + # Calculate primitive variables + rho = r > 0.5 ? 1.0 : 1.1691 + v1 = r > 0.5 ? 0.0 : 0.1882 * cos(phi) + v2 = r > 0.5 ? 0.0 : 0.1882 * sin(phi) + p = r > 0.5 ? 1.0 : 1.245 + + return prim2cons(SVector(rho, v1, v2, 0.0, p, 1.0, 1.0, 1.0, 0.0), equations) end initial_condition = initial_condition_shifted_weak_blast_wave # Get the DG approximation space volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) -solver = DGSEM(polydeg=5, surface_flux=(flux_hindenlang_gassner, flux_nonconservative_powell), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 5, + surface_flux = (flux_hindenlang_gassner, flux_nonconservative_powell), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) # Get the curved quad mesh from a mapping function # Mapping as described in https://arxiv.org/abs/2012.12040, but reduced to 2D function mapping(xi_, eta_) - # Transform input variables between -1 and 1 onto [0,3] - xi = 1.5 * xi_ + 1.5 - eta = 1.5 * eta_ + 1.5 + # Transform input variables between -1 and 1 onto [0,3] + xi = 1.5 * xi_ + 1.5 + eta = 1.5 * eta_ + 1.5 - y = eta + 3/8 * (cos(1.5 * pi * (2 * xi - 3)/3) * - cos(0.5 * pi * (2 * eta - 3)/3)) + y = eta + 3 / 8 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3)) - x = xi + 3/8 * (cos(0.5 * pi * (2 * xi - 3)/3) * - cos(2 * pi * (2 * y - 3)/3)) + x = xi + 3 / 8 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3)) - return SVector(x, y) + return SVector(x, y) end # Create curved mesh with 8 x 8 elements @@ -65,21 +66,24 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=false, - extra_analysis_integrals=(entropy, energy_total, - energy_kinetic, energy_internal, - energy_magnetic, cross_helicity)) - -alive_callback = AliveCallback(analysis_interval=analysis_interval) - -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = false, + extra_analysis_integrals = (entropy, energy_total, + energy_kinetic, + energy_internal, + energy_magnetic, + cross_helicity)) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) cfl = 1.0 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -91,7 +95,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_mhd_ec_shockcapturing.jl b/examples/structured_2d_dgsem/elixir_mhd_ec_shockcapturing.jl index 084aeca90b9..6668014a0b6 100644 --- a/examples/structured_2d_dgsem/elixir_mhd_ec_shockcapturing.jl +++ b/examples/structured_2d_dgsem/elixir_mhd_ec_shockcapturing.jl @@ -2,7 +2,6 @@ using OrdinaryDiffEq using Trixi - ############################################################################### # semidiscretization of the compressible ideal GLM-MHD equations equations = IdealGlmMhdEquations2D(1.4) @@ -10,17 +9,17 @@ equations = IdealGlmMhdEquations2D(1.4) initial_condition = initial_condition_weak_blast_wave surface_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) -volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) +volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) polydeg = 4 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) # Get the curved quad mesh from a mapping function @@ -31,16 +30,14 @@ function mapping(xi, eta) x = 2.0 * xi + 1.0 / 6.0 * (cos(0.5 * pi * xi) * cos(2 * pi * y)) return SVector(x, y) - end +end cells_per_dimension = (16, 16) -mesh = StructuredMesh(cells_per_dimension, mapping, periodicity=true) - +mesh = StructuredMesh(cells_per_dimension, mapping, periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -50,14 +47,14 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) cfl = 1.0 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -68,7 +65,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_shallowwater_conical_island.jl b/examples/structured_2d_dgsem/elixir_shallowwater_conical_island.jl index 44bc7a12b35..e65ed19221e 100644 --- a/examples/structured_2d_dgsem/elixir_shallowwater_conical_island.jl +++ b/examples/structured_2d_dgsem/elixir_shallowwater_conical_island.jl @@ -2,12 +2,12 @@ using OrdinaryDiffEq using Trixi - ############################################################################### - # Semidiscretization of the shallow water equations +############################################################################### +# Semidiscretization of the shallow water equations # # TODO: TrixiShallowWater: wet/dry example elixir -equations = ShallowWaterEquations2D(gravity_constant=9.81, H0=1.4) +equations = ShallowWaterEquations2D(gravity_constant = 9.81, H0 = 1.4) """ initial_condition_conical_island(x, t, equations::ShallowWaterEquations2D) @@ -20,29 +20,29 @@ discontinuous water height is smoothed by a logistic function. This simulation u boundary conditions. """ function initial_condition_conical_island(x, t, equations::ShallowWaterEquations2D) - # Set the background values + # Set the background values - v1 = 0.0 - v2 = 0.0 + v1 = 0.0 + v2 = 0.0 - x1, x2 = x - b = max(0.1, 1.0 - 4.0 * sqrt(x1^2 + x2^2)) + x1, x2 = x + b = max(0.1, 1.0 - 4.0 * sqrt(x1^2 + x2^2)) - # use a logistic function to transfer water height value smoothly - L = equations.H0 # maximum of function - x0 = 0.3 # center point of function - k = -25.0 # sharpness of transfer + # use a logistic function to transfer water height value smoothly + L = equations.H0 # maximum of function + x0 = 0.3 # center point of function + k = -25.0 # sharpness of transfer - H = max(b, L/(1.0 + exp(-k*(sqrt(x1^2+x2^2) - x0)))) + H = max(b, L / (1.0 + exp(-k * (sqrt(x1^2 + x2^2) - x0)))) - # It is mandatory to shift the water level at dry areas to make sure the water height h - # stays positive. The system would not be stable for h set to a hard 0 due to division by h in - # the computation of velocity, e.g., (h v1) / h. Therefore, a small dry state threshold - # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above - # for the ShallowWaterEquations and added to the initial condition if h = 0. - # This default value can be changed within the constructor call depending on the simulation setup. - H = max(H, b + equations.threshold_limiter) - return prim2cons(SVector(H, v1, v2, b), equations) + # It is mandatory to shift the water level at dry areas to make sure the water height h + # stays positive. The system would not be stable for h set to a hard 0 due to division by h in + # the computation of velocity, e.g., (h v1) / h. Therefore, a small dry state threshold + # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above + # for the ShallowWaterEquations and added to the initial condition if h = 0. + # This default value can be changed within the constructor call depending on the simulation setup. + H = max(H, b + equations.threshold_limiter) + return prim2cons(SVector(H, v1, v2, b), equations) end initial_condition = initial_condition_conical_island @@ -51,19 +51,20 @@ initial_condition = initial_condition_conical_island # Get the DG approximation space volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -surface_flux = (FluxHydrostaticReconstruction(flux_hll_chen_noelle, hydrostatic_reconstruction_chen_noelle), +surface_flux = (FluxHydrostaticReconstruction(flux_hll_chen_noelle, + hydrostatic_reconstruction_chen_noelle), flux_nonconservative_chen_noelle) basis = LobattoLegendreBasis(4) indicator_sc = IndicatorHennemannGassnerShallowWater(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=waterheight_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = waterheight_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) @@ -71,7 +72,7 @@ solver = DGSEM(basis, surface_flux, volume_integral) # Get the StructuredMesh and setup a periodic mesh coordinates_min = (-1.0, -1.0) -coordinates_max = (1.0, 1.0) +coordinates_max = (1.0, 1.0) cells_per_dimension = (16, 16) @@ -92,22 +93,22 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) ############################################################################### # run the simulation -stage_limiter! = PositivityPreservingLimiterShallowWater(variables=(Trixi.waterheight,)) +stage_limiter! = PositivityPreservingLimiterShallowWater(variables = (Trixi.waterheight,)) sol = solve(ode, SSPRK43(stage_limiter!); - ode_default_options()..., callback=callbacks); + ode_default_options()..., callback = callbacks); -summary_callback() # print the timer summary \ No newline at end of file +summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_shallowwater_parabolic_bowl.jl b/examples/structured_2d_dgsem/elixir_shallowwater_parabolic_bowl.jl index 15cfe6698fc..bc198f18835 100644 --- a/examples/structured_2d_dgsem/elixir_shallowwater_parabolic_bowl.jl +++ b/examples/structured_2d_dgsem/elixir_shallowwater_parabolic_bowl.jl @@ -7,7 +7,7 @@ using Trixi # # TODO: TrixiShallowWater: wet/dry example elixir -equations = ShallowWaterEquations2D(gravity_constant=9.81) +equations = ShallowWaterEquations2D(gravity_constant = 9.81) """ initial_condition_parabolic_bowl(x, t, equations:: ShallowWaterEquations2D) @@ -28,53 +28,52 @@ The particular setup below is taken from Section 6.2 of curvilinear meshes with wet/dry fronts accelerated by GPUs [DOI: 10.1016/j.jcp.2018.08.038](https://doi.org/10.1016/j.jcp.2018.08.038). """ -function initial_condition_parabolic_bowl(x, t, equations:: ShallowWaterEquations2D) - a = 1.0 - h_0 = 0.1 - sigma = 0.5 - ω = sqrt(2 * equations.gravity * h_0) / a - - v1 = -sigma * ω * sin(ω * t) - v2 = sigma * ω * cos(ω * t) - - b = h_0 * ((x[1])^2 + (x[2])^2) / a^2 - - H = sigma * h_0 / a^2 * (2 * x[1] * cos(ω * t) + 2 * x[2] * sin(ω * t) - sigma) + h_0 - - # It is mandatory to shift the water level at dry areas to make sure the water height h - # stays positive. The system would not be stable for h set to a hard 0 due to division by h in - # the computation of velocity, e.g., (h v1) / h. Therefore, a small dry state threshold - # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above - # for the ShallowWaterEquations and added to the initial condition if h = 0. - # This default value can be changed within the constructor call depending on the simulation setup. - H = max(H, b + equations.threshold_limiter) - return prim2cons(SVector(H, v1, v2, b), equations) +function initial_condition_parabolic_bowl(x, t, equations::ShallowWaterEquations2D) + a = 1.0 + h_0 = 0.1 + sigma = 0.5 + ω = sqrt(2 * equations.gravity * h_0) / a + + v1 = -sigma * ω * sin(ω * t) + v2 = sigma * ω * cos(ω * t) + + b = h_0 * ((x[1])^2 + (x[2])^2) / a^2 + + H = sigma * h_0 / a^2 * (2 * x[1] * cos(ω * t) + 2 * x[2] * sin(ω * t) - sigma) + h_0 + + # It is mandatory to shift the water level at dry areas to make sure the water height h + # stays positive. The system would not be stable for h set to a hard 0 due to division by h in + # the computation of velocity, e.g., (h v1) / h. Therefore, a small dry state threshold + # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above + # for the ShallowWaterEquations and added to the initial condition if h = 0. + # This default value can be changed within the constructor call depending on the simulation setup. + H = max(H, b + equations.threshold_limiter) + return prim2cons(SVector(H, v1, v2, b), equations) end initial_condition = initial_condition_parabolic_bowl - ############################################################################### # Get the DG approximation space volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -surface_flux = (FluxHydrostaticReconstruction(flux_hll_chen_noelle, hydrostatic_reconstruction_chen_noelle), +surface_flux = (FluxHydrostaticReconstruction(flux_hll_chen_noelle, + hydrostatic_reconstruction_chen_noelle), flux_nonconservative_chen_noelle) basis = LobattoLegendreBasis(4) indicator_sc = IndicatorHennemannGassnerShallowWater(equations, basis, - alpha_max=0.6, - alpha_min=0.001, - alpha_smooth=true, - variable=waterheight_pressure) + alpha_max = 0.6, + alpha_min = 0.001, + alpha_smooth = true, + variable = waterheight_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) - ############################################################################### coordinates_min = (-2.0, -2.0) @@ -96,24 +95,25 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=false, - extra_analysis_integrals=(energy_kinetic, - energy_internal)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = false, + extra_analysis_integrals = (energy_kinetic, + energy_internal)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) -stage_limiter! = PositivityPreservingLimiterShallowWater(variables=(Trixi.waterheight,)) +stage_limiter! = PositivityPreservingLimiterShallowWater(variables = (Trixi.waterheight,)) ############################################################################### # run the simulation sol = solve(ode, SSPRK43(stage_limiter!); - ode_default_options()..., callback=callbacks); + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_shallowwater_source_terms.jl b/examples/structured_2d_dgsem/elixir_shallowwater_source_terms.jl index 18f48080850..48fe37b9996 100644 --- a/examples/structured_2d_dgsem/elixir_shallowwater_source_terms.jl +++ b/examples/structured_2d_dgsem/elixir_shallowwater_source_terms.jl @@ -5,13 +5,14 @@ using Trixi ############################################################################### # semidiscretization of the shallow water equations -equations = ShallowWaterEquations2D(gravity_constant=9.81) +equations = ShallowWaterEquations2D(gravity_constant = 9.81) initial_condition = initial_condition_convergence_test volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -solver = DGSEM(polydeg=3, surface_flux=(flux_lax_friedrichs, flux_nonconservative_fjordholm_etal), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, + surface_flux = (flux_lax_friedrichs, flux_nonconservative_fjordholm_etal), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (0.0, 0.0) coordinates_max = (sqrt(2.0), sqrt(2.0)) @@ -20,10 +21,8 @@ cells_per_dimension = (8, 8) mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max) - semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -34,16 +33,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=2.0) +stepsize_callback = StepsizeCallback(cfl = 2.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -53,7 +52,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_shallowwater_well_balanced.jl b/examples/structured_2d_dgsem/elixir_shallowwater_well_balanced.jl index 17836fa6b8f..61dd252fd83 100644 --- a/examples/structured_2d_dgsem/elixir_shallowwater_well_balanced.jl +++ b/examples/structured_2d_dgsem/elixir_shallowwater_well_balanced.jl @@ -7,21 +7,21 @@ using Trixi # semidiscretization of the shallow water equations with a discontinuous # bottom topography function (set in the initial conditions) -equations = ShallowWaterEquations2D(gravity_constant=9.81, H0=3.0) +equations = ShallowWaterEquations2D(gravity_constant = 9.81, H0 = 3.0) # An initial condition with constant total water height and zero velocities to test well-balancedness. # Note, this routine is used to compute errors in the analysis callback but the initialization is # overwritten by `initial_condition_discontinuous_well_balancedness` below. function initial_condition_well_balancedness(x, t, equations::ShallowWaterEquations2D) - # Set the background values - H = equations.H0 - v1 = 0.0 - v2 = 0.0 - # bottom topography taken from Pond.control in [HOHQMesh](https://github.com/trixi-framework/HOHQMesh) - x1, x2 = x - b = ( 1.5 / exp( 0.5 * ((x1 - 1.0)^2 + (x2 - 1.0)^2) ) - + 0.75 / exp( 0.5 * ((x1 + 1.0)^2 + (x2 + 1.0)^2) ) ) - return prim2cons(SVector(H, v1, v2, b), equations) + # Set the background values + H = equations.H0 + v1 = 0.0 + v2 = 0.0 + # bottom topography taken from Pond.control in [HOHQMesh](https://github.com/trixi-framework/HOHQMesh) + x1, x2 = x + b = (1.5 / exp(0.5 * ((x1 - 1.0)^2 + (x2 - 1.0)^2)) + + 0.75 / exp(0.5 * ((x1 + 1.0)^2 + (x2 + 1.0)^2))) + return prim2cons(SVector(H, v1, v2, b), equations) end initial_condition = initial_condition_well_balancedness @@ -30,16 +30,17 @@ initial_condition = initial_condition_well_balancedness # Get the DG approximation space volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -surface_flux = (FluxHydrostaticReconstruction(flux_lax_friedrichs, hydrostatic_reconstruction_audusse_etal), +surface_flux = (FluxHydrostaticReconstruction(flux_lax_friedrichs, + hydrostatic_reconstruction_audusse_etal), flux_nonconservative_audusse_etal) -solver = DGSEM(polydeg=4, surface_flux=surface_flux, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 4, surface_flux = surface_flux, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### # This setup a structured periodic mesh coordinates_min = (-2.0, -2.0) -coordinates_max = ( 2.0, 2.0) +coordinates_max = (2.0, 2.0) cells_per_dimension = (4, 4) @@ -64,30 +65,33 @@ ode = semidiscretize(semi, tspan) # In contrast to the usual signature of initial conditions, this one get passed the # `element_id` explicitly. In particular, this initial conditions works as intended # only for the specific mesh loaded above! -function initial_condition_discontinuous_well_balancedness(x, t, element_id, equations::ShallowWaterEquations2D) - # Set the background values - H = equations.H0 - v1 = 0.0 - v2 = 0.0 - b = 0.0 - - # Setup a discontinuous bottom topography using the element id number - if element_id == 7 - b = 2.0 + 0.5 * sin(2.0 * pi * x[1]) + 0.5 * cos(2.0 * pi * x[2]) - end - - return prim2cons(SVector(H, v1, v2, b), equations) +function initial_condition_discontinuous_well_balancedness(x, t, element_id, + equations::ShallowWaterEquations2D) + # Set the background values + H = equations.H0 + v1 = 0.0 + v2 = 0.0 + b = 0.0 + + # Setup a discontinuous bottom topography using the element id number + if element_id == 7 + b = 2.0 + 0.5 * sin(2.0 * pi * x[1]) + 0.5 * cos(2.0 * pi * x[2]) + end + + return prim2cons(SVector(H, v1, v2, b), equations) end # point to the data we want to augment u = Trixi.wrap_array(ode.u0, semi) # reset the initial condition for element in eachelement(semi.solver, semi.cache) - for j in eachnode(semi.solver), i in eachnode(semi.solver) - x_node = Trixi.get_node_coords(semi.cache.elements.node_coordinates, equations, semi.solver, i, j, element) - u_node = initial_condition_discontinuous_well_balancedness(x_node, first(tspan), element, equations) - Trixi.set_node_vars!(u, u_node, equations, semi.solver, i, j, element) - end + for j in eachnode(semi.solver), i in eachnode(semi.solver) + x_node = Trixi.get_node_coords(semi.cache.elements.node_coordinates, equations, + semi.solver, i, j, element) + u_node = initial_condition_discontinuous_well_balancedness(x_node, first(tspan), + element, equations) + Trixi.set_node_vars!(u, u_node, equations, semi.solver, i, j, element) + end end ############################################################################### @@ -96,16 +100,16 @@ end summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(lake_at_rest_error,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (lake_at_rest_error,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=3.0) +stepsize_callback = StepsizeCallback(cfl = 3.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) @@ -113,7 +117,7 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_2d_dgsem/elixir_shallowwater_well_balanced_wet_dry.jl b/examples/structured_2d_dgsem/elixir_shallowwater_well_balanced_wet_dry.jl index b18b02e0b4c..8e492b1ba05 100644 --- a/examples/structured_2d_dgsem/elixir_shallowwater_well_balanced_wet_dry.jl +++ b/examples/structured_2d_dgsem/elixir_shallowwater_well_balanced_wet_dry.jl @@ -8,8 +8,7 @@ using Printf: @printf, @sprintf # # TODO: TrixiShallowWater: wet/dry example elixir - -equations = ShallowWaterEquations2D(gravity_constant=9.812) +equations = ShallowWaterEquations2D(gravity_constant = 9.812) """ initial_condition_well_balanced_chen_noelle(x, t, equations:: ShallowWaterEquations2D) @@ -24,29 +23,30 @@ The initial condition is taken from Section 5.2 of the paper: A new hydrostatic reconstruction scheme based on subcell reconstructions [DOI:10.1137/15M1053074](https://dx.doi.org/10.1137/15M1053074) """ -function initial_condition_complex_bottom_well_balanced(x, t, equations:: ShallowWaterEquations2D) - v1 = 0 - v2 = 0 - b = sin(4 * pi * x[1]) + 3 - - if x[1] >= 0.5 - b = sin(4 * pi * x[1]) + 1 - end - - H = max(b, 2.5) - - if x[1] >= 0.5 - H = max(b, 1.5) - end - - # It is mandatory to shift the water level at dry areas to make sure the water height h - # stays positive. The system would not be stable for h set to a hard 0 due to division by h in - # the computation of velocity, e.g., (h v1) / h. Therefore, a small dry state threshold - # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above - # for the ShallowWaterEquations and added to the initial condition if h = 0. - # This default value can be changed within the constructor call depending on the simulation setup. - H = max(H, b + equations.threshold_limiter) - return prim2cons(SVector(H, v1, v2, b), equations) +function initial_condition_complex_bottom_well_balanced(x, t, + equations::ShallowWaterEquations2D) + v1 = 0 + v2 = 0 + b = sin(4 * pi * x[1]) + 3 + + if x[1] >= 0.5 + b = sin(4 * pi * x[1]) + 1 + end + + H = max(b, 2.5) + + if x[1] >= 0.5 + H = max(b, 1.5) + end + + # It is mandatory to shift the water level at dry areas to make sure the water height h + # stays positive. The system would not be stable for h set to a hard 0 due to division by h in + # the computation of velocity, e.g., (h v1) / h. Therefore, a small dry state threshold + # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above + # for the ShallowWaterEquations and added to the initial condition if h = 0. + # This default value can be changed within the constructor call depending on the simulation setup. + H = max(H, b + equations.threshold_limiter) + return prim2cons(SVector(H, v1, v2, b), equations) end initial_condition = initial_condition_complex_bottom_well_balanced @@ -56,23 +56,23 @@ initial_condition = initial_condition_complex_bottom_well_balanced volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -surface_flux = (FluxHydrostaticReconstruction(flux_hll_chen_noelle, hydrostatic_reconstruction_chen_noelle), +surface_flux = (FluxHydrostaticReconstruction(flux_hll_chen_noelle, + hydrostatic_reconstruction_chen_noelle), flux_nonconservative_chen_noelle) basis = LobattoLegendreBasis(3) indicator_sc = IndicatorHennemannGassnerShallowWater(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=waterheight_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = waterheight_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) - ############################################################################### # Create the StructuredMesh for the domain [0, 1]^2 @@ -83,7 +83,6 @@ cells_per_dimension = (16, 16) mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max) - # create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -107,18 +106,20 @@ ode = semidiscretize(semi, tspan) u = Trixi.wrap_array(ode.u0, semi) # reset the initial condition for element in eachelement(semi.solver, semi.cache) - for j in eachnode(semi.solver), i in eachnode(semi.solver) - x_node = Trixi.get_node_coords(semi.cache.elements.node_coordinates, equations, semi.solver, i, j, element) - # We know that the discontinuity is a vertical line. Slightly augment the x value by a factor - # of unit roundoff to avoid the repeted value from the LGL nodes at at interface. - if i == 1 - x_node = SVector(nextfloat(x_node[1]) , x_node[2]) - elseif i == nnodes(semi.solver) - x_node = SVector(prevfloat(x_node[1]) , x_node[2]) + for j in eachnode(semi.solver), i in eachnode(semi.solver) + x_node = Trixi.get_node_coords(semi.cache.elements.node_coordinates, equations, + semi.solver, i, j, element) + # We know that the discontinuity is a vertical line. Slightly augment the x value by a factor + # of unit roundoff to avoid the repeted value from the LGL nodes at at interface. + if i == 1 + x_node = SVector(nextfloat(x_node[1]), x_node[2]) + elseif i == nnodes(semi.solver) + x_node = SVector(prevfloat(x_node[1]), x_node[2]) + end + u_node = initial_condition_complex_bottom_well_balanced(x_node, first(tspan), + equations) + Trixi.set_node_vars!(u, u_node, equations, semi.solver, i, j, element) end - u_node = initial_condition_complex_bottom_well_balanced(x_node, first(tspan), equations) - Trixi.set_node_vars!(u, u_node, equations, semi.solver, i, j, element) - end end ############################################################################### @@ -127,25 +128,27 @@ end summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=false) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = false) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) -callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) +callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, + stepsize_callback) -stage_limiter! = PositivityPreservingLimiterShallowWater(variables=(Trixi.waterheight,)) +stage_limiter! = PositivityPreservingLimiterShallowWater(variables = (Trixi.waterheight,)) ############################################################################### # run the simulation -sol = solve(ode, SSPRK43(stage_limiter!); dt=1.0, - ode_default_options()..., callback=callbacks, adaptive=false); +sol = solve(ode, SSPRK43(stage_limiter!); dt = 1.0, + ode_default_options()..., callback = callbacks, adaptive = false); summary_callback() # print the timer summary @@ -160,39 +163,43 @@ summary_callback() # print the timer summary function lake_at_rest_error_two_level(u, x, equations::ShallowWaterEquations2D) h, _, _, b = u - # For well-balancedness testing with possible wet/dry regions the reference - # water height `H0` accounts for the possibility that the bottom topography - # can emerge out of the water as well as for the threshold offset to avoid - # division by a "hard" zero water heights as well. - if x[1] < 0.5 - H0_wet_dry = max( 2.5 , b + equations.threshold_limiter ) - else - H0_wet_dry = max( 1.5 , b + equations.threshold_limiter ) - end - - return abs(H0_wet_dry - (h + b)) + # For well-balancedness testing with possible wet/dry regions the reference + # water height `H0` accounts for the possibility that the bottom topography + # can emerge out of the water as well as for the threshold offset to avoid + # division by a "hard" zero water heights as well. + if x[1] < 0.5 + H0_wet_dry = max(2.5, b + equations.threshold_limiter) + else + H0_wet_dry = max(1.5, b + equations.threshold_limiter) + end + + return abs(H0_wet_dry - (h + b)) end # point to the data we want to analyze u = Trixi.wrap_array(sol[end], semi) # Perform the actual integration of the well-balancedness error over the domain -l1_well_balance_error = Trixi.integrate_via_indices(u, mesh, equations, semi.solver, semi.cache; normalize=true) do u, i, j, element, equations, solver - x_node = Trixi.get_node_coords(semi.cache.elements.node_coordinates, equations, solver, i, j, element) - # We know that the discontinuity is a vertical line. Slightly augment the x value by a factor - # of unit roundoff to avoid the repeted value from the LGL nodes at at interface. - if i == 1 - x_node = SVector(nextfloat(x_node[1]) , x_node[2]) - elseif i == nnodes(semi.solver) - x_node = SVector(prevfloat(x_node[1]) , x_node[2]) - end - u_local = Trixi.get_node_vars(u, equations, solver, i, j, element) - return lake_at_rest_error_two_level(u_local, x_node, equations) +l1_well_balance_error = Trixi.integrate_via_indices(u, mesh, equations, semi.solver, + semi.cache; + normalize = true) do u, i, j, element, + equations, solver + x_node = Trixi.get_node_coords(semi.cache.elements.node_coordinates, equations, solver, + i, j, element) + # We know that the discontinuity is a vertical line. Slightly augment the x value by a factor + # of unit roundoff to avoid the repeted value from the LGL nodes at at interface. + if i == 1 + x_node = SVector(nextfloat(x_node[1]), x_node[2]) + elseif i == nnodes(semi.solver) + x_node = SVector(prevfloat(x_node[1]), x_node[2]) + end + u_local = Trixi.get_node_vars(u, equations, solver, i, j, element) + return lake_at_rest_error_two_level(u_local, x_node, equations) end # report the well-balancedness lake-at-rest error to the screen println("─"^100) println(" Lake-at-rest error for '", Trixi.get_name(equations), "' with ", summary(solver), - " at final time " * @sprintf("%10.8e", tspan[end])) + " at final time " * @sprintf("%10.8e", tspan[end])) @printf(" %-12s:", Trixi.pretty_form_utf(lake_at_rest_error)) @printf(" % 10.8e", l1_well_balance_error) diff --git a/examples/structured_3d_dgsem/elixir_advection_basic.jl b/examples/structured_3d_dgsem/elixir_advection_basic.jl index 47ae6352485..5b0bb371fe8 100644 --- a/examples/structured_3d_dgsem/elixir_advection_basic.jl +++ b/examples/structured_3d_dgsem/elixir_advection_basic.jl @@ -11,18 +11,18 @@ advection_velocity = (0.2, -0.7, 0.5) equations = LinearScalarAdvectionEquation3D(advection_velocity) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-1.0, -1.0, -1.0) # minimum coordinates (min(x), min(y), min(z)) -coordinates_max = ( 1.0, 1.0, 1.0) # maximum coordinates (max(x), max(y), max(z)) +coordinates_max = (1.0, 1.0, 1.0) # maximum coordinates (max(x), max(y), max(z)) cells_per_dimension = (8, 8, 8) # Create curved mesh with 8 x 8 x 8 elements mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max) # A semidiscretization collects data structures and functions for the spatial discretization -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, solver) - +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, + solver) ############################################################################### # ODE solvers, callbacks etc. @@ -35,30 +35,30 @@ ode = semidiscretize(semi, (0.0, 1.0)); summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The SaveRestartCallback allows to save a file from which a Trixi.jl simulation can be restarted -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.2) +stepsize_callback = StepsizeCallback(cfl = 1.2) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, save_restart, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, save_restart, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); # Print the timer summary summary_callback() diff --git a/examples/structured_3d_dgsem/elixir_advection_free_stream.jl b/examples/structured_3d_dgsem/elixir_advection_free_stream.jl index 749233b8c68..12d52f15160 100644 --- a/examples/structured_3d_dgsem/elixir_advection_free_stream.jl +++ b/examples/structured_3d_dgsem/elixir_advection_free_stream.jl @@ -13,24 +13,27 @@ solver = DGSEM(3, flux_lax_friedrichs) # Mapping as described in https://arxiv.org/abs/2012.12040 function mapping(xi_, eta_, zeta_) - # Transform input variables between -1 and 1 onto [0,3] - xi = 1.5 * xi_ + 1.5 - eta = 1.5 * eta_ + 1.5 - zeta = 1.5 * zeta_ + 1.5 - - y = eta + 3/8 * (cos(1.5 * pi * (2 * xi - 3)/3) * - cos(0.5 * pi * (2 * eta - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - x = xi + 3/8 * (cos(0.5 * pi * (2 * xi - 3)/3) * - cos(2 * pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - z = zeta + 3/8 * (cos(0.5 * pi * (2 * x - 3)/3) * - cos(pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - return SVector(x, y, z) + # Transform input variables between -1 and 1 onto [0,3] + xi = 1.5 * xi_ + 1.5 + eta = 1.5 * eta_ + 1.5 + zeta = 1.5 * zeta_ + 1.5 + + y = eta + + 3 / 8 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + x = xi + + 3 / 8 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + z = zeta + + 3 / 8 * (cos(0.5 * pi * (2 * x - 3) / 3) * + cos(pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + return SVector(x, y, z) end cells_per_dimension = (8, 8, 8) @@ -41,7 +44,6 @@ mesh = StructuredMesh(cells_per_dimension, mapping) # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_constant, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -53,26 +55,26 @@ ode = semidiscretize(semi, (0.0, 1.0)); summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=2.0) +stepsize_callback = StepsizeCallback(cfl = 2.0) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); # Print the timer summary summary_callback() diff --git a/examples/structured_3d_dgsem/elixir_advection_nonperiodic_curved.jl b/examples/structured_3d_dgsem/elixir_advection_nonperiodic_curved.jl index fa8ae756566..1a20a9c8533 100644 --- a/examples/structured_3d_dgsem/elixir_advection_nonperiodic_curved.jl +++ b/examples/structured_3d_dgsem/elixir_advection_nonperiodic_curved.jl @@ -11,36 +11,38 @@ equations = LinearScalarAdvectionEquation3D(advection_velocity) initial_condition = initial_condition_convergence_test boundary_conditions = BoundaryConditionDirichlet(initial_condition) -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) # Mapping as described in https://arxiv.org/abs/2012.12040 but with less warping. function mapping(xi, eta, zeta) - # Don't transform input variables between -1 and 1 onto [0,3] to obtain curved boundaries - # xi = 1.5 * xi_ + 1.5 - # eta = 1.5 * eta_ + 1.5 - # zeta = 1.5 * zeta_ + 1.5 - - y = eta + 1/6 * (cos(1.5 * pi * (2 * xi - 3)/3) * - cos(0.5 * pi * (2 * eta - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - x = xi + 1/6 * (cos(0.5 * pi * (2 * xi - 3)/3) * - cos(2 * pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - z = zeta + 1/6 * (cos(0.5 * pi * (2 * x - 3)/3) * - cos(pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - return SVector(x, y, z) + # Don't transform input variables between -1 and 1 onto [0,3] to obtain curved boundaries + # xi = 1.5 * xi_ + 1.5 + # eta = 1.5 * eta_ + 1.5 + # zeta = 1.5 * zeta_ + 1.5 + + y = eta + + 1 / 6 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + x = xi + + 1 / 6 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + z = zeta + + 1 / 6 * (cos(0.5 * pi * (2 * x - 3) / 3) * + cos(pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + return SVector(x, y, z) end cells_per_dimension = (8, 8, 8) -mesh = StructuredMesh(cells_per_dimension, mapping, periodicity=false) +mesh = StructuredMesh(cells_per_dimension, mapping, periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -51,20 +53,20 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.2) +stepsize_callback = StepsizeCallback(cfl = 1.2) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -76,7 +78,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_3d_dgsem/elixir_advection_restart.jl b/examples/structured_3d_dgsem/elixir_advection_restart.jl index 39d28848c77..e516d794df8 100644 --- a/examples/structured_3d_dgsem/elixir_advection_restart.jl +++ b/examples/structured_3d_dgsem/elixir_advection_restart.jl @@ -6,8 +6,7 @@ using Trixi # create a restart file trixi_include(@__MODULE__, joinpath(@__DIR__, "elixir_advection_basic.jl"), - cells_per_dimension=(4, 4, 4)) - + cells_per_dimension = (4, 4, 4)) ############################################################################### # adapt the parameters that have changed compared to "elixir_advection_extended.jl" @@ -18,7 +17,8 @@ trixi_include(@__MODULE__, joinpath(@__DIR__, "elixir_advection_basic.jl"), restart_filename = joinpath("out", "restart_000010.h5") mesh = load_mesh(restart_filename) -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, solver) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, + solver) tspan = (load_time(restart_filename), 2.0) dt = load_dt(restart_filename) @@ -27,14 +27,12 @@ ode = semidiscretize(semi, tspan, restart_filename); # Do not overwrite the initial snapshot written by elixir_advection_extended.jl. save_solution.condition.save_initial_solution = false -integrator = init(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=dt, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +integrator = init(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = dt, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks, maxiters = 100_000); # Get the last time index and work with that. -integrator.iter = load_timestep(restart_filename) -integrator.stats.naccept = integrator.iter - +load_timestep!(integrator, restart_filename) ############################################################################### # run the simulation diff --git a/examples/structured_3d_dgsem/elixir_euler_ec.jl b/examples/structured_3d_dgsem/elixir_euler_ec.jl index 0009eb31180..1330006760e 100644 --- a/examples/structured_3d_dgsem/elixir_euler_ec.jl +++ b/examples/structured_3d_dgsem/elixir_euler_ec.jl @@ -5,7 +5,7 @@ using Trixi ############################################################################### # semidiscretization of the compressible Euler equations -equations = CompressibleEulerEquations3D(5/3) +equations = CompressibleEulerEquations3D(5 / 3) initial_condition = initial_condition_weak_blast_wave @@ -13,32 +13,35 @@ initial_condition = initial_condition_weak_blast_wave # Get the DG approximation space volume_flux = flux_ranocha -solver = DGSEM(polydeg=5, surface_flux=flux_ranocha, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 5, surface_flux = flux_ranocha, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### # Get the curved quad mesh from a file # Mapping as described in https://arxiv.org/abs/2012.12040 function mapping(xi_, eta_, zeta_) - # Transform input variables between -1 and 1 onto [0,3] - xi = 1.5 * xi_ + 1.5 - eta = 1.5 * eta_ + 1.5 - zeta = 1.5 * zeta_ + 1.5 - - y = eta + 3/8 * (cos(1.5 * pi * (2 * xi - 3)/3) * - cos(0.5 * pi * (2 * eta - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - x = xi + 3/8 * (cos(0.5 * pi * (2 * xi - 3)/3) * - cos(2 * pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - z = zeta + 3/8 * (cos(0.5 * pi * (2 * x - 3)/3) * - cos(pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - return SVector(x, y, z) + # Transform input variables between -1 and 1 onto [0,3] + xi = 1.5 * xi_ + 1.5 + eta = 1.5 * eta_ + 1.5 + zeta = 1.5 * zeta_ + 1.5 + + y = eta + + 3 / 8 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + x = xi + + 3 / 8 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + z = zeta + + 3 / 8 * (cos(0.5 * pi * (2 * x - 3) / 3) * + cos(pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + return SVector(x, y, z) end cells_per_dimension = (4, 4, 4) @@ -59,15 +62,15 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -78,7 +81,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_3d_dgsem/elixir_euler_free_stream.jl b/examples/structured_3d_dgsem/elixir_euler_free_stream.jl index b0e71435767..1b01287100e 100644 --- a/examples/structured_3d_dgsem/elixir_euler_free_stream.jl +++ b/examples/structured_3d_dgsem/elixir_euler_free_stream.jl @@ -9,29 +9,32 @@ equations = CompressibleEulerEquations3D(1.4) initial_condition = initial_condition_constant -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralWeakForm()) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralWeakForm()) # Mapping as described in https://arxiv.org/abs/2012.12040 function mapping(xi_, eta_, zeta_) - # Transform input variables between -1 and 1 onto [0,3] - xi = 1.5 * xi_ + 1.5 - eta = 1.5 * eta_ + 1.5 - zeta = 1.5 * zeta_ + 1.5 - - y = eta + 3/8 * (cos(1.5 * pi * (2 * xi - 3)/3) * - cos(0.5 * pi * (2 * eta - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - x = xi + 3/8 * (cos(0.5 * pi * (2 * xi - 3)/3) * - cos(2 * pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - z = zeta + 3/8 * (cos(0.5 * pi * (2 * x - 3)/3) * - cos(pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - return SVector(x, y, z) + # Transform input variables between -1 and 1 onto [0,3] + xi = 1.5 * xi_ + 1.5 + eta = 1.5 * eta_ + 1.5 + zeta = 1.5 * zeta_ + 1.5 + + y = eta + + 3 / 8 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + x = xi + + 3 / 8 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + z = zeta + + 3 / 8 * (cos(0.5 * pi * (2 * x - 3) / 3) * + cos(pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + return SVector(x, y, z) end cells_per_dimension = (4, 4, 4) @@ -40,7 +43,6 @@ mesh = StructuredMesh(cells_per_dimension, mapping) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -50,30 +52,29 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.3) +stepsize_callback = StepsizeCallback(cfl = 1.3) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_restart, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_3d_dgsem/elixir_euler_sedov.jl b/examples/structured_3d_dgsem/elixir_euler_sedov.jl index e0595437c99..1f2d9d2eeb6 100644 --- a/examples/structured_3d_dgsem/elixir_euler_sedov.jl +++ b/examples/structured_3d_dgsem/elixir_euler_sedov.jl @@ -14,28 +14,29 @@ The Sedov blast wave setup based on Flash - https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 with smaller strength of the initial discontinuity. """ -function initial_condition_medium_sedov_blast_wave(x, t, equations::CompressibleEulerEquations3D) - # Set up polar coordinates - inicenter = SVector(0.0, 0.0, 0.0) - x_norm = x[1] - inicenter[1] - y_norm = x[2] - inicenter[2] - z_norm = x[3] - inicenter[3] - r = sqrt(x_norm^2 + y_norm^2 + z_norm^2) - - # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 - r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) - E = 1.0 - p0_inner = 3 * (equations.gamma - 1) * E / (4 * pi * r0^2) - p0_outer = 1.0e-3 - - # Calculate primitive variables - rho = 1.0 - v1 = 0.0 - v2 = 0.0 - v3 = 0.0 - p = r > r0 ? p0_outer : p0_inner - - return prim2cons(SVector(rho, v1, v2, v3, p), equations) +function initial_condition_medium_sedov_blast_wave(x, t, + equations::CompressibleEulerEquations3D) + # Set up polar coordinates + inicenter = SVector(0.0, 0.0, 0.0) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + z_norm = x[3] - inicenter[3] + r = sqrt(x_norm^2 + y_norm^2 + z_norm^2) + + # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 + r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) + E = 1.0 + p0_inner = 3 * (equations.gamma - 1) * E / (4 * pi * r0^2) + p0_outer = 1.0e-3 + + # Calculate primitive variables + rho = 1.0 + v1 = 0.0 + v2 = 0.0 + v3 = 0.0 + p = r > r0 ? p0_outer : p0_inner + + return prim2cons(SVector(rho, v1, v2, v3, p), equations) end initial_condition = initial_condition_medium_sedov_blast_wave @@ -45,30 +46,31 @@ volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=1.0, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 1.0, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) -solver = DGSEM(polydeg=polydeg, surface_flux=surface_flux, volume_integral=volume_integral) +solver = DGSEM(polydeg = polydeg, surface_flux = surface_flux, + volume_integral = volume_integral) # Mapping as described in https://arxiv.org/abs/2012.12040 function mapping(xi, eta, zeta) - y = eta + 0.125 * (cos(1.5 * pi * xi) * cos(0.5 * pi * eta) * cos(0.5 * pi * zeta)) + y = eta + 0.125 * (cos(1.5 * pi * xi) * cos(0.5 * pi * eta) * cos(0.5 * pi * zeta)) - x = xi + 0.125 * (cos(0.5 * pi * xi) * cos(2 * pi * y) * cos(0.5 * pi * zeta)) + x = xi + 0.125 * (cos(0.5 * pi * xi) * cos(2 * pi * y) * cos(0.5 * pi * zeta)) - z = zeta + 0.125 * (cos(0.5 * pi * x) * cos(pi * y) * cos(0.5 * pi * zeta)) + z = zeta + 0.125 * (cos(0.5 * pi * x) * cos(pi * y) * cos(0.5 * pi * zeta)) - return SVector(x, y, z) + return SVector(x, y, z) end cells_per_dimension = (4, 4, 4) -mesh = StructuredMesh(cells_per_dimension, mapping, periodicity=true) +mesh = StructuredMesh(cells_per_dimension, mapping, periodicity = true) # create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -82,15 +84,15 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -101,7 +103,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_3d_dgsem/elixir_euler_source_terms.jl b/examples/structured_3d_dgsem/elixir_euler_source_terms.jl index d8c6ea4bb83..ebf1336c12c 100644 --- a/examples/structured_3d_dgsem/elixir_euler_source_terms.jl +++ b/examples/structured_3d_dgsem/elixir_euler_source_terms.jl @@ -11,8 +11,8 @@ equations = CompressibleEulerEquations3D(1.4) initial_condition = initial_condition_convergence_test -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralWeakForm()) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralWeakForm()) # coordinates_min = (0.0, 0.0, 0.0) # coordinates_max = (2.0, 2.0, 2.0) @@ -28,8 +28,7 @@ cells_per_dimension = (4, 4, 4) mesh = StructuredMesh(cells_per_dimension, (f1, f2, f3, f4, f5, f6)) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -40,27 +39,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.6) +stepsize_callback = StepsizeCallback(cfl = 0.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_3d_dgsem/elixir_euler_source_terms_nonperiodic_curved.jl b/examples/structured_3d_dgsem/elixir_euler_source_terms_nonperiodic_curved.jl index 8ddfd426553..eb358fa5da1 100644 --- a/examples/structured_3d_dgsem/elixir_euler_source_terms_nonperiodic_curved.jl +++ b/examples/structured_3d_dgsem/elixir_euler_source_terms_nonperiodic_curved.jl @@ -12,46 +12,48 @@ initial_condition = initial_condition_convergence_test # you can either use a single function to impose the BCs weakly in all # 2*ndims == 4 directions or you can pass a tuple containing BCs for each direction boundary_condition = BoundaryConditionDirichlet(initial_condition) -boundary_conditions = (x_neg=boundary_condition, - x_pos=boundary_condition, - y_neg=boundary_condition, - y_pos=boundary_condition, - z_neg=boundary_condition, - z_pos=boundary_condition,) +boundary_conditions = (x_neg = boundary_condition, + x_pos = boundary_condition, + y_neg = boundary_condition, + y_pos = boundary_condition, + z_neg = boundary_condition, + z_pos = boundary_condition) -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralWeakForm()) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralWeakForm()) # Mapping as described in https://arxiv.org/abs/2012.12040 but with less warping. function mapping(xi, eta, zeta) - # Don't transform input variables between -1 and 1 onto [0,3] to obtain curved boundaries - # xi = 1.5 * xi_ + 1.5 - # eta = 1.5 * eta_ + 1.5 - # zeta = 1.5 * zeta_ + 1.5 - - y = eta + 1/6 * (cos(1.5 * pi * (2 * xi - 3)/3) * - cos(0.5 * pi * (2 * eta - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - x = xi + 1/6 * (cos(0.5 * pi * (2 * xi - 3)/3) * - cos(2 * pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - z = zeta + 1/6 * (cos(0.5 * pi * (2 * x - 3)/3) * - cos(pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - # Transform the weird deformed cube to be approximately the cube [0,2]^3 - return SVector(x + 1, y + 1, z + 1) + # Don't transform input variables between -1 and 1 onto [0,3] to obtain curved boundaries + # xi = 1.5 * xi_ + 1.5 + # eta = 1.5 * eta_ + 1.5 + # zeta = 1.5 * zeta_ + 1.5 + + y = eta + + 1 / 6 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + x = xi + + 1 / 6 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + z = zeta + + 1 / 6 * (cos(0.5 * pi * (2 * x - 3) / 3) * + cos(pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + # Transform the weird deformed cube to be approximately the cube [0,2]^3 + return SVector(x + 1, y + 1, z + 1) end cells_per_dimension = (4, 4, 4) -mesh = StructuredMesh(cells_per_dimension, mapping, periodicity=false) +mesh = StructuredMesh(cells_per_dimension, mapping, periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test, - boundary_conditions=boundary_conditions) - + source_terms = source_terms_convergence_test, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -62,27 +64,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.6) +stepsize_callback = StepsizeCallback(cfl = 0.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_3d_dgsem/elixir_mhd_alfven_wave.jl b/examples/structured_3d_dgsem/elixir_mhd_alfven_wave.jl index f4da8ee9470..03f50ff3e55 100644 --- a/examples/structured_3d_dgsem/elixir_mhd_alfven_wave.jl +++ b/examples/structured_3d_dgsem/elixir_mhd_alfven_wave.jl @@ -5,13 +5,15 @@ using Trixi ############################################################################### # semidiscretization of the compressible ideal GLM-MHD equations -equations = IdealGlmMhdEquations3D(5/3) +equations = IdealGlmMhdEquations3D(5 / 3) initial_condition = initial_condition_convergence_test volume_flux = (flux_central, flux_nonconservative_powell) -solver = DGSEM(polydeg=5, surface_flux=(flux_hll, flux_nonconservative_powell), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 5, + surface_flux = (flux_hlle, + flux_nonconservative_powell), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) # Create the mesh # Note, we use the domain [-1, 1]^3 for the Alfvén wave convergence test case so the @@ -19,13 +21,13 @@ solver = DGSEM(polydeg=5, surface_flux=(flux_hll, flux_nonconservative_powell), # Mapping as described in https://arxiv.org/abs/2012.12040 function mapping(xi, eta, zeta) - y = eta + 0.125 * (cos(1.5 * pi * xi) * cos(0.5 * pi * eta) * cos(0.5 * pi * zeta)) + y = eta + 0.125 * (cos(1.5 * pi * xi) * cos(0.5 * pi * eta) * cos(0.5 * pi * zeta)) - x = xi + 0.125 * (cos(0.5 * pi * xi) * cos(2 * pi * y) * cos(0.5 * pi * zeta)) + x = xi + 0.125 * (cos(0.5 * pi * xi) * cos(2 * pi * y) * cos(0.5 * pi * zeta)) - z = zeta + 0.125 * (cos(0.5 * pi * x) * cos(pi * y) * cos(0.5 * pi * zeta)) + z = zeta + 0.125 * (cos(0.5 * pi * x) * cos(pi * y) * cos(0.5 * pi * zeta)) - return SVector(x, y, z) + return SVector(x, y, z) end cells_per_dimension = (4, 4, 4) @@ -43,18 +45,18 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) cfl = 1.2 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -62,11 +64,10 @@ callbacks = CallbackSet(summary_callback, stepsize_callback, glm_speed_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_3d_dgsem/elixir_mhd_ec.jl b/examples/structured_3d_dgsem/elixir_mhd_ec.jl index a8c2288e811..5b3cd6f3718 100644 --- a/examples/structured_3d_dgsem/elixir_mhd_ec.jl +++ b/examples/structured_3d_dgsem/elixir_mhd_ec.jl @@ -10,31 +10,35 @@ equations = IdealGlmMhdEquations3D(1.4) initial_condition = initial_condition_weak_blast_wave volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) -solver = DGSEM(polydeg=3, surface_flux=(flux_hindenlang_gassner, flux_nonconservative_powell), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, + surface_flux = (flux_hindenlang_gassner, flux_nonconservative_powell), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) # Create a heavily warped curved mesh # Mapping as described in https://arxiv.org/abs/2012.12040 function mapping(xi_, eta_, zeta_) - # Transform input variables between -1 and 1 onto [0,3] - xi = 1.5 * xi_ + 1.5 - eta = 1.5 * eta_ + 1.5 - zeta = 1.5 * zeta_ + 1.5 - - y = eta + 3/8 * (cos(1.5 * pi * (2 * xi - 3)/3) * - cos(0.5 * pi * (2 * eta - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - x = xi + 3/8 * (cos(0.5 * pi * (2 * xi - 3)/3) * - cos(2 * pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - z = zeta + 3/8 * (cos(0.5 * pi * (2 * x - 3)/3) * - cos(pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - return SVector(x, y, z) + # Transform input variables between -1 and 1 onto [0,3] + xi = 1.5 * xi_ + 1.5 + eta = 1.5 * eta_ + 1.5 + zeta = 1.5 * zeta_ + 1.5 + + y = eta + + 3 / 8 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + x = xi + + 3 / 8 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + z = zeta + + 3 / 8 * (cos(0.5 * pi * (2 * x - 3) / 3) * + cos(pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + return SVector(x, y, z) end cells_per_dimension = (4, 4, 4) @@ -52,19 +56,19 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) cfl = 1.4 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -72,11 +76,10 @@ callbacks = CallbackSet(summary_callback, stepsize_callback, glm_speed_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/structured_3d_dgsem/elixir_mhd_ec_shockcapturing.jl b/examples/structured_3d_dgsem/elixir_mhd_ec_shockcapturing.jl index d669c2350a5..084e2ee962a 100644 --- a/examples/structured_3d_dgsem/elixir_mhd_ec_shockcapturing.jl +++ b/examples/structured_3d_dgsem/elixir_mhd_ec_shockcapturing.jl @@ -10,42 +10,46 @@ equations = IdealGlmMhdEquations3D(1.4) initial_condition = initial_condition_weak_blast_wave surface_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) -volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) +volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) polydeg = 4 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) -solver = DGSEM(polydeg=polydeg, surface_flux=surface_flux, volume_integral=volume_integral) +solver = DGSEM(polydeg = polydeg, surface_flux = surface_flux, + volume_integral = volume_integral) # Create a heavily warped curved mesh # Mapping as described in https://arxiv.org/abs/2012.12040 function mapping(xi_, eta_, zeta_) - # Transform input variables between -1 and 1 onto [0,3] - xi = 1.5 * xi_ + 1.5 - eta = 1.5 * eta_ + 1.5 - zeta = 1.5 * zeta_ + 1.5 - - y = eta + 3/8 * (cos(1.5 * pi * (2 * xi - 3)/3) * - cos(0.5 * pi * (2 * eta - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - x = xi + 3/8 * (cos(0.5 * pi * (2 * xi - 3)/3) * - cos(2 * pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - z = zeta + 3/8 * (cos(0.5 * pi * (2 * x - 3)/3) * - cos(pi * (2 * y - 3)/3) * - cos(0.5 * pi * (2 * zeta - 3)/3)) - - return SVector(x, y, z) + # Transform input variables between -1 and 1 onto [0,3] + xi = 1.5 * xi_ + 1.5 + eta = 1.5 * eta_ + 1.5 + zeta = 1.5 * zeta_ + 1.5 + + y = eta + + 3 / 8 * (cos(1.5 * pi * (2 * xi - 3) / 3) * + cos(0.5 * pi * (2 * eta - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + x = xi + + 3 / 8 * (cos(0.5 * pi * (2 * xi - 3) / 3) * + cos(2 * pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + z = zeta + + 3 / 8 * (cos(0.5 * pi * (2 * x - 3) / 3) * + cos(pi * (2 * y - 3) / 3) * + cos(0.5 * pi * (2 * zeta - 3) / 3)) + + return SVector(x, y, z) end cells_per_dimension = (8, 8, 8) @@ -63,25 +67,24 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) cfl = 1.4 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, stepsize_callback, glm_speed_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/t8code_2d_dgsem/elixir_mhd_alfven_wave.jl b/examples/t8code_2d_dgsem/elixir_mhd_alfven_wave.jl index e11d46bb539..e184cb3fd05 100644 --- a/examples/t8code_2d_dgsem/elixir_mhd_alfven_wave.jl +++ b/examples/t8code_2d_dgsem/elixir_mhd_alfven_wave.jl @@ -11,7 +11,8 @@ initial_condition = initial_condition_convergence_test # Get the DG approximation space volume_flux = (flux_central, flux_nonconservative_powell) -solver = DGSEM(polydeg = 4, surface_flux = (flux_hll, flux_nonconservative_powell), + +solver = DGSEM(polydeg = 4, surface_flux = (flux_hlle, flux_nonconservative_powell), volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (0.0, 0.0) diff --git a/examples/tree_1d_dgsem/elixir_advection_amr.jl b/examples/tree_1d_dgsem/elixir_advection_amr.jl index dc371233bc8..1071c98ab7e 100644 --- a/examples/tree_1d_dgsem/elixir_advection_amr.jl +++ b/examples/tree_1d_dgsem/elixir_advection_amr.jl @@ -10,18 +10,16 @@ equations = LinearScalarAdvectionEquation1D(advection_velocity) initial_condition = initial_condition_gauss -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-5.0,) -coordinates_max = ( 5.0,) +coordinates_max = (5.0,) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=30_000) - + initial_refinement_level = 4, + n_cells_max = 30_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -31,37 +29,36 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable=first), - base_level=4, - med_level=5, med_threshold=0.1, - max_level=6, max_threshold=0.6) +amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable = first), + base_level = 4, + med_level = 5, med_threshold = 0.1, + max_level = 6, max_threshold = 0.6) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, amr_callback, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_advection_amr_nonperiodic.jl b/examples/tree_1d_dgsem/elixir_advection_amr_nonperiodic.jl index 098deedb9d6..ff62e905429 100644 --- a/examples/tree_1d_dgsem/elixir_advection_amr_nonperiodic.jl +++ b/examples/tree_1d_dgsem/elixir_advection_amr_nonperiodic.jl @@ -11,21 +11,19 @@ equations = LinearScalarAdvectionEquation1D(advection_velocity) initial_condition = initial_condition_gauss boundary_conditions = BoundaryConditionDirichlet(initial_condition) -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (0.0,) coordinates_max = (5.0,) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000, - periodicity=false) - + initial_refinement_level = 4, + n_cells_max = 10_000, + periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -36,40 +34,39 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable=first), - base_level=4, - med_level=5, med_threshold=0.1, - max_level=6, max_threshold=0.6) +amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable = first), + base_level = 4, + med_level = 5, med_threshold = 0.1, + max_level = 6, max_threshold = 0.6) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_restart, save_solution, amr_callback, stepsize_callback); - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=stepsize_callback(ode), # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = stepsize_callback(ode), # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_advection_basic.jl b/examples/tree_1d_dgsem/elixir_advection_basic.jl index d61062c772e..cba522f6366 100644 --- a/examples/tree_1d_dgsem/elixir_advection_basic.jl +++ b/examples/tree_1d_dgsem/elixir_advection_basic.jl @@ -9,19 +9,19 @@ advection_velocity = 1.0 equations = LinearScalarAdvectionEquation1D(advection_velocity) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = -1.0 # minimum coordinate -coordinates_max = 1.0 # maximum coordinate +coordinates_max = 1.0 # maximum coordinate # Create a uniformly refined mesh with periodic boundaries mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=30_000) # set maximum capacity of tree data structure + initial_refinement_level = 4, + n_cells_max = 30_000) # set maximum capacity of tree data structure # A semidiscretization collects data structures and functions for the spatial discretization -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, solver) - +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, + solver) ############################################################################### # ODE solvers, callbacks etc. @@ -34,26 +34,26 @@ ode = semidiscretize(semi, (0.0, 1.0)); summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); # Print the timer summary summary_callback() diff --git a/examples/tree_1d_dgsem/elixir_advection_diffusion.jl b/examples/tree_1d_dgsem/elixir_advection_diffusion.jl index 0472bd25a71..72b8b3f1933 100644 --- a/examples/tree_1d_dgsem/elixir_advection_diffusion.jl +++ b/examples/tree_1d_dgsem/elixir_advection_diffusion.jl @@ -11,49 +11,52 @@ diffusivity() = 0.1 equations_parabolic = LaplaceDiffusion1D(diffusivity(), equations) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = -pi # minimum coordinate -coordinates_max = pi # maximum coordinate +coordinates_max = pi # maximum coordinate # Create a uniformly refined mesh with periodic boundaries mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=30_000, # set maximum capacity of tree data structure - periodicity=true) - -function x_trans_periodic(x, domain_length = SVector(2*pi), center = SVector(0.0)) - x_normalized = x .- center - x_shifted = x_normalized .% domain_length - x_offset = ((x_shifted .< -0.5*domain_length) - (x_shifted .> 0.5*domain_length)) .* domain_length - return center + x_shifted + x_offset + initial_refinement_level = 4, + n_cells_max = 30_000, # set maximum capacity of tree data structure + periodicity = true) + +function x_trans_periodic(x, domain_length = SVector(2 * pi), center = SVector(0.0)) + x_normalized = x .- center + x_shifted = x_normalized .% domain_length + x_offset = ((x_shifted .< -0.5 * domain_length) - (x_shifted .> 0.5 * domain_length)) .* + domain_length + return center + x_shifted + x_offset end # Define initial condition -function initial_condition_diffusive_convergence_test(x, t, equation::LinearScalarAdvectionEquation1D) - # Store translated coordinate for easy use of exact solution - x_trans = x_trans_periodic(x - equation.advection_velocity * t) - - nu = diffusivity() - c = 0.0 - A = 1.0 - L = 2 - f = 1/L - omega = 1.0 - scalar = c + A * sin(omega * sum(x_trans)) * exp(-nu * omega^2 * t) - return SVector(scalar) +function initial_condition_diffusive_convergence_test(x, t, + equation::LinearScalarAdvectionEquation1D) + # Store translated coordinate for easy use of exact solution + x_trans = x_trans_periodic(x - equation.advection_velocity * t) + + nu = diffusivity() + c = 0.0 + A = 1.0 + L = 2 + f = 1 / L + omega = 1.0 + scalar = c + A * sin(omega * sum(x_trans)) * exp(-nu * omega^2 * t) + return SVector(scalar) end initial_condition = initial_condition_diffusive_convergence_test - + # define periodic boundary conditions everywhere boundary_conditions = boundary_condition_periodic boundary_conditions_parabolic = boundary_condition_periodic # A semidiscretization collects data structures and functions for the spatial discretization -semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), - initial_condition_diffusive_convergence_test, solver; - boundary_conditions=(boundary_conditions, boundary_conditions_parabolic)) - +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition_diffusive_convergence_test, + solver; + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic)) ############################################################################### # ODE solvers, callbacks etc. @@ -67,23 +70,22 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The AliveCallback prints short status information in regular intervals -alive_callback = AliveCallback(analysis_interval=100) +alive_callback = AliveCallback(analysis_interval = 100) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) - ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks time_int_tol = 1.0e-10 time_abs_tol = 1.0e-10 -sol = solve(ode, KenCarp4(autodiff=false), abstol=time_abs_tol, reltol=time_int_tol, - save_everystep=false, callback=callbacks) +sol = solve(ode, KenCarp4(autodiff = false), abstol = time_abs_tol, reltol = time_int_tol, + save_everystep = false, callback = callbacks) # Print the timer summary summary_callback() diff --git a/examples/tree_1d_dgsem/elixir_advection_extended.jl b/examples/tree_1d_dgsem/elixir_advection_extended.jl index 5c87ac7ef5c..df185834701 100644 --- a/examples/tree_1d_dgsem/elixir_advection_extended.jl +++ b/examples/tree_1d_dgsem/elixir_advection_extended.jl @@ -18,21 +18,20 @@ initial_condition = initial_condition_convergence_test boundary_conditions = boundary_condition_periodic # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = -1.0 # minimum coordinate -coordinates_max = 1.0 # maximum coordinate +coordinates_max = 1.0 # maximum coordinate # Create a uniformly refined mesh with periodic boundaries mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=30_000, # set maximum capacity of tree data structure - periodicity=true) + initial_refinement_level = 4, + n_cells_max = 30_000, # set maximum capacity of tree data structure + periodicity = true) # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -47,24 +46,24 @@ summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy, energy_total)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy, energy_total)) # The AliveCallback prints short status information in regular intervals -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) # The SaveRestartCallback allows to save a file from which a Trixi.jl simulation can be restarted -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver callbacks = CallbackSet(summary_callback, @@ -72,14 +71,13 @@ callbacks = CallbackSet(summary_callback, save_restart, save_solution, stepsize_callback) - ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); # Print the timer summary summary_callback() diff --git a/examples/tree_1d_dgsem/elixir_advection_finite_volume.jl b/examples/tree_1d_dgsem/elixir_advection_finite_volume.jl index 28518e7276a..62701f3ecf5 100644 --- a/examples/tree_1d_dgsem/elixir_advection_finite_volume.jl +++ b/examples/tree_1d_dgsem/elixir_advection_finite_volume.jl @@ -10,19 +10,19 @@ equations = LinearScalarAdvectionEquation1D(advection_velocity) # Create DG solver with polynomial degree = 0, i.e., a first order finite volume solver, # with (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=0, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 0, surface_flux = flux_lax_friedrichs) coordinates_min = -1.0 # minimum coordinate -coordinates_max = 1.0 # maximum coordinate +coordinates_max = 1.0 # maximum coordinate # Create a uniformly refined mesh with periodic boundaries mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=5, - n_cells_max=30_000) # set maximum capacity of tree data structure + initial_refinement_level = 5, + n_cells_max = 30_000) # set maximum capacity of tree data structure # A semidiscretization collects data structures and functions for the spatial discretization -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, solver) - +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, + solver) ############################################################################### # ODE solvers, callbacks etc. @@ -35,22 +35,21 @@ ode = semidiscretize(semi, (0.0, 1.0)); summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=0.9) +stepsize_callback = StepsizeCallback(cfl = 0.9) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver callbacks = CallbackSet(summary_callback, analysis_callback, stepsize_callback) - ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks sol = solve(ode, Euler(), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); # Print the timer summary summary_callback() diff --git a/examples/tree_1d_dgsem/elixir_burgers_basic.jl b/examples/tree_1d_dgsem/elixir_burgers_basic.jl index cebd9b11201..f57b8e730fe 100644 --- a/examples/tree_1d_dgsem/elixir_burgers_basic.jl +++ b/examples/tree_1d_dgsem/elixir_burgers_basic.jl @@ -9,18 +9,16 @@ equations = InviscidBurgersEquation1D() initial_condition = initial_condition_convergence_test -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = 0.0 coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) - + initial_refinement_level = 4, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -31,29 +29,28 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_errors=(:l2_error_primitive, - :linf_error_primitive)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_errors = (:l2_error_primitive, + :linf_error_primitive)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_burgers_linear_stability.jl b/examples/tree_1d_dgsem/elixir_burgers_linear_stability.jl index 6a25f94ca05..ae2039edde6 100644 --- a/examples/tree_1d_dgsem/elixir_burgers_linear_stability.jl +++ b/examples/tree_1d_dgsem/elixir_burgers_linear_stability.jl @@ -8,23 +8,22 @@ using Trixi equations = InviscidBurgersEquation1D() function initial_condition_linear_stability(x, t, equation::InviscidBurgersEquation1D) - k = 1 - 2 + sinpi(k * (x[1] - 0.7)) |> SVector + k = 1 + 2 + sinpi(k * (x[1] - 0.7)) |> SVector end volume_flux = flux_ec -solver = DGSEM(polydeg=3, surface_flux=flux_ec, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_ec, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = -1.0 -coordinates_max = 1.0 +coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) - - -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_linear_stability, solver) + initial_refinement_level = 4, + n_cells_max = 10_000) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_linear_stability, + solver) ############################################################################### # ODE solvers, callbacks etc. @@ -35,23 +34,22 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_errors=(:l2_error_primitive, - :linf_error_primitive)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_errors = (:l2_error_primitive, + :linf_error_primitive)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_burgers_rarefaction.jl b/examples/tree_1d_dgsem/elixir_burgers_rarefaction.jl index 28ab7b7c768..d32b9d6f1f4 100644 --- a/examples/tree_1d_dgsem/elixir_burgers_rarefaction.jl +++ b/examples/tree_1d_dgsem/elixir_burgers_rarefaction.jl @@ -10,18 +10,18 @@ equations = InviscidBurgersEquation1D() basis = LobattoLegendreBasis(3) # Use shock capturing techniques to suppress oscillations at discontinuities indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=1.0, - alpha_min=0.001, - alpha_smooth=true, - variable=first) + alpha_max = 1.0, + alpha_min = 0.001, + alpha_smooth = true, + variable = first) -volume_flux = flux_ec +volume_flux = flux_ec surface_flux = flux_lax_friedrichs volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) - + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) + solver = DGSEM(basis, surface_flux, volume_integral) coordinate_min = 0.0 @@ -29,42 +29,41 @@ coordinate_max = 1.0 # Make sure to turn periodicity explicitly off as special boundary conditions are specified mesh = TreeMesh(coordinate_min, coordinate_max, - initial_refinement_level=6, - n_cells_max=10_000, - periodicity=false) + initial_refinement_level = 6, + n_cells_max = 10_000, + periodicity = false) # Discontinuous initial condition (Riemann Problem) leading to a rarefaction fan. function initial_condition_rarefaction(x, t, equation::InviscidBurgersEquation1D) - scalar = x[1] < 0.5 ? 0.5 : 1.5 + scalar = x[1] < 0.5 ? 0.5 : 1.5 - return SVector(scalar) -end + return SVector(scalar) +end ############################################################################### # Specify non-periodic boundary conditions function inflow(x, t, equations::InviscidBurgersEquation1D) - return initial_condition_rarefaction(coordinate_min, t, equations) + return initial_condition_rarefaction(coordinate_min, t, equations) end boundary_condition_inflow = BoundaryConditionDirichlet(inflow) function boundary_condition_outflow(u_inner, orientation, normal_direction, x, t, - surface_flux_function, equations::InviscidBurgersEquation1D) - # Calculate the boundary flux entirely from the internal solution state - flux = Trixi.flux(u_inner, normal_direction, equations) + surface_flux_function, + equations::InviscidBurgersEquation1D) + # Calculate the boundary flux entirely from the internal solution state + flux = Trixi.flux(u_inner, normal_direction, equations) - return flux + return flux end +boundary_conditions = (x_neg = boundary_condition_inflow, + x_pos = boundary_condition_outflow) -boundary_conditions = (x_neg=boundary_condition_inflow, - x_pos=boundary_condition_outflow) - initial_condition = initial_condition_rarefaction semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -75,12 +74,11 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) - -stepsize_callback = StepsizeCallback(cfl=0.9) +alive_callback = AliveCallback(analysis_interval = analysis_interval) +stepsize_callback = StepsizeCallback(cfl = 0.9) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -89,9 +87,8 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation - -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=42, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 42, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_burgers_shock.jl b/examples/tree_1d_dgsem/elixir_burgers_shock.jl index 00b5314e19f..1f0b0e7e042 100644 --- a/examples/tree_1d_dgsem/elixir_burgers_shock.jl +++ b/examples/tree_1d_dgsem/elixir_burgers_shock.jl @@ -10,17 +10,17 @@ equations = InviscidBurgersEquation1D() basis = LobattoLegendreBasis(3) # Use shock capturing techniques to suppress oscillations at discontinuities indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=1.0, - alpha_min=0.001, - alpha_smooth=true, - variable=first) + alpha_max = 1.0, + alpha_min = 0.001, + alpha_smooth = true, + variable = first) -volume_flux = flux_ec +volume_flux = flux_ec surface_flux = flux_lax_friedrichs volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=surface_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = surface_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) @@ -29,42 +29,41 @@ coordinate_max = 1.0 # Make sure to turn periodicity explicitly off as special boundary conditions are specified mesh = TreeMesh(coordinate_min, coordinate_max, - initial_refinement_level=6, - n_cells_max=10_000, - periodicity=false) + initial_refinement_level = 6, + n_cells_max = 10_000, + periodicity = false) # Discontinuous initial condition (Riemann Problem) leading to a shock to test e.g. correct shock speed. function initial_condition_shock(x, t, equation::InviscidBurgersEquation1D) - scalar = x[1] < 0.5 ? 1.5 : 0.5 + scalar = x[1] < 0.5 ? 1.5 : 0.5 - return SVector(scalar) + return SVector(scalar) end ############################################################################### # Specify non-periodic boundary conditions function inflow(x, t, equations::InviscidBurgersEquation1D) - return initial_condition_shock(coordinate_min, t, equations) + return initial_condition_shock(coordinate_min, t, equations) end boundary_condition_inflow = BoundaryConditionDirichlet(inflow) function boundary_condition_outflow(u_inner, orientation, normal_direction, x, t, - surface_flux_function, equations::InviscidBurgersEquation1D) - # Calculate the boundary flux entirely from the internal solution state - flux = Trixi.flux(u_inner, normal_direction, equations) + surface_flux_function, + equations::InviscidBurgersEquation1D) + # Calculate the boundary flux entirely from the internal solution state + flux = Trixi.flux(u_inner, normal_direction, equations) - return flux + return flux end - -boundary_conditions = (x_neg=boundary_condition_inflow, - x_pos=boundary_condition_outflow) +boundary_conditions = (x_neg = boundary_condition_inflow, + x_pos = boundary_condition_outflow) initial_condition = initial_condition_shock semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -75,12 +74,11 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) - -stepsize_callback = StepsizeCallback(cfl=0.85) +alive_callback = AliveCallback(analysis_interval = analysis_interval) +stepsize_callback = StepsizeCallback(cfl = 0.85) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -89,9 +87,8 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation - -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=42, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 42, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_euler_blast_wave.jl b/examples/tree_1d_dgsem/elixir_euler_blast_wave.jl index 2318063c2be..9cba4936d22 100644 --- a/examples/tree_1d_dgsem/elixir_euler_blast_wave.jl +++ b/examples/tree_1d_dgsem/elixir_euler_blast_wave.jl @@ -16,49 +16,47 @@ A medium blast wave taken from [arXiv: 2008.12044](https://arxiv.org/abs/2008.12044) """ function initial_condition_blast_wave(x, t, equations::CompressibleEulerEquations1D) - # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" - # Set up polar coordinates - inicenter = SVector(0.0) - x_norm = x[1] - inicenter[1] - r = abs(x_norm) - # The following code is equivalent to - # phi = atan(0.0, x_norm) - # cos_phi = cos(phi) - # in 1D but faster - cos_phi = x_norm > 0 ? one(x_norm) : -one(x_norm) - - # Calculate primitive variables - rho = r > 0.5 ? 1.0 : 1.1691 - v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi - p = r > 0.5 ? 1.0E-3 : 1.245 - - return prim2cons(SVector(rho, v1, p), equations) + # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" + # Set up polar coordinates + inicenter = SVector(0.0) + x_norm = x[1] - inicenter[1] + r = abs(x_norm) + # The following code is equivalent to + # phi = atan(0.0, x_norm) + # cos_phi = cos(phi) + # in 1D but faster + cos_phi = x_norm > 0 ? one(x_norm) : -one(x_norm) + + # Calculate primitive variables + rho = r > 0.5 ? 1.0 : 1.1691 + v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi + p = r > 0.5 ? 1.0E-3 : 1.245 + + return prim2cons(SVector(rho, v1, p), equations) end initial_condition = initial_condition_blast_wave surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha +volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-2.0,) -coordinates_max = ( 2.0,) +coordinates_max = (2.0,) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=10_000) - + initial_refinement_level = 6, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -69,27 +67,26 @@ summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_euler_blast_wave_neuralnetwork_perssonperaire.jl b/examples/tree_1d_dgsem/elixir_euler_blast_wave_neuralnetwork_perssonperaire.jl deleted file mode 100644 index d35dec6bc73..00000000000 --- a/examples/tree_1d_dgsem/elixir_euler_blast_wave_neuralnetwork_perssonperaire.jl +++ /dev/null @@ -1,112 +0,0 @@ -using Downloads: download -using Flux -using BSON: load -network = joinpath(@__DIR__, "modelnnpp-0.97-0.0001.bson") -download("https://github.com/trixi-framework/Trixi_IndicatorNeuralNetwork_networks/raw/main/networks/modelnnpp-0.97-0.0001.bson", network) -model1d = load(network, @__MODULE__)[:model1d] - -using OrdinaryDiffEq -using Trixi - -# This elixir was one of the setups used in the following master thesis: -# - Julia Odenthal (2021) -# Shock capturing with artificial neural networks -# University of Cologne, advisors: Gregor Gassner, Michael Schlottke-Lakemper -# This motivates the particular choice of fluxes, mesh resolution etc. - - -############################################################################### -# semidiscretization of the compressible Euler equations - -equations = CompressibleEulerEquations1D(1.4) - -""" - initial_condition_blast_wave(x, t, equations::CompressibleEulerEquations1D) - -A medium 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](https://arxiv.org/abs/2008.12044) -""" -function initial_condition_blast_wave(x, t, equations::CompressibleEulerEquations1D) - # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" - # Set up polar coordinates - inicenter = SVector(0.0) - x_norm = x[1] - inicenter[1] - r = abs(x_norm) - # The following code is equivalent to - # phi = atan(0.0, x_norm) - # cos_phi = cos(phi) - # in 1D but faster - cos_phi = x_norm > 0 ? one(x_norm) : -one(x_norm) - - # Calculate primitive variables - rho = r > 0.5 ? 1.0 : 1.1691 - v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi - p = r > 0.5 ? 1.0E-3 : 1.245 - - return prim2cons(SVector(rho, v1, p), equations) -end -initial_condition = initial_condition_blast_wave - -surface_flux = flux_lax_friedrichs -volume_flux = flux_chandrashekar -basis = LobattoLegendreBasis(3) -indicator_sc = IndicatorNeuralNetwork(equations, basis, - indicator_type=NeuralNetworkPerssonPeraire(), - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - alpha_continuous=false, - alpha_amr=false, - variable=density_pressure, - network=model1d) -volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) -solver = DGSEM(basis, surface_flux, volume_integral) - -coordinates_min = (-2.0,) -coordinates_max = ( 2.0,) -mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=10_000) - - -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - - -############################################################################### -# ODE solvers, callbacks etc. - -tspan = (0.0, 12.5) -ode = semidiscretize(semi, tspan) - -summary_callback = SummaryCallback() - -analysis_interval = 100 - -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) - -alive_callback = AliveCallback(analysis_interval=analysis_interval) - -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) - -stepsize_callback = StepsizeCallback(cfl=0.5) - -callbacks = CallbackSet(summary_callback, - analysis_callback, alive_callback, - save_solution, - stepsize_callback) - - -############################################################################### -# run the simulation - -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); -summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_euler_blast_wave_neuralnetwork_rayhesthaven.jl b/examples/tree_1d_dgsem/elixir_euler_blast_wave_neuralnetwork_rayhesthaven.jl deleted file mode 100644 index fb36f8540f8..00000000000 --- a/examples/tree_1d_dgsem/elixir_euler_blast_wave_neuralnetwork_rayhesthaven.jl +++ /dev/null @@ -1,112 +0,0 @@ -using Downloads: download -using Flux -using BSON: load -network = joinpath(@__DIR__, "modelnnrh-0.95-0.009.bson") -download("https://github.com/trixi-framework/Trixi_IndicatorNeuralNetwork_networks/raw/main/networks/modelnnrh-0.95-0.009.bson", network) -model1d = load(network, @__MODULE__)[:model1d] - -using OrdinaryDiffEq -using Trixi - -# This elixir was one of the setups used in the following master thesis: -# - Julia Odenthal (2021) -# Shock capturing with artificial neural networks -# University of Cologne, advisors: Gregor Gassner, Michael Schlottke-Lakemper -# This motivates the particular choice of fluxes, mesh resolution etc. - - -############################################################################### -# semidiscretization of the compressible Euler equations - -equations = CompressibleEulerEquations1D(1.4) - -""" - initial_condition_blast_wave(x, t, equations::CompressibleEulerEquations1D) - -A medium 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](https://arxiv.org/abs/2008.12044) -""" -function initial_condition_blast_wave(x, t, equations::CompressibleEulerEquations1D) - # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" - # Set up polar coordinates - inicenter = SVector(0.0) - x_norm = x[1] - inicenter[1] - r = abs(x_norm) - # The following code is equivalent to - # phi = atan(0.0, x_norm) - # cos_phi = cos(phi) - # in 1D but faster - cos_phi = x_norm > 0 ? one(x_norm) : -one(x_norm) - - # Calculate primitive variables - rho = r > 0.5 ? 1.0 : 1.1691 - v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi - p = r > 0.5 ? 1.0E-3 : 1.245 - - return prim2cons(SVector(rho, v1, p), equations) -end -initial_condition = initial_condition_blast_wave - -surface_flux = flux_lax_friedrichs -volume_flux = flux_chandrashekar -basis = LobattoLegendreBasis(3) -indicator_sc = IndicatorNeuralNetwork(equations, basis, - indicator_type=NeuralNetworkRayHesthaven(), - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - alpha_continuous=false, - alpha_amr=false, - variable=density_pressure, - network=model1d) -volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) -solver = DGSEM(basis, surface_flux, volume_integral) - -coordinates_min = (-2.0,) -coordinates_max = ( 2.0,) -mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=10_000) - - -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - - -############################################################################### -# ODE solvers, callbacks etc. - -tspan = (0.0, 12.5) -ode = semidiscretize(semi, tspan) - -summary_callback = SummaryCallback() - -analysis_interval = 100 - -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) - -alive_callback = AliveCallback(analysis_interval=analysis_interval) - -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) - -stepsize_callback = StepsizeCallback(cfl=0.5) - -callbacks = CallbackSet(summary_callback, - analysis_callback, alive_callback, - save_solution, - stepsize_callback) - - -############################################################################### -# run the simulation - -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); -summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_euler_convergence_pure_fv.jl b/examples/tree_1d_dgsem/elixir_euler_convergence_pure_fv.jl index fe221ea5bd7..1fa07d4edda 100644 --- a/examples/tree_1d_dgsem/elixir_euler_convergence_pure_fv.jl +++ b/examples/tree_1d_dgsem/elixir_euler_convergence_pure_fv.jl @@ -9,19 +9,17 @@ equations = CompressibleEulerEquations1D(1.4) initial_condition = initial_condition_convergence_test -solver = DGSEM(polydeg=3, surface_flux=flux_hllc, - volume_integral=VolumeIntegralPureLGLFiniteVolume(flux_hllc)) +solver = DGSEM(polydeg = 3, surface_flux = flux_hllc, + volume_integral = VolumeIntegralPureLGLFiniteVolume(flux_hllc)) coordinates_min = 0.0 coordinates_max = 2.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) - + initial_refinement_level = 4, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -32,29 +30,28 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_errors=(:l2_error_primitive, - :linf_error_primitive)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_errors = (:l2_error_primitive, + :linf_error_primitive)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_euler_density_wave.jl b/examples/tree_1d_dgsem/elixir_euler_density_wave.jl index 746989dfe56..01ccbb2b517 100644 --- a/examples/tree_1d_dgsem/elixir_euler_density_wave.jl +++ b/examples/tree_1d_dgsem/elixir_euler_density_wave.jl @@ -8,18 +8,16 @@ equations = CompressibleEulerEquations1D(1.4) initial_condition = initial_condition_density_wave -solver = DGSEM(polydeg=5, surface_flux=flux_central) +solver = DGSEM(polydeg = 5, surface_flux = flux_central) coordinates_min = -1.0 -coordinates_max = 1.0 +coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=30_000) - + initial_refinement_level = 2, + n_cells_max = 30_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -29,16 +27,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 2000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -48,7 +46,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=stepsize_callback(ode), # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = stepsize_callback(ode), # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_euler_ec.jl b/examples/tree_1d_dgsem/elixir_euler_ec.jl index f20bd4fd69e..0be9c8fbf4c 100644 --- a/examples/tree_1d_dgsem/elixir_euler_ec.jl +++ b/examples/tree_1d_dgsem/elixir_euler_ec.jl @@ -9,19 +9,17 @@ equations = CompressibleEulerEquations1D(1.4) initial_condition = initial_condition_weak_blast_wave volume_flux = flux_ranocha -solver = DGSEM(polydeg=3, surface_flux=flux_ranocha, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_ranocha, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-2.0,) -coordinates_max = ( 2.0,) +coordinates_max = (2.0,) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=5, - n_cells_max=10_000) - + initial_refinement_level = 5, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -31,27 +29,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_euler_positivity.jl b/examples/tree_1d_dgsem/elixir_euler_positivity.jl index 966661e8894..3fb96fb807b 100644 --- a/examples/tree_1d_dgsem/elixir_euler_positivity.jl +++ b/examples/tree_1d_dgsem/elixir_euler_positivity.jl @@ -14,97 +14,92 @@ The Sedov blast wave setup based on Flash - https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 """ function initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEquations1D) - # Set up polar coordinates - inicenter = SVector(0.0) - x_norm = x[1] - inicenter[1] - r = abs(x_norm) - - # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 - r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) - # r0 = 0.5 # = more reasonable setup - E = 1.0 - p0_inner = 6 * (equations.gamma - 1) * E / (3 * pi * r0) - p0_outer = 1.0e-5 # = true Sedov setup - # p0_outer = 1.0e-3 # = more reasonable setup - - # Calculate primitive variables - rho = 1.0 - v1 = 0.0 - p = r > r0 ? p0_outer : p0_inner - - return prim2cons(SVector(rho, v1, p), equations) + # Set up polar coordinates + inicenter = SVector(0.0) + x_norm = x[1] - inicenter[1] + r = abs(x_norm) + + # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 + r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) + # r0 = 0.5 # = more reasonable setup + E = 1.0 + p0_inner = 6 * (equations.gamma - 1) * E / (3 * pi * r0) + p0_outer = 1.0e-5 # = true Sedov setup + # p0_outer = 1.0e-3 # = more reasonable setup + + # Calculate primitive variables + rho = 1.0 + v1 = 0.0 + p = r > r0 ? p0_outer : p0_inner + + return prim2cons(SVector(rho, v1, p), equations) end initial_condition = initial_condition_sedov_blast_wave surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha +volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-2.0,) -coordinates_max = ( 2.0,) +coordinates_max = (2.0,) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=10_000) - + initial_refinement_level = 6, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. tspan = (0.0, 4.0) ode = semidiscretize(semi, tspan) - summary_callback = SummaryCallback() analysis_interval = 500 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_indicator = IndicatorLöhner(semi, - variable=density_pressure) + variable = density_pressure) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=4, - med_level =0, med_threshold=0.1, # med_level = current level - max_level =6, max_threshold=0.3) + base_level = 4, + med_level = 0, med_threshold = 0.1, # med_level = current level + max_level = 6, max_threshold = 0.3) amr_callback = AMRCallback(semi, amr_controller, - interval=2, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 2, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, amr_callback, stepsize_callback) - -stage_limiter! = PositivityPreservingLimiterZhangShu(thresholds=(5.0e-6, 5.0e-6), - variables=(Trixi.density, pressure)) - +stage_limiter! = PositivityPreservingLimiterZhangShu(thresholds = (5.0e-6, 5.0e-6), + variables = (Trixi.density, pressure)) ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(stage_limiter!, williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(stage_limiter!, williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_euler_quasi_1d_discontinuous.jl b/examples/tree_1d_dgsem/elixir_euler_quasi_1d_discontinuous.jl new file mode 100644 index 00000000000..cc4535be028 --- /dev/null +++ b/examples/tree_1d_dgsem/elixir_euler_quasi_1d_discontinuous.jl @@ -0,0 +1,85 @@ +using OrdinaryDiffEq +using Trixi + +############################################################################### +# Semidiscretization of the quasi 1d compressible Euler equations +# See Chan et al. https://doi.org/10.48550/arXiv.2307.12089 for details + +equations = CompressibleEulerEquationsQuasi1D(1.4) + +""" + initial_condition_discontinuity(x, t, equations::CompressibleEulerEquations1D) + +A discontinuous initial condition taken from +- 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](https://doi.org/10.48550/arXiv.2307.12089) +""" +function initial_condition_discontinuity(x, t, + equations::CompressibleEulerEquationsQuasi1D) + rho = (x[1] < 0) ? 3.4718 : 2.0 + v1 = (x[1] < 0) ? -2.5923 : -3.0 + p = (x[1] < 0) ? 5.7118 : 2.639 + a = (x[1] < 0) ? 1.0 : 1.5 + + return prim2cons(SVector(rho, v1, p, a), equations) +end + +initial_condition = initial_condition_discontinuity + +surface_flux = (flux_lax_friedrichs, flux_nonconservative_chan_etal) +volume_flux = (flux_chan_etal, flux_nonconservative_chan_etal) + +basis = LobattoLegendreBasis(3) +indicator_sc = IndicatorHennemannGassner(equations, basis, + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) +volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) +solver = DGSEM(basis, surface_flux, volume_integral) + +coordinates_min = (-1.0,) +coordinates_max = (1.0,) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level = 6, + n_cells_max = 10_000) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 2.0) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 100 + +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) + +stepsize_callback = StepsizeCallback(cfl = 0.5) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + save_solution, + stepsize_callback) + +############################################################################### +# run the simulation + +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); +summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_euler_quasi_1d_ec.jl b/examples/tree_1d_dgsem/elixir_euler_quasi_1d_ec.jl new file mode 100644 index 00000000000..ae1b2b24b62 --- /dev/null +++ b/examples/tree_1d_dgsem/elixir_euler_quasi_1d_ec.jl @@ -0,0 +1,73 @@ +using OrdinaryDiffEq +using Trixi + +############################################################################### +# Semidiscretization of the quasi 1d compressible Euler equations with a discontinuous nozzle width function. +# See Chan et al. https://doi.org/10.48550/arXiv.2307.12089 for details + +equations = CompressibleEulerEquationsQuasi1D(1.4) + +# Setup a truly discontinuous density function and nozzle width for +# this academic testcase of entropy conservation. The errors from the analysis +# callback are not important but the entropy error for this test case +# `∑∂S/∂U ⋅ Uₜ` should be around machine roundoff. +# Works as intended for TreeMesh1D with `initial_refinement_level=6`. If the mesh +# refinement level is changed the initial condition below may need changed as well to +# ensure that the discontinuities lie on an element interface. +function initial_condition_ec(x, t, equations::CompressibleEulerEquationsQuasi1D) + v1 = 0.1 + rho = 2.0 + 0.1 * x[1] + p = 3.0 + a = 2.0 + x[1] + + return prim2cons(SVector(rho, v1, p, a), equations) +end + +initial_condition = initial_condition_ec + +surface_flux = (flux_chan_etal, flux_nonconservative_chan_etal) +volume_flux = surface_flux +solver = DGSEM(polydeg = 4, surface_flux = surface_flux, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) + +coordinates_min = (-1.0,) +coordinates_max = (1.0,) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level = 6, + n_cells_max = 10_000) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 0.4) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 100 + +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) + +stepsize_callback = StepsizeCallback(cfl = 0.8) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + save_solution, + stepsize_callback) + +############################################################################### +# run the simulation + +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); +summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_euler_quasi_1d_source_terms.jl b/examples/tree_1d_dgsem/elixir_euler_quasi_1d_source_terms.jl new file mode 100644 index 00000000000..91bb1ba6e8c --- /dev/null +++ b/examples/tree_1d_dgsem/elixir_euler_quasi_1d_source_terms.jl @@ -0,0 +1,60 @@ +using OrdinaryDiffEq +using Trixi +using ForwardDiff + +############################################################################### +# Semidiscretization of the quasi 1d compressible Euler equations +# See Chan et al. https://doi.org/10.48550/arXiv.2307.12089 for details + +equations = CompressibleEulerEquationsQuasi1D(1.4) + +initial_condition = initial_condition_convergence_test + +surface_flux = (flux_chan_etal, flux_nonconservative_chan_etal) +volume_flux = surface_flux +solver = DGSEM(polydeg = 4, surface_flux = surface_flux, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) + +coordinates_min = -1.0 +coordinates_max = 1.0 +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level = 4, + n_cells_max = 10_000) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + source_terms = source_terms_convergence_test) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 2.0) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_errors = (:l2_error_primitive, + :linf_error_primitive)) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) + +stepsize_callback = StepsizeCallback(cfl = 0.8) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + save_solution, + stepsize_callback) + +############################################################################### +# run the simulation + +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); +summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_euler_sedov_blast_wave.jl b/examples/tree_1d_dgsem/elixir_euler_sedov_blast_wave.jl index 106ccacf4f5..b67b2bc602e 100644 --- a/examples/tree_1d_dgsem/elixir_euler_sedov_blast_wave.jl +++ b/examples/tree_1d_dgsem/elixir_euler_sedov_blast_wave.jl @@ -14,96 +14,92 @@ The Sedov blast wave setup based on Flash - https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 """ function initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEquations1D) - # Set up polar coordinates - inicenter = SVector(0.0) - x_norm = x[1] - inicenter[1] - r = abs(x_norm) - - # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 - r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) - # r0 = 0.5 # = more reasonable setup - E = 1.0 - p0_inner = 6 * (equations.gamma - 1) * E / (3 * pi * r0) - p0_outer = 1.0e-5 # = true Sedov setup - # p0_outer = 1.0e-3 # = more reasonable setup - - # Calculate primitive variables - rho = 1.0 - v1 = 0.0 - p = r > r0 ? p0_outer : p0_inner - - return prim2cons(SVector(rho, v1, p), equations) + # Set up polar coordinates + inicenter = SVector(0.0) + x_norm = x[1] - inicenter[1] + r = abs(x_norm) + + # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 + r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) + # r0 = 0.5 # = more reasonable setup + E = 1.0 + p0_inner = 6 * (equations.gamma - 1) * E / (3 * pi * r0) + p0_outer = 1.0e-5 # = true Sedov setup + # p0_outer = 1.0e-3 # = more reasonable setup + + # Calculate primitive variables + rho = 1.0 + v1 = 0.0 + p = r > r0 ? p0_outer : p0_inner + + return prim2cons(SVector(rho, v1, p), equations) end initial_condition = initial_condition_sedov_blast_wave surface_flux = flux_lax_friedrichs -volume_flux = flux_chandrashekar +volume_flux = flux_chandrashekar basis = LobattoLegendreBasis(3) shock_indicator_variable = density_pressure indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=shock_indicator_variable) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = shock_indicator_variable) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-2.0,) -coordinates_max = ( 2.0,) +coordinates_max = (2.0,) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=10_000) - + initial_refinement_level = 6, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. tspan = (0.0, 12.5) ode = semidiscretize(semi, tspan) - summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_indicator = IndicatorHennemannGassner(semi, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=4, - max_level=6, max_threshold=0.01) + base_level = 4, + max_level = 6, max_threshold = 0.01) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, amr_callback, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=stepsize_callback(ode), # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = stepsize_callback(ode), # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_euler_sedov_blast_wave_pure_fv.jl b/examples/tree_1d_dgsem/elixir_euler_sedov_blast_wave_pure_fv.jl index ebe8fa7cebf..8a0241680b9 100644 --- a/examples/tree_1d_dgsem/elixir_euler_sedov_blast_wave_pure_fv.jl +++ b/examples/tree_1d_dgsem/elixir_euler_sedov_blast_wave_pure_fv.jl @@ -14,25 +14,25 @@ The Sedov blast wave setup based on Flash - https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 """ function initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEquations1D) - # Set up polar coordinates - inicenter = SVector(0.0) - x_norm = x[1] - inicenter[1] - r = abs(x_norm) - - # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 - r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) - # r0 = 0.5 # = more reasonable setup - E = 1.0 - p0_inner = 6 * (equations.gamma - 1) * E / (3 * pi * r0) - p0_outer = 1.0e-5 # = true Sedov setup - # p0_outer = 1.0e-3 # = more reasonable setup - - # Calculate primitive variables - rho = 1.0 - v1 = 0.0 - p = r > r0 ? p0_outer : p0_inner - - return prim2cons(SVector(rho, v1, p), equations) + # Set up polar coordinates + inicenter = SVector(0.0) + x_norm = x[1] - inicenter[1] + r = abs(x_norm) + + # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 + r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) + # r0 = 0.5 # = more reasonable setup + E = 1.0 + p0_inner = 6 * (equations.gamma - 1) * E / (3 * pi * r0) + p0_outer = 1.0e-5 # = true Sedov setup + # p0_outer = 1.0e-3 # = more reasonable setup + + # Calculate primitive variables + rho = 1.0 + v1 = 0.0 + p = r > r0 ? p0_outer : p0_inner + + return prim2cons(SVector(rho, v1, p), equations) end initial_condition = initial_condition_sedov_blast_wave @@ -42,59 +42,55 @@ volume_integral = VolumeIntegralPureLGLFiniteVolume(flux_hllc) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-2.0,) -coordinates_max = ( 2.0,) +coordinates_max = (2.0,) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=7, - n_cells_max=10_000) - + initial_refinement_level = 7, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. tspan = (0.0, 12.5) ode = semidiscretize(semi, tspan) - summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_indicator = IndicatorHennemannGassner(semi, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=4, - max_level=7, max_threshold=0.01) + base_level = 4, + max_level = 7, max_threshold = 0.01) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=0.25) +stepsize_callback = StepsizeCallback(cfl = 0.25) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, amr_callback, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=stepsize_callback(ode), # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = stepsize_callback(ode), # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_euler_shockcapturing.jl b/examples/tree_1d_dgsem/elixir_euler_shockcapturing.jl index 90547f8ddc1..08367505377 100644 --- a/examples/tree_1d_dgsem/elixir_euler_shockcapturing.jl +++ b/examples/tree_1d_dgsem/elixir_euler_shockcapturing.jl @@ -10,28 +10,26 @@ equations = CompressibleEulerEquations1D(1.4) initial_condition = initial_condition_weak_blast_wave surface_flux = flux_lax_friedrichs -volume_flux = flux_shima_etal +volume_flux = flux_shima_etal basis = LobattoLegendreBasis(3) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = -2.0 -coordinates_max = 2.0 +coordinates_max = 2.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=5, - n_cells_max=10_000) - + initial_refinement_level = 5, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -41,27 +39,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_euler_source_terms.jl b/examples/tree_1d_dgsem/elixir_euler_source_terms.jl index 213206eb9e0..555910f69f0 100644 --- a/examples/tree_1d_dgsem/elixir_euler_source_terms.jl +++ b/examples/tree_1d_dgsem/elixir_euler_source_terms.jl @@ -11,18 +11,16 @@ initial_condition = initial_condition_convergence_test # Note that the expected EOC of 5 is not reached with this flux. # Using flux_hll instead yields the expected EOC. -solver = DGSEM(polydeg=4, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 4, surface_flux = flux_lax_friedrichs) coordinates_min = 0.0 coordinates_max = 2.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) - + initial_refinement_level = 4, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -33,29 +31,28 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_errors=(:l2_error_primitive, - :linf_error_primitive)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_errors = (:l2_error_primitive, + :linf_error_primitive)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_euler_source_terms_nonperiodic.jl b/examples/tree_1d_dgsem/elixir_euler_source_terms_nonperiodic.jl index 3794e0c8d54..922ac3dd97d 100644 --- a/examples/tree_1d_dgsem/elixir_euler_source_terms_nonperiodic.jl +++ b/examples/tree_1d_dgsem/elixir_euler_source_terms_nonperiodic.jl @@ -13,23 +13,21 @@ initial_condition = initial_condition_convergence_test # 1*ndims == 2 directions or you can pass a tuple containing BCs for # each direction boundary_condition = BoundaryConditionDirichlet(initial_condition) -boundary_conditions = (x_neg=boundary_condition, - x_pos=boundary_condition) +boundary_conditions = (x_neg = boundary_condition, + x_pos = boundary_condition) -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (0.0,) coordinates_max = (2.0,) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000, - periodicity=false) - + initial_refinement_level = 4, + n_cells_max = 10_000, + periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test, - boundary_conditions=boundary_conditions) - + source_terms = source_terms_convergence_test, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -40,30 +38,29 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_restart, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_eulergravity_convergence.jl b/examples/tree_1d_dgsem/elixir_eulergravity_convergence.jl index 42de0e18e51..acde04780ee 100644 --- a/examples/tree_1d_dgsem/elixir_eulergravity_convergence.jl +++ b/examples/tree_1d_dgsem/elixir_eulergravity_convergence.jl @@ -15,11 +15,11 @@ solver_euler = DGSEM(polydeg, flux_hll) coordinates_min = 0.0 coordinates_max = 2.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=10_000) - -semi_euler = SemidiscretizationHyperbolic(mesh, equations_euler, initial_condition, solver_euler) + initial_refinement_level = 2, + n_cells_max = 10_000) +semi_euler = SemidiscretizationHyperbolic(mesh, equations_euler, initial_condition, + solver_euler) ############################################################################### # semidiscretization of the hyperbolic diffusion equations @@ -27,22 +27,21 @@ equations_gravity = HyperbolicDiffusionEquations1D() solver_gravity = DGSEM(polydeg, flux_lax_friedrichs) -semi_gravity = SemidiscretizationHyperbolic(mesh, equations_gravity, initial_condition, solver_gravity, - source_terms=source_terms_harmonic) - +semi_gravity = SemidiscretizationHyperbolic(mesh, equations_gravity, initial_condition, + solver_gravity, + source_terms = source_terms_harmonic) ############################################################################### # combining both semidiscretizations for Euler + self-gravity -parameters = ParametersEulerGravity(background_density=2.0, # aka rho0 - gravitational_constant=1.0, # aka G - cfl=1.5, - resid_tol=1.0e-10, - n_iterations_max=1000, - timestep_gravity=timestep_gravity_erk52_3Sstar!) +parameters = ParametersEulerGravity(background_density = 2.0, # aka rho0 + gravitational_constant = 1.0, # aka G + cfl = 1.5, + resid_tol = 1.0e-10, + n_iterations_max = 1000, + timestep_gravity = timestep_gravity_erk52_3Sstar!) semi = SemidiscretizationEulerGravity(semi_euler, semi_gravity, parameters) - ############################################################################### # ODE solvers, callbacks etc. tspan = (0.0, 0.5) @@ -51,20 +50,20 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi_euler, interval=analysis_interval, - save_analysis=true) +analysis_callback = AnalysisCallback(semi_euler, interval = analysis_interval, + save_analysis = true) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=10, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 10, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.1) +stepsize_callback = StepsizeCallback(cfl = 1.1) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -73,11 +72,10 @@ callbacks = CallbackSet(summary_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary println("Number of gravity subcycles: ", semi.gravity_counter.ncalls_since_readout) diff --git a/examples/tree_1d_dgsem/elixir_eulermulti_convergence_ec.jl b/examples/tree_1d_dgsem/elixir_eulermulti_convergence_ec.jl index 2444fe8611d..6d6316898b7 100644 --- a/examples/tree_1d_dgsem/elixir_eulermulti_convergence_ec.jl +++ b/examples/tree_1d_dgsem/elixir_eulermulti_convergence_ec.jl @@ -4,25 +4,23 @@ using Trixi ############################################################################### # semidiscretization of the compressible Euler multicomponent equations -equations = CompressibleEulerMulticomponentEquations1D(gammas = (1.4, 1.4), +equations = CompressibleEulerMulticomponentEquations1D(gammas = (1.4, 1.4), gas_constants = (0.4, 0.4)) initial_condition = initial_condition_convergence_test volume_flux = flux_ranocha -solver = DGSEM(polydeg=3, surface_flux=flux_ranocha, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_ranocha, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-1.0,) -coordinates_max = ( 1.0,) +coordinates_max = (1.0,) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=30_000) - + initial_refinement_level = 3, + n_cells_max = 30_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -33,27 +31,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_eulermulti_convergence_es.jl b/examples/tree_1d_dgsem/elixir_eulermulti_convergence_es.jl index 86f4a4bad04..1b37a8a2279 100644 --- a/examples/tree_1d_dgsem/elixir_eulermulti_convergence_es.jl +++ b/examples/tree_1d_dgsem/elixir_eulermulti_convergence_es.jl @@ -4,25 +4,23 @@ using Trixi ############################################################################### # semidiscretization of the compressible Euler multicomponent equations -equations = CompressibleEulerMulticomponentEquations1D(gammas = (1.4, 1.4, 1.4, 1.4), +equations = CompressibleEulerMulticomponentEquations1D(gammas = (1.4, 1.4, 1.4, 1.4), gas_constants = (0.4, 0.4, 0.4, 0.4)) initial_condition = initial_condition_convergence_test volume_flux = flux_ranocha -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-1.0,) -coordinates_max = ( 1.0,) +coordinates_max = (1.0,) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=30_000) - + initial_refinement_level = 3, + n_cells_max = 30_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -33,27 +31,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_eulermulti_ec.jl b/examples/tree_1d_dgsem/elixir_eulermulti_ec.jl index 04d937a9a8f..73f8de15d82 100644 --- a/examples/tree_1d_dgsem/elixir_eulermulti_ec.jl +++ b/examples/tree_1d_dgsem/elixir_eulermulti_ec.jl @@ -4,26 +4,23 @@ using Trixi ############################################################################### # semidiscretization of the compressible Euler multicomponent equations -equations = CompressibleEulerMulticomponentEquations1D(gammas = (1.4, 1.4, 1.4), +equations = CompressibleEulerMulticomponentEquations1D(gammas = (1.4, 1.4, 1.4), gas_constants = (0.4, 0.4, 0.4)) - initial_condition = initial_condition_weak_blast_wave volume_flux = flux_ranocha -solver = DGSEM(polydeg=3, surface_flux=flux_ranocha, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_ranocha, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-2.0,) -coordinates_max = ( 2.0,) +coordinates_max = (2.0,) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=5, - n_cells_max=10_000) - + initial_refinement_level = 5, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -34,28 +31,27 @@ summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(Trixi.density,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (Trixi.density,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_eulermulti_es.jl b/examples/tree_1d_dgsem/elixir_eulermulti_es.jl index 7abb3b0d021..7fbec0c0055 100644 --- a/examples/tree_1d_dgsem/elixir_eulermulti_es.jl +++ b/examples/tree_1d_dgsem/elixir_eulermulti_es.jl @@ -4,26 +4,23 @@ using Trixi ############################################################################### # semidiscretization of the compressible Euler multicomponent equations -equations = CompressibleEulerMulticomponentEquations1D(gammas = (1.4, 1.4), +equations = CompressibleEulerMulticomponentEquations1D(gammas = (1.4, 1.4), gas_constants = (0.4, 0.4)) - initial_condition = initial_condition_weak_blast_wave volume_flux = flux_ranocha -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-2.0,) -coordinates_max = ( 2.0,) +coordinates_max = (2.0,) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=5, - n_cells_max=10_000) - + initial_refinement_level = 5, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -34,31 +31,30 @@ summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(Trixi.density,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (Trixi.density,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_restart, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_eulermulti_two_interacting_blast_waves.jl b/examples/tree_1d_dgsem/elixir_eulermulti_two_interacting_blast_waves.jl index 81966194180..c093420cc7c 100644 --- a/examples/tree_1d_dgsem/elixir_eulermulti_two_interacting_blast_waves.jl +++ b/examples/tree_1d_dgsem/elixir_eulermulti_two_interacting_blast_waves.jl @@ -5,8 +5,8 @@ using Trixi ############################################################################### # semidiscretization of the compressible Euler equations -equations = CompressibleEulerMulticomponentEquations1D(gammas = (1.4, 1.4, 1.4), - gas_constants = (0.4, 0.4, 0.4)) +equations = CompressibleEulerMulticomponentEquations1D(gammas = (1.4, 1.4, 1.4), + gas_constants = (0.4, 0.4, 0.4)) """ initial_condition_two_interacting_blast_waves(x, t, equations::CompressibleEulerMulticomponentEquations1D) @@ -16,69 +16,67 @@ A multicomponent two interacting blast wave test taken from The consistent multi-fluid advection method [arXiv: 9807241](https://arxiv.org/pdf/astro-ph/9807241.pdf) """ -function initial_condition_two_interacting_blast_waves(x, t, equations::CompressibleEulerMulticomponentEquations1D) +function initial_condition_two_interacting_blast_waves(x, t, + equations::CompressibleEulerMulticomponentEquations1D) + rho1 = 0.5 * x[1]^2 + rho2 = 0.5 * (sin(20 * x[1]))^2 + rho3 = 1 - rho1 - rho2 - rho1 = 0.5 * x[1]^2 - rho2 = 0.5 * (sin(20 * x[1]))^2 - rho3 = 1 - rho1 - rho2 + prim_rho = SVector{3, real(equations)}(rho1, rho2, rho3) - prim_rho = SVector{3, real(equations)}(rho1, rho2, rho3) + v1 = 0.0 - v1 = 0.0 + if x[1] <= 0.1 + p = 1000 + elseif x[1] < 0.9 + p = 0.01 + else + p = 100 + end - if x[1] <= 0.1 - p = 1000 - elseif x[1] < 0.9 - p = 0.01 - else - p = 100 - end + prim_other = SVector{2, real(equations)}(v1, p) - prim_other = SVector{2, real(equations)}(v1, p) - - return prim2cons(vcat(prim_other, prim_rho), equations) + return prim2cons(vcat(prim_other, prim_rho), equations) end initial_condition = initial_condition_two_interacting_blast_waves -function boundary_condition_two_interacting_blast_waves(u_inner, orientation, direction, x, t, - surface_flux_function, +function boundary_condition_two_interacting_blast_waves(u_inner, orientation, direction, + x, t, surface_flux_function, equations::CompressibleEulerMulticomponentEquations1D) - - u_inner_reflect = SVector(-u_inner[1], u_inner[2], u_inner[3], u_inner[4], u_inner[5]) - # Calculate boundary flux - if iseven(direction) # u_inner is "left" of boundary, u_boundary is "right" of boundary - flux = surface_flux_function(u_inner, u_inner_reflect, orientation, equations) - else # u_boundary is "left" of boundary, u_inner is "right" of boundary - flux = surface_flux_function(u_inner_reflect, u_inner, orientation, equations) - end - - return flux + u_inner_reflect = SVector(-u_inner[1], u_inner[2], u_inner[3], u_inner[4], u_inner[5]) + # Calculate boundary flux + if iseven(direction) # u_inner is "left" of boundary, u_boundary is "right" of boundary + flux = surface_flux_function(u_inner, u_inner_reflect, orientation, equations) + else # u_boundary is "left" of boundary, u_inner is "right" of boundary + flux = surface_flux_function(u_inner_reflect, u_inner, orientation, equations) + end + + return flux end boundary_conditions = boundary_condition_two_interacting_blast_waves surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha +volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) indicator_sc = IndicatorHennemannGassner(equations, basis, alpha_max = 0.8, alpha_min = 0.0, alpha_smooth = true, - variable=pressure) + variable = pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (0.0,) coordinates_max = (1.0,) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=9, - n_cells_max=10_000, - periodicity=false) - - -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, boundary_conditions=boundary_conditions) + initial_refinement_level = 9, + n_cells_max = 10_000, + periodicity = false) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -90,16 +88,16 @@ summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.1) +stepsize_callback = StepsizeCallback(cfl = 0.1) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -109,7 +107,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_hypdiff_harmonic_nonperiodic.jl b/examples/tree_1d_dgsem/elixir_hypdiff_harmonic_nonperiodic.jl index 9a19807ae29..b9173ec9f49 100644 --- a/examples/tree_1d_dgsem/elixir_hypdiff_harmonic_nonperiodic.jl +++ b/examples/tree_1d_dgsem/elixir_hypdiff_harmonic_nonperiodic.jl @@ -5,7 +5,7 @@ using Trixi ############################################################################### # semidiscretization of the hyperbolic diffusion equations -equations = HyperbolicDiffusionEquations1D(nu=1.25) +equations = HyperbolicDiffusionEquations1D(nu = 1.25) """ initial_condition_poisson_nonperiodic(x, t, equations::HyperbolicDiffusionEquations1D) @@ -16,36 +16,36 @@ A non-priodic harmonic function used in combination with !!! note The only harmonic functions in 1D have the form phi(x) = A + Bx """ -function initial_condition_harmonic_nonperiodic(x, t, equations::HyperbolicDiffusionEquations1D) - # elliptic equation: -νΔϕ = f - if t == 0.0 - phi = 5.0 - q1 = 0.0 - else - A = 3 - B = exp(1) - phi = A + B * x[1] - q1 = B - end - return SVector(phi, q1) +function initial_condition_harmonic_nonperiodic(x, t, + equations::HyperbolicDiffusionEquations1D) + # elliptic equation: -νΔϕ = f + if t == 0.0 + phi = 5.0 + q1 = 0.0 + else + A = 3 + B = exp(1) + phi = A + B * x[1] + q1 = B + end + return SVector(phi, q1) end initial_condition = initial_condition_harmonic_nonperiodic boundary_conditions = BoundaryConditionDirichlet(initial_condition) -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = -1.0 -coordinates_max = 2.0 +coordinates_max = 2.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=30_000, - periodicity=false) + initial_refinement_level = 2, + n_cells_max = 30_000, + periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions, - source_terms=source_terms_harmonic) - + boundary_conditions = boundary_conditions, + source_terms = source_terms_harmonic) ############################################################################### # ODE solvers, callbacks etc. @@ -56,30 +56,29 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() resid_tol = 5.0e-12 -steady_state_callback = SteadyStateCallback(abstol=resid_tol, reltol=0.0) +steady_state_callback = SteadyStateCallback(abstol = resid_tol, reltol = 0.0) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.75) +stepsize_callback = StepsizeCallback(cfl = 1.75) callbacks = CallbackSet(summary_callback, steady_state_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation sol = Trixi.solve(ode, Trixi.HypDiffN3Erk3Sstar52(), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_hypdiff_nonperiodic.jl b/examples/tree_1d_dgsem/elixir_hypdiff_nonperiodic.jl index 827d8d25ce7..4da3b33a466 100644 --- a/examples/tree_1d_dgsem/elixir_hypdiff_nonperiodic.jl +++ b/examples/tree_1d_dgsem/elixir_hypdiff_nonperiodic.jl @@ -11,19 +11,18 @@ initial_condition = initial_condition_poisson_nonperiodic boundary_conditions = boundary_condition_poisson_nonperiodic -solver = DGSEM(polydeg=4, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 4, surface_flux = flux_lax_friedrichs) coordinates_min = 0.0 coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=30_000, - periodicity=false) + initial_refinement_level = 3, + n_cells_max = 30_000, + periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions, - source_terms=source_terms_poisson_nonperiodic) - + boundary_conditions = boundary_conditions, + source_terms = source_terms_poisson_nonperiodic) ############################################################################### # ODE solvers, callbacks etc. @@ -34,31 +33,30 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() resid_tol = 5.0e-12 -steady_state_callback = SteadyStateCallback(abstol=resid_tol, reltol=0.0) +steady_state_callback = SteadyStateCallback(abstol = resid_tol, reltol = 0.0) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy, energy_total)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy, energy_total)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, steady_state_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_mhd_alfven_wave.jl b/examples/tree_1d_dgsem/elixir_mhd_alfven_wave.jl index 82bca93c707..1a66ac60b9b 100644 --- a/examples/tree_1d_dgsem/elixir_mhd_alfven_wave.jl +++ b/examples/tree_1d_dgsem/elixir_mhd_alfven_wave.jl @@ -4,25 +4,23 @@ using Trixi ############################################################################### # semidiscretization of the ideal MHD equations -gamma = 5/3 +gamma = 5 / 3 equations = IdealGlmMhdEquations1D(gamma) initial_condition = initial_condition_convergence_test volume_flux = flux_hindenlang_gassner -solver = DGSEM(polydeg=4, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 4, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = 0.0 coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=10_000) - + initial_refinement_level = 2, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -32,32 +30,33 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_errors=(:l2_error_primitive, - :linf_error_primitive), - extra_analysis_integrals=(entropy, energy_total, - energy_kinetic, energy_internal, - energy_magnetic, cross_helicity)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_errors = (:l2_error_primitive, + :linf_error_primitive), + extra_analysis_integrals = (entropy, energy_total, + energy_kinetic, + energy_internal, + energy_magnetic, + cross_helicity)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_mhd_briowu_shock_tube.jl b/examples/tree_1d_dgsem/elixir_mhd_briowu_shock_tube.jl index c5727109d92..4d537508b47 100644 --- a/examples/tree_1d_dgsem/elixir_mhd_briowu_shock_tube.jl +++ b/examples/tree_1d_dgsem/elixir_mhd_briowu_shock_tube.jl @@ -17,46 +17,44 @@ MHD extension of the Sod shock tube. Taken from Section V of the article [DOI: 10.1016/0021-9991(88)90120-9](https://doi.org/10.1016/0021-9991(88)90120-9) """ function initial_condition_briowu_shock_tube(x, t, equations::IdealGlmMhdEquations1D) - # domain must be set to [0, 1], γ = 2, final time = 0.12 - rho = x[1] < 0.5 ? 1.0 : 0.125 - v1 = 0.0 - v2 = 0.0 - v3 = 0.0 - p = x[1] < 0.5 ? 1.0 : 0.1 - B1 = 0.75 - B2 = x[1] < 0.5 ? 1.0 : -1.0 - B3 = 0.0 - return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3), equations) + # domain must be set to [0, 1], γ = 2, final time = 0.12 + rho = x[1] < 0.5 ? 1.0 : 0.125 + v1 = 0.0 + v2 = 0.0 + v3 = 0.0 + p = x[1] < 0.5 ? 1.0 : 0.1 + B1 = 0.75 + B2 = x[1] < 0.5 ? 1.0 : -1.0 + B3 = 0.0 + return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3), equations) end initial_condition = initial_condition_briowu_shock_tube boundary_conditions = BoundaryConditionDirichlet(initial_condition) -surface_flux = flux_hll -volume_flux = flux_derigs_etal +surface_flux = flux_hlle +volume_flux = flux_derigs_etal basis = LobattoLegendreBasis(4) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = 0.0 coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000, - periodicity=false) - + initial_refinement_level = 4, + n_cells_max = 10_000, + periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -67,45 +65,44 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_errors=(:l2_error_primitive, - :linf_error_primitive)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_errors = (:l2_error_primitive, + :linf_error_primitive)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_indicator = IndicatorHennemannGassner(semi, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=4, - max_level=6, max_threshold=0.01) + base_level = 4, + max_level = 6, max_threshold = 0.01) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=0.65) +stepsize_callback = StepsizeCallback(cfl = 0.65) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_restart, save_solution, amr_callback, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_mhd_ec.jl b/examples/tree_1d_dgsem/elixir_mhd_ec.jl index 1f2e77006b1..e5da808f696 100644 --- a/examples/tree_1d_dgsem/elixir_mhd_ec.jl +++ b/examples/tree_1d_dgsem/elixir_mhd_ec.jl @@ -10,19 +10,17 @@ equations = IdealGlmMhdEquations1D(gamma) initial_condition = initial_condition_weak_blast_wave volume_flux = flux_hindenlang_gassner -solver = DGSEM(polydeg=3, surface_flux=flux_hindenlang_gassner, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_hindenlang_gassner, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = 0.0 coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) - + initial_refinement_level = 4, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -32,29 +30,28 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_errors=(:l2_error_primitive, - :linf_error_primitive)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_errors = (:l2_error_primitive, + :linf_error_primitive)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_mhd_ryujones_shock_tube.jl b/examples/tree_1d_dgsem/elixir_mhd_ryujones_shock_tube.jl index 010788d48f5..a7d7689a806 100644 --- a/examples/tree_1d_dgsem/elixir_mhd_ryujones_shock_tube.jl +++ b/examples/tree_1d_dgsem/elixir_mhd_ryujones_shock_tube.jl @@ -4,7 +4,7 @@ using Trixi ############################################################################### # semidiscretization of the ideal MHD equations -gamma = 5/3 +gamma = 5 / 3 equations = IdealGlmMhdEquations1D(gamma) """ @@ -22,48 +22,46 @@ present in the one dimensional MHD equations. It is the second test from Section This paper has a typo in the initial conditions. Their variable `E` should be `p`. """ function initial_condition_ryujones_shock_tube(x, t, equations::IdealGlmMhdEquations1D) - # domain must be set to [0, 1], γ = 5/3, final time = 0.2 - rho = x[1] <= 0.5 ? 1.08 : 1.0 - v1 = x[1] <= 0.5 ? 1.2 : 0.0 - v2 = x[1] <= 0.5 ? 0.01 : 0.0 - v3 = x[1] <= 0.5 ? 0.5 : 0.0 - p = x[1] <= 0.5 ? 0.95 : 1.0 - inv_sqrt4pi = 1.0 / sqrt(4 * pi) - B1 = 2 * inv_sqrt4pi - B2 = x[1] <= 0.5 ? 3.6 * inv_sqrt4pi : 4.0 * inv_sqrt4pi - B3 = B1 - - return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3), equations) + # domain must be set to [0, 1], γ = 5/3, final time = 0.2 + rho = x[1] <= 0.5 ? 1.08 : 1.0 + v1 = x[1] <= 0.5 ? 1.2 : 0.0 + v2 = x[1] <= 0.5 ? 0.01 : 0.0 + v3 = x[1] <= 0.5 ? 0.5 : 0.0 + p = x[1] <= 0.5 ? 0.95 : 1.0 + inv_sqrt4pi = 1.0 / sqrt(4 * pi) + B1 = 2 * inv_sqrt4pi + B2 = x[1] <= 0.5 ? 3.6 * inv_sqrt4pi : 4.0 * inv_sqrt4pi + B3 = B1 + + return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3), equations) end initial_condition = initial_condition_ryujones_shock_tube boundary_conditions = BoundaryConditionDirichlet(initial_condition) -surface_flux = flux_hll -volume_flux = flux_hindenlang_gassner +surface_flux = flux_hlle +volume_flux = flux_hindenlang_gassner basis = LobattoLegendreBasis(3) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=Trixi.density) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = Trixi.density) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = 0.0 coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=7, - n_cells_max=10_000, - periodicity=false) - + initial_refinement_level = 7, + n_cells_max = 10_000, + periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -74,27 +72,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_mhd_shu_osher_shock_tube.jl b/examples/tree_1d_dgsem/elixir_mhd_shu_osher_shock_tube.jl index 8c60b449e90..689537ebdd4 100644 --- a/examples/tree_1d_dgsem/elixir_mhd_shu_osher_shock_tube.jl +++ b/examples/tree_1d_dgsem/elixir_mhd_shu_osher_shock_tube.jl @@ -4,7 +4,7 @@ using Trixi ############################################################################### # semidiscretization of the ideal MHD equations -gamma = 5/3 +gamma = 5 / 3 equations = IdealGlmMhdEquations1D(gamma) """ @@ -17,19 +17,19 @@ Taken from Section 4.1 of [DOI: 10.1016/j.jcp.2016.04.048](https://doi.org/10.1016/j.jcp.2016.04.048) """ function initial_condition_shu_osher_shock_tube(x, t, equations::IdealGlmMhdEquations1D) - # domain must be set to [-5, 5], γ = 5/3, final time = 0.7 - # initial shock location is taken to be at x = -4 - x_0 = -4.0 - rho = x[1] <= x_0 ? 3.5 : 1.0 + 0.2 * sin(5.0 * x[1]) - v1 = x[1] <= x_0 ? 5.8846 : 0.0 - v2 = x[1] <= x_0 ? 1.1198 : 0.0 - v3 = 0.0 - p = x[1] <= x_0 ? 42.0267 : 1.0 - B1 = 1.0 - B2 = x[1] <= x_0 ? 3.6359 : 1.0 - B3 = 0.0 - - return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3), equations) + # domain must be set to [-5, 5], γ = 5/3, final time = 0.7 + # initial shock location is taken to be at x = -4 + x_0 = -4.0 + rho = x[1] <= x_0 ? 3.5 : 1.0 + 0.2 * sin(5.0 * x[1]) + v1 = x[1] <= x_0 ? 5.8846 : 0.0 + v2 = x[1] <= x_0 ? 1.1198 : 0.0 + v3 = 0.0 + p = x[1] <= x_0 ? 42.0267 : 1.0 + B1 = 1.0 + B2 = x[1] <= x_0 ? 3.6359 : 1.0 + B3 = 0.0 + + return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3), equations) end """ @@ -41,50 +41,49 @@ but shock propagates from right to left. !!! note This is useful to exercise some of the components of the HLL flux. """ -function initial_condition_shu_osher_shock_tube_flipped(x, t, equations::IdealGlmMhdEquations1D) - # domain must be set to [-5, 5], γ = 5/3, final time = 0.7 - # initial shock location is taken to be at x = 4 - x_0 = 4.0 - rho = x[1] <= x_0 ? 1.0 + 0.2 * sin(5.0 * x[1]) : 3.5 - v1 = x[1] <= x_0 ? 0.0 : -5.8846 - v2 = x[1] <= x_0 ? 0.0 : -1.1198 - v3 = 0.0 - p = x[1] <= x_0 ? 1.0 : 42.0267 - B1 = 1.0 - B2 = x[1] <= x_0 ? 1.0 : 3.6359 - B3 = 0.0 - - return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3), equations) +function initial_condition_shu_osher_shock_tube_flipped(x, t, + equations::IdealGlmMhdEquations1D) + # domain must be set to [-5, 5], γ = 5/3, final time = 0.7 + # initial shock location is taken to be at x = 4 + x_0 = 4.0 + rho = x[1] <= x_0 ? 1.0 + 0.2 * sin(5.0 * x[1]) : 3.5 + v1 = x[1] <= x_0 ? 0.0 : -5.8846 + v2 = x[1] <= x_0 ? 0.0 : -1.1198 + v3 = 0.0 + p = x[1] <= x_0 ? 1.0 : 42.0267 + B1 = 1.0 + B2 = x[1] <= x_0 ? 1.0 : 3.6359 + B3 = 0.0 + + return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3), equations) end initial_condition = initial_condition_shu_osher_shock_tube boundary_conditions = BoundaryConditionDirichlet(initial_condition) -surface_flux = flux_hll -volume_flux = flux_hindenlang_gassner +surface_flux = flux_hlle +volume_flux = flux_hindenlang_gassner basis = LobattoLegendreBasis(4) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = -5.0 -coordinates_max = 5.0 +coordinates_max = 5.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000, - periodicity=false) - + initial_refinement_level = 4, + n_cells_max = 10_000, + periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -95,42 +94,43 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(energy_kinetic, energy_internal, - energy_magnetic, cross_helicity)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (energy_kinetic, + energy_internal, + energy_magnetic, + cross_helicity)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_indicator = IndicatorHennemannGassner(semi, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=4, - max_level=7, max_threshold=0.01) + base_level = 4, + max_level = 7, max_threshold = 0.01) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, amr_callback, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_mhd_torrilhon_shock_tube.jl b/examples/tree_1d_dgsem/elixir_mhd_torrilhon_shock_tube.jl index 68556764293..3b366c35e0f 100644 --- a/examples/tree_1d_dgsem/elixir_mhd_torrilhon_shock_tube.jl +++ b/examples/tree_1d_dgsem/elixir_mhd_torrilhon_shock_tube.jl @@ -4,7 +4,7 @@ using Trixi ############################################################################### # semidiscretization of the ideal MHD equations -gamma = 5/3 +gamma = 5 / 3 equations = IdealGlmMhdEquations1D(gamma) """ @@ -16,46 +16,44 @@ Torrilhon's shock tube test case for one dimensional ideal MHD equations. [DOI: 10.1017/S0022377803002186](https://doi.org/10.1017/S0022377803002186) """ function initial_condition_torrilhon_shock_tube(x, t, equations::IdealGlmMhdEquations1D) - # domain must be set to [-1, 1.5], γ = 5/3, final time = 0.4 - rho = x[1] <= 0 ? 3.0 : 1.0 - v1 = 0.0 - v2 = 0.0 - v3 = 0.0 - p = x[1] <= 0 ? 3.0 : 1.0 - B1 = 1.5 - B2 = x[1] <= 0 ? 1.0 : cos(1.5) - B3 = x[1] <= 0 ? 0.0 : sin(1.5) - return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3), equations) + # domain must be set to [-1, 1.5], γ = 5/3, final time = 0.4 + rho = x[1] <= 0 ? 3.0 : 1.0 + v1 = 0.0 + v2 = 0.0 + v3 = 0.0 + p = x[1] <= 0 ? 3.0 : 1.0 + B1 = 1.5 + B2 = x[1] <= 0 ? 1.0 : cos(1.5) + B3 = x[1] <= 0 ? 0.0 : sin(1.5) + return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3), equations) end initial_condition = initial_condition_torrilhon_shock_tube boundary_conditions = BoundaryConditionDirichlet(initial_condition) surface_flux = flux_lax_friedrichs -volume_flux = flux_central +volume_flux = flux_central basis = LobattoLegendreBasis(3) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = -1.0 -coordinates_max = 1.5 +coordinates_max = 1.5 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=7, - n_cells_max=10_000, - periodicity=false) - + initial_refinement_level = 7, + n_cells_max = 10_000, + periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -66,29 +64,28 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_errors=(:l2_error_primitive, - :linf_error_primitive)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_errors = (:l2_error_primitive, + :linf_error_primitive)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_mhdmulti_briowu_shock_tube.jl b/examples/tree_1d_dgsem/elixir_mhdmulti_briowu_shock_tube.jl index 376f11d52a2..831fa7afedb 100644 --- a/examples/tree_1d_dgsem/elixir_mhdmulti_briowu_shock_tube.jl +++ b/examples/tree_1d_dgsem/elixir_mhdmulti_briowu_shock_tube.jl @@ -4,8 +4,8 @@ using Trixi ############################################################################### # semidiscretization of the ideal MHD equations -equations = IdealGlmMhdMulticomponentEquations1D(gammas = (2.0, 2.0), - gas_constants = (2.0, 2.0)) +equations = IdealGlmMhdMulticomponentEquations1D(gammas = (2.0, 2.0), + gas_constants = (2.0, 2.0)) """ initial_condition_briowu_shock_tube(x, t, equations::IdealGlmMhdMulticomponentEquations1D) @@ -16,55 +16,62 @@ MHD extension of the Sod shock tube. Taken from Section V of the article An Upwind Differencing Scheme for the Equations of Ideal Magnetohydrodynamics [DOI: 10.1016/0021-9991(88)90120-9](https://doi.org/10.1016/0021-9991(88)90120-9) """ -function initial_condition_briowu_shock_tube(x, t, equations::IdealGlmMhdMulticomponentEquations1D) - # domain must be set to [0, 1], γ = 2, final time = 0.12 - if x[1] < 0.5 - rho = 1.0 - prim_rho = SVector{ncomponents(equations), real(equations)}(2^(i-1) * (1-2)/(1-2^ncomponents(equations)) * rho for i in eachcomponent(equations)) - else - rho = 0.125 - prim_rho = SVector{ncomponents(equations), real(equations)}(2^(i-1) * (1-2)/(1-2^ncomponents(equations)) * rho for i in eachcomponent(equations)) - end - v1 = 0.0 - v2 = 0.0 - v3 = 0.0 - p = x[1] < 0.5 ? 1.0 : 0.1 - B1 = 0.75 - B2 = x[1] < 0.5 ? 1.0 : -1.0 - B3 = 0.0 - - prim_other = SVector(v1, v2, v3, p, B1, B2, B3) - return prim2cons(vcat(prim_other, prim_rho), equations) +function initial_condition_briowu_shock_tube(x, t, + equations::IdealGlmMhdMulticomponentEquations1D) + # domain must be set to [0, 1], γ = 2, final time = 0.12 + if x[1] < 0.5 + rho = 1.0 + prim_rho = SVector{ncomponents(equations), real(equations)}(2^(i - 1) * (1 - 2) / + (1 - + 2^ncomponents(equations)) * + rho + for i in eachcomponent(equations)) + else + rho = 0.125 + prim_rho = SVector{ncomponents(equations), real(equations)}(2^(i - 1) * (1 - 2) / + (1 - + 2^ncomponents(equations)) * + rho + for i in eachcomponent(equations)) + end + v1 = 0.0 + v2 = 0.0 + v3 = 0.0 + p = x[1] < 0.5 ? 1.0 : 0.1 + B1 = 0.75 + B2 = x[1] < 0.5 ? 1.0 : -1.0 + B3 = 0.0 + + prim_other = SVector(v1, v2, v3, p, B1, B2, B3) + return prim2cons(vcat(prim_other, prim_rho), equations) end initial_condition = initial_condition_briowu_shock_tube boundary_conditions = BoundaryConditionDirichlet(initial_condition) surface_flux = flux_lax_friedrichs -volume_flux = flux_hindenlang_gassner +volume_flux = flux_hindenlang_gassner basis = LobattoLegendreBasis(3) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.8, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.8, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = 0.0 coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000, - periodicity=false) - + initial_refinement_level = 4, + n_cells_max = 10_000, + periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -75,45 +82,44 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_errors=(:l2_error_primitive, - :linf_error_primitive)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_errors = (:l2_error_primitive, + :linf_error_primitive)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_indicator = IndicatorHennemannGassner(semi, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=4, - max_level=6, max_threshold=0.01) + base_level = 4, + max_level = 6, max_threshold = 0.01) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_restart, save_solution, amr_callback, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_mhdmulti_convergence.jl b/examples/tree_1d_dgsem/elixir_mhdmulti_convergence.jl index 573bf6bc3e9..a1636c08478 100644 --- a/examples/tree_1d_dgsem/elixir_mhdmulti_convergence.jl +++ b/examples/tree_1d_dgsem/elixir_mhdmulti_convergence.jl @@ -5,25 +5,23 @@ using Trixi ############################################################################### # semidiscretization of the compressible ideal GLM-MHD equations -equations = IdealGlmMhdMulticomponentEquations1D(gammas = (5/3, 5/3, 5/3), - gas_constants = (2.08, 2.08, 2.08)) +equations = IdealGlmMhdMulticomponentEquations1D(gammas = (5 / 3, 5 / 3, 5 / 3), + gas_constants = (2.08, 2.08, 2.08)) initial_condition = initial_condition_convergence_test volume_flux = flux_hindenlang_gassner -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = 0.0 coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=10_000) - + initial_refinement_level = 2, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -33,17 +31,18 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=true) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=10, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 10, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) cfl = 0.5 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -51,11 +50,10 @@ callbacks = CallbackSet(summary_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_mhdmulti_ec.jl b/examples/tree_1d_dgsem/elixir_mhdmulti_ec.jl index 69ea0551bed..71466f3138a 100644 --- a/examples/tree_1d_dgsem/elixir_mhdmulti_ec.jl +++ b/examples/tree_1d_dgsem/elixir_mhdmulti_ec.jl @@ -4,25 +4,23 @@ using Trixi ############################################################################### # semidiscretization of the ideal MHD equations -equations = IdealGlmMhdMulticomponentEquations1D(gammas = (2.0, 2.0, 2.0), +equations = IdealGlmMhdMulticomponentEquations1D(gammas = (2.0, 2.0, 2.0), gas_constants = (2.0, 2.0, 2.0)) initial_condition = initial_condition_weak_blast_wave volume_flux = flux_hindenlang_gassner -solver = DGSEM(polydeg=3, surface_flux=flux_hindenlang_gassner, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_hindenlang_gassner, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = 0.0 coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) - + initial_refinement_level = 4, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -32,26 +30,25 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_mhdmulti_es.jl b/examples/tree_1d_dgsem/elixir_mhdmulti_es.jl index 93cf3e0fdb2..37623e048ed 100644 --- a/examples/tree_1d_dgsem/elixir_mhdmulti_es.jl +++ b/examples/tree_1d_dgsem/elixir_mhdmulti_es.jl @@ -4,25 +4,23 @@ using Trixi ############################################################################### # semidiscretization of the ideal MHD equations -equations = IdealGlmMhdMulticomponentEquations1D(gammas = (2.0, 2.0, 2.0), +equations = IdealGlmMhdMulticomponentEquations1D(gammas = (2.0, 2.0, 2.0), gas_constants = (2.0, 2.0, 2.0)) initial_condition = initial_condition_weak_blast_wave volume_flux = flux_hindenlang_gassner -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = 0.0 coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) - + initial_refinement_level = 4, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -32,29 +30,28 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_errors=(:l2_error_primitive, - :linf_error_primitive)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_errors = (:l2_error_primitive, + :linf_error_primitive)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_navierstokes_convergence_periodic.jl b/examples/tree_1d_dgsem/elixir_navierstokes_convergence_periodic.jl index 3f72d319b0b..33ad0d5271c 100644 --- a/examples/tree_1d_dgsem/elixir_navierstokes_convergence_periodic.jl +++ b/examples/tree_1d_dgsem/elixir_navierstokes_convergence_periodic.jl @@ -10,101 +10,101 @@ prandtl_number() = 0.72 mu() = 6.25e-4 # equivalent to Re = 1600 equations = CompressibleEulerEquations1D(1.4) -equations_parabolic = CompressibleNavierStokesDiffusion1D(equations, mu=mu(), - Prandtl=prandtl_number()) +equations_parabolic = CompressibleNavierStokesDiffusion1D(equations, mu = mu(), + Prandtl = prandtl_number()) # This convergence test setup was originally derived by Andrew Winters (@andrewwinters5000) # (Simplified version of the 2D) function initial_condition_navier_stokes_convergence_test(x, t, equations) - # Amplitude and shift - A = 0.5 - c = 2.0 + # Amplitude and shift + A = 0.5 + c = 2.0 - # convenience values for trig. functions - pi_x = pi * x[1] - pi_t = pi * t + # convenience values for trig. functions + pi_x = pi * x[1] + pi_t = pi * t - rho = c + A * sin(pi_x) * cos(pi_t) - v1 = sin(pi_x) * cos(pi_t) - p = rho^2 + rho = c + A * sin(pi_x) * cos(pi_t) + v1 = sin(pi_x) * cos(pi_t) + p = rho^2 - return prim2cons(SVector(rho, v1, p), equations) + return prim2cons(SVector(rho, v1, p), equations) end initial_condition = initial_condition_navier_stokes_convergence_test @inline function source_terms_navier_stokes_convergence_test(u, x, t, equations) - # we currently need to hardcode these parameters until we fix the "combined equation" issue - # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 - inv_gamma_minus_one = inv(equations.gamma - 1) - Pr = prandtl_number() - mu_ = mu() - - # Same settings as in `initial_condition` - # Amplitude and shift - A = 0.5 - c = 2.0 - - # convenience values for trig. functions - pi_x = pi * x[1] - pi_t = pi * t - - # compute the manufactured solution and all necessary derivatives - rho = c + A * sin(pi_x) * cos(pi_t) - rho_t = -pi * A * sin(pi_x) * sin(pi_t) - rho_x = pi * A * cos(pi_x) * cos(pi_t) - rho_xx = -pi * pi * A * sin(pi_x) * cos(pi_t) - - v1 = sin(pi_x) * cos(pi_t) - v1_t = -pi * sin(pi_x) * sin(pi_t) - v1_x = pi * cos(pi_x) * cos(pi_t) - v1_xx = -pi * pi * sin(pi_x) * cos(pi_t) - - p = rho * rho - p_t = 2.0 * rho * rho_t - p_x = 2.0 * rho * rho_x - p_xx = 2.0 * rho * rho_xx + 2.0 * rho_x * rho_x - - E = p * inv_gamma_minus_one + 0.5 * rho * v1^2 - E_t = p_t * inv_gamma_minus_one + 0.5 * rho_t * v1^2 + rho * v1 * v1_t - E_x = p_x * inv_gamma_minus_one + 0.5 * rho_x * v1^2 + rho * v1 * v1_x - - # Some convenience constants - T_const = equations.gamma * inv_gamma_minus_one / Pr - inv_rho_cubed = 1.0 / (rho^3) - - # compute the source terms - # density equation - du1 = rho_t + rho_x * v1 + rho * v1_x - - # x-momentum equation - du2 = ( rho_t * v1 + rho * v1_t - + p_x + rho_x * v1^2 + 2.0 * rho * v1 * v1_x - # stress tensor from x-direction - - v1_xx * mu_) - - # total energy equation - du3 = ( E_t + v1_x * (E + p) + v1 * (E_x + p_x) - # stress tensor and temperature gradient terms from x-direction - - v1_xx * v1 * mu_ - - v1_x * v1_x * mu_ - - T_const * inv_rho_cubed * ( p_xx * rho * rho - - 2.0 * p_x * rho * rho_x - + 2.0 * p * rho_x * rho_x - - p * rho * rho_xx ) * mu_) - - return SVector(du1, du2, du3) + # we currently need to hardcode these parameters until we fix the "combined equation" issue + # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 + inv_gamma_minus_one = inv(equations.gamma - 1) + Pr = prandtl_number() + mu_ = mu() + + # Same settings as in `initial_condition` + # Amplitude and shift + A = 0.5 + c = 2.0 + + # convenience values for trig. functions + pi_x = pi * x[1] + pi_t = pi * t + + # compute the manufactured solution and all necessary derivatives + rho = c + A * sin(pi_x) * cos(pi_t) + rho_t = -pi * A * sin(pi_x) * sin(pi_t) + rho_x = pi * A * cos(pi_x) * cos(pi_t) + rho_xx = -pi * pi * A * sin(pi_x) * cos(pi_t) + + v1 = sin(pi_x) * cos(pi_t) + v1_t = -pi * sin(pi_x) * sin(pi_t) + v1_x = pi * cos(pi_x) * cos(pi_t) + v1_xx = -pi * pi * sin(pi_x) * cos(pi_t) + + p = rho * rho + p_t = 2.0 * rho * rho_t + p_x = 2.0 * rho * rho_x + p_xx = 2.0 * rho * rho_xx + 2.0 * rho_x * rho_x + + E = p * inv_gamma_minus_one + 0.5 * rho * v1^2 + E_t = p_t * inv_gamma_minus_one + 0.5 * rho_t * v1^2 + rho * v1 * v1_t + E_x = p_x * inv_gamma_minus_one + 0.5 * rho_x * v1^2 + rho * v1 * v1_x + + # Some convenience constants + T_const = equations.gamma * inv_gamma_minus_one / Pr + inv_rho_cubed = 1.0 / (rho^3) + + # compute the source terms + # density equation + du1 = rho_t + rho_x * v1 + rho * v1_x + + # x-momentum equation + du2 = (rho_t * v1 + rho * v1_t + + p_x + rho_x * v1^2 + 2.0 * rho * v1 * v1_x - + # stress tensor from x-direction + v1_xx * mu_) + + # total energy equation + du3 = (E_t + v1_x * (E + p) + v1 * (E_x + p_x) - + # stress tensor and temperature gradient terms from x-direction + v1_xx * v1 * mu_ - + v1_x * v1_x * mu_ - + T_const * inv_rho_cubed * + (p_xx * rho * rho - + 2.0 * p_x * rho * rho_x + + 2.0 * p * rho_x * rho_x - + p * rho * rho_xx) * mu_) + + return SVector(du1, du2, du3) end volume_flux = flux_ranocha -solver = DGSEM(polydeg=3, surface_flux=flux_hllc, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_hllc, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = -1.0 -coordinates_max = 1.0 +coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=100_000) - + initial_refinement_level = 4, + n_cells_max = 100_000) semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver, @@ -119,9 +119,9 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval,) +alive_callback = AliveCallback(analysis_interval = analysis_interval) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -131,6 +131,6 @@ callbacks = CallbackSet(summary_callback, # run the simulation time_int_tol = 1e-9 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) -summary_callback() # print the timer summary \ No newline at end of file +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) +summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_navierstokes_convergence_walls.jl b/examples/tree_1d_dgsem/elixir_navierstokes_convergence_walls.jl index 181a2cb209f..40030d53345 100644 --- a/examples/tree_1d_dgsem/elixir_navierstokes_convergence_walls.jl +++ b/examples/tree_1d_dgsem/elixir_navierstokes_convergence_walls.jl @@ -8,135 +8,145 @@ prandtl_number() = 0.72 mu() = 0.01 equations = CompressibleEulerEquations1D(1.4) -equations_parabolic = CompressibleNavierStokesDiffusion1D(equations, mu=mu(), Prandtl=prandtl_number(), - gradient_variables=GradientVariablesPrimitive()) +equations_parabolic = CompressibleNavierStokesDiffusion1D(equations, mu = mu(), + Prandtl = prandtl_number(), + gradient_variables = GradientVariablesPrimitive()) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralWeakForm()) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralWeakForm()) coordinates_min = -1.0 -coordinates_max = 1.0 +coordinates_max = 1.0 # Create a uniformly refined mesh with periodic boundaries mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - periodicity=false, - n_cells_max=30_000) # set maximum capacity of tree data structure + initial_refinement_level = 3, + periodicity = false, + n_cells_max = 30_000) # set maximum capacity of tree data structure # Note: the initial condition cannot be specialized to `CompressibleNavierStokesDiffusion1D` # since it is called by both the parabolic solver (which passes in `CompressibleNavierStokesDiffusion1D`) # and by the initial condition (which passes in `CompressibleEulerEquations1D`). # This convergence test setup was originally derived by Andrew Winters (@andrewwinters5000) function initial_condition_navier_stokes_convergence_test(x, t, equations) - # Amplitude and shift - A = 0.5 - c = 2.0 + # Amplitude and shift + A = 0.5 + c = 2.0 - # convenience values for trig. functions - pi_x = pi * x[1] - pi_t = pi * t + # convenience values for trig. functions + pi_x = pi * x[1] + pi_t = pi * t - rho = c + A * cos(pi_x) * cos(pi_t) - v1 = log(x[1] + 2.0) * (1.0 - exp(-A * (x[1] - 1.0)) ) * cos(pi_t) - p = rho^2 + rho = c + A * cos(pi_x) * cos(pi_t) + v1 = log(x[1] + 2.0) * (1.0 - exp(-A * (x[1] - 1.0))) * cos(pi_t) + p = rho^2 - return prim2cons(SVector(rho, v1, p), equations) + return prim2cons(SVector(rho, v1, p), equations) end @inline function source_terms_navier_stokes_convergence_test(u, x, t, equations) - x = x[1] - - # TODO: parabolic - # we currently need to hardcode these parameters until we fix the "combined equation" issue - # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 - inv_gamma_minus_one = inv(equations.gamma - 1) - Pr = prandtl_number() - mu_ = mu() - - # Same settings as in `initial_condition` - # Amplitude and shift - A = 0.5 - c = 2.0 - - # convenience values for trig. functions - pi_x = pi * x - pi_t = pi * t - - # compute the manufactured solution and all necessary derivatives - rho = c + A * cos(pi_x) * cos(pi_t) - rho_t = -pi * A * cos(pi_x) * sin(pi_t) - rho_x = -pi * A * sin(pi_x) * cos(pi_t) - rho_xx = -pi * pi * A * cos(pi_x) * cos(pi_t) - - v1 = log(x + 2.0) * (1.0 - exp(-A * (x - 1.0))) * cos(pi_t) - v1_t = -pi * log(x + 2.0) * (1.0 - exp(-A * (x - 1.0))) * sin(pi_t) - v1_x = (A * log(x + 2.0) * exp(-A * (x - 1.0)) + (1.0 - exp(-A * (x - 1.0))) / (x + 2.0)) * cos(pi_t) - v1_xx = (( 2.0 * A * exp(-A * (x - 1.0)) / (x + 2.0) - - A * A * log(x + 2.0) * exp(-A * (x - 1.0)) - - (1.0 - exp(-A * (x - 1.0))) / ((x + 2.0) * (x + 2.0))) * cos(pi_t)) - - p = rho * rho - p_t = 2.0 * rho * rho_t - p_x = 2.0 * rho * rho_x - p_xx = 2.0 * rho * rho_xx + 2.0 * rho_x * rho_x - - # Note this simplifies slightly because the ansatz assumes that v1 = v2 - E = p * inv_gamma_minus_one + 0.5 * rho * v1^2 - E_t = p_t * inv_gamma_minus_one + 0.5 * rho_t * v1^2 + rho * v1 * v1_t - E_x = p_x * inv_gamma_minus_one + 0.5 * rho_x * v1^2 + rho * v1 * v1_x - - # Some convenience constants - T_const = equations.gamma * inv_gamma_minus_one / Pr - inv_rho_cubed = 1.0 / (rho^3) - - # compute the source terms - # density equation - du1 = rho_t + rho_x * v1 + rho * v1_x - - # y-momentum equation - du2 = ( rho_t * v1 + rho * v1_t - + p_x + rho_x * v1^2 + 2.0 * rho * v1 * v1_x - # stress tensor from y-direction - - v1_xx * mu_) - - # total energy equation - du3 = ( E_t + v1_x * (E + p) + v1 * (E_x + p_x) - # stress tensor and temperature gradient terms from x-direction - - v1_xx * v1 * mu_ - - v1_x * v1_x * mu_ - - T_const * inv_rho_cubed * ( p_xx * rho * rho - - 2.0 * p_x * rho * rho_x - + 2.0 * p * rho_x * rho_x - - p * rho * rho_xx ) * mu_ ) - - return SVector(du1, du2, du3) + x = x[1] + + # TODO: parabolic + # we currently need to hardcode these parameters until we fix the "combined equation" issue + # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 + inv_gamma_minus_one = inv(equations.gamma - 1) + Pr = prandtl_number() + mu_ = mu() + + # Same settings as in `initial_condition` + # Amplitude and shift + A = 0.5 + c = 2.0 + + # convenience values for trig. functions + pi_x = pi * x + pi_t = pi * t + + # compute the manufactured solution and all necessary derivatives + rho = c + A * cos(pi_x) * cos(pi_t) + rho_t = -pi * A * cos(pi_x) * sin(pi_t) + rho_x = -pi * A * sin(pi_x) * cos(pi_t) + rho_xx = -pi * pi * A * cos(pi_x) * cos(pi_t) + + v1 = log(x + 2.0) * (1.0 - exp(-A * (x - 1.0))) * cos(pi_t) + v1_t = -pi * log(x + 2.0) * (1.0 - exp(-A * (x - 1.0))) * sin(pi_t) + v1_x = (A * log(x + 2.0) * exp(-A * (x - 1.0)) + + (1.0 - exp(-A * (x - 1.0))) / (x + 2.0)) * cos(pi_t) + v1_xx = ((2.0 * A * exp(-A * (x - 1.0)) / (x + 2.0) - + A * A * log(x + 2.0) * exp(-A * (x - 1.0)) - + (1.0 - exp(-A * (x - 1.0))) / ((x + 2.0) * (x + 2.0))) * cos(pi_t)) + + p = rho * rho + p_t = 2.0 * rho * rho_t + p_x = 2.0 * rho * rho_x + p_xx = 2.0 * rho * rho_xx + 2.0 * rho_x * rho_x + + # Note this simplifies slightly because the ansatz assumes that v1 = v2 + E = p * inv_gamma_minus_one + 0.5 * rho * v1^2 + E_t = p_t * inv_gamma_minus_one + 0.5 * rho_t * v1^2 + rho * v1 * v1_t + E_x = p_x * inv_gamma_minus_one + 0.5 * rho_x * v1^2 + rho * v1 * v1_x + + # Some convenience constants + T_const = equations.gamma * inv_gamma_minus_one / Pr + inv_rho_cubed = 1.0 / (rho^3) + + # compute the source terms + # density equation + du1 = rho_t + rho_x * v1 + rho * v1_x + + # y-momentum equation + du2 = (rho_t * v1 + rho * v1_t + + p_x + rho_x * v1^2 + 2.0 * rho * v1 * v1_x - + # stress tensor from y-direction + v1_xx * mu_) + + # total energy equation + du3 = (E_t + v1_x * (E + p) + v1 * (E_x + p_x) - + # stress tensor and temperature gradient terms from x-direction + v1_xx * v1 * mu_ - + v1_x * v1_x * mu_ - + T_const * inv_rho_cubed * + (p_xx * rho * rho - + 2.0 * p_x * rho * rho_x + + 2.0 * p * rho_x * rho_x - + p * rho * rho_xx) * mu_) + + return SVector(du1, du2, du3) end initial_condition = initial_condition_navier_stokes_convergence_test # BC types -velocity_bc_left_right = NoSlip((x, t, equations) -> initial_condition_navier_stokes_convergence_test(x, t, equations)[2]) - -heat_bc_left = Isothermal((x, t, equations) -> - Trixi.temperature(initial_condition_navier_stokes_convergence_test(x, t, equations), - equations_parabolic)) +velocity_bc_left_right = NoSlip((x, t, equations) -> initial_condition_navier_stokes_convergence_test(x, + t, + equations)[2]) + +heat_bc_left = Isothermal((x, t, equations) -> Trixi.temperature(initial_condition_navier_stokes_convergence_test(x, + t, + equations), + equations_parabolic)) heat_bc_right = Adiabatic((x, t, equations) -> 0.0) -boundary_condition_left = BoundaryConditionNavierStokesWall(velocity_bc_left_right, heat_bc_left) -boundary_condition_right = BoundaryConditionNavierStokesWall(velocity_bc_left_right, heat_bc_right) +boundary_condition_left = BoundaryConditionNavierStokesWall(velocity_bc_left_right, + heat_bc_left) +boundary_condition_right = BoundaryConditionNavierStokesWall(velocity_bc_left_right, + heat_bc_right) # define inviscid boundary conditions boundary_conditions = (; x_neg = boundary_condition_slip_wall, - x_pos = boundary_condition_slip_wall) + x_pos = boundary_condition_slip_wall) # define viscous boundary conditions boundary_conditions_parabolic = (; x_neg = boundary_condition_left, - x_pos = boundary_condition_right) + x_pos = boundary_condition_right) -semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver; - boundary_conditions=(boundary_conditions, boundary_conditions_parabolic), - source_terms=source_terms_navier_stokes_convergence_test) +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, solver; + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic), + source_terms = source_terms_navier_stokes_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -146,15 +156,15 @@ tspan = (0.0, 1.0) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) ############################################################################### # run the simulation time_int_tol = 1e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, dt = 1e-5, - ode_default_options()..., callback=callbacks) -summary_callback() # print the timer summary \ No newline at end of file +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, dt = 1e-5, + ode_default_options()..., callback = callbacks) +summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_navierstokes_convergence_walls_amr.jl b/examples/tree_1d_dgsem/elixir_navierstokes_convergence_walls_amr.jl new file mode 100644 index 00000000000..e833155a68e --- /dev/null +++ b/examples/tree_1d_dgsem/elixir_navierstokes_convergence_walls_amr.jl @@ -0,0 +1,182 @@ +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the ideal compressible Navier-Stokes equations + +prandtl_number() = 0.72 +mu() = 0.01 + +equations = CompressibleEulerEquations1D(1.4) +equations_parabolic = CompressibleNavierStokesDiffusion1D(equations, mu = mu(), + Prandtl = prandtl_number(), + gradient_variables = GradientVariablesEntropy()) + +# Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralWeakForm()) + +coordinates_min = -1.0 +coordinates_max = 1.0 + +# Create a uniformly refined mesh with periodic boundaries +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level = 3, + periodicity = false, + n_cells_max = 30_000) # set maximum capacity of tree data structure + +# Note: the initial condition cannot be specialized to `CompressibleNavierStokesDiffusion1D` +# since it is called by both the parabolic solver (which passes in `CompressibleNavierStokesDiffusion1D`) +# and by the initial condition (which passes in `CompressibleEulerEquations1D`). +# This convergence test setup was originally derived by Andrew Winters (@andrewwinters5000) +function initial_condition_navier_stokes_convergence_test(x, t, equations) + # Amplitude and shift + A = 0.5 + c = 2.0 + + # convenience values for trig. functions + pi_x = pi * x[1] + pi_t = pi * t + + rho = c + A * cos(pi_x) * cos(pi_t) + v1 = log(x[1] + 2.0) * (1.0 - exp(-A * (x[1] - 1.0))) * cos(pi_t) + p = rho^2 + + return prim2cons(SVector(rho, v1, p), equations) +end + +@inline function source_terms_navier_stokes_convergence_test(u, x, t, equations) + x = x[1] + + # TODO: parabolic + # we currently need to hardcode these parameters until we fix the "combined equation" issue + # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 + inv_gamma_minus_one = inv(equations.gamma - 1) + Pr = prandtl_number() + mu_ = mu() + + # Same settings as in `initial_condition` + # Amplitude and shift + A = 0.5 + c = 2.0 + + # convenience values for trig. functions + pi_x = pi * x + pi_t = pi * t + + # compute the manufactured solution and all necessary derivatives + rho = c + A * cos(pi_x) * cos(pi_t) + rho_t = -pi * A * cos(pi_x) * sin(pi_t) + rho_x = -pi * A * sin(pi_x) * cos(pi_t) + rho_xx = -pi * pi * A * cos(pi_x) * cos(pi_t) + + v1 = log(x + 2.0) * (1.0 - exp(-A * (x - 1.0))) * cos(pi_t) + v1_t = -pi * log(x + 2.0) * (1.0 - exp(-A * (x - 1.0))) * sin(pi_t) + v1_x = (A * log(x + 2.0) * exp(-A * (x - 1.0)) + + (1.0 - exp(-A * (x - 1.0))) / (x + 2.0)) * cos(pi_t) + v1_xx = ((2.0 * A * exp(-A * (x - 1.0)) / (x + 2.0) - + A * A * log(x + 2.0) * exp(-A * (x - 1.0)) - + (1.0 - exp(-A * (x - 1.0))) / ((x + 2.0) * (x + 2.0))) * cos(pi_t)) + + p = rho * rho + p_t = 2.0 * rho * rho_t + p_x = 2.0 * rho * rho_x + p_xx = 2.0 * rho * rho_xx + 2.0 * rho_x * rho_x + + # Note this simplifies slightly because the ansatz assumes that v1 = v2 + E = p * inv_gamma_minus_one + 0.5 * rho * v1^2 + E_t = p_t * inv_gamma_minus_one + 0.5 * rho_t * v1^2 + rho * v1 * v1_t + E_x = p_x * inv_gamma_minus_one + 0.5 * rho_x * v1^2 + rho * v1 * v1_x + + # Some convenience constants + T_const = equations.gamma * inv_gamma_minus_one / Pr + inv_rho_cubed = 1.0 / (rho^3) + + # compute the source terms + # density equation + du1 = rho_t + rho_x * v1 + rho * v1_x + + # y-momentum equation + du2 = (rho_t * v1 + rho * v1_t + + p_x + rho_x * v1^2 + 2.0 * rho * v1 * v1_x - + # stress tensor from y-direction + v1_xx * mu_) + + # total energy equation + du3 = (E_t + v1_x * (E + p) + v1 * (E_x + p_x) - + # stress tensor and temperature gradient terms from x-direction + v1_xx * v1 * mu_ - + v1_x * v1_x * mu_ - + T_const * inv_rho_cubed * + (p_xx * rho * rho - + 2.0 * p_x * rho * rho_x + + 2.0 * p * rho_x * rho_x - + p * rho * rho_xx) * mu_) + + return SVector(du1, du2, du3) +end + +initial_condition = initial_condition_navier_stokes_convergence_test + +# BC types +velocity_bc_left_right = NoSlip((x, t, equations) -> initial_condition_navier_stokes_convergence_test(x, + t, + equations)[2]) + +heat_bc_left = Isothermal((x, t, equations) -> Trixi.temperature(initial_condition_navier_stokes_convergence_test(x, + t, + equations), + equations_parabolic)) +heat_bc_right = Adiabatic((x, t, equations) -> 0.0) + +boundary_condition_left = BoundaryConditionNavierStokesWall(velocity_bc_left_right, + heat_bc_left) +boundary_condition_right = BoundaryConditionNavierStokesWall(velocity_bc_left_right, + heat_bc_right) + +# define inviscid boundary conditions +boundary_conditions = (; x_neg = boundary_condition_slip_wall, + x_pos = boundary_condition_slip_wall) + +# define viscous boundary conditions +boundary_conditions_parabolic = (; x_neg = boundary_condition_left, + x_pos = boundary_condition_right) + +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, solver; + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic), + source_terms = source_terms_navier_stokes_convergence_test) + +############################################################################### +# ODE solvers, callbacks etc. + +# Create ODE problem with time span `tspan` +tspan = (0.0, 1.0) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() +alive_callback = AliveCallback(alive_interval = 10) +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + +amr_controller = ControllerThreeLevel(semi, + IndicatorLöhner(semi, variable = Trixi.density), + base_level = 3, + med_level = 4, med_threshold = 0.005, + max_level = 5, max_threshold = 0.01) + +amr_callback = AMRCallback(semi, amr_controller, + interval = 5, + adapt_initial_condition = true) + +# Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver +callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, amr_callback) + +############################################################################### +# run the simulation + +time_int_tol = 1e-8 +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, dt = 1e-5, + ode_default_options()..., callback = callbacks) +summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_shallow_water_quasi_1d_source_terms.jl b/examples/tree_1d_dgsem/elixir_shallow_water_quasi_1d_source_terms.jl new file mode 100644 index 00000000000..72747c669e2 --- /dev/null +++ b/examples/tree_1d_dgsem/elixir_shallow_water_quasi_1d_source_terms.jl @@ -0,0 +1,60 @@ +using OrdinaryDiffEq +using Trixi + +############################################################################### +# Semidiscretization of the quasi 1d shallow water equations +# See Chan et al. https://doi.org/10.48550/arXiv.2307.12089 for details + +equations = ShallowWaterEquationsQuasi1D(gravity_constant = 9.81) + +initial_condition = initial_condition_convergence_test + +############################################################################### +# Get the DG approximation space + +volume_flux = (flux_chan_etal, flux_nonconservative_chan_etal) +surface_flux = (FluxPlusDissipation(flux_chan_etal, DissipationLocalLaxFriedrichs()), + flux_nonconservative_chan_etal) +solver = DGSEM(polydeg = 3, surface_flux = surface_flux, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) + +############################################################################### +# Get the TreeMesh and setup a periodic mesh + +coordinates_min = 0.0 +coordinates_max = sqrt(2.0) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level = 3, + n_cells_max = 10_000, + periodicity = true) + +# create the semi discretization object +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + source_terms = source_terms_convergence_test) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 1.0) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 500 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 200, + save_initial_solution = true, + save_final_solution = true) + +callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) + +############################################################################### +# run the simulation + +# use a Runge-Kutta method with automatic (error based) time step size control +sol = solve(ode, RDPK3SpFSAL49(); abstol = 1.0e-8, reltol = 1.0e-8, + ode_default_options()..., callback = callbacks); +summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_shallowwater_beach.jl b/examples/tree_1d_dgsem/elixir_shallowwater_beach.jl index 1288bc5e66a..378079ca334 100644 --- a/examples/tree_1d_dgsem/elixir_shallowwater_beach.jl +++ b/examples/tree_1d_dgsem/elixir_shallowwater_beach.jl @@ -7,7 +7,7 @@ using Trixi # # TODO: TrixiShallowWater: wet/dry example elixir -equations = ShallowWaterEquations1D(gravity_constant=9.812) +equations = ShallowWaterEquations1D(gravity_constant = 9.812) """ initial_condition_beach(x, t, equations:: ShallowWaterEquations1D) @@ -22,33 +22,33 @@ found in section 5.2 of the paper: Finite volume evolution Galerkin methods for the shallow water equations with dry beds\n [DOI: 10.4208/cicp.220210.020710a](https://dx.doi.org/10.4208/cicp.220210.020710a) """ -function initial_condition_beach(x, t, equations:: ShallowWaterEquations1D) - D = 1 - delta = 0.02 - gamma = sqrt((3 * delta) / (4 * D)) - x_a = sqrt((4 * D) / (3 * delta)) * acosh(sqrt(20)) - - f = D + 40 * delta * sech(gamma * (8 * x[1] - x_a))^2 - - # steep curved beach - b = 0.01 + 99 / 409600 * 4^x[1] - - if x[1] >= 6 - H = b - v = 0.0 - else - H = f - v = sqrt(equations.gravity / D) * H - end - - # It is mandatory to shift the water level at dry areas to make sure the water height h - # stays positive. The system would not be stable for h set to a hard 0 due to division by h in - # the computation of velocity, e.g., (h v) / h. Therefore, a small dry state threshold - # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above - # for the ShallowWaterEquations and added to the initial condition if h = 0. - # This default value can be changed within the constructor call depending on the simulation setup. - H = max(H, b + equations.threshold_limiter) - return prim2cons(SVector(H, v, b), equations) +function initial_condition_beach(x, t, equations::ShallowWaterEquations1D) + D = 1 + delta = 0.02 + gamma = sqrt((3 * delta) / (4 * D)) + x_a = sqrt((4 * D) / (3 * delta)) * acosh(sqrt(20)) + + f = D + 40 * delta * sech(gamma * (8 * x[1] - x_a))^2 + + # steep curved beach + b = 0.01 + 99 / 409600 * 4^x[1] + + if x[1] >= 6 + H = b + v = 0.0 + else + H = f + v = sqrt(equations.gravity / D) * H + end + + # It is mandatory to shift the water level at dry areas to make sure the water height h + # stays positive. The system would not be stable for h set to a hard 0 due to division by h in + # the computation of velocity, e.g., (h v) / h. Therefore, a small dry state threshold + # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above + # for the ShallowWaterEquations and added to the initial condition if h = 0. + # This default value can be changed within the constructor call depending on the simulation setup. + H = max(H, b + equations.threshold_limiter) + return prim2cons(SVector(H, v, b), equations) end initial_condition = initial_condition_beach @@ -58,19 +58,20 @@ boundary_condition = boundary_condition_slip_wall # Get the DG approximation space volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -surface_flux = (FluxHydrostaticReconstruction(flux_hll_chen_noelle, hydrostatic_reconstruction_chen_noelle), +surface_flux = (FluxHydrostaticReconstruction(flux_hll_chen_noelle, + hydrostatic_reconstruction_chen_noelle), flux_nonconservative_chen_noelle) basis = LobattoLegendreBasis(3) indicator_sc = IndicatorHennemannGassnerShallowWater(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=waterheight_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = waterheight_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) @@ -81,13 +82,13 @@ coordinates_min = 0.0 coordinates_max = 8.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=7, - n_cells_max=10_000, - periodicity=false) + initial_refinement_level = 7, + n_cells_max = 10_000, + periodicity = false) # create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_condition) + boundary_conditions = boundary_condition) ############################################################################### # ODE solvers, callbacks etc. @@ -98,24 +99,25 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=false, - extra_analysis_integrals=(energy_kinetic, - energy_internal)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = false, + extra_analysis_integrals = (energy_kinetic, + energy_internal)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(dt=0.5, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(dt = 0.5, + save_initial_solution = true, + save_final_solution = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) -stage_limiter! = PositivityPreservingLimiterShallowWater(variables=(Trixi.waterheight,)) +stage_limiter! = PositivityPreservingLimiterShallowWater(variables = (Trixi.waterheight,)) ############################################################################### # run the simulation sol = solve(ode, SSPRK43(stage_limiter!); - ode_default_options()..., callback=callbacks); + ode_default_options()..., callback = callbacks); -summary_callback() # print the timer summary \ No newline at end of file +summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_shallowwater_ec.jl b/examples/tree_1d_dgsem/elixir_shallowwater_ec.jl index 1469afec1ca..a3df37fb966 100644 --- a/examples/tree_1d_dgsem/elixir_shallowwater_ec.jl +++ b/examples/tree_1d_dgsem/elixir_shallowwater_ec.jl @@ -6,7 +6,7 @@ using Trixi # Semidiscretization of the shallow water equations with a discontinuous # bottom topography function -equations = ShallowWaterEquations1D(gravity_constant=9.81) +equations = ShallowWaterEquations1D(gravity_constant = 9.81) # Initial condition with a truly discontinuous water height, velocity, and bottom # topography function as an academic testcase for entropy conservation. @@ -16,23 +16,23 @@ equations = ShallowWaterEquations1D(gravity_constant=9.81) # refinement level is changed the initial condition below may need changed as well to # ensure that the discontinuities lie on an element interface. function initial_condition_ec_discontinuous_bottom(x, t, equations::ShallowWaterEquations1D) - # Set the background values - H = 4.25 - v = 0.0 - b = sin(x[1]) # arbitrary continuous function - - # Setup the discontinuous water height and velocity - if x[1] >= 0.125 && x[1] <= 0.25 - H = 5.0 - v = 0.1882 - end - - # Setup a discontinuous bottom topography - if x[1] >= -0.25 && x[1] <= -0.125 - b = 2.0 + 0.5 * sin(2.0 * pi * x[1]) - end - - return prim2cons(SVector(H, v, b), equations) + # Set the background values + H = 4.25 + v = 0.0 + b = sin(x[1]) # arbitrary continuous function + + # Setup the discontinuous water height and velocity + if x[1] >= 0.125 && x[1] <= 0.25 + H = 5.0 + v = 0.1882 + end + + # Setup a discontinuous bottom topography + if x[1] >= -0.25 && x[1] <= -0.125 + b = 2.0 + 0.5 * sin(2.0 * pi * x[1]) + end + + return prim2cons(SVector(H, v, b), equations) end initial_condition = initial_condition_ec_discontinuous_bottom @@ -41,8 +41,9 @@ initial_condition = initial_condition_ec_discontinuous_bottom # Get the DG approximation space volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -solver = DGSEM(polydeg=4, surface_flux=(flux_fjordholm_etal, flux_nonconservative_fjordholm_etal), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 4, + surface_flux = (flux_fjordholm_etal, flux_nonconservative_fjordholm_etal), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### # Get the TreeMesh and setup a periodic mesh @@ -50,8 +51,8 @@ solver = DGSEM(polydeg=4, surface_flux=(flux_fjordholm_etal, flux_nonconservativ coordinates_min = -1.0 coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) + initial_refinement_level = 4, + n_cells_max = 10_000) # Create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -68,15 +69,15 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=3.0) +stepsize_callback = StepsizeCallback(cfl = 3.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) @@ -84,7 +85,7 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_shallowwater_parabolic_bowl.jl b/examples/tree_1d_dgsem/elixir_shallowwater_parabolic_bowl.jl index 916bba76ece..a586562af7e 100644 --- a/examples/tree_1d_dgsem/elixir_shallowwater_parabolic_bowl.jl +++ b/examples/tree_1d_dgsem/elixir_shallowwater_parabolic_bowl.jl @@ -7,7 +7,7 @@ using Trixi # # TODO: TrixiShallowWater: wet/dry example elixir -equations = ShallowWaterEquations1D(gravity_constant=9.81) +equations = ShallowWaterEquations1D(gravity_constant = 9.81) """ initial_condition_parabolic_bowl(x, t, equations:: ShallowWaterEquations1D) @@ -28,26 +28,26 @@ The particular setup below is taken from Section 6.2 of curvilinear meshes with wet/dry fronts accelerated by GPUs [DOI: 10.1016/j.jcp.2018.08.038](https://doi.org/10.1016/j.jcp.2018.08.038). """ -function initial_condition_parabolic_bowl(x, t, equations:: ShallowWaterEquations1D) - a = 1 - h_0 = 0.1 - sigma = 0.5 - ω = sqrt(2 * equations.gravity * h_0) / a - - v = -sigma * ω * sin(ω * t) - - b = h_0 * x[1]^2 / a^2 - - H = sigma * h_0 / a^2 * (2 * x[1] * cos(ω * t) - sigma) + h_0 - - # It is mandatory to shift the water level at dry areas to make sure the water height h - # stays positive. The system would not be stable for h set to a hard 0 due to division by h in - # the computation of velocity, e.g., (h v) / h. Therefore, a small dry state threshold - # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above - # for the ShallowWaterEquations and added to the initial condition if h = 0. - # This default value can be changed within the constructor call depending on the simulation setup. - H = max(H, b + equations.threshold_limiter) - return prim2cons(SVector(H, v, b), equations) +function initial_condition_parabolic_bowl(x, t, equations::ShallowWaterEquations1D) + a = 1 + h_0 = 0.1 + sigma = 0.5 + ω = sqrt(2 * equations.gravity * h_0) / a + + v = -sigma * ω * sin(ω * t) + + b = h_0 * x[1]^2 / a^2 + + H = sigma * h_0 / a^2 * (2 * x[1] * cos(ω * t) - sigma) + h_0 + + # It is mandatory to shift the water level at dry areas to make sure the water height h + # stays positive. The system would not be stable for h set to a hard 0 due to division by h in + # the computation of velocity, e.g., (h v) / h. Therefore, a small dry state threshold + # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above + # for the ShallowWaterEquations and added to the initial condition if h = 0. + # This default value can be changed within the constructor call depending on the simulation setup. + H = max(H, b + equations.threshold_limiter) + return prim2cons(SVector(H, v, b), equations) end initial_condition = initial_condition_parabolic_bowl @@ -56,19 +56,20 @@ initial_condition = initial_condition_parabolic_bowl # Get the DG approximation space volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -surface_flux = (FluxHydrostaticReconstruction(flux_hll_chen_noelle, hydrostatic_reconstruction_chen_noelle), +surface_flux = (FluxHydrostaticReconstruction(flux_hll_chen_noelle, + hydrostatic_reconstruction_chen_noelle), flux_nonconservative_chen_noelle) basis = LobattoLegendreBasis(5) indicator_sc = IndicatorHennemannGassnerShallowWater(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=waterheight_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = waterheight_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) @@ -79,8 +80,8 @@ coordinates_min = -2.0 coordinates_max = 2.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=10_000) + initial_refinement_level = 6, + n_cells_max = 10_000) # create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -94,24 +95,25 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=false, - extra_analysis_integrals=(energy_kinetic, - energy_internal)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = false, + extra_analysis_integrals = (energy_kinetic, + energy_internal)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) -stage_limiter! = PositivityPreservingLimiterShallowWater(variables=(Trixi.waterheight,)) +stage_limiter! = PositivityPreservingLimiterShallowWater(variables = (Trixi.waterheight,)) ############################################################################### # run the simulation sol = solve(ode, SSPRK43(stage_limiter!); - ode_default_options()..., callback=callbacks); + ode_default_options()..., callback = callbacks); -summary_callback() # print the timer summary \ No newline at end of file +summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_shallowwater_quasi_1d_discontinuous.jl b/examples/tree_1d_dgsem/elixir_shallowwater_quasi_1d_discontinuous.jl new file mode 100644 index 00000000000..76c04759389 --- /dev/null +++ b/examples/tree_1d_dgsem/elixir_shallowwater_quasi_1d_discontinuous.jl @@ -0,0 +1,73 @@ +using OrdinaryDiffEq +using Trixi + +############################################################################### +# Semidiscretization of the quasi 1d shallow water equations +# See Chan et al. https://doi.org/10.48550/arXiv.2307.12089 for details + +equations = ShallowWaterEquationsQuasi1D(gravity_constant = 9.81) + +function initial_condition_discontinuity(x, t, equations::ShallowWaterEquationsQuasi1D) + H = 2 + 0.1 * exp(-25 * x[1]^2) + v = 0.0 + + if x[1] > 0 + b = 0.1 + a = 1.0 + else + b = 0.0 + a = 1.1 + end + + return prim2cons(SVector(H, v, b, a), equations) +end + +initial_condition = initial_condition_discontinuity + +############################################################################### +# Get the DG approximation space + +volume_flux = (flux_chan_etal, flux_nonconservative_chan_etal) +surface_flux = (flux_lax_friedrichs, flux_nonconservative_chan_etal) +solver = DGSEM(polydeg = 3, surface_flux = surface_flux, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) + +############################################################################### +# Get the TreeMesh and setup a periodic mesh + +coordinates_min = -0.5 +coordinates_max = 0.5 +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level = 3, + n_cells_max = 10_000, + periodicity = true) + +# create the semi discretization object +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 0.25) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 500 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 200, + save_initial_solution = true, + save_final_solution = true) + +callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) + +############################################################################### +# run the simulation + +# use a Runge-Kutta method with automatic (error based) time step size control +sol = solve(ode, RDPK3SpFSAL49(); abstol = 1.0e-8, reltol = 1.0e-8, + ode_default_options()..., callback = callbacks); +summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_shallowwater_quasi_1d_well_balanced.jl b/examples/tree_1d_dgsem/elixir_shallowwater_quasi_1d_well_balanced.jl new file mode 100644 index 00000000000..d9f1a52b500 --- /dev/null +++ b/examples/tree_1d_dgsem/elixir_shallowwater_quasi_1d_well_balanced.jl @@ -0,0 +1,84 @@ +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the shallow water equations with a discontinuous +# bottom topography function and channel width function + +equations = ShallowWaterEquationsQuasi1D(gravity_constant = 9.81, H0 = 2.0) + +# Setup a truly discontinuous bottom topography function and channel width for +# this academic testcase of well-balancedness. The errors from the analysis +# callback are not important but the error for this lake-at-rest test case +# `∑|H0-(h+b)|` should be around machine roundoff. +# Works as intended for TreeMesh1D with `initial_refinement_level=3`. If the mesh +# refinement level is changed the initial condition below may need changed as well to +# ensure that the discontinuities lie on an element interface. +function initial_condition_discontinuous_well_balancedness(x, t, + equations::ShallowWaterEquationsQuasi1D) + H = equations.H0 + v = 0.0 + + # for a periodic domain, this choice of `b` and `a` mimic + # discontinuity across the periodic boundary. + b = 0.5 * (x[1] + 1) + a = 2 + x[1] + + return prim2cons(SVector(H, v, b, a), equations) +end + +initial_condition = initial_condition_discontinuous_well_balancedness + +############################################################################### +# Get the DG approximation space + +volume_flux = (flux_chan_etal, flux_nonconservative_chan_etal) +surface_flux = volume_flux +solver = DGSEM(polydeg = 4, surface_flux = surface_flux, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) + +############################################################################### +# Get the TreeMesh and setup a periodic mesh + +coordinates_min = -1.0 +coordinates_max = 1.0 +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level = 3, + n_cells_max = 10_000) + +# Create the semi discretization object +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + +############################################################################### +# ODE solver + +tspan = (0.0, 100.0) +ode = semidiscretize(semi, tspan) + +############################################################################### +# Callbacks + +summary_callback = SummaryCallback() + +analysis_interval = 1000 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (lake_at_rest_error,)) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true) + +stepsize_callback = StepsizeCallback(cfl = 3.0) + +callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, + stepsize_callback) + +############################################################################### +# run the simulation + +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); +summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_shallowwater_shock_capturing.jl b/examples/tree_1d_dgsem/elixir_shallowwater_shock_capturing.jl index 62346d7b5ab..511f33d1101 100644 --- a/examples/tree_1d_dgsem/elixir_shallowwater_shock_capturing.jl +++ b/examples/tree_1d_dgsem/elixir_shallowwater_shock_capturing.jl @@ -5,36 +5,37 @@ using Trixi ############################################################################### # Semidiscretization of the shallow water equations -equations = ShallowWaterEquations1D(gravity_constant=9.812, H0=1.75) +equations = ShallowWaterEquations1D(gravity_constant = 9.812, H0 = 1.75) # Initial condition with a truly discontinuous velocity and bottom topography. # Works as intended for TreeMesh1D with `initial_refinement_level=3`. If the mesh # refinement level is changed the initial condition below may need changed as well to # ensure that the discontinuities lie on an element interface. -function initial_condition_stone_throw_discontinuous_bottom(x, t, equations::ShallowWaterEquations1D) +function initial_condition_stone_throw_discontinuous_bottom(x, t, + equations::ShallowWaterEquations1D) - # Calculate primitive variables + # Calculate primitive variables - # flat lake - H = equations.H0 + # flat lake + H = equations.H0 - # Discontinuous velocity - v = 0.0 - if x[1] >= -0.75 && x[1] <= 0.0 - v = -1.0 - elseif x[1] >= 0.0 && x[1] <= 0.75 - v = 1.0 - end + # Discontinuous velocity + v = 0.0 + if x[1] >= -0.75 && x[1] <= 0.0 + v = -1.0 + elseif x[1] >= 0.0 && x[1] <= 0.75 + v = 1.0 + end - b = ( 1.5 / exp( 0.5 * ((x[1] - 1.0)^2 ) ) - + 0.75 / exp( 0.5 * ((x[1] + 1.0)^2 ) ) ) + b = (1.5 / exp(0.5 * ((x[1] - 1.0)^2)) + + 0.75 / exp(0.5 * ((x[1] + 1.0)^2))) - # Force a discontinuous bottom topography - if x[1] >= -1.5 && x[1] <= 0.0 - b = 0.5 - end + # Force a discontinuous bottom topography + if x[1] >= -1.5 && x[1] <= 0.0 + b = 0.5 + end - return prim2cons(SVector(H, v, b), equations) + return prim2cons(SVector(H, v, b), equations) end initial_condition = initial_condition_stone_throw_discontinuous_bottom @@ -45,18 +46,19 @@ boundary_condition = boundary_condition_slip_wall # Get the DG approximation space volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -surface_flux = (FluxHydrostaticReconstruction(flux_lax_friedrichs, hydrostatic_reconstruction_audusse_etal), +surface_flux = (FluxHydrostaticReconstruction(flux_lax_friedrichs, + hydrostatic_reconstruction_audusse_etal), flux_nonconservative_audusse_etal) basis = LobattoLegendreBasis(4) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=waterheight_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = waterheight_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) @@ -66,9 +68,9 @@ solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = -3.0 coordinates_max = 3.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=10_000, - periodicity=false) + initial_refinement_level = 3, + n_cells_max = 10_000, + periodicity = false) # create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, @@ -86,28 +88,29 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=false, - extra_analysis_integrals=(energy_kinetic, - energy_internal, - lake_at_rest_error)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = false, + extra_analysis_integrals = (energy_kinetic, + energy_internal, + lake_at_rest_error)) # Enable in-situ visualization with a new plot generated every 50 time steps # and we explicitly pass that the plot data will be one-dimensional # visualization = VisualizationCallback(interval=50, plot_data_creator=PlotData1D) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution)#, - # visualization) +# visualization) ############################################################################### # run the simulation # use a Runge-Kutta method with automatic (error based) time step size control -sol = solve(ode, RDPK3SpFSAL49(); abstol=1.0e-7, reltol=1.0e-7, - ode_default_options()..., callback=callbacks); +sol = solve(ode, RDPK3SpFSAL49(); abstol = 1.0e-7, reltol = 1.0e-7, + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_shallowwater_source_terms.jl b/examples/tree_1d_dgsem/elixir_shallowwater_source_terms.jl index 2f9f93f4335..af596a377f8 100644 --- a/examples/tree_1d_dgsem/elixir_shallowwater_source_terms.jl +++ b/examples/tree_1d_dgsem/elixir_shallowwater_source_terms.jl @@ -5,17 +5,17 @@ using Trixi ############################################################################### # Semidiscretization of the shallow water equations -equations = ShallowWaterEquations1D(gravity_constant=9.81) +equations = ShallowWaterEquations1D(gravity_constant = 9.81) initial_condition = initial_condition_convergence_test - ############################################################################### # Get the DG approximation space volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -solver = DGSEM(polydeg=3, surface_flux=(flux_lax_friedrichs, flux_nonconservative_fjordholm_etal), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, + surface_flux = (flux_lax_friedrichs, flux_nonconservative_fjordholm_etal), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### # Get the TreeMesh and setup a periodic mesh @@ -23,13 +23,13 @@ solver = DGSEM(polydeg=3, surface_flux=(flux_lax_friedrichs, flux_nonconservativ coordinates_min = 0.0 coordinates_max = sqrt(2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=10_000, - periodicity=true) + initial_refinement_level = 3, + n_cells_max = 10_000, + periodicity = true) # create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -40,13 +40,13 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 500 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=200, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 200, + save_initial_solution = true, + save_final_solution = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) @@ -54,6 +54,6 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav # run the simulation # use a Runge-Kutta method with automatic (error based) time step size control -sol = solve(ode, RDPK3SpFSAL49(); abstol=1.0e-8, reltol=1.0e-8, - ode_default_options()..., callback=callbacks); +sol = solve(ode, RDPK3SpFSAL49(); abstol = 1.0e-8, reltol = 1.0e-8, + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_shallowwater_source_terms_dirichlet.jl b/examples/tree_1d_dgsem/elixir_shallowwater_source_terms_dirichlet.jl index c8ef1c1b70b..cbc98a30f9f 100644 --- a/examples/tree_1d_dgsem/elixir_shallowwater_source_terms_dirichlet.jl +++ b/examples/tree_1d_dgsem/elixir_shallowwater_source_terms_dirichlet.jl @@ -5,7 +5,7 @@ using Trixi ############################################################################### # Semidiscretization of the shallow water equations -equations = ShallowWaterEquations1D(gravity_constant=9.81) +equations = ShallowWaterEquations1D(gravity_constant = 9.81) initial_condition = initial_condition_convergence_test @@ -16,8 +16,8 @@ boundary_condition = BoundaryConditionDirichlet(initial_condition) volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) surface_flux = (flux_lax_friedrichs, flux_nonconservative_fjordholm_etal) -solver = DGSEM(polydeg=3, surface_flux=surface_flux, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = surface_flux, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### # Get the TreeMesh and setup a periodic mesh @@ -25,14 +25,14 @@ solver = DGSEM(polydeg=3, surface_flux=surface_flux, coordinates_min = 0.0 coordinates_max = sqrt(2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=10_000, - periodicity=false) + initial_refinement_level = 3, + n_cells_max = 10_000, + periodicity = false) # create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, boundary_conditions = boundary_condition, - source_terms=source_terms_convergence_test) + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -43,13 +43,13 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 500 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=200, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 200, + save_initial_solution = true, + save_final_solution = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) @@ -57,6 +57,6 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav # run the simulation # use a Runge-Kutta method with automatic (error based) time step size control -sol = solve(ode, RDPK3SpFSAL49(); abstol=1.0e-8, reltol=1.0e-8, - ode_default_options()..., callback=callbacks); +sol = solve(ode, RDPK3SpFSAL49(); abstol = 1.0e-8, reltol = 1.0e-8, + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_shallowwater_twolayer_convergence.jl b/examples/tree_1d_dgsem/elixir_shallowwater_twolayer_convergence.jl index e9f444aed27..e6a01849852 100644 --- a/examples/tree_1d_dgsem/elixir_shallowwater_twolayer_convergence.jl +++ b/examples/tree_1d_dgsem/elixir_shallowwater_twolayer_convergence.jl @@ -5,18 +5,18 @@ using Trixi ############################################################################### # Semidiscretization of the two-layer shallow water equations -equations = ShallowWaterTwoLayerEquations1D(gravity_constant=10.0, rho_upper=0.9, rho_lower=1.0) +equations = ShallowWaterTwoLayerEquations1D(gravity_constant = 10.0, rho_upper = 0.9, + rho_lower = 1.0) initial_condition = initial_condition_convergence_test - ############################################################################### # Get the DG approximation space -volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -solver = DGSEM(polydeg=3, surface_flux=(flux_fjordholm_etal, flux_nonconservative_fjordholm_etal), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) - +volume_flux = (flux_wintermeyer_etal, flux_nonconservative_ersing_etal) +solver = DGSEM(polydeg = 3, + surface_flux = (flux_wintermeyer_etal, flux_nonconservative_ersing_etal), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### # Get the TreeMesh and setup a periodic mesh @@ -24,13 +24,13 @@ solver = DGSEM(polydeg=3, surface_flux=(flux_fjordholm_etal, flux_nonconservativ coordinates_min = 0.0 coordinates_max = sqrt(2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=10_000, - periodicity=true) + initial_refinement_level = 3, + n_cells_max = 10_000, + periodicity = true) # create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -41,13 +41,13 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 500 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=500, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 500, + save_initial_solution = true, + save_final_solution = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) @@ -55,6 +55,6 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav # run the simulation # use a Runge-Kutta method with automatic (error based) time step size control - sol = solve(ode, RDPK3SpFSAL49(), abstol=1.0e-8, reltol=1.0e-8, - save_everystep=false, callback=callbacks); +sol = solve(ode, RDPK3SpFSAL49(), abstol = 1.0e-8, reltol = 1.0e-8, + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_shallowwater_twolayer_dam_break.jl b/examples/tree_1d_dgsem/elixir_shallowwater_twolayer_dam_break.jl index 60770d158fa..03b93754d0f 100644 --- a/examples/tree_1d_dgsem/elixir_shallowwater_twolayer_dam_break.jl +++ b/examples/tree_1d_dgsem/elixir_shallowwater_twolayer_dam_break.jl @@ -6,28 +6,29 @@ using Trixi # Semidiscretization of the two-layer shallow water equations for a dam break # test with a discontinuous bottom topography function to test entropy conservation -equations = ShallowWaterTwoLayerEquations1D(gravity_constant=9.81, H0=2.0, rho_upper=0.9, rho_lower=1.0) +equations = ShallowWaterTwoLayerEquations1D(gravity_constant = 9.81, H0 = 2.0, + rho_upper = 0.9, rho_lower = 1.0) # Initial condition of a dam break with a discontinuous water heights and bottom topography. # Works as intended for TreeMesh1D with `initial_refinement_level=5`. If the mesh # refinement level is changed the initial condition below may need changed as well to # ensure that the discontinuities lie on an element interface. function initial_condition_dam_break(x, t, equations::ShallowWaterTwoLayerEquations1D) - v1_upper = 0.0 - v1_lower = 0.0 - - # Set the discontinuity - if x[1] <= 10.0 - H_lower = 2.0 - H_upper = 4.0 - b = 0.0 - else - H_lower = 1.5 - H_upper = 3.0 - b = 0.5 - end - - return prim2cons(SVector(H_upper, v1_upper, H_lower, v1_lower, b), equations) + v1_upper = 0.0 + v1_lower = 0.0 + + # Set the discontinuity + if x[1] <= 10.0 + H_lower = 2.0 + H_upper = 4.0 + b = 0.0 + else + H_lower = 1.5 + H_upper = 3.0 + b = 0.5 + end + + return prim2cons(SVector(H_upper, v1_upper, H_lower, v1_lower, b), equations) end initial_condition = initial_condition_dam_break @@ -35,9 +36,10 @@ initial_condition = initial_condition_dam_break ############################################################################### # Get the DG approximation space -volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -solver = DGSEM(polydeg=3, surface_flux=(flux_fjordholm_etal, flux_nonconservative_fjordholm_etal), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +volume_flux = (flux_wintermeyer_etal, flux_nonconservative_ersing_etal) +solver = DGSEM(polydeg = 3, + surface_flux = (flux_wintermeyer_etal, flux_nonconservative_ersing_etal), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### # Get the TreeMesh and setup a non-periodic mesh @@ -45,20 +47,20 @@ solver = DGSEM(polydeg=3, surface_flux=(flux_fjordholm_etal, flux_nonconservativ coordinates_min = 0.0 coordinates_max = 20.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=5, - n_cells_max=10000, - periodicity=false) + initial_refinement_level = 5, + n_cells_max = 10000, + periodicity = false) boundary_condition = boundary_condition_slip_wall # create the semidiscretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_condition) + boundary_conditions = boundary_condition) ############################################################################### # ODE solvers -tspan = (0.0,0.4) +tspan = (0.0, 0.4) ode = semidiscretize(semi, tspan) ############################################################################### @@ -67,16 +69,19 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 500 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=false, - extra_analysis_integrals=(energy_total, energy_kinetic, energy_internal,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = false, + extra_analysis_integrals = (energy_total, + energy_kinetic, + energy_internal)) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=500, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 500, + save_initial_solution = true, + save_final_solution = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) @@ -84,6 +89,6 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav # run the simulation # use a Runge-Kutta method with automatic (error based) time step size control -sol = solve(ode, RDPK3SpFSAL49(), abstol=1.0e-8, reltol=1.0e-8, - save_everystep=false, callback=callbacks); -summary_callback() # print the timer summary \ No newline at end of file +sol = solve(ode, RDPK3SpFSAL49(), abstol = 1.0e-8, reltol = 1.0e-8, + save_everystep = false, callback = callbacks); +summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_shallowwater_twolayer_well_balanced.jl b/examples/tree_1d_dgsem/elixir_shallowwater_twolayer_well_balanced.jl index bec0b8ab69c..098e3aaf601 100644 --- a/examples/tree_1d_dgsem/elixir_shallowwater_twolayer_well_balanced.jl +++ b/examples/tree_1d_dgsem/elixir_shallowwater_twolayer_well_balanced.jl @@ -5,7 +5,8 @@ using Trixi ############################################################################### # Semidiscretization of the two-layer shallow water equations to test well-balancedness -equations = ShallowWaterTwoLayerEquations1D(gravity_constant=1.0, H0=0.6, rho_upper=0.9, rho_lower=1.0) +equations = ShallowWaterTwoLayerEquations1D(gravity_constant = 1.0, H0 = 0.6, + rho_upper = 0.9, rho_lower = 1.0) """ initial_condition_fjordholm_well_balanced(x, t, equations::ShallowWaterTwoLayerEquations1D) @@ -15,7 +16,8 @@ Initial condition to test well balanced with a bottom topography from Fjordholm Energy conservative and stable schemes for the two-layer shallow water equations. [DOI: 10.1142/9789814417099_0039](https://doi.org/10.1142/9789814417099_0039) """ -function initial_condition_fjordholm_well_balanced(x, t, equations::ShallowWaterTwoLayerEquations1D) +function initial_condition_fjordholm_well_balanced(x, t, + equations::ShallowWaterTwoLayerEquations1D) inicenter = 0.5 x_norm = x[1] - inicenter r = abs(x_norm) @@ -24,18 +26,19 @@ function initial_condition_fjordholm_well_balanced(x, t, equations::ShallowWater H_upper = 0.6 v1_upper = 0.0 v1_lower = 0.0 - b = r <= 0.1 ? 0.2 * (cos(10 * pi * (x[1] - 0.5)) + 1) : 0.0 + b = r <= 0.1 ? 0.2 * (cos(10 * pi * (x[1] - 0.5)) + 1) : 0.0 return prim2cons(SVector(H_upper, v1_upper, H_lower, v1_lower, b), equations) - end +end initial_condition = initial_condition_fjordholm_well_balanced ############################################################################### # Get the DG approximation space -volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -solver = DGSEM(polydeg=3, surface_flux=(flux_es_fjordholm_etal, flux_nonconservative_fjordholm_etal), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +volume_flux = (flux_wintermeyer_etal, flux_nonconservative_ersing_etal) +solver = DGSEM(polydeg = 3, + surface_flux = (flux_es_ersing_etal, flux_nonconservative_ersing_etal), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### # Get the TreeMesh and setup a periodic mesh @@ -43,9 +46,9 @@ solver = DGSEM(polydeg=3, surface_flux=(flux_es_fjordholm_etal, flux_nonconserva coordinates_min = 0.0 coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000, - periodicity=true) + initial_refinement_level = 4, + n_cells_max = 10_000, + periodicity = true) # create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -59,16 +62,17 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=false, - extra_analysis_integrals=(lake_at_rest_error,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = false, + extra_analysis_integrals = (lake_at_rest_error,)) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) @@ -76,7 +80,7 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced.jl b/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced.jl index e07bc04d76a..649e5023f6d 100644 --- a/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced.jl +++ b/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced.jl @@ -6,7 +6,7 @@ using Trixi # semidiscretization of the shallow water equations with a discontinuous # bottom topography function -equations = ShallowWaterEquations1D(gravity_constant=9.81, H0=3.25) +equations = ShallowWaterEquations1D(gravity_constant = 9.81, H0 = 3.25) # Setup a truly discontinuous bottom topography function for this academic # testcase of well-balancedness. The errors from the analysis callback are @@ -15,18 +15,19 @@ equations = ShallowWaterEquations1D(gravity_constant=9.81, H0=3.25) # Works as intended for TreeMesh1D with `initial_refinement_level=3`. If the mesh # refinement level is changed the initial condition below may need changed as well to # ensure that the discontinuities lie on an element interface. -function initial_condition_discontinuous_well_balancedness(x, t, equations::ShallowWaterEquations1D) - # Set the background values - H = equations.H0 - v = 0.0 - b = 0.0 - - # Setup a discontinuous bottom topography - if x[1] >= 0.5 && x[1] <= 0.75 - b = 2.0 + 0.5 * sin(2.0 * pi * x[1]) - end - - return prim2cons(SVector(H, v, b), equations) +function initial_condition_discontinuous_well_balancedness(x, t, + equations::ShallowWaterEquations1D) + # Set the background values + H = equations.H0 + v = 0.0 + b = 0.0 + + # Setup a discontinuous bottom topography + if x[1] >= 0.5 && x[1] <= 0.75 + b = 2.0 + 0.5 * sin(2.0 * pi * x[1]) + end + + return prim2cons(SVector(H, v, b), equations) end initial_condition = initial_condition_discontinuous_well_balancedness @@ -36,17 +37,17 @@ initial_condition = initial_condition_discontinuous_well_balancedness volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) surface_flux = (flux_fjordholm_etal, flux_nonconservative_fjordholm_etal) -solver = DGSEM(polydeg=4, surface_flux=surface_flux, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 4, surface_flux = surface_flux, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### # Get the TreeMesh and setup a periodic mesh coordinates_min = -1.0 -coordinates_max = 1.0 +coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=10_000) + initial_refinement_level = 3, + n_cells_max = 10_000) # Create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -63,16 +64,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(lake_at_rest_error,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (lake_at_rest_error,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=3.0) +stepsize_callback = StepsizeCallback(cfl = 3.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) @@ -80,7 +81,7 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced_nonperiodic.jl b/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced_nonperiodic.jl index ef707b803e9..e55fffc101e 100644 --- a/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced_nonperiodic.jl +++ b/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced_nonperiodic.jl @@ -5,19 +5,19 @@ using Trixi ############################################################################### # Semidiscretization of the shallow water equations -equations = ShallowWaterEquations1D(gravity_constant=1.0, H0=3.0) +equations = ShallowWaterEquations1D(gravity_constant = 1.0, H0 = 3.0) # An initial condition with constant total water height and zero velocities to test well-balancedness. function initial_condition_well_balancedness(x, t, equations::ShallowWaterEquations1D) - # Set the background values - H = equations.H0 - v = 0.0 + # Set the background values + H = equations.H0 + v = 0.0 - b = (1.5 / exp( 0.5 * ((x[1] - 1.0)^2))+ 0.75 / exp(0.5 * ((x[1] + 1.0)^2))) + b = (1.5 / exp(0.5 * ((x[1] - 1.0)^2)) + 0.75 / exp(0.5 * ((x[1] + 1.0)^2))) - return prim2cons(SVector(H, v, b), equations) + return prim2cons(SVector(H, v, b), equations) end - + initial_condition = initial_condition_well_balancedness boundary_condition = BoundaryConditionDirichlet(initial_condition) @@ -26,8 +26,8 @@ boundary_condition = BoundaryConditionDirichlet(initial_condition) # Get the DG approximation space volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -solver = DGSEM(polydeg=4, surface_flux=(flux_hll, flux_nonconservative_fjordholm_etal), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 4, surface_flux = (flux_hll, flux_nonconservative_fjordholm_etal), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### # Get the TreeMesh and setup a periodic mesh @@ -35,9 +35,9 @@ solver = DGSEM(polydeg=4, surface_flux=(flux_hll, flux_nonconservative_fjordholm coordinates_min = 0.0 coordinates_max = sqrt(2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=10_000, - periodicity=false) + initial_refinement_level = 3, + n_cells_max = 10_000, + periodicity = false) # create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, @@ -52,25 +52,25 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - save_analysis=true, - extra_analysis_integrals=(lake_at_rest_error,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true, + extra_analysis_integrals = (lake_at_rest_error,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) -callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, +callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced_wet_dry.jl b/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced_wet_dry.jl index 8de46c61794..26a8960ab46 100644 --- a/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced_wet_dry.jl +++ b/examples/tree_1d_dgsem/elixir_shallowwater_well_balanced_wet_dry.jl @@ -8,7 +8,7 @@ using Printf: @printf, @sprintf # # TODO: TrixiShallowWater: wet/dry example elixir -equations = ShallowWaterEquations1D(gravity_constant=9.812) +equations = ShallowWaterEquations1D(gravity_constant = 9.812) """ initial_condition_complex_bottom_well_balanced(x, t, equations:: ShallowWaterEquations1D) @@ -23,28 +23,29 @@ The initial condition is taken from Section 5.2 of the paper: A new hydrostatic reconstruction scheme based on subcell reconstructions [DOI:10.1137/15M1053074](https://dx.doi.org/10.1137/15M1053074) """ -function initial_condition_complex_bottom_well_balanced(x, t, equations:: ShallowWaterEquations1D) - v = 0.0 - b = sin(4 * pi * x[1]) + 3 - - if x[1] >= 0.5 - b = sin(4 * pi * x[1]) + 1 - end - - H = max(b, 2.5) - - if x[1] >= 0.5 - H = max(b, 1.5) - end - - # It is mandatory to shift the water level at dry areas to make sure the water height h - # stays positive. The system would not be stable for h set to a hard 0 due to division by h in - # the computation of velocity, e.g., (h v) / h. Therefore, a small dry state threshold - # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above - # for the ShallowWaterEquations and added to the initial condition if h = 0. - # This default value can be changed within the constructor call depending on the simulation setup. - H = max(H, b + equations.threshold_limiter) - return prim2cons(SVector(H, v, b), equations) +function initial_condition_complex_bottom_well_balanced(x, t, + equations::ShallowWaterEquations1D) + v = 0.0 + b = sin(4 * pi * x[1]) + 3 + + if x[1] >= 0.5 + b = sin(4 * pi * x[1]) + 1 + end + + H = max(b, 2.5) + + if x[1] >= 0.5 + H = max(b, 1.5) + end + + # It is mandatory to shift the water level at dry areas to make sure the water height h + # stays positive. The system would not be stable for h set to a hard 0 due to division by h in + # the computation of velocity, e.g., (h v) / h. Therefore, a small dry state threshold + # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above + # for the ShallowWaterEquations and added to the initial condition if h = 0. + # This default value can be changed within the constructor call depending on the simulation setup. + H = max(H, b + equations.threshold_limiter) + return prim2cons(SVector(H, v, b), equations) end initial_condition = initial_condition_complex_bottom_well_balanced @@ -53,19 +54,20 @@ initial_condition = initial_condition_complex_bottom_well_balanced # Get the DG approximation space volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -surface_flux = (FluxHydrostaticReconstruction(flux_hll_chen_noelle, hydrostatic_reconstruction_chen_noelle), +surface_flux = (FluxHydrostaticReconstruction(flux_hll_chen_noelle, + hydrostatic_reconstruction_chen_noelle), flux_nonconservative_chen_noelle) basis = LobattoLegendreBasis(3) indicator_sc = IndicatorHennemannGassnerShallowWater(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=waterheight_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = waterheight_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) @@ -76,8 +78,8 @@ coordinates_min = 0.0 coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=10_000) + initial_refinement_level = 6, + n_cells_max = 10_000) # create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -91,26 +93,27 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 5000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=false) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = false) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=5000, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 5000, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=1.5) +stepsize_callback = StepsizeCallback(cfl = 1.5) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) -stage_limiter! = PositivityPreservingLimiterShallowWater(variables=(Trixi.waterheight,)) +stage_limiter! = PositivityPreservingLimiterShallowWater(variables = (Trixi.waterheight,)) ############################################################################### # run the simulation -sol = solve(ode, SSPRK43(stage_limiter!); dt=1.0, - ode_default_options()..., callback=callbacks, adaptive=false); +sol = solve(ode, SSPRK43(stage_limiter!); dt = 1.0, + ode_default_options()..., callback = callbacks, adaptive = false); summary_callback() # print the timer summary @@ -123,35 +126,39 @@ summary_callback() # print the timer summary # Declare a special version of the function to compute the lake-at-rest error # OBS! The reference water height values are hardcoded for convenience. function lake_at_rest_error_two_level(u, x, equations::ShallowWaterEquations1D) - h, _, b = u - - # For well-balancedness testing with possible wet/dry regions the reference - # water height `H0` accounts for the possibility that the bottom topography - # can emerge out of the water as well as for the threshold offset to avoid - # division by a "hard" zero water heights as well. - if x[1] < 0.5 - H0_wet_dry = max( 2.5 , b + equations.threshold_limiter ) - else - H0_wet_dry = max( 1.5 , b + equations.threshold_limiter ) - end - - return abs(H0_wet_dry - (h + b)) - end + h, _, b = u + + # For well-balancedness testing with possible wet/dry regions the reference + # water height `H0` accounts for the possibility that the bottom topography + # can emerge out of the water as well as for the threshold offset to avoid + # division by a "hard" zero water heights as well. + if x[1] < 0.5 + H0_wet_dry = max(2.5, b + equations.threshold_limiter) + else + H0_wet_dry = max(1.5, b + equations.threshold_limiter) + end + + return abs(H0_wet_dry - (h + b)) +end # point to the data we want to analyze u = Trixi.wrap_array(sol[end], semi) # Perform the actual integration of the well-balancedness error over the domain -l1_well_balance_error = Trixi.integrate_via_indices(u, mesh, equations, semi.solver, semi.cache; normalize=true) do u, i, element, equations, solver - x_node = Trixi.get_node_coords(semi.cache.elements.node_coordinates, equations, solver, i, element) - # We know that the discontinuity is a vertical line. Slightly augment the x value by a factor - # of unit roundoff to avoid the repeted value from the LGL nodes at at interface. - if i == 1 - x_node = SVector(nextfloat(x_node[1])) - elseif i == nnodes(semi.solver) - x_node = SVector(prevfloat(x_node[1])) - end - u_local = Trixi.get_node_vars(u, equations, solver, i, element) - return lake_at_rest_error_two_level(u_local, x_node, equations) +l1_well_balance_error = Trixi.integrate_via_indices(u, mesh, equations, semi.solver, + semi.cache; + normalize = true) do u, i, element, + equations, solver + x_node = Trixi.get_node_coords(semi.cache.elements.node_coordinates, equations, solver, + i, element) + # We know that the discontinuity is a vertical line. Slightly augment the x value by a factor + # of unit roundoff to avoid the repeted value from the LGL nodes at at interface. + if i == 1 + x_node = SVector(nextfloat(x_node[1])) + elseif i == nnodes(semi.solver) + x_node = SVector(prevfloat(x_node[1])) + end + u_local = Trixi.get_node_vars(u, equations, solver, i, element) + return lake_at_rest_error_two_level(u_local, x_node, equations) end # report the well-balancedness lake-at-rest error to the screen @@ -162,4 +169,4 @@ println(" Lake-at-rest error for '", Trixi.get_name(equations), "' with ", summa @printf(" %-12s:", Trixi.pretty_form_utf(lake_at_rest_error)) @printf(" % 10.8e", l1_well_balance_error) println() -println("─"^100) \ No newline at end of file +println("─"^100) diff --git a/examples/tree_1d_fdsbp/elixir_advection_upwind.jl b/examples/tree_1d_fdsbp/elixir_advection_upwind.jl index 1f2498e0866..389a8566c97 100644 --- a/examples/tree_1d_fdsbp/elixir_advection_upwind.jl +++ b/examples/tree_1d_fdsbp/elixir_advection_upwind.jl @@ -24,7 +24,7 @@ solver = FDSBP(D_upw, volume_integral = VolumeIntegralUpwind(flux_splitting)) coordinates_min = -1.0 -coordinates_max = 1.0 +coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, initial_refinement_level = 4, n_cells_max = 10_000, @@ -32,7 +32,6 @@ mesh = TreeMesh(coordinates_min, coordinates_max, semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_sin, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -42,17 +41,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) - ############################################################################### # run the simulation -sol = solve(ode, RDPK3SpFSAL49(); abstol=1.0e-6, reltol=1.0e-6, - ode_default_options()..., callback=callbacks); +sol = solve(ode, RDPK3SpFSAL49(); abstol = 1.0e-6, reltol = 1.0e-6, + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_fdsbp/elixir_advection_upwind_periodic.jl b/examples/tree_1d_fdsbp/elixir_advection_upwind_periodic.jl index 035d3568a80..2d7c13d7e57 100644 --- a/examples/tree_1d_fdsbp/elixir_advection_upwind_periodic.jl +++ b/examples/tree_1d_fdsbp/elixir_advection_upwind_periodic.jl @@ -23,7 +23,7 @@ solver = FDSBP(D_upw, volume_integral = VolumeIntegralUpwind(flux_splitting)) coordinates_min = -1.0 -coordinates_max = 1.0 +coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, initial_refinement_level = 0, n_cells_max = 10_000, @@ -31,7 +31,6 @@ mesh = TreeMesh(coordinates_min, coordinates_max, semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_sin, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -41,17 +40,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) - ############################################################################### # run the simulation -sol = solve(ode, RDPK3SpFSAL49(); abstol=1.0e-6, reltol=1.0e-6, - ode_default_options()..., callback=callbacks); +sol = solve(ode, RDPK3SpFSAL49(); abstol = 1.0e-6, reltol = 1.0e-6, + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_fdsbp/elixir_burgers_basic.jl b/examples/tree_1d_fdsbp/elixir_burgers_basic.jl index c7b0176dfdc..c58fc497e14 100644 --- a/examples/tree_1d_fdsbp/elixir_burgers_basic.jl +++ b/examples/tree_1d_fdsbp/elixir_burgers_basic.jl @@ -12,24 +12,23 @@ equations = InviscidBurgersEquation1D() initial_condition = initial_condition_convergence_test D_upw = upwind_operators(SummationByPartsOperators.Mattsson2017, - derivative_order=1, - accuracy_order=4, - xmin=-1.0, xmax=1.0, - N=32) + derivative_order = 1, + accuracy_order = 4, + xmin = -1.0, xmax = 1.0, + N = 32) flux_splitting = splitting_lax_friedrichs solver = FDSBP(D_upw, - surface_integral=SurfaceIntegralUpwind(flux_splitting), - volume_integral=VolumeIntegralUpwind(flux_splitting)) + surface_integral = SurfaceIntegralUpwind(flux_splitting), + volume_integral = VolumeIntegralUpwind(flux_splitting)) coordinates_min = 0.0 coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=10_000) + initial_refinement_level = 3, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -40,25 +39,24 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 200 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_errors=(:l2_error_primitive, - :linf_error_primitive)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_errors = (:l2_error_primitive, + :linf_error_primitive)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) - ############################################################################### # run the simulation -sol = solve(ode, SSPRK43(); abstol=1.0e-9, reltol=1.0e-9, - ode_default_options()..., callback=callbacks); +sol = solve(ode, SSPRK43(); abstol = 1.0e-9, reltol = 1.0e-9, + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_fdsbp/elixir_burgers_linear_stability.jl b/examples/tree_1d_fdsbp/elixir_burgers_linear_stability.jl index 20508feba22..eeaae7a7843 100644 --- a/examples/tree_1d_fdsbp/elixir_burgers_linear_stability.jl +++ b/examples/tree_1d_fdsbp/elixir_burgers_linear_stability.jl @@ -10,28 +10,28 @@ using Trixi equations = InviscidBurgersEquation1D() function initial_condition_linear_stability(x, t, equation::InviscidBurgersEquation1D) - k = 1 - 2 + sinpi(k * (x[1] - 0.7)) |> SVector + k = 1 + 2 + sinpi(k * (x[1] - 0.7)) |> SVector end D_upw = upwind_operators(SummationByPartsOperators.Mattsson2017, - derivative_order=1, - accuracy_order=4, - xmin=-1.0, xmax=1.0, - N=16) + derivative_order = 1, + accuracy_order = 4, + xmin = -1.0, xmax = 1.0, + N = 16) flux_splitting = splitting_lax_friedrichs solver = FDSBP(D_upw, - surface_integral=SurfaceIntegralUpwind(flux_splitting), - volume_integral=VolumeIntegralUpwind(flux_splitting)) + surface_integral = SurfaceIntegralUpwind(flux_splitting), + volume_integral = VolumeIntegralUpwind(flux_splitting)) coordinates_min = -1.0 -coordinates_max = 1.0 +coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) - -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_linear_stability, solver) + initial_refinement_level = 4, + n_cells_max = 10_000) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_linear_stability, + solver) ############################################################################### # ODE solvers, callbacks etc. @@ -42,19 +42,18 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_errors=(:l2_error_primitive, - :linf_error_primitive)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_errors = (:l2_error_primitive, + :linf_error_primitive)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) - ############################################################################### # run the simulation -sol = solve(ode, SSPRK43(); abstol=1.0e-6, reltol=1.0e-6, - ode_default_options()..., callback=callbacks); +sol = solve(ode, SSPRK43(); abstol = 1.0e-6, reltol = 1.0e-6, + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_1d_fdsbp/elixir_euler_convergence.jl b/examples/tree_1d_fdsbp/elixir_euler_convergence.jl index f9f9297f7c8..7b6bfee946e 100644 --- a/examples/tree_1d_fdsbp/elixir_euler_convergence.jl +++ b/examples/tree_1d_fdsbp/elixir_euler_convergence.jl @@ -12,24 +12,23 @@ equations = CompressibleEulerEquations1D(1.4) initial_condition = initial_condition_convergence_test D_upw = upwind_operators(SummationByPartsOperators.Mattsson2017, - derivative_order=1, - accuracy_order=4, - xmin=-1.0, xmax=1.0, - N=32) + derivative_order = 1, + accuracy_order = 4, + xmin = -1.0, xmax = 1.0, + N = 32) flux_splitting = splitting_steger_warming solver = FDSBP(D_upw, - surface_integral=SurfaceIntegralUpwind(flux_splitting), - volume_integral=VolumeIntegralUpwind(flux_splitting)) + surface_integral = SurfaceIntegralUpwind(flux_splitting), + volume_integral = VolumeIntegralUpwind(flux_splitting)) coordinates_min = 0.0 coordinates_max = 2.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=1, - n_cells_max=10_000) + initial_refinement_level = 1, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -40,25 +39,24 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_errors=(:l2_error_primitive, - :linf_error_primitive)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_errors = (:l2_error_primitive, + :linf_error_primitive)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) - ############################################################################### # run the simulation -sol = solve(ode, SSPRK43(); abstol=1.0e-6, reltol=1.0e-6, - ode_default_options()..., callback=callbacks) +sol = solve(ode, SSPRK43(); abstol = 1.0e-6, reltol = 1.0e-6, + ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary diff --git a/examples/tree_1d_fdsbp/elixir_euler_density_wave.jl b/examples/tree_1d_fdsbp/elixir_euler_density_wave.jl index 5c5192a3fbe..a28cd01120b 100644 --- a/examples/tree_1d_fdsbp/elixir_euler_density_wave.jl +++ b/examples/tree_1d_fdsbp/elixir_euler_density_wave.jl @@ -11,24 +11,23 @@ equations = CompressibleEulerEquations1D(1.4) initial_condition = initial_condition_density_wave D_upw = upwind_operators(SummationByPartsOperators.Mattsson2017, - derivative_order=1, - accuracy_order=4, - xmin=-1.0, xmax=1.0, - N=16) + derivative_order = 1, + accuracy_order = 4, + xmin = -1.0, xmax = 1.0, + N = 16) flux_splitting = splitting_coirier_vanleer solver = FDSBP(D_upw, - surface_integral=SurfaceIntegralUpwind(flux_splitting), - volume_integral=VolumeIntegralUpwind(flux_splitting)) + surface_integral = SurfaceIntegralUpwind(flux_splitting), + volume_integral = VolumeIntegralUpwind(flux_splitting)) coordinates_min = -1.0 -coordinates_max = 1.0 +coordinates_max = 1.0 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=30_000) + initial_refinement_level = 2, + n_cells_max = 30_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -38,23 +37,22 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 10000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) - ############################################################################### # run the simulation -sol = solve(ode, SSPRK43(); abstol=1.0e-6, reltol=1.0e-6, - ode_default_options()..., callback=callbacks) +sol = solve(ode, SSPRK43(); abstol = 1.0e-6, reltol = 1.0e-6, + ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_acoustics_convergence.jl b/examples/tree_2d_dgsem/elixir_acoustics_convergence.jl index d34399a5576..615da951871 100644 --- a/examples/tree_2d_dgsem/elixir_acoustics_convergence.jl +++ b/examples/tree_2d_dgsem/elixir_acoustics_convergence.jl @@ -4,26 +4,25 @@ using Trixi ############################################################################### # semidiscretization of the acoustic perturbation equations -equations = AcousticPerturbationEquations2D(v_mean_global=(0.5, 0.3), c_mean_global=2.0, - rho_mean_global=0.9) +equations = AcousticPerturbationEquations2D(v_mean_global = (0.5, 0.3), c_mean_global = 2.0, + rho_mean_global = 0.9) initial_condition = initial_condition_convergence_test # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (0.0, 0.0) # minimum coordinates (min(x), min(y)) coordinates_max = (2.0, 2.0) # maximum coordinates (max(x), max(y)) # Create a uniformly refined mesh with periodic boundaries mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=30_000) # set maximum capacity of tree data structure + initial_refinement_level = 3, + n_cells_max = 30_000) # set maximum capacity of tree data structure # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -37,26 +36,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); # Print the timer summary summary_callback() diff --git a/examples/tree_2d_dgsem/elixir_acoustics_gauss.jl b/examples/tree_2d_dgsem/elixir_acoustics_gauss.jl index fa608e78693..b3fe55dccea 100644 --- a/examples/tree_2d_dgsem/elixir_acoustics_gauss.jl +++ b/examples/tree_2d_dgsem/elixir_acoustics_gauss.jl @@ -10,20 +10,19 @@ rho_mean_global = 1.0 equations = AcousticPerturbationEquations2D(v_mean_global, c_mean_global, rho_mean_global) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-1.0, -1.0) # minimum coordinates (min(x), min(y)) -coordinates_max = ( 1.0, 1.0) # maximum coordinates (max(x), max(y)) +coordinates_max = (1.0, 1.0) # maximum coordinates (max(x), max(y)) # Create a uniformly refined mesh with periodic boundaries mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=30_000) # set maximum capacity of tree data structure + initial_refinement_level = 4, + n_cells_max = 30_000) # set maximum capacity of tree data structure # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_gauss, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -36,26 +35,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); # Print the timer summary summary_callback() diff --git a/examples/tree_2d_dgsem/elixir_acoustics_gauss_wall.jl b/examples/tree_2d_dgsem/elixir_acoustics_gauss_wall.jl index 78102eaf874..918c0831fcd 100644 --- a/examples/tree_2d_dgsem/elixir_acoustics_gauss_wall.jl +++ b/examples/tree_2d_dgsem/elixir_acoustics_gauss_wall.jl @@ -4,20 +4,20 @@ using Trixi ############################################################################### # semidiscretization of the acoustic perturbation equations -equations = AcousticPerturbationEquations2D(v_mean_global=(0.5, 0.0), c_mean_global=1.0, - rho_mean_global=1.0) +equations = AcousticPerturbationEquations2D(v_mean_global = (0.5, 0.0), c_mean_global = 1.0, + rho_mean_global = 1.0) # Create DG solver with polynomial degree = 5 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=5, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 5, surface_flux = flux_lax_friedrichs) coordinates_min = (-100.0, 0.0) # minimum coordinates (min(x), min(y)) coordinates_max = (100.0, 200.0) # maximum coordinates (max(x), max(y)) # Create a uniformly refined mesh with periodic boundaries mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=100_000, - periodicity=false) + initial_refinement_level = 4, + n_cells_max = 100_000, + periodicity = false) """ initial_condition_gauss_wall(x, t, equations::AcousticPerturbationEquations2D) @@ -26,20 +26,19 @@ A Gaussian pulse, used in the `gauss_wall` example elixir in combination with [`boundary_condition_wall`](@ref). Uses the global mean values from `equations`. """ function initial_condition_gauss_wall(x, t, equations::AcousticPerturbationEquations2D) - v1_prime = 0.0 - v2_prime = 0.0 - p_prime = exp(-log(2) * (x[1]^2 + (x[2] - 25)^2) / 25) + v1_prime = 0.0 + v2_prime = 0.0 + p_prime = exp(-log(2) * (x[1]^2 + (x[2] - 25)^2) / 25) - prim = SVector(v1_prime, v2_prime, p_prime, global_mean_vars(equations)...) + prim = SVector(v1_prime, v2_prime, p_prime, global_mean_vars(equations)...) - return prim2cons(prim, equations) + return prim2cons(prim, equations) end initial_condition = initial_condition_gauss_wall # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_condition_wall) - + boundary_conditions = boundary_condition_wall) ############################################################################### # ODE solvers, callbacks etc. @@ -53,24 +52,25 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, solution_variables=cons2state) +save_solution = SaveSolutionCallback(interval = 100, solution_variables = cons2state) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=0.7) +stepsize_callback = StepsizeCallback(cfl = 0.7) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks) +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks) # Print the timer summary summary_callback() diff --git a/examples/tree_2d_dgsem/elixir_acoustics_gaussian_source.jl b/examples/tree_2d_dgsem/elixir_acoustics_gaussian_source.jl index 0a0e2520581..71d4f1a9f68 100644 --- a/examples/tree_2d_dgsem/elixir_acoustics_gaussian_source.jl +++ b/examples/tree_2d_dgsem/elixir_acoustics_gaussian_source.jl @@ -3,45 +3,45 @@ using Trixi # Oscillating Gaussian-shaped source terms function source_terms_gauss(u, x, t, equations::AcousticPerturbationEquations2D) - r = 0.1 - A = 1.0 - f = 2.0 + r = 0.1 + A = 1.0 + f = 2.0 - # Velocity sources - s1 = 0.0 - s2 = 0.0 - # Pressure source - s3 = exp(-(x[1]^2 + x[2]^2) / (2 * r^2)) * A * sin(2 * pi * f * t) + # Velocity sources + s1 = 0.0 + s2 = 0.0 + # Pressure source + s3 = exp(-(x[1]^2 + x[2]^2) / (2 * r^2)) * A * sin(2 * pi * f * t) - # Mean sources - s4 = s5 = s6 = s7 = 0.0 + # Mean sources + s4 = s5 = s6 = s7 = 0.0 - return SVector(s1, s2, s3, s4, s5, s6, s7) + return SVector(s1, s2, s3, s4, s5, s6, s7) end ############################################################################### # semidiscretization of the acoustic perturbation equations -equations = AcousticPerturbationEquations2D(v_mean_global=(-0.5, 0.25), c_mean_global=1.0, - rho_mean_global=1.0) +equations = AcousticPerturbationEquations2D(v_mean_global = (-0.5, 0.25), + c_mean_global = 1.0, + rho_mean_global = 1.0) initial_condition = initial_condition_constant # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-3.0, -3.0) # minimum coordinates (min(x), min(y)) -coordinates_max = ( 3.0, 3.0) # maximum coordinates (max(x), max(y)) +coordinates_max = (3.0, 3.0) # maximum coordinates (max(x), max(y)) # Create a uniformly refined mesh with periodic boundaries mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=30_000) # set maximum capacity of tree data structure + initial_refinement_level = 4, + n_cells_max = 30_000) # set maximum capacity of tree data structure # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_gauss) - + source_terms = source_terms_gauss) ############################################################################### # ODE solvers, callbacks etc. @@ -55,30 +55,29 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The TimeSeriesCallback records the solution at the given points over time time_series = TimeSeriesCallback(semi, [(0.0, 0.0), (-1.0, 0.5)]) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, time_series, stepsize_callback) - ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); # Print the timer summary summary_callback() diff --git a/examples/tree_2d_dgsem/elixir_acoustics_monopole.jl b/examples/tree_2d_dgsem/elixir_acoustics_monopole.jl index 0fdcbd22c44..d7265775114 100644 --- a/examples/tree_2d_dgsem/elixir_acoustics_monopole.jl +++ b/examples/tree_2d_dgsem/elixir_acoustics_monopole.jl @@ -4,11 +4,11 @@ using Trixi ############################################################################### # semidiscretization of the acoustic perturbation equations -equations = AcousticPerturbationEquations2D(v_mean_global=(0.0, 0.0), c_mean_global=0.0, - rho_mean_global=0.0) +equations = AcousticPerturbationEquations2D(v_mean_global = (0.0, 0.0), c_mean_global = 0.0, + rho_mean_global = 0.0) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-20.6, 0.0) # minimum coordinates (min(x), min(y)) coordinates_max = (30.6, 51.2) # maximum coordinates (max(x), max(y)) @@ -20,20 +20,20 @@ Initial condition for the monopole in a boundary layer setup, used in combinatio [`boundary_condition_monopole`](@ref). """ function initial_condition_monopole(x, t, equations::AcousticPerturbationEquations2D) - m = 0.3 # Mach number + m = 0.3 # Mach number - v1_prime = 0.0 - v2_prime = 0.0 - p_prime = 0.0 + v1_prime = 0.0 + v2_prime = 0.0 + p_prime = 0.0 - v1_mean = x[2] > 1 ? m : m * (2*x[2] - 2*x[2]^2 + x[2]^4) - v2_mean = 0.0 - c_mean = 1.0 - rho_mean = 1.0 + v1_mean = x[2] > 1 ? m : m * (2 * x[2] - 2 * x[2]^2 + x[2]^4) + v2_mean = 0.0 + c_mean = 1.0 + rho_mean = 1.0 - prim = SVector(v1_prime, v2_prime, p_prime, v1_mean, v2_mean, c_mean, rho_mean) + prim = SVector(v1_prime, v2_prime, p_prime, v1_mean, v2_mean, c_mean, rho_mean) - return prim2cons(prim, equations) + return prim2cons(prim, equations) end initial_condition = initial_condition_monopole # does not use the global mean values given above @@ -45,32 +45,35 @@ Boundary condition for a monopole in a boundary layer at the -y boundary, i.e. ` This will return an error for any other direction. This boundary condition is used in combination with [`initial_condition_monopole`](@ref). """ -function boundary_condition_monopole(u_inner, orientation, direction, x, t, surface_flux_function, +function boundary_condition_monopole(u_inner, orientation, direction, x, t, + surface_flux_function, equations::AcousticPerturbationEquations2D) - if direction != 3 - error("expected direction = 3, got $direction instead") - end - - # Wall at the boundary in -y direction with a monopole at -0.05 <= x <= 0.05. In the monopole area - # we use a sinusoidal boundary state for the perturbed variables. For the rest of the -y boundary - # we set the boundary state to the inner state and multiply the perturbed velocity in the - # y-direction by -1. - if -0.05 <= x[1] <= 0.05 # Monopole - v1_prime = 0.0 - v2_prime = p_prime = sin(2 * pi * t) - - prim_boundary = SVector(v1_prime, v2_prime, p_prime, u_inner[4], u_inner[5], u_inner[6], u_inner[7]) - - u_boundary = prim2cons(prim_boundary, equations) - else # Wall - u_boundary = SVector(u_inner[1], -u_inner[2], u_inner[3], u_inner[4], u_inner[5], u_inner[6], - u_inner[7]) - end - - # Calculate boundary flux - flux = surface_flux_function(u_boundary, u_inner, orientation, equations) + if direction != 3 + error("expected direction = 3, got $direction instead") + end + + # Wall at the boundary in -y direction with a monopole at -0.05 <= x <= 0.05. In the monopole area + # we use a sinusoidal boundary state for the perturbed variables. For the rest of the -y boundary + # we set the boundary state to the inner state and multiply the perturbed velocity in the + # y-direction by -1. + if -0.05 <= x[1] <= 0.05 # Monopole + v1_prime = 0.0 + v2_prime = p_prime = sin(2 * pi * t) + + prim_boundary = SVector(v1_prime, v2_prime, p_prime, u_inner[4], u_inner[5], + u_inner[6], u_inner[7]) + + u_boundary = prim2cons(prim_boundary, equations) + else # Wall + u_boundary = SVector(u_inner[1], -u_inner[2], u_inner[3], u_inner[4], u_inner[5], + u_inner[6], + u_inner[7]) + end + + # Calculate boundary flux + flux = surface_flux_function(u_boundary, u_inner, orientation, equations) - return flux + return flux end """ @@ -80,42 +83,42 @@ end Boundary condition that uses a boundary state where the state variables are zero and the mean variables are the same as in `u_inner`. """ -function boundary_condition_zero(u_inner, orientation, direction, x, t, surface_flux_function, +function boundary_condition_zero(u_inner, orientation, direction, x, t, + surface_flux_function, equations::AcousticPerturbationEquations2D) - value = zero(eltype(u_inner)) - u_boundary = SVector(value, value, value, cons2mean(u_inner, equations)...) + value = zero(eltype(u_inner)) + u_boundary = SVector(value, value, value, cons2mean(u_inner, equations)...) - # Calculate boundary flux - if iseven(direction) # u_inner is "left" of boundary, u_boundary is "right" of boundary - flux = surface_flux_function(u_inner, u_boundary, orientation, equations) - else # u_boundary is "left" of boundary, u_inner is "right" of boundary - flux = surface_flux_function(u_boundary, u_inner, orientation, equations) - end + # Calculate boundary flux + if iseven(direction) # u_inner is "left" of boundary, u_boundary is "right" of boundary + flux = surface_flux_function(u_inner, u_boundary, orientation, equations) + else # u_boundary is "left" of boundary, u_inner is "right" of boundary + flux = surface_flux_function(u_boundary, u_inner, orientation, equations) + end - return flux + return flux end -boundary_conditions = (x_neg=boundary_condition_zero, - x_pos=boundary_condition_zero, - y_neg=boundary_condition_monopole, - y_pos=boundary_condition_zero) +boundary_conditions = (x_neg = boundary_condition_zero, + x_pos = boundary_condition_zero, + y_neg = boundary_condition_monopole, + y_pos = boundary_condition_zero) # Create a uniformly refined mesh with periodic boundaries mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=100_000, - periodicity=false) + initial_refinement_level = 6, + n_cells_max = 100_000, + periodicity = false) # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. # Create ODE problem with time span from 0.0 to 24.0 -tspan = (0.0, 24.0) +tspan = (0.0, 24.0) ode = semidiscretize(semi, tspan) # At the beginning of the main loop, the SummaryCallback prints a summary of the simulation setup @@ -123,24 +126,25 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks) +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks) # Print the timer summary -summary_callback() \ No newline at end of file +summary_callback() diff --git a/examples/tree_2d_dgsem/elixir_advection_amr.jl b/examples/tree_2d_dgsem/elixir_advection_amr.jl index 84841877448..c3f971d2ffc 100644 --- a/examples/tree_2d_dgsem/elixir_advection_amr.jl +++ b/examples/tree_2d_dgsem/elixir_advection_amr.jl @@ -9,18 +9,16 @@ advection_velocity = (0.2, -0.7) equations = LinearScalarAdvectionEquation2D(advection_velocity) initial_condition = initial_condition_gauss -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-5.0, -5.0) -coordinates_max = ( 5.0, 5.0) +coordinates_max = (5.0, 5.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=30_000) - + initial_refinement_level = 4, + n_cells_max = 30_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -30,37 +28,36 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable=first), - base_level=4, - med_level=5, med_threshold=0.1, - max_level=6, max_threshold=0.6) +amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable = first), + base_level = 4, + med_level = 5, med_threshold = 0.1, + max_level = 6, max_threshold = 0.6) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, amr_callback, stepsize_callback); - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_advection_amr_coarsen_twice.jl b/examples/tree_2d_dgsem/elixir_advection_amr_coarsen_twice.jl index 897d3569e10..aa042e7500e 100644 --- a/examples/tree_2d_dgsem/elixir_advection_amr_coarsen_twice.jl +++ b/examples/tree_2d_dgsem/elixir_advection_amr_coarsen_twice.jl @@ -3,7 +3,6 @@ using OrdinaryDiffEq using Trixi - # Define new structs inside a module to allow re-evaluating the file. # This module name needs to be unique among all examples, otherwise Julia will throw warnings # if multiple test cases using the same module name are run in the same session. @@ -11,27 +10,27 @@ module TrixiExtensionCoarsen using Trixi -struct IndicatorAlwaysCoarsen{Cache<:NamedTuple} <: Trixi.AbstractIndicator - cache::Cache +struct IndicatorAlwaysCoarsen{Cache <: NamedTuple} <: Trixi.AbstractIndicator + cache::Cache end function IndicatorAlwaysCoarsen(semi) - basis = semi.solver.basis - alpha = Vector{real(basis)}() - cache = (; semi.mesh, alpha) + basis = semi.solver.basis + alpha = Vector{real(basis)}() + cache = (; semi.mesh, alpha) - return IndicatorAlwaysCoarsen{typeof(cache)}(cache) + return IndicatorAlwaysCoarsen{typeof(cache)}(cache) end -function (indicator::IndicatorAlwaysCoarsen)(u::AbstractArray{<:Any,4}, +function (indicator::IndicatorAlwaysCoarsen)(u::AbstractArray{<:Any, 4}, mesh, equations, dg, cache; t, kwargs...) - alpha = indicator.cache.alpha - resize!(alpha, nelements(dg, cache)) + alpha = indicator.cache.alpha + resize!(alpha, nelements(dg, cache)) - alpha .= -1.0 + alpha .= -1.0 - return alpha + return alpha end end # module TrixiExtensionCoarsen @@ -46,18 +45,16 @@ equations = LinearScalarAdvectionEquation2D(advection_velocity) initial_condition = initial_condition_gauss -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-5.0, -5.0) -coordinates_max = ( 5.0, 5.0) +coordinates_max = (5.0, 5.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=30_000) - + initial_refinement_level = 4, + n_cells_max = 30_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -67,37 +64,37 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -amr_controller = ControllerThreeLevel(semi, TrixiExtensionCoarsen.IndicatorAlwaysCoarsen(semi), - base_level=2, max_level=2, - med_threshold=0.1, max_threshold=0.6) +amr_controller = ControllerThreeLevel(semi, + TrixiExtensionCoarsen.IndicatorAlwaysCoarsen(semi), + base_level = 2, max_level = 2, + med_threshold = 0.1, max_threshold = 0.6) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, amr_callback, stepsize_callback); - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_advection_amr_nonperiodic.jl b/examples/tree_2d_dgsem/elixir_advection_amr_nonperiodic.jl index 42aee985889..abb8a5035be 100644 --- a/examples/tree_2d_dgsem/elixir_advection_amr_nonperiodic.jl +++ b/examples/tree_2d_dgsem/elixir_advection_amr_nonperiodic.jl @@ -14,19 +14,17 @@ initial_condition = initial_condition_gauss # 2*ndims == 4 directions or you can pass a tuple containing BCs for each direction boundary_conditions = BoundaryConditionDirichlet(initial_condition) -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-5.0, -5.0) -coordinates_max = ( 5.0, 5.0) +coordinates_max = (5.0, 5.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=30_000, - periodicity=false) - + initial_refinement_level = 4, + n_cells_max = 30_000, + periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -37,26 +35,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable=first), - base_level=4, - med_level=5, med_threshold=0.1, - max_level=6, max_threshold=0.6) +amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable = first), + base_level = 4, + med_level = 5, med_threshold = 0.1, + max_level = 6, max_threshold = 0.6) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -65,7 +63,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=stepsize_callback(ode), # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = stepsize_callback(ode), # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_advection_amr_refine_twice.jl b/examples/tree_2d_dgsem/elixir_advection_amr_refine_twice.jl index e69cab29bb6..7b441775204 100644 --- a/examples/tree_2d_dgsem/elixir_advection_amr_refine_twice.jl +++ b/examples/tree_2d_dgsem/elixir_advection_amr_refine_twice.jl @@ -3,7 +3,6 @@ using OrdinaryDiffEq using Trixi - # Define new structs inside a module to allow re-evaluating the file. # This module name needs to be unique among all examples, otherwise Julia will throw warnings # if multiple test cases using the same module name are run in the same session. @@ -11,27 +10,27 @@ module TrixiExtensionRefine using Trixi -struct IndicatorAlwaysRefine{Cache<:NamedTuple} <: Trixi.AbstractIndicator - cache::Cache +struct IndicatorAlwaysRefine{Cache <: NamedTuple} <: Trixi.AbstractIndicator + cache::Cache end function IndicatorAlwaysRefine(semi) - basis = semi.solver.basis - alpha = Vector{real(basis)}() - cache = (; semi.mesh, alpha) + basis = semi.solver.basis + alpha = Vector{real(basis)}() + cache = (; semi.mesh, alpha) - return IndicatorAlwaysRefine{typeof(cache)}(cache) + return IndicatorAlwaysRefine{typeof(cache)}(cache) end -function (indicator::IndicatorAlwaysRefine)(u::AbstractArray{<:Any,4}, +function (indicator::IndicatorAlwaysRefine)(u::AbstractArray{<:Any, 4}, mesh, equations, dg, cache; t, kwargs...) - alpha = indicator.cache.alpha - resize!(alpha, nelements(dg, cache)) + alpha = indicator.cache.alpha + resize!(alpha, nelements(dg, cache)) - alpha .= 1.0 + alpha .= 1.0 - return alpha + return alpha end end # module TrixiExtensionRefine @@ -46,18 +45,16 @@ equations = LinearScalarAdvectionEquation2D(advection_velocity) initial_condition = initial_condition_gauss -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-5.0, -5.0) -coordinates_max = ( 5.0, 5.0) +coordinates_max = (5.0, 5.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=30_000) - + initial_refinement_level = 2, + n_cells_max = 30_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -67,37 +64,37 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -amr_controller = ControllerThreeLevel(semi, TrixiExtensionRefine.IndicatorAlwaysRefine(semi), - base_level=4, max_level=4, - med_threshold=0.1, max_threshold=0.6) +amr_controller = ControllerThreeLevel(semi, + TrixiExtensionRefine.IndicatorAlwaysRefine(semi), + base_level = 4, max_level = 4, + med_threshold = 0.1, max_threshold = 0.6) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, amr_callback, stepsize_callback); - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_advection_amr_solution_independent.jl b/examples/tree_2d_dgsem/elixir_advection_amr_solution_independent.jl index efd282dab1f..03a213689ec 100644 --- a/examples/tree_2d_dgsem/elixir_advection_amr_solution_independent.jl +++ b/examples/tree_2d_dgsem/elixir_advection_amr_solution_independent.jl @@ -7,69 +7,68 @@ module TrixiExtension using Trixi -struct IndicatorSolutionIndependent{Cache<:NamedTuple} <: Trixi.AbstractIndicator - cache::Cache +struct IndicatorSolutionIndependent{Cache <: NamedTuple} <: Trixi.AbstractIndicator + cache::Cache end function IndicatorSolutionIndependent(semi) - basis = semi.solver.basis - alpha = Vector{real(basis)}() - cache = (; semi.mesh, alpha) - return IndicatorSolutionIndependent{typeof(cache)}(cache) + basis = semi.solver.basis + alpha = Vector{real(basis)}() + cache = (; semi.mesh, alpha) + return IndicatorSolutionIndependent{typeof(cache)}(cache) end -function (indicator::IndicatorSolutionIndependent)(u::AbstractArray{<:Any,4}, +function (indicator::IndicatorSolutionIndependent)(u::AbstractArray{<:Any, 4}, mesh, equations, dg, cache; t, kwargs...) - - mesh = indicator.cache.mesh - alpha = indicator.cache.alpha - resize!(alpha, nelements(dg, cache)) - - #Predict the theoretical center. - advection_velocity = (0.2, -0.7) - center = t.*advection_velocity - - inner_distance = 1 - outer_distance = 1.85 - - #Iterate over all elements - for element in 1:length(alpha) - #Calculate periodic distance between cell and center. - cell_id = cache.elements.cell_ids[element] - coordinates = mesh.tree.coordinates[1:2, cell_id] - - #The geometric shape of the amr should be preserved when the base_level is increased. - #This is done by looking at the original coordinates of each cell. - cell_coordinates = original_coordinates(coordinates, 5/8) - cell_distance = periodic_distance_2d(cell_coordinates, center, 10) - if cell_distance < (inner_distance+outer_distance)/2 - cell_coordinates = original_coordinates(coordinates, 5/16) - cell_distance = periodic_distance_2d(cell_coordinates, center, 10) + mesh = indicator.cache.mesh + alpha = indicator.cache.alpha + resize!(alpha, nelements(dg, cache)) + + #Predict the theoretical center. + advection_velocity = (0.2, -0.7) + center = t .* advection_velocity + + inner_distance = 1 + outer_distance = 1.85 + + #Iterate over all elements + for element in 1:length(alpha) + #Calculate periodic distance between cell and center. + cell_id = cache.elements.cell_ids[element] + coordinates = mesh.tree.coordinates[1:2, cell_id] + + #The geometric shape of the amr should be preserved when the base_level is increased. + #This is done by looking at the original coordinates of each cell. + cell_coordinates = original_coordinates(coordinates, 5 / 8) + cell_distance = periodic_distance_2d(cell_coordinates, center, 10) + if cell_distance < (inner_distance + outer_distance) / 2 + cell_coordinates = original_coordinates(coordinates, 5 / 16) + cell_distance = periodic_distance_2d(cell_coordinates, center, 10) + end + + #Set alpha according to cells position inside the circles. + target_level = (cell_distance < inner_distance) + (cell_distance < outer_distance) + alpha[element] = target_level / 2 end - - #Set alpha according to cells position inside the circles. - target_level = (cell_distance < inner_distance) + (cell_distance < outer_distance) - alpha[element] = target_level/2 - end - return alpha + return alpha end # For periodic domains, distance between two points must take into account # periodic extensions of the domain function periodic_distance_2d(coordinates, center, domain_length) - dx = coordinates .- center - dx_shifted = abs.(dx .% domain_length) - dx_periodic = min.(dx_shifted, domain_length .- dx_shifted) - return sqrt(sum(dx_periodic.^2)) + dx = coordinates .- center + dx_shifted = abs.(dx .% domain_length) + dx_periodic = min.(dx_shifted, domain_length .- dx_shifted) + return sqrt(sum(dx_periodic .^ 2)) end #This takes a cells coordinates and transforms them into the coordinates of a parent-cell it originally refined from. #It does it so that the parent-cell has given cell_length. function original_coordinates(coordinates, cell_length) - offset = coordinates .% cell_length - offset_sign = sign.(offset) - border = coordinates - offset - center = border + (offset_sign .* cell_length/2) - return center + offset = coordinates .% cell_length + offset_sign = sign.(offset) + border = coordinates - offset + center = border + (offset_sign .* cell_length / 2) + return center end end # module TrixiExtension @@ -83,18 +82,16 @@ equations = LinearScalarAdvectionEquation2D(advection_velocity) initial_condition = initial_condition_gauss -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-5.0, -5.0) -coordinates_max = ( 5.0, 5.0) +coordinates_max = (5.0, 5.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=30_000) - + initial_refinement_level = 4, + n_cells_max = 30_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -104,38 +101,38 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -amr_controller = ControllerThreeLevel(semi, TrixiExtension.IndicatorSolutionIndependent(semi), - base_level=4, - med_level=5, med_threshold=0.1, - max_level=6, max_threshold=0.6) +amr_controller = ControllerThreeLevel(semi, + TrixiExtension.IndicatorSolutionIndependent(semi), + base_level = 4, + med_level = 5, med_threshold = 0.1, + max_level = 6, max_threshold = 0.6) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, amr_callback, stepsize_callback); - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_advection_amr_visualization.jl b/examples/tree_2d_dgsem/elixir_advection_amr_visualization.jl index f517b4eb1cf..7b67b811177 100644 --- a/examples/tree_2d_dgsem/elixir_advection_amr_visualization.jl +++ b/examples/tree_2d_dgsem/elixir_advection_amr_visualization.jl @@ -9,27 +9,26 @@ using Plots advection_velocity = (0.2, -0.7) equations = LinearScalarAdvectionEquation2D(advection_velocity) -function initial_condition_gauss_largedomain(x, t, equation::LinearScalarAdvectionEquation2D) - # Store translated coordinate for easy use of exact solution - domain_length = SVector(10, 10) - x_trans = Trixi.x_trans_periodic_2d(x - equation.advection_velocity * t, domain_length) +function initial_condition_gauss_largedomain(x, t, + equation::LinearScalarAdvectionEquation2D) + # Store translated coordinate for easy use of exact solution + domain_length = SVector(10, 10) + x_trans = Trixi.x_trans_periodic_2d(x - equation.advection_velocity * t, domain_length) - return SVector(exp(-(x_trans[1]^2 + x_trans[2]^2))) + return SVector(exp(-(x_trans[1]^2 + x_trans[2]^2))) end initial_condition = initial_condition_gauss_largedomain -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-5.0, -5.0) -coordinates_max = ( 5.0, 5.0) +coordinates_max = (5.0, 5.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=30_000) - + initial_refinement_level = 3, + n_cells_max = 30_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -39,41 +38,40 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) # Enable in-situ visualization with a new plot generated every 20 time steps # and additional plotting options passed as keyword arguments -visualization = VisualizationCallback(interval=20, clims=(0,1)) +visualization = VisualizationCallback(interval = 20, clims = (0, 1)) -amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable=first), - base_level=3, - med_level=4, med_threshold=0.1, - max_level=5, max_threshold=0.6) +amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable = first), + base_level = 3, + med_level = 4, med_threshold = 0.1, + max_level = 5, max_threshold = 0.6) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, visualization, amr_callback, stepsize_callback); - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_advection_basic.jl b/examples/tree_2d_dgsem/elixir_advection_basic.jl index 269ab8cdd04..0ec0bc3629a 100644 --- a/examples/tree_2d_dgsem/elixir_advection_basic.jl +++ b/examples/tree_2d_dgsem/elixir_advection_basic.jl @@ -9,19 +9,19 @@ advection_velocity = (0.2, -0.7) equations = LinearScalarAdvectionEquation2D(advection_velocity) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-1.0, -1.0) # minimum coordinates (min(x), min(y)) -coordinates_max = ( 1.0, 1.0) # maximum coordinates (max(x), max(y)) +coordinates_max = (1.0, 1.0) # maximum coordinates (max(x), max(y)) # Create a uniformly refined mesh with periodic boundaries mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=30_000) # set maximum capacity of tree data structure + initial_refinement_level = 4, + n_cells_max = 30_000) # set maximum capacity of tree data structure # A semidiscretization collects data structures and functions for the spatial discretization -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, solver) - +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, + solver) ############################################################################### # ODE solvers, callbacks etc. @@ -34,26 +34,26 @@ ode = semidiscretize(semi, (0.0, 1.0)); summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); # Print the timer summary summary_callback() diff --git a/examples/tree_2d_dgsem/elixir_advection_callbacks.jl b/examples/tree_2d_dgsem/elixir_advection_callbacks.jl index 2ddd3e92ed2..708cd0aa3a3 100644 --- a/examples/tree_2d_dgsem/elixir_advection_callbacks.jl +++ b/examples/tree_2d_dgsem/elixir_advection_callbacks.jl @@ -2,7 +2,6 @@ using OrdinaryDiffEq using Trixi - # define new structs inside a module to allow re-evaluating the file module TrixiExtensionExample @@ -14,83 +13,81 @@ using OrdinaryDiffEq: DiscreteCallback, u_modified! # each time it is called. Its sole purpose here is to showcase how to implement # a stage callback for Trixi.jl. struct ExampleStageCallback - times::Vector{Float64} - min_values::Vector{Float64} - max_values::Vector{Float64} - - # You can optionally define an inner constructor like the one below to set up - # some required stuff. You can also create outer constructors (not demonstrated - # here) for further customization options. - function ExampleStageCallback() - new(Float64[], Float64[], Float64[]) - end + times::Vector{Float64} + min_values::Vector{Float64} + max_values::Vector{Float64} + + # You can optionally define an inner constructor like the one below to set up + # some required stuff. You can also create outer constructors (not demonstrated + # here) for further customization options. + function ExampleStageCallback() + new(Float64[], Float64[], Float64[]) + end end # This method is called when the `ExampleStageCallback` is used as `stage_limiter!` # which gets called after every RK stage. There is no specific initialization # method for such `stage_limiter!`s in OrdinaryDiffEq.jl. function (example_stage_callback::ExampleStageCallback)(u_ode, _, semi, t) + min_val, max_val = extrema(u_ode) + push!(example_stage_callback.times, t) + push!(example_stage_callback.min_values, min_val) + push!(example_stage_callback.max_values, max_val) - min_val, max_val = extrema(u_ode) - push!(example_stage_callback.times, t) - push!(example_stage_callback.min_values, min_val) - push!(example_stage_callback.max_values, max_val) - - return nothing + return nothing end - # This is an example implementation for a simple step callback (i.e., a callable # that is potentially executed after each Runge-Kutta *step*), which records # some values each time it is called. Its sole purpose here is to showcase # how to implement a step callback for Trixi.jl. struct ExampleStepCallback - message::String - times::Vector{Float64} - min_values::Vector{Float64} - max_values::Vector{Float64} - - # You can optionally define an inner constructor like the one below to set up - # some required stuff. You can also create outer constructors (not demonstrated - # here) for further customization options. - function ExampleStepCallback(message::String) - new(message, Float64[], Float64[], Float64[]) - end + message::String + times::Vector{Float64} + min_values::Vector{Float64} + max_values::Vector{Float64} + + # You can optionally define an inner constructor like the one below to set up + # some required stuff. You can also create outer constructors (not demonstrated + # here) for further customization options. + function ExampleStepCallback(message::String) + new(message, Float64[], Float64[], Float64[]) + end end # This method is called when the `ExampleStepCallback` is used as callback # which gets called after RK steps. function (example_callback::ExampleStepCallback)(integrator) - u_ode = integrator.u - t = integrator.t - # You can also access semi = integrator.p - - min_val, max_val = extrema(u_ode) - push!(example_callback.times, t) - push!(example_callback.min_values, min_val) - push!(example_callback.max_values, max_val) - - # avoid re-evaluating possible FSAL stages - u_modified!(integrator, false) - return nothing + u_ode = integrator.u + t = integrator.t + # You can also access semi = integrator.p + + min_val, max_val = extrema(u_ode) + push!(example_callback.times, t) + push!(example_callback.min_values, min_val) + push!(example_callback.max_values, max_val) + + # avoid re-evaluating possible FSAL stages + u_modified!(integrator, false) + return nothing end # This method is used to wrap an `ExampleStepCallback` inside a `DiscreteCallback` # which gets called after every RK step. You can pass an additional initialization # method and a separate condition specifying whether the callback shall be called. function ExampleStepCallback(; message::String) - # Call the `ExampleStepCallback` after every RK step. - condition = (u_ode, t, integrator) -> true + # Call the `ExampleStepCallback` after every RK step. + condition = (u_ode, t, integrator) -> true - # You can optionally pass an initialization method. There, you can access the - # `ExampleStepCallback` as `cb.affect!`. - initialize = (cb, u_ode, t, integrator) -> println(cb.affect!.message) + # You can optionally pass an initialization method. There, you can access the + # `ExampleStepCallback` as `cb.affect!`. + initialize = (cb, u_ode, t, integrator) -> println(cb.affect!.message) - example_callback = ExampleStepCallback(message) + example_callback = ExampleStepCallback(message) - DiscreteCallback(condition, example_callback, - save_positions=(false,false), - initialize=initialize) + DiscreteCallback(condition, example_callback, + save_positions = (false, false), + initialize = initialize) end end # module TrixiExtensionExample @@ -104,18 +101,16 @@ advection_velocity = (0.2, -0.7) equations = LinearScalarAdvectionEquation2D(advection_velocity) initial_condition = initial_condition_convergence_test -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-1.0, -1.0) -coordinates_max = ( 1.0, 1.0) +coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=30_000) - + initial_refinement_level = 4, + n_cells_max = 30_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -125,19 +120,19 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy, energy_total)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy, energy_total)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2cons) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2cons) -example_callback = TrixiExtensionExample.ExampleStepCallback(message="안녕하세요?") +example_callback = TrixiExtensionExample.ExampleStepCallback(message = "안녕하세요?") -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -158,9 +153,10 @@ example_stage_callback! = TrixiExtensionExample.ExampleStageCallback() ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(example_stage_callback!, williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, + CarpenterKennedy2N54(example_stage_callback!, williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary # Check whether we recorded the same values. diff --git a/examples/tree_2d_dgsem/elixir_advection_diffusion.jl b/examples/tree_2d_dgsem/elixir_advection_diffusion.jl index a716bd278b8..1f765ff3564 100644 --- a/examples/tree_2d_dgsem/elixir_advection_diffusion.jl +++ b/examples/tree_2d_dgsem/elixir_advection_diffusion.jl @@ -10,30 +10,31 @@ diffusivity() = 5.0e-2 equations_parabolic = LaplaceDiffusion2D(diffusivity(), equations) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-1.0, -1.0) # minimum coordinates (min(x), min(y)) -coordinates_max = ( 1.0, 1.0) # maximum coordinates (max(x), max(y)) +coordinates_max = (1.0, 1.0) # maximum coordinates (max(x), max(y)) # Create a uniformly refined mesh with periodic boundaries mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - periodicity=true, - n_cells_max=30_000) # set maximum capacity of tree data structure + initial_refinement_level = 4, + periodicity = true, + n_cells_max = 30_000) # set maximum capacity of tree data structure # Define initial condition -function initial_condition_diffusive_convergence_test(x, t, equation::LinearScalarAdvectionEquation2D) - # Store translated coordinate for easy use of exact solution - x_trans = x - equation.advection_velocity * t - - nu = diffusivity() - c = 1.0 - A = 0.5 - L = 2 - f = 1/L - omega = 2 * pi * f - scalar = c + A * sin(omega * sum(x_trans)) * exp(-2 * nu * omega^2 * t) - return SVector(scalar) +function initial_condition_diffusive_convergence_test(x, t, + equation::LinearScalarAdvectionEquation2D) + # Store translated coordinate for easy use of exact solution + x_trans = x - equation.advection_velocity * t + + nu = diffusivity() + c = 1.0 + A = 0.5 + L = 2 + f = 1 / L + omega = 2 * pi * f + scalar = c + A * sin(omega * sum(x_trans)) * exp(-2 * nu * omega^2 * t) + return SVector(scalar) end initial_condition = initial_condition_diffusive_convergence_test @@ -45,9 +46,8 @@ boundary_conditions_parabolic = boundary_condition_periodic semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver; - boundary_conditions=(boundary_conditions, - boundary_conditions_parabolic)) - + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic)) ############################################################################### # ODE solvers, callbacks etc. @@ -62,23 +62,22 @@ summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) # The AliveCallback prints short status information in regular intervals -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) - ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks alg = RDPK3SpFSAL49() time_int_tol = 1.0e-11 -sol = solve(ode, alg; abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) +sol = solve(ode, alg; abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) # Print the timer summary summary_callback() diff --git a/examples/tree_2d_dgsem/elixir_advection_diffusion_nonperiodic.jl b/examples/tree_2d_dgsem/elixir_advection_diffusion_nonperiodic.jl index c3cd2ebeb20..8da542b0b5d 100644 --- a/examples/tree_2d_dgsem/elixir_advection_diffusion_nonperiodic.jl +++ b/examples/tree_2d_dgsem/elixir_advection_diffusion_nonperiodic.jl @@ -10,16 +10,16 @@ equations = LinearScalarAdvectionEquation2D(advection_velocity) equations_parabolic = LaplaceDiffusion2D(diffusivity(), equations) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-1.0, -0.5) # minimum coordinates (min(x), min(y)) -coordinates_max = ( 0.0, 0.5) # maximum coordinates (max(x), max(y)) +coordinates_max = (0.0, 0.5) # maximum coordinates (max(x), max(y)) # Create a uniformly refined mesh with periodic boundaries mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - periodicity=false, - n_cells_max=30_000) # set maximum capacity of tree data structure + initial_refinement_level = 4, + periodicity = false, + n_cells_max = 30_000) # set maximum capacity of tree data structure # Example setup taken from # - Truman Ellis, Jesse Chan, and Leszek Demkowicz (2016). @@ -28,22 +28,22 @@ mesh = TreeMesh(coordinates_min, coordinates_max, # to numerical partial differential equations. # [DOI](https://doi.org/10.1007/978-3-319-41640-3_6). function initial_condition_eriksson_johnson(x, t, equations) - l = 4 - epsilon = diffusivity() # TODO: this requires epsilon < .6 due to sqrt - lambda_1 = (-1 + sqrt(1 - 4 * epsilon * l)) / (-2 * epsilon) - lambda_2 = (-1 - sqrt(1 - 4 * epsilon * l)) / (-2 * epsilon) - r1 = (1 + sqrt(1 + 4 * pi^2 * epsilon^2)) / (2 * epsilon) - s1 = (1 - sqrt(1 + 4 * pi^2 * epsilon^2)) / (2 * epsilon) - u = exp(-l * t) * (exp(lambda_1 * x[1]) - exp(lambda_2 * x[1])) + - cos(pi * x[2]) * (exp(s1 * x[1]) - exp(r1 * x[1])) / (exp(-s1) - exp(-r1)) - return SVector{1}(u) + l = 4 + epsilon = diffusivity() # TODO: this requires epsilon < .6 due to sqrt + lambda_1 = (-1 + sqrt(1 - 4 * epsilon * l)) / (-2 * epsilon) + lambda_2 = (-1 - sqrt(1 - 4 * epsilon * l)) / (-2 * epsilon) + r1 = (1 + sqrt(1 + 4 * pi^2 * epsilon^2)) / (2 * epsilon) + s1 = (1 - sqrt(1 + 4 * pi^2 * epsilon^2)) / (2 * epsilon) + u = exp(-l * t) * (exp(lambda_1 * x[1]) - exp(lambda_2 * x[1])) + + cos(pi * x[2]) * (exp(s1 * x[1]) - exp(r1 * x[1])) / (exp(-s1) - exp(-r1)) + return SVector{1}(u) end initial_condition = initial_condition_eriksson_johnson boundary_conditions = (; x_neg = BoundaryConditionDirichlet(initial_condition), - y_neg = BoundaryConditionDirichlet(initial_condition), - y_pos = BoundaryConditionDirichlet(initial_condition), - x_pos = boundary_condition_do_nothing) + y_neg = BoundaryConditionDirichlet(initial_condition), + y_pos = BoundaryConditionDirichlet(initial_condition), + x_pos = boundary_condition_do_nothing) boundary_conditions_parabolic = BoundaryConditionDirichlet(initial_condition) @@ -51,9 +51,8 @@ boundary_conditions_parabolic = BoundaryConditionDirichlet(initial_condition) semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver; - boundary_conditions=(boundary_conditions, - boundary_conditions_parabolic)) - + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic)) ############################################################################### # ODE solvers, callbacks etc. @@ -68,22 +67,21 @@ summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) # The AliveCallback prints short status information in regular intervals -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) - ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks time_int_tol = 1.0e-11 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) # Print the timer summary summary_callback() diff --git a/examples/tree_2d_dgsem/elixir_advection_extended.jl b/examples/tree_2d_dgsem/elixir_advection_extended.jl index 8c837957ffd..4d3da47b04a 100644 --- a/examples/tree_2d_dgsem/elixir_advection_extended.jl +++ b/examples/tree_2d_dgsem/elixir_advection_extended.jl @@ -18,21 +18,20 @@ initial_condition = initial_condition_convergence_test boundary_conditions = boundary_condition_periodic # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-1.0, -1.0) # minimum coordinates (min(x), min(y)) -coordinates_max = ( 1.0, 1.0) # maximum coordinates (max(x), max(y)) +coordinates_max = (1.0, 1.0) # maximum coordinates (max(x), max(y)) # Create a uniformly refined mesh with periodic boundaries mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=30_000, # set maximum capacity of tree data structure - periodicity=true) + initial_refinement_level = 4, + n_cells_max = 30_000, # set maximum capacity of tree data structure + periodicity = true) # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -47,24 +46,24 @@ summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy, energy_total)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy, energy_total)) # The AliveCallback prints short status information in regular intervals -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) # The SaveRestartCallback allows to save a file from which a Trixi.jl simulation can be restarted -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 40, + save_final_restart = true) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver callbacks = CallbackSet(summary_callback, @@ -72,14 +71,14 @@ callbacks = CallbackSet(summary_callback, save_restart, save_solution, stepsize_callback) - ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +alg = CarpenterKennedy2N54(williamson_condition = false) +sol = solve(ode, alg, + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks; ode_default_options()...); # Print the timer summary summary_callback() diff --git a/examples/tree_2d_dgsem/elixir_advection_mortar.jl b/examples/tree_2d_dgsem/elixir_advection_mortar.jl index 2a283fb9008..645c55ba438 100644 --- a/examples/tree_2d_dgsem/elixir_advection_mortar.jl +++ b/examples/tree_2d_dgsem/elixir_advection_mortar.jl @@ -9,22 +9,19 @@ advection_velocity = (0.2, -0.7) equations = LinearScalarAdvectionEquation2D(advection_velocity) initial_condition = initial_condition_convergence_test -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-1.0, -1.0) -coordinates_max = ( 1.0, 1.0) -refinement_patches = ( - (type="box", coordinates_min=(0.0, -1.0), coordinates_max=(1.0, 1.0)), -) +coordinates_max = (1.0, 1.0) +refinement_patches = ((type = "box", coordinates_min = (0.0, -1.0), + coordinates_max = (1.0, 1.0)),) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - refinement_patches=refinement_patches, - n_cells_max=10_000,) - + initial_refinement_level = 2, + refinement_patches = refinement_patches, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -34,28 +31,27 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_advection_restart.jl b/examples/tree_2d_dgsem/elixir_advection_restart.jl index 72efb7d0c84..e0d1003f524 100644 --- a/examples/tree_2d_dgsem/elixir_advection_restart.jl +++ b/examples/tree_2d_dgsem/elixir_advection_restart.jl @@ -3,10 +3,11 @@ using OrdinaryDiffEq using Trixi ############################################################################### -# create a restart file - -trixi_include(@__MODULE__, joinpath(@__DIR__, "elixir_advection_extended.jl")) - +# Define time integration algorithm +alg = CarpenterKennedy2N54(williamson_condition = false) +# Create a restart file +trixi_include(@__MODULE__, joinpath(@__DIR__, "elixir_advection_extended.jl"), alg = alg, + tspan = (0.0, 10.0)) ############################################################################### # adapt the parameters that have changed compared to "elixir_advection_extended.jl" @@ -14,26 +15,29 @@ trixi_include(@__MODULE__, joinpath(@__DIR__, "elixir_advection_extended.jl")) # Note: If you get a restart file from somewhere else, you need to provide # appropriate setups in the elixir loading a restart file -restart_filename = joinpath("out", "restart_000018.h5") +restart_filename = joinpath("out", "restart_000040.h5") mesh = load_mesh(restart_filename) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) -tspan = (load_time(restart_filename), 2.0) +tspan = (load_time(restart_filename), 10.0) dt = load_dt(restart_filename) ode = semidiscretize(semi, tspan, restart_filename); # Do not overwrite the initial snapshot written by elixir_advection_extended.jl. save_solution.condition.save_initial_solution = false -alg = CarpenterKennedy2N54(williamson_condition=false) integrator = init(ode, alg, - dt=dt, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks) + dt = dt, # solve needs some value here but it will be overwritten by the stepsize_callback + callback = callbacks, maxiters = 100_000; ode_default_options()...) + +# Load saved context for adaptive time integrator +if integrator.opts.adaptive + load_adaptive_time_integrator!(integrator, restart_filename) +end # Get the last time index and work with that. -integrator.iter = load_timestep(restart_filename) -integrator.stats.naccept = integrator.iter +load_timestep!(integrator, restart_filename) ############################################################################### # run the simulation diff --git a/examples/tree_2d_dgsem/elixir_advection_timeintegration.jl b/examples/tree_2d_dgsem/elixir_advection_timeintegration.jl index be87f24f817..06982bb9a27 100644 --- a/examples/tree_2d_dgsem/elixir_advection_timeintegration.jl +++ b/examples/tree_2d_dgsem/elixir_advection_timeintegration.jl @@ -9,18 +9,16 @@ advection_velocity = (0.2, -0.7) equations = LinearScalarAdvectionEquation2D(advection_velocity) initial_condition = initial_condition_gauss -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-5.0, -5.0) -coordinates_max = ( 5.0, 5.0) +coordinates_max = (5.0, 5.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=30_000) - + initial_refinement_level = 4, + n_cells_max = 30_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -30,39 +28,38 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2cons) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2cons) -amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable=first), - base_level=4, - med_level=5, med_threshold=0.1, - max_level=6, max_threshold=0.6) +amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable = first), + base_level = 4, + med_level = 5, med_threshold = 0.1, + max_level = 6, max_threshold = 0.6) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, amr_callback, stepsize_callback) - ############################################################################### # run the simulation # sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), ode_algorithm = Trixi.CarpenterKennedy2N54() sol = Trixi.solve(ode, ode_algorithm, - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_astro_jet_amr.jl b/examples/tree_2d_dgsem/elixir_euler_astro_jet_amr.jl index c5790e455bc..1393f4a6cc8 100644 --- a/examples/tree_2d_dgsem/elixir_euler_astro_jet_amr.jl +++ b/examples/tree_2d_dgsem/elixir_euler_astro_jet_amr.jl @@ -4,7 +4,7 @@ using Trixi ############################################################################### # semidiscretization of the compressible Euler equations -gamma = 5/3 +gamma = 5 / 3 equations = CompressibleEulerEquations2D(gamma) # Initial condition adopted from @@ -13,55 +13,54 @@ equations = CompressibleEulerEquations2D(gamma) # https://tinyurl.com/c76fjtx4 # Mach = 2000 jet function initial_condition_astro_jet(x, t, equations::CompressibleEulerEquations2D) - @unpack gamma = equations - rho = 0.5 - v1 = 0 - v2 = 0 - p = 0.4127 - # add inflow for t>0 at x=-0.5 - # domain size is [-0.5,+0.5]^2 - if (t > 0) && (x[1] ≈ -0.5) && (abs(x[2]) < 0.05) - rho = 5 - v1 = 800 # about Mach number Ma = 2000 + @unpack gamma = equations + rho = 0.5 + v1 = 0 v2 = 0 p = 0.4127 - end - return prim2cons(SVector(rho, v1, v2, p), equations) + # add inflow for t>0 at x=-0.5 + # domain size is [-0.5,+0.5]^2 + if (t > 0) && (x[1] ≈ -0.5) && (abs(x[2]) < 0.05) + rho = 5 + v1 = 800 # about Mach number Ma = 2000 + v2 = 0 + p = 0.4127 + end + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_astro_jet -boundary_conditions = ( - x_neg=BoundaryConditionDirichlet(initial_condition_astro_jet), - x_pos=BoundaryConditionDirichlet(initial_condition_astro_jet), - y_neg=boundary_condition_periodic, - y_pos=boundary_condition_periodic, - ) +boundary_conditions = (x_neg = BoundaryConditionDirichlet(initial_condition_astro_jet), + x_pos = BoundaryConditionDirichlet(initial_condition_astro_jet), + y_neg = boundary_condition_periodic, + y_pos = boundary_condition_periodic) surface_flux = flux_lax_friedrichs # HLLC needs more shock capturing (alpha_max) -volume_flux = flux_ranocha # works with Chandrashekar flux as well +volume_flux = flux_ranocha # works with Chandrashekar flux as well polydeg = 3 basis = LobattoLegendreBasis(polydeg) # shock capturing necessary for this tough example indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.3, - alpha_min=0.0001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.3, + alpha_min = 0.0001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-0.5, -0.5) -coordinates_max = ( 0.5, 0.5) +coordinates_max = (0.5, 0.5) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - periodicity=(false,true), - n_cells_max=100_000) -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, boundary_conditions=boundary_conditions) + initial_refinement_level = 6, + periodicity = (false, true), + n_cells_max = 100_000) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -72,43 +71,43 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 5000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) - -alive_callback = AliveCallback(analysis_interval=analysis_interval) - -save_solution = SaveSolutionCallback(interval=5000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) - -amr_indicator = IndicatorHennemannGassner(semi, - alpha_max=1.0, - alpha_min=0.0001, - alpha_smooth=false, - variable=Trixi.density) - -amr_controller = ControllerThreeLevelCombined(semi, amr_indicator, indicator_sc, - base_level=2, - med_level =0, med_threshold=0.0003, # med_level = current level - max_level =8, max_threshold=0.003, - max_threshold_secondary=indicator_sc.alpha_max) - -amr_callback = AMRCallback(semi, amr_controller, - interval=1, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 5000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) + +amr_indicator = IndicatorHennemannGassner(semi, + alpha_max = 1.0, + alpha_min = 0.0001, + alpha_smooth = false, + variable = Trixi.density) + +amr_controller = ControllerThreeLevelCombined(semi, amr_indicator, indicator_sc, + base_level = 2, + med_level = 0, med_threshold = 0.0003, # med_level = current level + max_level = 8, max_threshold = 0.003, + max_threshold_secondary = indicator_sc.alpha_max) + +amr_callback = AMRCallback(semi, amr_controller, + interval = 1, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) callbacks = CallbackSet(summary_callback, - analysis_callback, alive_callback, + analysis_callback, alive_callback, amr_callback, save_solution) # positivity limiter necessary for this tough example -stage_limiter! = PositivityPreservingLimiterZhangShu(thresholds=(5.0e-6, 5.0e-6), - variables=(Trixi.density, pressure)) +stage_limiter! = PositivityPreservingLimiterZhangShu(thresholds = (5.0e-6, 5.0e-6), + variables = (Trixi.density, pressure)) ############################################################################### # run the simulation # use adaptive time stepping based on error estimates, time step roughly dt = 1e-7 sol = solve(ode, SSPRK43(stage_limiter!); - ode_default_options()..., callback=callbacks); + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave.jl index 0da18b7120d..ccd7b54086b 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave.jl @@ -16,48 +16,46 @@ A medium blast wave taken from [arXiv: 2008.12044](https://arxiv.org/abs/2008.12044) """ function initial_condition_blast_wave(x, t, equations::CompressibleEulerEquations2D) - # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" - # Set up polar coordinates - inicenter = SVector(0.0, 0.0) - x_norm = x[1] - inicenter[1] - y_norm = x[2] - inicenter[2] - r = sqrt(x_norm^2 + y_norm^2) - phi = atan(y_norm, x_norm) - sin_phi, cos_phi = sincos(phi) - - # Calculate primitive variables - rho = r > 0.5 ? 1.0 : 1.1691 - v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi - v2 = r > 0.5 ? 0.0 : 0.1882 * sin_phi - p = r > 0.5 ? 1.0E-3 : 1.245 - - return prim2cons(SVector(rho, v1, v2, p), equations) + # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" + # Set up polar coordinates + inicenter = SVector(0.0, 0.0) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + phi = atan(y_norm, x_norm) + sin_phi, cos_phi = sincos(phi) + + # Calculate primitive variables + rho = r > 0.5 ? 1.0 : 1.1691 + v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi + v2 = r > 0.5 ? 0.0 : 0.1882 * sin_phi + p = r > 0.5 ? 1.0E-3 : 1.245 + + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_blast_wave surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha +volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-2.0, -2.0) -coordinates_max = ( 2.0, 2.0) +coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=10_000) - + initial_refinement_level = 6, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -67,27 +65,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.9) +stepsize_callback = StepsizeCallback(cfl = 0.9) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_amr.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_amr.jl index 6ce9268486c..d32c2e51b06 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_amr.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_amr.jl @@ -16,48 +16,46 @@ A medium blast wave taken from [arXiv: 2008.12044](https://arxiv.org/abs/2008.12044) """ function initial_condition_blast_wave(x, t, equations::CompressibleEulerEquations2D) - # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" - # Set up polar coordinates - inicenter = SVector(0.0, 0.0) - x_norm = x[1] - inicenter[1] - y_norm = x[2] - inicenter[2] - r = sqrt(x_norm^2 + y_norm^2) - phi = atan(y_norm, x_norm) - sin_phi, cos_phi = sincos(phi) - - # Calculate primitive variables - rho = r > 0.5 ? 1.0 : 1.1691 - v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi - v2 = r > 0.5 ? 0.0 : 0.1882 * sin_phi - p = r > 0.5 ? 1.0E-3 : 1.245 - - return prim2cons(SVector(rho, v1, v2, p), equations) + # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" + # Set up polar coordinates + inicenter = SVector(0.0, 0.0) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + phi = atan(y_norm, x_norm) + sin_phi, cos_phi = sincos(phi) + + # Calculate primitive variables + rho = r > 0.5 ? 1.0 : 1.1691 + v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi + v2 = r > 0.5 ? 0.0 : 0.1882 * sin_phi + p = r > 0.5 ? 1.0E-3 : 1.245 + + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_blast_wave surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha +volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-2.0, -2.0) -coordinates_max = ( 2.0, 2.0) +coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=10_000) - + initial_refinement_level = 6, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -67,40 +65,39 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_indicator = IndicatorHennemannGassner(semi, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=4, - max_level =6, max_threshold=0.01) + base_level = 4, + max_level = 6, max_threshold = 0.01) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=0.9) +stepsize_callback = StepsizeCallback(cfl = 0.9) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, amr_callback, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_neuralnetwork_cnn.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_neuralnetwork_cnn.jl deleted file mode 100644 index 659788f2f5c..00000000000 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_neuralnetwork_cnn.jl +++ /dev/null @@ -1,109 +0,0 @@ -using Downloads: download -using Flux -using BSON: load -network = joinpath(@__DIR__, "modelcnn-0.964-0.001.bson") -download("https://github.com/trixi-framework/Trixi_IndicatorNeuralNetwork_networks/raw/main/networks/modelcnn-0.964-0.001.bson", network) -model2dcnn = load(network, @__MODULE__)[:model2dcnn] - -using OrdinaryDiffEq -using Trixi - -# This elixir was one of the setups used in the following master thesis: -# - Julia Odenthal (2021) -# Shock capturing with artificial neural networks -# University of Cologne, advisors: Gregor Gassner, Michael Schlottke-Lakemper -# This motivates the particular choice of fluxes, mesh resolution etc. - -############################################################################### -# semidiscretization of the compressible Euler equations - -equations = CompressibleEulerEquations2D(1.4) - -""" - initial_condition_blast_wave(x, t, equations::CompressibleEulerEquations2D) - -A medium 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](https://arxiv.org/abs/2008.12044) -""" -function initial_condition_blast_wave(x, t, equations::CompressibleEulerEquations2D) - # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" - # Set up polar coordinates - inicenter = SVector(0.0, 0.0) - x_norm = x[1] - inicenter[1] - y_norm = x[2] - inicenter[2] - r = sqrt(x_norm^2 + y_norm^2) - phi = atan(y_norm, x_norm) - sin_phi, cos_phi = sincos(phi) - - # Calculate primitive variables - rho = r > 0.5 ? 1.0 : 1.1691 - v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi - v2 = r > 0.5 ? 0.0 : 0.1882 * sin_phi - p = r > 0.5 ? 1.0E-3 : 1.245 - - return prim2cons(SVector(rho, v1, v2, p), equations) -end -initial_condition = initial_condition_blast_wave - -surface_flux = flux_lax_friedrichs -volume_flux = flux_chandrashekar -basis = LobattoLegendreBasis(3) -indicator_sc = IndicatorNeuralNetwork(equations, basis, - indicator_type=NeuralNetworkCNN(), - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - alpha_continuous=true, - alpha_amr=false, - variable=density_pressure, - network=model2dcnn) -volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) -solver = DGSEM(basis, surface_flux, volume_integral) - -coordinates_min = (-2.0, -2.0) -coordinates_max = ( 2.0, 2.0) -mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=10_000) - - -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - - -############################################################################### -# ODE solvers, callbacks etc. - -tspan = (0.0, 12.5) -ode = semidiscretize(semi, tspan) - -summary_callback = SummaryCallback() - -analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) - -alive_callback = AliveCallback(analysis_interval=analysis_interval) - -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) - -stepsize_callback = StepsizeCallback(cfl=0.9) - -callbacks = CallbackSet(summary_callback, - analysis_callback, alive_callback, - save_solution, - stepsize_callback) - - -############################################################################### -# run the simulation - -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); -summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_neuralnetwork_perssonperaire.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_neuralnetwork_perssonperaire.jl deleted file mode 100644 index 3f4862674d2..00000000000 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_neuralnetwork_perssonperaire.jl +++ /dev/null @@ -1,109 +0,0 @@ -using Downloads: download -using Flux -using BSON: load -network = joinpath(@__DIR__, "modelnnpp-0.904-0.0005.bson") -download("https://github.com/trixi-framework/Trixi_IndicatorNeuralNetwork_networks/raw/main/networks/modelnnpp-0.904-0.0005.bson", network) -model2d = load(network, @__MODULE__)[:model2d] - -using OrdinaryDiffEq -using Trixi - -# This elixir was one of the setups used in the following master thesis: -# - Julia Odenthal (2021) -# Shock capturing with artificial neural networks -# University of Cologne, advisors: Gregor Gassner, Michael Schlottke-Lakemper -# This motivates the particular choice of fluxes, mesh resolution etc. - -############################################################################### -# semidiscretization of the compressible Euler equations - -equations = CompressibleEulerEquations2D(1.4) - -""" - initial_condition_blast_wave(x, t, equations::CompressibleEulerEquations2D) - -A medium 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](https://arxiv.org/abs/2008.12044) -""" -function initial_condition_blast_wave(x, t, equations::CompressibleEulerEquations2D) - # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" - # Set up polar coordinates - inicenter = SVector(0.0, 0.0) - x_norm = x[1] - inicenter[1] - y_norm = x[2] - inicenter[2] - r = sqrt(x_norm^2 + y_norm^2) - phi = atan(y_norm, x_norm) - sin_phi, cos_phi = sincos(phi) - - # Calculate primitive variables - rho = r > 0.5 ? 1.0 : 1.1691 - v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi - v2 = r > 0.5 ? 0.0 : 0.1882 * sin_phi - p = r > 0.5 ? 1.0E-3 : 1.245 - - return prim2cons(SVector(rho, v1, v2, p), equations) -end -initial_condition = initial_condition_blast_wave - -surface_flux = flux_lax_friedrichs -volume_flux = flux_chandrashekar -basis = LobattoLegendreBasis(3) -indicator_sc = IndicatorNeuralNetwork(equations, basis, - indicator_type=NeuralNetworkPerssonPeraire(), - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - alpha_continuous=true, - alpha_amr=false, - variable=density_pressure, - network=model2d) -volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) -solver = DGSEM(basis, surface_flux, volume_integral) - -coordinates_min = (-2.0, -2.0) -coordinates_max = ( 2.0, 2.0) -mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=10_000) - - -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - - -############################################################################### -# ODE solvers, callbacks etc. - -tspan = (0.0, 12.5) -ode = semidiscretize(semi, tspan) - -summary_callback = SummaryCallback() - -analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) - -alive_callback = AliveCallback(analysis_interval=analysis_interval) - -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) - -stepsize_callback = StepsizeCallback(cfl=0.9) - -callbacks = CallbackSet(summary_callback, - analysis_callback, alive_callback, - save_solution, - stepsize_callback) - - -############################################################################### -# run the simulation - -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); -summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_neuralnetwork_rayhesthaven.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_neuralnetwork_rayhesthaven.jl deleted file mode 100644 index db2fffacb36..00000000000 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_neuralnetwork_rayhesthaven.jl +++ /dev/null @@ -1,112 +0,0 @@ -using Downloads: download -using Flux -using Random -using BSON: load -network = joinpath(@__DIR__, "modelnnrhs-0.973-0.001.bson") -download("https://github.com/trixi-framework/Trixi_IndicatorNeuralNetwork_networks/raw/main/networks/modelnnrhs-0.973-0.001.bson", network) -model2d = load(network, @__MODULE__)[:model2d] - -using OrdinaryDiffEq -using Trixi - -# This elixir was one of the setups used in the following master thesis: -# - Julia Odenthal (2021) -# Shock capturing with artificial neural networks -# University of Cologne, advisors: Gregor Gassner, Michael Schlottke-Lakemper -# This motivates the particular choice of fluxes, mesh resolution etc. - -############################################################################### -# semidiscretization of the compressible Euler equations - -equations = CompressibleEulerEquations2D(1.4) - -""" - initial_condition_blast_wave(x, t, equations::CompressibleEulerEquations2D) - -A medium 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](https://arxiv.org/abs/2008.12044) -""" -function initial_condition_blast_wave(x, t, equations::CompressibleEulerEquations2D) - # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" - # Set up polar coordinates - inicenter = SVector(0.0, 0.0) - x_norm = x[1] - inicenter[1] - y_norm = x[2] - inicenter[2] - r = sqrt(x_norm^2 + y_norm^2) - phi = atan(y_norm, x_norm) - sin_phi, cos_phi = sincos(phi) - - # Calculate primitive variables - rho = r > 0.5 ? 1.0 : 1.1691 - v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi - v2 = r > 0.5 ? 0.0 : 0.1882 * sin_phi - p = r > 0.5 ? 1.0E-3 : 1.245 - - return prim2cons(SVector(rho, v1, v2, p), equations) -end -initial_condition = initial_condition_blast_wave - -surface_flux = flux_lax_friedrichs -volume_flux = flux_chandrashekar -basis = LobattoLegendreBasis(3) -indicator_sc = IndicatorNeuralNetwork(equations, basis, - indicator_type=NeuralNetworkRayHesthaven(), - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - alpha_continuous=true, - alpha_amr=false, - variable=density_pressure, - network=model2d) -volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) -solver = DGSEM(basis, surface_flux, volume_integral) - -coordinates_min = (-2.0, -2.0) -coordinates_max = ( 2.0, 2.0) -refinement_patches = () # To allow for specifying them via `trixi_include` -mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - refinement_patches=refinement_patches, - n_cells_max=10_000) - - -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - - -############################################################################### -# ODE solvers, callbacks etc. - -tspan = (0.0, 12.5) -ode = semidiscretize(semi, tspan) - -summary_callback = SummaryCallback() - -analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) - -alive_callback = AliveCallback(analysis_interval=analysis_interval) - -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) - -stepsize_callback = StepsizeCallback(cfl=0.9) - -callbacks = CallbackSet(summary_callback, - analysis_callback, alive_callback, - save_solution, - stepsize_callback) - - -############################################################################### -# run the simulation - -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); -summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_pure_fv.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_pure_fv.jl index a0fc9349696..a2392d05e5a 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blast_wave_pure_fv.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_pure_fv.jl @@ -16,40 +16,38 @@ A medium blast wave taken from [arXiv: 2008.12044](https://arxiv.org/abs/2008.12044) """ function initial_condition_blast_wave(x, t, equations::CompressibleEulerEquations2D) - # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" - # Set up polar coordinates - inicenter = SVector(0.0, 0.0) - x_norm = x[1] - inicenter[1] - y_norm = x[2] - inicenter[2] - r = sqrt(x_norm^2 + y_norm^2) - phi = atan(y_norm, x_norm) - sin_phi, cos_phi = sincos(phi) - - # Calculate primitive variables - rho = r > 0.5 ? 1.0 : 1.1691 - v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi - v2 = r > 0.5 ? 0.0 : 0.1882 * sin_phi - p = r > 0.5 ? 1.0E-3 : 1.245 - - return prim2cons(SVector(rho, v1, v2, p), equations) + # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" + # Set up polar coordinates + inicenter = SVector(0.0, 0.0) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + phi = atan(y_norm, x_norm) + sin_phi, cos_phi = sincos(phi) + + # Calculate primitive variables + rho = r > 0.5 ? 1.0 : 1.1691 + v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi + v2 = r > 0.5 ? 0.0 : 0.1882 * sin_phi + p = r > 0.5 ? 1.0E-3 : 1.245 + + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_blast_wave -surface_flux = flux_hllc +surface_flux = flux_hllc basis = LobattoLegendreBasis(3) volume_integral = VolumeIntegralPureLGLFiniteVolume(flux_hllc) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-2.0, -2.0) -coordinates_max = ( 2.0, 2.0) +coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=10_000) - + initial_refinement_level = 6, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -59,27 +57,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.9) +stepsize_callback = StepsizeCallback(cfl = 0.9) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell_nonperiodic.jl b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell_nonperiodic.jl new file mode 100644 index 00000000000..209aa2ae352 --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_euler_blast_wave_sc_subcell_nonperiodic.jl @@ -0,0 +1,93 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations + +equations = CompressibleEulerEquations2D(1.4) + +""" + initial_condition_blast_wave(x, t, equations::CompressibleEulerEquations2D) + +A medium 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](https://arxiv.org/abs/2008.12044) +""" +function initial_condition_blast_wave(x, t, equations::CompressibleEulerEquations2D) + # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> "medium blast wave" + # Set up polar coordinates + inicenter = SVector(0.0, 0.0) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + phi = atan(y_norm, x_norm) + sin_phi, cos_phi = sincos(phi) + + # Calculate primitive variables + rho = r > 0.5 ? 1.0 : 1.1691 + v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi + v2 = r > 0.5 ? 0.0 : 0.1882 * sin_phi + p = r > 0.5 ? 1.0E-3 : 1.245 + + return prim2cons(SVector(rho, v1, v2, p), equations) +end +initial_condition = initial_condition_blast_wave + +boundary_condition = BoundaryConditionDirichlet(initial_condition) + +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +basis = LobattoLegendreBasis(3) +limiter_idp = SubcellLimiterIDP(equations, basis; + local_minmax_variables_cons = ["rho"]) +volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) +solver = DGSEM(basis, surface_flux, volume_integral) + +coordinates_min = (-2.0, -2.0) +coordinates_max = (2.0, 2.0) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level = 6, + n_cells_max = 10_000, + periodicity = false) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_condition) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 2.0) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) + +stepsize_callback = StepsizeCallback(cfl = 0.3) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + save_solution, + stepsize_callback) + +############################################################################### +# run the simulation + +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors = false)) + +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); +summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_blob_amr.jl b/examples/tree_2d_dgsem/elixir_euler_blob_amr.jl index f4040732667..2b3659017a3 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blob_amr.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blob_amr.jl @@ -4,7 +4,7 @@ using Trixi ############################################################################### # semidiscretization of the compressible Euler equations -gamma = 5/3 +gamma = 5 / 3 equations = CompressibleEulerEquations2D(gamma) """ @@ -16,67 +16,67 @@ The blob test case taken from [arXiv: astro-ph/0610051](https://arxiv.org/abs/astro-ph/0610051) """ function initial_condition_blob(x, t, equations::CompressibleEulerEquations2D) - # blob test case, see Agertz et al. https://arxiv.org/pdf/astro-ph/0610051.pdf - # other reference: https://arxiv.org/pdf/astro-ph/0610051.pdf - # change discontinuity to tanh - # typical domain is rectangular, we change it to a square - # resolution 128^2, 256^2 - # domain size is [-20.0,20.0]^2 - # gamma = 5/3 for this test case - R = 1.0 # radius of the blob - # background density - dens0 = 1.0 - Chi = 10.0 # density contrast - # reference time of characteristic growth of KH instability equal to 1.0 - tau_kh = 1.0 - tau_cr = tau_kh/1.6 # crushing time - # determine background velocity - velx0 = 2*R*sqrt(Chi)/tau_cr - vely0 = 0.0 - Ma0 = 2.7 # background flow Mach number Ma=v/c - c = velx0/Ma0 # sound speed - # use perfect gas assumption to compute background pressure via the sound speed c^2 = gamma * pressure/density - p0 = c*c*dens0/equations.gamma - # initial center of the blob - inicenter = [-15,0] - x_rel = x-inicenter - r = sqrt(x_rel[1]^2 + x_rel[2]^2) - # steepness of the tanh transition zone - slope = 2 - # density blob - dens = dens0 + (Chi-1) * 0.5*(1+(tanh(slope*(r+R)) - (tanh(slope*(r-R)) + 1))) - # velocity blob is zero - velx = velx0 - velx0 * 0.5*(1+(tanh(slope*(r+R)) - (tanh(slope*(r-R)) + 1))) - return prim2cons(SVector(dens, velx, vely0, p0), equations) + # blob test case, see Agertz et al. https://arxiv.org/pdf/astro-ph/0610051.pdf + # other reference: https://arxiv.org/pdf/astro-ph/0610051.pdf + # change discontinuity to tanh + # typical domain is rectangular, we change it to a square + # resolution 128^2, 256^2 + # domain size is [-20.0,20.0]^2 + # gamma = 5/3 for this test case + R = 1.0 # radius of the blob + # background density + dens0 = 1.0 + Chi = 10.0 # density contrast + # reference time of characteristic growth of KH instability equal to 1.0 + tau_kh = 1.0 + tau_cr = tau_kh / 1.6 # crushing time + # determine background velocity + velx0 = 2 * R * sqrt(Chi) / tau_cr + vely0 = 0.0 + Ma0 = 2.7 # background flow Mach number Ma=v/c + c = velx0 / Ma0 # sound speed + # use perfect gas assumption to compute background pressure via the sound speed c^2 = gamma * pressure/density + p0 = c * c * dens0 / equations.gamma + # initial center of the blob + inicenter = [-15, 0] + x_rel = x - inicenter + r = sqrt(x_rel[1]^2 + x_rel[2]^2) + # steepness of the tanh transition zone + slope = 2 + # density blob + dens = dens0 + + (Chi - 1) * 0.5 * (1 + (tanh(slope * (r + R)) - (tanh(slope * (r - R)) + 1))) + # velocity blob is zero + velx = velx0 - velx0 * 0.5 * (1 + (tanh(slope * (r + R)) - (tanh(slope * (r - R)) + 1))) + return prim2cons(SVector(dens, velx, vely0, p0), equations) end initial_condition = initial_condition_blob surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha +volume_flux = flux_ranocha basis = LobattoLegendreBasis(4) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.4, - alpha_min=0.0001, - alpha_smooth=true, - variable=pressure) + alpha_max = 0.4, + alpha_min = 0.0001, + alpha_smooth = true, + variable = pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-20.0, -20.0) -coordinates_max = ( 20.0, 20.0) +coordinates_max = (20.0, 20.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=100_000,) + initial_refinement_level = 6, + n_cells_max = 100_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -86,42 +86,41 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_indicator = IndicatorHennemannGassner(semi, - alpha_max=1.0, - alpha_min=0.0001, - alpha_smooth=false, - variable=Trixi.density) + alpha_max = 1.0, + alpha_min = 0.0001, + alpha_smooth = false, + variable = Trixi.density) amr_controller = ControllerThreeLevelCombined(semi, amr_indicator, indicator_sc, - base_level=4, - med_level =0, med_threshold=0.0003, # med_level = current level - max_level =7, max_threshold=0.003, - max_threshold_secondary=indicator_sc.alpha_max) + base_level = 4, + med_level = 0, med_threshold = 0.0003, # med_level = current level + max_level = 7, max_threshold = 0.003, + max_threshold_secondary = indicator_sc.alpha_max) amr_callback = AMRCallback(semi, amr_controller, - interval=1, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 1, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=0.25) +stepsize_callback = StepsizeCallback(cfl = 0.25) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, amr_callback, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_blob_mortar.jl b/examples/tree_2d_dgsem/elixir_euler_blob_mortar.jl index 5b7365f860f..8bd5db00c9a 100644 --- a/examples/tree_2d_dgsem/elixir_euler_blob_mortar.jl +++ b/examples/tree_2d_dgsem/elixir_euler_blob_mortar.jl @@ -4,7 +4,7 @@ using Trixi ############################################################################### # semidiscretization of the compressible Euler equations -gamma = 5/3 +gamma = 5 / 3 equations = CompressibleEulerEquations2D(gamma) """ @@ -16,71 +16,71 @@ The blob test case taken from [arXiv: astro-ph/0610051](https://arxiv.org/abs/astro-ph/0610051) """ function initial_condition_blob(x, t, equations::CompressibleEulerEquations2D) - # blob test case, see Agertz et al. https://arxiv.org/pdf/astro-ph/0610051.pdf - # other reference: https://arxiv.org/pdf/astro-ph/0610051.pdf - # change discontinuity to tanh - # typical domain is rectangular, we change it to a square - # resolution 128^2, 256^2 - # domain size is [-20.0,20.0]^2 - # gamma = 5/3 for this test case - R = 1.0 # radius of the blob - # background density - dens0 = 1.0 - Chi = 10.0 # density contrast - # reference time of characteristic growth of KH instability equal to 1.0 - tau_kh = 1.0 - tau_cr = tau_kh/1.6 # crushing time - # determine background velocity - velx0 = 2*R*sqrt(Chi)/tau_cr - vely0 = 0.0 - Ma0 = 2.7 # background flow Mach number Ma=v/c - c = velx0/Ma0 # sound speed - # use perfect gas assumption to compute background pressure via the sound speed c^2 = gamma * pressure/density - p0 = c*c*dens0/equations.gamma - # initial center of the blob - inicenter = [-15,0] - x_rel = x-inicenter - r = sqrt(x_rel[1]^2 + x_rel[2]^2) - # steepness of the tanh transition zone - slope = 2 - # density blob - dens = dens0 + (Chi-1) * 0.5*(1+(tanh(slope*(r+R)) - (tanh(slope*(r-R)) + 1))) - # velocity blob is zero - velx = velx0 - velx0 * 0.5*(1+(tanh(slope*(r+R)) - (tanh(slope*(r-R)) + 1))) - return prim2cons(SVector(dens, velx, vely0, p0), equations) + # blob test case, see Agertz et al. https://arxiv.org/pdf/astro-ph/0610051.pdf + # other reference: https://arxiv.org/pdf/astro-ph/0610051.pdf + # change discontinuity to tanh + # typical domain is rectangular, we change it to a square + # resolution 128^2, 256^2 + # domain size is [-20.0,20.0]^2 + # gamma = 5/3 for this test case + R = 1.0 # radius of the blob + # background density + dens0 = 1.0 + Chi = 10.0 # density contrast + # reference time of characteristic growth of KH instability equal to 1.0 + tau_kh = 1.0 + tau_cr = tau_kh / 1.6 # crushing time + # determine background velocity + velx0 = 2 * R * sqrt(Chi) / tau_cr + vely0 = 0.0 + Ma0 = 2.7 # background flow Mach number Ma=v/c + c = velx0 / Ma0 # sound speed + # use perfect gas assumption to compute background pressure via the sound speed c^2 = gamma * pressure/density + p0 = c * c * dens0 / equations.gamma + # initial center of the blob + inicenter = [-15, 0] + x_rel = x - inicenter + r = sqrt(x_rel[1]^2 + x_rel[2]^2) + # steepness of the tanh transition zone + slope = 2 + # density blob + dens = dens0 + + (Chi - 1) * 0.5 * (1 + (tanh(slope * (r + R)) - (tanh(slope * (r - R)) + 1))) + # velocity blob is zero + velx = velx0 - velx0 * 0.5 * (1 + (tanh(slope * (r + R)) - (tanh(slope * (r - R)) + 1))) + return prim2cons(SVector(dens, velx, vely0, p0), equations) end initial_condition = initial_condition_blob surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha +volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.05, - alpha_min=0.0001, - alpha_smooth=true, - variable=pressure) + alpha_max = 0.05, + alpha_min = 0.0001, + alpha_smooth = true, + variable = pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-32.0, -32.0) -coordinates_max = ( 32.0, 32.0) -refinement_patches = ( - (type="box", coordinates_min=(-40.0, -5.0), coordinates_max=(40.0, 5.0)), - (type="box", coordinates_min=(-40.0, -5.0), coordinates_max=(40.0, 5.0)), -) +coordinates_max = (32.0, 32.0) +refinement_patches = ((type = "box", coordinates_min = (-40.0, -5.0), + coordinates_max = (40.0, 5.0)), + (type = "box", coordinates_min = (-40.0, -5.0), + coordinates_max = (40.0, 5.0))) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - refinement_patches=refinement_patches, - n_cells_max=100_000,) + initial_refinement_level = 4, + refinement_patches = refinement_patches, + n_cells_max = 100_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -90,27 +90,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.7) +stepsize_callback = StepsizeCallback(cfl = 0.7) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_colliding_flow.jl b/examples/tree_2d_dgsem/elixir_euler_colliding_flow.jl index cb2a5b16816..984ac3ff1f6 100644 --- a/examples/tree_2d_dgsem/elixir_euler_colliding_flow.jl +++ b/examples/tree_2d_dgsem/elixir_euler_colliding_flow.jl @@ -10,71 +10,71 @@ equations = CompressibleEulerEquations2D(gamma) # This is a hand made colliding flow setup without reference. Features Mach=70 inflow from both # sides, with relative low temperature, such that pressure keeps relatively small # Computed with gamma close to 1, to simulate isothermal gas -function initial_condition_colliding_flow_astro(x, t, equations::CompressibleEulerEquations2D) - # change discontinuity to tanh - # resolution 128^2 elements (refined close to the interface) and polydeg=3 (total of 512^2 DOF) - # domain size is [-64,+64]^2 - @unpack gamma = equations - # the quantities are chosen such, that they are as close as possible to the astro examples - # keep in mind, that in the astro example, the physical units are weird (parsec, mega years, ...) - rho = 0.0247 - c = 0.2 - p = c^2 / gamma * rho - vel = 13.907432274789372 - slope = 1.0 - v1 = -vel*tanh(slope * x[1]) - # add small initial disturbance to the field, but only close to the interface - if abs(x[1]) < 10 - v1 = v1 * (1 + 0.01 * sin(pi * x[2])) - end - v2 = 0.0 - return prim2cons(SVector(rho, v1, v2, p), equations) +function initial_condition_colliding_flow_astro(x, t, + equations::CompressibleEulerEquations2D) + # change discontinuity to tanh + # resolution 128^2 elements (refined close to the interface) and polydeg=3 (total of 512^2 DOF) + # domain size is [-64,+64]^2 + @unpack gamma = equations + # the quantities are chosen such, that they are as close as possible to the astro examples + # keep in mind, that in the astro example, the physical units are weird (parsec, mega years, ...) + rho = 0.0247 + c = 0.2 + p = c^2 / gamma * rho + vel = 13.907432274789372 + slope = 1.0 + v1 = -vel * tanh(slope * x[1]) + # add small initial disturbance to the field, but only close to the interface + if abs(x[1]) < 10 + v1 = v1 * (1 + 0.01 * sin(pi * x[2])) + end + v2 = 0.0 + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_colliding_flow_astro - -boundary_conditions = ( - x_neg=BoundaryConditionDirichlet(initial_condition_colliding_flow_astro), - x_pos=BoundaryConditionDirichlet(initial_condition_colliding_flow_astro), - y_neg=boundary_condition_periodic, - y_pos=boundary_condition_periodic, - ) - - +boundary_conditions = (x_neg = BoundaryConditionDirichlet(initial_condition_colliding_flow_astro), + x_pos = BoundaryConditionDirichlet(initial_condition_colliding_flow_astro), + y_neg = boundary_condition_periodic, + y_pos = boundary_condition_periodic) surface_flux = flux_lax_friedrichs # HLLC needs more shock capturing (alpha_max) -volume_flux = flux_ranocha # works with Chandrashekar flux as well +volume_flux = flux_ranocha # works with Chandrashekar flux as well polydeg = 3 basis = LobattoLegendreBasis(polydeg) # shock capturing necessary for this tough example, however alpha_max = 0.5 is fine indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.0001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.0001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-64.0, -64.0) -coordinates_max = ( 64.0, 64.0) +coordinates_max = (64.0, 64.0) # only refinement in a patch. Needs x=-17/+17 to trigger refinement due to coarse base mesh -refinement_patches = ( - (type="box", coordinates_min=(-17, -64), coordinates_max=(17, 64)), - (type="box", coordinates_min=(-17, -64), coordinates_max=(17, 64)), - (type="box", coordinates_min=(-17, -64), coordinates_max=(17, 64)), - (type="box", coordinates_min=(-17, -64), coordinates_max=(17, 64)), - #(type="box", coordinates_min=(-17, -64), coordinates_max=(17, 64)), # very high resolution, takes about 1000s on 2 cores -) +refinement_patches = ((type = "box", coordinates_min = (-17, -64), + coordinates_max = (17, 64)), + (type = "box", coordinates_min = (-17, -64), + coordinates_max = (17, 64)), + (type = "box", coordinates_min = (-17, -64), + coordinates_max = (17, 64)), + (type = "box", coordinates_min = (-17, -64), + coordinates_max = (17, 64)) + #(type="box", coordinates_min=(-17, -64), coordinates_max=(17, 64)), # very high resolution, takes about 1000s on 2 cores + ) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - refinement_patches=refinement_patches, - periodicity=(false,true), - n_cells_max=100_000) -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, boundary_conditions=boundary_conditions) + initial_refinement_level = 3, + refinement_patches = refinement_patches, + periodicity = (false, true), + n_cells_max = 100_000) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -85,26 +85,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) callbacks = CallbackSet(summary_callback, - analysis_callback, alive_callback, + analysis_callback, alive_callback, save_solution) # positivity limiter necessary for this tough example -stage_limiter! = PositivityPreservingLimiterZhangShu(thresholds=(5.0e-6, 5.0e-6), - variables=(Trixi.density, pressure)) +stage_limiter! = PositivityPreservingLimiterZhangShu(thresholds = (5.0e-6, 5.0e-6), + variables = (Trixi.density, pressure)) ############################################################################### # run the simulation # use adaptive time stepping based on error estimates, time step roughly dt = 5e-3 sol = solve(ode, SSPRK43(stage_limiter!); - ode_default_options()..., callback=callbacks); + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_colliding_flow_amr.jl b/examples/tree_2d_dgsem/elixir_euler_colliding_flow_amr.jl index 21de07147ca..a9eb671929f 100644 --- a/examples/tree_2d_dgsem/elixir_euler_colliding_flow_amr.jl +++ b/examples/tree_2d_dgsem/elixir_euler_colliding_flow_amr.jl @@ -10,62 +10,59 @@ equations = CompressibleEulerEquations2D(gamma) # This is a hand made colliding flow setup without reference. Features Mach=70 inflow from both # sides, with relative low temperature, such that pressure keeps relatively small # Computed with gamma close to 1, to simulate isothermal gas -function initial_condition_colliding_flow_astro(x, t, equations::CompressibleEulerEquations2D) - # change discontinuity to tanh - # resolution 128^2 elements (refined close to the interface) and polydeg=3 (total of 512^2 DOF) - # domain size is [-64,+64]^2 - @unpack gamma = equations - # the quantities are chosen such, that they are as close as possible to the astro examples - # keep in mind, that in the astro example, the physical units are weird (parsec, mega years, ...) - rho = 0.0247 - c = 0.2 - p = c^2 / gamma * rho - vel = 13.907432274789372 - slope = 1.0 - v1 = -vel*tanh(slope * x[1]) - # add small initial disturbance to the field, but only close to the interface - if abs(x[1]) < 10 - v1 = v1 * (1 + 0.01 * sin(pi*x[2])) - end - v2 = 0.0 - return prim2cons(SVector(rho, v1, v2, p), equations) +function initial_condition_colliding_flow_astro(x, t, + equations::CompressibleEulerEquations2D) + # change discontinuity to tanh + # resolution 128^2 elements (refined close to the interface) and polydeg=3 (total of 512^2 DOF) + # domain size is [-64,+64]^2 + @unpack gamma = equations + # the quantities are chosen such, that they are as close as possible to the astro examples + # keep in mind, that in the astro example, the physical units are weird (parsec, mega years, ...) + rho = 0.0247 + c = 0.2 + p = c^2 / gamma * rho + vel = 13.907432274789372 + slope = 1.0 + v1 = -vel * tanh(slope * x[1]) + # add small initial disturbance to the field, but only close to the interface + if abs(x[1]) < 10 + v1 = v1 * (1 + 0.01 * sin(pi * x[2])) + end + v2 = 0.0 + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_colliding_flow_astro - -boundary_conditions = ( - x_neg=BoundaryConditionDirichlet(initial_condition_colliding_flow_astro), - x_pos=BoundaryConditionDirichlet(initial_condition_colliding_flow_astro), - y_neg=boundary_condition_periodic, - y_pos=boundary_condition_periodic, - ) - - +boundary_conditions = (x_neg = BoundaryConditionDirichlet(initial_condition_colliding_flow_astro), + x_pos = BoundaryConditionDirichlet(initial_condition_colliding_flow_astro), + y_neg = boundary_condition_periodic, + y_pos = boundary_condition_periodic) surface_flux = flux_lax_friedrichs # HLLC needs more shock capturing (alpha_max) -volume_flux = flux_ranocha # works with Chandrashekar flux as well +volume_flux = flux_ranocha # works with Chandrashekar flux as well polydeg = 3 basis = LobattoLegendreBasis(polydeg) # shock capturing necessary for this tough example, however alpha_max = 0.5 is fine indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.0001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.0001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-64.0, -64.0) -coordinates_max = ( 64.0, 64.0) +coordinates_max = (64.0, 64.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - periodicity=(false,true), - n_cells_max=100_000) -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, boundary_conditions=boundary_conditions) + initial_refinement_level = 4, + periodicity = (false, true), + n_cells_max = 100_000) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -76,44 +73,44 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) # Simulation also feasible without AMR: AMR reduces CPU time by a factor of about 2 amr_indicator = IndicatorHennemannGassner(semi, - alpha_max=1.0, - alpha_min=0.0001, - alpha_smooth=false, - variable=Trixi.density) + alpha_max = 1.0, + alpha_min = 0.0001, + alpha_smooth = false, + variable = Trixi.density) amr_controller = ControllerThreeLevelCombined(semi, amr_indicator, indicator_sc, - base_level=2, - med_level =0, med_threshold=0.0003, # med_level = current level - max_level =8, max_threshold=0.003, - max_threshold_secondary=indicator_sc.alpha_max) + base_level = 2, + med_level = 0, med_threshold = 0.0003, # med_level = current level + max_level = 8, max_threshold = 0.003, + max_threshold_secondary = indicator_sc.alpha_max) amr_callback = AMRCallback(semi, amr_controller, - interval=1, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 1, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) callbacks = CallbackSet(summary_callback, - analysis_callback, alive_callback, + analysis_callback, alive_callback, amr_callback, save_solution) # positivity limiter necessary for this tough example -stage_limiter! = PositivityPreservingLimiterZhangShu(thresholds=(5.0e-6, 5.0e-6), - variables=(Trixi.density, pressure)) +stage_limiter! = PositivityPreservingLimiterZhangShu(thresholds = (5.0e-6, 5.0e-6), + variables = (Trixi.density, pressure)) ############################################################################### # run the simulation # use adaptive time stepping based on error estimates, time step roughly dt = 5e-3 sol = solve(ode, SSPRK43(stage_limiter!); - ode_default_options()..., callback=callbacks); + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_convergence_pure_fv.jl b/examples/tree_2d_dgsem/elixir_euler_convergence_pure_fv.jl index 89d7422cfe6..96184b5ba47 100644 --- a/examples/tree_2d_dgsem/elixir_euler_convergence_pure_fv.jl +++ b/examples/tree_2d_dgsem/elixir_euler_convergence_pure_fv.jl @@ -18,13 +18,11 @@ solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (0.0, 0.0) coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) - + initial_refinement_level = 4, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -35,16 +33,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -54,7 +52,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_density_wave.jl b/examples/tree_2d_dgsem/elixir_euler_density_wave.jl index a5e9d30e389..0f9e232fa14 100644 --- a/examples/tree_2d_dgsem/elixir_euler_density_wave.jl +++ b/examples/tree_2d_dgsem/elixir_euler_density_wave.jl @@ -9,18 +9,16 @@ equations = CompressibleEulerEquations2D(gamma) initial_condition = initial_condition_density_wave -solver = DGSEM(polydeg=5, surface_flux=flux_central) +solver = DGSEM(polydeg = 5, surface_flux = flux_central) coordinates_min = (-1.0, -1.0) -coordinates_max = ( 1.0, 1.0) +coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=30_000) - + initial_refinement_level = 2, + n_cells_max = 30_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -30,27 +28,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_ec.jl b/examples/tree_2d_dgsem/elixir_euler_ec.jl index 88f65c3d689..e634a383cdf 100644 --- a/examples/tree_2d_dgsem/elixir_euler_ec.jl +++ b/examples/tree_2d_dgsem/elixir_euler_ec.jl @@ -9,20 +9,18 @@ equations = CompressibleEulerEquations2D(1.4) initial_condition = initial_condition_weak_blast_wave volume_flux = flux_ranocha -solver = DGSEM(polydeg=3, surface_flux=flux_ranocha, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_ranocha, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-2.0, -2.0) -coordinates_max = ( 2.0, 2.0) +coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=5, - n_cells_max=10_000, - periodicity=true) - + initial_refinement_level = 5, + n_cells_max = 10_000, + periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_condition_periodic) - + boundary_conditions = boundary_condition_periodic) ############################################################################### # ODE solvers, callbacks etc. @@ -33,27 +31,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability.jl index 4fdedf516ef..5e6b1e0cc0d 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability.jl @@ -16,40 +16,41 @@ A version of the classical Kelvin-Helmholtz instability based on of the Euler Equations [arXiv: 2102.06017](https://arxiv.org/abs/2102.06017) """ -function initial_condition_kelvin_helmholtz_instability(x, t, equations::CompressibleEulerEquations2D) - # change discontinuity to tanh - # typical resolution 128^2, 256^2 - # domain size is [-1,+1]^2 - slope = 15 - amplitude = 0.02 - B = tanh(slope * x[2] + 7.5) - tanh(slope * x[2] - 7.5) - rho = 0.5 + 0.75 * B - v1 = 0.5 * (B - 1) - v2 = 0.1 * sin(2 * pi * x[1]) - p = 1.0 - return prim2cons(SVector(rho, v1, v2, p), equations) +function initial_condition_kelvin_helmholtz_instability(x, t, + equations::CompressibleEulerEquations2D) + # change discontinuity to tanh + # typical resolution 128^2, 256^2 + # domain size is [-1,+1]^2 + slope = 15 + amplitude = 0.02 + B = tanh(slope * x[2] + 7.5) - tanh(slope * x[2] - 7.5) + rho = 0.5 + 0.75 * B + v1 = 0.5 * (B - 1) + v2 = 0.1 * sin(2 * pi * x[1]) + p = 1.0 + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_kelvin_helmholtz_instability surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha +volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.002, - alpha_min=0.0001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.002, + alpha_min = 0.0001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-1.0, -1.0) -coordinates_max = ( 1.0, 1.0) +coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=5, - n_cells_max=100_000) + initial_refinement_level = 5, + n_cells_max = 100_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) ############################################################################### @@ -61,27 +62,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=20, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 20, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.3) +stepsize_callback = StepsizeCallback(cfl = 1.3) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_amr.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_amr.jl index b8927c3fd6b..5c237835cc5 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_amr.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_amr.jl @@ -16,45 +16,44 @@ A version of the classical Kelvin-Helmholtz instability based on of the Euler Equations [arXiv: 2102.06017](https://arxiv.org/abs/2102.06017) """ -function initial_condition_kelvin_helmholtz_instability(x, t, equations::CompressibleEulerEquations2D) - # change discontinuity to tanh - # typical resolution 128^2, 256^2 - # domain size is [-1,+1]^2 - slope = 15 - amplitude = 0.02 - B = tanh(slope * x[2] + 7.5) - tanh(slope * x[2] - 7.5) - rho = 0.5 + 0.75 * B - v1 = 0.5 * (B - 1) - v2 = 0.1 * sin(2 * pi * x[1]) - p = 1.0 - return prim2cons(SVector(rho, v1, v2, p), equations) +function initial_condition_kelvin_helmholtz_instability(x, t, + equations::CompressibleEulerEquations2D) + # change discontinuity to tanh + # typical resolution 128^2, 256^2 + # domain size is [-1,+1]^2 + slope = 15 + amplitude = 0.02 + B = tanh(slope * x[2] + 7.5) - tanh(slope * x[2] - 7.5) + rho = 0.5 + 0.75 * B + v1 = 0.5 * (B - 1) + v2 = 0.1 * sin(2 * pi * x[1]) + p = 1.0 + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_kelvin_helmholtz_instability surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha +volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.002, - alpha_min=0.0001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.002, + alpha_min = 0.0001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-1.0, -1.0) -coordinates_max = ( 1.0, 1.0) +coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=5, - n_cells_max=100_000) - + initial_refinement_level = 5, + n_cells_max = 100_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -64,41 +63,40 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_indicator = IndicatorHennemannGassner(semi, - alpha_max=1.0, - alpha_min=0.0001, - alpha_smooth=false, - variable=Trixi.density) + alpha_max = 1.0, + alpha_min = 0.0001, + alpha_smooth = false, + variable = Trixi.density) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=4, - med_level=0, med_threshold=0.0003, # med_level = current level - max_level=6, max_threshold=0.003) + base_level = 4, + med_level = 0, med_threshold = 0.0003, # med_level = current level + max_level = 6, max_threshold = 0.003) amr_callback = AMRCallback(semi, amr_controller, - interval=1, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 1, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=1.3) +stepsize_callback = StepsizeCallback(cfl = 1.3) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, amr_callback, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_amr_neuralnetwork_perssonperaire.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_amr_neuralnetwork_perssonperaire.jl deleted file mode 100644 index 952fa372696..00000000000 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_amr_neuralnetwork_perssonperaire.jl +++ /dev/null @@ -1,130 +0,0 @@ -using Downloads: download -using Flux -using BSON: load -network = joinpath(@__DIR__, "modelnnpp-0.904-0.0005.bson") -download("https://github.com/trixi-framework/Trixi_IndicatorNeuralNetwork_networks/raw/main/networks/modelnnpp-0.904-0.0005.bson", network) -model2d = load(network, @__MODULE__)[:model2d] - -using Random: seed! -seed!(0) - -using OrdinaryDiffEq -using Trixi - -# This elixir was one of the setups used in the following master thesis: -# - Julia Odenthal (2021) -# Shock capturing with artificial neural networks -# University of Cologne, advisors: Gregor Gassner, Michael Schlottke-Lakemper -# This motivates the particular choice of fluxes, mesh resolution etc. - -############################################################################### -# semidiscretization of the compressible Euler equations -gamma = 1.4 -equations = CompressibleEulerEquations2D(gamma) - -""" - initial_condition_kelvin_helmholtz_instability(x, t, equations::CompressibleEulerEquations2D) - -A version of the classical Kelvin-Helmholtz instability based on -https://rsaa.anu.edu.au/research/established-projects/fyris/2-d-kelvin-helmholtz-test. -""" -function initial_condition_kelvin_helmholtz_instability(x, t, equations::CompressibleEulerEquations2D) - # change discontinuity to tanh - # typical resolution 128^2, 256^2 - # domain size is [-0.5,0.5]^2 - dens0 = 1.0 # outside density - dens1 = 2.0 # inside density - velx0 = -0.5 # outside velocity - velx1 = 0.5 # inside velocity - slope = 50 # used for tanh instead of discontinuous initial condition - # pressure equilibrium - p = 2.5 - # y velocity v2 is only white noise - v2 = 0.01*(rand(Float64,1)[1]-0.5) - # density - rho = dens0 + (dens1-dens0) * 0.5*(1+(tanh(slope*(x[2]+0.25)) - (tanh(slope*(x[2]-0.25)) + 1))) - # x velocity is also augmented with noise - v1 = velx0 + (velx1-velx0) * 0.5*(1+(tanh(slope*(x[2]+0.25)) - (tanh(slope*(x[2]-0.25)) + 1)))+0.01*(rand(Float64,1)[1]-0.5) - return prim2cons(SVector(rho, v1, v2, p), equations) -end -initial_condition = initial_condition_kelvin_helmholtz_instability - -surface_flux = flux_lax_friedrichs -volume_flux = flux_chandrashekar -polydeg = 3 -basis = LobattoLegendreBasis(polydeg) -indicator_sc = IndicatorNeuralNetwork(equations, basis, - indicator_type=NeuralNetworkPerssonPeraire(), - alpha_max=0.002, - alpha_min=0.0001, - alpha_smooth=true, - alpha_continuous=true, - alpha_amr=false, - variable=density_pressure, - network=model2d) -volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) -solver = DGSEM(basis, surface_flux, volume_integral) - -coordinates_min = (-0.5, -0.5) -coordinates_max = ( 0.5, 0.5) -mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=5, - n_cells_max=100_000) - - -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - - -############################################################################### -# ODE solvers, callbacks etc. - -tspan = (0.0, 5.0) -ode = semidiscretize(semi, tspan) - -summary_callback = SummaryCallback() - -analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) - -alive_callback = AliveCallback(analysis_interval=analysis_interval) - -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) - -amr_indicator = IndicatorNeuralNetwork(semi, - indicator_type=NeuralNetworkPerssonPeraire(), - alpha_max=1.0, - alpha_min=0.0001, - alpha_smooth=false, - alpha_continuous=true, - alpha_amr=true, - variable=density_pressure, - network=model2d) -amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=4, - med_level=6, med_threshold=0.3, # med_level = current level - max_level=7, max_threshold=0.5) -amr_callback = AMRCallback(semi, amr_controller, - interval=1, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) - -stepsize_callback = StepsizeCallback(cfl=1.3) - -callbacks = CallbackSet(summary_callback, - analysis_callback, alive_callback, - save_solution, - amr_callback, stepsize_callback) - - -############################################################################### -# run the simulation - -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); -summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_fjordholm_etal.jl b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_fjordholm_etal.jl index 8e7484a96d4..5b2b80d84f3 100644 --- a/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_fjordholm_etal.jl +++ b/examples/tree_2d_dgsem/elixir_euler_kelvin_helmholtz_instability_fjordholm_etal.jl @@ -1,7 +1,6 @@ using OrdinaryDiffEq using Trixi - ############################################################################### # semidiscretization of the compressible Euler equations gamma = 1.4 @@ -16,83 +15,86 @@ A version of the classical Kelvin-Helmholtz instability based on solutions for hyperbolic systems of conservation laws [arXiv: 1402.0909](https://arxiv.org/abs/1402.0909) """ -function initial_condition_kelvin_helmholtz_instability_fjordholm_etal(x, t, equations::CompressibleEulerEquations2D) - # typical resolution 128^2, 256^2 - # domain size is [0,+1]^2 - # interface is sharp, but randomly perturbed - # The random numbers used in the initial conditions have been generated as follows: - # - # using StableRNGs - # - # rng = StableRNG(100) - # - # a1 = rand(rng, m) - # a2 = rand(rng, m) - # a1 .= a1 / sum(a1) - # a2 .= a2 / sum(a2) - # b1 = (rand(rng, m) .- 0.5) .* pi - # b2 = (rand(rng, m) .- 0.5) .* pi - - m = 10 - a1 = [0.04457096674422902, 0.03891512410182607, 0.0030191053979293433, 0.0993913172320319, +function initial_condition_kelvin_helmholtz_instability_fjordholm_etal(x, t, + equations::CompressibleEulerEquations2D) + # typical resolution 128^2, 256^2 + # domain size is [0,+1]^2 + # interface is sharp, but randomly perturbed + # The random numbers used in the initial conditions have been generated as follows: + # + # using StableRNGs + # + # rng = StableRNG(100) + # + # a1 = rand(rng, m) + # a2 = rand(rng, m) + # a1 .= a1 / sum(a1) + # a2 .= a2 / sum(a2) + # b1 = (rand(rng, m) .- 0.5) .* pi + # b2 = (rand(rng, m) .- 0.5) .* pi + + m = 10 + a1 = [0.04457096674422902, 0.03891512410182607, 0.0030191053979293433, + 0.0993913172320319, 0.1622302137588842, 0.1831383653456182, 0.11758003014101702, 0.07964318348142958, 0.0863245324711805, 0.18518716132585408] - a2 = [0.061688440856337096, 0.23000237877135882, 0.04453793881833177, 0.19251530387370916, + a2 = [0.061688440856337096, 0.23000237877135882, 0.04453793881833177, + 0.19251530387370916, 0.11107917357941084, 0.05898041974649702, 0.09949312336096268, 0.07022276346006465, 0.10670366489014596, 0.02477679264318211] - b1 = [0.06582340543754152, 0.9857886297001535, 0.8450452205037154, -1.279648120993805, + b1 = [0.06582340543754152, 0.9857886297001535, 0.8450452205037154, -1.279648120993805, 0.45454198915209526, -0.13359370986823993, 0.07062615913363897, -1.0097986278512623, 1.0810669017430343, -0.14207309803877177] - b2 = [-1.1376882185131414, -1.4798197129947765, 0.6139290513283818, -0.3319087388365522, + b2 = [-1.1376882185131414, -1.4798197129947765, 0.6139290513283818, -0.3319087388365522, 0.14633328999192285, -0.06373231463100072, -0.6270101051216724, 0.13941252226261905, -1.0337526453303645, 1.0441408867083155] - Y1 = 0.0 - Y2 = 0.0 - for n = 1:m - Y1 += a1[n] * cos(b1[n] + 2 * n * pi * x[1]) - Y2 += a2[n] * cos(b2[n] + 2 * n * pi * x[1]) - end - - J1 = 0.25 - J2 = 0.75 - epsilon = 0.01 - I1 = J1 + epsilon * Y1 - I2 = J2 + epsilon * Y2 - - if (x[2] > I1) && (x[2] < I2) - rho = 2 - v1 = -0.5 - else - rho = 1 - v1 = 0.5 - end - v2 = 0 - p = 2.5 - - return prim2cons(SVector(rho, v1, v2, p), equations) + Y1 = 0.0 + Y2 = 0.0 + for n in 1:m + Y1 += a1[n] * cos(b1[n] + 2 * n * pi * x[1]) + Y2 += a2[n] * cos(b2[n] + 2 * n * pi * x[1]) + end + + J1 = 0.25 + J2 = 0.75 + epsilon = 0.01 + I1 = J1 + epsilon * Y1 + I2 = J2 + epsilon * Y2 + + if (x[2] > I1) && (x[2] < I2) + rho = 2 + v1 = -0.5 + else + rho = 1 + v1 = 0.5 + end + v2 = 0 + p = 2.5 + + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_kelvin_helmholtz_instability_fjordholm_etal surface_flux = flux_hllc -volume_flux = flux_ranocha +volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.001, - alpha_min=0.0001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.001, + alpha_min = 0.0001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (0.0, 0.0) coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=100_000) + initial_refinement_level = 6, + n_cells_max = 100_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -105,14 +107,14 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 400 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=400, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 400, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -121,5 +123,5 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation sol = solve(ode, SSPRK43(); - ode_default_options()..., callback=callbacks); + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_positivity.jl b/examples/tree_2d_dgsem/elixir_euler_positivity.jl index 4c7dd7eb6cf..6fec4c1bf9b 100644 --- a/examples/tree_2d_dgsem/elixir_euler_positivity.jl +++ b/examples/tree_2d_dgsem/elixir_euler_positivity.jl @@ -14,53 +14,51 @@ The Sedov blast wave setup based on Flash - https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 """ function initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEquations2D) - # Set up polar coordinates - inicenter = SVector(0.0, 0.0) - x_norm = x[1] - inicenter[1] - y_norm = x[2] - inicenter[2] - r = sqrt(x_norm^2 + y_norm^2) - - # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 - r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) - # r0 = 0.5 # = more reasonable setup - E = 1.0 - p0_inner = 3 * (equations.gamma - 1) * E / (3 * pi * r0^2) - p0_outer = 1.0e-5 # = true Sedov setup - # p0_outer = 1.0e-3 # = more reasonable setup - - # Calculate primitive variables - rho = 1.0 - v1 = 0.0 - v2 = 0.0 - p = r > r0 ? p0_outer : p0_inner - - return prim2cons(SVector(rho, v1, v2, p), equations) + # Set up polar coordinates + inicenter = SVector(0.0, 0.0) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + + # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 + r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) + # r0 = 0.5 # = more reasonable setup + E = 1.0 + p0_inner = 3 * (equations.gamma - 1) * E / (3 * pi * r0^2) + p0_outer = 1.0e-5 # = true Sedov setup + # p0_outer = 1.0e-3 # = more reasonable setup + + # Calculate primitive variables + rho = 1.0 + v1 = 0.0 + v2 = 0.0 + p = r > r0 ? p0_outer : p0_inner + + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_sedov_blast_wave surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha +volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-2.0, -2.0) -coordinates_max = ( 2.0, 2.0) +coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=100_000) - + initial_refinement_level = 6, + n_cells_max = 100_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -70,42 +68,40 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 500 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_indicator = IndicatorLöhner(semi, - variable=density_pressure) + variable = density_pressure) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=4, - med_level =0, med_threshold=0.1, # med_level = current level - max_level =6, max_threshold=0.3) + base_level = 4, + med_level = 0, med_threshold = 0.1, # med_level = current level + max_level = 6, max_threshold = 0.3) amr_callback = AMRCallback(semi, amr_controller, - interval=2, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 2, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, amr_callback, stepsize_callback) - -stage_limiter! = PositivityPreservingLimiterZhangShu(thresholds=(5.0e-6, 5.0e-6), - variables=(Trixi.density, pressure)) - +stage_limiter! = PositivityPreservingLimiterZhangShu(thresholds = (5.0e-6, 5.0e-6), + variables = (Trixi.density, pressure)) ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(stage_limiter!, williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(stage_limiter!, williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave.jl index 512e5822374..5b8959b97d1 100644 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave.jl +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave.jl @@ -14,53 +14,51 @@ The Sedov blast wave setup based on Flash - https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 """ function initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEquations2D) - # Set up polar coordinates - inicenter = SVector(0.0, 0.0) - x_norm = x[1] - inicenter[1] - y_norm = x[2] - inicenter[2] - r = sqrt(x_norm^2 + y_norm^2) - - # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 - r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) - # r0 = 0.5 # = more reasonable setup - E = 1.0 - p0_inner = 3 * (equations.gamma - 1) * E / (3 * pi * r0^2) - p0_outer = 1.0e-5 # = true Sedov setup - # p0_outer = 1.0e-3 # = more reasonable setup - - # Calculate primitive variables - rho = 1.0 - v1 = 0.0 - v2 = 0.0 - p = r > r0 ? p0_outer : p0_inner - - return prim2cons(SVector(rho, v1, v2, p), equations) + # Set up polar coordinates + inicenter = SVector(0.0, 0.0) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + + # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 + r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) + # r0 = 0.5 # = more reasonable setup + E = 1.0 + p0_inner = 3 * (equations.gamma - 1) * E / (3 * pi * r0^2) + p0_outer = 1.0e-5 # = true Sedov setup + # p0_outer = 1.0e-3 # = more reasonable setup + + # Calculate primitive variables + rho = 1.0 + v1 = 0.0 + v2 = 0.0 + p = r > r0 ? p0_outer : p0_inner + + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_sedov_blast_wave surface_flux = flux_lax_friedrichs -volume_flux = flux_chandrashekar +volume_flux = flux_chandrashekar basis = LobattoLegendreBasis(3) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-2.0, -2.0) -coordinates_max = ( 2.0, 2.0) +coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=100_000) - + initial_refinement_level = 6, + n_cells_max = 100_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -70,29 +68,29 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_indicator = IndicatorHennemannGassner(semi, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=4, - max_level =6, max_threshold=0.01) + base_level = 4, + max_level = 6, max_threshold = 0.01) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -101,7 +99,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_neuralnetwork_perssonperaire.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_neuralnetwork_perssonperaire.jl deleted file mode 100644 index 5fd32da2e5c..00000000000 --- a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_neuralnetwork_perssonperaire.jl +++ /dev/null @@ -1,127 +0,0 @@ -using Downloads: download -using Flux -using BSON: load -network = joinpath(@__DIR__, "modelnnpp-0.904-0.0005.bson") -download("https://github.com/trixi-framework/Trixi_IndicatorNeuralNetwork_networks/raw/main/networks/modelnnpp-0.904-0.0005.bson", network) -model2d = load(network, @__MODULE__)[:model2d] - -using OrdinaryDiffEq -using Trixi - -# This elixir was one of the setups used in the following master thesis: -# - Julia Odenthal (2021) -# Shock capturing with artificial neural networks -# University of Cologne, advisors: Gregor Gassner, Michael Schlottke-Lakemper -# This motivates the particular choice of fluxes, mesh resolution etc. - -############################################################################### -# semidiscretization of the compressible Euler equations -gamma = 1.4 -equations = CompressibleEulerEquations2D(gamma) - -""" - initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEquations2D) - -The Sedov blast wave setup based on Flash -- https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 -""" -function initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEquations2D) - # Set up polar coordinates - inicenter = SVector(0.0, 0.0) - x_norm = x[1] - inicenter[1] - y_norm = x[2] - inicenter[2] - r = sqrt(x_norm^2 + y_norm^2) - - # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 - r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) - # r0 = 0.5 # = more reasonable setup - E = 1.0 - p0_inner = 3 * (equations.gamma - 1) * E / (3 * pi * r0^2) - p0_outer = 1.0e-5 # = true Sedov setup - # p0_outer = 1.0e-3 # = more reasonable setup - - # Calculate primitive variables - rho = 1.0 - v1 = 0.0 - v2 = 0.0 - p = r > r0 ? p0_outer : p0_inner - - return prim2cons(SVector(rho, v1, v2, p), equations) -end -initial_condition = initial_condition_sedov_blast_wave - -surface_flux = flux_lax_friedrichs -volume_flux = flux_chandrashekar -basis = LobattoLegendreBasis(3) -indicator_sc = IndicatorNeuralNetwork(equations, basis, - indicator_type=NeuralNetworkPerssonPeraire(), - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - alpha_continuous=true, - alpha_amr=false, - variable=density_pressure, - network=model2d) -volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) -solver = DGSEM(basis, surface_flux, volume_integral) - -coordinates_min = (-2.0, -2.0) -coordinates_max = ( 2.0, 2.0) -mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - n_cells_max=100_000) - - -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - - -############################################################################### -# ODE solvers, callbacks etc. - -tspan = (0.0, 12.5) -ode = semidiscretize(semi, tspan) - -summary_callback = SummaryCallback() - -analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) - -alive_callback = AliveCallback(analysis_interval=analysis_interval) - -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) - -amr_indicator = IndicatorNeuralNetwork(semi, - indicator_type=NeuralNetworkPerssonPeraire(), - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - alpha_continuous=true, - alpha_amr=true, - variable=density_pressure, - network=model2d) -amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=4, - max_level =6, max_threshold=0.22) -amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) - -stepsize_callback = StepsizeCallback(cfl=0.9) - -callbacks = CallbackSet(summary_callback, - analysis_callback, alive_callback, - save_solution, - amr_callback, stepsize_callback) -############################################################################### -# run the simulation - -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); -summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl new file mode 100644 index 00000000000..c1ba3d96962 --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_euler_sedov_blast_wave_sc_subcell.jl @@ -0,0 +1,91 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations +gamma = 1.4 +equations = CompressibleEulerEquations2D(gamma) + +""" + initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEquations2D) + +The Sedov blast wave setup based on Flash +- https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 +""" +function initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEquations2D) + # Set up polar coordinates + inicenter = SVector(0.0, 0.0) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + + # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 + r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) + # r0 = 0.5 # = more reasonable setup + E = 1.0 + p0_inner = 3 * (equations.gamma - 1) * E / (3 * pi * r0^2) + p0_outer = 1.0e-5 # = true Sedov setup + # p0_outer = 1.0e-3 # = more reasonable setup + + # Calculate primitive variables + rho = 1.0 + v1 = 0.0 + v2 = 0.0 + p = r > r0 ? p0_outer : p0_inner + + return prim2cons(SVector(rho, v1, v2, p), equations) +end +initial_condition = initial_condition_sedov_blast_wave + +surface_flux = flux_lax_friedrichs +volume_flux = flux_chandrashekar +basis = LobattoLegendreBasis(3) +limiter_idp = SubcellLimiterIDP(equations, basis; + local_minmax_variables_cons = ["rho"]) +volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) +solver = DGSEM(basis, surface_flux, volume_integral) + +coordinates_min = (-2.0, -2.0) +coordinates_max = (2.0, 2.0) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level = 3, + n_cells_max = 100_000) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 3.0) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 1000 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) + +stepsize_callback = StepsizeCallback(cfl = 0.6) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + stepsize_callback, + save_solution) +############################################################################### +# run the simulation + +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors = false)) + +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); +summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_shockcapturing.jl b/examples/tree_2d_dgsem/elixir_euler_shockcapturing.jl index f0a7ed0b953..40f19cbd4e2 100644 --- a/examples/tree_2d_dgsem/elixir_euler_shockcapturing.jl +++ b/examples/tree_2d_dgsem/elixir_euler_shockcapturing.jl @@ -10,28 +10,26 @@ equations = CompressibleEulerEquations2D(1.4) initial_condition = initial_condition_weak_blast_wave surface_flux = flux_lax_friedrichs -volume_flux = flux_shima_etal +volume_flux = flux_shima_etal basis = LobattoLegendreBasis(3) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-2.0, -2.0) -coordinates_max = ( 2.0, 2.0) +coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=5, - n_cells_max=10_000) - + initial_refinement_level = 5, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -41,26 +39,25 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, stepsize_callback, save_solution, analysis_callback, alive_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl index 6b69e4db563..44e63a0872e 100644 --- a/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl +++ b/examples/tree_2d_dgsem/elixir_euler_shockcapturing_subcell.jl @@ -16,45 +16,44 @@ A medium blast wave (modified to lower density and higher pressure) taken from [arXiv: 2008.12044](https://arxiv.org/abs/2008.12044) """ function initial_condition_blast_wave(x, t, equations::CompressibleEulerEquations2D) - # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> modified to lower density, higher pressure - # Set up polar coordinates - inicenter = SVector(0.0, 0.0) - x_norm = x[1] - inicenter[1] - y_norm = x[2] - inicenter[2] - r = sqrt(x_norm^2 + y_norm^2) - phi = atan(y_norm, x_norm) - sin_phi, cos_phi = sincos(phi) - - # Calculate primitive variables "normal" medium blast wave - rho = r > 0.5 ? 0.1 : 0.2691 # rho = r > 0.5 ? 1 : 1.1691 - v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi - v2 = r > 0.5 ? 0.0 : 0.1882 * sin_phi - p = r > 0.5 ? 1.0E-1 : 1.245 # p = r > 0.5 ? 1.0E-3 : 1.245 - - return prim2cons(SVector(rho, v1, v2, p), equations) + # Modified From Hennemann & Gassner JCP paper 2020 (Sec. 6.3) -> modified to lower density, higher pressure + # Set up polar coordinates + inicenter = SVector(0.0, 0.0) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + phi = atan(y_norm, x_norm) + sin_phi, cos_phi = sincos(phi) + + # Calculate primitive variables "normal" medium blast wave + rho = r > 0.5 ? 0.1 : 0.2691 # rho = r > 0.5 ? 1 : 1.1691 + v1 = r > 0.5 ? 0.0 : 0.1882 * cos_phi + v2 = r > 0.5 ? 0.0 : 0.1882 * sin_phi + p = r > 0.5 ? 1.0E-1 : 1.245 # p = r > 0.5 ? 1.0E-3 : 1.245 + + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_blast_wave surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha +volume_flux = flux_ranocha basis = LobattoLegendreBasis(3) limiter_idp = SubcellLimiterIDP(equations, basis; - positivity_variables_cons=[1], - positivity_correction_factor=0.5) + positivity_variables_cons = ["rho"], + positivity_correction_factor = 0.5) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-2.0, -2.0) -coordinates_max = ( 2.0, 2.0) +coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=5, - n_cells_max=100_000) + initial_refinement_level = 5, + n_cells_max = 100_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -64,29 +63,28 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(dt = 0.1, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.6) +stepsize_callback = StepsizeCallback(cfl = 0.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -stage_callbacks = (SubcellLimiterIDPCorrection(),) +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors = false)) -sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_source_terms.jl b/examples/tree_2d_dgsem/elixir_euler_source_terms.jl index 36d93147289..ec230145537 100644 --- a/examples/tree_2d_dgsem/elixir_euler_source_terms.jl +++ b/examples/tree_2d_dgsem/elixir_euler_source_terms.jl @@ -8,18 +8,16 @@ using Trixi equations = CompressibleEulerEquations2D(1.4) initial_condition = initial_condition_convergence_test -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (0.0, 0.0) coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) - + initial_refinement_level = 4, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -30,16 +28,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -49,7 +47,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_source_terms_amr_refine_coarsen.jl b/examples/tree_2d_dgsem/elixir_euler_source_terms_amr_refine_coarsen.jl index 231486b11c9..28ab4cec1d3 100644 --- a/examples/tree_2d_dgsem/elixir_euler_source_terms_amr_refine_coarsen.jl +++ b/examples/tree_2d_dgsem/elixir_euler_source_terms_amr_refine_coarsen.jl @@ -10,60 +10,57 @@ module TrixiExtensionEulerAMR using Trixi -struct IndicatorRefineCoarsen{Cache<:NamedTuple} <: Trixi.AbstractIndicator - cache::Cache +struct IndicatorRefineCoarsen{Cache <: NamedTuple} <: Trixi.AbstractIndicator + cache::Cache end function IndicatorRefineCoarsen(semi) - basis = semi.solver.basis - alpha = Vector{real(basis)}() - cache = (; semi.mesh, alpha) + basis = semi.solver.basis + alpha = Vector{real(basis)}() + cache = (; semi.mesh, alpha) - return IndicatorRefineCoarsen{typeof(cache)}(cache) + return IndicatorRefineCoarsen{typeof(cache)}(cache) end -function (indicator::IndicatorRefineCoarsen)(u::AbstractArray{<:Any,4}, +function (indicator::IndicatorRefineCoarsen)(u::AbstractArray{<:Any, 4}, mesh, equations, dg, cache; t, kwargs...) - alpha = indicator.cache.alpha - resize!(alpha, nelements(dg, cache)) - - if t >= 0.7 && t < 1.0 - # Refine to max level - alpha .= 1.0 - elseif t >= 1.0 - # Coarsen to base level - alpha .= -1.0 - else - alpha .= 0.0 - end - - return alpha + alpha = indicator.cache.alpha + resize!(alpha, nelements(dg, cache)) + + if t >= 0.7 && t < 1.0 + # Refine to max level + alpha .= 1.0 + elseif t >= 1.0 + # Coarsen to base level + alpha .= -1.0 + else + alpha .= 0.0 + end + + return alpha end end # module TrixiExtensionEulerAMR import .TrixiExtensionEulerAMR - ############################################################################### # semidiscretization of the compressible Euler equations equations = CompressibleEulerEquations2D(1.4) initial_condition = initial_condition_convergence_test -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (0.0, 0.0) coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=10_000) - + initial_refinement_level = 3, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -74,25 +71,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -amr_controller = ControllerThreeLevel(semi, TrixiExtensionEulerAMR.IndicatorRefineCoarsen(semi), - base_level=3, max_level=6, - med_threshold=0.1, max_threshold=0.6) +amr_controller = ControllerThreeLevel(semi, + TrixiExtensionEulerAMR.IndicatorRefineCoarsen(semi), + base_level = 3, max_level = 6, + med_threshold = 0.1, max_threshold = 0.6) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -102,7 +100,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_source_terms_nonperiodic.jl b/examples/tree_2d_dgsem/elixir_euler_source_terms_nonperiodic.jl index 9826a53d3d5..05ed7ba78cc 100644 --- a/examples/tree_2d_dgsem/elixir_euler_source_terms_nonperiodic.jl +++ b/examples/tree_2d_dgsem/elixir_euler_source_terms_nonperiodic.jl @@ -12,26 +12,23 @@ initial_condition = initial_condition_convergence_test # you can either use a single function to impose the BCs weakly in all # 2*ndims == 4 directions or you can pass a tuple containing BCs for each direction boundary_condition = BoundaryConditionDirichlet(initial_condition) -boundary_conditions = (x_neg=boundary_condition, - x_pos=boundary_condition, - y_neg=boundary_condition, - y_pos=boundary_condition,) - -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +boundary_conditions = (x_neg = boundary_condition, + x_pos = boundary_condition, + y_neg = boundary_condition, + y_pos = boundary_condition) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (0.0, 0.0) coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000, - periodicity=false) - + initial_refinement_level = 4, + n_cells_max = 10_000, + periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test, - boundary_conditions=boundary_conditions) - + source_terms = source_terms_convergence_test, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -42,19 +39,19 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -63,7 +60,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_vortex.jl b/examples/tree_2d_dgsem/elixir_euler_vortex.jl index 14e46ce7540..c87d6f49ba8 100644 --- a/examples/tree_2d_dgsem/elixir_euler_vortex.jl +++ b/examples/tree_2d_dgsem/elixir_euler_vortex.jl @@ -17,46 +17,45 @@ The classical isentropic vortex test case of [NASA/CR-97-206253](https://ntrs.nasa.gov/citations/19980007543) """ function initial_condition_isentropic_vortex(x, t, equations::CompressibleEulerEquations2D) - # needs appropriate mesh size, e.g. [-10,-10]x[10,10] - # for error convergence: make sure that the end time is such that the vortex is back at the initial state!! - # for the current velocity and domain size: t_end should be a multiple of 20s - # initial center of the vortex - inicenter = SVector(0.0, 0.0) - # size and strength of the vortex - iniamplitude = 5.0 - # base flow - rho = 1.0 - v1 = 1.0 - v2 = 1.0 - vel = SVector(v1, v2) - p = 25.0 - rt = p / rho # ideal gas equation - t_loc = 0.0 - cent = inicenter + vel*t_loc # advection of center - # ATTENTION: handle periodic BC, but only for v1 = v2 = 1.0 (!!!!) - cent = x - cent # distance to center point - # cent = cross(iniaxis, cent) # distance to axis, tangent vector, length r - # cross product with iniaxis = [0, 0, 1] - cent = SVector(-cent[2], cent[1]) - r2 = cent[1]^2 + cent[2]^2 - du = iniamplitude / (2*π) * exp(0.5 * (1 - r2)) # vel. perturbation - dtemp = -(equations.gamma - 1) / (2 * equations.gamma * rt) * du^2 # isentropic - rho = rho * (1 + dtemp)^(1 / (equations.gamma - 1)) - vel = vel + du * cent - v1, v2 = vel - p = p * (1 + dtemp)^(equations.gamma / (equations.gamma - 1)) - prim = SVector(rho, v1, v2, p) - return prim2cons(prim, equations) + # needs appropriate mesh size, e.g. [-10,-10]x[10,10] + # for error convergence: make sure that the end time is such that the vortex is back at the initial state!! + # for the current velocity and domain size: t_end should be a multiple of 20s + # initial center of the vortex + inicenter = SVector(0.0, 0.0) + # size and strength of the vortex + iniamplitude = 5.0 + # base flow + rho = 1.0 + v1 = 1.0 + v2 = 1.0 + vel = SVector(v1, v2) + p = 25.0 + rt = p / rho # ideal gas equation + t_loc = 0.0 + cent = inicenter + vel * t_loc # advection of center + # ATTENTION: handle periodic BC, but only for v1 = v2 = 1.0 (!!!!) + cent = x - cent # distance to center point + # cent = cross(iniaxis, cent) # distance to axis, tangent vector, length r + # cross product with iniaxis = [0, 0, 1] + cent = SVector(-cent[2], cent[1]) + r2 = cent[1]^2 + cent[2]^2 + du = iniamplitude / (2 * π) * exp(0.5 * (1 - r2)) # vel. perturbation + dtemp = -(equations.gamma - 1) / (2 * equations.gamma * rt) * du^2 # isentropic + rho = rho * (1 + dtemp)^(1 / (equations.gamma - 1)) + vel = vel + du * cent + v1, v2 = vel + p = p * (1 + dtemp)^(equations.gamma / (equations.gamma - 1)) + prim = SVector(rho, v1, v2, p) + return prim2cons(prim, equations) end initial_condition = initial_condition_isentropic_vortex -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-10.0, -10.0) -coordinates_max = ( 10.0, 10.0) +coordinates_max = (10.0, 10.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) - + initial_refinement_level = 4, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -69,30 +68,31 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=true, - extra_analysis_errors=(:conservation_error,), - extra_analysis_integrals=(entropy, energy_total, - energy_kinetic, energy_internal)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true, + extra_analysis_errors = (:conservation_error,), + extra_analysis_integrals = (entropy, energy_total, + energy_kinetic, + energy_internal)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.1) +stepsize_callback = StepsizeCallback(cfl = 1.1) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_vortex_amr.jl b/examples/tree_2d_dgsem/elixir_euler_vortex_amr.jl index 6f6eb25efa4..e9831c95526 100644 --- a/examples/tree_2d_dgsem/elixir_euler_vortex_amr.jl +++ b/examples/tree_2d_dgsem/elixir_euler_vortex_amr.jl @@ -7,55 +7,54 @@ module TrixiExtension using Trixi -struct IndicatorVortex{Cache<:NamedTuple} <: Trixi.AbstractIndicator - cache::Cache +struct IndicatorVortex{Cache <: NamedTuple} <: Trixi.AbstractIndicator + cache::Cache end function IndicatorVortex(semi) - basis = semi.solver.basis - alpha = Vector{real(basis)}() - A = Array{real(basis), 2} - indicator_threaded = [A(undef, nnodes(basis), nnodes(basis)) - for _ in 1:Threads.nthreads()] - cache = (; semi.mesh, alpha, indicator_threaded) - - return IndicatorVortex{typeof(cache)}(cache) + basis = semi.solver.basis + alpha = Vector{real(basis)}() + A = Array{real(basis), 2} + indicator_threaded = [A(undef, nnodes(basis), nnodes(basis)) + for _ in 1:Threads.nthreads()] + cache = (; semi.mesh, alpha, indicator_threaded) + + return IndicatorVortex{typeof(cache)}(cache) end -function (indicator_vortex::IndicatorVortex)(u::AbstractArray{<:Any,4}, +function (indicator_vortex::IndicatorVortex)(u::AbstractArray{<:Any, 4}, mesh, equations, dg, cache; t, kwargs...) - mesh = indicator_vortex.cache.mesh - alpha = indicator_vortex.cache.alpha - indicator_threaded = indicator_vortex.cache.indicator_threaded - resize!(alpha, nelements(dg, cache)) - - - # get analytical vortex center (based on assumption that center=[0.0,0.0] - # at t=0.0 and that we stop after one period) - domain_length = mesh.tree.length_level_0 - if t < 0.5 * domain_length - center = (t, t) - else - center = (t-domain_length, t-domain_length) - end - - Threads.@threads for element in eachelement(dg, cache) - cell_id = cache.elements.cell_ids[element] - coordinates = (mesh.tree.coordinates[1, cell_id], mesh.tree.coordinates[2, cell_id]) - # use the negative radius as indicator since the AMR controller increases - # the level with increasing value of the indicator and we want to use - # high levels near the vortex center - alpha[element] = -periodic_distance_2d(coordinates, center, domain_length) - end - - return alpha + mesh = indicator_vortex.cache.mesh + alpha = indicator_vortex.cache.alpha + indicator_threaded = indicator_vortex.cache.indicator_threaded + resize!(alpha, nelements(dg, cache)) + + # get analytical vortex center (based on assumption that center=[0.0,0.0] + # at t=0.0 and that we stop after one period) + domain_length = mesh.tree.length_level_0 + if t < 0.5 * domain_length + center = (t, t) + else + center = (t - domain_length, t - domain_length) + end + + Threads.@threads for element in eachelement(dg, cache) + cell_id = cache.elements.cell_ids[element] + coordinates = (mesh.tree.coordinates[1, cell_id], mesh.tree.coordinates[2, cell_id]) + # use the negative radius as indicator since the AMR controller increases + # the level with increasing value of the indicator and we want to use + # high levels near the vortex center + alpha[element] = -periodic_distance_2d(coordinates, center, domain_length) + end + + return alpha end function periodic_distance_2d(coordinates, center, domain_length) - dx = @. abs(coordinates - center) - dx_periodic = @. min(dx, domain_length - dx) - return sqrt(sum(abs2, dx_periodic)) + dx = @. abs(coordinates - center) + dx_periodic = @. min(dx, domain_length - dx) + return sqrt(sum(abs2, dx_periodic)) end end # module TrixiExtension @@ -77,48 +76,47 @@ The classical isentropic vortex test case of [NASA/CR-97-206253](https://ntrs.nasa.gov/citations/19980007543) """ function initial_condition_isentropic_vortex(x, t, equations::CompressibleEulerEquations2D) - # needs appropriate mesh size, e.g. [-10,-10]x[10,10] - # for error convergence: make sure that the end time is such that the vortex is back at the initial state!! - # for the current velocity and domain size: t_end should be a multiple of 20s - # initial center of the vortex - inicenter = SVector(0.0, 0.0) - # size and strength of the vortex - iniamplitude = 5.0 - # base flow - rho = 1.0 - v1 = 1.0 - v2 = 1.0 - vel = SVector(v1, v2) - p = 25.0 - rt = p / rho # ideal gas equation - t_loc = 0.0 - cent = inicenter + vel*t_loc # advection of center - # ATTENTION: handle periodic BC, but only for v1 = v2 = 1.0 (!!!!) - - cent = x - cent # distance to center point - - # cent = cross(iniaxis, cent) # distance to axis, tangent vector, length r - # cross product with iniaxis = [0, 0, 1] - cent = SVector(-cent[2], cent[1]) - r2 = cent[1]^2 + cent[2]^2 - du = iniamplitude / (2*π) * exp(0.5 * (1 - r2)) # vel. perturbation - dtemp = -(equations.gamma - 1) / (2 * equations.gamma * rt) * du^2 # isentropic - rho = rho * (1 + dtemp)^(1 / (equations.gamma - 1)) - vel = vel + du * cent - v1, v2 = vel - p = p * (1 + dtemp)^(equations.gamma / (equations.gamma - 1)) - prim = SVector(rho, v1, v2, p) - return prim2cons(prim, equations) + # needs appropriate mesh size, e.g. [-10,-10]x[10,10] + # for error convergence: make sure that the end time is such that the vortex is back at the initial state!! + # for the current velocity and domain size: t_end should be a multiple of 20s + # initial center of the vortex + inicenter = SVector(0.0, 0.0) + # size and strength of the vortex + iniamplitude = 5.0 + # base flow + rho = 1.0 + v1 = 1.0 + v2 = 1.0 + vel = SVector(v1, v2) + p = 25.0 + rt = p / rho # ideal gas equation + t_loc = 0.0 + cent = inicenter + vel * t_loc # advection of center + # ATTENTION: handle periodic BC, but only for v1 = v2 = 1.0 (!!!!) + + cent = x - cent # distance to center point + + # cent = cross(iniaxis, cent) # distance to axis, tangent vector, length r + # cross product with iniaxis = [0, 0, 1] + cent = SVector(-cent[2], cent[1]) + r2 = cent[1]^2 + cent[2]^2 + du = iniamplitude / (2 * π) * exp(0.5 * (1 - r2)) # vel. perturbation + dtemp = -(equations.gamma - 1) / (2 * equations.gamma * rt) * du^2 # isentropic + rho = rho * (1 + dtemp)^(1 / (equations.gamma - 1)) + vel = vel + du * cent + v1, v2 = vel + p = p * (1 + dtemp)^(equations.gamma / (equations.gamma - 1)) + prim = SVector(rho, v1, v2, p) + return prim2cons(prim, equations) end initial_condition = initial_condition_isentropic_vortex -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-10.0, -10.0) -coordinates_max = ( 10.0, 10.0) +coordinates_max = (10.0, 10.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=10_000) - + initial_refinement_level = 3, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -132,39 +130,40 @@ summary_callback = SummaryCallback() analysis_interval = 200 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=true, - extra_analysis_errors=(:conservation_error,), - extra_analysis_integrals=(entropy, energy_total, - energy_kinetic, energy_internal)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true, + extra_analysis_errors = (:conservation_error,), + extra_analysis_integrals = (entropy, energy_total, + energy_kinetic, + energy_internal)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=50, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 50, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_controller = ControllerThreeLevel(semi, TrixiExtension.IndicatorVortex(semi), - base_level=3, - med_level=4, med_threshold=-3.0, - max_level=5, max_threshold=-2.0) + base_level = 3, + med_level = 4, med_threshold = -3.0, + max_level = 5, max_threshold = -2.0) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=1.1) +stepsize_callback = StepsizeCallback(cfl = 1.1) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, amr_callback, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_vortex_mortar.jl b/examples/tree_2d_dgsem/elixir_euler_vortex_mortar.jl index 637133b9b2f..858799d2d3d 100644 --- a/examples/tree_2d_dgsem/elixir_euler_vortex_mortar.jl +++ b/examples/tree_2d_dgsem/elixir_euler_vortex_mortar.jl @@ -17,49 +17,48 @@ The classical isentropic vortex test case of [NASA/CR-97-206253](https://ntrs.nasa.gov/citations/19980007543) """ function initial_condition_isentropic_vortex(x, t, equations::CompressibleEulerEquations2D) - # needs appropriate mesh size, e.g. [-10,-10]x[10,10] - # for error convergence: make sure that the end time is such that the vortex is back at the initial state!! - # for the current velocity and domain size: t_end should be a multiple of 20s - # initial center of the vortex - inicenter = SVector(0.0, 0.0) - # size and strength of the vortex - iniamplitude = 5.0 - # base flow - rho = 1.0 - v1 = 1.0 - v2 = 1.0 - vel = SVector(v1, v2) - p = 25.0 - rt = p / rho # ideal gas equation - t_loc = 0.0 - cent = inicenter + vel*t_loc # advection of center - # ATTENTION: handle periodic BC, but only for v1 = v2 = 1.0 (!!!!) - cent = x - cent # distance to center point - # cent = cross(iniaxis, cent) # distance to axis, tangent vector, length r - # cross product with iniaxis = [0, 0, 1] - cent = SVector(-cent[2], cent[1]) - r2 = cent[1]^2 + cent[2]^2 - du = iniamplitude / (2*π) * exp(0.5 * (1 - r2)) # vel. perturbation - dtemp = -(equations.gamma - 1) / (2 * equations.gamma * rt) * du^2 # isentropic - rho = rho * (1 + dtemp)^(1 / (equations.gamma - 1)) - vel = vel + du * cent - v1, v2 = vel - p = p * (1 + dtemp)^(equations.gamma / (equations.gamma - 1)) - prim = SVector(rho, v1, v2, p) - return prim2cons(prim, equations) + # needs appropriate mesh size, e.g. [-10,-10]x[10,10] + # for error convergence: make sure that the end time is such that the vortex is back at the initial state!! + # for the current velocity and domain size: t_end should be a multiple of 20s + # initial center of the vortex + inicenter = SVector(0.0, 0.0) + # size and strength of the vortex + iniamplitude = 5.0 + # base flow + rho = 1.0 + v1 = 1.0 + v2 = 1.0 + vel = SVector(v1, v2) + p = 25.0 + rt = p / rho # ideal gas equation + t_loc = 0.0 + cent = inicenter + vel * t_loc # advection of center + # ATTENTION: handle periodic BC, but only for v1 = v2 = 1.0 (!!!!) + cent = x - cent # distance to center point + # cent = cross(iniaxis, cent) # distance to axis, tangent vector, length r + # cross product with iniaxis = [0, 0, 1] + cent = SVector(-cent[2], cent[1]) + r2 = cent[1]^2 + cent[2]^2 + du = iniamplitude / (2 * π) * exp(0.5 * (1 - r2)) # vel. perturbation + dtemp = -(equations.gamma - 1) / (2 * equations.gamma * rt) * du^2 # isentropic + rho = rho * (1 + dtemp)^(1 / (equations.gamma - 1)) + vel = vel + du * cent + v1, v2 = vel + p = p * (1 + dtemp)^(equations.gamma / (equations.gamma - 1)) + prim = SVector(rho, v1, v2, p) + return prim2cons(prim, equations) end initial_condition = initial_condition_isentropic_vortex -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-10.0, -10.0) -coordinates_max = ( 10.0, 10.0) -refinement_patches = ( - (type="box", coordinates_min=(0.0, -10.0), coordinates_max=(10.0, 10.0)), -) +coordinates_max = (10.0, 10.0) +refinement_patches = ((type = "box", coordinates_min = (0.0, -10.0), + coordinates_max = (10.0, 10.0)),) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - refinement_patches=refinement_patches, - n_cells_max=10_000,) + initial_refinement_level = 4, + refinement_patches = refinement_patches, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -72,30 +71,31 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=true, - extra_analysis_errors=(:conservation_error,), - extra_analysis_integrals=(entropy, energy_total, - energy_kinetic, energy_internal)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true, + extra_analysis_errors = (:conservation_error,), + extra_analysis_integrals = (entropy, energy_total, + energy_kinetic, + energy_internal)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.4) +stepsize_callback = StepsizeCallback(cfl = 1.4) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_vortex_mortar_shockcapturing.jl b/examples/tree_2d_dgsem/elixir_euler_vortex_mortar_shockcapturing.jl index dc6a326c5d5..026f6d1462c 100644 --- a/examples/tree_2d_dgsem/elixir_euler_vortex_mortar_shockcapturing.jl +++ b/examples/tree_2d_dgsem/elixir_euler_vortex_mortar_shockcapturing.jl @@ -17,36 +17,36 @@ The classical isentropic vortex test case of [NASA/CR-97-206253](https://ntrs.nasa.gov/citations/19980007543) """ function initial_condition_isentropic_vortex(x, t, equations::CompressibleEulerEquations2D) - # needs appropriate mesh size, e.g. [-10,-10]x[10,10] - # for error convergence: make sure that the end time is such that the vortex is back at the initial state!! - # for the current velocity and domain size: t_end should be a multiple of 20s - # initial center of the vortex - inicenter = SVector(0.0, 0.0) - # size and strength of the vortex - iniamplitude = 5.0 - # base flow - rho = 1.0 - v1 = 1.0 - v2 = 1.0 - vel = SVector(v1, v2) - p = 25.0 - rt = p / rho # ideal gas equation - t_loc = 0.0 - cent = inicenter + vel*t_loc # advection of center - # ATTENTION: handle periodic BC, but only for v1 = v2 = 1.0 (!!!!) - cent = x - cent # distance to center point - # cent = cross(iniaxis, cent) # distance to axis, tangent vector, length r - # cross product with iniaxis = [0, 0, 1] - cent = SVector(-cent[2], cent[1]) - r2 = cent[1]^2 + cent[2]^2 - du = iniamplitude / (2*π) * exp(0.5 * (1 - r2)) # vel. perturbation - dtemp = -(equations.gamma - 1) / (2 * equations.gamma * rt) * du^2 # isentropic - rho = rho * (1 + dtemp)^(1 / (equations.gamma - 1)) - vel = vel + du * cent - v1, v2 = vel - p = p * (1 + dtemp)^(equations.gamma / (equations.gamma - 1)) - prim = SVector(rho, v1, v2, p) - return prim2cons(prim, equations) + # needs appropriate mesh size, e.g. [-10,-10]x[10,10] + # for error convergence: make sure that the end time is such that the vortex is back at the initial state!! + # for the current velocity and domain size: t_end should be a multiple of 20s + # initial center of the vortex + inicenter = SVector(0.0, 0.0) + # size and strength of the vortex + iniamplitude = 5.0 + # base flow + rho = 1.0 + v1 = 1.0 + v2 = 1.0 + vel = SVector(v1, v2) + p = 25.0 + rt = p / rho # ideal gas equation + t_loc = 0.0 + cent = inicenter + vel * t_loc # advection of center + # ATTENTION: handle periodic BC, but only for v1 = v2 = 1.0 (!!!!) + cent = x - cent # distance to center point + # cent = cross(iniaxis, cent) # distance to axis, tangent vector, length r + # cross product with iniaxis = [0, 0, 1] + cent = SVector(-cent[2], cent[1]) + r2 = cent[1]^2 + cent[2]^2 + du = iniamplitude / (2 * π) * exp(0.5 * (1 - r2)) # vel. perturbation + dtemp = -(equations.gamma - 1) / (2 * equations.gamma * rt) * du^2 # isentropic + rho = rho * (1 + dtemp)^(1 / (equations.gamma - 1)) + vel = vel + du * cent + v1, v2 = vel + p = p * (1 + dtemp)^(equations.gamma / (equations.gamma - 1)) + prim = SVector(rho, v1, v2, p) + return prim2cons(prim, equations) end initial_condition = initial_condition_isentropic_vortex @@ -56,24 +56,23 @@ volume_flux = flux_shima_etal polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-10.0, -10.0) -coordinates_max = ( 10.0, 10.0) -refinement_patches = ( - (type="box", coordinates_min=(0.0, -10.0), coordinates_max=(10.0, 10.0)), -) +coordinates_max = (10.0, 10.0) +refinement_patches = ((type = "box", coordinates_min = (0.0, -10.0), + coordinates_max = (10.0, 10.0)),) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - refinement_patches=refinement_patches, - n_cells_max=10_000,) + initial_refinement_level = 4, + refinement_patches = refinement_patches, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -86,30 +85,31 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=true, - extra_analysis_errors=(:conservation_error,), - extra_analysis_integrals=(entropy, energy_total, - energy_kinetic, energy_internal)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true, + extra_analysis_errors = (:conservation_error,), + extra_analysis_integrals = (entropy, energy_total, + energy_kinetic, + energy_internal)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.7) +stepsize_callback = StepsizeCallback(cfl = 0.7) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_vortex_mortar_split.jl b/examples/tree_2d_dgsem/elixir_euler_vortex_mortar_split.jl index 99036c36451..d719e01fd7c 100644 --- a/examples/tree_2d_dgsem/elixir_euler_vortex_mortar_split.jl +++ b/examples/tree_2d_dgsem/elixir_euler_vortex_mortar_split.jl @@ -17,52 +17,51 @@ The classical isentropic vortex test case of [NASA/CR-97-206253](https://ntrs.nasa.gov/citations/19980007543) """ function initial_condition_isentropic_vortex(x, t, equations::CompressibleEulerEquations2D) - # needs appropriate mesh size, e.g. [-10,-10]x[10,10] - # for error convergence: make sure that the end time is such that the vortex is back at the initial state!! - # for the current velocity and domain size: t_end should be a multiple of 20s - # initial center of the vortex - inicenter = SVector(0.0, 0.0) - # size and strength of the vortex - iniamplitude = 5.0 - # base flow - rho = 1.0 - v1 = 1.0 - v2 = 1.0 - vel = SVector(v1, v2) - p = 25.0 - rt = p / rho # ideal gas equation - t_loc = 0.0 - cent = inicenter + vel*t_loc # advection of center - # ATTENTION: handle periodic BC, but only for v1 = v2 = 1.0 (!!!!) - cent = x - cent # distance to center point - # cent = cross(iniaxis, cent) # distance to axis, tangent vector, length r - # cross product with iniaxis = [0, 0, 1] - cent = SVector(-cent[2], cent[1]) - r2 = cent[1]^2 + cent[2]^2 - du = iniamplitude / (2*π) * exp(0.5 * (1 - r2)) # vel. perturbation - dtemp = -(equations.gamma - 1) / (2 * equations.gamma * rt) * du^2 # isentropic - rho = rho * (1 + dtemp)^(1 / (equations.gamma - 1)) - vel = vel + du * cent - v1, v2 = vel - p = p * (1 + dtemp)^(equations.gamma / (equations.gamma - 1)) - prim = SVector(rho, v1, v2, p) - return prim2cons(prim, equations) + # needs appropriate mesh size, e.g. [-10,-10]x[10,10] + # for error convergence: make sure that the end time is such that the vortex is back at the initial state!! + # for the current velocity and domain size: t_end should be a multiple of 20s + # initial center of the vortex + inicenter = SVector(0.0, 0.0) + # size and strength of the vortex + iniamplitude = 5.0 + # base flow + rho = 1.0 + v1 = 1.0 + v2 = 1.0 + vel = SVector(v1, v2) + p = 25.0 + rt = p / rho # ideal gas equation + t_loc = 0.0 + cent = inicenter + vel * t_loc # advection of center + # ATTENTION: handle periodic BC, but only for v1 = v2 = 1.0 (!!!!) + cent = x - cent # distance to center point + # cent = cross(iniaxis, cent) # distance to axis, tangent vector, length r + # cross product with iniaxis = [0, 0, 1] + cent = SVector(-cent[2], cent[1]) + r2 = cent[1]^2 + cent[2]^2 + du = iniamplitude / (2 * π) * exp(0.5 * (1 - r2)) # vel. perturbation + dtemp = -(equations.gamma - 1) / (2 * equations.gamma * rt) * du^2 # isentropic + rho = rho * (1 + dtemp)^(1 / (equations.gamma - 1)) + vel = vel + du * cent + v1, v2 = vel + p = p * (1 + dtemp)^(equations.gamma / (equations.gamma - 1)) + prim = SVector(rho, v1, v2, p) + return prim2cons(prim, equations) end initial_condition = initial_condition_isentropic_vortex volume_flux = flux_shima_etal -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-10.0, -10.0) -coordinates_max = ( 10.0, 10.0) -refinement_patches = ( - (type="box", coordinates_min=(0.0, -10.0), coordinates_max=(10.0, 10.0)), -) +coordinates_max = (10.0, 10.0) +refinement_patches = ((type = "box", coordinates_min = (0.0, -10.0), + coordinates_max = (10.0, 10.0)),) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - refinement_patches=refinement_patches, - n_cells_max=10_000,) + initial_refinement_level = 4, + refinement_patches = refinement_patches, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -75,30 +74,31 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=true, - extra_analysis_errors=(:conservation_error,), - extra_analysis_integrals=(entropy, energy_total, - energy_kinetic, energy_internal)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true, + extra_analysis_errors = (:conservation_error,), + extra_analysis_integrals = (entropy, energy_total, + energy_kinetic, + energy_internal)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.4) +stepsize_callback = StepsizeCallback(cfl = 1.4) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euler_vortex_shockcapturing.jl b/examples/tree_2d_dgsem/elixir_euler_vortex_shockcapturing.jl index 65a497374ed..99e4b090633 100644 --- a/examples/tree_2d_dgsem/elixir_euler_vortex_shockcapturing.jl +++ b/examples/tree_2d_dgsem/elixir_euler_vortex_shockcapturing.jl @@ -17,36 +17,36 @@ The classical isentropic vortex test case of [NASA/CR-97-206253](https://ntrs.nasa.gov/citations/19980007543) """ function initial_condition_isentropic_vortex(x, t, equations::CompressibleEulerEquations2D) - # needs appropriate mesh size, e.g. [-10,-10]x[10,10] - # for error convergence: make sure that the end time is such that the vortex is back at the initial state!! - # for the current velocity and domain size: t_end should be a multiple of 20s - # initial center of the vortex - inicenter = SVector(0.0, 0.0) - # size and strength of the vortex - iniamplitude = 5.0 - # base flow - rho = 1.0 - v1 = 1.0 - v2 = 1.0 - vel = SVector(v1, v2) - p = 25.0 - rt = p / rho # ideal gas equation - t_loc = 0.0 - cent = inicenter + vel*t_loc # advection of center - # ATTENTION: handle periodic BC, but only for v1 = v2 = 1.0 (!!!!) - cent = x - cent # distance to center point - # cent = cross(iniaxis, cent) # distance to axis, tangent vector, length r - # cross product with iniaxis = [0, 0, 1] - cent = SVector(-cent[2], cent[1]) - r2 = cent[1]^2 + cent[2]^2 - du = iniamplitude / (2*π) * exp(0.5 * (1 - r2)) # vel. perturbation - dtemp = -(equations.gamma - 1) / (2 * equations.gamma * rt) * du^2 # isentropic - rho = rho * (1 + dtemp)^(1 / (equations.gamma - 1)) - vel = vel + du * cent - v1, v2 = vel - p = p * (1 + dtemp)^(equations.gamma / (equations.gamma - 1)) - prim = SVector(rho, v1, v2, p) - return prim2cons(prim, equations) + # needs appropriate mesh size, e.g. [-10,-10]x[10,10] + # for error convergence: make sure that the end time is such that the vortex is back at the initial state!! + # for the current velocity and domain size: t_end should be a multiple of 20s + # initial center of the vortex + inicenter = SVector(0.0, 0.0) + # size and strength of the vortex + iniamplitude = 5.0 + # base flow + rho = 1.0 + v1 = 1.0 + v2 = 1.0 + vel = SVector(v1, v2) + p = 25.0 + rt = p / rho # ideal gas equation + t_loc = 0.0 + cent = inicenter + vel * t_loc # advection of center + # ATTENTION: handle periodic BC, but only for v1 = v2 = 1.0 (!!!!) + cent = x - cent # distance to center point + # cent = cross(iniaxis, cent) # distance to axis, tangent vector, length r + # cross product with iniaxis = [0, 0, 1] + cent = SVector(-cent[2], cent[1]) + r2 = cent[1]^2 + cent[2]^2 + du = iniamplitude / (2 * π) * exp(0.5 * (1 - r2)) # vel. perturbation + dtemp = -(equations.gamma - 1) / (2 * equations.gamma * rt) * du^2 # isentropic + rho = rho * (1 + dtemp)^(1 / (equations.gamma - 1)) + vel = vel + du * cent + v1, v2 = vel + p = p * (1 + dtemp)^(equations.gamma / (equations.gamma - 1)) + prim = SVector(rho, v1, v2, p) + return prim2cons(prim, equations) end initial_condition = initial_condition_isentropic_vortex @@ -56,20 +56,20 @@ volume_flux = flux_shima_etal polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-10.0, -10.0) -coordinates_max = ( 10.0, 10.0) +coordinates_max = (10.0, 10.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000,) + initial_refinement_level = 4, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -82,22 +82,24 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=true, - extra_analysis_errors=(:conservation_error,), - extra_analysis_integrals=(entropy, energy_total, - energy_kinetic, energy_internal)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true, + extra_analysis_errors = (:conservation_error,), + extra_analysis_integrals = (entropy, energy_total, + energy_kinetic, + energy_internal)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.7) +stepsize_callback = StepsizeCallback(cfl = 0.7) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -107,7 +109,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_euleracoustics_co-rotating_vortex_pair.jl b/examples/tree_2d_dgsem/elixir_euleracoustics_co-rotating_vortex_pair.jl index 38b48b5d537..ea81bd049e4 100644 --- a/examples/tree_2d_dgsem/elixir_euleracoustics_co-rotating_vortex_pair.jl +++ b/examples/tree_2d_dgsem/elixir_euleracoustics_co-rotating_vortex_pair.jl @@ -19,203 +19,199 @@ module VortexPairSetup using LinearAlgebra: norm using Trixi - # Parameters that describe the co-rotating vortex pair -struct VortexPair{RealT<:Real} - r0::RealT # Distance between origin and each vortex center - rc::RealT # Vortex core radius - c0::RealT # Speed of sound - circulation::RealT # Circulation of the vortices - rho0::RealT # Density +struct VortexPair{RealT <: Real} + r0::RealT # Distance between origin and each vortex center + rc::RealT # Vortex core radius + c0::RealT # Speed of sound + circulation::RealT # Circulation of the vortices + rho0::RealT # Density end - # Analytical flow solution, used for the initial condition of the flow simulation function velocity(x, t, vortex_pair::VortexPair) - @unpack r0, rc, circulation = vortex_pair + @unpack r0, rc, circulation = vortex_pair - omega = circulation / (4 * pi * r0^2) - si, co = sincos(omega * t) - b = SVector(r0 * co, r0 * si) # vortex centers are b and -b - z_plus = x - b - z_minus = x + b + omega = circulation / (4 * pi * r0^2) + si, co = sincos(omega * t) + b = SVector(r0 * co, r0 * si) # vortex centers are b and -b + z_plus = x - b + z_minus = x + b - # Transform to polar coordinates - r_plus = norm(z_plus) - r_minus = norm(z_minus) - theta_plus = atan(z_plus[2], z_plus[1]) - theta_minus = atan(z_minus[2], z_minus[1]) + # Transform to polar coordinates + r_plus = norm(z_plus) + r_minus = norm(z_minus) + theta_plus = atan(z_plus[2], z_plus[1]) + theta_minus = atan(z_minus[2], z_minus[1]) - si_plus, co_plus = sincos(theta_plus) - si_minus, co_minus = sincos(theta_minus) + si_plus, co_plus = sincos(theta_plus) + si_minus, co_minus = sincos(theta_minus) - v1 = -circulation/(2 * pi) * ( r_plus /(rc^2 + r_plus^2) * si_plus + - r_minus/(rc^2 + r_minus^2) * si_minus) - v2 = circulation/(2 * pi) * ( r_plus /(rc^2 + r_plus^2) * co_plus + - r_minus/(rc^2 + r_minus^2) * co_minus ) + v1 = -circulation / (2 * pi) * (r_plus / (rc^2 + r_plus^2) * si_plus + + r_minus / (rc^2 + r_minus^2) * si_minus) + v2 = circulation / (2 * pi) * (r_plus / (rc^2 + r_plus^2) * co_plus + + r_minus / (rc^2 + r_minus^2) * co_minus) - return SVector(v1, v2) + return SVector(v1, v2) end - # Initial condition of the flow simulation. Uses constant density rho0 and analytical velocities. # The pressure is calculated using the given speed of sound c0 and Bernoulli's principle -struct InitialCondition{RealT<:Real} - vortex_pair::VortexPair{RealT} +struct InitialCondition{RealT <: Real} + vortex_pair::VortexPair{RealT} end -function (initial_condition::InitialCondition)(x, t, equations::CompressibleEulerEquations2D) - @unpack vortex_pair = initial_condition - @unpack rho0, c0 = vortex_pair - gamma = equations.gamma +function (initial_condition::InitialCondition)(x, t, + equations::CompressibleEulerEquations2D) + @unpack vortex_pair = initial_condition + @unpack rho0, c0 = vortex_pair + gamma = equations.gamma - v = velocity(x, t, vortex_pair) - p0 = rho0 * c0^2 / gamma - p = p0 - 0.5 * (gamma-1)/gamma * sum(v.^2) # Bernoulli's principle + v = velocity(x, t, vortex_pair) + p0 = rho0 * c0^2 / gamma + p = p0 - 0.5 * (gamma - 1) / gamma * sum(v .^ 2) # Bernoulli's principle - prim = SVector(rho0, v[1], v[2], p) - return prim2cons(prim, equations) + prim = SVector(rho0, v[1], v[2], p) + return prim2cons(prim, equations) end - # For both the flow and acoustics solvers, a sponge layer is used to dampen the density # and pressure towards the freestream values (for the flow solver) and the perturbed pressure # to zero (for the acoustics solver). -struct SpongeLayer{RealT<:Real, uEltype<:Real, N, SourceTerms} - sponge_layer_min::NTuple{4, RealT} # (-x,+x,-y,+y) min coordinates of sponge layer per direction - sponge_layer_max::NTuple{4, RealT} # (-x,+x,-y,+y) max coordinates of sponge layer per direction - reference_values::NTuple{N, uEltype} # reference values for variables affected by sponge layer - source_terms::SourceTerms # source terms to be used outside the sponge zone +struct SpongeLayer{RealT <: Real, uEltype <: Real, N, SourceTerms} + sponge_layer_min::NTuple{4, RealT} # (-x,+x,-y,+y) min coordinates of sponge layer per direction + sponge_layer_max::NTuple{4, RealT} # (-x,+x,-y,+y) max coordinates of sponge layer per direction + reference_values::NTuple{N, uEltype} # reference values for variables affected by sponge layer + source_terms::SourceTerms # source terms to be used outside the sponge zone end -function SpongeLayer(; sponge_layer_min, sponge_layer_max, reference_values, source_terms=nothing) - return SpongeLayer(sponge_layer_min, sponge_layer_max, reference_values, source_terms) +function SpongeLayer(; sponge_layer_min, sponge_layer_max, reference_values, + source_terms = nothing) + return SpongeLayer(sponge_layer_min, sponge_layer_max, reference_values, source_terms) end function (sponge_layer::SpongeLayer)(u, x, t, equations) - @unpack sponge_layer_min, sponge_layer_max, reference_values, source_terms = sponge_layer - - if lies_in_sponge_layer(x, sponge_layer_min, sponge_layer_max) - return source_term_sponge_layer(u, x, t, equations, sponge_layer_min, sponge_layer_max, - reference_values) - elseif source_terms !== nothing - return source_terms(u, x, t, equations) - else - return SVector(ntuple(v -> zero(eltype(u)), Val(nvariables(equations)))) - end + @unpack sponge_layer_min, sponge_layer_max, reference_values, source_terms = sponge_layer + + if lies_in_sponge_layer(x, sponge_layer_min, sponge_layer_max) + return source_term_sponge_layer(u, x, t, equations, sponge_layer_min, + sponge_layer_max, + reference_values) + elseif source_terms !== nothing + return source_terms(u, x, t, equations) + else + return SVector(ntuple(v -> zero(eltype(u)), Val(nvariables(equations)))) + end end function lies_in_sponge_layer(x, sponge_layer_min, sponge_layer_max) - return (sponge_layer_min[1] <= x[1] <= sponge_layer_max[1]) || # -x direction - (sponge_layer_min[2] <= x[1] <= sponge_layer_max[2]) || # +x direction - (sponge_layer_min[3] <= x[2] <= sponge_layer_max[3]) || # -y direction - (sponge_layer_min[4] <= x[2] <= sponge_layer_max[4]) # +y direction + return (sponge_layer_min[1] <= x[1] <= sponge_layer_max[1]) || # -x direction + (sponge_layer_min[2] <= x[1] <= sponge_layer_max[2]) || # +x direction + (sponge_layer_min[3] <= x[2] <= sponge_layer_max[3]) || # -y direction + (sponge_layer_min[4] <= x[2] <= sponge_layer_max[4]) # +y direction end function source_term_sponge_layer(u, x, t, equations::AcousticPerturbationEquations2D, sponge_layer_min::NTuple{4}, sponge_layer_max::NTuple{4}, reference_values) - # Perturbed pressure source is -alpha^2 * (u - reference_value) where alpha in [0,1] is a damping - # factor depending on the position inside the sponge layer + # Perturbed pressure source is -alpha^2 * (u - reference_value) where alpha in [0,1] is a damping + # factor depending on the position inside the sponge layer - # Calculate the damping factors for each direction (=0 if x is not in the corresponding sponge - # zone) and take the maximum. This ensures proper damping if x lies in a corner where the sponge - # zones for two directions overlap - alphas = ntuple(i -> calc_damping_factor(x, i, sponge_layer_min, sponge_layer_max), - Val(2*ndims(equations))) - alpha_square = maximum(alphas)^2 + # Calculate the damping factors for each direction (=0 if x is not in the corresponding sponge + # zone) and take the maximum. This ensures proper damping if x lies in a corner where the sponge + # zones for two directions overlap + alphas = ntuple(i -> calc_damping_factor(x, i, sponge_layer_min, sponge_layer_max), + Val(2 * ndims(equations))) + alpha_square = maximum(alphas)^2 - return SVector(0, 0, -alpha_square*(u[3] - reference_values[1]/u[6]^2), 0, 0, 0, 0) + return SVector(0, 0, -alpha_square * (u[3] - reference_values[1] / u[6]^2), 0, 0, 0, 0) end function source_term_sponge_layer(u, x, t, equations::CompressibleEulerEquations2D, sponge_layer_min::NTuple{4}, sponge_layer_max::NTuple{4}, reference_values) - # Calculate the damping factors for each direction (=0 if x is not in the corresponding sponge - # zone) and take the maximum. This ensures proper damping if x lies in a corner where the sponge - # zones for two directions overlap - alphas = ntuple(i -> calc_damping_factor(x, i, sponge_layer_min, sponge_layer_max), - Val(2*ndims(equations))) - alpha_square = maximum(alphas)^2 - - u_prim = cons2prim(u, equations) - s = SVector(-alpha_square*(u_prim[1] - reference_values[1]), 0, 0, - -alpha_square*(u_prim[4] - reference_values[2])) - - return prim2cons(s, equations) + # Calculate the damping factors for each direction (=0 if x is not in the corresponding sponge + # zone) and take the maximum. This ensures proper damping if x lies in a corner where the sponge + # zones for two directions overlap + alphas = ntuple(i -> calc_damping_factor(x, i, sponge_layer_min, sponge_layer_max), + Val(2 * ndims(equations))) + alpha_square = maximum(alphas)^2 + + u_prim = cons2prim(u, equations) + s = SVector(-alpha_square * (u_prim[1] - reference_values[1]), 0, 0, + -alpha_square * (u_prim[4] - reference_values[2])) + + return prim2cons(s, equations) end function calc_damping_factor(x, direction, sponge_layer_min, sponge_layer_max) - # Damping factor alpha grows linearly from 0 to 1 depending on how deep x lies in the sponge layer - # If x does not lie in the sponge layer, this returns 0 - - # Get the coordinate that determines how deep we are in the sponge zone - if direction in (1, 2) - pos = x[1] - else - pos = x[2] - end - - # Determine where the sponge layer begins/ends to allow calculating the damping factor - if iseven(direction) - sponge_begin = sponge_layer_min[direction] - sponge_end = sponge_layer_max[direction] - else - sponge_begin = sponge_layer_max[direction] - sponge_end = sponge_layer_min[direction] - end - - alpha = (pos - sponge_begin) / (sponge_end - sponge_begin) - - # alpha lies in [0, 1] if and only if x lies in the sponge zone - if 0 <= alpha <= 1 - return alpha - else - return zero(alpha) - end + # Damping factor alpha grows linearly from 0 to 1 depending on how deep x lies in the sponge layer + # If x does not lie in the sponge layer, this returns 0 + + # Get the coordinate that determines how deep we are in the sponge zone + if direction in (1, 2) + pos = x[1] + else + pos = x[2] + end + + # Determine where the sponge layer begins/ends to allow calculating the damping factor + if iseven(direction) + sponge_begin = sponge_layer_min[direction] + sponge_end = sponge_layer_max[direction] + else + sponge_begin = sponge_layer_max[direction] + sponge_end = sponge_layer_min[direction] + end + + alpha = (pos - sponge_begin) / (sponge_end - sponge_begin) + + # alpha lies in [0, 1] if and only if x lies in the sponge zone + if 0 <= alpha <= 1 + return alpha + else + return zero(alpha) + end end - # Boundary condition for the flow problem: The sponge layer dampens density and pressure towards the # freestream values. The freestream values (converted into conservative variables) are therefore # used as a Dirichlet boundary struct BoundaryCondition{uEltype} - rho::uEltype - rho_e::uEltype + rho::uEltype + rho_e::uEltype end function (bc::BoundaryCondition)(u_inner, orientation, direction, x, t, surface_flux_function, equations::CompressibleEulerEquations2D) - u_boundary = SVector(bc.rho, zero(bc.rho), zero(bc.rho), bc.rho_e) + u_boundary = SVector(bc.rho, zero(bc.rho), zero(bc.rho), bc.rho_e) - # Calculate boundary flux - if iseven(direction) # u_inner is "left" of boundary, u_boundary is "right" of boundary - flux = surface_flux_function(u_inner, u_boundary, orientation, equations) - else # u_boundary is "left" of boundary, u_inner is "right" of boundary - flux = surface_flux_function(u_boundary, u_inner, orientation, equations) - end + # Calculate boundary flux + if iseven(direction) # u_inner is "left" of boundary, u_boundary is "right" of boundary + flux = surface_flux_function(u_inner, u_boundary, orientation, equations) + else # u_boundary is "left" of boundary, u_inner is "right" of boundary + flux = surface_flux_function(u_boundary, u_inner, orientation, equations) + end - return flux + return flux end end # module - import .VortexPairSetup - ############################################################################### # shared parameters, mesh and solver for both semidiscretizations # Parameters of the vortex pair -Mach = 1/9 +Mach = 1 / 9 c0 = 1.0 r0 = 1.0 circulation = 4 * pi * r0 * c0 * Mach rho = 1.0 -rc = 2/9 * r0 * 1.0 +rc = 2 / 9 * r0 * 1.0 T_r = 8 * pi^2 * r0^2 / circulation # Rotational period of the vortex pair T_a = T_r / 2 # Acoustic period of the vortex pair @@ -223,24 +219,22 @@ T_a = T_r / 2 # Acoustic period of the vortex pair vortex_pair = VortexPairSetup.VortexPair(r0, rc, c0, circulation, rho) # Shared mesh for both semidiscretizations -coordinates_min = (-135*r0, -135*r0) # minimum coordinates (min(x), min(y)) -coordinates_max = ( 135*r0, 135*r0) # maximum coordinates (max(x), max(y)) -refinement_patches = ( - (type="sphere", center=(0.0, 0.0), radius=85.0*r0), - (type="sphere", center=(0.0, 0.0), radius=20.0*r0), - (type="sphere", center=(0.0, 0.0), radius=10.0*r0), - (type="sphere", center=(0.0, 0.0), radius=5.0*r0) -) -initial_refinement_level=7 -n_cells_max=500_000 +coordinates_min = (-135 * r0, -135 * r0) # minimum coordinates (min(x), min(y)) +coordinates_max = (135 * r0, 135 * r0) # maximum coordinates (max(x), max(y)) +refinement_patches = ((type = "sphere", center = (0.0, 0.0), radius = 85.0 * r0), + (type = "sphere", center = (0.0, 0.0), radius = 20.0 * r0), + (type = "sphere", center = (0.0, 0.0), radius = 10.0 * r0), + (type = "sphere", center = (0.0, 0.0), radius = 5.0 * r0)) +initial_refinement_level = 7 +n_cells_max = 500_000 mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=initial_refinement_level, - refinement_patches=refinement_patches, - n_cells_max=n_cells_max, # set maximum capacity of tree data structure - periodicity=false) + initial_refinement_level = initial_refinement_level, + refinement_patches = refinement_patches, + n_cells_max = n_cells_max, # set maximum capacity of tree data structure + periodicity = false) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) ############################################################################### # semidiscretization Euler equations @@ -250,24 +244,37 @@ equations_euler = CompressibleEulerEquations2D(gamma) initial_condition_euler = VortexPairSetup.InitialCondition(vortex_pair) -sponge_layer_euler = VortexPairSetup.SpongeLayer(sponge_layer_min=(-135*r0, 115*r0, -135*r0, 115*r0), - sponge_layer_max=(-115*r0, 135*r0, -115*r0, 135*r0), - reference_values=(rho, rho * c0^2 / gamma)) # (rho0, p0) +sponge_layer_euler = VortexPairSetup.SpongeLayer(sponge_layer_min = (-135 * r0, 115 * r0, + -135 * r0, 115 * r0), + sponge_layer_max = (-115 * r0, 135 * r0, + -115 * r0, 135 * r0), + reference_values = (rho, + rho * c0^2 / gamma)) # (rho0, p0) -boundary_condition_euler = VortexPairSetup.BoundaryCondition(rho, (rho * c0^2 / gamma) / (gamma-1)) +boundary_condition_euler = VortexPairSetup.BoundaryCondition(rho, + (rho * c0^2 / gamma) / + (gamma - 1)) -semi_euler = SemidiscretizationHyperbolic(mesh, equations_euler, initial_condition_euler, solver, - boundary_conditions=boundary_condition_euler, - source_terms=sponge_layer_euler) +semi_euler = SemidiscretizationHyperbolic(mesh, equations_euler, initial_condition_euler, + solver, + boundary_conditions = boundary_condition_euler, + source_terms = sponge_layer_euler) ############################################################################### # semidiscretization acoustic perturbation equations -equations_acoustics = AcousticPerturbationEquations2D(v_mean_global=(13.0, 26.0), c_mean_global=39.0, - rho_mean_global=52.0) # global mean values will be overwritten - -sponge_layer_acoustics = VortexPairSetup.SpongeLayer(sponge_layer_min=(-135*r0, 100*r0, -135*r0, 100*r0), - sponge_layer_max=(-100*r0, 135*r0, -100*r0, 135*r0), - reference_values=(0.0,)) +equations_acoustics = AcousticPerturbationEquations2D(v_mean_global = (13.0, 26.0), + c_mean_global = 39.0, + rho_mean_global = 52.0) # global mean values will be overwritten + +sponge_layer_acoustics = VortexPairSetup.SpongeLayer(sponge_layer_min = (-135 * r0, + 100 * r0, + -135 * r0, + 100 * r0), + sponge_layer_max = (-100 * r0, + 135 * r0, + -100 * r0, + 135 * r0), + reference_values = (0.0,)) """ boundary_condition_zero(u_inner, orientation, direction, x, t, surface_flux_function, @@ -276,24 +283,27 @@ sponge_layer_acoustics = VortexPairSetup.SpongeLayer(sponge_layer_min=(-135*r0, Boundary condition that uses a boundary state where the state variables are zero and the mean variables are the same as in `u_inner`. """ -function boundary_condition_zero(u_inner, orientation, direction, x, t, surface_flux_function, +function boundary_condition_zero(u_inner, orientation, direction, x, t, + surface_flux_function, equations::AcousticPerturbationEquations2D) - value = zero(eltype(u_inner)) - u_boundary = SVector(value, value, value, cons2mean(u_inner, equations)...) + value = zero(eltype(u_inner)) + u_boundary = SVector(value, value, value, cons2mean(u_inner, equations)...) - # Calculate boundary flux - if iseven(direction) # u_inner is "left" of boundary, u_boundary is "right" of boundary - flux = surface_flux_function(u_inner, u_boundary, orientation, equations) - else # u_boundary is "left" of boundary, u_inner is "right" of boundary - flux = surface_flux_function(u_boundary, u_inner, orientation, equations) - end + # Calculate boundary flux + if iseven(direction) # u_inner is "left" of boundary, u_boundary is "right" of boundary + flux = surface_flux_function(u_inner, u_boundary, orientation, equations) + else # u_boundary is "left" of boundary, u_inner is "right" of boundary + flux = surface_flux_function(u_boundary, u_inner, orientation, equations) + end - return flux + return flux end -semi_acoustics = SemidiscretizationHyperbolic(mesh, equations_acoustics, initial_condition_constant, - solver, boundary_conditions=boundary_condition_zero, - source_terms=sponge_layer_acoustics) +semi_acoustics = SemidiscretizationHyperbolic(mesh, equations_acoustics, + initial_condition_constant, + solver, + boundary_conditions = boundary_condition_zero, + source_terms = sponge_layer_acoustics) ############################################################################### # ODE solvers, callbacks etc. for averaging the flow field @@ -307,12 +317,12 @@ ode_averaging = semidiscretize(semi_euler, tspan1) summary_callback = SummaryCallback() analysis_interval = 5000 -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) tspan_averaging = (50.0, 400.0) averaging_callback = AveragingCallback(semi_euler, tspan_averaging) -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) callbacks_averaging = CallbackSet(summary_callback, alive_callback, averaging_callback, stepsize_callback) @@ -321,14 +331,13 @@ callbacks_averaging = CallbackSet(summary_callback, alive_callback, averaging_ca # run simulation for averaging the flow field # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -sol_averaging = solve(ode_averaging, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks_averaging); +sol_averaging = solve(ode_averaging, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks_averaging); # Print the timer summary summary_callback() - ############################################################################### # set up coupled semidiscretization @@ -337,13 +346,13 @@ source_region(x) = sum(abs2, x) < 6.0^2 # calculate sources within radius 6 arou weights(x) = sum(abs2, x) < 5.0^2 ? 1.0 : cospi(0.5 * (norm(x) - 5.0)) semi = SemidiscretizationEulerAcoustics(semi_acoustics, semi_euler, - source_region=source_region, weights=weights) + source_region = source_region, weights = weights) ############################################################################### # ODE solvers, callbacks etc. for the coupled simulation # Create ODE problem -tspan = (0.0, 7.0*T_a) +tspan = (0.0, 7.0 * T_a) ode = semidiscretize(semi, tspan) # We need an additional ODE for the pure flow problem ode_euler = semidiscretize(semi.semi_euler, tspan) @@ -351,28 +360,30 @@ ode_euler = semidiscretize(semi.semi_euler, tspan) # Set up coupling callback cfl_acoustics = 0.8 cfl_euler = 0.8 -euler_acoustics_coupling = EulerAcousticsCouplingCallback( - ode_euler, "out/averaging.h5", CarpenterKennedy2N54(williamson_condition=false), - cfl_acoustics, cfl_euler, callback=SaveRestartCallback(interval=2300, output_directory="out/euler/")) +euler_acoustics_coupling = EulerAcousticsCouplingCallback(ode_euler, "out/averaging.h5", + CarpenterKennedy2N54(williamson_condition = false), + cfl_acoustics, cfl_euler, + callback = SaveRestartCallback(interval = 2300, + output_directory = "out/euler/")) # At the beginning of the main loop, the SummaryCallback prints a summary of the simulation setup # and resets the timers summary_callback = SummaryCallback() analysis_interval = 5000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) output_directory = "out/" -save_solution = SaveSolutionCallback(interval=2300, output_directory=output_directory) -save_restart = SaveRestartCallback(interval=2300, output_directory=output_directory) +save_solution = SaveSolutionCallback(interval = 2300, output_directory = output_directory) +save_restart = SaveRestartCallback(interval = 2300, output_directory = output_directory) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback, save_solution, save_restart, euler_acoustics_coupling) -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); # Print the timer summary -summary_callback() \ No newline at end of file +summary_callback() diff --git a/examples/tree_2d_dgsem/elixir_eulermulti_convergence_ec.jl b/examples/tree_2d_dgsem/elixir_eulermulti_convergence_ec.jl index d423b800fd0..bc4859e5760 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_convergence_ec.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_convergence_ec.jl @@ -4,25 +4,23 @@ using Trixi ############################################################################### # semidiscretization of the compressible Euler multicomponent equations -equations = CompressibleEulerMulticomponentEquations2D(gammas = (1.4, 1.4), +equations = CompressibleEulerMulticomponentEquations2D(gammas = (1.4, 1.4), gas_constants = (0.4, 0.4)) initial_condition = initial_condition_convergence_test volume_flux = flux_ranocha -solver = DGSEM(polydeg=3, surface_flux=flux_ranocha, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_ranocha, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-1.0, -1.0) -coordinates_max = ( 1.0, 1.0) +coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=30_000) - + initial_refinement_level = 3, + n_cells_max = 30_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -33,27 +31,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_eulermulti_convergence_es.jl b/examples/tree_2d_dgsem/elixir_eulermulti_convergence_es.jl index 62c5bab51ea..771343937a4 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_convergence_es.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_convergence_es.jl @@ -4,25 +4,23 @@ using Trixi ############################################################################### # semidiscretization of the compressible Euler multicomponent equations -equations = CompressibleEulerMulticomponentEquations2D(gammas = (1.4, 1.4), +equations = CompressibleEulerMulticomponentEquations2D(gammas = (1.4, 1.4), gas_constants = (0.4, 0.4)) initial_condition = initial_condition_convergence_test volume_flux = flux_ranocha -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-1.0, -1.0) -coordinates_max = ( 1.0, 1.0) +coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=30_000) - + initial_refinement_level = 4, + n_cells_max = 30_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -33,27 +31,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_eulermulti_ec.jl b/examples/tree_2d_dgsem/elixir_eulermulti_ec.jl index 0715dfe35d6..d912a280e49 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_ec.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_ec.jl @@ -4,26 +4,23 @@ using Trixi ############################################################################### # semidiscretization of the compressible Euler multicomponent equations -equations = CompressibleEulerMulticomponentEquations2D(gammas = 1.4, +equations = CompressibleEulerMulticomponentEquations2D(gammas = 1.4, gas_constants = 0.4) - initial_condition = initial_condition_weak_blast_wave volume_flux = flux_ranocha -solver = DGSEM(polydeg=3, surface_flux=flux_ranocha, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_ranocha, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-2.0, -2.0) -coordinates_max = ( 2.0, 2.0) +coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=5, - n_cells_max=10_000) - + initial_refinement_level = 5, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -34,28 +31,27 @@ summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(Trixi.density,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (Trixi.density,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_eulermulti_es.jl b/examples/tree_2d_dgsem/elixir_eulermulti_es.jl index a3e5580b572..470e533ab8d 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_es.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_es.jl @@ -4,25 +4,23 @@ using Trixi ############################################################################### # semidiscretization of the compressible Euler multicomponent equations -equations = CompressibleEulerMulticomponentEquations2D(gammas = (1.4, 1.4, 1.4, 1.4), +equations = CompressibleEulerMulticomponentEquations2D(gammas = (1.4, 1.4, 1.4, 1.4), gas_constants = (0.4, 0.4, 0.4, 0.4)) initial_condition = initial_condition_weak_blast_wave volume_flux = flux_ranocha -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-2.0, -2.0) -coordinates_max = ( 2.0, 2.0) +coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=5, - n_cells_max=10_000) - + initial_refinement_level = 5, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -32,30 +30,29 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_restart, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble.jl b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble.jl index 38510446cb1..c6ed07dcda1 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble.jl @@ -5,7 +5,7 @@ using Trixi # semidiscretization of the compressible Euler multicomponent equations # 1) Dry Air 2) Helium + 28% Air -equations = CompressibleEulerMulticomponentEquations2D(gammas = (1.4, 1.648), +equations = CompressibleEulerMulticomponentEquations2D(gammas = (1.4, 1.648), gas_constants = (0.287, 1.578)) """ @@ -16,124 +16,124 @@ A shock-bubble testcase for multicomponent Euler equations Formulation of Entropy-Stable schemes for the multicomponent compressible Euler equations [arXiv: 1904.00972](https://arxiv.org/abs/1904.00972) """ -function initial_condition_shock_bubble(x, t, equations::CompressibleEulerMulticomponentEquations2D{5, 2}) - # bubble test case, see Gouasmi et al. https://arxiv.org/pdf/1904.00972 - # other reference: https://www.researchgate.net/profile/Pep_Mulet/publication/222675930_A_flux-split_algorithm_applied_to_conservative_models_for_multicomponent_compressible_flows/links/568da54508aeaa1481ae7af0.pdf - # typical domain is rectangular, we change it to a square, as Trixi can only do squares - @unpack gas_constants = equations - - # Positivity Preserving Parameter, can be set to zero if scheme is positivity preserving - delta = 0.03 - - # Region I - rho1_1 = delta - rho2_1 = 1.225 * gas_constants[1]/gas_constants[2] - delta - v1_1 = zero(delta) - v2_1 = zero(delta) - p_1 = 101325 - - # Region II - rho1_2 = 1.225-delta - rho2_2 = delta - v1_2 = zero(delta) - v2_2 = zero(delta) - p_2 = 101325 - - # Region III - rho1_3 = 1.6861 - delta - rho2_3 = delta - v1_3 = -113.5243 - v2_3 = zero(delta) - p_3 = 159060 - - # Set up Region I & II: - inicenter = SVector(zero(delta), zero(delta)) - x_norm = x[1] - inicenter[1] - y_norm = x[2] - inicenter[2] - r = sqrt(x_norm^2 + y_norm^2) - - if (x[1] > 0.50) - # Set up Region III - rho1 = rho1_3 - rho2 = rho2_3 - v1 = v1_3 - v2 = v2_3 - p = p_3 - elseif (r < 0.25) - # Set up Region I - rho1 = rho1_1 - rho2 = rho2_1 - v1 = v1_1 - v2 = v2_1 - p = p_1 - else - # Set up Region II - rho1 = rho1_2 - rho2 = rho2_2 - v1 = v1_2 - v2 = v2_2 - p = p_2 - end - - return prim2cons(SVector(v1, v2, p, rho1, rho2), equations) +function initial_condition_shock_bubble(x, t, + equations::CompressibleEulerMulticomponentEquations2D{5, + 2}) + # bubble test case, see Gouasmi et al. https://arxiv.org/pdf/1904.00972 + # other reference: https://www.researchgate.net/profile/Pep_Mulet/publication/222675930_A_flux-split_algorithm_applied_to_conservative_models_for_multicomponent_compressible_flows/links/568da54508aeaa1481ae7af0.pdf + # typical domain is rectangular, we change it to a square, as Trixi can only do squares + @unpack gas_constants = equations + + # Positivity Preserving Parameter, can be set to zero if scheme is positivity preserving + delta = 0.03 + + # Region I + rho1_1 = delta + rho2_1 = 1.225 * gas_constants[1] / gas_constants[2] - delta + v1_1 = zero(delta) + v2_1 = zero(delta) + p_1 = 101325 + + # Region II + rho1_2 = 1.225 - delta + rho2_2 = delta + v1_2 = zero(delta) + v2_2 = zero(delta) + p_2 = 101325 + + # Region III + rho1_3 = 1.6861 - delta + rho2_3 = delta + v1_3 = -113.5243 + v2_3 = zero(delta) + p_3 = 159060 + + # Set up Region I & II: + inicenter = SVector(zero(delta), zero(delta)) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + + if (x[1] > 0.50) + # Set up Region III + rho1 = rho1_3 + rho2 = rho2_3 + v1 = v1_3 + v2 = v2_3 + p = p_3 + elseif (r < 0.25) + # Set up Region I + rho1 = rho1_1 + rho2 = rho2_1 + v1 = v1_1 + v2 = v2_1 + p = p_1 + else + # Set up Region II + rho1 = rho1_2 + rho2 = rho2_2 + v1 = v1_2 + v2 = v2_2 + p = p_2 + end + + return prim2cons(SVector(v1, v2, p, rho1, rho2), equations) end initial_condition = initial_condition_shock_bubble -surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha -basis = LobattoLegendreBasis(3) -indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) -volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) -solver = DGSEM(basis, surface_flux, volume_integral) - -coordinates_min = (-2.25, -2.225) -coordinates_max = ( 2.20, 2.225) -mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=1_000_000) - -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +basis = LobattoLegendreBasis(3) +indicator_sc = IndicatorHennemannGassner(equations, basis, + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) +volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) +solver = DGSEM(basis, surface_flux, volume_integral) + +coordinates_min = (-2.25, -2.225) +coordinates_max = (2.20, 2.225) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level = 3, + n_cells_max = 1_000_000) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) ############################################################################### # ODE solvers, callbacks etc. -tspan = (0.0, 0.01) -ode = semidiscretize(semi, tspan) - -summary_callback = SummaryCallback() +tspan = (0.0, 0.01) +ode = semidiscretize(semi, tspan) -analysis_interval = 300 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(Trixi.density,)) +summary_callback = SummaryCallback() -alive_callback = AliveCallback(analysis_interval=analysis_interval) +analysis_interval = 300 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (Trixi.density,)) -save_solution = SaveSolutionCallback(interval=300, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -stepsize_callback = StepsizeCallback(cfl=0.3) +save_solution = SaveSolutionCallback(interval = 300, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -callbacks = CallbackSet(summary_callback, - analysis_callback, - alive_callback, - save_solution, - stepsize_callback) +stepsize_callback = StepsizeCallback(cfl = 0.3) +callbacks = CallbackSet(summary_callback, + analysis_callback, + alive_callback, + save_solution, + stepsize_callback) ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, - callback=callbacks, - maxiters=1e5); -summary_callback() # print the timer summary \ No newline at end of file +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, + callback = callbacks, + maxiters = 1e5); +summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl new file mode 100644 index 00000000000..4b606502ebe --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl @@ -0,0 +1,140 @@ +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler multicomponent equations + +# 1) Dry Air 2) Helium + 28% Air +equations = CompressibleEulerMulticomponentEquations2D(gammas = (1.4, 1.648), + gas_constants = (0.287, 1.578)) + +""" + initial_condition_shock_bubble(x, t, equations::CompressibleEulerMulticomponentEquations2D{5, 2}) + +A shock-bubble testcase for multicomponent Euler equations +- Ayoub Gouasmi, Karthik Duraisamy, Scott Murman + Formulation of Entropy-Stable schemes for the multicomponent compressible Euler equations + [arXiv: 1904.00972](https://arxiv.org/abs/1904.00972) +""" +function initial_condition_shock_bubble(x, t, + equations::CompressibleEulerMulticomponentEquations2D{5, + 2}) + # bubble test case, see Gouasmi et al. https://arxiv.org/pdf/1904.00972 + # other reference: https://www.researchgate.net/profile/Pep_Mulet/publication/222675930_A_flux-split_algorithm_applied_to_conservative_models_for_multicomponent_compressible_flows/links/568da54508aeaa1481ae7af0.pdf + # typical domain is rectangular, we change it to a square, as Trixi can only do squares + @unpack gas_constants = equations + + # Positivity Preserving Parameter, can be set to zero if scheme is positivity preserving + delta = 0.03 + + # Region I + rho1_1 = delta + rho2_1 = 1.225 * gas_constants[1] / gas_constants[2] - delta + v1_1 = zero(delta) + v2_1 = zero(delta) + p_1 = 101325 + + # Region II + rho1_2 = 1.225 - delta + rho2_2 = delta + v1_2 = zero(delta) + v2_2 = zero(delta) + p_2 = 101325 + + # Region III + rho1_3 = 1.6861 - delta + rho2_3 = delta + v1_3 = -113.5243 + v2_3 = zero(delta) + p_3 = 159060 + + # Set up Region I & II: + inicenter = SVector(zero(delta), zero(delta)) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + + if (x[1] > 0.50) + # Set up Region III + rho1 = rho1_3 + rho2 = rho2_3 + v1 = v1_3 + v2 = v2_3 + p = p_3 + elseif (r < 0.25) + # Set up Region I + rho1 = rho1_1 + rho2 = rho2_1 + v1 = v1_1 + v2 = v2_1 + p = p_1 + else + # Set up Region II + rho1 = rho1_2 + rho2 = rho2_2 + v1 = v1_2 + v2 = v2_2 + p = p_2 + end + + return prim2cons(SVector(v1, v2, p, rho1, rho2), equations) +end +initial_condition = initial_condition_shock_bubble + +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +basis = LobattoLegendreBasis(3) + +limiter_idp = SubcellLimiterIDP(equations, basis; + local_minmax_variables_cons = ["rho" * string(i) + for i in eachcomponent(equations)]) +volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) + +solver = DGSEM(basis, surface_flux, volume_integral) + +coordinates_min = (-2.25, -2.225) +coordinates_max = (2.20, 2.225) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level = 3, + n_cells_max = 1_000_000) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 0.01) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 300 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (Trixi.density,)) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 600, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) + +stepsize_callback = StepsizeCallback(cfl = 0.5) + +callbacks = CallbackSet(summary_callback, + analysis_callback, + alive_callback, + save_solution, + stepsize_callback) + +############################################################################### +# run the simulation + +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback(save_errors = false)) + +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); +summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl index a67eaeb5b2b..78ff47e255f 100644 --- a/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl +++ b/examples/tree_2d_dgsem/elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl @@ -5,7 +5,7 @@ using Trixi # semidiscretization of the compressible Euler multicomponent equations # 1) Dry Air 2) Helium + 28% Air -equations = CompressibleEulerMulticomponentEquations2D(gammas = (1.4, 1.648), +equations = CompressibleEulerMulticomponentEquations2D(gammas = (1.4, 1.648), gas_constants = (0.287, 1.578)) """ @@ -16,125 +16,129 @@ A shock-bubble testcase for multicomponent Euler equations Formulation of Entropy-Stable schemes for the multicomponent compressible Euler equations [arXiv: 1904.00972](https://arxiv.org/abs/1904.00972) """ -function initial_condition_shock_bubble(x, t, equations::CompressibleEulerMulticomponentEquations2D{5, 2}) - # bubble test case, see Gouasmi et al. https://arxiv.org/pdf/1904.00972 - # other reference: https://www.researchgate.net/profile/Pep_Mulet/publication/222675930_A_flux-split_algorithm_applied_to_conservative_models_for_multicomponent_compressible_flows/links/568da54508aeaa1481ae7af0.pdf - # typical domain is rectangular, we change it to a square, as Trixi can only do squares - @unpack gas_constants = equations - - # Positivity Preserving Parameter, can be set to zero if scheme is positivity preserving - delta = 0.03 - - # Region I - rho1_1 = delta - rho2_1 = 1.225 * gas_constants[1]/gas_constants[2] - delta - v1_1 = zero(delta) - v2_1 = zero(delta) - p_1 = 101325 - - # Region II - rho1_2 = 1.225-delta - rho2_2 = delta - v1_2 = zero(delta) - v2_2 = zero(delta) - p_2 = 101325 - - # Region III - rho1_3 = 1.6861 - delta - rho2_3 = delta - v1_3 = -113.5243 - v2_3 = zero(delta) - p_3 = 159060 - - # Set up Region I & II: - inicenter = SVector(zero(delta), zero(delta)) - x_norm = x[1] - inicenter[1] - y_norm = x[2] - inicenter[2] - r = sqrt(x_norm^2 + y_norm^2) - - if (x[1] > 0.50) - # Set up Region III - rho1 = rho1_3 - rho2 = rho2_3 - v1 = v1_3 - v2 = v2_3 - p = p_3 - elseif (r < 0.25) - # Set up Region I - rho1 = rho1_1 - rho2 = rho2_1 - v1 = v1_1 - v2 = v2_1 - p = p_1 - else - # Set up Region II - rho1 = rho1_2 - rho2 = rho2_2 - v1 = v1_2 - v2 = v2_2 - p = p_2 - end - - return prim2cons(SVector(v1, v2, p, rho1, rho2), equations) +function initial_condition_shock_bubble(x, t, + equations::CompressibleEulerMulticomponentEquations2D{5, + 2}) + # bubble test case, see Gouasmi et al. https://arxiv.org/pdf/1904.00972 + # other reference: https://www.researchgate.net/profile/Pep_Mulet/publication/222675930_A_flux-split_algorithm_applied_to_conservative_models_for_multicomponent_compressible_flows/links/568da54508aeaa1481ae7af0.pdf + # typical domain is rectangular, we change it to a square, as Trixi can only do squares + @unpack gas_constants = equations + + # Positivity Preserving Parameter, can be set to zero if scheme is positivity preserving + delta = 0.03 + + # Region I + rho1_1 = delta + rho2_1 = 1.225 * gas_constants[1] / gas_constants[2] - delta + v1_1 = zero(delta) + v2_1 = zero(delta) + p_1 = 101325 + + # Region II + rho1_2 = 1.225 - delta + rho2_2 = delta + v1_2 = zero(delta) + v2_2 = zero(delta) + p_2 = 101325 + + # Region III + rho1_3 = 1.6861 - delta + rho2_3 = delta + v1_3 = -113.5243 + v2_3 = zero(delta) + p_3 = 159060 + + # Set up Region I & II: + inicenter = SVector(zero(delta), zero(delta)) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + + if (x[1] > 0.50) + # Set up Region III + rho1 = rho1_3 + rho2 = rho2_3 + v1 = v1_3 + v2 = v2_3 + p = p_3 + elseif (r < 0.25) + # Set up Region I + rho1 = rho1_1 + rho2 = rho2_1 + v1 = v1_1 + v2 = v2_1 + p = p_1 + else + # Set up Region II + rho1 = rho1_2 + rho2 = rho2_2 + v1 = v1_2 + v2 = v2_2 + p = p_2 + end + + return prim2cons(SVector(v1, v2, p, rho1, rho2), equations) end initial_condition = initial_condition_shock_bubble -surface_flux = flux_lax_friedrichs -volume_flux = flux_ranocha -basis = LobattoLegendreBasis(3) +surface_flux = flux_lax_friedrichs +volume_flux = flux_ranocha +basis = LobattoLegendreBasis(3) limiter_idp = SubcellLimiterIDP(equations, basis; - positivity_variables_cons=[(i+3 for i in eachcomponent(equations))...]) + positivity_variables_cons = ["rho" * string(i) + for i in eachcomponent(equations)]) volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) -coordinates_min = (-2.25, -2.225) -coordinates_max = ( 2.20, 2.225) -mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=1_000_000) - -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) +coordinates_min = (-2.25, -2.225) +coordinates_max = (2.20, 2.225) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level = 3, + n_cells_max = 1_000_000) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) ############################################################################### # ODE solvers, callbacks etc. -tspan = (0.0, 0.01) -ode = semidiscretize(semi, tspan) - -summary_callback = SummaryCallback() +tspan = (0.0, 0.01) +ode = semidiscretize(semi, tspan) -analysis_interval = 300 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(Trixi.density,)) +summary_callback = SummaryCallback() -alive_callback = AliveCallback(analysis_interval=analysis_interval) +analysis_interval = 300 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (Trixi.density,)) -save_solution = SaveSolutionCallback(interval=300, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -stepsize_callback = StepsizeCallback(cfl=0.9) +save_solution = SaveSolutionCallback(interval = 300, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -callbacks = CallbackSet(summary_callback, - analysis_callback, - alive_callback, - save_solution, - stepsize_callback) +stepsize_callback = StepsizeCallback(cfl = 0.9) +callbacks = CallbackSet(summary_callback, + analysis_callback, + alive_callback, + save_solution, + stepsize_callback) ############################################################################### # run the simulation -stage_callbacks = (SubcellLimiterIDPCorrection(),) +output_directory = "out" +stage_callbacks = (SubcellLimiterIDPCorrection(), + BoundsCheckCallback(save_errors = true, interval = 100, + output_directory = output_directory)) -sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks=stage_callbacks); - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); -summary_callback() # print the timer summary \ No newline at end of file +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); +summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_eulerpolytropic_convergence.jl b/examples/tree_2d_dgsem/elixir_eulerpolytropic_convergence.jl new file mode 100644 index 00000000000..95ef38eb701 --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_eulerpolytropic_convergence.jl @@ -0,0 +1,63 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the polytropic Euler equations + +gamma = 1.4 +kappa = 0.5 # Scaling factor for the pressure. +equations = PolytropicEulerEquations2D(gamma, kappa) + +initial_condition = initial_condition_convergence_test + +volume_flux = flux_winters_etal +solver = DGSEM(polydeg = 3, surface_flux = FluxHLL(min_max_speed_davis), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) + +coordinates_min = (0.0, 0.0) +coordinates_max = (1.0, 1.0) + +# Create a uniformly refined mesh with periodic boundaries +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level = 2, + periodicity = true, + n_cells_max = 30_000) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + source_terms = source_terms_convergence_test) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 0.1) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_errors = (:l2_error_primitive, + :linf_error_primitive)) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) + +stepsize_callback = StepsizeCallback(cfl = 0.1) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + save_solution, + stepsize_callback) + +############################################################################### +# run the simulation + +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); +summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_hypdiff_godunov.jl b/examples/tree_2d_dgsem/elixir_hypdiff_godunov.jl index abf9735fd28..1700957d900 100644 --- a/examples/tree_2d_dgsem/elixir_hypdiff_godunov.jl +++ b/examples/tree_2d_dgsem/elixir_hypdiff_godunov.jl @@ -8,51 +8,50 @@ using Trixi equations = HyperbolicDiffusionEquations2D() function initial_condition_poisson_periodic(x, t, equations::HyperbolicDiffusionEquations2D) - # elliptic equation: -νΔϕ = f - # depending on initial constant state, c, for phi this converges to the solution ϕ + c - if iszero(t) - phi = 0.0 - q1 = 0.0 - q2 = 0.0 - else - phi = sin(2.0*pi*x[1])*sin(2.0*pi*x[2]) - q1 = 2*pi*cos(2.0*pi*x[1])*sin(2.0*pi*x[2]) - q2 = 2*pi*sin(2.0*pi*x[1])*cos(2.0*pi*x[2]) - end - return SVector(phi, q1, q2) + # elliptic equation: -νΔϕ = f + # depending on initial constant state, c, for phi this converges to the solution ϕ + c + if iszero(t) + phi = 0.0 + q1 = 0.0 + q2 = 0.0 + else + phi = sin(2.0 * pi * x[1]) * sin(2.0 * pi * x[2]) + q1 = 2 * pi * cos(2.0 * pi * x[1]) * sin(2.0 * pi * x[2]) + q2 = 2 * pi * sin(2.0 * pi * x[1]) * cos(2.0 * pi * x[2]) + end + return SVector(phi, q1, q2) end initial_condition = initial_condition_poisson_periodic -@inline function source_terms_poisson_periodic(u, x, t, equations::HyperbolicDiffusionEquations2D) - # elliptic equation: -νΔϕ = f - # analytical solution: phi = sin(2πx)*sin(2πy) and f = -8νπ^2 sin(2πx)*sin(2πy) - @unpack inv_Tr = equations - C = -8 * equations.nu * pi^2 - - x1, x2 = x - tmp1 = sinpi(2 * x1) - tmp2 = sinpi(2 * x2) - du1 = -C*tmp1*tmp2 - du2 = -inv_Tr * u[2] - du3 = -inv_Tr * u[3] - - return SVector(du1, du2, du3) +@inline function source_terms_poisson_periodic(u, x, t, + equations::HyperbolicDiffusionEquations2D) + # elliptic equation: -νΔϕ = f + # analytical solution: phi = sin(2πx)*sin(2πy) and f = -8νπ^2 sin(2πx)*sin(2πy) + @unpack inv_Tr = equations + C = -8 * equations.nu * pi^2 + + x1, x2 = x + tmp1 = sinpi(2 * x1) + tmp2 = sinpi(2 * x2) + du1 = -C * tmp1 * tmp2 + du2 = -inv_Tr * u[2] + du3 = -inv_Tr * u[3] + + return SVector(du1, du2, du3) end volume_flux = flux_central -solver = DGSEM(polydeg=4, surface_flux=flux_godunov, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 4, surface_flux = flux_godunov, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (0.0, 0.0) coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=30_000) - + initial_refinement_level = 3, + n_cells_max = 30_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_poisson_periodic) - + source_terms = source_terms_poisson_periodic) ############################################################################### # ODE solvers, callbacks etc. @@ -63,30 +62,29 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() resid_tol = 5.0e-12 -steady_state_callback = SteadyStateCallback(abstol=resid_tol, reltol=0.0) +steady_state_callback = SteadyStateCallback(abstol = resid_tol, reltol = 0.0) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, steady_state_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_hypdiff_harmonic_nonperiodic.jl b/examples/tree_2d_dgsem/elixir_hypdiff_harmonic_nonperiodic.jl index c144ef47a63..e70b91906b1 100644 --- a/examples/tree_2d_dgsem/elixir_hypdiff_harmonic_nonperiodic.jl +++ b/examples/tree_2d_dgsem/elixir_hypdiff_harmonic_nonperiodic.jl @@ -7,44 +7,43 @@ using Trixi equations = HyperbolicDiffusionEquations2D() -@inline function initial_condition_harmonic_nonperiodic(x, t, equations::HyperbolicDiffusionEquations2D) - # elliptic equation: -ν Δϕ = 0 in Ω, u = g on ∂Ω - if t == 0.0 - phi = 1.0 - q1 = 1.0 - q2 = 1.0 - else - C = inv(sinh(pi)) - sinpi_x1, cospi_x1 = sincos(pi*x[1]) - sinpi_x2, cospi_x2 = sincos(pi*x[2]) - sinh_pix1 = sinh(pi*x[1]) - cosh_pix1 = cosh(pi*x[1]) - sinh_pix2 = sinh(pi*x[2]) - cosh_pix2 = cosh(pi*x[2]) - phi = C * (sinh_pix1 * sinpi_x2 + sinh_pix2 * sinpi_x1) - q1 = C * pi * (cosh_pix1 * sinpi_x2 + sinh_pix2 * cospi_x1) - q2 = C * pi * (sinh_pix1 * cospi_x2 + cosh_pix2 * sinpi_x1) - end - return SVector(phi, q1, q2) +@inline function initial_condition_harmonic_nonperiodic(x, t, + equations::HyperbolicDiffusionEquations2D) + # elliptic equation: -ν Δϕ = 0 in Ω, u = g on ∂Ω + if t == 0.0 + phi = 1.0 + q1 = 1.0 + q2 = 1.0 + else + C = inv(sinh(pi)) + sinpi_x1, cospi_x1 = sincos(pi * x[1]) + sinpi_x2, cospi_x2 = sincos(pi * x[2]) + sinh_pix1 = sinh(pi * x[1]) + cosh_pix1 = cosh(pi * x[1]) + sinh_pix2 = sinh(pi * x[2]) + cosh_pix2 = cosh(pi * x[2]) + phi = C * (sinh_pix1 * sinpi_x2 + sinh_pix2 * sinpi_x1) + q1 = C * pi * (cosh_pix1 * sinpi_x2 + sinh_pix2 * cospi_x1) + q2 = C * pi * (sinh_pix1 * cospi_x2 + cosh_pix2 * sinpi_x1) + end + return SVector(phi, q1, q2) end initial_condition = initial_condition_harmonic_nonperiodic boundary_conditions = BoundaryConditionDirichlet(initial_condition) -solver = DGSEM(polydeg=4, surface_flux=flux_godunov) +solver = DGSEM(polydeg = 4, surface_flux = flux_godunov) coordinates_min = (0.0, 0.0) coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=30_000, - periodicity=false) - + initial_refinement_level = 3, + n_cells_max = 30_000, + periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions, - source_terms=source_terms_harmonic) - + boundary_conditions = boundary_conditions, + source_terms = source_terms_harmonic) ############################################################################### # ODE solvers, callbacks etc. @@ -55,30 +54,29 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() resid_tol = 5.0e-12 -steady_state_callback = SteadyStateCallback(abstol=resid_tol, reltol=0.0) +steady_state_callback = SteadyStateCallback(abstol = resid_tol, reltol = 0.0) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, steady_state_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_hypdiff_lax_friedrichs.jl b/examples/tree_2d_dgsem/elixir_hypdiff_lax_friedrichs.jl index d0d706981a2..a1a0397a46c 100644 --- a/examples/tree_2d_dgsem/elixir_hypdiff_lax_friedrichs.jl +++ b/examples/tree_2d_dgsem/elixir_hypdiff_lax_friedrichs.jl @@ -8,49 +8,48 @@ using Trixi equations = HyperbolicDiffusionEquations2D() function initial_condition_poisson_periodic(x, t, equations::HyperbolicDiffusionEquations2D) - # elliptic equation: -νΔϕ = f - # depending on initial constant state, c, for phi this converges to the solution ϕ + c - if iszero(t) - phi = 0.0 - q1 = 0.0 - q2 = 0.0 - else - phi = sin(2.0*pi*x[1])*sin(2.0*pi*x[2]) - q1 = 2*pi*cos(2.0*pi*x[1])*sin(2.0*pi*x[2]) - q2 = 2*pi*sin(2.0*pi*x[1])*cos(2.0*pi*x[2]) - end - return SVector(phi, q1, q2) + # elliptic equation: -νΔϕ = f + # depending on initial constant state, c, for phi this converges to the solution ϕ + c + if iszero(t) + phi = 0.0 + q1 = 0.0 + q2 = 0.0 + else + phi = sin(2.0 * pi * x[1]) * sin(2.0 * pi * x[2]) + q1 = 2 * pi * cos(2.0 * pi * x[1]) * sin(2.0 * pi * x[2]) + q2 = 2 * pi * sin(2.0 * pi * x[1]) * cos(2.0 * pi * x[2]) + end + return SVector(phi, q1, q2) end initial_condition = initial_condition_poisson_periodic -@inline function source_terms_poisson_periodic(u, x, t, equations::HyperbolicDiffusionEquations2D) - # elliptic equation: -νΔϕ = f - # analytical solution: phi = sin(2πx)*sin(2πy) and f = -8νπ^2 sin(2πx)*sin(2πy) - @unpack inv_Tr = equations - C = -8 * equations.nu * pi^2 - - x1, x2 = x - tmp1 = sinpi(2 * x1) - tmp2 = sinpi(2 * x2) - du1 = -C*tmp1*tmp2 - du2 = -inv_Tr * u[2] - du3 = -inv_Tr * u[3] - - return SVector(du1, du2, du3) +@inline function source_terms_poisson_periodic(u, x, t, + equations::HyperbolicDiffusionEquations2D) + # elliptic equation: -νΔϕ = f + # analytical solution: phi = sin(2πx)*sin(2πy) and f = -8νπ^2 sin(2πx)*sin(2πy) + @unpack inv_Tr = equations + C = -8 * equations.nu * pi^2 + + x1, x2 = x + tmp1 = sinpi(2 * x1) + tmp2 = sinpi(2 * x2) + du1 = -C * tmp1 * tmp2 + du2 = -inv_Tr * u[2] + du3 = -inv_Tr * u[3] + + return SVector(du1, du2, du3) end -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (0.0, 0.0) coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=30_000) - + initial_refinement_level = 3, + n_cells_max = 30_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_poisson_periodic) - + source_terms = source_terms_poisson_periodic) ############################################################################### # ODE solvers, callbacks etc. @@ -61,31 +60,30 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() resid_tol = 5.0e-12 -steady_state_callback = SteadyStateCallback(abstol=resid_tol, reltol=0.0) +steady_state_callback = SteadyStateCallback(abstol = resid_tol, reltol = 0.0) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy, energy_total)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy, energy_total)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.2) +stepsize_callback = StepsizeCallback(cfl = 1.2) callbacks = CallbackSet(summary_callback, steady_state_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation sol = Trixi.solve(ode, Trixi.HypDiffN3Erk3Sstar52(), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_hypdiff_nonperiodic.jl b/examples/tree_2d_dgsem/elixir_hypdiff_nonperiodic.jl index fc825660f1e..1396481a3f1 100644 --- a/examples/tree_2d_dgsem/elixir_hypdiff_nonperiodic.jl +++ b/examples/tree_2d_dgsem/elixir_hypdiff_nonperiodic.jl @@ -9,25 +9,23 @@ equations = HyperbolicDiffusionEquations2D() initial_condition = initial_condition_poisson_nonperiodic # 1 => -x, 2 => +x, 3 => -y, 4 => +y as usual for orientations -boundary_conditions = (x_neg=boundary_condition_poisson_nonperiodic, - x_pos=boundary_condition_poisson_nonperiodic, - y_neg=boundary_condition_periodic, - y_pos=boundary_condition_periodic) +boundary_conditions = (x_neg = boundary_condition_poisson_nonperiodic, + x_pos = boundary_condition_poisson_nonperiodic, + y_neg = boundary_condition_periodic, + y_pos = boundary_condition_periodic) -solver = DGSEM(polydeg=4, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 4, surface_flux = flux_lax_friedrichs) coordinates_min = (0.0, 0.0) coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=30_000, - periodicity=(false, true)) - + initial_refinement_level = 3, + n_cells_max = 30_000, + periodicity = (false, true)) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions, - source_terms=source_terms_poisson_nonperiodic) - + boundary_conditions = boundary_conditions, + source_terms = source_terms_poisson_nonperiodic) ############################################################################### # ODE solvers, callbacks etc. @@ -38,30 +36,29 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() resid_tol = 5.0e-12 -steady_state_callback = SteadyStateCallback(abstol=resid_tol, reltol=0.0) +steady_state_callback = SteadyStateCallback(abstol = resid_tol, reltol = 0.0) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, steady_state_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_kpp.jl b/examples/tree_2d_dgsem/elixir_kpp.jl index f3cbc1cb664..b48bde0d155 100644 --- a/examples/tree_2d_dgsem/elixir_kpp.jl +++ b/examples/tree_2d_dgsem/elixir_kpp.jl @@ -25,22 +25,25 @@ end @inline function Trixi.flux_ec(u_ll, u_rr, orientation::Integer, ::KPPEquation2D) # The tolerance of 1e-12 is based on experience and somewhat arbitrarily chosen if abs(u_ll[1] - u_rr[1]) < 1e-12 - return 0.5 * (flux(u_ll, orientation, KPPEquation2D()) + flux(u_rr, orientation, KPPEquation2D())) + return 0.5 * (flux(u_ll, orientation, KPPEquation2D()) + + flux(u_rr, orientation, KPPEquation2D())) else factor = 1.0 / (u_rr[1] - u_ll[1]) if orientation == 1 - return SVector(factor*(-cos(u_rr[1]) + cos(u_ll[1]))) + return SVector(factor * (-cos(u_rr[1]) + cos(u_ll[1]))) else - return SVector(factor*(sin(u_rr[1]) - sin(u_ll[1]))) + return SVector(factor * (sin(u_rr[1]) - sin(u_ll[1]))) end end end # Wavespeeds @inline wavespeed(::KPPEquation2D) = 1.0 -@inline Trixi.max_abs_speeds(u, equation::KPPEquation2D) = (wavespeed(equation), wavespeed(equation)) +@inline Trixi.max_abs_speeds(u, equation::KPPEquation2D) = (wavespeed(equation), + wavespeed(equation)) @inline Trixi.max_abs_speed_naive(u_ll, u_rr, orientation::Integer, equation::KPPEquation2D) = wavespeed(equation) -@inline Trixi.max_abs_speed_naive(u_ll, u_rr, normal_direction::AbstractVector, equation::KPPEquation2D) = wavespeed(equation) * norm(normal_direction) +@inline Trixi.max_abs_speed_naive(u_ll, u_rr, normal_direction::AbstractVector, equation::KPPEquation2D) = wavespeed(equation) * + norm(normal_direction) # Compute entropy: we use the square entropy @inline Trixi.entropy(u::Real, ::KPPEquation2D) = 0.5 * u^2 @@ -74,24 +77,25 @@ volume_flux = flux_ec polydeg = 3 basis = LobattoLegendreBasis(polydeg) shock_indicator = IndicatorHennemannGassner(equation, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=first) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = first) volume_integral = VolumeIntegralShockCapturingHG(shock_indicator; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) -solver = DGSEM(polydeg=polydeg, surface_flux=surface_flux, volume_integral=volume_integral) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) +solver = DGSEM(polydeg = polydeg, surface_flux = surface_flux, + volume_integral = volume_integral) ############################################################################### # Set up the tree mesh (initially a Cartesian grid of [-2,2]^2) coordinates_min = (-2.0, -2.0) -coordinates_max = ( 2.0, 2.0) +coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=6, - periodicity=true, - n_cells_max=500_000) + initial_refinement_level = 6, + periodicity = true, + n_cells_max = 500_000) ############################################################################### # Create the semi discretization object @@ -100,23 +104,24 @@ semi = SemidiscretizationHyperbolic(mesh, equation, initial_condition_kpp, solve ############################################################################### # Set up adaptive mesh refinement amr_indicator = IndicatorHennemannGassner(semi, - alpha_max=1.0, - alpha_min=0.0001, - alpha_smooth=false, - variable=first) + alpha_max = 1.0, + alpha_min = 0.0001, + alpha_smooth = false, + variable = first) max_refinement_level = 8 amr_controller = ControllerThreeLevelCombined(semi, amr_indicator, shock_indicator, - base_level=2, - med_level=0, med_threshold=0.0003, - max_level=max_refinement_level, max_threshold=0.003, - max_threshold_secondary=shock_indicator.alpha_max) + base_level = 2, + med_level = 0, med_threshold = 0.0003, + max_level = max_refinement_level, + max_threshold = 0.003, + max_threshold_secondary = shock_indicator.alpha_max) amr_callback = AMRCallback(semi, amr_controller, - interval=1, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 1, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) ############################################################################### # ODE solvers, callbacks etc. @@ -125,14 +130,14 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -analysis_callback = AnalysisCallback(semi, interval=200) +analysis_callback = AnalysisCallback(semi, interval = 200) -alive_callback = AliveCallback(analysis_interval=200) +alive_callback = AliveCallback(analysis_interval = 200) -save_solution = SaveSolutionCallback(interval=200, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2cons) +save_solution = SaveSolutionCallback(interval = 200, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2cons) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -140,6 +145,6 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, SSPRK43(); ode_default_options()..., callback=callbacks) +sol = solve(ode, SSPRK43(); ode_default_options()..., callback = callbacks) summary_callback() # Print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_lbm_constant.jl b/examples/tree_2d_dgsem/elixir_lbm_constant.jl index 40b16f41ef6..5a4f3074e4e 100644 --- a/examples/tree_2d_dgsem/elixir_lbm_constant.jl +++ b/examples/tree_2d_dgsem/elixir_lbm_constant.jl @@ -5,22 +5,20 @@ using Trixi ############################################################################### # semidiscretization of the Lattice-Boltzmann equations for the D2Q9 scheme -equations = LatticeBoltzmannEquations2D(Ma=0.1, Re=Inf) +equations = LatticeBoltzmannEquations2D(Ma = 0.1, Re = Inf) initial_condition = initial_condition_constant -solver = DGSEM(polydeg=3, surface_flux=flux_godunov) +solver = DGSEM(polydeg = 3, surface_flux = flux_godunov) coordinates_min = (-1.0, -1.0) -coordinates_max = ( 1.0, 1.0) +coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000,) - + initial_refinement_level = 4, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -30,19 +28,19 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2macroscopic) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2macroscopic) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) collision_callback = LBMCollisionCallback() @@ -52,11 +50,10 @@ callbacks = CallbackSet(summary_callback, stepsize_callback, collision_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_lbm_couette.jl b/examples/tree_2d_dgsem/elixir_lbm_couette.jl index 6a33b2fb0ee..1ba040405d1 100644 --- a/examples/tree_2d_dgsem/elixir_lbm_couette.jl +++ b/examples/tree_2d_dgsem/elixir_lbm_couette.jl @@ -5,7 +5,7 @@ using Trixi ############################################################################### # semidiscretization of the Lattice-Boltzmann equations for the D2Q9 scheme -equations = LatticeBoltzmannEquations2D(Ma=0.05, Re=2000) +equations = LatticeBoltzmannEquations2D(Ma = 0.05, Re = 2000) """ initial_condition_couette_unsteady(x, t, equations::LatticeBoltzmannEquations2D) @@ -16,19 +16,20 @@ incompressible Navier-Stokes equations. To be used in combination with this setup will converge to the state set in [`initial_condition_couette_steady`](@ref). """ function initial_condition_couette_unsteady(x, t, equations::LatticeBoltzmannEquations2D) - @unpack L, u0, rho0, nu = equations + @unpack L, u0, rho0, nu = equations - x1, x2 = x - v1 = u0*x2/L - for m in 1:100 - lambda_m = m * pi / L - v1 += 2 * u0 * (-1)^m/(lambda_m * L) * exp(-nu * lambda_m^2 * t) * sin(lambda_m * x2) - end + x1, x2 = x + v1 = u0 * x2 / L + for m in 1:100 + lambda_m = m * pi / L + v1 += 2 * u0 * (-1)^m / (lambda_m * L) * exp(-nu * lambda_m^2 * t) * + sin(lambda_m * x2) + end - rho = 1 - v2 = 0 + rho = 1 + v2 = 0 - return equilibrium_distribution(rho, v1, v2, equations) + return equilibrium_distribution(rho, v1, v2, equations) end initial_condition = initial_condition_couette_unsteady @@ -44,53 +45,49 @@ Moving *upper* wall boundary condition for a Couette flow setup. To be used in c function boundary_condition_couette(u_inner, orientation, direction, x, t, surface_flux_function, equations::LatticeBoltzmannEquations2D) - return boundary_condition_moving_wall_ypos(u_inner, orientation, direction, x, t, - surface_flux_function, equations) + return boundary_condition_moving_wall_ypos(u_inner, orientation, direction, x, t, + surface_flux_function, equations) end function boundary_condition_moving_wall_ypos(u_inner, orientation, direction, x, t, surface_flux_function, equations::LatticeBoltzmannEquations2D) - @assert direction == 4 "moving wall assumed in +y direction" + @assert direction==4 "moving wall assumed in +y direction" - @unpack rho0, u0, weights, c_s = equations - cs_squared = c_s^2 + @unpack rho0, u0, weights, c_s = equations + cs_squared = c_s^2 - pdf1 = u_inner[3] + 2 * weights[1] * rho0 * u0 / cs_squared - pdf2 = u_inner[2] # outgoing - pdf3 = u_inner[1] + 2 * weights[3] * rho0 * (-u0) / cs_squared - pdf4 = u_inner[2] - pdf5 = u_inner[5] # outgoing - pdf6 = u_inner[6] # outgoing - pdf7 = u_inner[5] + 2 * weights[7] * rho0 * (-u0) / cs_squared - pdf8 = u_inner[6] + 2 * weights[8] * rho0 * u0 / cs_squared - pdf9 = u_inner[9] + pdf1 = u_inner[3] + 2 * weights[1] * rho0 * u0 / cs_squared + pdf2 = u_inner[2] # outgoing + pdf3 = u_inner[1] + 2 * weights[3] * rho0 * (-u0) / cs_squared + pdf4 = u_inner[2] + pdf5 = u_inner[5] # outgoing + pdf6 = u_inner[6] # outgoing + pdf7 = u_inner[5] + 2 * weights[7] * rho0 * (-u0) / cs_squared + pdf8 = u_inner[6] + 2 * weights[8] * rho0 * u0 / cs_squared + pdf9 = u_inner[9] - u_boundary = SVector(pdf1, pdf2, pdf3, pdf4, pdf5, pdf6, pdf7, pdf8, pdf9) + u_boundary = SVector(pdf1, pdf2, pdf3, pdf4, pdf5, pdf6, pdf7, pdf8, pdf9) - # Calculate boundary flux (u_inner is "left" of boundary, u_boundary is "right" of boundary) - return surface_flux_function(u_inner, u_boundary, orientation, equations) + # Calculate boundary flux (u_inner is "left" of boundary, u_boundary is "right" of boundary) + return surface_flux_function(u_inner, u_boundary, orientation, equations) end -boundary_conditions = ( - x_neg=boundary_condition_periodic, - x_pos=boundary_condition_periodic, - y_neg=boundary_condition_noslip_wall, - y_pos=boundary_condition_couette, - ) +boundary_conditions = (x_neg = boundary_condition_periodic, + x_pos = boundary_condition_periodic, + y_neg = boundary_condition_noslip_wall, + y_pos = boundary_condition_couette) -solver = DGSEM(polydeg=3, surface_flux=flux_godunov) +solver = DGSEM(polydeg = 3, surface_flux = flux_godunov) coordinates_min = (0.0, 0.0) coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - periodicity=(true, false), - n_cells_max=10_000,) - + initial_refinement_level = 3, + periodicity = (true, false), + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -101,26 +98,29 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) # Custom solution variables: normalize velocities by reference speed `u0` @inline function macroscopic_normalized(u, equations::LatticeBoltzmannEquations2D) - macroscopic = cons2macroscopic(u, equations) - rho, v1, v2, p = macroscopic + macroscopic = cons2macroscopic(u, equations) + rho, v1, v2, p = macroscopic - # Use `typeof(macroscopic)` to avoid having to explicitly add `using StaticArrays` - convert(typeof(macroscopic), (rho, v1/equations.u0, v2/equations.u0, p)) + # Use `typeof(macroscopic)` to avoid having to explicitly add `using StaticArrays` + convert(typeof(macroscopic), (rho, v1 / equations.u0, v2 / equations.u0, p)) +end +function Trixi.varnames(::typeof(macroscopic_normalized), + equations::LatticeBoltzmannEquations2D) + ("rho", "v1_normalized", "v2_normalized", "p") end -Trixi.varnames(::typeof(macroscopic_normalized), equations::LatticeBoltzmannEquations2D) = ("rho", "v1_normalized", "v2_normalized", "p") -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=macroscopic_normalized) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = macroscopic_normalized) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) collision_callback = LBMCollisionCallback() @@ -130,11 +130,10 @@ callbacks = CallbackSet(summary_callback, stepsize_callback, collision_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_lbm_lid_driven_cavity.jl b/examples/tree_2d_dgsem/elixir_lbm_lid_driven_cavity.jl index a34e784e7ac..d00926cafad 100644 --- a/examples/tree_2d_dgsem/elixir_lbm_lid_driven_cavity.jl +++ b/examples/tree_2d_dgsem/elixir_lbm_lid_driven_cavity.jl @@ -5,7 +5,7 @@ using Trixi ############################################################################### # semidiscretization of the Lattice-Boltzmann equations for the D2Q9 scheme -equations = LatticeBoltzmannEquations2D(Ma=0.1, Re=1000) +equations = LatticeBoltzmannEquations2D(Ma = 0.1, Re = 1000) """ initial_condition_lid_driven_cavity(x, t, equations::LatticeBoltzmannEquations2D) @@ -14,13 +14,13 @@ Initial state for a lid-driven cavity flow setup. To be used in combination with [`boundary_condition_lid_driven_cavity`](@ref) and [`boundary_condition_noslip_wall`](@ref). """ function initial_condition_lid_driven_cavity(x, t, equations::LatticeBoltzmannEquations2D) - @unpack L, u0, nu = equations + @unpack L, u0, nu = equations - rho = 1 - v1 = 0 - v2 = 0 + rho = 1 + v1 = 0 + v2 = 0 - return equilibrium_distribution(rho, v1, v2, equations) + return equilibrium_distribution(rho, v1, v2, equations) end initial_condition = initial_condition_lid_driven_cavity @@ -35,53 +35,49 @@ no-slip wall. To be used in combination with [`initial_condition_lid_driven_cavi function boundary_condition_lid_driven_cavity(u_inner, orientation, direction, x, t, surface_flux_function, equations::LatticeBoltzmannEquations2D) - return boundary_condition_moving_wall_ypos(u_inner, orientation, direction, x, t, - surface_flux_function, equations) + return boundary_condition_moving_wall_ypos(u_inner, orientation, direction, x, t, + surface_flux_function, equations) end function boundary_condition_moving_wall_ypos(u_inner, orientation, direction, x, t, surface_flux_function, equations::LatticeBoltzmannEquations2D) - @assert direction == 4 "moving wall assumed in +y direction" + @assert direction==4 "moving wall assumed in +y direction" - @unpack rho0, u0, weights, c_s = equations - cs_squared = c_s^2 + @unpack rho0, u0, weights, c_s = equations + cs_squared = c_s^2 - pdf1 = u_inner[3] + 2 * weights[1] * rho0 * u0 / cs_squared - pdf2 = u_inner[2] # outgoing - pdf3 = u_inner[1] + 2 * weights[3] * rho0 * (-u0) / cs_squared - pdf4 = u_inner[2] - pdf5 = u_inner[5] # outgoing - pdf6 = u_inner[6] # outgoing - pdf7 = u_inner[5] + 2 * weights[7] * rho0 * (-u0) / cs_squared - pdf8 = u_inner[6] + 2 * weights[8] * rho0 * u0 / cs_squared - pdf9 = u_inner[9] + pdf1 = u_inner[3] + 2 * weights[1] * rho0 * u0 / cs_squared + pdf2 = u_inner[2] # outgoing + pdf3 = u_inner[1] + 2 * weights[3] * rho0 * (-u0) / cs_squared + pdf4 = u_inner[2] + pdf5 = u_inner[5] # outgoing + pdf6 = u_inner[6] # outgoing + pdf7 = u_inner[5] + 2 * weights[7] * rho0 * (-u0) / cs_squared + pdf8 = u_inner[6] + 2 * weights[8] * rho0 * u0 / cs_squared + pdf9 = u_inner[9] - u_boundary = SVector(pdf1, pdf2, pdf3, pdf4, pdf5, pdf6, pdf7, pdf8, pdf9) + u_boundary = SVector(pdf1, pdf2, pdf3, pdf4, pdf5, pdf6, pdf7, pdf8, pdf9) - # Calculate boundary flux (u_inner is "left" of boundary, u_boundary is "right" of boundary) - return surface_flux_function(u_inner, u_boundary, orientation, equations) + # Calculate boundary flux (u_inner is "left" of boundary, u_boundary is "right" of boundary) + return surface_flux_function(u_inner, u_boundary, orientation, equations) end -boundary_conditions = ( - x_neg=boundary_condition_noslip_wall, - x_pos=boundary_condition_noslip_wall, - y_neg=boundary_condition_noslip_wall, - y_pos=boundary_condition_lid_driven_cavity, - ) +boundary_conditions = (x_neg = boundary_condition_noslip_wall, + x_pos = boundary_condition_noslip_wall, + y_neg = boundary_condition_noslip_wall, + y_pos = boundary_condition_lid_driven_cavity) -solver = DGSEM(polydeg=5, surface_flux=flux_godunov) +solver = DGSEM(polydeg = 5, surface_flux = flux_godunov) coordinates_min = (0.0, 0.0) coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - periodicity=false, - n_cells_max=10_000,) - + initial_refinement_level = 4, + periodicity = false, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -92,16 +88,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2macroscopic) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2macroscopic) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) collision_callback = LBMCollisionCallback() @@ -111,11 +107,10 @@ callbacks = CallbackSet(summary_callback, stepsize_callback, collision_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_linearizedeuler_convergence.jl b/examples/tree_2d_dgsem/elixir_linearizedeuler_convergence.jl index 14459fa4cb8..93272833b74 100644 --- a/examples/tree_2d_dgsem/elixir_linearizedeuler_convergence.jl +++ b/examples/tree_2d_dgsem/elixir_linearizedeuler_convergence.jl @@ -4,25 +4,25 @@ using Trixi ############################################################################### # semidiscretization of the linearized Euler equations -equations = LinearizedEulerEquations2D(v_mean_global=(0.0, 0.0), c_mean_global=1.0, rho_mean_global=1.0) +equations = LinearizedEulerEquations2D(v_mean_global = (0.0, 0.0), c_mean_global = 1.0, + rho_mean_global = 1.0) initial_condition = initial_condition_convergence_test # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-1.0, -1.0) # minimum coordinates (min(x), min(y)) -coordinates_max = ( 1.0, 1.0) # maximum coordinates (max(x), max(y)) +coordinates_max = (1.0, 1.0) # maximum coordinates (max(x), max(y)) # Create a uniformly refined mesh with periodic boundaries mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=30_000) + initial_refinement_level = 4, + n_cells_max = 30_000) # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -37,28 +37,29 @@ summary_callback = SummaryCallback() analysis_interval = 100 # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=analysis_interval, solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = analysis_interval, + solution_variables = cons2prim) # The AliveCallback prints short status information in regular intervals -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=0.8) +stepsize_callback = StepsizeCallback(cfl = 0.8) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, alive_callback, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, alive_callback, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); # print the timer summary summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_linearizedeuler_gauss_wall.jl b/examples/tree_2d_dgsem/elixir_linearizedeuler_gauss_wall.jl index 14fe201a291..fad03fab6ef 100644 --- a/examples/tree_2d_dgsem/elixir_linearizedeuler_gauss_wall.jl +++ b/examples/tree_2d_dgsem/elixir_linearizedeuler_gauss_wall.jl @@ -5,33 +5,32 @@ using Trixi ############################################################################### # semidiscretization of the linearized Euler equations -equations = LinearizedEulerEquations2D(v_mean_global=(0.5, 0.0), c_mean_global=1.0, - rho_mean_global=1.0) +equations = LinearizedEulerEquations2D(v_mean_global = (0.5, 0.0), c_mean_global = 1.0, + rho_mean_global = 1.0) # Create DG solver with polynomial degree = 5 and upwind flux as surface flux -solver = DGSEM(polydeg=5, surface_flux=flux_godunov) +solver = DGSEM(polydeg = 5, surface_flux = flux_godunov) coordinates_min = (-100.0, 0.0) # minimum coordinates (min(x), min(y)) coordinates_max = (100.0, 200.0) # maximum coordinates (max(x), max(y)) # Create a uniformly refined mesh with periodic boundaries mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=100_000, - periodicity=false) + initial_refinement_level = 4, + n_cells_max = 100_000, + periodicity = false) function initial_condition_gauss_wall(x, t, equations::LinearizedEulerEquations2D) - v1_prime = 0.0 - v2_prime = 0.0 - rho_prime = p_prime = exp(-log(2) * (x[1]^2 + (x[2] - 25)^2) / 25) - return SVector(rho_prime, v1_prime, v2_prime, p_prime) + v1_prime = 0.0 + v2_prime = 0.0 + rho_prime = p_prime = exp(-log(2) * (x[1]^2 + (x[2] - 25)^2) / 25) + return SVector(rho_prime, v1_prime, v2_prime, p_prime) end initial_condition = initial_condition_gauss_wall # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_condition_wall) - + boundary_conditions = boundary_condition_wall) ############################################################################### # ODE solvers, callbacks etc. @@ -45,24 +44,25 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100) +save_solution = SaveSolutionCallback(interval = 100) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=0.7) +stepsize_callback = StepsizeCallback(cfl = 0.7) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks) +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks) # Print the timer summary summary_callback() diff --git a/examples/tree_2d_dgsem/elixir_mhd_alfven_wave.jl b/examples/tree_2d_dgsem/elixir_mhd_alfven_wave.jl index d9e59160e7d..377a07e947e 100644 --- a/examples/tree_2d_dgsem/elixir_mhd_alfven_wave.jl +++ b/examples/tree_2d_dgsem/elixir_mhd_alfven_wave.jl @@ -4,25 +4,24 @@ using Trixi ############################################################################### # semidiscretization of the compressible ideal GLM-MHD equations -gamma = 5/3 +gamma = 5 / 3 equations = IdealGlmMhdEquations2D(gamma) initial_condition = initial_condition_convergence_test volume_flux = (flux_central, flux_nonconservative_powell) -solver = DGSEM(polydeg=3, surface_flux=(flux_lax_friedrichs, flux_nonconservative_powell), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, + surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (0.0, 0.0) coordinates_max = (sqrt(2.0), sqrt(2.0)) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) - + initial_refinement_level = 4, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -32,22 +31,25 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=true, - extra_analysis_integrals=(entropy, energy_total, - energy_kinetic, energy_internal, - energy_magnetic, cross_helicity)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true, + extra_analysis_integrals = (entropy, energy_total, + energy_kinetic, + energy_internal, + energy_magnetic, + cross_helicity)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=10, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 10, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) cfl = 1.5 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -56,11 +58,10 @@ callbacks = CallbackSet(summary_callback, stepsize_callback, glm_speed_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_mhd_alfven_wave_mortar.jl b/examples/tree_2d_dgsem/elixir_mhd_alfven_wave_mortar.jl index 11dfeacde6a..0200b591844 100644 --- a/examples/tree_2d_dgsem/elixir_mhd_alfven_wave_mortar.jl +++ b/examples/tree_2d_dgsem/elixir_mhd_alfven_wave_mortar.jl @@ -4,25 +4,25 @@ using Trixi ############################################################################### # semidiscretization of the compressible ideal GLM-MHD equations -gamma = 5/3 +gamma = 5 / 3 equations = IdealGlmMhdEquations2D(gamma) initial_condition = initial_condition_convergence_test volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) -solver = DGSEM(polydeg=3, surface_flux=(flux_hll, flux_nonconservative_powell), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, + surface_flux = (flux_hlle, + flux_nonconservative_powell), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (0.0, 0.0) coordinates_max = (sqrt(2.0), sqrt(2.0)) -refinement_patches = ( - (type="box", coordinates_min=0.25 .* coordinates_max, - coordinates_max=0.75 .* coordinates_max), -) +refinement_patches = ((type = "box", coordinates_min = 0.25 .* coordinates_max, + coordinates_max = 0.75 .* coordinates_max),) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - refinement_patches=refinement_patches, - n_cells_max=10_000,) + initial_refinement_level = 4, + refinement_patches = refinement_patches, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -35,22 +35,25 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=true, - extra_analysis_integrals=(entropy, energy_total, - energy_kinetic, energy_internal, - energy_magnetic, cross_helicity)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true, + extra_analysis_integrals = (entropy, energy_total, + energy_kinetic, + energy_internal, + energy_magnetic, + cross_helicity)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=10, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 10, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) cfl = 1.0 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -62,7 +65,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_mhd_blast_wave.jl b/examples/tree_2d_dgsem/elixir_mhd_blast_wave.jl index af05fffaf54..a0909ca7580 100644 --- a/examples/tree_2d_dgsem/elixir_mhd_blast_wave.jl +++ b/examples/tree_2d_dgsem/elixir_mhd_blast_wave.jl @@ -16,52 +16,50 @@ An MHD blast wave taken from [doi: 10.1365/s13291-018-0178-9](https://doi.org/10.1365/s13291-018-0178-9) """ function initial_condition_blast_wave(x, t, equations::IdealGlmMhdEquations2D) - # setup taken from Derigs et al. DMV article (2018) - # domain must be [-0.5, 0.5] x [-0.5, 0.5], γ = 1.4 - r = sqrt(x[1]^2 + x[2]^2) - f = (0.1 - r)/0.01 - if r <= 0.09 - p = 1000.0 - elseif r >= 0.1 - p = 0.1 - else - p = 0.1 + 999.9*f - end - rho = 1.0 - v1 = 0.0 - v2 = 0.0 - v3 = 0.0 - B1 = 100.0/sqrt(4.0*pi) - B2 = 0.0 - B3 = 0.0 - psi = 0.0 - return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3, psi), equations) + # setup taken from Derigs et al. DMV article (2018) + # domain must be [-0.5, 0.5] x [-0.5, 0.5], γ = 1.4 + r = sqrt(x[1]^2 + x[2]^2) + f = (0.1 - r) / 0.01 + if r <= 0.09 + p = 1000.0 + elseif r >= 0.1 + p = 0.1 + else + p = 0.1 + 999.9 * f + end + rho = 1.0 + v1 = 0.0 + v2 = 0.0 + v3 = 0.0 + B1 = 100.0 / sqrt(4.0 * pi) + B2 = 0.0 + B3 = 0.0 + psi = 0.0 + return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3, psi), equations) end initial_condition = initial_condition_blast_wave surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell) -volume_flux = (flux_central, flux_nonconservative_powell) +volume_flux = (flux_central, flux_nonconservative_powell) basis = LobattoLegendreBasis(3) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-0.5, -0.5) -coordinates_max = ( 0.5, 0.5) +coordinates_max = (0.5, 0.5) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) - + initial_refinement_level = 4, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -71,32 +69,32 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_indicator = IndicatorHennemannGassner(semi, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=false, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = false, + variable = density_pressure) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=4, - max_level =6, max_threshold=0.01) + base_level = 4, + max_level = 6, max_threshold = 0.01) amr_callback = AMRCallback(semi, amr_controller, - interval=7, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 7, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) cfl = 0.8 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -109,7 +107,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_mhd_ec.jl b/examples/tree_2d_dgsem/elixir_mhd_ec.jl index 5873388f798..173d3ed448f 100644 --- a/examples/tree_2d_dgsem/elixir_mhd_ec.jl +++ b/examples/tree_2d_dgsem/elixir_mhd_ec.jl @@ -10,19 +10,18 @@ equations = IdealGlmMhdEquations2D(1.4) initial_condition = initial_condition_weak_blast_wave volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) -solver = DGSEM(polydeg=3, surface_flux=(flux_hindenlang_gassner, flux_nonconservative_powell), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, + surface_flux = (flux_hindenlang_gassner, flux_nonconservative_powell), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-2.0, -2.0) -coordinates_max = ( 2.0, 2.0) +coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) - + initial_refinement_level = 4, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -32,19 +31,19 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=10, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 10, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) cfl = 1.0 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -53,11 +52,10 @@ callbacks = CallbackSet(summary_callback, stepsize_callback, glm_speed_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_mhd_orszag_tang.jl b/examples/tree_2d_dgsem/elixir_mhd_orszag_tang.jl index 460b24e02b2..7f26f270d6e 100644 --- a/examples/tree_2d_dgsem/elixir_mhd_orszag_tang.jl +++ b/examples/tree_2d_dgsem/elixir_mhd_orszag_tang.jl @@ -4,7 +4,7 @@ using Trixi ############################################################################### # semidiscretization of the compressible ideal GLM-MHD equations -gamma = 5/3 +gamma = 5 / 3 equations = IdealGlmMhdEquations2D(gamma) """ @@ -16,44 +16,42 @@ The classical Orszag-Tang vortex test case. Here, the setup is taken from [doi: 10.1365/s13291-018-0178-9](https://doi.org/10.1365/s13291-018-0178-9) """ function initial_condition_orszag_tang(x, t, equations::IdealGlmMhdEquations2D) - # setup taken from Derigs et al. DMV article (2018) - # domain must be [0, 1] x [0, 1], γ = 5/3 - rho = 1.0 - v1 = -sin(2.0*pi*x[2]) - v2 = sin(2.0*pi*x[1]) - v3 = 0.0 - p = 1.0 / equations.gamma - B1 = -sin(2.0*pi*x[2]) / equations.gamma - B2 = sin(4.0*pi*x[1]) / equations.gamma - B3 = 0.0 - psi = 0.0 - return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3, psi), equations) + # setup taken from Derigs et al. DMV article (2018) + # domain must be [0, 1] x [0, 1], γ = 5/3 + rho = 1.0 + v1 = -sin(2.0 * pi * x[2]) + v2 = sin(2.0 * pi * x[1]) + v3 = 0.0 + p = 1.0 / equations.gamma + B1 = -sin(2.0 * pi * x[2]) / equations.gamma + B2 = sin(4.0 * pi * x[1]) / equations.gamma + B3 = 0.0 + psi = 0.0 + return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3, psi), equations) end initial_condition = initial_condition_orszag_tang surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell) -volume_flux = (flux_central, flux_nonconservative_powell) +volume_flux = (flux_central, flux_nonconservative_powell) basis = LobattoLegendreBasis(3) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (0.0, 0.0) coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) - + initial_refinement_level = 4, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -63,32 +61,32 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_indicator = IndicatorHennemannGassner(semi, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=false, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = false, + variable = density_pressure) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=4, - max_level =6, max_threshold=0.01) + base_level = 4, + max_level = 6, max_threshold = 0.01) amr_callback = AMRCallback(semi, amr_controller, - interval=6, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 6, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) cfl = 1.25 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -101,7 +99,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_mhd_rotor.jl b/examples/tree_2d_dgsem/elixir_mhd_rotor.jl index c6d880e9e9d..3109b1ce303 100644 --- a/examples/tree_2d_dgsem/elixir_mhd_rotor.jl +++ b/examples/tree_2d_dgsem/elixir_mhd_rotor.jl @@ -2,7 +2,6 @@ using OrdinaryDiffEq using Trixi - ############################################################################### # semidiscretization of the compressible ideal GLM-MHD equations equations = IdealGlmMhdEquations2D(1.4) @@ -16,59 +15,57 @@ The classical MHD rotor test case. Here, the setup is taken from [doi: 10.1365/s13291-018-0178-9](https://doi.org/10.1365/s13291-018-0178-9) """ function initial_condition_rotor(x, t, equations::IdealGlmMhdEquations2D) - # setup taken from Derigs et al. DMV article (2018) - # domain must be [0, 1] x [0, 1], γ = 1.4 - dx = x[1] - 0.5 - dy = x[2] - 0.5 - r = sqrt(dx^2 + dy^2) - f = (0.115 - r)/0.015 - if r <= 0.1 - rho = 10.0 - v1 = -20.0*dy - v2 = 20.0*dx - elseif r >= 0.115 - rho = 1.0 - v1 = 0.0 - v2 = 0.0 - else - rho = 1.0 + 9.0*f - v1 = -20.0*f*dy - v2 = 20.0*f*dx - end - v3 = 0.0 - p = 1.0 - B1 = 5.0/sqrt(4.0*pi) - B2 = 0.0 - B3 = 0.0 - psi = 0.0 - return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3, psi), equations) + # setup taken from Derigs et al. DMV article (2018) + # domain must be [0, 1] x [0, 1], γ = 1.4 + dx = x[1] - 0.5 + dy = x[2] - 0.5 + r = sqrt(dx^2 + dy^2) + f = (0.115 - r) / 0.015 + if r <= 0.1 + rho = 10.0 + v1 = -20.0 * dy + v2 = 20.0 * dx + elseif r >= 0.115 + rho = 1.0 + v1 = 0.0 + v2 = 0.0 + else + rho = 1.0 + 9.0 * f + v1 = -20.0 * f * dy + v2 = 20.0 * f * dx + end + v3 = 0.0 + p = 1.0 + B1 = 5.0 / sqrt(4.0 * pi) + B2 = 0.0 + B3 = 0.0 + psi = 0.0 + return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3, psi), equations) end initial_condition = initial_condition_rotor surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell) -volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) +volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) polydeg = 4 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (0.0, 0.0) coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) - + initial_refinement_level = 4, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -78,32 +75,32 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_indicator = IndicatorHennemannGassner(semi, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=false, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = false, + variable = density_pressure) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=4, - max_level =6, max_threshold=0.01) + base_level = 4, + max_level = 6, max_threshold = 0.01) amr_callback = AMRCallback(semi, amr_controller, - interval=6, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 6, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) cfl = 0.35 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -116,7 +113,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl b/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl new file mode 100644 index 00000000000..fe9ad92467f --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_mhd_shockcapturing_subcell.jl @@ -0,0 +1,106 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible ideal GLM-MHD equations + +equations = IdealGlmMhdEquations2D(1.4) + +""" + initial_condition_blast_wave(x, t, equations::IdealGlmMhdEquations2D) + +An MHD blast wave modified from: +- Dominik Derigs, Gregor J. Gassner, Stefanie Walch & Andrew R. Winters (2018) + Entropy Stable Finite Volume Approximations for Ideal Magnetohydrodynamics + [doi: 10.1365/s13291-018-0178-9](https://doi.org/10.1365/s13291-018-0178-9) +This setup needs a positivity limiter for the density. +""" +function initial_condition_blast_wave(x, t, equations::IdealGlmMhdEquations2D) + # setup taken from Derigs et al. DMV article (2018) + # domain must be [-0.5, 0.5] x [-0.5, 0.5], γ = 1.4 + r = sqrt(x[1]^2 + x[2]^2) + + pmax = 10.0 + pmin = 1.0 + rhomax = 1.0 + rhomin = 0.01 + if r <= 0.09 + p = pmax + rho = rhomax + elseif r >= 0.1 + p = pmin + rho = rhomin + else + p = pmin + (0.1 - r) * (pmax - pmin) / 0.01 + rho = rhomin + (0.1 - r) * (rhomax - rhomin) / 0.01 + end + v1 = 0.0 + v2 = 0.0 + v3 = 0.0 + B1 = 1.0 / sqrt(4.0 * pi) + B2 = 0.0 + B3 = 0.0 + psi = 0.0 + return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3, psi), equations) +end +initial_condition = initial_condition_blast_wave + +surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell_local_symmetric) +volume_flux = (flux_derigs_etal, flux_nonconservative_powell_local_symmetric) +basis = LobattoLegendreBasis(3) + +limiter_idp = SubcellLimiterIDP(equations, basis; + positivity_variables_cons = ["rho"], + positivity_correction_factor = 0.5) +volume_integral = VolumeIntegralSubcellLimiting(limiter_idp; + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) +solver = DGSEM(basis, surface_flux, volume_integral) + +coordinates_min = (-0.5, -0.5) +coordinates_max = (0.5, 0.5) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level = 4, + n_cells_max = 10_000) + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 0.1) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) + +cfl = 0.5 +stepsize_callback = StepsizeCallback(cfl = cfl) + +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) + +callbacks = CallbackSet(summary_callback, + analysis_callback, + alive_callback, + save_solution, + stepsize_callback, + glm_speed_callback) + +############################################################################### +# run the simulation +stage_callbacks = (SubcellLimiterIDPCorrection(), BoundsCheckCallback()) + +sol = Trixi.solve(ode, Trixi.SimpleSSPRK33(stage_callbacks = stage_callbacks); + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); +summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_mhdmulti_convergence.jl b/examples/tree_2d_dgsem/elixir_mhdmulti_convergence.jl index a7551f48937..4f1f8c5f2b7 100644 --- a/examples/tree_2d_dgsem/elixir_mhdmulti_convergence.jl +++ b/examples/tree_2d_dgsem/elixir_mhdmulti_convergence.jl @@ -5,25 +5,24 @@ using Trixi ############################################################################### # semidiscretization of the compressible ideal GLM-MHD equations -equations = IdealGlmMhdMulticomponentEquations2D(gammas = (5/3, 5/3, 5/3), - gas_constants = (2.08, 2.08, 2.08)) +equations = IdealGlmMhdMulticomponentEquations2D(gammas = (5 / 3, 5 / 3, 5 / 3), + gas_constants = (2.08, 2.08, 2.08)) initial_condition = initial_condition_convergence_test volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) -solver = DGSEM(polydeg=3, surface_flux=(flux_lax_friedrichs, flux_nonconservative_powell), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, + surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (0.0, 0.0) coordinates_max = (sqrt(2), sqrt(2)) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=10_000) - + initial_refinement_level = 2, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -33,19 +32,20 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=true) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=10, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 10, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) cfl = 1.0 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -54,11 +54,10 @@ callbacks = CallbackSet(summary_callback, stepsize_callback, glm_speed_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_mhdmulti_ec.jl b/examples/tree_2d_dgsem/elixir_mhdmulti_ec.jl index ec2f3c21cdd..a7db9eeee96 100644 --- a/examples/tree_2d_dgsem/elixir_mhdmulti_ec.jl +++ b/examples/tree_2d_dgsem/elixir_mhdmulti_ec.jl @@ -5,25 +5,24 @@ using Trixi ############################################################################### # semidiscretization of the compressible ideal GLM-MHD equations -equations = IdealGlmMhdMulticomponentEquations2D(gammas = (1.4, 1.4), - gas_constants = (1.0, 1.0)) +equations = IdealGlmMhdMulticomponentEquations2D(gammas = (1.4, 1.4), + gas_constants = (1.0, 1.0)) initial_condition = initial_condition_weak_blast_wave volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) -solver = DGSEM(polydeg=3, surface_flux=(flux_hindenlang_gassner, flux_nonconservative_powell), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, + surface_flux = (flux_hindenlang_gassner, flux_nonconservative_powell), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-2.0, -2.0) -coordinates_max = ( 2.0, 2.0) +coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) - + initial_refinement_level = 4, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -33,19 +32,19 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=10, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 10, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) cfl = 1.0 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -54,11 +53,10 @@ callbacks = CallbackSet(summary_callback, stepsize_callback, glm_speed_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_mhdmulti_es.jl b/examples/tree_2d_dgsem/elixir_mhdmulti_es.jl index 3cd9c621ae3..fcaabdc7a58 100644 --- a/examples/tree_2d_dgsem/elixir_mhdmulti_es.jl +++ b/examples/tree_2d_dgsem/elixir_mhdmulti_es.jl @@ -5,25 +5,24 @@ using Trixi ############################################################################### # semidiscretization of the compressible ideal GLM-MHD equations -equations = IdealGlmMhdMulticomponentEquations2D(gammas = (5/3, 5/3), - gas_constants = (0.2, 0.2)) +equations = IdealGlmMhdMulticomponentEquations2D(gammas = (5 / 3, 5 / 3), + gas_constants = (0.2, 0.2)) initial_condition = initial_condition_weak_blast_wave volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) -solver = DGSEM(polydeg=3, surface_flux=(flux_lax_friedrichs, flux_nonconservative_powell), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, + surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-2.0, -2.0) -coordinates_max = ( 2.0, 2.0) +coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) - + initial_refinement_level = 4, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -33,19 +32,19 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=10, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 10, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) cfl = 1.0 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -54,11 +53,10 @@ callbacks = CallbackSet(summary_callback, stepsize_callback, glm_speed_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_mhdmulti_rotor.jl b/examples/tree_2d_dgsem/elixir_mhdmulti_rotor.jl index 55a4004f794..5ca21cc5e9c 100644 --- a/examples/tree_2d_dgsem/elixir_mhdmulti_rotor.jl +++ b/examples/tree_2d_dgsem/elixir_mhdmulti_rotor.jl @@ -2,10 +2,9 @@ using OrdinaryDiffEq using Trixi - ############################################################################### # semidiscretization of the compressible ideal GLM-MHD equations -equations = IdealGlmMhdMulticomponentEquations2D(gammas = (1.4, 1.4), +equations = IdealGlmMhdMulticomponentEquations2D(gammas = (1.4, 1.4), gas_constants = (1.0, 1.0)) """ @@ -14,62 +13,60 @@ equations = IdealGlmMhdMulticomponentEquations2D(gammas = (1.4, 1.4), The classical MHD rotor test case adapted to two density components. """ function initial_condition_rotor(x, t, equations::IdealGlmMhdMulticomponentEquations2D) - # setup taken from Derigs et al. DMV article (2018) - # domain must be [0, 1] x [0, 1], γ = 1.4 - dx = x[1] - 0.5 - dy = x[2] - 0.5 - r = sqrt(dx^2 + dy^2) - f = (0.115 - r)/0.015 - if r <= 0.1 - rho1 = 10.0 - rho2 = 5.0 - v1 = -20.0*dy - v2 = 20.0*dx - elseif r >= 0.115 - rho1 = 1.0 - rho2 = 0.5 - v1 = 0.0 - v2 = 0.0 - else - rho1 = 1.0 + 9.0*f - rho2 = 0.5 + 4.5*f - v1 = -20.0*f*dy - v2 = 20.0*f*dx - end - v3 = 0.0 - p = 1.0 - B1 = 5.0/sqrt(4.0*pi) - B2 = 0.0 - B3 = 0.0 - psi = 0.0 - return prim2cons(SVector(v1, v2, v3, p, B1, B2, B3, psi, rho1, rho2), equations) + # setup taken from Derigs et al. DMV article (2018) + # domain must be [0, 1] x [0, 1], γ = 1.4 + dx = x[1] - 0.5 + dy = x[2] - 0.5 + r = sqrt(dx^2 + dy^2) + f = (0.115 - r) / 0.015 + if r <= 0.1 + rho1 = 10.0 + rho2 = 5.0 + v1 = -20.0 * dy + v2 = 20.0 * dx + elseif r >= 0.115 + rho1 = 1.0 + rho2 = 0.5 + v1 = 0.0 + v2 = 0.0 + else + rho1 = 1.0 + 9.0 * f + rho2 = 0.5 + 4.5 * f + v1 = -20.0 * f * dy + v2 = 20.0 * f * dx + end + v3 = 0.0 + p = 1.0 + B1 = 5.0 / sqrt(4.0 * pi) + B2 = 0.0 + B3 = 0.0 + psi = 0.0 + return prim2cons(SVector(v1, v2, v3, p, B1, B2, B3, psi, rho1, rho2), equations) end initial_condition = initial_condition_rotor surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell) -volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) +volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.8, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.8, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (0.0, 0.0) coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) - + initial_refinement_level = 4, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -79,32 +76,32 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_indicator = IndicatorHennemannGassner(semi, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=false, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = false, + variable = density_pressure) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=4, - max_level =6, max_threshold=0.01) + base_level = 4, + max_level = 6, max_threshold = 0.01) amr_callback = AMRCallback(semi, amr_controller, - interval=6, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 6, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) cfl = 1.0 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -117,7 +114,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_navierstokes_convergence.jl b/examples/tree_2d_dgsem/elixir_navierstokes_convergence.jl index b68e9e6c97e..b0c8678baad 100644 --- a/examples/tree_2d_dgsem/elixir_navierstokes_convergence.jl +++ b/examples/tree_2d_dgsem/elixir_navierstokes_convergence.jl @@ -8,163 +8,171 @@ prandtl_number() = 0.72 mu() = 0.01 equations = CompressibleEulerEquations2D(1.4) -equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu=mu(), Prandtl=prandtl_number(), - gradient_variables=GradientVariablesPrimitive()) +equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu = mu(), + Prandtl = prandtl_number(), + gradient_variables = GradientVariablesPrimitive()) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralWeakForm()) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralWeakForm()) coordinates_min = (-1.0, -1.0) # minimum coordinates (min(x), min(y)) -coordinates_max = ( 1.0, 1.0) # maximum coordinates (max(x), max(y)) +coordinates_max = (1.0, 1.0) # maximum coordinates (max(x), max(y)) # Create a uniformly refined mesh with periodic boundaries mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - periodicity=(true, false), - n_cells_max=30_000) # set maximum capacity of tree data structure + initial_refinement_level = 4, + periodicity = (true, false), + n_cells_max = 30_000) # set maximum capacity of tree data structure # Note: the initial condition cannot be specialized to `CompressibleNavierStokesDiffusion2D` # since it is called by both the parabolic solver (which passes in `CompressibleNavierStokesDiffusion2D`) # and by the initial condition (which passes in `CompressibleEulerEquations2D`). # This convergence test setup was originally derived by Andrew Winters (@andrewwinters5000) function initial_condition_navier_stokes_convergence_test(x, t, equations) - # Amplitude and shift - A = 0.5 - c = 2.0 + # Amplitude and shift + A = 0.5 + c = 2.0 - # convenience values for trig. functions - pi_x = pi * x[1] - pi_y = pi * x[2] - pi_t = pi * t + # convenience values for trig. functions + pi_x = pi * x[1] + pi_y = pi * x[2] + pi_t = pi * t - rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t) - v1 = sin(pi_x) * log(x[2] + 2.0) * (1.0 - exp(-A * (x[2] - 1.0)) ) * cos(pi_t) - v2 = v1 - p = rho^2 + rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t) + v1 = sin(pi_x) * log(x[2] + 2.0) * (1.0 - exp(-A * (x[2] - 1.0))) * cos(pi_t) + v2 = v1 + p = rho^2 - return prim2cons(SVector(rho, v1, v2, p), equations) + return prim2cons(SVector(rho, v1, v2, p), equations) end @inline function source_terms_navier_stokes_convergence_test(u, x, t, equations) - y = x[2] - - # TODO: parabolic - # we currently need to hardcode these parameters until we fix the "combined equation" issue - # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 - inv_gamma_minus_one = inv(equations.gamma - 1) - Pr = prandtl_number() - mu_ = mu() - - # Same settings as in `initial_condition` - # Amplitude and shift - A = 0.5 - c = 2.0 - - # convenience values for trig. functions - pi_x = pi * x[1] - pi_y = pi * x[2] - pi_t = pi * t - - # compute the manufactured solution and all necessary derivatives - rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t) - rho_t = -pi * A * sin(pi_x) * cos(pi_y) * sin(pi_t) - rho_x = pi * A * cos(pi_x) * cos(pi_y) * cos(pi_t) - rho_y = -pi * A * sin(pi_x) * sin(pi_y) * cos(pi_t) - rho_xx = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t) - rho_yy = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t) - - v1 = sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) - v1_t = -pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * sin(pi_t) - v1_x = pi * cos(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) - v1_y = sin(pi_x) * (A * log(y + 2.0) * exp(-A * (y - 1.0)) + (1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t) - v1_xx = -pi * pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) - v1_xy = pi * cos(pi_x) * (A * log(y + 2.0) * exp(-A * (y - 1.0)) + (1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t) - v1_yy = (sin(pi_x) * ( 2.0 * A * exp(-A * (y - 1.0)) / (y + 2.0) - - A * A * log(y + 2.0) * exp(-A * (y - 1.0)) - - (1.0 - exp(-A * (y - 1.0))) / ((y + 2.0) * (y + 2.0))) * cos(pi_t)) - v2 = v1 - v2_t = v1_t - v2_x = v1_x - v2_y = v1_y - v2_xx = v1_xx - v2_xy = v1_xy - v2_yy = v1_yy - - p = rho * rho - p_t = 2.0 * rho * rho_t - p_x = 2.0 * rho * rho_x - p_y = 2.0 * rho * rho_y - p_xx = 2.0 * rho * rho_xx + 2.0 * rho_x * rho_x - p_yy = 2.0 * rho * rho_yy + 2.0 * rho_y * rho_y - - # Note this simplifies slightly because the ansatz assumes that v1 = v2 - E = p * inv_gamma_minus_one + 0.5 * rho * (v1^2 + v2^2) - E_t = p_t * inv_gamma_minus_one + rho_t * v1^2 + 2.0 * rho * v1 * v1_t - E_x = p_x * inv_gamma_minus_one + rho_x * v1^2 + 2.0 * rho * v1 * v1_x - E_y = p_y * inv_gamma_minus_one + rho_y * v1^2 + 2.0 * rho * v1 * v1_y - - # Some convenience constants - T_const = equations.gamma * inv_gamma_minus_one / Pr - inv_rho_cubed = 1.0 / (rho^3) - - # compute the source terms - # density equation - du1 = rho_t + rho_x * v1 + rho * v1_x + rho_y * v2 + rho * v2_y - - # x-momentum equation - du2 = ( rho_t * v1 + rho * v1_t + p_x + rho_x * v1^2 - + 2.0 * rho * v1 * v1_x - + rho_y * v1 * v2 - + rho * v1_y * v2 - + rho * v1 * v2_y - # stress tensor from x-direction - - 4.0 / 3.0 * v1_xx * mu_ - + 2.0 / 3.0 * v2_xy * mu_ - - v1_yy * mu_ - - v2_xy * mu_ ) - # y-momentum equation - du3 = ( rho_t * v2 + rho * v2_t + p_y + rho_x * v1 * v2 - + rho * v1_x * v2 - + rho * v1 * v2_x - + rho_y * v2^2 - + 2.0 * rho * v2 * v2_y - # stress tensor from y-direction - - v1_xy * mu_ - - v2_xx * mu_ - - 4.0 / 3.0 * v2_yy * mu_ - + 2.0 / 3.0 * v1_xy * mu_ ) - # total energy equation - du4 = ( E_t + v1_x * (E + p) + v1 * (E_x + p_x) - + v2_y * (E + p) + v2 * (E_y + p_y) - # stress tensor and temperature gradient terms from x-direction - - 4.0 / 3.0 * v1_xx * v1 * mu_ - + 2.0 / 3.0 * v2_xy * v1 * mu_ - - 4.0 / 3.0 * v1_x * v1_x * mu_ - + 2.0 / 3.0 * v2_y * v1_x * mu_ - - v1_xy * v2 * mu_ - - v2_xx * v2 * mu_ - - v1_y * v2_x * mu_ - - v2_x * v2_x * mu_ - - T_const * inv_rho_cubed * ( p_xx * rho * rho - - 2.0 * p_x * rho * rho_x - + 2.0 * p * rho_x * rho_x - - p * rho * rho_xx ) * mu_ - # stress tensor and temperature gradient terms from y-direction - - v1_yy * v1 * mu_ - - v2_xy * v1 * mu_ - - v1_y * v1_y * mu_ - - v2_x * v1_y * mu_ - - 4.0 / 3.0 * v2_yy * v2 * mu_ - + 2.0 / 3.0 * v1_xy * v2 * mu_ - - 4.0 / 3.0 * v2_y * v2_y * mu_ - + 2.0 / 3.0 * v1_x * v2_y * mu_ - - T_const * inv_rho_cubed * ( p_yy * rho * rho - - 2.0 * p_y * rho * rho_y - + 2.0 * p * rho_y * rho_y - - p * rho * rho_yy ) * mu_ ) - - return SVector(du1, du2, du3, du4) + y = x[2] + + # TODO: parabolic + # we currently need to hardcode these parameters until we fix the "combined equation" issue + # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 + inv_gamma_minus_one = inv(equations.gamma - 1) + Pr = prandtl_number() + mu_ = mu() + + # Same settings as in `initial_condition` + # Amplitude and shift + A = 0.5 + c = 2.0 + + # convenience values for trig. functions + pi_x = pi * x[1] + pi_y = pi * x[2] + pi_t = pi * t + + # compute the manufactured solution and all necessary derivatives + rho = c + A * sin(pi_x) * cos(pi_y) * cos(pi_t) + rho_t = -pi * A * sin(pi_x) * cos(pi_y) * sin(pi_t) + rho_x = pi * A * cos(pi_x) * cos(pi_y) * cos(pi_t) + rho_y = -pi * A * sin(pi_x) * sin(pi_y) * cos(pi_t) + rho_xx = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t) + rho_yy = -pi * pi * A * sin(pi_x) * cos(pi_y) * cos(pi_t) + + v1 = sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) + v1_t = -pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * sin(pi_t) + v1_x = pi * cos(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) + v1_y = sin(pi_x) * + (A * log(y + 2.0) * exp(-A * (y - 1.0)) + + (1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t) + v1_xx = -pi * pi * sin(pi_x) * log(y + 2.0) * (1.0 - exp(-A * (y - 1.0))) * cos(pi_t) + v1_xy = pi * cos(pi_x) * + (A * log(y + 2.0) * exp(-A * (y - 1.0)) + + (1.0 - exp(-A * (y - 1.0))) / (y + 2.0)) * cos(pi_t) + v1_yy = (sin(pi_x) * + (2.0 * A * exp(-A * (y - 1.0)) / (y + 2.0) - + A * A * log(y + 2.0) * exp(-A * (y - 1.0)) - + (1.0 - exp(-A * (y - 1.0))) / ((y + 2.0) * (y + 2.0))) * cos(pi_t)) + v2 = v1 + v2_t = v1_t + v2_x = v1_x + v2_y = v1_y + v2_xx = v1_xx + v2_xy = v1_xy + v2_yy = v1_yy + + p = rho * rho + p_t = 2.0 * rho * rho_t + p_x = 2.0 * rho * rho_x + p_y = 2.0 * rho * rho_y + p_xx = 2.0 * rho * rho_xx + 2.0 * rho_x * rho_x + p_yy = 2.0 * rho * rho_yy + 2.0 * rho_y * rho_y + + # Note this simplifies slightly because the ansatz assumes that v1 = v2 + E = p * inv_gamma_minus_one + 0.5 * rho * (v1^2 + v2^2) + E_t = p_t * inv_gamma_minus_one + rho_t * v1^2 + 2.0 * rho * v1 * v1_t + E_x = p_x * inv_gamma_minus_one + rho_x * v1^2 + 2.0 * rho * v1 * v1_x + E_y = p_y * inv_gamma_minus_one + rho_y * v1^2 + 2.0 * rho * v1 * v1_y + + # Some convenience constants + T_const = equations.gamma * inv_gamma_minus_one / Pr + inv_rho_cubed = 1.0 / (rho^3) + + # compute the source terms + # density equation + du1 = rho_t + rho_x * v1 + rho * v1_x + rho_y * v2 + rho * v2_y + + # x-momentum equation + du2 = (rho_t * v1 + rho * v1_t + p_x + rho_x * v1^2 + + 2.0 * rho * v1 * v1_x + + rho_y * v1 * v2 + + rho * v1_y * v2 + + rho * v1 * v2_y - + # stress tensor from x-direction + 4.0 / 3.0 * v1_xx * mu_ + + 2.0 / 3.0 * v2_xy * mu_ - + v1_yy * mu_ - + v2_xy * mu_) + # y-momentum equation + du3 = (rho_t * v2 + rho * v2_t + p_y + rho_x * v1 * v2 + + rho * v1_x * v2 + + rho * v1 * v2_x + + rho_y * v2^2 + + 2.0 * rho * v2 * v2_y - + # stress tensor from y-direction + v1_xy * mu_ - + v2_xx * mu_ - + 4.0 / 3.0 * v2_yy * mu_ + + 2.0 / 3.0 * v1_xy * mu_) + # total energy equation + du4 = (E_t + v1_x * (E + p) + v1 * (E_x + p_x) + + v2_y * (E + p) + v2 * (E_y + p_y) - + # stress tensor and temperature gradient terms from x-direction + 4.0 / 3.0 * v1_xx * v1 * mu_ + + 2.0 / 3.0 * v2_xy * v1 * mu_ - + 4.0 / 3.0 * v1_x * v1_x * mu_ + + 2.0 / 3.0 * v2_y * v1_x * mu_ - + v1_xy * v2 * mu_ - + v2_xx * v2 * mu_ - + v1_y * v2_x * mu_ - + v2_x * v2_x * mu_ - + T_const * inv_rho_cubed * + (p_xx * rho * rho - + 2.0 * p_x * rho * rho_x + + 2.0 * p * rho_x * rho_x - + p * rho * rho_xx) * mu_ - + # stress tensor and temperature gradient terms from y-direction + v1_yy * v1 * mu_ - + v2_xy * v1 * mu_ - + v1_y * v1_y * mu_ - + v2_x * v1_y * mu_ - + 4.0 / 3.0 * v2_yy * v2 * mu_ + + 2.0 / 3.0 * v1_xy * v2 * mu_ - + 4.0 / 3.0 * v2_y * v2_y * mu_ + + 2.0 / 3.0 * v1_x * v2_y * mu_ - + T_const * inv_rho_cubed * + (p_yy * rho * rho - + 2.0 * p_y * rho * rho_y + + 2.0 * p * rho_y * rho_y - + p * rho * rho_yy) * mu_) + + return SVector(du1, du2, du3, du4) end initial_condition = initial_condition_navier_stokes_convergence_test @@ -175,23 +183,26 @@ velocity_bc_top_bottom = NoSlip() do x, t, equations return SVector(u[2], u[3]) end heat_bc_top_bottom = Adiabatic((x, t, equations) -> 0.0) -boundary_condition_top_bottom = BoundaryConditionNavierStokesWall(velocity_bc_top_bottom, heat_bc_top_bottom) +boundary_condition_top_bottom = BoundaryConditionNavierStokesWall(velocity_bc_top_bottom, + heat_bc_top_bottom) # define inviscid boundary conditions boundary_conditions = (; x_neg = boundary_condition_periodic, - x_pos = boundary_condition_periodic, - y_neg = boundary_condition_slip_wall, - y_pos = boundary_condition_slip_wall) + x_pos = boundary_condition_periodic, + y_neg = boundary_condition_slip_wall, + y_pos = boundary_condition_slip_wall) # define viscous boundary conditions boundary_conditions_parabolic = (; x_neg = boundary_condition_periodic, - x_pos = boundary_condition_periodic, - y_neg = boundary_condition_top_bottom, - y_pos = boundary_condition_top_bottom) + x_pos = boundary_condition_periodic, + y_neg = boundary_condition_top_bottom, + y_pos = boundary_condition_top_bottom) -semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver; - boundary_conditions=(boundary_conditions, boundary_conditions_parabolic), - source_terms=source_terms_navier_stokes_convergence_test) +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, solver; + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic), + source_terms = source_terms_navier_stokes_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -201,16 +212,15 @@ tspan = (0.0, 0.5) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) ############################################################################### # run the simulation time_int_tol = 1e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, dt = 1e-5, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, dt = 1e-5, + ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary - diff --git a/examples/tree_2d_dgsem/elixir_navierstokes_lid_driven_cavity.jl b/examples/tree_2d_dgsem/elixir_navierstokes_lid_driven_cavity.jl index 81e48737e79..70d76fc9075 100644 --- a/examples/tree_2d_dgsem/elixir_navierstokes_lid_driven_cavity.jl +++ b/examples/tree_2d_dgsem/elixir_navierstokes_lid_driven_cavity.jl @@ -9,28 +9,27 @@ prandtl_number() = 0.72 mu() = 0.001 equations = CompressibleEulerEquations2D(1.4) -equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu=mu(), - Prandtl=prandtl_number()) +equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu = mu(), + Prandtl = prandtl_number()) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-1.0, -1.0) # minimum coordinates (min(x), min(y)) -coordinates_max = ( 1.0, 1.0) # maximum coordinates (max(x), max(y)) +coordinates_max = (1.0, 1.0) # maximum coordinates (max(x), max(y)) # Create a uniformly refined mesh mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - periodicity=false, - n_cells_max=30_000) # set maximum capacity of tree data structure - + initial_refinement_level = 4, + periodicity = false, + n_cells_max = 30_000) # set maximum capacity of tree data structure function initial_condition_cavity(x, t, equations::CompressibleEulerEquations2D) - Ma = 0.1 - rho = 1.0 - u, v = 0.0, 0.0 - p = 1.0 / (Ma^2 * equations.gamma) - return prim2cons(SVector(rho, u, v, p), equations) + Ma = 0.1 + rho = 1.0 + u, v = 0.0, 0.0 + p = 1.0 / (Ma^2 * equations.gamma) + return prim2cons(SVector(rho, u, v, p), equations) end initial_condition = initial_condition_cavity @@ -41,19 +40,18 @@ heat_bc = Adiabatic((x, t, equations) -> 0.0) boundary_condition_lid = BoundaryConditionNavierStokesWall(velocity_bc_lid, heat_bc) boundary_condition_cavity = BoundaryConditionNavierStokesWall(velocity_bc_cavity, heat_bc) -# define periodic boundary conditions everywhere boundary_conditions = boundary_condition_slip_wall boundary_conditions_parabolic = (; x_neg = boundary_condition_cavity, - y_neg = boundary_condition_cavity, - y_pos = boundary_condition_lid, - x_pos = boundary_condition_cavity) + y_neg = boundary_condition_cavity, + y_pos = boundary_condition_lid, + x_pos = boundary_condition_cavity) # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver; - boundary_conditions=(boundary_conditions, - boundary_conditions_parabolic)) + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic)) ############################################################################### # ODE solvers, callbacks etc. @@ -63,17 +61,15 @@ tspan = (0.0, 25.0) ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=100) +alive_callback = AliveCallback(alive_interval = 100) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) -callbacks = CallbackSet(summary_callback, alive_callback) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) +callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) ############################################################################### # run the simulation time_int_tol = 1e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary - - diff --git a/examples/tree_2d_dgsem/elixir_navierstokes_shear_layer.jl b/examples/tree_2d_dgsem/elixir_navierstokes_shear_layer.jl deleted file mode 100644 index dd26fd8097b..00000000000 --- a/examples/tree_2d_dgsem/elixir_navierstokes_shear_layer.jl +++ /dev/null @@ -1,73 +0,0 @@ - -using OrdinaryDiffEq -using Trixi - -############################################################################### -# semidiscretization of the compressible Navier-Stokes equations - -# TODO: parabolic; unify names of these accessor functions -prandtl_number() = 0.72 -mu() = 1.0/3.0 * 10^(-3) # equivalent to Re = 3000 - -equations = CompressibleEulerEquations2D(1.4) -equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu=mu(), - Prandtl=prandtl_number()) - -function initial_condition_shear_layer(x, t, equations::CompressibleEulerEquations2D) - # Shear layer parameters - k = 80 - delta = 0.05 - u0 = 1.0 - - Ms = 0.1 # maximum Mach number - - rho = 1.0 - v1 = x[2] <= 0.5 ? u0 * tanh(k*(x[2]*0.5 - 0.25)) : u0 * tanh(k*(0.75 -x[2]*0.5)) - v2 = u0 * delta * sin(2*pi*(x[1]*0.5 + 0.25)) - p = (u0 / Ms)^2 * rho / equations.gamma # scaling to get Ms - - return prim2cons(SVector(rho, v1, v2, p), equations) -end -initial_condition = initial_condition_shear_layer - -volume_flux = flux_ranocha -solver = DGSEM(polydeg=3, surface_flux=flux_hllc, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) - -coordinates_min = (0.0, 0.0) -coordinates_max = (1.0, 1.0) -mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=100_000) - - -semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), - initial_condition, solver) - -############################################################################### -# ODE solvers, callbacks etc. - -tspan = (0.0, 2.0) -ode = semidiscretize(semi, tspan) - -summary_callback = SummaryCallback() - -analysis_interval = 50 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=true, - extra_analysis_integrals=(energy_kinetic, - energy_internal, - enstrophy)) - -alive_callback = AliveCallback(analysis_interval=analysis_interval,) - -callbacks = CallbackSet(summary_callback, - analysis_callback, - alive_callback) - -############################################################################### -# run the simulation - -time_int_tol = 1e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) -summary_callback() # print the timer summary \ No newline at end of file diff --git a/examples/tree_2d_dgsem/elixir_navierstokes_shearlayer_amr.jl b/examples/tree_2d_dgsem/elixir_navierstokes_shearlayer_amr.jl new file mode 100644 index 00000000000..4d92ea261e9 --- /dev/null +++ b/examples/tree_2d_dgsem/elixir_navierstokes_shearlayer_amr.jl @@ -0,0 +1,96 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Navier-Stokes equations + +# TODO: parabolic; unify names of these accessor functions +prandtl_number() = 0.72 +mu() = 1.0 / 3.0 * 10^(-5) # equivalent to Re = 30,000 + +equations = CompressibleEulerEquations2D(1.4) +equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu = mu(), + Prandtl = prandtl_number()) + +""" +A compressible version of the double shear layer initial condition. Adapted from +Brown and Minion (1995). + +- David L. Brown and Michael L. Minion (1995) + Performance of Under-resolved Two-Dimensional Incompressible Flow Simulations. + [DOI: 10.1006/jcph.1995.1205](https://doi.org/10.1006/jcph.1995.1205) +""" +function initial_condition_shear_layer(x, t, equations::CompressibleEulerEquations2D) + # Shear layer parameters + k = 80 + delta = 0.05 + u0 = 1.0 + + Ms = 0.1 # maximum Mach number + + rho = 1.0 + v1 = x[2] <= 0.5 ? u0 * tanh(k * (x[2] - 0.25)) : u0 * tanh(k * (0.75 - x[2])) + v2 = u0 * delta * sin(2 * pi * (x[1] + 0.25)) + p = (u0 / Ms)^2 * rho / equations.gamma # scaling to get Ms + + return prim2cons(SVector(rho, v1, v2, p), equations) +end +initial_condition = initial_condition_shear_layer + +volume_flux = flux_ranocha +solver = DGSEM(polydeg = 3, surface_flux = flux_hllc, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) + +coordinates_min = (0.0, 0.0) +coordinates_max = (1.0, 1.0) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level = 4, + n_cells_max = 100_000) + +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, solver) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 1.0) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 2000 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +# This uses velocity-based AMR +@inline function v1(u, equations::CompressibleEulerEquations2D) + rho, rho_v1, _, _ = u + return rho_v1 / rho +end +amr_indicator = IndicatorLöhner(semi, variable = v1) +amr_controller = ControllerThreeLevel(semi, amr_indicator, + base_level = 3, + med_level = 5, med_threshold = 0.2, + max_level = 7, max_threshold = 0.5) +amr_callback = AMRCallback(semi, amr_controller, + interval = 50, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) + +stepsize_callback = StepsizeCallback(cfl = 1.3) + +callbacks = CallbackSet(summary_callback, + analysis_callback, + alive_callback, + amr_callback, + stepsize_callback) + +############################################################################### +# run the simulation + +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); +summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_navierstokes_taylor_green_vortex.jl b/examples/tree_2d_dgsem/elixir_navierstokes_taylor_green_vortex.jl index c3cbc858f7b..a3e38bf6d92 100644 --- a/examples/tree_2d_dgsem/elixir_navierstokes_taylor_green_vortex.jl +++ b/examples/tree_2d_dgsem/elixir_navierstokes_taylor_green_vortex.jl @@ -10,8 +10,8 @@ prandtl_number() = 0.72 mu() = 6.25e-4 # equivalent to Re = 1600 equations = CompressibleEulerEquations2D(1.4) -equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu=mu(), - Prandtl=prandtl_number()) +equations_parabolic = CompressibleNavierStokesDiffusion2D(equations, mu = mu(), + Prandtl = prandtl_number()) """ initial_condition_taylor_green_vortex(x, t, equations::CompressibleEulerEquations2D) @@ -22,30 +22,30 @@ This forms the basis behind the 3D case found for instance in Simulation of the Compressible Taylor Green Vortex using High-Order Flux Reconstruction Schemes [DOI: 10.2514/6.2014-3210](https://doi.org/10.2514/6.2014-3210) """ -function initial_condition_taylor_green_vortex(x, t, equations::CompressibleEulerEquations2D) - A = 1.0 # magnitude of speed - Ms = 0.1 # maximum Mach number - - rho = 1.0 - v1 = A * sin(x[1]) * cos(x[2]) - v2 = -A * cos(x[1]) * sin(x[2]) - p = (A / Ms)^2 * rho / equations.gamma # scaling to get Ms - p = p + 1.0/4.0 * A^2 * rho * (cos(2*x[1]) + cos(2*x[2])) - - return prim2cons(SVector(rho, v1, v2, p), equations) +function initial_condition_taylor_green_vortex(x, t, + equations::CompressibleEulerEquations2D) + A = 1.0 # magnitude of speed + Ms = 0.1 # maximum Mach number + + rho = 1.0 + v1 = A * sin(x[1]) * cos(x[2]) + v2 = -A * cos(x[1]) * sin(x[2]) + p = (A / Ms)^2 * rho / equations.gamma # scaling to get Ms + p = p + 1.0 / 4.0 * A^2 * rho * (cos(2 * x[1]) + cos(2 * x[2])) + + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_taylor_green_vortex volume_flux = flux_ranocha -solver = DGSEM(polydeg=3, surface_flux=flux_hllc, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_hllc, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-1.0, -1.0) .* pi -coordinates_max = ( 1.0, 1.0) .* pi +coordinates_max = (1.0, 1.0) .* pi mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=100_000) - + initial_refinement_level = 4, + n_cells_max = 100_000) semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver) @@ -59,11 +59,12 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=true, - extra_analysis_integrals=(energy_kinetic, - energy_internal)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true, + extra_analysis_integrals = (energy_kinetic, + energy_internal)) -alive_callback = AliveCallback(analysis_interval=analysis_interval,) +alive_callback = AliveCallback(analysis_interval = analysis_interval) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -73,6 +74,6 @@ callbacks = CallbackSet(summary_callback, # run the simulation time_int_tol = 1e-9 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) -summary_callback() # print the timer summary \ No newline at end of file +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) +summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_shallowwater_conical_island.jl b/examples/tree_2d_dgsem/elixir_shallowwater_conical_island.jl index 7c60e35b03e..349b3741869 100644 --- a/examples/tree_2d_dgsem/elixir_shallowwater_conical_island.jl +++ b/examples/tree_2d_dgsem/elixir_shallowwater_conical_island.jl @@ -7,7 +7,7 @@ using Trixi # # TODO: TrixiShallowWater: wet/dry example elixir -equations = ShallowWaterEquations2D(gravity_constant=9.81, H0=1.4) +equations = ShallowWaterEquations2D(gravity_constant = 9.81, H0 = 1.4) """ initial_condition_conical_island(x, t, equations::ShallowWaterEquations2D) @@ -21,29 +21,29 @@ boundary condition with the initial values. Due to the dry cells at the boundary effect of an outflow which can be seen in the simulation. """ function initial_condition_conical_island(x, t, equations::ShallowWaterEquations2D) - # Set the background values + # Set the background values - v1 = 0.0 - v2 = 0.0 + v1 = 0.0 + v2 = 0.0 - x1, x2 = x - b = max(0.1, 1.0 - 4.0 * sqrt(x1^2 + x2^2)) + x1, x2 = x + b = max(0.1, 1.0 - 4.0 * sqrt(x1^2 + x2^2)) - # use a logistic function to transfer water height value smoothly - L = equations.H0 # maximum of function - x0 = 0.3 # center point of function - k = -25.0 # sharpness of transfer + # use a logistic function to transfer water height value smoothly + L = equations.H0 # maximum of function + x0 = 0.3 # center point of function + k = -25.0 # sharpness of transfer - H = max(b, L/(1.0 + exp(-k*(sqrt(x1^2+x2^2) - x0)))) + H = max(b, L / (1.0 + exp(-k * (sqrt(x1^2 + x2^2) - x0)))) - # It is mandatory to shift the water level at dry areas to make sure the water height h - # stays positive. The system would not be stable for h set to a hard 0 due to division by h in - # the computation of velocity, e.g., (h v1) / h. Therefore, a small dry state threshold - # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above - # for the ShallowWaterEquations and added to the initial condition if h = 0. - # This default value can be changed within the constructor call depending on the simulation setup. - H = max(H, b + equations.threshold_limiter) - return prim2cons(SVector(H, v1, v2, b), equations) + # It is mandatory to shift the water level at dry areas to make sure the water height h + # stays positive. The system would not be stable for h set to a hard 0 due to division by h in + # the computation of velocity, e.g., (h v1) / h. Therefore, a small dry state threshold + # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above + # for the ShallowWaterEquations and added to the initial condition if h = 0. + # This default value can be changed within the constructor call depending on the simulation setup. + H = max(H, b + equations.threshold_limiter) + return prim2cons(SVector(H, v1, v2, b), equations) end initial_condition = initial_condition_conical_island @@ -53,19 +53,20 @@ boundary_conditions = BoundaryConditionDirichlet(initial_condition) # Get the DG approximation space volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -surface_flux = (FluxHydrostaticReconstruction(flux_hll_chen_noelle, hydrostatic_reconstruction_chen_noelle), +surface_flux = (FluxHydrostaticReconstruction(flux_hll_chen_noelle, + hydrostatic_reconstruction_chen_noelle), flux_nonconservative_chen_noelle) basis = LobattoLegendreBasis(4) indicator_sc = IndicatorHennemannGassnerShallowWater(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=waterheight_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = waterheight_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) @@ -75,13 +76,13 @@ solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-1.0, -1.0) coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000, - periodicity=false) + initial_refinement_level = 4, + n_cells_max = 10_000, + periodicity = false) # Create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) + boundary_conditions = boundary_conditions) ############################################################################### # ODE solver @@ -95,22 +96,22 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) ############################################################################### # run the simulation -stage_limiter! = PositivityPreservingLimiterShallowWater(variables=(Trixi.waterheight,)) +stage_limiter! = PositivityPreservingLimiterShallowWater(variables = (Trixi.waterheight,)) sol = solve(ode, SSPRK43(stage_limiter!); - ode_default_options()..., callback=callbacks); + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_shallowwater_ec.jl b/examples/tree_2d_dgsem/elixir_shallowwater_ec.jl index eed0a350e7e..bc528ae7756 100644 --- a/examples/tree_2d_dgsem/elixir_shallowwater_ec.jl +++ b/examples/tree_2d_dgsem/elixir_shallowwater_ec.jl @@ -6,7 +6,7 @@ using Trixi # semidiscretization of the shallow water equations with a discontinuous # bottom topography function -equations = ShallowWaterEquations2D(gravity_constant=9.81) +equations = ShallowWaterEquations2D(gravity_constant = 9.81) # Note, this initial condition is used to compute errors in the analysis callback but the initialization is # overwritten by `initial_condition_ec_discontinuous_bottom` below. @@ -16,17 +16,18 @@ initial_condition = initial_condition_weak_blast_wave # Get the DG approximation space volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -solver = DGSEM(polydeg=4, surface_flux=(flux_fjordholm_etal, flux_nonconservative_fjordholm_etal), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 4, + surface_flux = (flux_fjordholm_etal, flux_nonconservative_fjordholm_etal), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### # Get the TreeMesh and setup a periodic mesh coordinates_min = (-1.0, -1.0) -coordinates_max = ( 1.0, 1.0) +coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=10_000) + initial_refinement_level = 2, + n_cells_max = 10_000) # Create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -46,45 +47,48 @@ ode = semidiscretize(semi, tspan) # In contrast to the usual signature of initial conditions, this one get passed the # `element_id` explicitly. In particular, this initial conditions works as intended # only for the TreeMesh2D with initial_refinement_level=2. -function initial_condition_ec_discontinuous_bottom(x, t, element_id, equations::ShallowWaterEquations2D) - # Set up polar coordinates - inicenter = SVector(0.7, 0.7) - x_norm = x[1] - inicenter[1] - y_norm = x[2] - inicenter[2] - r = sqrt(x_norm^2 + y_norm^2) - phi = atan(y_norm, x_norm) - sin_phi, cos_phi = sincos(phi) - - # Set the background values - H = 4.25 - v1 = 0.0 - v2 = 0.0 - b = 0.0 - - # setup the discontinuous water height and velocities - if element_id == 10 - H = 5.0 - v1 = 0.1882 * cos_phi - v2 = 0.1882 * sin_phi - end - - # Setup a discontinuous bottom topography using the element id number - if element_id == 7 - b = 2.0 + 0.5 * sin(2.0 * pi * x[1]) + 0.5 * cos(2.0 * pi * x[2]) - end - - return prim2cons(SVector(H, v1, v2, b), equations) +function initial_condition_ec_discontinuous_bottom(x, t, element_id, + equations::ShallowWaterEquations2D) + # Set up polar coordinates + inicenter = SVector(0.7, 0.7) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + phi = atan(y_norm, x_norm) + sin_phi, cos_phi = sincos(phi) + + # Set the background values + H = 4.25 + v1 = 0.0 + v2 = 0.0 + b = 0.0 + + # setup the discontinuous water height and velocities + if element_id == 10 + H = 5.0 + v1 = 0.1882 * cos_phi + v2 = 0.1882 * sin_phi + end + + # Setup a discontinuous bottom topography using the element id number + if element_id == 7 + b = 2.0 + 0.5 * sin(2.0 * pi * x[1]) + 0.5 * cos(2.0 * pi * x[2]) + end + + return prim2cons(SVector(H, v1, v2, b), equations) end # point to the data we want to augment u = Trixi.wrap_array(ode.u0, semi) # reset the initial condition for element in eachelement(semi.solver, semi.cache) - for j in eachnode(semi.solver), i in eachnode(semi.solver) - x_node = Trixi.get_node_coords(semi.cache.elements.node_coordinates, equations, semi.solver, i, j, element) - u_node = initial_condition_ec_discontinuous_bottom(x_node, first(tspan), element, equations) - Trixi.set_node_vars!(u, u_node, equations, semi.solver, i, j, element) - end + for j in eachnode(semi.solver), i in eachnode(semi.solver) + x_node = Trixi.get_node_coords(semi.cache.elements.node_coordinates, equations, + semi.solver, i, j, element) + u_node = initial_condition_ec_discontinuous_bottom(x_node, first(tspan), element, + equations) + Trixi.set_node_vars!(u, u_node, equations, semi.solver, i, j, element) + end end ############################################################################### @@ -93,15 +97,15 @@ end summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(dt=0.2, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(dt = 0.2, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=3.0) +stepsize_callback = StepsizeCallback(cfl = 3.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) @@ -109,7 +113,7 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_shallowwater_parabolic_bowl.jl b/examples/tree_2d_dgsem/elixir_shallowwater_parabolic_bowl.jl index 03dcf017266..2008019cc31 100644 --- a/examples/tree_2d_dgsem/elixir_shallowwater_parabolic_bowl.jl +++ b/examples/tree_2d_dgsem/elixir_shallowwater_parabolic_bowl.jl @@ -7,7 +7,7 @@ using Trixi # # TODO: TrixiShallowWater: wet/dry example elixir -equations = ShallowWaterEquations2D(gravity_constant=9.81) +equations = ShallowWaterEquations2D(gravity_constant = 9.81) """ initial_condition_parabolic_bowl(x, t, equations:: ShallowWaterEquations2D) @@ -28,27 +28,27 @@ The particular setup below is taken from Section 6.2 of curvilinear meshes with wet/dry fronts accelerated by GPUs [DOI: 10.1016/j.jcp.2018.08.038](https://doi.org/10.1016/j.jcp.2018.08.038). """ -function initial_condition_parabolic_bowl(x, t, equations:: ShallowWaterEquations2D) - a = 1.0 - h_0 = 0.1 - sigma = 0.5 - ω = sqrt(2 * equations.gravity * h_0) / a - - v1 = -sigma * ω * sin(ω * t) - v2 = sigma * ω * cos(ω * t) - - b = h_0 * ((x[1])^2 + (x[2])^2) / a^2 - - H = sigma * h_0 / a^2 * (2 * x[1] * cos(ω * t) + 2 * x[2] * sin(ω * t) - sigma) + h_0 - - # It is mandatory to shift the water level at dry areas to make sure the water height h - # stays positive. The system would not be stable for h set to a hard 0 due to division by h in - # the computation of velocity, e.g., (h v1) / h. Therefore, a small dry state threshold - # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above - # for the ShallowWaterEquations and added to the initial condition if h = 0. - # This default value can be changed within the constructor call depending on the simulation setup. - H = max(H, b + equations.threshold_limiter) - return prim2cons(SVector(H, v1, v2, b), equations) +function initial_condition_parabolic_bowl(x, t, equations::ShallowWaterEquations2D) + a = 1.0 + h_0 = 0.1 + sigma = 0.5 + ω = sqrt(2 * equations.gravity * h_0) / a + + v1 = -sigma * ω * sin(ω * t) + v2 = sigma * ω * cos(ω * t) + + b = h_0 * ((x[1])^2 + (x[2])^2) / a^2 + + H = sigma * h_0 / a^2 * (2 * x[1] * cos(ω * t) + 2 * x[2] * sin(ω * t) - sigma) + h_0 + + # It is mandatory to shift the water level at dry areas to make sure the water height h + # stays positive. The system would not be stable for h set to a hard 0 due to division by h in + # the computation of velocity, e.g., (h v1) / h. Therefore, a small dry state threshold + # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above + # for the ShallowWaterEquations and added to the initial condition if h = 0. + # This default value can be changed within the constructor call depending on the simulation setup. + H = max(H, b + equations.threshold_limiter) + return prim2cons(SVector(H, v1, v2, b), equations) end initial_condition = initial_condition_parabolic_bowl @@ -56,23 +56,23 @@ initial_condition = initial_condition_parabolic_bowl # Get the DG approximation space volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -surface_flux = (FluxHydrostaticReconstruction(flux_hll_chen_noelle, hydrostatic_reconstruction_chen_noelle), +surface_flux = (FluxHydrostaticReconstruction(flux_hll_chen_noelle, + hydrostatic_reconstruction_chen_noelle), flux_nonconservative_chen_noelle) basis = LobattoLegendreBasis(7) indicator_sc = IndicatorHennemannGassnerShallowWater(equations, basis, - alpha_max=0.6, - alpha_min=0.001, - alpha_smooth=true, - variable=waterheight_pressure) + alpha_max = 0.6, + alpha_min = 0.001, + alpha_smooth = true, + variable = waterheight_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) - ############################################################################### # Create the TreeMesh for the domain [-2, 2]^2 @@ -80,8 +80,8 @@ coordinates_min = (-2.0, -2.0) coordinates_max = (2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=5, - n_cells_max=10_000) + initial_refinement_level = 5, + n_cells_max = 10_000) # create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -95,19 +95,20 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=false, - extra_analysis_integrals=(energy_kinetic, - energy_internal)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = false, + extra_analysis_integrals = (energy_kinetic, + energy_internal)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) -stage_limiter! = PositivityPreservingLimiterShallowWater(variables=(Trixi.waterheight,)) +stage_limiter! = PositivityPreservingLimiterShallowWater(variables = (Trixi.waterheight,)) ############################################################################### # run the simulation @@ -115,6 +116,6 @@ stage_limiter! = PositivityPreservingLimiterShallowWater(variables=(Trixi.waterh callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) sol = solve(ode, SSPRK43(stage_limiter!); - ode_default_options()..., callback=callbacks); + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_shallowwater_source_terms.jl b/examples/tree_2d_dgsem/elixir_shallowwater_source_terms.jl index 6d4f6fe518c..c92e885c161 100644 --- a/examples/tree_2d_dgsem/elixir_shallowwater_source_terms.jl +++ b/examples/tree_2d_dgsem/elixir_shallowwater_source_terms.jl @@ -5,17 +5,17 @@ using Trixi ############################################################################### # semidiscretization of the shallow water equations -equations = ShallowWaterEquations2D(gravity_constant=9.81) +equations = ShallowWaterEquations2D(gravity_constant = 9.81) initial_condition = initial_condition_convergence_test # MMS EOC test - ############################################################################### # Get the DG approximation space volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -solver = DGSEM(polydeg=3, surface_flux=(flux_lax_friedrichs, flux_nonconservative_fjordholm_etal), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, + surface_flux = (flux_lax_friedrichs, flux_nonconservative_fjordholm_etal), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### # Get the TreeMesh and setup a periodic mesh @@ -23,13 +23,13 @@ solver = DGSEM(polydeg=3, surface_flux=(flux_lax_friedrichs, flux_nonconservativ coordinates_min = (0.0, 0.0) coordinates_max = (sqrt(2.0), sqrt(2.0)) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=10_000, - periodicity=true) + initial_refinement_level = 3, + n_cells_max = 10_000, + periodicity = true) # create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -40,13 +40,13 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 500 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=200, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 200, + save_initial_solution = true, + save_final_solution = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) @@ -54,6 +54,6 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav # run the simulation # use a Runge-Kutta method with automatic (error based) time step size control -sol = solve(ode, RDPK3SpFSAL49(); abstol=1.0e-8, reltol=1.0e-8, - ode_default_options()..., callback=callbacks); +sol = solve(ode, RDPK3SpFSAL49(); abstol = 1.0e-8, reltol = 1.0e-8, + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_shallowwater_source_terms_dirichlet.jl b/examples/tree_2d_dgsem/elixir_shallowwater_source_terms_dirichlet.jl index c3da957b764..f7544b1e32e 100644 --- a/examples/tree_2d_dgsem/elixir_shallowwater_source_terms_dirichlet.jl +++ b/examples/tree_2d_dgsem/elixir_shallowwater_source_terms_dirichlet.jl @@ -5,7 +5,7 @@ using Trixi ############################################################################### # Semidiscretization of the shallow water equations -equations = ShallowWaterEquations2D(gravity_constant=9.81) +equations = ShallowWaterEquations2D(gravity_constant = 9.81) initial_condition = initial_condition_convergence_test @@ -15,8 +15,9 @@ boundary_condition = BoundaryConditionDirichlet(initial_condition) # Get the DG approximation space volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -solver = DGSEM(polydeg=3, surface_flux=(flux_lax_friedrichs, flux_nonconservative_fjordholm_etal), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, + surface_flux = (flux_lax_friedrichs, flux_nonconservative_fjordholm_etal), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### # Get the TreeMesh and setup a periodic mesh @@ -24,14 +25,14 @@ solver = DGSEM(polydeg=3, surface_flux=(flux_lax_friedrichs, flux_nonconservativ coordinates_min = (0.0, 0.0) coordinates_max = (sqrt(2.0), sqrt(2.0)) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=10_000, - periodicity=false) + initial_refinement_level = 3, + n_cells_max = 10_000, + periodicity = false) # create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, boundary_conditions = boundary_condition, - source_terms=source_terms_convergence_test) + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -42,13 +43,13 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 500 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=200, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 200, + save_initial_solution = true, + save_final_solution = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) @@ -56,6 +57,6 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav # run the simulation # use a Runge-Kutta method with automatic (error based) time step size control -sol = solve(ode, RDPK3SpFSAL49(); abstol=1.0e-8, reltol=1.0e-8, - ode_default_options()..., callback=callbacks); +sol = solve(ode, RDPK3SpFSAL49(); abstol = 1.0e-8, reltol = 1.0e-8, + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_shallowwater_twolayer_convergence.jl b/examples/tree_2d_dgsem/elixir_shallowwater_twolayer_convergence.jl index 402361c8823..790916e4467 100644 --- a/examples/tree_2d_dgsem/elixir_shallowwater_twolayer_convergence.jl +++ b/examples/tree_2d_dgsem/elixir_shallowwater_twolayer_convergence.jl @@ -5,17 +5,18 @@ using Trixi ############################################################################### # Semidiscretization of the two-layer shallow water equations -equations = ShallowWaterTwoLayerEquations2D(gravity_constant=10.0, rho_upper=0.9, rho_lower=1.0) +equations = ShallowWaterTwoLayerEquations2D(gravity_constant = 10.0, rho_upper = 0.9, + rho_lower = 1.0) initial_condition = initial_condition_convergence_test ############################################################################### # Get the DG approximation space -volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -solver = DGSEM(polydeg=3, surface_flux=(flux_fjordholm_etal, flux_nonconservative_fjordholm_etal), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) - +volume_flux = (flux_wintermeyer_etal, flux_nonconservative_ersing_etal) +solver = DGSEM(polydeg = 3, + surface_flux = (flux_wintermeyer_etal, flux_nonconservative_ersing_etal), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### # Get the TreeMesh and setup a periodic mesh @@ -23,13 +24,13 @@ solver = DGSEM(polydeg=3, surface_flux=(flux_fjordholm_etal, flux_nonconservativ coordinates_min = (0.0, 0.0) coordinates_max = (sqrt(2.0), sqrt(2.0)) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=20_000, - periodicity=true) + initial_refinement_level = 3, + n_cells_max = 20_000, + periodicity = true) # Create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -40,13 +41,13 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 500 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=500, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 500, + save_initial_solution = true, + save_final_solution = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) @@ -54,6 +55,6 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav # run the simulation # use a Runge-Kutta method with automatic (error based) time step size control -sol = solve(ode, RDPK3SpFSAL49(), abstol=1.0e-8, reltol=1.0e-8, -save_everystep=false, callback=callbacks); +sol = solve(ode, RDPK3SpFSAL49(), abstol = 1.0e-8, reltol = 1.0e-8, + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_shallowwater_twolayer_well_balanced.jl b/examples/tree_2d_dgsem/elixir_shallowwater_twolayer_well_balanced.jl index ba4bcd25774..264c26390fe 100644 --- a/examples/tree_2d_dgsem/elixir_shallowwater_twolayer_well_balanced.jl +++ b/examples/tree_2d_dgsem/elixir_shallowwater_twolayer_well_balanced.jl @@ -6,21 +6,24 @@ using Trixi # Semidiscretization of the two-layer shallow water equations with a bottom topography function # to test well-balancedness -equations = ShallowWaterTwoLayerEquations2D(gravity_constant=9.81, H0=0.6, rho_upper=0.9, rho_lower=1.0) +equations = ShallowWaterTwoLayerEquations2D(gravity_constant = 9.81, H0 = 0.6, + rho_upper = 0.9, rho_lower = 1.0) # An initial condition with constant total water height, zero velocities and a bottom topography to # test well-balancedness function initial_condition_well_balanced(x, t, equations::ShallowWaterTwoLayerEquations2D) - H_lower = 0.5 - H_upper = 0.6 - v1_upper = 0.0 - v2_upper = 0.0 - v1_lower = 0.0 - v2_lower = 0.0 - b = (((x[1] - 0.5)^2 + (x[2] - 0.5)^2) < 0.04 ? 0.2 * (cos(4 * pi * sqrt((x[1] - 0.5)^2 + (x[2] + - -0.5)^2)) + 1) : 0.0) - - return prim2cons(SVector(H_upper, v1_upper, v2_upper, H_lower, v1_lower, v2_lower, b), equations) + H_lower = 0.5 + H_upper = 0.6 + v1_upper = 0.0 + v2_upper = 0.0 + v1_lower = 0.0 + v2_lower = 0.0 + b = (((x[1] - 0.5)^2 + (x[2] - 0.5)^2) < 0.04 ? + 0.2 * (cos(4 * pi * sqrt((x[1] - 0.5)^2 + (x[2] + + -0.5)^2)) + 1) : 0.0) + + return prim2cons(SVector(H_upper, v1_upper, v2_upper, H_lower, v1_lower, v2_lower, b), + equations) end initial_condition = initial_condition_well_balanced @@ -28,10 +31,10 @@ initial_condition = initial_condition_well_balanced ############################################################################### # Get the DG approximation space -volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -surface_flux = (flux_es_fjordholm_etal, flux_nonconservative_fjordholm_etal) -solver = DGSEM(polydeg=3, surface_flux=surface_flux, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +volume_flux = (flux_wintermeyer_etal, flux_nonconservative_ersing_etal) +surface_flux = (flux_es_ersing_etal, flux_nonconservative_ersing_etal) +solver = DGSEM(polydeg = 3, surface_flux = surface_flux, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### # Get the TreeMesh and setup a periodic mesh @@ -39,9 +42,9 @@ solver = DGSEM(polydeg=3, surface_flux=surface_flux, coordinates_min = (0.0, 0.0) coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=10_000, - periodicity=true) + initial_refinement_level = 3, + n_cells_max = 10_000, + periodicity = true) # Create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -55,16 +58,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(lake_at_rest_error,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (lake_at_rest_error,)) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) @@ -72,7 +75,7 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_shallowwater_well_balanced.jl b/examples/tree_2d_dgsem/elixir_shallowwater_well_balanced.jl index 23efdcb7366..13023dfaba2 100644 --- a/examples/tree_2d_dgsem/elixir_shallowwater_well_balanced.jl +++ b/examples/tree_2d_dgsem/elixir_shallowwater_well_balanced.jl @@ -6,21 +6,21 @@ using Trixi # semidiscretization of the shallow water equations with a discontinuous # bottom topography function -equations = ShallowWaterEquations2D(gravity_constant=9.81, H0=3.25) +equations = ShallowWaterEquations2D(gravity_constant = 9.81, H0 = 3.25) # An initial condition with constant total water height and zero velocities to test well-balancedness. # Note, this routine is used to compute errors in the analysis callback but the initialization is # overwritten by `initial_condition_discontinuous_well_balancedness` below. function initial_condition_well_balancedness(x, t, equations::ShallowWaterEquations2D) - # Set the background values - H = equations.H0 - v1 = 0.0 - v2 = 0.0 - # bottom topography taken from Pond.control in [HOHQMesh](https://github.com/trixi-framework/HOHQMesh) - x1, x2 = x - b = ( 1.5 / exp( 0.5 * ((x1 - 1.0)^2 + (x2 - 1.0)^2) ) - + 0.75 / exp( 0.5 * ((x1 + 1.0)^2 + (x2 + 1.0)^2) ) ) - return prim2cons(SVector(H, v1, v2, b), equations) + # Set the background values + H = equations.H0 + v1 = 0.0 + v2 = 0.0 + # bottom topography taken from Pond.control in [HOHQMesh](https://github.com/trixi-framework/HOHQMesh) + x1, x2 = x + b = (1.5 / exp(0.5 * ((x1 - 1.0)^2 + (x2 - 1.0)^2)) + + 0.75 / exp(0.5 * ((x1 + 1.0)^2 + (x2 + 1.0)^2))) + return prim2cons(SVector(H, v1, v2, b), equations) end initial_condition = initial_condition_well_balancedness @@ -30,17 +30,17 @@ initial_condition = initial_condition_well_balancedness volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) surface_flux = (flux_fjordholm_etal, flux_nonconservative_fjordholm_etal) -solver = DGSEM(polydeg=4, surface_flux=surface_flux, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 4, surface_flux = surface_flux, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### # Get the TreeMesh and setup a periodic mesh coordinates_min = (-1.0, -1.0) -coordinates_max = ( 1.0, 1.0) +coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=10_000) + initial_refinement_level = 2, + n_cells_max = 10_000) # Create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -61,30 +61,33 @@ ode = semidiscretize(semi, tspan) # In contrast to the usual signature of initial conditions, this one get passed the # `element_id` explicitly. In particular, this initial conditions works as intended # only for the TreeMesh2D with initial_refinement_level=2. -function initial_condition_discontinuous_well_balancedness(x, t, element_id, equations::ShallowWaterEquations2D) - # Set the background values - H = equations.H0 - v1 = 0.0 - v2 = 0.0 - b = 0.0 - - # Setup a discontinuous bottom topography using the element id number - if element_id == 7 - b = 2.0 + 0.5 * sin(2.0 * pi * x[1]) + 0.5 * cos(2.0 * pi * x[2]) - end - - return prim2cons(SVector(H, v1, v2, b), equations) +function initial_condition_discontinuous_well_balancedness(x, t, element_id, + equations::ShallowWaterEquations2D) + # Set the background values + H = equations.H0 + v1 = 0.0 + v2 = 0.0 + b = 0.0 + + # Setup a discontinuous bottom topography using the element id number + if element_id == 7 + b = 2.0 + 0.5 * sin(2.0 * pi * x[1]) + 0.5 * cos(2.0 * pi * x[2]) + end + + return prim2cons(SVector(H, v1, v2, b), equations) end # point to the data we want to augment u = Trixi.wrap_array(ode.u0, semi) # reset the initial condition for element in eachelement(semi.solver, semi.cache) - for j in eachnode(semi.solver), i in eachnode(semi.solver) - x_node = Trixi.get_node_coords(semi.cache.elements.node_coordinates, equations, semi.solver, i, j, element) - u_node = initial_condition_discontinuous_well_balancedness(x_node, first(tspan), element, equations) - Trixi.set_node_vars!(u, u_node, equations, semi.solver, i, j, element) - end + for j in eachnode(semi.solver), i in eachnode(semi.solver) + x_node = Trixi.get_node_coords(semi.cache.elements.node_coordinates, equations, + semi.solver, i, j, element) + u_node = initial_condition_discontinuous_well_balancedness(x_node, first(tspan), + element, equations) + Trixi.set_node_vars!(u, u_node, equations, semi.solver, i, j, element) + end end ############################################################################### @@ -93,16 +96,16 @@ end summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(lake_at_rest_error,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (lake_at_rest_error,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=3.0) +stepsize_callback = StepsizeCallback(cfl = 3.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) @@ -110,7 +113,7 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_shallowwater_well_balanced_wall.jl b/examples/tree_2d_dgsem/elixir_shallowwater_well_balanced_wall.jl index 66cd27f6864..f50bd4e4f65 100644 --- a/examples/tree_2d_dgsem/elixir_shallowwater_well_balanced_wall.jl +++ b/examples/tree_2d_dgsem/elixir_shallowwater_well_balanced_wall.jl @@ -5,21 +5,21 @@ using Trixi # semidiscretization of the shallow water equations with a discontinuous # bottom topography function -equations = ShallowWaterEquations2D(gravity_constant=9.81, H0=3.25) +equations = ShallowWaterEquations2D(gravity_constant = 9.81, H0 = 3.25) # An initial condition with constant total water height and zero velocities to test well-balancedness. # Note, this routine is used to compute errors in the analysis callback but the initialization is # overwritten by `initial_condition_discontinuous_well_balancedness` below. function initial_condition_well_balancedness(x, t, equations::ShallowWaterEquations2D) - # Set the background values - H = equations.H0 - v1 = 0.0 - v2 = 0.0 - # bottom topography taken from Pond.control in [HOHQMesh](https://github.com/trixi-framework/HOHQMesh) - x1, x2 = x - b = ( 1.5 / exp( 0.5 * ((x1 - 1.0)^2 + (x2 - 1.0)^2) ) - + 0.75 / exp( 0.5 * ((x1 + 1.0)^2 + (x2 + 1.0)^2) ) ) - return prim2cons(SVector(H, v1, v2, b), equations) + # Set the background values + H = equations.H0 + v1 = 0.0 + v2 = 0.0 + # bottom topography taken from Pond.control in [HOHQMesh](https://github.com/trixi-framework/HOHQMesh) + x1, x2 = x + b = (1.5 / exp(0.5 * ((x1 - 1.0)^2 + (x2 - 1.0)^2)) + + 0.75 / exp(0.5 * ((x1 + 1.0)^2 + (x2 + 1.0)^2))) + return prim2cons(SVector(H, v1, v2, b), equations) end initial_condition = initial_condition_well_balancedness @@ -31,8 +31,8 @@ boundary_condition = boundary_condition_slip_wall volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) surface_flux = (flux_fjordholm_etal, flux_nonconservative_fjordholm_etal) -solver = DGSEM(polydeg=4, surface_flux=surface_flux, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 4, surface_flux = surface_flux, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### # Get the TreeMesh and setup a periodic mesh @@ -40,8 +40,8 @@ solver = DGSEM(polydeg=4, surface_flux=surface_flux, coordinates_min = (-1.0, -1.0) coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=10_000, + initial_refinement_level = 2, + n_cells_max = 10_000, periodicity = false) # create the semi discretization object @@ -64,30 +64,33 @@ ode = semidiscretize(semi, tspan) # In contrast to the usual signature of initial conditions, this one get passed the # `element_id` explicitly. In particular, this initial conditions works as intended # only for the TreeMesh2D with initial_refinement_level=2. -function initial_condition_discontinuous_well_balancedness(x, t, element_id, equations::ShallowWaterEquations2D) - # Set the background values - H = equations.H0 - v1 = 0.0 - v2 = 0.0 - b = 0.0 - - # Setup a discontinuous bottom topography using the element id number - if element_id == 7 - b = 2.0 + 0.5 * sin(2.0 * pi * x[1]) + 0.5 * cos(2.0 * pi * x[2]) - end - - return prim2cons(SVector(H, v1, v2, b), equations) +function initial_condition_discontinuous_well_balancedness(x, t, element_id, + equations::ShallowWaterEquations2D) + # Set the background values + H = equations.H0 + v1 = 0.0 + v2 = 0.0 + b = 0.0 + + # Setup a discontinuous bottom topography using the element id number + if element_id == 7 + b = 2.0 + 0.5 * sin(2.0 * pi * x[1]) + 0.5 * cos(2.0 * pi * x[2]) + end + + return prim2cons(SVector(H, v1, v2, b), equations) end # point to the data we want to augment u = Trixi.wrap_array(ode.u0, semi) # reset the initial condition for element in eachelement(semi.solver, semi.cache) - for j in eachnode(semi.solver), i in eachnode(semi.solver) - x_node = Trixi.get_node_coords(semi.cache.elements.node_coordinates, equations, semi.solver, i, j, element) - u_node = initial_condition_discontinuous_well_balancedness(x_node, first(tspan), element, equations) - Trixi.set_node_vars!(u, u_node, equations, semi.solver, i, j, element) - end + for j in eachnode(semi.solver), i in eachnode(semi.solver) + x_node = Trixi.get_node_coords(semi.cache.elements.node_coordinates, equations, + semi.solver, i, j, element) + u_node = initial_condition_discontinuous_well_balancedness(x_node, first(tspan), + element, equations) + Trixi.set_node_vars!(u, u_node, equations, semi.solver, i, j, element) + end end ############################################################################### @@ -96,16 +99,16 @@ end summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(lake_at_rest_error,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (lake_at_rest_error,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=3.0) +stepsize_callback = StepsizeCallback(cfl = 3.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) @@ -113,7 +116,7 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); -summary_callback() # print the timer summary \ No newline at end of file +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); +summary_callback() # print the timer summary diff --git a/examples/tree_2d_dgsem/elixir_shallowwater_well_balanced_wet_dry.jl b/examples/tree_2d_dgsem/elixir_shallowwater_well_balanced_wet_dry.jl index 6fede2fa4ea..034411c2b54 100644 --- a/examples/tree_2d_dgsem/elixir_shallowwater_well_balanced_wet_dry.jl +++ b/examples/tree_2d_dgsem/elixir_shallowwater_well_balanced_wet_dry.jl @@ -8,7 +8,7 @@ using Printf: @printf, @sprintf # # TODO: TrixiShallowWater: wet/dry example elixir -equations = ShallowWaterEquations2D(gravity_constant=9.812) +equations = ShallowWaterEquations2D(gravity_constant = 9.812) """ initial_condition_well_balanced_chen_noelle(x, t, equations:: ShallowWaterEquations2D) @@ -23,28 +23,29 @@ The initial condition is taken from Section 5.2 of the paper: A new hydrostatic reconstruction scheme based on subcell reconstructions [DOI:10.1137/15M1053074](https://dx.doi.org/10.1137/15M1053074) """ -function initial_condition_complex_bottom_well_balanced(x, t, equations::ShallowWaterEquations2D) - v1 = 0 - v2 = 0 - b = sin(4 * pi * x[1]) + 3 - - if x[1] >= 0.5 - b = sin(4 * pi * x[1]) + 1 - end - - H = max(b, 2.5) - if x[1] >= 0.5 - H = max(b, 1.5) - end - - # It is mandatory to shift the water level at dry areas to make sure the water height h - # stays positive. The system would not be stable for h set to a hard 0 due to division by h in - # the computation of velocity, e.g., (h v1) / h. Therefore, a small dry state threshold - # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above - # for the ShallowWaterEquations and added to the initial condition if h = 0. - # This default value can be changed within the constructor call depending on the simulation setup. - H = max(H, b + equations.threshold_limiter) - return prim2cons(SVector(H, v1, v2, b), equations) +function initial_condition_complex_bottom_well_balanced(x, t, + equations::ShallowWaterEquations2D) + v1 = 0 + v2 = 0 + b = sin(4 * pi * x[1]) + 3 + + if x[1] >= 0.5 + b = sin(4 * pi * x[1]) + 1 + end + + H = max(b, 2.5) + if x[1] >= 0.5 + H = max(b, 1.5) + end + + # It is mandatory to shift the water level at dry areas to make sure the water height h + # stays positive. The system would not be stable for h set to a hard 0 due to division by h in + # the computation of velocity, e.g., (h v1) / h. Therefore, a small dry state threshold + # with a default value of 500*eps() ≈ 1e-13 in double precision, is set in the constructor above + # for the ShallowWaterEquations and added to the initial condition if h = 0. + # This default value can be changed within the constructor call depending on the simulation setup. + H = max(H, b + equations.threshold_limiter) + return prim2cons(SVector(H, v1, v2, b), equations) end initial_condition = initial_condition_complex_bottom_well_balanced @@ -53,19 +54,20 @@ initial_condition = initial_condition_complex_bottom_well_balanced # Get the DG approximation space volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -surface_flux = (FluxHydrostaticReconstruction(flux_hll_chen_noelle, hydrostatic_reconstruction_chen_noelle), +surface_flux = (FluxHydrostaticReconstruction(flux_hll_chen_noelle, + hydrostatic_reconstruction_chen_noelle), flux_nonconservative_chen_noelle) basis = LobattoLegendreBasis(3) indicator_sc = IndicatorHennemannGassnerShallowWater(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=waterheight_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = waterheight_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) @@ -76,8 +78,8 @@ coordinates_min = (0.0, 0.0) coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=10_000) + initial_refinement_level = 3, + n_cells_max = 10_000) # create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -102,18 +104,20 @@ ode = semidiscretize(semi, tspan) u = Trixi.wrap_array(ode.u0, semi) # reset the initial condition for element in eachelement(semi.solver, semi.cache) - for j in eachnode(semi.solver), i in eachnode(semi.solver) - x_node = Trixi.get_node_coords(semi.cache.elements.node_coordinates, equations, semi.solver, i, j, element) - # We know that the discontinuity is a vertical line. Slightly augment the x value by a factor - # of unit roundoff to avoid the repeted value from the LGL nodes at at interface. - if i == 1 - x_node = SVector(nextfloat(x_node[1]) , x_node[2]) - elseif i == nnodes(semi.solver) - x_node = SVector(prevfloat(x_node[1]) , x_node[2]) + for j in eachnode(semi.solver), i in eachnode(semi.solver) + x_node = Trixi.get_node_coords(semi.cache.elements.node_coordinates, equations, + semi.solver, i, j, element) + # We know that the discontinuity is a vertical line. Slightly augment the x value by a factor + # of unit roundoff to avoid the repeted value from the LGL nodes at at interface. + if i == 1 + x_node = SVector(nextfloat(x_node[1]), x_node[2]) + elseif i == nnodes(semi.solver) + x_node = SVector(prevfloat(x_node[1]), x_node[2]) + end + u_node = initial_condition_complex_bottom_well_balanced(x_node, first(tspan), + equations) + Trixi.set_node_vars!(u, u_node, equations, semi.solver, i, j, element) end - u_node = initial_condition_complex_bottom_well_balanced(x_node, first(tspan), equations) - Trixi.set_node_vars!(u, u_node, equations, semi.solver, i, j, element) - end end ############################################################################### @@ -122,27 +126,27 @@ end summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=false) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = false) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true) - -stepsize_callback = StepsizeCallback(cfl=2.0) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true) +stepsize_callback = StepsizeCallback(cfl = 2.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) -stage_limiter! = PositivityPreservingLimiterShallowWater(variables=(Trixi.waterheight,)) +stage_limiter! = PositivityPreservingLimiterShallowWater(variables = (Trixi.waterheight,)) ############################################################################### # run the simulation -sol = solve(ode, SSPRK43(stage_limiter!); dt=1.0, - ode_default_options()..., callback=callbacks, adaptive=false); +sol = solve(ode, SSPRK43(stage_limiter!); dt = 1.0, + ode_default_options()..., callback = callbacks, adaptive = false); summary_callback() # print the timer summary @@ -157,34 +161,38 @@ summary_callback() # print the timer summary function lake_at_rest_error_two_level(u, x, equations::ShallowWaterEquations2D) h, _, _, b = u - # For well-balancedness testing with possible wet/dry regions the reference - # water height `H0` accounts for the possibility that the bottom topography - # can emerge out of the water as well as for the threshold offset to avoid - # division by a "hard" zero water heights as well. + # For well-balancedness testing with possible wet/dry regions the reference + # water height `H0` accounts for the possibility that the bottom topography + # can emerge out of the water as well as for the threshold offset to avoid + # division by a "hard" zero water heights as well. - if x[1] < 0.5 - H0_wet_dry = max( 2.5 , b + equations.threshold_limiter ) - else - H0_wet_dry = max( 1.5 , b + equations.threshold_limiter ) - end + if x[1] < 0.5 + H0_wet_dry = max(2.5, b + equations.threshold_limiter) + else + H0_wet_dry = max(1.5, b + equations.threshold_limiter) + end - return abs(H0_wet_dry - (h + b)) + return abs(H0_wet_dry - (h + b)) end # point to the data we want to analyze u = Trixi.wrap_array(sol[end], semi) # Perform the actual integration of the well-balancedness error over the domain -l1_well_balance_error = Trixi.integrate_via_indices(u, mesh, equations, semi.solver, semi.cache; normalize=true) do u, i, j, element, equations, solver - x_node = Trixi.get_node_coords(semi.cache.elements.node_coordinates, equations, solver, i, j, element) - # We know that the discontinuity is a vertical line. Slightly augment the x value by a factor - # of unit roundoff to avoid the repeted value from the LGL nodes at at interface. - if i == 1 - x_node = SVector(nextfloat(x_node[1]) , x_node[2]) - elseif i == nnodes(semi.solver) - x_node = SVector(prevfloat(x_node[1]) , x_node[2]) - end - u_local = Trixi.get_node_vars(u, equations, solver, i, j, element) - return lake_at_rest_error_two_level(u_local, x_node, equations) +l1_well_balance_error = Trixi.integrate_via_indices(u, mesh, equations, semi.solver, + semi.cache; + normalize = true) do u, i, j, element, + equations, solver + x_node = Trixi.get_node_coords(semi.cache.elements.node_coordinates, equations, solver, + i, j, element) + # We know that the discontinuity is a vertical line. Slightly augment the x value by a factor + # of unit roundoff to avoid the repeted value from the LGL nodes at at interface. + if i == 1 + x_node = SVector(nextfloat(x_node[1]), x_node[2]) + elseif i == nnodes(semi.solver) + x_node = SVector(prevfloat(x_node[1]), x_node[2]) + end + u_local = Trixi.get_node_vars(u, equations, solver, i, j, element) + return lake_at_rest_error_two_level(u_local, x_node, equations) end # report the well-balancedness lake-at-rest error to the screen diff --git a/examples/tree_2d_fdsbp/elixir_advection_extended.jl b/examples/tree_2d_fdsbp/elixir_advection_extended.jl index 6e599d9f42d..8716a9a6b78 100644 --- a/examples/tree_2d_fdsbp/elixir_advection_extended.jl +++ b/examples/tree_2d_fdsbp/elixir_advection_extended.jl @@ -13,22 +13,21 @@ equations = LinearScalarAdvectionEquation2D(advection_velocity) initial_condition = initial_condition_convergence_test D_SBP = derivative_operator(SummationByPartsOperators.MattssonNordström2004(), - derivative_order=1, accuracy_order=4, - xmin=0.0, xmax=1.0, N=100) + derivative_order = 1, accuracy_order = 4, + xmin = 0.0, xmax = 1.0, N = 100) solver = FDSBP(D_SBP, - surface_integral=SurfaceIntegralStrongForm(flux_lax_friedrichs), - volume_integral=VolumeIntegralStrongForm()) + surface_integral = SurfaceIntegralStrongForm(flux_lax_friedrichs), + volume_integral = VolumeIntegralStrongForm()) coordinates_min = (-1.0, -1.0) -coordinates_max = ( 1.0, 1.0) +coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=1, - n_cells_max=30_000, - periodicity=true) + initial_refinement_level = 1, + n_cells_max = 30_000, + periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -38,19 +37,18 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(energy_total,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (energy_total,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) - ############################################################################### # run the simulation -sol = solve(ode, RDPK3SpFSAL49(); abstol=1.0e-9, reltol=1.0e-9, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = 1.0e-9, reltol = 1.0e-9, + ode_default_options()..., callback = callbacks) summary_callback() diff --git a/examples/tree_2d_fdsbp/elixir_euler_convergence.jl b/examples/tree_2d_fdsbp/elixir_euler_convergence.jl index 2a6c291f0bf..123be02bd17 100644 --- a/examples/tree_2d_fdsbp/elixir_euler_convergence.jl +++ b/examples/tree_2d_fdsbp/elixir_euler_convergence.jl @@ -13,23 +13,24 @@ initial_condition = initial_condition_convergence_test source_terms = source_terms_convergence_test D_upw = upwind_operators(SummationByPartsOperators.Mattsson2017, - derivative_order=1, - accuracy_order=4, - xmin=-1.0, xmax=1.0, - N=16) + derivative_order = 1, + accuracy_order = 4, + xmin = -1.0, xmax = 1.0, + N = 16) flux_splitting = splitting_steger_warming solver = FDSBP(D_upw, - surface_integral=SurfaceIntegralUpwind(flux_splitting), - volume_integral=VolumeIntegralUpwind(flux_splitting)) + surface_integral = SurfaceIntegralUpwind(flux_splitting), + volume_integral = VolumeIntegralUpwind(flux_splitting)) coordinates_min = (-1.0, -1.0) -coordinates_max = ( 1.0, 1.0) +coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=30_000, - periodicity=true) + initial_refinement_level = 3, + n_cells_max = 30_000, + periodicity = true) -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, source_terms = source_terms_convergence_test) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -40,15 +41,15 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(energy_total,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (energy_total,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -58,6 +59,6 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, SSPRK43(); abstol=1.0e-9, reltol=1.0e-9, - ode_default_options()..., callback=callbacks) +sol = solve(ode, SSPRK43(); abstol = 1.0e-9, reltol = 1.0e-9, + ode_default_options()..., callback = callbacks) summary_callback() diff --git a/examples/tree_2d_fdsbp/elixir_euler_kelvin_helmholtz_instability.jl b/examples/tree_2d_fdsbp/elixir_euler_kelvin_helmholtz_instability.jl index e63343852ab..4c41b84af33 100644 --- a/examples/tree_2d_fdsbp/elixir_euler_kelvin_helmholtz_instability.jl +++ b/examples/tree_2d_fdsbp/elixir_euler_kelvin_helmholtz_instability.jl @@ -9,42 +9,42 @@ using Trixi equations = CompressibleEulerEquations2D(1.4) -function initial_condition_kelvin_helmholtz_instability(x, t, equations::CompressibleEulerEquations2D) - # change discontinuity to tanh - # typical resolution 128^2, 256^2 - # domain size is [-1,+1]^2 - slope = 15 - amplitude = 0.02 - B = tanh(slope * x[2] + 7.5) - tanh(slope * x[2] - 7.5) - rho = 0.5 + 0.75 * B - v1 = 0.5 * (B - 1) - v2 = 0.1 * sin(2 * pi * x[1]) - p = 1.0 - return prim2cons(SVector(rho, v1, v2, p), equations) +function initial_condition_kelvin_helmholtz_instability(x, t, + equations::CompressibleEulerEquations2D) + # change discontinuity to tanh + # typical resolution 128^2, 256^2 + # domain size is [-1,+1]^2 + slope = 15 + amplitude = 0.02 + B = tanh(slope * x[2] + 7.5) - tanh(slope * x[2] - 7.5) + rho = 0.5 + 0.75 * B + v1 = 0.5 * (B - 1) + v2 = 0.1 * sin(2 * pi * x[1]) + p = 1.0 + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_kelvin_helmholtz_instability D_upw = upwind_operators(SummationByPartsOperators.Mattsson2017, - derivative_order=1, - accuracy_order=4, - xmin=-1.0, xmax=1.0, - N=16) + derivative_order = 1, + accuracy_order = 4, + xmin = -1.0, xmax = 1.0, + N = 16) flux_splitting = splitting_vanleer_haenel solver = FDSBP(D_upw, - surface_integral=SurfaceIntegralUpwind(flux_splitting), - volume_integral=VolumeIntegralUpwind(flux_splitting)) + surface_integral = SurfaceIntegralUpwind(flux_splitting), + volume_integral = VolumeIntegralUpwind(flux_splitting)) coordinates_min = (-1.0, -1.0) -coordinates_max = ( 1.0, 1.0) +coordinates_max = (1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=30_000, - periodicity=true) + initial_refinement_level = 4, + n_cells_max = 30_000, + periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -54,27 +54,26 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - save_analysis=true, - extra_analysis_integrals=(entropy, - energy_total,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true, + extra_analysis_integrals = (entropy, + energy_total)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, alive_callback) - ############################################################################### # run the simulation -sol = solve(ode, SSPRK43(); abstol=1.0e-6, reltol=1.0e-6, dt=1e-3, - ode_default_options()..., callback=callbacks) +sol = solve(ode, SSPRK43(); abstol = 1.0e-6, reltol = 1.0e-6, dt = 1e-3, + ode_default_options()..., callback = callbacks) summary_callback() diff --git a/examples/tree_2d_fdsbp/elixir_euler_vortex.jl b/examples/tree_2d_fdsbp/elixir_euler_vortex.jl index c1bee8f9c4d..d0847cc8016 100644 --- a/examples/tree_2d_fdsbp/elixir_euler_vortex.jl +++ b/examples/tree_2d_fdsbp/elixir_euler_vortex.jl @@ -19,62 +19,61 @@ The classical isentropic vortex test case of [NASA/CR-97-206253](https://ntrs.nasa.gov/citations/19980007543) """ function initial_condition_isentropic_vortex(x, t, equations::CompressibleEulerEquations2D) - # needs appropriate mesh size, e.g. [-10,-10]x[10,10] - # for error convergence: make sure that the end time is such that the is back at the initial state!! - # for the current velocity and domain size: t_end should be a multiple of 20s - # initial center of the vortex - inicenter = SVector(0.0, 0.0) - # size and strength of the vortex - iniamplitude = 5.0 - # base flow - rho = 1.0 - v1 = 1.0 - v2 = 1.0 - vel = SVector(v1, v2) - p = 25.0 - rt = p / rho # ideal gas equation - t_loc = 0.0 - cent = inicenter + vel*t_loc # advection of center - # ATTENTION: handle periodic BC, but only for v1 = v2 = 1.0 (!!!!) - - cent = x - cent # distance to center point - - #cent=cross(iniaxis,cent) # distance to axis, tangent vector, length r - # cross product with iniaxis = [0, 0, 1] - cent = SVector(-cent[2], cent[1]) - r2 = cent[1]^2 + cent[2]^2 - du = iniamplitude/(2*π)*exp(0.5*(1-r2)) # vel. perturbation - dtemp = -(equations.gamma-1)/(2*equations.gamma*rt)*du^2 # isentropic - rho = rho * (1+dtemp)^(1/(equations.gamma-1)) - vel = vel + du*cent - v1, v2 = vel - p = p * (1+dtemp)^(equations.gamma/(equations.gamma-1)) - prim = SVector(rho, v1, v2, p) - return prim2cons(prim, equations) + # needs appropriate mesh size, e.g. [-10,-10]x[10,10] + # for error convergence: make sure that the end time is such that the is back at the initial state!! + # for the current velocity and domain size: t_end should be a multiple of 20s + # initial center of the vortex + inicenter = SVector(0.0, 0.0) + # size and strength of the vortex + iniamplitude = 5.0 + # base flow + rho = 1.0 + v1 = 1.0 + v2 = 1.0 + vel = SVector(v1, v2) + p = 25.0 + rt = p / rho # ideal gas equation + t_loc = 0.0 + cent = inicenter + vel * t_loc # advection of center + # ATTENTION: handle periodic BC, but only for v1 = v2 = 1.0 (!!!!) + + cent = x - cent # distance to center point + + #cent=cross(iniaxis,cent) # distance to axis, tangent vector, length r + # cross product with iniaxis = [0, 0, 1] + cent = SVector(-cent[2], cent[1]) + r2 = cent[1]^2 + cent[2]^2 + du = iniamplitude / (2 * π) * exp(0.5 * (1 - r2)) # vel. perturbation + dtemp = -(equations.gamma - 1) / (2 * equations.gamma * rt) * du^2 # isentropic + rho = rho * (1 + dtemp)^(1 / (equations.gamma - 1)) + vel = vel + du * cent + v1, v2 = vel + p = p * (1 + dtemp)^(equations.gamma / (equations.gamma - 1)) + prim = SVector(rho, v1, v2, p) + return prim2cons(prim, equations) end initial_condition = initial_condition_isentropic_vortex D_upw = upwind_operators(SummationByPartsOperators.Mattsson2017, - derivative_order=1, - accuracy_order=4, - xmin=-1.0, xmax=1.0, - N=16) + derivative_order = 1, + accuracy_order = 4, + xmin = -1.0, xmax = 1.0, + N = 16) flux_splitting = splitting_steger_warming solver = FDSBP(D_upw, - surface_integral=SurfaceIntegralUpwind(flux_splitting), - volume_integral=VolumeIntegralUpwind(flux_splitting)) + surface_integral = SurfaceIntegralUpwind(flux_splitting), + volume_integral = VolumeIntegralUpwind(flux_splitting)) coordinates_min = (-10.0, -10.0) -coordinates_max = ( 10.0, 10.0) +coordinates_max = (10.0, 10.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=30_000, - periodicity=true) + initial_refinement_level = 3, + n_cells_max = 30_000, + periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -84,24 +83,23 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, alive_callback) - ############################################################################### # run the simulation -sol = solve(ode, SSPRK43(); abstol=1.0e-6, reltol=1.0e-6, dt=1e-3, - ode_default_options()..., callback=callbacks) +sol = solve(ode, SSPRK43(); abstol = 1.0e-6, reltol = 1.0e-6, dt = 1e-3, + ode_default_options()..., callback = callbacks) summary_callback() diff --git a/examples/tree_3d_dgsem/elixir_advection_amr.jl b/examples/tree_3d_dgsem/elixir_advection_amr.jl index 67664eed563..19a9bd18a8a 100644 --- a/examples/tree_3d_dgsem/elixir_advection_amr.jl +++ b/examples/tree_3d_dgsem/elixir_advection_amr.jl @@ -9,18 +9,16 @@ advection_velocity = (0.2, -0.7, 0.5) equations = LinearScalarAdvectionEquation3D(advection_velocity) initial_condition = initial_condition_gauss -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-5.0, -5.0, -5.0) -coordinates_max = ( 5.0, 5.0, 5.0) +coordinates_max = (5.0, 5.0, 5.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=30_000) - + initial_refinement_level = 4, + n_cells_max = 30_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -30,26 +28,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable=first), - base_level=4, - med_level=5, med_threshold=0.1, - max_level=6, max_threshold=0.6) +amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable = first), + base_level = 4, + med_level = 5, med_threshold = 0.1, + max_level = 6, max_threshold = 0.6) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=1.2) +stepsize_callback = StepsizeCallback(cfl = 1.2) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -61,7 +59,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_3d_dgsem/elixir_advection_basic.jl b/examples/tree_3d_dgsem/elixir_advection_basic.jl index da91a70fe6d..3ea50423be7 100644 --- a/examples/tree_3d_dgsem/elixir_advection_basic.jl +++ b/examples/tree_3d_dgsem/elixir_advection_basic.jl @@ -9,19 +9,19 @@ advection_velocity = (0.2, -0.7, 0.5) equations = LinearScalarAdvectionEquation3D(advection_velocity) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-1.0, -1.0, -1.0) # minimum coordinates (min(x), min(y), min(z)) -coordinates_max = ( 1.0, 1.0, 1.0) # maximum coordinates (max(x), max(y), max(z)) +coordinates_max = (1.0, 1.0, 1.0) # maximum coordinates (max(x), max(y), max(z)) # Create a uniformly refined mesh with periodic boundaries mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=30_000) # set maximum capacity of tree data structure + initial_refinement_level = 3, + n_cells_max = 30_000) # set maximum capacity of tree data structure # A semidiscretization collects data structures and functions for the spatial discretization -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, solver) - +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, + solver) ############################################################################### # ODE solvers, callbacks etc. @@ -34,26 +34,26 @@ ode = semidiscretize(semi, (0.0, 1.0)); summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.2) +stepsize_callback = StepsizeCallback(cfl = 1.2) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) - +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); # Print the timer summary summary_callback() diff --git a/examples/tree_3d_dgsem/elixir_advection_diffusion_amr.jl b/examples/tree_3d_dgsem/elixir_advection_diffusion_amr.jl new file mode 100644 index 00000000000..6a8f8d02590 --- /dev/null +++ b/examples/tree_3d_dgsem/elixir_advection_diffusion_amr.jl @@ -0,0 +1,93 @@ + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the linear advection equation + +advection_velocity = (0.2, -0.7, 0.5) +equations = LinearScalarAdvectionEquation3D(advection_velocity) + +diffusivity() = 5.0e-4 +equations_parabolic = LaplaceDiffusion3D(diffusivity(), equations) + +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) + +coordinates_min = (-1.0, -1.0, -1.0) +coordinates_max = (1.0, 1.0, 1.0) +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level = 4, + n_cells_max = 80_000) + +# Define initial condition +function initial_condition_diffusive_convergence_test(x, t, + equation::LinearScalarAdvectionEquation3D) + # Store translated coordinate for easy use of exact solution + x_trans = x - equation.advection_velocity * t + + nu = diffusivity() + c = 1.0 + A = 0.5 + L = 2 + f = 1 / L + omega = 2 * pi * f + scalar = c + A * sin(omega * sum(x_trans)) * exp(-2 * nu * omega^2 * t) + return SVector(scalar) +end +initial_condition = initial_condition_diffusive_convergence_test + +# define periodic boundary conditions everywhere +boundary_conditions = boundary_condition_periodic +boundary_conditions_parabolic = boundary_condition_periodic + +# A semidiscretization collects data structures and functions for the spatial discretization +semi = SemidiscretizationHyperbolicParabolic(mesh, + (equations, equations_parabolic), + initial_condition, solver; + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic)) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 0.2) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) + +amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable = first), + base_level = 3, + med_level = 4, med_threshold = 1.2, + max_level = 5, max_threshold = 1.45) +amr_callback = AMRCallback(semi, amr_controller, + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) + +stepsize_callback = StepsizeCallback(cfl = 1.0) + +callbacks = CallbackSet(summary_callback, + analysis_callback, + alive_callback, + save_solution, + amr_callback, + stepsize_callback) + +############################################################################### +# run the simulation + +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); +summary_callback() # print the timer summary diff --git a/examples/tree_3d_dgsem/elixir_advection_diffusion_nonperiodic.jl b/examples/tree_3d_dgsem/elixir_advection_diffusion_nonperiodic.jl new file mode 100644 index 00000000000..4c30406680a --- /dev/null +++ b/examples/tree_3d_dgsem/elixir_advection_diffusion_nonperiodic.jl @@ -0,0 +1,89 @@ +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the linear advection-diffusion equation + +diffusivity() = 5.0e-2 +advection_velocity = (1.0, 0.0, 0.0) +equations = LinearScalarAdvectionEquation3D(advection_velocity) +equations_parabolic = LaplaceDiffusion3D(diffusivity(), equations) + +# Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) + +coordinates_min = (-1.0, -0.5, -0.25) # minimum coordinates (min(x), min(y), min(z)) +coordinates_max = (0.0, 0.5, 0.25) # maximum coordinates (max(x), max(y), max(z)) + +# Create a uniformly refined mesh with periodic boundaries +mesh = TreeMesh(coordinates_min, coordinates_max, + initial_refinement_level = 3, + periodicity = false, + n_cells_max = 30_000) # set maximum capacity of tree data structure + +# Example setup taken from +# - Truman Ellis, Jesse Chan, and Leszek Demkowicz (2016). +# Robust DPG methods for transient convection-diffusion. +# In: Building bridges: connections and challenges in modern approaches +# to numerical partial differential equations. +# [DOI](https://doi.org/10.1007/978-3-319-41640-3_6). +function initial_condition_eriksson_johnson(x, t, equations) + l = 4 + epsilon = diffusivity() # TODO: this requires epsilon < .6 due to sqrt + lambda_1 = (-1 + sqrt(1 - 4 * epsilon * l)) / (-2 * epsilon) + lambda_2 = (-1 - sqrt(1 - 4 * epsilon * l)) / (-2 * epsilon) + r1 = (1 + sqrt(1 + 4 * pi^2 * epsilon^2)) / (2 * epsilon) + s1 = (1 - sqrt(1 + 4 * pi^2 * epsilon^2)) / (2 * epsilon) + u = exp(-l * t) * (exp(lambda_1 * x[1]) - exp(lambda_2 * x[1])) + + cos(pi * x[2]) * (exp(s1 * x[1]) - exp(r1 * x[1])) / (exp(-s1) - exp(-r1)) + return SVector{1}(u) +end +initial_condition = initial_condition_eriksson_johnson + +boundary_conditions = (; x_neg = BoundaryConditionDirichlet(initial_condition), + y_neg = BoundaryConditionDirichlet(initial_condition), + z_neg = boundary_condition_do_nothing, + y_pos = BoundaryConditionDirichlet(initial_condition), + x_pos = boundary_condition_do_nothing, + z_pos = boundary_condition_do_nothing) + +boundary_conditions_parabolic = BoundaryConditionDirichlet(initial_condition) + +# A semidiscretization collects data structures and functions for the spatial discretization +semi = SemidiscretizationHyperbolicParabolic(mesh, + (equations, equations_parabolic), + initial_condition, solver; + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic)) + +############################################################################### +# ODE solvers, callbacks etc. + +# Create ODE problem with time span `tspan` +tspan = (0.0, 0.5) +ode = semidiscretize(semi, tspan); + +# At the beginning of the main loop, the SummaryCallback prints a summary of the simulation setup +# and resets the timers +summary_callback = SummaryCallback() + +# The AnalysisCallback allows to analyse the solution in regular intervals and prints the results +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + +# The AliveCallback prints short status information in regular intervals +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +# Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver +callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) + +############################################################################### +# run the simulation + +# OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks +time_int_tol = 1.0e-11 +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) + +# Print the timer summary +summary_callback() diff --git a/examples/tree_3d_dgsem/elixir_advection_extended.jl b/examples/tree_3d_dgsem/elixir_advection_extended.jl index d820f47f25c..efc20c64f6d 100644 --- a/examples/tree_3d_dgsem/elixir_advection_extended.jl +++ b/examples/tree_3d_dgsem/elixir_advection_extended.jl @@ -18,21 +18,20 @@ initial_condition = initial_condition_convergence_test boundary_conditions = boundary_condition_periodic # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-1.0, -1.0, -1.0) # minimum coordinates (min(x), min(y), min(z)) -coordinates_max = ( 1.0, 1.0, 1.0) # maximum coordinates (max(x), max(y), max(z)) +coordinates_max = (1.0, 1.0, 1.0) # maximum coordinates (max(x), max(y), max(z)) # Create a uniformly refined mesh with periodic boundaries mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=30_000, # set maximum capacity of tree data structure - periodicity=true) + initial_refinement_level = 3, + n_cells_max = 30_000, # set maximum capacity of tree data structure + periodicity = true) # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -47,24 +46,24 @@ summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy, energy_total)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy, energy_total)) # The AliveCallback prints short status information in regular intervals -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) # The SaveRestartCallback allows to save a file from which a Trixi simulation can be restarted -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.2) +stepsize_callback = StepsizeCallback(cfl = 1.2) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver callbacks = CallbackSet(summary_callback, @@ -72,14 +71,13 @@ callbacks = CallbackSet(summary_callback, save_restart, save_solution, stepsize_callback) - ############################################################################### # run the simulation # OrdinaryDiffEq's `solve` method evolves the solution in time and executes the passed callbacks -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); # Print the timer summary summary_callback() diff --git a/examples/tree_3d_dgsem/elixir_advection_mortar.jl b/examples/tree_3d_dgsem/elixir_advection_mortar.jl index 7b24f152b6a..d27a19c7dcf 100644 --- a/examples/tree_3d_dgsem/elixir_advection_mortar.jl +++ b/examples/tree_3d_dgsem/elixir_advection_mortar.jl @@ -9,23 +9,21 @@ advection_velocity = (0.2, -0.7, 0.5) equations = LinearScalarAdvectionEquation3D(advection_velocity) initial_condition = initial_condition_convergence_test -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-1.0, -1.0, -1.0) -coordinates_max = ( 1.0, 1.0, 1.0) -refinement_patches = ( - (type="box", coordinates_min=(0.0, -1.0, -1.0), coordinates_max=(1.0, 1.0, 1.0)), - (type="box", coordinates_min=(0.0, -0.5, -0.5), coordinates_max=(0.5, 0.5, 0.5)), -) +coordinates_max = (1.0, 1.0, 1.0) +refinement_patches = ((type = "box", coordinates_min = (0.0, -1.0, -1.0), + coordinates_max = (1.0, 1.0, 1.0)), + (type = "box", coordinates_min = (0.0, -0.5, -0.5), + coordinates_max = (0.5, 0.5, 0.5))) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - refinement_patches=refinement_patches, - n_cells_max=10_000,) - + initial_refinement_level = 2, + refinement_patches = refinement_patches, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -35,17 +33,17 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.2) +stepsize_callback = StepsizeCallback(cfl = 1.2) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -53,11 +51,10 @@ callbacks = CallbackSet(summary_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_3d_dgsem/elixir_advection_restart.jl b/examples/tree_3d_dgsem/elixir_advection_restart.jl index 3061f165874..a53f4ebf5b1 100644 --- a/examples/tree_3d_dgsem/elixir_advection_restart.jl +++ b/examples/tree_3d_dgsem/elixir_advection_restart.jl @@ -7,7 +7,6 @@ using Trixi trixi_include(@__MODULE__, joinpath(@__DIR__, "elixir_advection_extended.jl")) - ############################################################################### # adapt the parameters that have changed compared to "elixir_advection_extended.jl" @@ -26,14 +25,12 @@ ode = semidiscretize(semi, tspan, restart_filename); # Do not overwrite the initial snapshot written by elixir_advection_extended.jl. save_solution.condition.save_initial_solution = false -integrator = init(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=dt, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +integrator = init(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = dt, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks, maxiters = 100_000); # Get the last time index and work with that. -integrator.iter = load_timestep(restart_filename) -integrator.stats.naccept = integrator.iter - +load_timestep!(integrator, restart_filename) ############################################################################### # run the simulation diff --git a/examples/tree_3d_dgsem/elixir_euler_amr.jl b/examples/tree_3d_dgsem/elixir_euler_amr.jl index f226a6b446d..9bd7f74c688 100644 --- a/examples/tree_3d_dgsem/elixir_euler_amr.jl +++ b/examples/tree_3d_dgsem/elixir_euler_amr.jl @@ -14,30 +14,28 @@ A Gaussian pulse in the density with constant velocity and pressure; reduces the compressible Euler equations to the linear advection equations. """ function initial_condition_density_pulse(x, t, equations::CompressibleEulerEquations3D) - rho = 1 + exp(-(x[1]^2 + x[2]^2 + x[3]^2))/2 - v1 = 1 - v2 = 1 - v3 = 1 - rho_v1 = rho * v1 - rho_v2 = rho * v2 - rho_v3 = rho * v3 - p = 1 - rho_e = p/(equations.gamma - 1) + 1/2 * rho * (v1^2 + v2^2 + v3^2) - return SVector(rho, rho_v1, rho_v2, rho_v3, rho_e) + rho = 1 + exp(-(x[1]^2 + x[2]^2 + x[3]^2)) / 2 + v1 = 1 + v2 = 1 + v3 = 1 + rho_v1 = rho * v1 + rho_v2 = rho * v2 + rho_v3 = rho * v3 + p = 1 + rho_e = p / (equations.gamma - 1) + 1 / 2 * rho * (v1^2 + v2^2 + v3^2) + return SVector(rho, rho_v1, rho_v2, rho_v3, rho_e) end initial_condition = initial_condition_density_pulse -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (-5.0, -5.0, -5.0) -coordinates_max = ( 5.0, 5.0, 5.0) +coordinates_max = (5.0, 5.0, 5.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=4, - n_cells_max=10_000) - + initial_refinement_level = 4, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -47,40 +45,39 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable=first), - base_level=4, - med_level=5, med_threshold=1.05, - max_level=6, max_threshold=1.3) +amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable = first), + base_level = 4, + med_level = 5, med_threshold = 1.05, + max_level = 6, max_threshold = 1.3) amr_callback = AMRCallback(semi, amr_controller, - interval=5, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 5, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=0.9) +stepsize_callback = StepsizeCallback(cfl = 0.9) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_restart, save_solution, amr_callback, stepsize_callback); - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_3d_dgsem/elixir_euler_blob_amr.jl b/examples/tree_3d_dgsem/elixir_euler_blob_amr.jl index a8d112f5b05..0ce886620cc 100644 --- a/examples/tree_3d_dgsem/elixir_euler_blob_amr.jl +++ b/examples/tree_3d_dgsem/elixir_euler_blob_amr.jl @@ -4,7 +4,7 @@ using Trixi ############################################################################### # semidiscretization of the compressible Euler equations -gamma = 5/3 +gamma = 5 / 3 equations = CompressibleEulerEquations3D(gamma) """ @@ -16,63 +16,65 @@ The blob test case taken from [arXiv: astro-ph/0610051](https://arxiv.org/abs/astro-ph/0610051) """ function initial_condition_blob(x, t, equations::CompressibleEulerEquations3D) - # blob test case, see Agertz et al. https://arxiv.org/pdf/astro-ph/0610051.pdf - # other reference: https://arxiv.org/pdf/astro-ph/0610051.pdf - # change discontinuity to tanh - # typical domain is rectangular, we change it to a square - # resolution 128^3, 256^3 - # domain size is [-20.0,20.0]^3 - # gamma = 5/3 for this test case - R = 1.0 # radius of the blob - # background density - rho = 1.0 - Chi = 10.0 # density contrast - # reference time of characteristic growth of KH instability equal to 1.0 - tau_kh = 1.0 - tau_cr = tau_kh / 1.6 # crushing time - # determine background velocity - v1 = 2 * R * sqrt(Chi) / tau_cr - v2 = 0.0 - v3 = 0.0 - Ma0 = 2.7 # background flow Mach number Ma=v/c - c = v1 / Ma0 # sound speed - # use perfect gas assumption to compute background pressure via the sound speed c^2 = gamma * pressure/density - p = c * c * rho / equations.gamma - # initial center of the blob - inicenter = [-15, 0, 0] - x_rel = x - inicenter - r = sqrt(x_rel[1]^2 + x_rel[2]^2 + x_rel[3]^2) - # steepness of the tanh transition zone - slope = 2 - # density blob - rho = rho + (Chi - 1) * 0.5 * (1 + (tanh(slope * (r + R)) - (tanh(slope *(r - R)) + 1))) - # velocity blob is zero - v1 = v1 - v1 * 0.5 * (1 + (tanh(slope *(r + R)) - (tanh(slope *(r - R)) + 1))) - return prim2cons(SVector(rho, v1, v2, v3, p), equations) + # blob test case, see Agertz et al. https://arxiv.org/pdf/astro-ph/0610051.pdf + # other reference: https://arxiv.org/pdf/astro-ph/0610051.pdf + # change discontinuity to tanh + # typical domain is rectangular, we change it to a square + # resolution 128^3, 256^3 + # domain size is [-20.0,20.0]^3 + # gamma = 5/3 for this test case + R = 1.0 # radius of the blob + # background density + rho = 1.0 + Chi = 10.0 # density contrast + # reference time of characteristic growth of KH instability equal to 1.0 + tau_kh = 1.0 + tau_cr = tau_kh / 1.6 # crushing time + # determine background velocity + v1 = 2 * R * sqrt(Chi) / tau_cr + v2 = 0.0 + v3 = 0.0 + Ma0 = 2.7 # background flow Mach number Ma=v/c + c = v1 / Ma0 # sound speed + # use perfect gas assumption to compute background pressure via the sound speed c^2 = gamma * pressure/density + p = c * c * rho / equations.gamma + # initial center of the blob + inicenter = [-15, 0, 0] + x_rel = x - inicenter + r = sqrt(x_rel[1]^2 + x_rel[2]^2 + x_rel[3]^2) + # steepness of the tanh transition zone + slope = 2 + # density blob + rho = rho + + (Chi - 1) * 0.5 * (1 + (tanh(slope * (r + R)) - (tanh(slope * (r - R)) + 1))) + # velocity blob is zero + v1 = v1 - v1 * 0.5 * (1 + (tanh(slope * (r + R)) - (tanh(slope * (r - R)) + 1))) + return prim2cons(SVector(rho, v1, v2, v3, p), equations) end initial_condition = initial_condition_blob volume_flux = flux_ranocha -solver = DGSEM(polydeg=3, surface_flux=flux_hllc, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_hllc, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-20.0, -20.0, -20.0) -coordinates_max = ( 20.0, 20.0, 20.0) - -refinement_patches = ( - (type="box", coordinates_min=(-20.0, -10.0, -10.0), coordinates_max=(-10.0, 10.0, 10.0)), - (type="box", coordinates_min=(-20.0, -5.0, -5.0), coordinates_max=(-10.0, 5.0, 5.0)), - (type="box", coordinates_min=(-17.0, -2.0, -2.0), coordinates_max=(-13.0, 2.0, 2.0)), - (type="box", coordinates_min=(-17.0, -2.0, -2.0), coordinates_max=(-13.0, 2.0, 2.0)), -) +coordinates_max = (20.0, 20.0, 20.0) + +refinement_patches = ((type = "box", coordinates_min = (-20.0, -10.0, -10.0), + coordinates_max = (-10.0, 10.0, 10.0)), + (type = "box", coordinates_min = (-20.0, -5.0, -5.0), + coordinates_max = (-10.0, 5.0, 5.0)), + (type = "box", coordinates_min = (-17.0, -2.0, -2.0), + coordinates_max = (-13.0, 2.0, 2.0)), + (type = "box", coordinates_min = (-17.0, -2.0, -2.0), + coordinates_max = (-13.0, 2.0, 2.0))) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - refinement_patches=refinement_patches, - n_cells_max=100_000,) + initial_refinement_level = 2, + refinement_patches = refinement_patches, + n_cells_max = 100_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -82,41 +84,40 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 200 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=200, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 200, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_indicator = IndicatorLöhner(semi, - variable=Trixi.density) + variable = Trixi.density) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=1, - med_level =0, med_threshold=0.1, # med_level = current level - max_level =6, max_threshold=0.3) + base_level = 1, + med_level = 0, med_threshold = 0.1, # med_level = current level + max_level = 6, max_threshold = 0.3) amr_callback = AMRCallback(semi, amr_controller, - interval=3, - adapt_initial_condition=false, - adapt_initial_condition_only_refine=true) + interval = 3, + adapt_initial_condition = false, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=1.7) +stepsize_callback = StepsizeCallback(cfl = 1.7) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, amr_callback, stepsize_callback) - -stage_limiter! = PositivityPreservingLimiterZhangShu(thresholds=(1.0e-4, 1.0e-4), - variables=(Trixi.density, pressure)) +stage_limiter! = PositivityPreservingLimiterZhangShu(thresholds = (1.0e-4, 1.0e-4), + variables = (Trixi.density, pressure)) ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(stage_limiter!, williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(stage_limiter!, williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_3d_dgsem/elixir_euler_convergence.jl b/examples/tree_3d_dgsem/elixir_euler_convergence.jl index 2eeb280ae1f..170b292a42f 100644 --- a/examples/tree_3d_dgsem/elixir_euler_convergence.jl +++ b/examples/tree_3d_dgsem/elixir_euler_convergence.jl @@ -9,19 +9,17 @@ equations = CompressibleEulerEquations3D(2.0) initial_condition = initial_condition_eoc_test_coupled_euler_gravity -solver = DGSEM(polydeg=3, surface_flux=flux_hll, - volume_integral=VolumeIntegralWeakForm()) +solver = DGSEM(polydeg = 3, surface_flux = flux_hll, + volume_integral = VolumeIntegralWeakForm()) coordinates_min = (0.0, 0.0, 0.0) coordinates_max = (2.0, 2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=10_000) - + initial_refinement_level = 2, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_eoc_test_euler) - + source_terms = source_terms_eoc_test_euler) ############################################################################### # ODE solvers, callbacks etc. @@ -32,27 +30,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.1) +stepsize_callback = StepsizeCallback(cfl = 1.1) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_3d_dgsem/elixir_euler_convergence_pure_fv.jl b/examples/tree_3d_dgsem/elixir_euler_convergence_pure_fv.jl index dbf5747784c..4789b46dacc 100644 --- a/examples/tree_3d_dgsem/elixir_euler_convergence_pure_fv.jl +++ b/examples/tree_3d_dgsem/elixir_euler_convergence_pure_fv.jl @@ -9,19 +9,17 @@ equations = CompressibleEulerEquations3D(1.4) initial_condition = initial_condition_convergence_test -solver = DGSEM(polydeg=3, surface_flux=flux_hllc, - volume_integral=VolumeIntegralPureLGLFiniteVolume(flux_hllc)) +solver = DGSEM(polydeg = 3, surface_flux = flux_hllc, + volume_integral = VolumeIntegralPureLGLFiniteVolume(flux_hllc)) coordinates_min = (0.0, 0.0, 0.0) coordinates_max = (2.0, 2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=10_000) - + initial_refinement_level = 2, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -32,27 +30,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.6) +stepsize_callback = StepsizeCallback(cfl = 0.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_3d_dgsem/elixir_euler_density_pulse.jl b/examples/tree_3d_dgsem/elixir_euler_density_pulse.jl index ee788321c66..cad8fc578c8 100644 --- a/examples/tree_3d_dgsem/elixir_euler_density_pulse.jl +++ b/examples/tree_3d_dgsem/elixir_euler_density_pulse.jl @@ -14,33 +14,31 @@ A Gaussian pulse in the density with constant velocity and pressure; reduces the compressible Euler equations to the linear advection equations. """ function initial_condition_density_pulse(x, t, equations::CompressibleEulerEquations3D) - rho = 1 + exp(-(x[1]^2 + x[2]^2 + x[3]^2))/2 - v1 = 1 - v2 = 1 - v3 = 1 - rho_v1 = rho * v1 - rho_v2 = rho * v2 - rho_v3 = rho * v3 - p = 1 - rho_e = p/(equations.gamma - 1) + 1/2 * rho * (v1^2 + v2^2 + v3^2) - return SVector(rho, rho_v1, rho_v2, rho_v3, rho_e) + rho = 1 + exp(-(x[1]^2 + x[2]^2 + x[3]^2)) / 2 + v1 = 1 + v2 = 1 + v3 = 1 + rho_v1 = rho * v1 + rho_v2 = rho * v2 + rho_v3 = rho * v3 + p = 1 + rho_e = p / (equations.gamma - 1) + 1 / 2 * rho * (v1^2 + v2^2 + v3^2) + return SVector(rho, rho_v1, rho_v2, rho_v3, rho_e) end initial_condition = initial_condition_density_pulse volume_flux = flux_ranocha -solver = DGSEM(polydeg=3, surface_flux=flux_ranocha, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_ranocha, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-2.0, -2.0, -2.0) -coordinates_max = ( 2.0, 2.0, 2.0) +coordinates_max = (2.0, 2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=100_000) - + initial_refinement_level = 3, + n_cells_max = 100_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -50,30 +48,29 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.1) +stepsize_callback = StepsizeCallback(cfl = 1.1) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_restart, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_3d_dgsem/elixir_euler_ec.jl b/examples/tree_3d_dgsem/elixir_euler_ec.jl index 08fd1b998d5..88d7cbc7ba5 100644 --- a/examples/tree_3d_dgsem/elixir_euler_ec.jl +++ b/examples/tree_3d_dgsem/elixir_euler_ec.jl @@ -10,19 +10,17 @@ equations = CompressibleEulerEquations3D(1.4) initial_condition = initial_condition_weak_blast_wave volume_flux = flux_ranocha -solver = DGSEM(polydeg=3, surface_flux=flux_ranocha, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_ranocha, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-2.0, -2.0, -2.0) -coordinates_max = ( 2.0, 2.0, 2.0) +coordinates_max = (2.0, 2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=100_000) - + initial_refinement_level = 3, + n_cells_max = 100_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -32,27 +30,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.3) +stepsize_callback = StepsizeCallback(cfl = 1.3) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_3d_dgsem/elixir_euler_mortar.jl b/examples/tree_3d_dgsem/elixir_euler_mortar.jl index c9fc2dfed50..cf103dc26cf 100644 --- a/examples/tree_3d_dgsem/elixir_euler_mortar.jl +++ b/examples/tree_3d_dgsem/elixir_euler_mortar.jl @@ -8,22 +8,19 @@ using Trixi equations = CompressibleEulerEquations3D(1.4) initial_condition = initial_condition_convergence_test -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (0.0, 0.0, 0.0) coordinates_max = (2.0, 2.0, 2.0) -refinement_patches = ( - (type="box", coordinates_min=(0.5, 0.5, 0.5), coordinates_max=(1.5, 1.5, 1.5)), -) +refinement_patches = ((type = "box", coordinates_min = (0.5, 0.5, 0.5), + coordinates_max = (1.5, 1.5, 1.5)),) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - refinement_patches=refinement_patches, - n_cells_max=10_000) - + initial_refinement_level = 2, + refinement_patches = refinement_patches, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -34,16 +31,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.6) +stepsize_callback = StepsizeCallback(cfl = 0.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -53,7 +50,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_3d_dgsem/elixir_euler_sedov_blast_wave.jl b/examples/tree_3d_dgsem/elixir_euler_sedov_blast_wave.jl index 3641878149a..87774ada266 100644 --- a/examples/tree_3d_dgsem/elixir_euler_sedov_blast_wave.jl +++ b/examples/tree_3d_dgsem/elixir_euler_sedov_blast_wave.jl @@ -19,34 +19,34 @@ based on Should be used together with [`boundary_condition_sedov_self_gravity`](@ref). """ function initial_condition_sedov_self_gravity(x, t, equations::CompressibleEulerEquations3D) - # Calculate radius as distance from origin - r = sqrt(x[1]^2 + x[2]^2 + x[3]^2) - - # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 - r0 = 0.25 # = 4.0 * smallest dx (for domain length=8 and max-ref=7) - E = 1.0 - p_inner = (equations.gamma - 1) * E / (4/3 * pi * r0^3) - p_ambient = 1e-5 # = true Sedov setup - - # Calculate primitive variables - # use a logistic function to transfer density value smoothly - L = 1.0 # maximum of function - x0 = 1.0 # center point of function - k = -50.0 # sharpness of transfer - logistic_function_rho = L/(1.0 + exp(-k*(r - x0))) - rho_ambient = 1e-5 - rho = max(logistic_function_rho, rho_ambient) # clip background density to not be so tiny - - # velocities are zero - v1 = 0.0 - v2 = 0.0 - v3 = 0.0 - - # use a logistic function to transfer pressure value smoothly - logistic_function_p = p_inner/(1.0 + exp(-k*(r - r0))) - p = max(logistic_function_p, p_ambient) - - return prim2cons(SVector(rho, v1, v2, v3, p), equations) + # Calculate radius as distance from origin + r = sqrt(x[1]^2 + x[2]^2 + x[3]^2) + + # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 + r0 = 0.25 # = 4.0 * smallest dx (for domain length=8 and max-ref=7) + E = 1.0 + p_inner = (equations.gamma - 1) * E / (4 / 3 * pi * r0^3) + p_ambient = 1e-5 # = true Sedov setup + + # Calculate primitive variables + # use a logistic function to transfer density value smoothly + L = 1.0 # maximum of function + x0 = 1.0 # center point of function + k = -50.0 # sharpness of transfer + logistic_function_rho = L / (1.0 + exp(-k * (r - x0))) + rho_ambient = 1e-5 + rho = max(logistic_function_rho, rho_ambient) # clip background density to not be so tiny + + # velocities are zero + v1 = 0.0 + v2 = 0.0 + v3 = 0.0 + + # use a logistic function to transfer pressure value smoothly + logistic_function_p = p_inner / (1.0 + exp(-k * (r - r0))) + p = max(logistic_function_p, p_ambient) + + return prim2cons(SVector(rho, v1, v2, v3, p), equations) end initial_condition = initial_condition_sedov_self_gravity @@ -64,26 +64,26 @@ based on Should be used together with [`initial_condition_sedov_self_gravity`](@ref). """ function boundary_condition_sedov_self_gravity(u_inner, orientation, direction, x, t, - surface_flux_function, - equations::CompressibleEulerEquations3D) - # velocities are zero, density/pressure are ambient values according to - # initial_condition_sedov_self_gravity - rho = 1e-5 - v1 = 0.0 - v2 = 0.0 - v3 = 0.0 - p = 1e-5 - - u_boundary = prim2cons(SVector(rho, v1, v2, v3, p), equations) - - # Calculate boundary flux - if iseven(direction) # u_inner is "left" of boundary, u_boundary is "right" of boundary - flux = surface_flux_function(u_inner, u_boundary, orientation, equations) - else # u_boundary is "left" of boundary, u_inner is "right" of boundary - flux = surface_flux_function(u_boundary, u_inner, orientation, equations) - end - - return flux + surface_flux_function, + equations::CompressibleEulerEquations3D) + # velocities are zero, density/pressure are ambient values according to + # initial_condition_sedov_self_gravity + rho = 1e-5 + v1 = 0.0 + v2 = 0.0 + v3 = 0.0 + p = 1e-5 + + u_boundary = prim2cons(SVector(rho, v1, v2, v3, p), equations) + + # Calculate boundary flux + if iseven(direction) # u_inner is "left" of boundary, u_boundary is "right" of boundary + flux = surface_flux_function(u_inner, u_boundary, orientation, equations) + else # u_boundary is "left" of boundary, u_inner is "right" of boundary + flux = surface_flux_function(u_boundary, u_inner, orientation, equations) + end + + return flux end boundary_conditions = boundary_condition_sedov_self_gravity @@ -92,26 +92,24 @@ volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.7, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.7, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-4.0, -4.0, -4.0) -coordinates_max = ( 4.0, 4.0, 4.0) +coordinates_max = (4.0, 4.0, 4.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=1_000_000, - periodicity=false) - + initial_refinement_level = 2, + n_cells_max = 1_000_000, + periodicity = false) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -122,42 +120,41 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_indicator = IndicatorHennemannGassner(semi, - alpha_max=1.0, - alpha_min=0.0, - alpha_smooth=false, - variable=density_pressure) + alpha_max = 1.0, + alpha_min = 0.0, + alpha_smooth = false, + variable = density_pressure) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=2, - max_level =7, max_threshold=0.0003) + base_level = 2, + max_level = 7, max_threshold = 0.0003) amr_callback = AMRCallback(semi, amr_controller, - interval=1, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 1, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=0.35) +stepsize_callback = StepsizeCallback(cfl = 0.35) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, amr_callback, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_3d_dgsem/elixir_euler_shockcapturing.jl b/examples/tree_3d_dgsem/elixir_euler_shockcapturing.jl index 3015f6c50a4..0a90615016c 100644 --- a/examples/tree_3d_dgsem/elixir_euler_shockcapturing.jl +++ b/examples/tree_3d_dgsem/elixir_euler_shockcapturing.jl @@ -10,30 +10,28 @@ equations = CompressibleEulerEquations3D(1.4) initial_condition = initial_condition_weak_blast_wave surface_flux = flux_ranocha # OBS! Using a non-dissipative flux is only sensible to test EC, - # but not for real shock simulations +# but not for real shock simulations volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-2.0, -2.0, -2.0) -coordinates_max = ( 2.0, 2.0, 2.0) +coordinates_max = (2.0, 2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=100_000) - + initial_refinement_level = 3, + n_cells_max = 100_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -43,27 +41,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.4) +stepsize_callback = StepsizeCallback(cfl = 1.4) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_3d_dgsem/elixir_euler_shockcapturing_amr.jl b/examples/tree_3d_dgsem/elixir_euler_shockcapturing_amr.jl index 3d338cd7f01..be31fbbc42c 100644 --- a/examples/tree_3d_dgsem/elixir_euler_shockcapturing_amr.jl +++ b/examples/tree_3d_dgsem/elixir_euler_shockcapturing_amr.jl @@ -10,30 +10,28 @@ equations = CompressibleEulerEquations3D(1.4) initial_condition = initial_condition_weak_blast_wave surface_flux = flux_ranocha # OBS! Using a non-dissipative flux is only sensible to test EC, - # but not for real shock simulations +# but not for real shock simulations volume_flux = flux_ranocha polydeg = 3 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) coordinates_min = (-2.0, -2.0, -2.0) -coordinates_max = ( 2.0, 2.0, 2.0) +coordinates_max = (2.0, 2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=100_000) - + initial_refinement_level = 3, + n_cells_max = 100_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -43,41 +41,39 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) amr_indicator = IndicatorHennemannGassner(semi, - alpha_smooth=false, - variable=density_pressure) + alpha_smooth = false, + variable = density_pressure) amr_controller = ControllerThreeLevel(semi, amr_indicator, - base_level=2, - max_level =4, max_threshold=0.0003) + base_level = 2, + max_level = 4, max_threshold = 0.0003) amr_callback = AMRCallback(semi, amr_controller, - interval=1, - adapt_initial_condition=true, - adapt_initial_condition_only_refine=true) + interval = 1, + adapt_initial_condition = true, + adapt_initial_condition_only_refine = true) -stepsize_callback = StepsizeCallback(cfl=1.3) +stepsize_callback = StepsizeCallback(cfl = 1.3) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, amr_callback, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary - diff --git a/examples/tree_3d_dgsem/elixir_euler_source_terms.jl b/examples/tree_3d_dgsem/elixir_euler_source_terms.jl index 3445e9fc433..f0246c30490 100644 --- a/examples/tree_3d_dgsem/elixir_euler_source_terms.jl +++ b/examples/tree_3d_dgsem/elixir_euler_source_terms.jl @@ -9,19 +9,17 @@ equations = CompressibleEulerEquations3D(1.4) initial_condition = initial_condition_convergence_test -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralWeakForm()) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralWeakForm()) coordinates_min = (0.0, 0.0, 0.0) coordinates_max = (2.0, 2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=10_000) - + initial_refinement_level = 2, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -32,27 +30,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=0.6) +stepsize_callback = StepsizeCallback(cfl = 0.6) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_3d_dgsem/elixir_euler_taylor_green_vortex.jl b/examples/tree_3d_dgsem/elixir_euler_taylor_green_vortex.jl index 693f9ce9049..135ee673e44 100644 --- a/examples/tree_3d_dgsem/elixir_euler_taylor_green_vortex.jl +++ b/examples/tree_3d_dgsem/elixir_euler_taylor_green_vortex.jl @@ -12,35 +12,37 @@ equations = CompressibleEulerEquations3D(1.4) The classical inviscid Taylor-Green vortex. """ -function initial_condition_taylor_green_vortex(x, t, equations::CompressibleEulerEquations3D) - A = 1.0 # magnitude of speed - Ms = 0.1 # maximum Mach number - - rho = 1.0 - v1 = A * sin(x[1]) * cos(x[2]) * cos(x[3]) - v2 = -A * cos(x[1]) * sin(x[2]) * cos(x[3]) - v3 = 0.0 - p = (A / Ms)^2 * rho / equations.gamma # scaling to get Ms - p = p + 1.0/16.0 * A^2 * rho * (cos(2*x[1])*cos(2*x[3]) + 2*cos(2*x[2]) + 2*cos(2*x[1]) + cos(2*x[2])*cos(2*x[3])) - - return prim2cons(SVector(rho, v1, v2, v3, p), equations) +function initial_condition_taylor_green_vortex(x, t, + equations::CompressibleEulerEquations3D) + A = 1.0 # magnitude of speed + Ms = 0.1 # maximum Mach number + + rho = 1.0 + v1 = A * sin(x[1]) * cos(x[2]) * cos(x[3]) + v2 = -A * cos(x[1]) * sin(x[2]) * cos(x[3]) + v3 = 0.0 + p = (A / Ms)^2 * rho / equations.gamma # scaling to get Ms + p = p + + 1.0 / 16.0 * A^2 * rho * + (cos(2 * x[1]) * cos(2 * x[3]) + 2 * cos(2 * x[2]) + 2 * cos(2 * x[1]) + + cos(2 * x[2]) * cos(2 * x[3])) + + return prim2cons(SVector(rho, v1, v2, v3, p), equations) end initial_condition = initial_condition_taylor_green_vortex volume_flux = flux_ranocha -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-1.0, -1.0, -1.0) .* pi -coordinates_max = ( 1.0, 1.0, 1.0) .* pi +coordinates_max = (1.0, 1.0, 1.0) .* pi mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=100_000) - + initial_refinement_level = 3, + n_cells_max = 100_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -50,27 +52,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.4) +stepsize_callback = StepsizeCallback(cfl = 1.4) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_3d_dgsem/elixir_eulergravity_convergence.jl b/examples/tree_3d_dgsem/elixir_eulergravity_convergence.jl index 6699ec9a4da..21ef661d0b6 100644 --- a/examples/tree_3d_dgsem/elixir_eulergravity_convergence.jl +++ b/examples/tree_3d_dgsem/elixir_eulergravity_convergence.jl @@ -15,12 +15,12 @@ solver_euler = DGSEM(polydeg, flux_hll) coordinates_min = (0.0, 0.0, 0.0) coordinates_max = (2.0, 2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=10_000) - -semi_euler = SemidiscretizationHyperbolic(mesh, equations_euler, initial_condition, solver_euler, - source_terms=source_terms_eoc_test_coupled_euler_gravity) + initial_refinement_level = 2, + n_cells_max = 10_000) +semi_euler = SemidiscretizationHyperbolic(mesh, equations_euler, initial_condition, + solver_euler, + source_terms = source_terms_eoc_test_coupled_euler_gravity) ############################################################################### # semidiscretization of the hyperbolic diffusion equations @@ -28,22 +28,21 @@ equations_gravity = HyperbolicDiffusionEquations3D() solver_gravity = DGSEM(polydeg, flux_lax_friedrichs) -semi_gravity = SemidiscretizationHyperbolic(mesh, equations_gravity, initial_condition, solver_gravity, - source_terms=source_terms_harmonic) - +semi_gravity = SemidiscretizationHyperbolic(mesh, equations_gravity, initial_condition, + solver_gravity, + source_terms = source_terms_harmonic) ############################################################################### # combining both semidiscretizations for Euler + self-gravity -parameters = ParametersEulerGravity(background_density=2.0, # aka rho0 - gravitational_constant=1.0, # aka G - cfl=1.5, - resid_tol=1.0e-10, - n_iterations_max=1000, - timestep_gravity=timestep_gravity_erk52_3Sstar!) +parameters = ParametersEulerGravity(background_density = 2.0, # aka rho0 + gravitational_constant = 1.0, # aka G + cfl = 1.5, + resid_tol = 1.0e-10, + n_iterations_max = 1000, + timestep_gravity = timestep_gravity_erk52_3Sstar!) semi = SemidiscretizationEulerGravity(semi_euler, semi_gravity, parameters) - ############################################################################### # ODE solvers, callbacks etc. tspan = (0.0, 0.5) @@ -52,20 +51,20 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi_euler, interval=analysis_interval, - save_analysis=true) +analysis_callback = AnalysisCallback(semi_euler, interval = analysis_interval, + save_analysis = true) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=10, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 10, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.1) +stepsize_callback = StepsizeCallback(cfl = 1.1) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -74,11 +73,10 @@ callbacks = CallbackSet(summary_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary println("Number of gravity subcycles: ", semi.gravity_counter.ncalls_since_readout) diff --git a/examples/tree_3d_dgsem/elixir_hypdiff_lax_friedrichs.jl b/examples/tree_3d_dgsem/elixir_hypdiff_lax_friedrichs.jl index c7744ce23bd..7bba154a925 100644 --- a/examples/tree_3d_dgsem/elixir_hypdiff_lax_friedrichs.jl +++ b/examples/tree_3d_dgsem/elixir_hypdiff_lax_friedrichs.jl @@ -8,53 +8,52 @@ using Trixi equations = HyperbolicDiffusionEquations3D() function initial_condition_poisson_periodic(x, t, equations::HyperbolicDiffusionEquations3D) - # elliptic equation: -νΔϕ = f - # depending on initial constant state, c, for phi this converges to the solution ϕ + c - if iszero(t) - phi = 0.0 - q1 = 0.0 - q2 = 0.0 - q3 = 0.0 - else - phi = sin(2 * pi * x[1]) * sin(2 * pi * x[2]) * sin(2 * pi * x[3]) - q1 = 2 * pi * cos(2 * pi * x[1]) * sin(2 * pi * x[2]) * sin(2 * pi * x[3]) - q2 = 2 * pi * sin(2 * pi * x[1]) * cos(2 * pi * x[2]) * sin(2 * pi * x[3]) - q3 = 2 * pi * sin(2 * pi * x[1]) * sin(2 * pi * x[2]) * cos(2 * pi * x[3]) - end - return SVector(phi, q1, q2, q3) + # elliptic equation: -νΔϕ = f + # depending on initial constant state, c, for phi this converges to the solution ϕ + c + if iszero(t) + phi = 0.0 + q1 = 0.0 + q2 = 0.0 + q3 = 0.0 + else + phi = sin(2 * pi * x[1]) * sin(2 * pi * x[2]) * sin(2 * pi * x[3]) + q1 = 2 * pi * cos(2 * pi * x[1]) * sin(2 * pi * x[2]) * sin(2 * pi * x[3]) + q2 = 2 * pi * sin(2 * pi * x[1]) * cos(2 * pi * x[2]) * sin(2 * pi * x[3]) + q3 = 2 * pi * sin(2 * pi * x[1]) * sin(2 * pi * x[2]) * cos(2 * pi * x[3]) + end + return SVector(phi, q1, q2, q3) end initial_condition = initial_condition_poisson_periodic -@inline function source_terms_poisson_periodic(u, x, t, equations::HyperbolicDiffusionEquations3D) - # elliptic equation: -νΔϕ = f - # analytical solution: phi = sin(2πx)*sin(2πy) and f = -8νπ^2 sin(2πx)*sin(2πy) - @unpack inv_Tr = equations - C = -12 * equations.nu * pi^2 - - x1, x2, x3 = x - tmp1 = sinpi(2 * x1) - tmp2 = sinpi(2 * x2) - tmp3 = sinpi(2 * x3) - du1 = -C*tmp1*tmp2*tmp3 - du2 = -inv_Tr * u[2] - du3 = -inv_Tr * u[3] - du4 = -inv_Tr * u[4] - - return SVector(du1, du2, du3, du4) +@inline function source_terms_poisson_periodic(u, x, t, + equations::HyperbolicDiffusionEquations3D) + # elliptic equation: -νΔϕ = f + # analytical solution: phi = sin(2πx)*sin(2πy) and f = -8νπ^2 sin(2πx)*sin(2πy) + @unpack inv_Tr = equations + C = -12 * equations.nu * pi^2 + + x1, x2, x3 = x + tmp1 = sinpi(2 * x1) + tmp2 = sinpi(2 * x2) + tmp3 = sinpi(2 * x3) + du1 = -C * tmp1 * tmp2 * tmp3 + du2 = -inv_Tr * u[2] + du3 = -inv_Tr * u[3] + du4 = -inv_Tr * u[4] + + return SVector(du1, du2, du3, du4) end -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs) coordinates_min = (0.0, 0.0, 0.0) coordinates_max = (1.0, 1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=30_000) - + initial_refinement_level = 3, + n_cells_max = 30_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_poisson_periodic) - + source_terms = source_terms_poisson_periodic) ############################################################################### # ODE solvers, callbacks etc. @@ -65,20 +64,20 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() resid_tol = 5.0e-12 -steady_state_callback = SteadyStateCallback(abstol=resid_tol, reltol=0.0) +steady_state_callback = SteadyStateCallback(abstol = resid_tol, reltol = 0.0) analysis_interval = 200 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy, energy_total)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy, energy_total)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=2.4) +stepsize_callback = StepsizeCallback(cfl = 2.4) callbacks = CallbackSet(summary_callback, steady_state_callback, analysis_callback, alive_callback, @@ -89,6 +88,6 @@ callbacks = CallbackSet(summary_callback, steady_state_callback, # run the simulation sol = Trixi.solve(ode, Trixi.HypDiffN3Erk3Sstar52(), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_3d_dgsem/elixir_hypdiff_nonperiodic.jl b/examples/tree_3d_dgsem/elixir_hypdiff_nonperiodic.jl index beefb22ea1e..831e01519b6 100644 --- a/examples/tree_3d_dgsem/elixir_hypdiff_nonperiodic.jl +++ b/examples/tree_3d_dgsem/elixir_hypdiff_nonperiodic.jl @@ -8,27 +8,25 @@ using Trixi equations = HyperbolicDiffusionEquations3D() initial_condition = initial_condition_poisson_nonperiodic -boundary_conditions = (x_neg=boundary_condition_poisson_nonperiodic, - x_pos=boundary_condition_poisson_nonperiodic, - y_neg=boundary_condition_periodic, - y_pos=boundary_condition_periodic, - z_neg=boundary_condition_periodic, - z_pos=boundary_condition_periodic) +boundary_conditions = (x_neg = boundary_condition_poisson_nonperiodic, + x_pos = boundary_condition_poisson_nonperiodic, + y_neg = boundary_condition_periodic, + y_pos = boundary_condition_periodic, + z_neg = boundary_condition_periodic, + z_pos = boundary_condition_periodic) -solver = DGSEM(polydeg=4, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 4, surface_flux = flux_lax_friedrichs) coordinates_min = (0.0, 0.0, 0.0) coordinates_max = (1.0, 1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=30_000, - periodicity=(false, true, true)) - + initial_refinement_level = 2, + n_cells_max = 30_000, + periodicity = (false, true, true)) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_poisson_nonperiodic, - boundary_conditions=boundary_conditions) - + source_terms = source_terms_poisson_nonperiodic, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -39,31 +37,30 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() resid_tol = 1.0e-5 -steady_state_callback = SteadyStateCallback(abstol=resid_tol, reltol=0.0) +steady_state_callback = SteadyStateCallback(abstol = resid_tol, reltol = 0.0) analysis_interval = 200 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(entropy, energy_total)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (entropy, energy_total)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.8) +stepsize_callback = StepsizeCallback(cfl = 1.8) callbacks = CallbackSet(summary_callback, steady_state_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation sol = Trixi.solve(ode, Trixi.HypDiffN3Erk3Sstar52(), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_3d_dgsem/elixir_lbm_constant.jl b/examples/tree_3d_dgsem/elixir_lbm_constant.jl index 269a0da2d50..ee38f62887d 100644 --- a/examples/tree_3d_dgsem/elixir_lbm_constant.jl +++ b/examples/tree_3d_dgsem/elixir_lbm_constant.jl @@ -5,22 +5,20 @@ using Trixi ############################################################################### # semidiscretization of the Lattice-Boltzmann equations for the D3Q27 scheme -equations = LatticeBoltzmannEquations3D(Ma=0.1, Re=Inf) +equations = LatticeBoltzmannEquations3D(Ma = 0.1, Re = Inf) initial_condition = initial_condition_constant -solver = DGSEM(polydeg=3, surface_flux=flux_godunov) +solver = DGSEM(polydeg = 3, surface_flux = flux_godunov) coordinates_min = (-1.0, -1.0, -1.0) -coordinates_max = ( 1.0, 1.0, 1.0) +coordinates_max = (1.0, 1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=10_000,) - + initial_refinement_level = 3, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -30,19 +28,19 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=100, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 100, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2macroscopic) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2macroscopic) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) collision_callback = LBMCollisionCallback() @@ -52,11 +50,10 @@ callbacks = CallbackSet(summary_callback, stepsize_callback, collision_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_3d_dgsem/elixir_lbm_taylor_green_vortex.jl b/examples/tree_3d_dgsem/elixir_lbm_taylor_green_vortex.jl index b3835eb1287..0980ee56be3 100644 --- a/examples/tree_3d_dgsem/elixir_lbm_taylor_green_vortex.jl +++ b/examples/tree_3d_dgsem/elixir_lbm_taylor_green_vortex.jl @@ -6,7 +6,7 @@ using Trixi # semidiscretization of the Lattice-Boltzmann equations for the D3Q27 scheme L = 1.0 # reference length -equations = LatticeBoltzmannEquations3D(Ma=0.1, Re=1600.0; L=L) +equations = LatticeBoltzmannEquations3D(Ma = 0.1, Re = 1600.0; L = L) """ initial_condition_taylor_green_vortex(x, t, equations::LatticeBoltzmannEquations3D) @@ -14,52 +14,51 @@ equations = LatticeBoltzmannEquations3D(Ma=0.1, Re=1600.0; L=L) Initialize the flow field to the Taylor-Green vortex setup """ function initial_condition_taylor_green_vortex(x, t, equations::LatticeBoltzmannEquations3D) - @unpack u0, rho0, L = equations + @unpack u0, rho0, L = equations - v1 = u0 * sin(x[1] / L) * cos(x[2] / L) * cos(x[3] / L) - v2 = -u0 * cos(x[1] / L) * sin(x[2] / L) * cos(x[3] / L) - v3 = 0 - p0 = (pressure(rho0, equations) + - rho0 * u0^2 / 16 * (cos(2 * x[1] / L) + cos(2 * x[2] / L)) * (cos(2 * x[3] / L) + 2)) - rho = density(p0, equations) + v1 = u0 * sin(x[1] / L) * cos(x[2] / L) * cos(x[3] / L) + v2 = -u0 * cos(x[1] / L) * sin(x[2] / L) * cos(x[3] / L) + v3 = 0 + p0 = (pressure(rho0, equations) + + rho0 * u0^2 / 16 * (cos(2 * x[1] / L) + cos(2 * x[2] / L)) * + (cos(2 * x[3] / L) + 2)) + rho = density(p0, equations) - return equilibrium_distribution(rho, v1, v2, v3, equations) + return equilibrium_distribution(rho, v1, v2, v3, equations) end initial_condition = initial_condition_taylor_green_vortex -solver = DGSEM(polydeg=3, surface_flux=flux_godunov) +solver = DGSEM(polydeg = 3, surface_flux = flux_godunov) -coordinates_min = (-pi*L, -pi*L, -pi*L) -coordinates_max = ( pi*L, pi*L, pi*L) +coordinates_min = (-pi * L, -pi * L, -pi * L) +coordinates_max = (pi * L, pi * L, pi * L) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=5, - n_cells_max=300_000,) - + initial_refinement_level = 5, + n_cells_max = 300_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. -tspan = (0.0, 20*equations.L/equations.u0) # Final time is `20` in non-dimensional time +tspan = (0.0, 20 * equations.L / equations.u0) # Final time is `20` in non-dimensional time ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 20 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - save_analysis=true, - extra_analysis_integrals=(Trixi.energy_kinetic_nondimensional,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true, + extra_analysis_integrals = (Trixi.energy_kinetic_nondimensional,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2macroscopic) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2macroscopic) -stepsize_callback = StepsizeCallback(cfl=0.3) +stepsize_callback = StepsizeCallback(cfl = 0.3) collision_callback = LBMCollisionCallback() @@ -69,12 +68,11 @@ callbacks = CallbackSet(summary_callback, stepsize_callback, collision_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks, - save_start=false, alias_u0=true); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks, + save_start = false, alias_u0 = true); summary_callback() # print the timer summary diff --git a/examples/tree_3d_dgsem/elixir_mhd_alfven_wave.jl b/examples/tree_3d_dgsem/elixir_mhd_alfven_wave.jl index 191982bf2d6..9aab5e58788 100644 --- a/examples/tree_3d_dgsem/elixir_mhd_alfven_wave.jl +++ b/examples/tree_3d_dgsem/elixir_mhd_alfven_wave.jl @@ -5,24 +5,23 @@ using Trixi ############################################################################### # semidiscretization of the compressible ideal GLM-MHD equations -equations = IdealGlmMhdEquations3D(5/3) +equations = IdealGlmMhdEquations3D(5 / 3) initial_condition = initial_condition_convergence_test volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) -solver = DGSEM(polydeg=3, surface_flux=(flux_lax_friedrichs, flux_nonconservative_powell), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, + surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-1.0, -1.0, -1.0) -coordinates_max = ( 1.0, 1.0, 1.0) +coordinates_max = (1.0, 1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=10_000) - + initial_refinement_level = 2, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -32,18 +31,18 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=10, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 10, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) cfl = 1.5 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -51,11 +50,10 @@ callbacks = CallbackSet(summary_callback, stepsize_callback, glm_speed_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_3d_dgsem/elixir_mhd_alfven_wave_mortar.jl b/examples/tree_3d_dgsem/elixir_mhd_alfven_wave_mortar.jl index e23f7ce5460..2fa22d535d7 100644 --- a/examples/tree_3d_dgsem/elixir_mhd_alfven_wave_mortar.jl +++ b/examples/tree_3d_dgsem/elixir_mhd_alfven_wave_mortar.jl @@ -5,24 +5,24 @@ using Trixi ############################################################################### # semidiscretization of the compressible ideal GLM-MHD equations -equations = IdealGlmMhdEquations3D(5/3) +equations = IdealGlmMhdEquations3D(5 / 3) initial_condition = initial_condition_convergence_test volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) -solver = DGSEM(polydeg=3, surface_flux=(flux_hll, flux_nonconservative_powell), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, + surface_flux = (flux_hlle, + flux_nonconservative_powell), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-1.0, -1.0, -1.0) -coordinates_max = ( 1.0, 1.0, 1.0) -refinement_patches = ( - (type="box", coordinates_min=(-0.5, -0.5, -0.5), - coordinates_max=( 0.5, 0.5, 0.5)), -) +coordinates_max = (1.0, 1.0, 1.0) +refinement_patches = ((type = "box", coordinates_min = (-0.5, -0.5, -0.5), + coordinates_max = (0.5, 0.5, 0.5)),) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - refinement_patches=refinement_patches, - n_cells_max=10_000) + initial_refinement_level = 2, + refinement_patches = refinement_patches, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -35,18 +35,18 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) cfl = 1.0 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -54,11 +54,10 @@ callbacks = CallbackSet(summary_callback, stepsize_callback, glm_speed_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_3d_dgsem/elixir_mhd_ec.jl b/examples/tree_3d_dgsem/elixir_mhd_ec.jl index 057ffcb031f..1f0088e82c9 100644 --- a/examples/tree_3d_dgsem/elixir_mhd_ec.jl +++ b/examples/tree_3d_dgsem/elixir_mhd_ec.jl @@ -10,19 +10,18 @@ equations = IdealGlmMhdEquations3D(1.4) initial_condition = initial_condition_weak_blast_wave volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) -solver = DGSEM(polydeg=3, surface_flux=(flux_hindenlang_gassner, flux_nonconservative_powell), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, + surface_flux = (flux_hindenlang_gassner, flux_nonconservative_powell), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-2.0, -2.0, -2.0) -coordinates_max = ( 2.0, 2.0, 2.0) +coordinates_max = (2.0, 2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=10_000) - + initial_refinement_level = 2, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -32,19 +31,19 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=10, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 10, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) cfl = 1.4 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, @@ -52,11 +51,10 @@ callbacks = CallbackSet(summary_callback, stepsize_callback, glm_speed_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_3d_dgsem/elixir_mhd_ec_shockcapturing.jl b/examples/tree_3d_dgsem/elixir_mhd_ec_shockcapturing.jl index 6b4f6e310ce..f8a72b6f452 100644 --- a/examples/tree_3d_dgsem/elixir_mhd_ec_shockcapturing.jl +++ b/examples/tree_3d_dgsem/elixir_mhd_ec_shockcapturing.jl @@ -10,25 +10,26 @@ equations = IdealGlmMhdEquations3D(1.4) initial_condition = initial_condition_weak_blast_wave surface_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) -volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) +volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) polydeg = 4 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) -solver = DGSEM(polydeg=polydeg, surface_flux=surface_flux, volume_integral=volume_integral) +solver = DGSEM(polydeg = polydeg, surface_flux = surface_flux, + volume_integral = volume_integral) coordinates_min = (-2.0, -2.0, -2.0) -coordinates_max = ( 2.0, 2.0, 2.0) +coordinates_max = (2.0, 2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=10_000) + initial_refinement_level = 3, + n_cells_max = 10_000) # create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -42,25 +43,24 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) cfl = 1.4 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, stepsize_callback, glm_speed_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_3d_dgsem/elixir_navierstokes_convergence.jl b/examples/tree_3d_dgsem/elixir_navierstokes_convergence.jl index ebb0137a1bb..3ada9503c6a 100644 --- a/examples/tree_3d_dgsem/elixir_navierstokes_convergence.jl +++ b/examples/tree_3d_dgsem/elixir_navierstokes_convergence.jl @@ -8,213 +8,215 @@ prandtl_number() = 0.72 mu() = 0.01 equations = CompressibleEulerEquations3D(1.4) -equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu=mu(), Prandtl=prandtl_number(), - gradient_variables=GradientVariablesPrimitive()) +equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu = mu(), + Prandtl = prandtl_number(), + gradient_variables = GradientVariablesPrimitive()) # Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux -solver = DGSEM(polydeg=3, surface_flux=flux_lax_friedrichs, - volume_integral=VolumeIntegralWeakForm()) +solver = DGSEM(polydeg = 3, surface_flux = flux_lax_friedrichs, + volume_integral = VolumeIntegralWeakForm()) coordinates_min = (-1.0, -1.0, -1.0) # minimum coordinates (min(x), min(y), min(z)) -coordinates_max = ( 1.0, 1.0, 1.0) # maximum coordinates (max(x), max(y), max(z)) +coordinates_max = (1.0, 1.0, 1.0) # maximum coordinates (max(x), max(y), max(z)) # Create a uniformly refined mesh with periodic boundaries mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - periodicity=(true, false, true), - n_cells_max=50_000) # set maximum capacity of tree data structure + initial_refinement_level = 3, + periodicity = (true, false, true), + n_cells_max = 50_000) # set maximum capacity of tree data structure # Note: the initial condition cannot be specialized to `CompressibleNavierStokesDiffusion3D` # since it is called by both the parabolic solver (which passes in `CompressibleNavierStokesDiffusion3D`) # and by the initial condition (which passes in `CompressibleEulerEquations3D`). # This convergence test setup was originally derived by Andrew Winters (@andrewwinters5000) function initial_condition_navier_stokes_convergence_test(x, t, equations) - # Constants. OBS! Must match those in `source_terms_navier_stokes_convergence_test` - c = 2.0 - A1 = 0.5 - A2 = 1.0 - A3 = 0.5 - - # Convenience values for trig. functions - pi_x = pi * x[1] - pi_y = pi * x[2] - pi_z = pi * x[3] - pi_t = pi * t - - rho = c + A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) - v1 = A2 * sin(pi_x) * log(x[2] + 2.0) * (1.0 - exp(-A3 * (x[2] - 1.0))) * sin(pi_z) * cos(pi_t) - v2 = v1 - v3 = v1 - p = rho^2 - - return prim2cons(SVector(rho, v1, v2, v3, p), equations) + # Constants. OBS! Must match those in `source_terms_navier_stokes_convergence_test` + c = 2.0 + A1 = 0.5 + A2 = 1.0 + A3 = 0.5 + + # Convenience values for trig. functions + pi_x = pi * x[1] + pi_y = pi * x[2] + pi_z = pi * x[3] + pi_t = pi * t + + rho = c + A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) + v1 = A2 * sin(pi_x) * log(x[2] + 2.0) * (1.0 - exp(-A3 * (x[2] - 1.0))) * sin(pi_z) * + cos(pi_t) + v2 = v1 + v3 = v1 + p = rho^2 + + return prim2cons(SVector(rho, v1, v2, v3, p), equations) end @inline function source_terms_navier_stokes_convergence_test(u, x, t, equations) - # TODO: parabolic - # we currently need to hardcode these parameters until we fix the "combined equation" issue - # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 - inv_gamma_minus_one = inv(equations.gamma - 1) - Pr = prandtl_number() - mu_ = mu() - - # Constants. OBS! Must match those in `initial_condition_navier_stokes_convergence_test` - c = 2.0 - A1 = 0.5 - A2 = 1.0 - A3 = 0.5 - - # Convenience values for trig. functions - pi_x = pi * x[1] - pi_y = pi * x[2] - pi_z = pi * x[3] - pi_t = pi * t - - # Define auxiliary functions for the strange function of the y variable - # to make expressions easier to read - g = log(x[2] + 2.0) * (1.0 - exp(-A3 * (x[2] - 1.0))) - g_y = ( A3 * log(x[2] + 2.0) * exp(-A3 * (x[2] - 1.0)) - + (1.0 - exp(-A3 * (x[2] - 1.0))) / (x[2] + 2.0) ) - g_yy = ( 2.0 * A3 * exp(-A3 * (x[2] - 1.0)) / (x[2] + 2.0) - - (1.0 - exp(-A3 * (x[2] - 1.0))) / ((x[2] + 2.0)^2) - - A3^2 * log(x[2] + 2.0) * exp(-A3 * (x[2] - 1.0)) ) - - # Density and its derivatives - rho = c + A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) - rho_t = -pi * A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * sin(pi_t) - rho_x = pi * A1 * cos(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) - rho_y = -pi * A1 * sin(pi_x) * sin(pi_y) * sin(pi_z) * cos(pi_t) - rho_z = pi * A1 * sin(pi_x) * cos(pi_y) * cos(pi_z) * cos(pi_t) - rho_xx = -pi^2 * (rho - c) - rho_yy = -pi^2 * (rho - c) - rho_zz = -pi^2 * (rho - c) - - # Velocities and their derivatives - # v1 terms - v1 = A2 * sin(pi_x) * g * sin(pi_z) * cos(pi_t) - v1_t = -pi * A2 * sin(pi_x) * g * sin(pi_z) * sin(pi_t) - v1_x = pi * A2 * cos(pi_x) * g * sin(pi_z) * cos(pi_t) - v1_y = A2 * sin(pi_x) * g_y * sin(pi_z) * cos(pi_t) - v1_z = pi * A2 * sin(pi_x) * g * cos(pi_z) * cos(pi_t) - v1_xx = -pi^2 * v1 - v1_yy = A2 * sin(pi_x) * g_yy * sin(pi_z) * cos(pi_t) - v1_zz = -pi^2 * v1 - v1_xy = pi * A2 * cos(pi_x) * g_y * sin(pi_z) * cos(pi_t) - v1_xz = pi^2 * A2 * cos(pi_x) * g * cos(pi_z) * cos(pi_t) - v1_yz = pi * A2 * sin(pi_x) * g_y * cos(pi_z) * cos(pi_t) - # v2 terms (simplifies from ansatz) - v2 = v1 - v2_t = v1_t - v2_x = v1_x - v2_y = v1_y - v2_z = v1_z - v2_xx = v1_xx - v2_yy = v1_yy - v2_zz = v1_zz - v2_xy = v1_xy - v2_yz = v1_yz - # v3 terms (simplifies from ansatz) - v3 = v1 - v3_t = v1_t - v3_x = v1_x - v3_y = v1_y - v3_z = v1_z - v3_xx = v1_xx - v3_yy = v1_yy - v3_zz = v1_zz - v3_xz = v1_xz - v3_yz = v1_yz - - # Pressure and its derivatives - p = rho^2 - p_t = 2.0 * rho * rho_t - p_x = 2.0 * rho * rho_x - p_y = 2.0 * rho * rho_y - p_z = 2.0 * rho * rho_z - - # Total energy and its derivatives; simiplifies from ansatz that v2 = v1 and v3 = v1 - E = p * inv_gamma_minus_one + 1.5 * rho * v1^2 - E_t = p_t * inv_gamma_minus_one + 1.5 * rho_t * v1^2 + 3.0 * rho * v1 * v1_t - E_x = p_x * inv_gamma_minus_one + 1.5 * rho_x * v1^2 + 3.0 * rho * v1 * v1_x - E_y = p_y * inv_gamma_minus_one + 1.5 * rho_y * v1^2 + 3.0 * rho * v1 * v1_y - E_z = p_z * inv_gamma_minus_one + 1.5 * rho_z * v1^2 + 3.0 * rho * v1 * v1_z - - # Divergence of Fick's law ∇⋅∇q = kappa ∇⋅∇T; simplifies because p = rho², so T = p/rho = rho - kappa = equations.gamma * inv_gamma_minus_one / Pr - q_xx = kappa * rho_xx # kappa T_xx - q_yy = kappa * rho_yy # kappa T_yy - q_zz = kappa * rho_zz # kappa T_zz - - # Stress tensor and its derivatives (exploit symmetry) - tau11 = 4.0 / 3.0 * v1_x - 2.0 / 3.0 * (v2_y + v3_z) - tau12 = v1_y + v2_x - tau13 = v1_z + v3_x - tau22 = 4.0 / 3.0 * v2_y - 2.0 / 3.0 * (v1_x + v3_z) - tau23 = v2_z + v3_y - tau33 = 4.0 / 3.0 * v3_z - 2.0 / 3.0 * (v1_x + v2_y) - - tau11_x = 4.0 / 3.0 * v1_xx - 2.0 / 3.0 * (v2_xy + v3_xz) - tau12_x = v1_xy + v2_xx - tau13_x = v1_xz + v3_xx - - tau12_y = v1_yy + v2_xy - tau22_y = 4.0 / 3.0 * v2_yy - 2.0 / 3.0 * (v1_xy + v3_yz) - tau23_y = v2_yz + v3_yy - - tau13_z = v1_zz + v3_xz - tau23_z = v2_zz + v3_yz - tau33_z = 4.0 / 3.0 * v3_zz - 2.0 / 3.0 * (v1_xz + v2_yz) - - # Compute the source terms - # Density equation - du1 = ( rho_t + rho_x * v1 + rho * v1_x - + rho_y * v2 + rho * v2_y - + rho_z * v3 + rho * v3_z ) - # x-momentum equation - du2 = ( rho_t * v1 + rho * v1_t + p_x + rho_x * v1^2 - + 2.0 * rho * v1 * v1_x - + rho_y * v1 * v2 - + rho * v1_y * v2 - + rho * v1 * v2_y - + rho_z * v1 * v3 - + rho * v1_z * v3 - + rho * v1 * v3_z - - mu_ * (tau11_x + tau12_y + tau13_z) ) - # y-momentum equation - du3 = ( rho_t * v2 + rho * v2_t + p_y + rho_x * v1 * v2 - + rho * v1_x * v2 - + rho * v1 * v2_x - + rho_y * v2^2 - + 2.0 * rho * v2 * v2_y - + rho_z * v2 * v3 - + rho * v2_z * v3 - + rho * v2 * v3_z - - mu_ * (tau12_x + tau22_y + tau23_z) ) - # z-momentum equation - du4 = ( rho_t * v3 + rho * v3_t + p_z + rho_x * v1 * v3 - + rho * v1_x * v3 - + rho * v1 * v3_x - + rho_y * v2 * v3 - + rho * v2_y * v3 - + rho * v2 * v3_y - + rho_z * v3^2 - + 2.0 * rho * v3 * v3_z - - mu_ * (tau13_x + tau23_y + tau33_z) ) - # Total energy equation - du5 = ( E_t + v1_x * (E + p) + v1 * (E_x + p_x) - + v2_y * (E + p) + v2 * (E_y + p_y) - + v3_z * (E + p) + v3 * (E_z + p_z) - # stress tensor and temperature gradient from x-direction - - mu_ * ( q_xx + v1_x * tau11 + v2_x * tau12 + v3_x * tau13 - + v1 * tau11_x + v2 * tau12_x + v3 * tau13_x) - # stress tensor and temperature gradient terms from y-direction - - mu_ * ( q_yy + v1_y * tau12 + v2_y * tau22 + v3_y * tau23 - + v1 * tau12_y + v2 * tau22_y + v3 * tau23_y) - # stress tensor and temperature gradient terms from z-direction - - mu_ * ( q_zz + v1_z * tau13 + v2_z * tau23 + v3_z * tau33 - + v1 * tau13_z + v2 * tau23_z + v3 * tau33_z) ) - - return SVector(du1, du2, du3, du4, du5) + # TODO: parabolic + # we currently need to hardcode these parameters until we fix the "combined equation" issue + # see also https://github.com/trixi-framework/Trixi.jl/pull/1160 + inv_gamma_minus_one = inv(equations.gamma - 1) + Pr = prandtl_number() + mu_ = mu() + + # Constants. OBS! Must match those in `initial_condition_navier_stokes_convergence_test` + c = 2.0 + A1 = 0.5 + A2 = 1.0 + A3 = 0.5 + + # Convenience values for trig. functions + pi_x = pi * x[1] + pi_y = pi * x[2] + pi_z = pi * x[3] + pi_t = pi * t + + # Define auxiliary functions for the strange function of the y variable + # to make expressions easier to read + g = log(x[2] + 2.0) * (1.0 - exp(-A3 * (x[2] - 1.0))) + g_y = (A3 * log(x[2] + 2.0) * exp(-A3 * (x[2] - 1.0)) + + (1.0 - exp(-A3 * (x[2] - 1.0))) / (x[2] + 2.0)) + g_yy = (2.0 * A3 * exp(-A3 * (x[2] - 1.0)) / (x[2] + 2.0) - + (1.0 - exp(-A3 * (x[2] - 1.0))) / ((x[2] + 2.0)^2) - + A3^2 * log(x[2] + 2.0) * exp(-A3 * (x[2] - 1.0))) + + # Density and its derivatives + rho = c + A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) + rho_t = -pi * A1 * sin(pi_x) * cos(pi_y) * sin(pi_z) * sin(pi_t) + rho_x = pi * A1 * cos(pi_x) * cos(pi_y) * sin(pi_z) * cos(pi_t) + rho_y = -pi * A1 * sin(pi_x) * sin(pi_y) * sin(pi_z) * cos(pi_t) + rho_z = pi * A1 * sin(pi_x) * cos(pi_y) * cos(pi_z) * cos(pi_t) + rho_xx = -pi^2 * (rho - c) + rho_yy = -pi^2 * (rho - c) + rho_zz = -pi^2 * (rho - c) + + # Velocities and their derivatives + # v1 terms + v1 = A2 * sin(pi_x) * g * sin(pi_z) * cos(pi_t) + v1_t = -pi * A2 * sin(pi_x) * g * sin(pi_z) * sin(pi_t) + v1_x = pi * A2 * cos(pi_x) * g * sin(pi_z) * cos(pi_t) + v1_y = A2 * sin(pi_x) * g_y * sin(pi_z) * cos(pi_t) + v1_z = pi * A2 * sin(pi_x) * g * cos(pi_z) * cos(pi_t) + v1_xx = -pi^2 * v1 + v1_yy = A2 * sin(pi_x) * g_yy * sin(pi_z) * cos(pi_t) + v1_zz = -pi^2 * v1 + v1_xy = pi * A2 * cos(pi_x) * g_y * sin(pi_z) * cos(pi_t) + v1_xz = pi^2 * A2 * cos(pi_x) * g * cos(pi_z) * cos(pi_t) + v1_yz = pi * A2 * sin(pi_x) * g_y * cos(pi_z) * cos(pi_t) + # v2 terms (simplifies from ansatz) + v2 = v1 + v2_t = v1_t + v2_x = v1_x + v2_y = v1_y + v2_z = v1_z + v2_xx = v1_xx + v2_yy = v1_yy + v2_zz = v1_zz + v2_xy = v1_xy + v2_yz = v1_yz + # v3 terms (simplifies from ansatz) + v3 = v1 + v3_t = v1_t + v3_x = v1_x + v3_y = v1_y + v3_z = v1_z + v3_xx = v1_xx + v3_yy = v1_yy + v3_zz = v1_zz + v3_xz = v1_xz + v3_yz = v1_yz + + # Pressure and its derivatives + p = rho^2 + p_t = 2.0 * rho * rho_t + p_x = 2.0 * rho * rho_x + p_y = 2.0 * rho * rho_y + p_z = 2.0 * rho * rho_z + + # Total energy and its derivatives; simiplifies from ansatz that v2 = v1 and v3 = v1 + E = p * inv_gamma_minus_one + 1.5 * rho * v1^2 + E_t = p_t * inv_gamma_minus_one + 1.5 * rho_t * v1^2 + 3.0 * rho * v1 * v1_t + E_x = p_x * inv_gamma_minus_one + 1.5 * rho_x * v1^2 + 3.0 * rho * v1 * v1_x + E_y = p_y * inv_gamma_minus_one + 1.5 * rho_y * v1^2 + 3.0 * rho * v1 * v1_y + E_z = p_z * inv_gamma_minus_one + 1.5 * rho_z * v1^2 + 3.0 * rho * v1 * v1_z + + # Divergence of Fick's law ∇⋅∇q = kappa ∇⋅∇T; simplifies because p = rho², so T = p/rho = rho + kappa = equations.gamma * inv_gamma_minus_one / Pr + q_xx = kappa * rho_xx # kappa T_xx + q_yy = kappa * rho_yy # kappa T_yy + q_zz = kappa * rho_zz # kappa T_zz + + # Stress tensor and its derivatives (exploit symmetry) + tau11 = 4.0 / 3.0 * v1_x - 2.0 / 3.0 * (v2_y + v3_z) + tau12 = v1_y + v2_x + tau13 = v1_z + v3_x + tau22 = 4.0 / 3.0 * v2_y - 2.0 / 3.0 * (v1_x + v3_z) + tau23 = v2_z + v3_y + tau33 = 4.0 / 3.0 * v3_z - 2.0 / 3.0 * (v1_x + v2_y) + + tau11_x = 4.0 / 3.0 * v1_xx - 2.0 / 3.0 * (v2_xy + v3_xz) + tau12_x = v1_xy + v2_xx + tau13_x = v1_xz + v3_xx + + tau12_y = v1_yy + v2_xy + tau22_y = 4.0 / 3.0 * v2_yy - 2.0 / 3.0 * (v1_xy + v3_yz) + tau23_y = v2_yz + v3_yy + + tau13_z = v1_zz + v3_xz + tau23_z = v2_zz + v3_yz + tau33_z = 4.0 / 3.0 * v3_zz - 2.0 / 3.0 * (v1_xz + v2_yz) + + # Compute the source terms + # Density equation + du1 = (rho_t + rho_x * v1 + rho * v1_x + + rho_y * v2 + rho * v2_y + + rho_z * v3 + rho * v3_z) + # x-momentum equation + du2 = (rho_t * v1 + rho * v1_t + p_x + rho_x * v1^2 + + 2.0 * rho * v1 * v1_x + + rho_y * v1 * v2 + + rho * v1_y * v2 + + rho * v1 * v2_y + + rho_z * v1 * v3 + + rho * v1_z * v3 + + rho * v1 * v3_z - + mu_ * (tau11_x + tau12_y + tau13_z)) + # y-momentum equation + du3 = (rho_t * v2 + rho * v2_t + p_y + rho_x * v1 * v2 + + rho * v1_x * v2 + + rho * v1 * v2_x + + rho_y * v2^2 + + 2.0 * rho * v2 * v2_y + + rho_z * v2 * v3 + + rho * v2_z * v3 + + rho * v2 * v3_z - + mu_ * (tau12_x + tau22_y + tau23_z)) + # z-momentum equation + du4 = (rho_t * v3 + rho * v3_t + p_z + rho_x * v1 * v3 + + rho * v1_x * v3 + + rho * v1 * v3_x + + rho_y * v2 * v3 + + rho * v2_y * v3 + + rho * v2 * v3_y + + rho_z * v3^2 + + 2.0 * rho * v3 * v3_z - + mu_ * (tau13_x + tau23_y + tau33_z)) + # Total energy equation + du5 = (E_t + v1_x * (E + p) + v1 * (E_x + p_x) + + v2_y * (E + p) + v2 * (E_y + p_y) + + v3_z * (E + p) + v3 * (E_z + p_z) - + # stress tensor and temperature gradient from x-direction + mu_ * (q_xx + v1_x * tau11 + v2_x * tau12 + v3_x * tau13 + + v1 * tau11_x + v2 * tau12_x + v3 * tau13_x) - + # stress tensor and temperature gradient terms from y-direction + mu_ * (q_yy + v1_y * tau12 + v2_y * tau22 + v3_y * tau23 + + v1 * tau12_y + v2 * tau22_y + v3 * tau23_y) - + # stress tensor and temperature gradient terms from z-direction + mu_ * (q_zz + v1_z * tau13 + v2_z * tau23 + v3_z * tau33 + + v1 * tau13_z + v2 * tau23_z + v3 * tau33_z)) + + return SVector(du1, du2, du3, du4, du5) end initial_condition = initial_condition_navier_stokes_convergence_test @@ -222,30 +224,33 @@ initial_condition = initial_condition_navier_stokes_convergence_test # BC types velocity_bc_top_bottom = NoSlip() do x, t, equations u = initial_condition_navier_stokes_convergence_test(x, t, equations) - return SVector(u[2], u[3], u[4]) + return SVector(u[2], u[3], u[4]) end heat_bc_top_bottom = Adiabatic((x, t, equations) -> 0.0) -boundary_condition_top_bottom = BoundaryConditionNavierStokesWall(velocity_bc_top_bottom, heat_bc_top_bottom) +boundary_condition_top_bottom = BoundaryConditionNavierStokesWall(velocity_bc_top_bottom, + heat_bc_top_bottom) # define inviscid boundary conditions boundary_conditions = (; x_neg = boundary_condition_periodic, - x_pos = boundary_condition_periodic, - y_neg = boundary_condition_slip_wall, - y_pos = boundary_condition_slip_wall, - z_neg = boundary_condition_periodic, - z_pos = boundary_condition_periodic) + x_pos = boundary_condition_periodic, + y_neg = boundary_condition_slip_wall, + y_pos = boundary_condition_slip_wall, + z_neg = boundary_condition_periodic, + z_pos = boundary_condition_periodic) # define viscous boundary conditions boundary_conditions_parabolic = (; x_neg = boundary_condition_periodic, - x_pos = boundary_condition_periodic, - y_neg = boundary_condition_top_bottom, - y_pos = boundary_condition_top_bottom, - z_neg = boundary_condition_periodic, - z_pos = boundary_condition_periodic) - -semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver; - boundary_conditions=(boundary_conditions, boundary_conditions_parabolic), - source_terms=source_terms_navier_stokes_convergence_test) + x_pos = boundary_condition_periodic, + y_neg = boundary_condition_top_bottom, + y_pos = boundary_condition_top_bottom, + z_neg = boundary_condition_periodic, + z_pos = boundary_condition_periodic) + +semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, solver; + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic), + source_terms = source_terms_navier_stokes_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -255,16 +260,15 @@ tspan = (0.0, 1.0) ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() -alive_callback = AliveCallback(alive_interval=10) +alive_callback = AliveCallback(alive_interval = 10) analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) ############################################################################### # run the simulation time_int_tol = 1e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, dt = 1e-5, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, dt = 1e-5, + ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary - diff --git a/examples/tree_3d_dgsem/elixir_navierstokes_taylor_green_vortex.jl b/examples/tree_3d_dgsem/elixir_navierstokes_taylor_green_vortex.jl index 5556831a59d..65bd9aa133d 100644 --- a/examples/tree_3d_dgsem/elixir_navierstokes_taylor_green_vortex.jl +++ b/examples/tree_3d_dgsem/elixir_navierstokes_taylor_green_vortex.jl @@ -10,8 +10,8 @@ prandtl_number() = 0.72 mu() = 6.25e-4 # equivalent to Re = 1600 equations = CompressibleEulerEquations3D(1.4) -equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu=mu(), - Prandtl=prandtl_number()) +equations_parabolic = CompressibleNavierStokesDiffusion3D(equations, mu = mu(), + Prandtl = prandtl_number()) """ initial_condition_taylor_green_vortex(x, t, equations::CompressibleEulerEquations3D) @@ -22,31 +22,34 @@ The classical viscous Taylor-Green vortex, as found for instance in Simulation of the Compressible Taylor Green Vortex using High-Order Flux Reconstruction Schemes [DOI: 10.2514/6.2014-3210](https://doi.org/10.2514/6.2014-3210) """ -function initial_condition_taylor_green_vortex(x, t, equations::CompressibleEulerEquations3D) - A = 1.0 # magnitude of speed - Ms = 0.1 # maximum Mach number - - rho = 1.0 - v1 = A * sin(x[1]) * cos(x[2]) * cos(x[3]) - v2 = -A * cos(x[1]) * sin(x[2]) * cos(x[3]) - v3 = 0.0 - p = (A / Ms)^2 * rho / equations.gamma # scaling to get Ms - p = p + 1.0/16.0 * A^2 * rho * (cos(2*x[1])*cos(2*x[3]) + 2*cos(2*x[2]) + 2*cos(2*x[1]) + cos(2*x[2])*cos(2*x[3])) - - return prim2cons(SVector(rho, v1, v2, v3, p), equations) +function initial_condition_taylor_green_vortex(x, t, + equations::CompressibleEulerEquations3D) + A = 1.0 # magnitude of speed + Ms = 0.1 # maximum Mach number + + rho = 1.0 + v1 = A * sin(x[1]) * cos(x[2]) * cos(x[3]) + v2 = -A * cos(x[1]) * sin(x[2]) * cos(x[3]) + v3 = 0.0 + p = (A / Ms)^2 * rho / equations.gamma # scaling to get Ms + p = p + + 1.0 / 16.0 * A^2 * rho * + (cos(2 * x[1]) * cos(2 * x[3]) + 2 * cos(2 * x[2]) + 2 * cos(2 * x[1]) + + cos(2 * x[2]) * cos(2 * x[3])) + + return prim2cons(SVector(rho, v1, v2, v3, p), equations) end initial_condition = initial_condition_taylor_green_vortex volume_flux = flux_ranocha -solver = DGSEM(polydeg=3, surface_flux=flux_hllc, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 3, surface_flux = flux_hllc, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) coordinates_min = (-1.0, -1.0, -1.0) .* pi -coordinates_max = ( 1.0, 1.0, 1.0) .* pi +coordinates_max = (1.0, 1.0, 1.0) .* pi mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=3, - n_cells_max=100_000) - + initial_refinement_level = 3, + n_cells_max = 100_000) semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver) @@ -60,12 +63,13 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 50 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=true, - extra_analysis_integrals=(energy_kinetic, - energy_internal, - enstrophy)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true, + extra_analysis_integrals = (energy_kinetic, + energy_internal, + enstrophy)) -alive_callback = AliveCallback(analysis_interval=analysis_interval,) +alive_callback = AliveCallback(analysis_interval = analysis_interval) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -75,6 +79,6 @@ callbacks = CallbackSet(summary_callback, # run the simulation time_int_tol = 1e-8 -sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary diff --git a/examples/tree_3d_fdsbp/elixir_advection_extended.jl b/examples/tree_3d_fdsbp/elixir_advection_extended.jl index 241e0698649..22085a63510 100644 --- a/examples/tree_3d_fdsbp/elixir_advection_extended.jl +++ b/examples/tree_3d_fdsbp/elixir_advection_extended.jl @@ -13,22 +13,21 @@ equations = LinearScalarAdvectionEquation3D(advection_velocity) initial_condition = initial_condition_convergence_test D_SBP = derivative_operator(SummationByPartsOperators.MattssonNordström2004(), - derivative_order=1, accuracy_order=4, - xmin=0.0, xmax=1.0, N=10) + derivative_order = 1, accuracy_order = 4, + xmin = 0.0, xmax = 1.0, N = 10) solver = FDSBP(D_SBP, - surface_integral=SurfaceIntegralStrongForm(flux_lax_friedrichs), - volume_integral=VolumeIntegralStrongForm()) + surface_integral = SurfaceIntegralStrongForm(flux_lax_friedrichs), + volume_integral = VolumeIntegralStrongForm()) coordinates_min = (-1.0, -1.0, -1.0) -coordinates_max = ( 1.0, 1.0, 1.0) +coordinates_max = (1.0, 1.0, 1.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=1, - n_cells_max=30_000, - periodicity=true) + initial_refinement_level = 1, + n_cells_max = 30_000, + periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -38,19 +37,18 @@ ode = semidiscretize(semi, tspan); summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(energy_total,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (energy_total,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) - ############################################################################### # run the simulation -sol = solve(ode, RDPK3SpFSAL49(); abstol=1.0e-9, reltol=1.0e-9, - ode_default_options()..., callback=callbacks) +sol = solve(ode, RDPK3SpFSAL49(); abstol = 1.0e-9, reltol = 1.0e-9, + ode_default_options()..., callback = callbacks) summary_callback() diff --git a/examples/tree_3d_fdsbp/elixir_euler_convergence.jl b/examples/tree_3d_fdsbp/elixir_euler_convergence.jl index 6aafa1b5cc1..aa5b231ee13 100644 --- a/examples/tree_3d_fdsbp/elixir_euler_convergence.jl +++ b/examples/tree_3d_fdsbp/elixir_euler_convergence.jl @@ -11,24 +11,23 @@ equations = CompressibleEulerEquations3D(1.4) initial_condition = initial_condition_convergence_test D_upw = upwind_operators(SummationByPartsOperators.Mattsson2017, - derivative_order=1, - accuracy_order=4, - xmin=-1.0, xmax=1.0, - N=16) + derivative_order = 1, + accuracy_order = 4, + xmin = -1.0, xmax = 1.0, + N = 16) flux_splitting = splitting_steger_warming solver = FDSBP(D_upw, - surface_integral=SurfaceIntegralUpwind(flux_splitting), - volume_integral=VolumeIntegralUpwind(flux_splitting)) + surface_integral = SurfaceIntegralUpwind(flux_splitting), + volume_integral = VolumeIntegralUpwind(flux_splitting)) coordinates_min = (0.0, 0.0, 0.0) coordinates_max = (2.0, 2.0, 2.0) mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=10_000) + initial_refinement_level = 2, + n_cells_max = 10_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) - + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -39,27 +38,26 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) -stepsize_callback = StepsizeCallback(cfl=1.1) +stepsize_callback = StepsizeCallback(cfl = 1.1) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/tree_3d_fdsbp/elixir_euler_taylor_green_vortex.jl b/examples/tree_3d_fdsbp/elixir_euler_taylor_green_vortex.jl index d2495cff5cd..0354200ae42 100644 --- a/examples/tree_3d_fdsbp/elixir_euler_taylor_green_vortex.jl +++ b/examples/tree_3d_fdsbp/elixir_euler_taylor_green_vortex.jl @@ -14,40 +14,43 @@ equations = CompressibleEulerEquations3D(1.4) The classical inviscid Taylor-Green vortex. """ -function initial_condition_taylor_green_vortex(x, t, equations::CompressibleEulerEquations3D) - A = 1.0 # magnitude of speed - Ms = 0.1 # maximum Mach number - - rho = 1.0 - v1 = A * sin(x[1]) * cos(x[2]) * cos(x[3]) - v2 = -A * cos(x[1]) * sin(x[2]) * cos(x[3]) - v3 = 0.0 - p = (A / Ms)^2 * rho / equations.gamma # scaling to get Ms - p = p + 1.0/16.0 * A^2 * rho * (cos(2*x[1])*cos(2*x[3]) + 2*cos(2*x[2]) + 2*cos(2*x[1]) + cos(2*x[2])*cos(2*x[3])) - - return prim2cons(SVector(rho, v1, v2, v3, p), equations) +function initial_condition_taylor_green_vortex(x, t, + equations::CompressibleEulerEquations3D) + A = 1.0 # magnitude of speed + Ms = 0.1 # maximum Mach number + + rho = 1.0 + v1 = A * sin(x[1]) * cos(x[2]) * cos(x[3]) + v2 = -A * cos(x[1]) * sin(x[2]) * cos(x[3]) + v3 = 0.0 + p = (A / Ms)^2 * rho / equations.gamma # scaling to get Ms + p = p + + 1.0 / 16.0 * A^2 * rho * + (cos(2 * x[1]) * cos(2 * x[3]) + 2 * cos(2 * x[2]) + 2 * cos(2 * x[1]) + + cos(2 * x[2]) * cos(2 * x[3])) + + return prim2cons(SVector(rho, v1, v2, v3, p), equations) end initial_condition = initial_condition_taylor_green_vortex D_upw = upwind_operators(SummationByPartsOperators.Mattsson2017, - derivative_order=1, - accuracy_order=4, - xmin=-1.0, xmax=1.0, - N=16) + derivative_order = 1, + accuracy_order = 4, + xmin = -1.0, xmax = 1.0, + N = 16) flux_splitting = splitting_steger_warming solver = FDSBP(D_upw, - surface_integral=SurfaceIntegralUpwind(flux_splitting), - volume_integral=VolumeIntegralUpwind(flux_splitting)) + surface_integral = SurfaceIntegralUpwind(flux_splitting), + volume_integral = VolumeIntegralUpwind(flux_splitting)) coordinates_min = (-1.0, -1.0, -1.0) .* pi -coordinates_max = ( 1.0, 1.0, 1.0) .* pi +coordinates_max = (1.0, 1.0, 1.0) .* pi mesh = TreeMesh(coordinates_min, coordinates_max, - initial_refinement_level=2, - n_cells_max=100_000) + initial_refinement_level = 2, + n_cells_max = 100_000) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) - ############################################################################### # ODE solvers, callbacks etc. @@ -57,28 +60,27 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - save_analysis=true, - extra_analysis_integrals=(energy_total, - energy_kinetic, - energy_internal,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true, + extra_analysis_integrals = (energy_total, + energy_kinetic, + energy_internal)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) - ############################################################################### # run the simulation -sol = solve(ode, SSPRK43(); abstol=1.0e-6, reltol=1.0e-6, - ode_default_options()..., callback=callbacks) +sol = solve(ode, SSPRK43(); abstol = 1.0e-6, reltol = 1.0e-6, + ode_default_options()..., callback = callbacks) summary_callback() # print the timer summary diff --git a/examples/unstructured_2d_dgsem/elixir_acoustics_gauss_wall.jl b/examples/unstructured_2d_dgsem/elixir_acoustics_gauss_wall.jl index 2f8228dffb8..8f8e867dca8 100644 --- a/examples/unstructured_2d_dgsem/elixir_acoustics_gauss_wall.jl +++ b/examples/unstructured_2d_dgsem/elixir_acoustics_gauss_wall.jl @@ -6,16 +6,18 @@ using Trixi ############################################################################### # semidiscretization of the acoustic perturbation equations -equations = AcousticPerturbationEquations2D(v_mean_global=(0.0, -0.5), c_mean_global=1.0, - rho_mean_global=1.0) +equations = AcousticPerturbationEquations2D(v_mean_global = (0.0, -0.5), + c_mean_global = 1.0, + rho_mean_global = 1.0) # Create DG solver with polynomial degree = 4 and (local) Lax-Friedrichs/Rusanov flux -solver = DGSEM(polydeg=4, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 4, surface_flux = flux_lax_friedrichs) # Create unstructured quadrilateral mesh from a file default_mesh_file = joinpath(@__DIR__, "mesh_five_circles_in_circle.mesh") -isfile(default_mesh_file) || download("https://gist.githubusercontent.com/andrewwinters5000/3c79baad6b4d73bb26ec6420b5d16f45/raw/22aefc4ec2107cf0bffc40e81dfbc52240c625b1/mesh_five_circles_in_circle.mesh", - default_mesh_file) +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/3c79baad6b4d73bb26ec6420b5d16f45/raw/22aefc4ec2107cf0bffc40e81dfbc52240c625b1/mesh_five_circles_in_circle.mesh", + default_mesh_file) mesh_file = default_mesh_file mesh = UnstructuredMesh2D(mesh_file) @@ -27,27 +29,26 @@ A Gaussian pulse, used in the `gauss_wall` example elixir in combination with [`boundary_condition_wall`](@ref). Uses the global mean values from `equations`. """ function initial_condition_gauss_wall(x, t, equations::AcousticPerturbationEquations2D) - v1_prime = 0.0 - v2_prime = 0.0 - p_prime = exp(-log(2) * (x[1]^2 + (x[2] - 25)^2) / 25) + v1_prime = 0.0 + v2_prime = 0.0 + p_prime = exp(-log(2) * (x[1]^2 + (x[2] - 25)^2) / 25) - prim = SVector(v1_prime, v2_prime, p_prime, global_mean_vars(equations)...) + prim = SVector(v1_prime, v2_prime, p_prime, global_mean_vars(equations)...) - return prim2cons(prim, equations) + return prim2cons(prim, equations) end initial_condition = initial_condition_gauss_wall -boundary_conditions = Dict( :OuterCircle => boundary_condition_slip_wall, - :InnerCircle1 => boundary_condition_slip_wall, - :InnerCircle2 => boundary_condition_slip_wall, - :InnerCircle3 => boundary_condition_slip_wall, - :InnerCircle4 => boundary_condition_slip_wall, - :InnerCircle5 => boundary_condition_slip_wall ) +boundary_conditions = Dict(:OuterCircle => boundary_condition_slip_wall, + :InnerCircle1 => boundary_condition_slip_wall, + :InnerCircle2 => boundary_condition_slip_wall, + :InnerCircle3 => boundary_condition_slip_wall, + :InnerCircle4 => boundary_condition_slip_wall, + :InnerCircle5 => boundary_condition_slip_wall) # A semidiscretization collects data structures and functions for the spatial discretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) - + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -61,10 +62,10 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=50, solution_variables=cons2state) +save_solution = SaveSolutionCallback(interval = 50, solution_variables = cons2state) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver callbacks = CallbackSet(summary_callback, analysis_callback, save_solution) @@ -73,7 +74,7 @@ callbacks = CallbackSet(summary_callback, analysis_callback, save_solution) # run the simulation # use a Runge-Kutta method with automatic (error based) time step size control -sol = solve(ode, RDPK3SpFSAL49(); abstol=1.0e-6, reltol=1.0e-6, - ode_default_options()..., callback=callbacks); +sol = solve(ode, RDPK3SpFSAL49(); abstol = 1.0e-6, reltol = 1.0e-6, + ode_default_options()..., callback = callbacks); # Print the timer summary summary_callback() diff --git a/examples/unstructured_2d_dgsem/elixir_advection_basic.jl b/examples/unstructured_2d_dgsem/elixir_advection_basic.jl index 274978d48b0..afef6c2c38f 100644 --- a/examples/unstructured_2d_dgsem/elixir_advection_basic.jl +++ b/examples/unstructured_2d_dgsem/elixir_advection_basic.jl @@ -12,22 +12,24 @@ equations = LinearScalarAdvectionEquation2D(advection_velocity) ############################################################################### # Get the DG approximation space -solver = DGSEM(polydeg=6, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 6, surface_flux = flux_lax_friedrichs) ############################################################################### # Get the curved quad mesh from a file (downloads the file if not available locally) default_mesh_file = joinpath(@__DIR__, "mesh_periodic_square_with_twist.mesh") -isfile(default_mesh_file) || download("https://gist.githubusercontent.com/andrewwinters5000/12ce661d7c354c3d94c74b964b0f1c96/raw/8275b9a60c6e7ebbdea5fc4b4f091c47af3d5273/mesh_periodic_square_with_twist.mesh", - default_mesh_file) +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/12ce661d7c354c3d94c74b964b0f1c96/raw/8275b9a60c6e7ebbdea5fc4b4f091c47af3d5273/mesh_periodic_square_with_twist.mesh", + default_mesh_file) mesh_file = default_mesh_file -mesh = UnstructuredMesh2D(mesh_file, periodicity=true) +mesh = UnstructuredMesh2D(mesh_file, periodicity = true) ############################################################################### # create the semi discretization object -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, solver) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, + solver) ############################################################################### # ODE solvers, callbacks etc. @@ -40,22 +42,23 @@ ode = semidiscretize(semi, (0.0, 1.0)); summary_callback = SummaryCallback() # The AnalysisCallback allows to analyse the solution in regular intervals and prints the results -analysis_callback = AnalysisCallback(semi, interval=100) +analysis_callback = AnalysisCallback(semi, interval = 100) # The SaveSolutionCallback allows to save the solution to a file in regular intervals -save_solution = SaveSolutionCallback(interval=100, - solution_variables=cons2prim) +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) # The StepsizeCallback handles the re-calculation of the maximum Δt after each time step -stepsize_callback = StepsizeCallback(cfl=1.6) +stepsize_callback = StepsizeCallback(cfl = 1.6) # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver -callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, stepsize_callback) +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/unstructured_2d_dgsem/elixir_euler_basic.jl b/examples/unstructured_2d_dgsem/elixir_euler_basic.jl index 9fbea47a9d5..cd6a1995757 100644 --- a/examples/unstructured_2d_dgsem/elixir_euler_basic.jl +++ b/examples/unstructured_2d_dgsem/elixir_euler_basic.jl @@ -12,23 +12,24 @@ initial_condition = initial_condition_convergence_test source_terms = source_terms_convergence_test boundary_condition_convergence_test = BoundaryConditionDirichlet(initial_condition) -boundary_conditions = Dict( :Slant => boundary_condition_convergence_test, - :Bezier => boundary_condition_convergence_test, - :Right => boundary_condition_convergence_test, - :Bottom => boundary_condition_convergence_test, - :Top => boundary_condition_convergence_test ) +boundary_conditions = Dict(:Slant => boundary_condition_convergence_test, + :Bezier => boundary_condition_convergence_test, + :Right => boundary_condition_convergence_test, + :Bottom => boundary_condition_convergence_test, + :Top => boundary_condition_convergence_test) ############################################################################### # Get the DG approximation space -solver = DGSEM(polydeg=8, surface_flux=flux_lax_friedrichs) +solver = DGSEM(polydeg = 8, surface_flux = flux_lax_friedrichs) ############################################################################### # Get the curved quad mesh from a file (downloads the file if not available locally) default_mesh_file = joinpath(@__DIR__, "mesh_trixi_unstructured_mesh_docs.mesh") -isfile(default_mesh_file) || download("https://gist.githubusercontent.com/andrewwinters5000/52056f1487853fab63b7f4ed7f171c80/raw/9d573387dfdbb8bce2a55db7246f4207663ac07f/mesh_trixi_unstructured_mesh_docs.mesh", - default_mesh_file) +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/52056f1487853fab63b7f4ed7f171c80/raw/9d573387dfdbb8bce2a55db7246f4207663ac07f/mesh_trixi_unstructured_mesh_docs.mesh", + default_mesh_file) mesh_file = default_mesh_file mesh = UnstructuredMesh2D(mesh_file) @@ -37,8 +38,8 @@ mesh = UnstructuredMesh2D(mesh_file) # create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms, - boundary_conditions=boundary_conditions) + source_terms = source_terms, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -49,18 +50,18 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_restart = SaveRestartCallback(interval=50, - save_final_restart=true) +save_restart = SaveRestartCallback(interval = 50, + save_final_restart = true) -save_solution = SaveSolutionCallback(interval=10, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 10, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=0.9) +stepsize_callback = StepsizeCallback(cfl = 0.9) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -72,7 +73,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/unstructured_2d_dgsem/elixir_euler_ec.jl b/examples/unstructured_2d_dgsem/elixir_euler_ec.jl index 2725142fd17..0f53aa62a18 100644 --- a/examples/unstructured_2d_dgsem/elixir_euler_ec.jl +++ b/examples/unstructured_2d_dgsem/elixir_euler_ec.jl @@ -6,7 +6,7 @@ using Trixi ############################################################################### # semidiscretization of the compressible Euler equations -equations = CompressibleEulerEquations2D(5/3) +equations = CompressibleEulerEquations2D(5 / 3) initial_condition = initial_condition_weak_blast_wave @@ -14,18 +14,19 @@ initial_condition = initial_condition_weak_blast_wave # Get the DG approximation space volume_flux = flux_ranocha -solver = DGSEM(polydeg=6, surface_flux=flux_ranocha, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 6, surface_flux = flux_ranocha, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### # Get the curved quad mesh from a file default_mesh_file = joinpath(@__DIR__, "mesh_periodic_square_with_twist.mesh") -isfile(default_mesh_file) || download("https://gist.githubusercontent.com/andrewwinters5000/12ce661d7c354c3d94c74b964b0f1c96/raw/8275b9a60c6e7ebbdea5fc4b4f091c47af3d5273/mesh_periodic_square_with_twist.mesh", - default_mesh_file) +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/12ce661d7c354c3d94c74b964b0f1c96/raw/8275b9a60c6e7ebbdea5fc4b4f091c47af3d5273/mesh_periodic_square_with_twist.mesh", + default_mesh_file) mesh_file = default_mesh_file -mesh = UnstructuredMesh2D(mesh_file, periodicity=true) +mesh = UnstructuredMesh2D(mesh_file, periodicity = true) ############################################################################### # create the semi discretization object @@ -41,15 +42,15 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -60,7 +61,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/unstructured_2d_dgsem/elixir_euler_free_stream.jl b/examples/unstructured_2d_dgsem/elixir_euler_free_stream.jl index 36e119ab794..a2fec1a320a 100644 --- a/examples/unstructured_2d_dgsem/elixir_euler_free_stream.jl +++ b/examples/unstructured_2d_dgsem/elixir_euler_free_stream.jl @@ -11,25 +11,26 @@ equations = CompressibleEulerEquations2D(1.4) initial_condition = initial_condition_constant boundary_condition_free_stream = BoundaryConditionDirichlet(initial_condition) -boundary_conditions = Dict( :Body => boundary_condition_free_stream, - :Button1 => boundary_condition_free_stream, - :Button2 => boundary_condition_free_stream, - :Eye1 => boundary_condition_free_stream, - :Eye2 => boundary_condition_free_stream, - :Smile => boundary_condition_free_stream, - :Bowtie => boundary_condition_free_stream ) +boundary_conditions = Dict(:Body => boundary_condition_free_stream, + :Button1 => boundary_condition_free_stream, + :Button2 => boundary_condition_free_stream, + :Eye1 => boundary_condition_free_stream, + :Eye2 => boundary_condition_free_stream, + :Smile => boundary_condition_free_stream, + :Bowtie => boundary_condition_free_stream) ############################################################################### # Get the DG approximation space -solver = DGSEM(polydeg=6, surface_flux=flux_hll) +solver = DGSEM(polydeg = 6, surface_flux = flux_hll) ############################################################################### # Get the curved quad mesh from a file (downloads the file if not available locally) default_mesh_file = joinpath(@__DIR__, "mesh_gingerbread_man.mesh") -isfile(default_mesh_file) || download("https://gist.githubusercontent.com/andrewwinters5000/2c6440b5f8a57db131061ad7aa78ee2b/raw/1f89fdf2c874ff678c78afb6fe8dc784bdfd421f/mesh_gingerbread_man.mesh", - default_mesh_file) +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/2c6440b5f8a57db131061ad7aa78ee2b/raw/1f89fdf2c874ff678c78afb6fe8dc784bdfd421f/mesh_gingerbread_man.mesh", + default_mesh_file) mesh_file = default_mesh_file mesh = UnstructuredMesh2D(mesh_file) @@ -38,7 +39,7 @@ mesh = UnstructuredMesh2D(mesh_file) # create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -49,15 +50,15 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) @@ -65,7 +66,7 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/unstructured_2d_dgsem/elixir_euler_periodic.jl b/examples/unstructured_2d_dgsem/elixir_euler_periodic.jl index 796c99987a2..afd177f0740 100644 --- a/examples/unstructured_2d_dgsem/elixir_euler_periodic.jl +++ b/examples/unstructured_2d_dgsem/elixir_euler_periodic.jl @@ -15,24 +15,25 @@ boundary_conditions = boundary_condition_periodic ############################################################################### # Get the DG approximation space -solver = DGSEM(polydeg=6, surface_flux=FluxRotated(flux_hll)) +solver = DGSEM(polydeg = 6, surface_flux = FluxRotated(flux_hll)) ############################################################################### # Get the curved quad mesh from a file (downloads the file if not available locally) default_mesh_file = joinpath(@__DIR__, "mesh_periodic_square_with_twist.mesh") -isfile(default_mesh_file) || download("https://gist.githubusercontent.com/andrewwinters5000/12ce661d7c354c3d94c74b964b0f1c96/raw/8275b9a60c6e7ebbdea5fc4b4f091c47af3d5273/mesh_periodic_square_with_twist.mesh", - default_mesh_file) +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/12ce661d7c354c3d94c74b964b0f1c96/raw/8275b9a60c6e7ebbdea5fc4b4f091c47af3d5273/mesh_periodic_square_with_twist.mesh", + default_mesh_file) mesh_file = default_mesh_file -mesh = UnstructuredMesh2D(mesh_file, periodicity=true) +mesh = UnstructuredMesh2D(mesh_file, periodicity = true) ############################################################################### # create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms, - boundary_conditions=boundary_conditions) + source_terms = source_terms, + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -43,14 +44,14 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback) ############################################################################### # run the simulation -sol = solve(ode, SSPRK43(); ode_default_options()..., callback=callbacks); +sol = solve(ode, SSPRK43(); ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/unstructured_2d_dgsem/elixir_euler_restart.jl b/examples/unstructured_2d_dgsem/elixir_euler_restart.jl index b85cc2c6d70..c1908691902 100644 --- a/examples/unstructured_2d_dgsem/elixir_euler_restart.jl +++ b/examples/unstructured_2d_dgsem/elixir_euler_restart.jl @@ -7,7 +7,6 @@ using Trixi trixi_include(@__MODULE__, joinpath(@__DIR__, "elixir_euler_basic.jl")) - ############################################################################### # adapt the parameters that have changed compared to "elixir_advection_extended.jl" @@ -18,8 +17,8 @@ restart_filename = joinpath("out", "restart_000050.h5") mesh = load_mesh(restart_filename) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms, - boundary_conditions=boundary_conditions) + source_terms = source_terms, + boundary_conditions = boundary_conditions) tspan = (load_time(restart_filename), 1.0) dt = load_dt(restart_filename) @@ -28,18 +27,15 @@ ode = semidiscretize(semi, tspan, restart_filename); # Do not overwrite the initial snapshot written by elixir_advection_extended.jl. save_solution.condition.save_initial_solution = false -integrator = init(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=dt, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +integrator = init(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = dt, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks, maxiters = 100_000); # Get the last time index and work with that. -integrator.iter = load_timestep(restart_filename) -integrator.stats.naccept = integrator.iter - +load_timestep!(integrator, restart_filename) ############################################################################### # run the simulation sol = solve!(integrator) summary_callback() # print the timer summary - diff --git a/examples/unstructured_2d_dgsem/elixir_euler_sedov.jl b/examples/unstructured_2d_dgsem/elixir_euler_sedov.jl index 570a2084691..e1cc0932969 100644 --- a/examples/unstructured_2d_dgsem/elixir_euler_sedov.jl +++ b/examples/unstructured_2d_dgsem/elixir_euler_sedov.jl @@ -14,25 +14,25 @@ The Sedov blast wave setup based on Flash - https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 """ function initial_condition_sedov_blast_wave(x, t, equations::CompressibleEulerEquations2D) - # Set up polar coordinates - inicenter = SVector(0.0, 0.0) - x_norm = x[1] - inicenter[1] - y_norm = x[2] - inicenter[2] - r = sqrt(x_norm^2 + y_norm^2) - - # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 - r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) - E = 1.0 - p0_inner = 3 * (equations.gamma - 1) * E / (3 * pi * r0^2) - p0_outer = 1.0e-5 # = true Sedov setup - - # Calculate primitive variables - rho = 1.0 - v1 = 0.0 - v2 = 0.0 - p = r > r0 ? p0_outer : p0_inner - - return prim2cons(SVector(rho, v1, v2, p), equations) + # Set up polar coordinates + inicenter = SVector(0.0, 0.0) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + + # Setup based on https://flash.rochester.edu/site/flashcode/user_support/flash_ug_devel/node187.html#SECTION010114000000000000000 + r0 = 0.21875 # = 3.5 * smallest dx (for domain length=4 and max-ref=6) + E = 1.0 + p0_inner = 3 * (equations.gamma - 1) * E / (3 * pi * r0^2) + p0_outer = 1.0e-5 # = true Sedov setup + + # Calculate primitive variables + rho = 1.0 + v1 = 0.0 + v2 = 0.0 + p = r > r0 ? p0_outer : p0_inner + + return prim2cons(SVector(rho, v1, v2, p), equations) end initial_condition = initial_condition_sedov_blast_wave @@ -43,23 +43,25 @@ volume_flux = flux_ranocha polydeg = 6 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=1.0, - alpha_min=0.001, - alpha_smooth=true, - variable=density_pressure) + alpha_max = 1.0, + alpha_min = 0.001, + alpha_smooth = true, + variable = density_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) -solver = DGSEM(polydeg=polydeg, surface_flux=surface_flux, volume_integral=volume_integral) +solver = DGSEM(polydeg = polydeg, surface_flux = surface_flux, + volume_integral = volume_integral) # Get the curved quad mesh from a file default_mesh_file = joinpath(@__DIR__, "mesh_periodic_square_with_twist.mesh") -isfile(default_mesh_file) || download("https://gist.githubusercontent.com/andrewwinters5000/12ce661d7c354c3d94c74b964b0f1c96/raw/8275b9a60c6e7ebbdea5fc4b4f091c47af3d5273/mesh_periodic_square_with_twist.mesh", - default_mesh_file) +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/12ce661d7c354c3d94c74b964b0f1c96/raw/8275b9a60c6e7ebbdea5fc4b4f091c47af3d5273/mesh_periodic_square_with_twist.mesh", + default_mesh_file) mesh_file = default_mesh_file -mesh = UnstructuredMesh2D(mesh_file, periodicity=true) +mesh = UnstructuredMesh2D(mesh_file, periodicity = true) # create the semidiscretization semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -73,15 +75,15 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 300 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=300, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 300, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=0.5) +stepsize_callback = StepsizeCallback(cfl = 0.5) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -92,7 +94,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/unstructured_2d_dgsem/elixir_euler_wall_bc.jl b/examples/unstructured_2d_dgsem/elixir_euler_wall_bc.jl index 5bfe1ae4e0e..b2abefe7eeb 100644 --- a/examples/unstructured_2d_dgsem/elixir_euler_wall_bc.jl +++ b/examples/unstructured_2d_dgsem/elixir_euler_wall_bc.jl @@ -10,40 +10,41 @@ equations = CompressibleEulerEquations2D(1.4) @inline function uniform_flow_state(x, t, equations::CompressibleEulerEquations2D) - # set the freestream flow parameters - rho_freestream = 1.0 - u_freestream = 0.3 - p_freestream = inv(equations.gamma) - - theta = pi / 90.0 # analogous with a two degree angle of attack - si, co = sincos(theta) - v1 = u_freestream * co - v2 = u_freestream * si - - prim = SVector(rho_freestream, v1, v2, p_freestream) - return prim2cons(prim, equations) + # set the freestream flow parameters + rho_freestream = 1.0 + u_freestream = 0.3 + p_freestream = inv(equations.gamma) + + theta = pi / 90.0 # analogous with a two degree angle of attack + si, co = sincos(theta) + v1 = u_freestream * co + v2 = u_freestream * si + + prim = SVector(rho_freestream, v1, v2, p_freestream) + return prim2cons(prim, equations) end initial_condition = uniform_flow_state boundary_condition_uniform_flow = BoundaryConditionDirichlet(uniform_flow_state) -boundary_conditions = Dict( :Bottom => boundary_condition_uniform_flow, - :Top => boundary_condition_uniform_flow, - :Right => boundary_condition_uniform_flow, - :Left => boundary_condition_uniform_flow, - :Circle => boundary_condition_slip_wall ) +boundary_conditions = Dict(:Bottom => boundary_condition_uniform_flow, + :Top => boundary_condition_uniform_flow, + :Right => boundary_condition_uniform_flow, + :Left => boundary_condition_uniform_flow, + :Circle => boundary_condition_slip_wall) ############################################################################### # Get the DG approximation space -solver = DGSEM(polydeg=4, surface_flux=flux_hll) +solver = DGSEM(polydeg = 4, surface_flux = flux_hll) ############################################################################### # Get the curved quad mesh from a file default_mesh_file = joinpath(@__DIR__, "mesh_box_around_circle.mesh") -isfile(default_mesh_file) || download("https://gist.githubusercontent.com/andrewwinters5000/8b9b11a1eedfa54b215c122c3d17b271/raw/0d2b5d98c87e67a6f384693a8b8e54b4c9fcbf3d/mesh_box_around_circle.mesh", - default_mesh_file) +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/8b9b11a1eedfa54b215c122c3d17b271/raw/0d2b5d98c87e67a6f384693a8b8e54b4c9fcbf3d/mesh_box_around_circle.mesh", + default_mesh_file) mesh_file = default_mesh_file mesh = UnstructuredMesh2D(mesh_file) @@ -52,7 +53,7 @@ mesh = UnstructuredMesh2D(mesh_file) # create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_conditions) + boundary_conditions = boundary_conditions) ############################################################################### # ODE solvers, callbacks etc. @@ -63,22 +64,23 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=10, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 10, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) -callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) +callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, + stepsize_callback) ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/unstructured_2d_dgsem/elixir_mhd_alfven_wave.jl b/examples/unstructured_2d_dgsem/elixir_mhd_alfven_wave.jl index 6b31776b297..3ed3e828ca8 100644 --- a/examples/unstructured_2d_dgsem/elixir_mhd_alfven_wave.jl +++ b/examples/unstructured_2d_dgsem/elixir_mhd_alfven_wave.jl @@ -5,22 +5,25 @@ using Trixi ############################################################################### # semidiscretization of the compressible ideal GLM-MHD equations -gamma = 5/3 +gamma = 5 / 3 equations = IdealGlmMhdEquations2D(gamma) initial_condition = initial_condition_convergence_test volume_flux = (flux_central, flux_nonconservative_powell) -solver = DGSEM(polydeg=7, surface_flux=(flux_hll, flux_nonconservative_powell), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 7, + surface_flux = (flux_hlle, + flux_nonconservative_powell), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) # Get the unstructured quad mesh from a file (downloads the file if not available locally) default_mesh_file = joinpath(@__DIR__, "mesh_alfven_wave_with_twist_and_flip.mesh") -isfile(default_mesh_file) || download("https://gist.githubusercontent.com/andrewwinters5000/8f8cd23df27fcd494553f2a89f3c1ba4/raw/85e3c8d976bbe57ca3d559d653087b0889535295/mesh_alfven_wave_with_twist_and_flip.mesh", - default_mesh_file) +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/8f8cd23df27fcd494553f2a89f3c1ba4/raw/85e3c8d976bbe57ca3d559d653087b0889535295/mesh_alfven_wave_with_twist_and_flip.mesh", + default_mesh_file) mesh_file = default_mesh_file -mesh = UnstructuredMesh2D(mesh_file, periodicity=true) +mesh = UnstructuredMesh2D(mesh_file, periodicity = true) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -33,21 +36,24 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=false, - extra_analysis_integrals=(entropy, energy_total, - energy_kinetic, energy_internal, - energy_magnetic, cross_helicity)) - -alive_callback = AliveCallback(analysis_interval=analysis_interval) - -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = false, + extra_analysis_integrals = (entropy, energy_total, + energy_kinetic, + energy_internal, + energy_magnetic, + cross_helicity)) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) cfl = 0.9 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -56,11 +62,10 @@ callbacks = CallbackSet(summary_callback, stepsize_callback, glm_speed_callback) - ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/unstructured_2d_dgsem/elixir_mhd_ec.jl b/examples/unstructured_2d_dgsem/elixir_mhd_ec.jl index d75079bb8d7..a40f92cac02 100644 --- a/examples/unstructured_2d_dgsem/elixir_mhd_ec.jl +++ b/examples/unstructured_2d_dgsem/elixir_mhd_ec.jl @@ -6,40 +6,42 @@ using Trixi ############################################################################### # semidiscretization of the compressible ideal GLM-MHD equations -equations = IdealGlmMhdEquations2D(5/3) +equations = IdealGlmMhdEquations2D(5 / 3) function initial_condition_shifted_weak_blast_wave(x, t, equations::IdealGlmMhdEquations2D) - # Adapted MHD version of the weak blast wave from Hennemann & Gassner JCP paper 2020 (Sec. 6.3) - # Shift blastwave to center of domain - inicenter = (sqrt(2)/2, sqrt(2)/2) - x_norm = x[1] - inicenter[1] - y_norm = x[2] - inicenter[2] - r = sqrt(x_norm^2 + y_norm^2) - phi = atan(y_norm, x_norm) - - # Calculate primitive variables - rho = r > 0.5 ? 1.0 : 1.1691 - v1 = r > 0.5 ? 0.0 : 0.1882 * cos(phi) - v2 = r > 0.5 ? 0.0 : 0.1882 * sin(phi) - p = r > 0.5 ? 1.0 : 1.245 - - return prim2cons(SVector(rho, v1, v2, 0.0, p, 1.0, 1.0, 1.0, 0.0), equations) + # Adapted MHD version of the weak blast wave from Hennemann & Gassner JCP paper 2020 (Sec. 6.3) + # Shift blastwave to center of domain + inicenter = (sqrt(2) / 2, sqrt(2) / 2) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + phi = atan(y_norm, x_norm) + + # Calculate primitive variables + rho = r > 0.5 ? 1.0 : 1.1691 + v1 = r > 0.5 ? 0.0 : 0.1882 * cos(phi) + v2 = r > 0.5 ? 0.0 : 0.1882 * sin(phi) + p = r > 0.5 ? 1.0 : 1.245 + + return prim2cons(SVector(rho, v1, v2, 0.0, p, 1.0, 1.0, 1.0, 0.0), equations) end initial_condition = initial_condition_shifted_weak_blast_wave # Get the DG approximation space volume_flux = (flux_hindenlang_gassner, flux_nonconservative_powell) -solver = DGSEM(polydeg=6, surface_flux=(flux_hindenlang_gassner, flux_nonconservative_powell), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 6, + surface_flux = (flux_hindenlang_gassner, flux_nonconservative_powell), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) # Get the unstructured quad mesh from a file (downloads the file if not available locally) default_mesh_file = joinpath(@__DIR__, "mesh_alfven_wave_with_twist_and_flip.mesh") -isfile(default_mesh_file) || download("https://gist.githubusercontent.com/andrewwinters5000/8f8cd23df27fcd494553f2a89f3c1ba4/raw/85e3c8d976bbe57ca3d559d653087b0889535295/mesh_alfven_wave_with_twist_and_flip.mesh", - default_mesh_file) +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/8f8cd23df27fcd494553f2a89f3c1ba4/raw/85e3c8d976bbe57ca3d559d653087b0889535295/mesh_alfven_wave_with_twist_and_flip.mesh", + default_mesh_file) mesh_file = default_mesh_file -mesh = UnstructuredMesh2D(mesh_file, periodicity=true) +mesh = UnstructuredMesh2D(mesh_file, periodicity = true) # create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -53,21 +55,24 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=false, - extra_analysis_integrals=(entropy, energy_total, - energy_kinetic, energy_internal, - energy_magnetic, cross_helicity)) - -alive_callback = AliveCallback(analysis_interval=analysis_interval) - -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true, - solution_variables=cons2prim) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = false, + extra_analysis_integrals = (entropy, energy_total, + energy_kinetic, + energy_internal, + energy_magnetic, + cross_helicity)) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) cfl = 1.0 -stepsize_callback = StepsizeCallback(cfl=cfl) +stepsize_callback = StepsizeCallback(cfl = cfl) -glm_speed_callback = GlmSpeedCallback(glm_scale=0.5, cfl=cfl) +glm_speed_callback = GlmSpeedCallback(glm_scale = 0.5, cfl = cfl) callbacks = CallbackSet(summary_callback, analysis_callback, @@ -79,7 +84,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/unstructured_2d_dgsem/elixir_shallowwater_dirichlet.jl b/examples/unstructured_2d_dgsem/elixir_shallowwater_dirichlet.jl index 044b2549b01..1148f25fae3 100644 --- a/examples/unstructured_2d_dgsem/elixir_shallowwater_dirichlet.jl +++ b/examples/unstructured_2d_dgsem/elixir_shallowwater_dirichlet.jl @@ -7,47 +7,48 @@ using Trixi # semidiscretization of the shallow water equations with a continuous # bottom topography function (set in the initial conditions) -equations = ShallowWaterEquations2D(gravity_constant=1.0, H0=3.0) +equations = ShallowWaterEquations2D(gravity_constant = 1.0, H0 = 3.0) # An initial condition with constant total water height and zero velocities to test well-balancedness. function initial_condition_well_balancedness(x, t, equations::ShallowWaterEquations2D) - # Set the background values - H = equations.H0 - v1 = 0.0 - v2 = 0.0 - # bottom topography taken from Pond.control in [HOHQMesh](https://github.com/trixi-framework/HOHQMesh) - x1, x2 = x - b = ( 1.5 / exp( 0.5 * ((x1 - 1.0)^2 + (x2 - 1.0)^2) ) - + 0.75 / exp( 0.5 * ((x1 + 1.0)^2 + (x2 + 1.0)^2) ) ) - return prim2cons(SVector(H, v1, v2, b), equations) + # Set the background values + H = equations.H0 + v1 = 0.0 + v2 = 0.0 + # bottom topography taken from Pond.control in [HOHQMesh](https://github.com/trixi-framework/HOHQMesh) + x1, x2 = x + b = (1.5 / exp(0.5 * ((x1 - 1.0)^2 + (x2 - 1.0)^2)) + + 0.75 / exp(0.5 * ((x1 + 1.0)^2 + (x2 + 1.0)^2))) + return prim2cons(SVector(H, v1, v2, b), equations) end initial_condition = initial_condition_well_balancedness boundary_condition_constant = BoundaryConditionDirichlet(initial_condition) -boundary_condition = Dict( :OuterCircle => boundary_condition_constant ) +boundary_condition = Dict(:OuterCircle => boundary_condition_constant) ############################################################################### # Get the DG approximation space volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -solver = DGSEM(polydeg=4, surface_flux=(flux_hll, flux_nonconservative_fjordholm_etal), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 4, surface_flux = (flux_hll, flux_nonconservative_fjordholm_etal), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### # This setup is for the curved, split form well-balancedness testing # Get the unstructured quad mesh from a file (downloads the file if not available locally) default_mesh_file = joinpath(@__DIR__, "mesh_outer_circle.mesh") -isfile(default_mesh_file) || download("https://gist.githubusercontent.com/andrewwinters5000/9beddd9cd00e2a0a15865129eeb24928/raw/be71e67fa48bc4e1e97f5f6cd77c3ed34c6ba9be/mesh_outer_circle.mesh", - default_mesh_file) +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/9beddd9cd00e2a0a15865129eeb24928/raw/be71e67fa48bc4e1e97f5f6cd77c3ed34c6ba9be/mesh_outer_circle.mesh", + default_mesh_file) mesh_file = default_mesh_file mesh = UnstructuredMesh2D(mesh_file) # Create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_condition) + boundary_conditions = boundary_condition) ############################################################################### # ODE solvers, callbacks, etc. @@ -58,15 +59,15 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - save_analysis=true, - extra_analysis_integrals=(lake_at_rest_error,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true, + extra_analysis_integrals = (lake_at_rest_error,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) @@ -74,6 +75,6 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav # run the simulation # use a Runge-Kutta method with automatic (error based) time step size control -sol = solve(ode, RDPK3SpFSAL49(); abstol=1.0e-11, reltol=1.0e-11, - ode_default_options()..., callback=callbacks); +sol = solve(ode, RDPK3SpFSAL49(); abstol = 1.0e-11, reltol = 1.0e-11, + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/unstructured_2d_dgsem/elixir_shallowwater_ec.jl b/examples/unstructured_2d_dgsem/elixir_shallowwater_ec.jl index 138b256c08b..8e9d396d826 100644 --- a/examples/unstructured_2d_dgsem/elixir_shallowwater_ec.jl +++ b/examples/unstructured_2d_dgsem/elixir_shallowwater_ec.jl @@ -7,7 +7,7 @@ using Trixi # semidiscretization of the shallow water equations with a discontinuous # bottom topography function -equations = ShallowWaterEquations2D(gravity_constant=9.81) +equations = ShallowWaterEquations2D(gravity_constant = 9.81) # Note, this initial condition is used to compute errors in the analysis callback but the initialization is # overwritten by `initial_condition_ec_discontinuous_bottom` below. @@ -17,19 +17,21 @@ initial_condition = initial_condition_weak_blast_wave # Get the DG approximation space volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -solver = DGSEM(polydeg=6, surface_flux=(flux_fjordholm_etal, flux_nonconservative_fjordholm_etal), - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 6, + surface_flux = (flux_fjordholm_etal, flux_nonconservative_fjordholm_etal), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### # This setup is for the curved, split form entropy conservation testing (needs periodic BCs) # Get the unstructured quad mesh from a file (downloads the file if not available locally) default_mesh_file = joinpath(@__DIR__, "mesh_alfven_wave_with_twist_and_flip.mesh") -isfile(default_mesh_file) || download("https://gist.githubusercontent.com/andrewwinters5000/8f8cd23df27fcd494553f2a89f3c1ba4/raw/85e3c8d976bbe57ca3d559d653087b0889535295/mesh_alfven_wave_with_twist_and_flip.mesh", - default_mesh_file) +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/8f8cd23df27fcd494553f2a89f3c1ba4/raw/85e3c8d976bbe57ca3d559d653087b0889535295/mesh_alfven_wave_with_twist_and_flip.mesh", + default_mesh_file) mesh_file = default_mesh_file -mesh = UnstructuredMesh2D(mesh_file, periodicity=true) +mesh = UnstructuredMesh2D(mesh_file, periodicity = true) # Create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -49,45 +51,48 @@ ode = semidiscretize(semi, tspan) # In contrast to the usual signature of initial conditions, this one get passed the # `element_id` explicitly. In particular, this initial conditions works as intended # only for the specific mesh loaded above! -function initial_condition_ec_discontinuous_bottom(x, t, element_id, equations::ShallowWaterEquations2D) - # Set up polar coordinates - inicenter = SVector(0.7, 0.7) - x_norm = x[1] - inicenter[1] - y_norm = x[2] - inicenter[2] - r = sqrt(x_norm^2 + y_norm^2) - phi = atan(y_norm, x_norm) - sin_phi, cos_phi = sincos(phi) - - # Set the background values - H = 3.25 - v1 = 0.0 - v2 = 0.0 - b = 0.0 - - # setup the discontinuous water height and velocities - if element_id == 10 - H = 4.0 - v1 = 0.1882 * cos_phi - v2 = 0.1882 * sin_phi - end - - # Setup a discontinuous bottom topography using the element id number - if element_id == 7 - b = 2.0 + 0.5 * sin(2.0 * pi * x[1]) + 0.5 * cos(2.0 * pi * x[2]) - end - - return prim2cons(SVector(H, v1, v2, b), equations) +function initial_condition_ec_discontinuous_bottom(x, t, element_id, + equations::ShallowWaterEquations2D) + # Set up polar coordinates + inicenter = SVector(0.7, 0.7) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + phi = atan(y_norm, x_norm) + sin_phi, cos_phi = sincos(phi) + + # Set the background values + H = 3.25 + v1 = 0.0 + v2 = 0.0 + b = 0.0 + + # setup the discontinuous water height and velocities + if element_id == 10 + H = 4.0 + v1 = 0.1882 * cos_phi + v2 = 0.1882 * sin_phi + end + + # Setup a discontinuous bottom topography using the element id number + if element_id == 7 + b = 2.0 + 0.5 * sin(2.0 * pi * x[1]) + 0.5 * cos(2.0 * pi * x[2]) + end + + return prim2cons(SVector(H, v1, v2, b), equations) end # point to the data we want to augment u = Trixi.wrap_array(ode.u0, semi) # reset the initial condition for element in eachelement(semi.solver, semi.cache) - for j in eachnode(semi.solver), i in eachnode(semi.solver) - x_node = Trixi.get_node_coords(semi.cache.elements.node_coordinates, equations, semi.solver, i, j, element) - u_node = initial_condition_ec_discontinuous_bottom(x_node, first(tspan), element, equations) - Trixi.set_node_vars!(u, u_node, equations, semi.solver, i, j, element) - end + for j in eachnode(semi.solver), i in eachnode(semi.solver) + x_node = Trixi.get_node_coords(semi.cache.elements.node_coordinates, equations, + semi.solver, i, j, element) + u_node = initial_condition_ec_discontinuous_bottom(x_node, first(tspan), element, + equations) + Trixi.set_node_vars!(u, u_node, equations, semi.solver, i, j, element) + end end ############################################################################### @@ -96,15 +101,15 @@ end summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=3.0) +stepsize_callback = StepsizeCallback(cfl = 3.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) @@ -112,7 +117,7 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/unstructured_2d_dgsem/elixir_shallowwater_ec_shockcapturing.jl b/examples/unstructured_2d_dgsem/elixir_shallowwater_ec_shockcapturing.jl index ee3650f3bb5..94202b81df0 100644 --- a/examples/unstructured_2d_dgsem/elixir_shallowwater_ec_shockcapturing.jl +++ b/examples/unstructured_2d_dgsem/elixir_shallowwater_ec_shockcapturing.jl @@ -7,7 +7,7 @@ using Trixi # semidiscretization of the shallow water equations with a discontinuous # bottom topography function -equations = ShallowWaterEquations2D(gravity_constant=9.81) +equations = ShallowWaterEquations2D(gravity_constant = 9.81) # Note, this initial condition is used to compute errors in the analysis callback but the initialization is # overwritten by `initial_condition_ec_discontinuous_bottom` below. @@ -17,17 +17,17 @@ initial_condition = initial_condition_weak_blast_wave # Get the DG approximation space surface_flux = (flux_fjordholm_etal, flux_nonconservative_fjordholm_etal) -volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) +volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) polydeg = 6 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=waterheight_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = waterheight_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) ############################################################################### @@ -35,11 +35,12 @@ solver = DGSEM(basis, surface_flux, volume_integral) # Get the unstructured quad mesh from a file (downloads the file if not available locally) default_mesh_file = joinpath(@__DIR__, "mesh_alfven_wave_with_twist_and_flip.mesh") -isfile(default_mesh_file) || download("https://gist.githubusercontent.com/andrewwinters5000/8f8cd23df27fcd494553f2a89f3c1ba4/raw/85e3c8d976bbe57ca3d559d653087b0889535295/mesh_alfven_wave_with_twist_and_flip.mesh", - default_mesh_file) +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/8f8cd23df27fcd494553f2a89f3c1ba4/raw/85e3c8d976bbe57ca3d559d653087b0889535295/mesh_alfven_wave_with_twist_and_flip.mesh", + default_mesh_file) mesh_file = default_mesh_file -mesh = UnstructuredMesh2D(mesh_file, periodicity=true) +mesh = UnstructuredMesh2D(mesh_file, periodicity = true) # Create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -59,45 +60,48 @@ ode = semidiscretize(semi, tspan) # In contrast to the usual signature of initial conditions, this one get passed the # `element_id` explicitly. In particular, this initial conditions works as intended # only for the specific mesh loaded above! -function initial_condition_ec_discontinuous_bottom(x, t, element_id, equations::ShallowWaterEquations2D) - # Set up polar coordinates - inicenter = SVector(0.7, 0.7) - x_norm = x[1] - inicenter[1] - y_norm = x[2] - inicenter[2] - r = sqrt(x_norm^2 + y_norm^2) - phi = atan(y_norm, x_norm) - sin_phi, cos_phi = sincos(phi) - - # Set the background values - H = 3.25 - v1 = 0.0 - v2 = 0.0 - b = 0.0 - - # setup the discontinuous water height and velocities - if element_id == 10 - H = 4.0 - v1 = 0.1882 * cos_phi - v2 = 0.1882 * sin_phi - end - - # Setup a discontinuous bottom topography using the element id number - if element_id == 7 - b = 2.0 + 0.5 * sin(2.0 * pi * x[1]) + 0.5 * cos(2.0 * pi * x[2]) - end - - return prim2cons(SVector(H, v1, v2, b), equations) +function initial_condition_ec_discontinuous_bottom(x, t, element_id, + equations::ShallowWaterEquations2D) + # Set up polar coordinates + inicenter = SVector(0.7, 0.7) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + phi = atan(y_norm, x_norm) + sin_phi, cos_phi = sincos(phi) + + # Set the background values + H = 3.25 + v1 = 0.0 + v2 = 0.0 + b = 0.0 + + # setup the discontinuous water height and velocities + if element_id == 10 + H = 4.0 + v1 = 0.1882 * cos_phi + v2 = 0.1882 * sin_phi + end + + # Setup a discontinuous bottom topography using the element id number + if element_id == 7 + b = 2.0 + 0.5 * sin(2.0 * pi * x[1]) + 0.5 * cos(2.0 * pi * x[2]) + end + + return prim2cons(SVector(H, v1, v2, b), equations) end # point to the data we want to augment u = Trixi.wrap_array(ode.u0, semi) # reset the initial condition for element in eachelement(semi.solver, semi.cache) - for j in eachnode(semi.solver), i in eachnode(semi.solver) - x_node = Trixi.get_node_coords(semi.cache.elements.node_coordinates, equations, semi.solver, i, j, element) - u_node = initial_condition_ec_discontinuous_bottom(x_node, first(tspan), element, equations) - Trixi.set_node_vars!(u, u_node, equations, semi.solver, i, j, element) - end + for j in eachnode(semi.solver), i in eachnode(semi.solver) + x_node = Trixi.get_node_coords(semi.cache.elements.node_coordinates, equations, + semi.solver, i, j, element) + u_node = initial_condition_ec_discontinuous_bottom(x_node, first(tspan), element, + equations) + Trixi.set_node_vars!(u, u_node, equations, semi.solver, i, j, element) + end end ############################################################################### @@ -106,11 +110,11 @@ end summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -stepsize_callback = StepsizeCallback(cfl=3.0) +stepsize_callback = StepsizeCallback(cfl = 3.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, stepsize_callback) @@ -118,7 +122,7 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/unstructured_2d_dgsem/elixir_shallowwater_source_terms.jl b/examples/unstructured_2d_dgsem/elixir_shallowwater_source_terms.jl index e0b64802ff8..07668688406 100644 --- a/examples/unstructured_2d_dgsem/elixir_shallowwater_source_terms.jl +++ b/examples/unstructured_2d_dgsem/elixir_shallowwater_source_terms.jl @@ -7,7 +7,7 @@ using Trixi # semidiscretization of the shallow water equations with a periodic # bottom topography function (set in the initial conditions) -equations = ShallowWaterEquations2D(gravity_constant=9.81) +equations = ShallowWaterEquations2D(gravity_constant = 9.81) initial_condition = initial_condition_convergence_test @@ -16,23 +16,24 @@ initial_condition = initial_condition_convergence_test volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) surface_flux = (flux_fjordholm_etal, flux_nonconservative_fjordholm_etal) -solver = DGSEM(polydeg=6, surface_flux=surface_flux, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +solver = DGSEM(polydeg = 6, surface_flux = surface_flux, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### # This setup is for the curved, split form convergence test on a periodic domain # Get the unstructured quad mesh from a file (downloads the file if not available locally) default_mesh_file = joinpath(@__DIR__, "mesh_alfven_wave_with_twist_and_flip.mesh") -isfile(default_mesh_file) || download("https://gist.githubusercontent.com/andrewwinters5000/8f8cd23df27fcd494553f2a89f3c1ba4/raw/85e3c8d976bbe57ca3d559d653087b0889535295/mesh_alfven_wave_with_twist_and_flip.mesh", - default_mesh_file) +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/8f8cd23df27fcd494553f2a89f3c1ba4/raw/85e3c8d976bbe57ca3d559d653087b0889535295/mesh_alfven_wave_with_twist_and_flip.mesh", + default_mesh_file) mesh_file = default_mesh_file -mesh = UnstructuredMesh2D(mesh_file, periodicity=true) +mesh = UnstructuredMesh2D(mesh_file, periodicity = true) # Create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -43,15 +44,15 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) @@ -59,7 +60,7 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/unstructured_2d_dgsem/elixir_shallowwater_three_mound_dam_break.jl b/examples/unstructured_2d_dgsem/elixir_shallowwater_three_mound_dam_break.jl index 65b0fcae462..6164f9d4a55 100644 --- a/examples/unstructured_2d_dgsem/elixir_shallowwater_three_mound_dam_break.jl +++ b/examples/unstructured_2d_dgsem/elixir_shallowwater_three_mound_dam_break.jl @@ -8,10 +8,8 @@ using Trixi # # TODO: TrixiShallowWater: wet/dry example elixir - -equations = ShallowWaterEquations2D(gravity_constant=9.81, H0=1.875, - threshold_limiter=1e-12, threshold_wet=1e-14) - +equations = ShallowWaterEquations2D(gravity_constant = 9.81, H0 = 1.875, + threshold_limiter = 1e-12, threshold_wet = 1e-14) """ initial_condition_three_mounds(x, t, equations::ShallowWaterEquations2D) @@ -28,66 +26,68 @@ The initial conditions is taken from Section 6.3 of the paper: """ function initial_condition_three_mounds(x, t, equations::ShallowWaterEquations2D) - # Set the background values - v1 = 0.0 - v2 = 0.0 + # Set the background values + v1 = 0.0 + v2 = 0.0 - x1, x2 = x - M_1 = 1 - 0.1 * sqrt( (x1 - 30.0)^2 + (x2 - 22.5)^2 ) - M_2 = 1 - 0.1 * sqrt( (x1 - 30.0)^2 + (x2 - 7.5)^2 ) - M_3 = 2.8 - 0.28 * sqrt( (x1 - 47.5)^2 + (x2 - 15.0)^2 ) + x1, x2 = x + M_1 = 1 - 0.1 * sqrt((x1 - 30.0)^2 + (x2 - 22.5)^2) + M_2 = 1 - 0.1 * sqrt((x1 - 30.0)^2 + (x2 - 7.5)^2) + M_3 = 2.8 - 0.28 * sqrt((x1 - 47.5)^2 + (x2 - 15.0)^2) - b = max(0.0, M_1, M_2, M_3) + b = max(0.0, M_1, M_2, M_3) - # use a logistic function to transfer water height value smoothly - L = equations.H0 # maximum of function - x0 = 8 # center point of function - k = -75.0 # sharpness of transfer + # use a logistic function to transfer water height value smoothly + L = equations.H0 # maximum of function + x0 = 8 # center point of function + k = -75.0 # sharpness of transfer - H = max(b, L / (1.0 + exp(-k * (x1 - x0)))) + H = max(b, L / (1.0 + exp(-k * (x1 - x0)))) - # Avoid division by zero by adjusting the initial condition with a small dry state threshold - # that defaults to 500*eps() ≈ 1e-13 in double precision and is set in the constructor above - # for the ShallowWaterEquations struct. - H = max(H, b + equations.threshold_limiter) - return prim2cons(SVector(H, v1, v2, b), equations) + # Avoid division by zero by adjusting the initial condition with a small dry state threshold + # that defaults to 500*eps() ≈ 1e-13 in double precision and is set in the constructor above + # for the ShallowWaterEquations struct. + H = max(H, b + equations.threshold_limiter) + return prim2cons(SVector(H, v1, v2, b), equations) end initial_condition = initial_condition_three_mounds function boundary_condition_outflow(u_inner, normal_direction::AbstractVector, x, t, - surface_flux_function, equations::ShallowWaterEquations2D) - # Impulse and bottom from inside, height from external state - u_outer = SVector(equations.threshold_wet, u_inner[2], u_inner[3], u_inner[4]) + surface_flux_function, + equations::ShallowWaterEquations2D) + # Impulse and bottom from inside, height from external state + u_outer = SVector(equations.threshold_wet, u_inner[2], u_inner[3], u_inner[4]) - # calculate the boundary flux - flux = surface_flux_function(u_inner, u_outer, normal_direction, equations) + # calculate the boundary flux + flux = surface_flux_function(u_inner, u_outer, normal_direction, equations) - return flux + return flux end -boundary_conditions = Dict( :Bottom => boundary_condition_slip_wall, - :Top => boundary_condition_slip_wall, - :Right => boundary_condition_outflow, - :Left => boundary_condition_slip_wall ) +boundary_conditions = Dict(:Bottom => boundary_condition_slip_wall, + :Top => boundary_condition_slip_wall, + :Right => boundary_condition_outflow, + :Left => boundary_condition_slip_wall) ############################################################################### # Get the DG approximation space volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -surface_flux = (FluxHydrostaticReconstruction(flux_hll_chen_noelle, hydrostatic_reconstruction_chen_noelle), +surface_flux = (FluxHydrostaticReconstruction(flux_hll_chen_noelle, + hydrostatic_reconstruction_chen_noelle), flux_nonconservative_chen_noelle) basis = LobattoLegendreBasis(4) indicator_sc = IndicatorHennemannGassnerShallowWater(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=waterheight_pressure) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = waterheight_pressure) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) solver = DGSEM(basis, surface_flux, volume_integral) @@ -96,8 +96,9 @@ solver = DGSEM(basis, surface_flux, volume_integral) default_meshfile = joinpath(@__DIR__, "mesh_three_mound.mesh") -isfile(default_meshfile) || download("https://gist.githubusercontent.com/svengoldberg/c3c87fecb3fc6e46be7f0d1c7cb35f83/raw/e817ecd9e6c4686581d63c46128f9b6468d396d3/mesh_three_mound.mesh", - default_meshfile) +isfile(default_meshfile) || + download("https://gist.githubusercontent.com/svengoldberg/c3c87fecb3fc6e46be7f0d1c7cb35f83/raw/e817ecd9e6c4686581d63c46128f9b6468d396d3/mesh_three_mound.mesh", + default_meshfile) meshfile = default_meshfile @@ -105,7 +106,7 @@ mesh = UnstructuredMesh2D(meshfile) # Create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver; - boundary_conditions=boundary_conditions) + boundary_conditions = boundary_conditions) ############################################################################### # ODE solver @@ -119,21 +120,21 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) ############################################################################### # run the simulation -stage_limiter! = PositivityPreservingLimiterShallowWater(variables=(Trixi.waterheight,)) +stage_limiter! = PositivityPreservingLimiterShallowWater(variables = (Trixi.waterheight,)) sol = solve(ode, SSPRK43(stage_limiter!); - ode_default_options()..., callback=callbacks); + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_convergence.jl b/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_convergence.jl index d9e71e4aa44..0b86095663a 100644 --- a/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_convergence.jl +++ b/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_convergence.jl @@ -7,32 +7,34 @@ using Trixi # Semidiscretization of the two-layer shallow water equations with a periodic # bottom topography function (set in the initial conditions) -equations = ShallowWaterTwoLayerEquations2D(gravity_constant=10.0, rho_upper=0.9, rho_lower=1.0) +equations = ShallowWaterTwoLayerEquations2D(gravity_constant = 10.0, rho_upper = 0.9, + rho_lower = 1.0) initial_condition = initial_condition_convergence_test ############################################################################### # Get the DG approximation space -volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -surface_flux = (flux_fjordholm_etal, flux_nonconservative_fjordholm_etal) -solver = DGSEM(polydeg=6, surface_flux=surface_flux, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +volume_flux = (flux_wintermeyer_etal, flux_nonconservative_ersing_etal) +surface_flux = (flux_wintermeyer_etal, flux_nonconservative_ersing_etal) +solver = DGSEM(polydeg = 6, surface_flux = surface_flux, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### # This setup is for the curved, split form convergence test on a periodic domain # Get the unstructured quad mesh from a file (downloads the file if not available locally) default_mesh_file = joinpath(@__DIR__, "mesh_alfven_wave_with_twist_and_flip.mesh") -isfile(default_mesh_file) || download("https://gist.githubusercontent.com/andrewwinters5000/8f8cd23df27fcd494553f2a89f3c1ba4/raw/85e3c8d976bbe57ca3d559d653087b0889535295/mesh_alfven_wave_with_twist_and_flip.mesh", - default_mesh_file) +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/8f8cd23df27fcd494553f2a89f3c1ba4/raw/85e3c8d976bbe57ca3d559d653087b0889535295/mesh_alfven_wave_with_twist_and_flip.mesh", + default_mesh_file) mesh_file = default_mesh_file -mesh = UnstructuredMesh2D(mesh_file, periodicity=true) +mesh = UnstructuredMesh2D(mesh_file, periodicity = true) # Create the semidiscretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - source_terms=source_terms_convergence_test) + source_terms = source_terms_convergence_test) ############################################################################### # ODE solvers, callbacks etc. @@ -43,15 +45,15 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 500 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=500, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 500, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) @@ -59,7 +61,7 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_dam_break.jl b/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_dam_break.jl index 4295f93b342..4ad5f7e3201 100644 --- a/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_dam_break.jl +++ b/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_dam_break.jl @@ -7,62 +7,64 @@ using Trixi # Semidiscretization of the two-layer shallow water equations for a dam break test with a # discontinuous bottom topography function to test energy conservation -equations = ShallowWaterTwoLayerEquations2D(gravity_constant=1.0, rho_upper=0.9, rho_lower=1.0) +equations = ShallowWaterTwoLayerEquations2D(gravity_constant = 1.0, rho_upper = 0.9, + rho_lower = 1.0) # This test case uses a special work around to setup a truly discontinuous bottom topography # function and initial condition for this academic testcase of entropy conservation. First, a # dummy initial_condition_dam_break is introduced to create the semidiscretization. Then the initial # condition is reset with the true discontinuous values from initial_condition_discontinuous_dam_break. -function initial_condition_dam_break(x, t,equations::ShallowWaterTwoLayerEquations2D) - if x[1] < sqrt(2)/2 - H_upper = 1.0 - H_lower = 0.6 - b = 0.1 - else - H_upper = 0.9 - H_lower = 0.5 - b = 0.0 - end - - v1_upper = 0.0 - v2_upper = 0.0 - v1_lower = 0.0 - v2_lower = 0.0 - return prim2cons(SVector(H_upper, v1_upper, v2_upper, H_lower, v1_lower, v2_lower, b), equations) +function initial_condition_dam_break(x, t, equations::ShallowWaterTwoLayerEquations2D) + if x[1] < sqrt(2) / 2 + H_upper = 1.0 + H_lower = 0.6 + b = 0.1 + else + H_upper = 0.9 + H_lower = 0.5 + b = 0.0 + end + + v1_upper = 0.0 + v2_upper = 0.0 + v1_lower = 0.0 + v2_lower = 0.0 + return prim2cons(SVector(H_upper, v1_upper, v2_upper, H_lower, v1_lower, v2_lower, b), + equations) end initial_condition = initial_condition_dam_break boundary_condition_constant = BoundaryConditionDirichlet(initial_condition_dam_break) - ############################################################################### # Get the DG approximation space -volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -surface_flux= (flux_fjordholm_etal, flux_nonconservative_fjordholm_etal) -solver = DGSEM(polydeg=6, surface_flux=surface_flux, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +volume_flux = (flux_wintermeyer_etal, flux_nonconservative_ersing_etal) +surface_flux = (flux_wintermeyer_etal, flux_nonconservative_ersing_etal) +solver = DGSEM(polydeg = 6, surface_flux = surface_flux, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### # Get the unstructured quad mesh from a file (downloads the file if not available locally) default_mesh_file = joinpath(@__DIR__, "mesh_alfven_wave_with_twist_and_flip.mesh") -isfile(default_mesh_file) || download("https://gist.githubusercontent.com/andrewwinters5000/8f8cd23df27fcd494553f2a89f3c1ba4/raw/85e3c8d976bbe57ca3d559d653087b0889535295/mesh_alfven_wave_with_twist_and_flip.mesh", - default_mesh_file) +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/8f8cd23df27fcd494553f2a89f3c1ba4/raw/85e3c8d976bbe57ca3d559d653087b0889535295/mesh_alfven_wave_with_twist_and_flip.mesh", + default_mesh_file) mesh_file = default_mesh_file -mesh = UnstructuredMesh2D(mesh_file, periodicity=false) +mesh = UnstructuredMesh2D(mesh_file, periodicity = false) # Boundary conditions -boundary_condition = Dict(:Top => boundary_condition_slip_wall, - :Left => boundary_condition_slip_wall, - :Right => boundary_condition_slip_wall, +boundary_condition = Dict(:Top => boundary_condition_slip_wall, + :Left => boundary_condition_slip_wall, + :Right => boundary_condition_slip_wall, :Bottom => boundary_condition_slip_wall) # Create the semi discretization object -semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, - solver, boundary_conditions=boundary_condition) +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, + solver, boundary_conditions = boundary_condition) ############################################################################### # ODE solver @@ -79,58 +81,63 @@ ode = semidiscretize(semi, tspan) # `element_id` explicitly. In particular, this initial conditions works as intended # only for the specific mesh loaded above! -function initial_condition_discontinuous_dam_break(x, t, element_id, +function initial_condition_discontinuous_dam_break(x, t, element_id, equations::ShallowWaterTwoLayerEquations2D) - # Constant values - v1_upper = 0.0 - v2_upper = 0.0 - v1_lower = 0.0 - v2_lower = 0.0 - - # Left side of discontinuity - IDs = [1, 2, 5, 6, 9, 10, 13, 14] - if element_id in IDs - H_upper = 1.0 - H_lower = 0.6 - b = 0.0 - # Right side of discontinuity - else - H_upper = 0.9 - H_lower = 0.5 - b = 0.1 - end - - return prim2cons(SVector(H_upper, v1_upper, v2_upper, H_lower, v1_lower, v2_lower, b), equations) + # Constant values + v1_upper = 0.0 + v2_upper = 0.0 + v1_lower = 0.0 + v2_lower = 0.0 + + # Left side of discontinuity + IDs = [1, 2, 5, 6, 9, 10, 13, 14] + if element_id in IDs + H_upper = 1.0 + H_lower = 0.6 + b = 0.0 + # Right side of discontinuity + else + H_upper = 0.9 + H_lower = 0.5 + b = 0.1 + end + + return prim2cons(SVector(H_upper, v1_upper, v2_upper, H_lower, v1_lower, v2_lower, b), + equations) end # point to the data we want to augment u = Trixi.wrap_array(ode.u0, semi) # reset the initial condition for element in eachelement(semi.solver, semi.cache) - for j in eachnode(semi.solver), i in eachnode(semi.solver) - x_node = Trixi.get_node_coords(semi.cache.elements.node_coordinates, equations, semi.solver, i, j, element) - u_node = initial_condition_discontinuous_dam_break(x_node, first(tspan), element, equations) - Trixi.set_node_vars!(u, u_node, equations, semi.solver, i, j, element) - end + for j in eachnode(semi.solver), i in eachnode(semi.solver) + x_node = Trixi.get_node_coords(semi.cache.elements.node_coordinates, equations, + semi.solver, i, j, element) + u_node = initial_condition_discontinuous_dam_break(x_node, first(tspan), element, + equations) + Trixi.set_node_vars!(u, u_node, equations, semi.solver, i, j, element) + end end - ############################################################################### # Callbacks summary_callback = SummaryCallback() analysis_interval = 500 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval,save_analysis=false, - extra_analysis_integrals=(energy_total, energy_kinetic, energy_internal,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = false, + extra_analysis_integrals = (energy_total, + energy_kinetic, + energy_internal)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=500, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 500, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) @@ -138,7 +145,7 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_well_balanced.jl b/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_well_balanced.jl index 40bc9f2ab42..6a727df2502 100644 --- a/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_well_balanced.jl +++ b/examples/unstructured_2d_dgsem/elixir_shallowwater_twolayer_well_balanced.jl @@ -7,22 +7,25 @@ using Trixi # Semidiscretization of the two-layer shallow water equations with a discontinuous bottom # topography to test well-balancedness -equations = ShallowWaterTwoLayerEquations2D(gravity_constant=1.0, H0=0.6, rho_upper=0.9, rho_lower=1.0) +equations = ShallowWaterTwoLayerEquations2D(gravity_constant = 1.0, H0 = 0.6, + rho_upper = 0.9, rho_lower = 1.0) # An initial condition with constant total water height, zero velocities and a bottom topography to # test well-balancedness function initial_condition_well_balanced(x, t, equations::ShallowWaterTwoLayerEquations2D) - H_lower = 0.5 - H_upper = 0.6 - v1_upper = 0.0 - v2_upper = 0.0 - v1_lower = 0.0 - v2_lower = 0.0 - - # Bottom Topography - b = (((x[1] - 0.5)^2 + (x[2] - 0.5)^2) < 0.04 ? 0.2 * (cos(4 * pi * sqrt((x[1] - 0.5)^2 + (x[2] + - -0.5)^2)) + 1) : 0.0) - return prim2cons(SVector(H_upper, v1_upper, v2_upper, H_lower, v1_lower, v2_lower, b), equations) + H_lower = 0.5 + H_upper = 0.6 + v1_upper = 0.0 + v2_upper = 0.0 + v1_lower = 0.0 + v2_lower = 0.0 + + # Bottom Topography + b = (((x[1] - 0.5)^2 + (x[2] - 0.5)^2) < 0.04 ? + 0.2 * (cos(4 * pi * sqrt((x[1] - 0.5)^2 + (x[2] + + -0.5)^2)) + 1) : 0.0) + return prim2cons(SVector(H_upper, v1_upper, v2_upper, H_lower, v1_lower, v2_lower, b), + equations) end initial_condition = initial_condition_well_balanced @@ -30,21 +33,22 @@ initial_condition = initial_condition_well_balanced ############################################################################### # Get the DG approximation space -volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -surface_flux = (flux_es_fjordholm_etal, flux_nonconservative_fjordholm_etal) -solver = DGSEM(polydeg=6, surface_flux=surface_flux, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +volume_flux = (flux_wintermeyer_etal, flux_nonconservative_ersing_etal) +surface_flux = (flux_es_ersing_etal, flux_nonconservative_ersing_etal) +solver = DGSEM(polydeg = 6, surface_flux = surface_flux, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### # This setup is for the curved, split form well-balancedness testing # Get the unstructured quad mesh from a file (downloads the file if not available locally) default_mesh_file = joinpath(@__DIR__, "mesh_alfven_wave_with_twist_and_flip.mesh") -isfile(default_mesh_file) || download("https://gist.githubusercontent.com/andrewwinters5000/8f8cd23df27fcd494553f2a89f3c1ba4/raw/85e3c8d976bbe57ca3d559d653087b0889535295/mesh_alfven_wave_with_twist_and_flip.mesh", - default_mesh_file) +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/8f8cd23df27fcd494553f2a89f3c1ba4/raw/85e3c8d976bbe57ca3d559d653087b0889535295/mesh_alfven_wave_with_twist_and_flip.mesh", + default_mesh_file) mesh_file = default_mesh_file -mesh = UnstructuredMesh2D(mesh_file, periodicity=true) +mesh = UnstructuredMesh2D(mesh_file, periodicity = true) # Create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -58,16 +62,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(lake_at_rest_error,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (lake_at_rest_error,)) -stepsize_callback = StepsizeCallback(cfl=1.0) +stepsize_callback = StepsizeCallback(cfl = 1.0) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) @@ -75,7 +79,7 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/unstructured_2d_dgsem/elixir_shallowwater_wall_bc_shockcapturing.jl b/examples/unstructured_2d_dgsem/elixir_shallowwater_wall_bc_shockcapturing.jl index 4700724c520..76b9642d595 100644 --- a/examples/unstructured_2d_dgsem/elixir_shallowwater_wall_bc_shockcapturing.jl +++ b/examples/unstructured_2d_dgsem/elixir_shallowwater_wall_bc_shockcapturing.jl @@ -7,63 +7,66 @@ using Trixi # semidiscretization of the shallow water equations with a continuous # bottom topography function -equations = ShallowWaterEquations2D(gravity_constant=9.812, H0=2.0) +equations = ShallowWaterEquations2D(gravity_constant = 9.812, H0 = 2.0) function initial_condition_stone_throw(x, t, equations::ShallowWaterEquations2D) - # Set up polar coordinates - inicenter = SVector(0.15, 0.15) - x_norm = x[1] - inicenter[1] - y_norm = x[2] - inicenter[2] - r = sqrt(x_norm^2 + y_norm^2) - - # Calculate primitive variables - H = equations.H0 - v1 = r < 0.6 ? 2.0 : 0.0 - v2 = r < 0.6 ? -2.0 : 0.0 - # bottom topography taken from Pond.control in [HOHQMesh](https://github.com/trixi-framework/HOHQMesh) - x1, x2 = x - b = ( 1.5 / exp( 0.5 * ((x1 - 1.0)^2 + (x2 - 1.0)^2) ) - + 0.75 / exp( 0.5 * ((x1 + 1.0)^2 + (x2 + 1.0)^2) ) ) - - return prim2cons(SVector(H, v1, v2, b), equations) + # Set up polar coordinates + inicenter = SVector(0.15, 0.15) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + + # Calculate primitive variables + H = equations.H0 + v1 = r < 0.6 ? 2.0 : 0.0 + v2 = r < 0.6 ? -2.0 : 0.0 + # bottom topography taken from Pond.control in [HOHQMesh](https://github.com/trixi-framework/HOHQMesh) + x1, x2 = x + b = (1.5 / exp(0.5 * ((x1 - 1.0)^2 + (x2 - 1.0)^2)) + + 0.75 / exp(0.5 * ((x1 + 1.0)^2 + (x2 + 1.0)^2))) + + return prim2cons(SVector(H, v1, v2, b), equations) end initial_condition = initial_condition_stone_throw -boundary_condition = Dict( :OuterCircle => boundary_condition_slip_wall ) +boundary_condition = Dict(:OuterCircle => boundary_condition_slip_wall) ############################################################################### # Get the DG approximation space -surface_flux=(FluxHydrostaticReconstruction(flux_hll, hydrostatic_reconstruction_audusse_etal), - flux_nonconservative_audusse_etal) +surface_flux = (FluxHydrostaticReconstruction(flux_hll, + hydrostatic_reconstruction_audusse_etal), + flux_nonconservative_audusse_etal) volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) polydeg = 6 basis = LobattoLegendreBasis(polydeg) indicator_sc = IndicatorHennemannGassner(equations, basis, - alpha_max=0.5, - alpha_min=0.001, - alpha_smooth=true, - variable=Trixi.waterheight) + alpha_max = 0.5, + alpha_min = 0.001, + alpha_smooth = true, + variable = Trixi.waterheight) volume_integral = VolumeIntegralShockCapturingHG(indicator_sc; - volume_flux_dg=volume_flux, - volume_flux_fv=surface_flux) + volume_flux_dg = volume_flux, + volume_flux_fv = surface_flux) -solver = DGSEM(polydeg=polydeg, surface_flux=surface_flux, volume_integral=volume_integral) +solver = DGSEM(polydeg = polydeg, surface_flux = surface_flux, + volume_integral = volume_integral) ############################################################################### # Get the unstructured quad mesh from a file (downloads the file if not available locally) default_mesh_file = joinpath(@__DIR__, "mesh_outer_circle.mesh") -isfile(default_mesh_file) || download("https://gist.githubusercontent.com/andrewwinters5000/9beddd9cd00e2a0a15865129eeb24928/raw/be71e67fa48bc4e1e97f5f6cd77c3ed34c6ba9be/mesh_outer_circle.mesh", - default_mesh_file) +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/9beddd9cd00e2a0a15865129eeb24928/raw/be71e67fa48bc4e1e97f5f6cd77c3ed34c6ba9be/mesh_outer_circle.mesh", + default_mesh_file) mesh_file = default_mesh_file mesh = UnstructuredMesh2D(mesh_file) # Create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - boundary_conditions=boundary_condition) + boundary_conditions = boundary_condition) ############################################################################### # ODE solvers, callbacks, etc. @@ -74,15 +77,16 @@ ode = semidiscretize(semi, tspan) summary_callback = SummaryCallback() analysis_interval = 100 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=false, - extra_analysis_integrals=(energy_kinetic, - energy_internal)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = false, + extra_analysis_integrals = (energy_kinetic, + energy_internal)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=100, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution) @@ -90,6 +94,6 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav # run the simulation # use a Runge-Kutta method with automatic (error based) time step size control -sol = solve(ode, RDPK3SpFSAL49(); abstol=1.0e-8, reltol=1.0e-8, - ode_default_options()..., callback=callbacks); +sol = solve(ode, RDPK3SpFSAL49(); abstol = 1.0e-8, reltol = 1.0e-8, + ode_default_options()..., callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/unstructured_2d_dgsem/elixir_shallowwater_well_balanced.jl b/examples/unstructured_2d_dgsem/elixir_shallowwater_well_balanced.jl index 645f985d10d..bf4d0be682a 100644 --- a/examples/unstructured_2d_dgsem/elixir_shallowwater_well_balanced.jl +++ b/examples/unstructured_2d_dgsem/elixir_shallowwater_well_balanced.jl @@ -7,21 +7,21 @@ using Trixi # semidiscretization of the shallow water equations with a discontinuous # bottom topography function (set in the initial conditions) -equations = ShallowWaterEquations2D(gravity_constant=9.81, H0=3.0) +equations = ShallowWaterEquations2D(gravity_constant = 9.81, H0 = 3.0) # An initial condition with constant total water height and zero velocities to test well-balancedness. # Note, this routine is used to compute errors in the analysis callback but the initialization is # overwritten by `initial_condition_discontinuous_well_balancedness` below. function initial_condition_well_balancedness(x, t, equations::ShallowWaterEquations2D) - # Set the background values - H = equations.H0 - v1 = 0.0 - v2 = 0.0 - # bottom topography taken from Pond.control in [HOHQMesh](https://github.com/trixi-framework/HOHQMesh) - x1, x2 = x - b = ( 1.5 / exp( 0.5 * ((x1 - 1.0)^2 + (x2 - 1.0)^2) ) - + 0.75 / exp( 0.5 * ((x1 + 1.0)^2 + (x2 + 1.0)^2) ) ) - return prim2cons(SVector(H, v1, v2, b), equations) + # Set the background values + H = equations.H0 + v1 = 0.0 + v2 = 0.0 + # bottom topography taken from Pond.control in [HOHQMesh](https://github.com/trixi-framework/HOHQMesh) + x1, x2 = x + b = (1.5 / exp(0.5 * ((x1 - 1.0)^2 + (x2 - 1.0)^2)) + + 0.75 / exp(0.5 * ((x1 + 1.0)^2 + (x2 + 1.0)^2))) + return prim2cons(SVector(H, v1, v2, b), equations) end initial_condition = initial_condition_well_balancedness @@ -30,20 +30,21 @@ initial_condition = initial_condition_well_balancedness # Get the DG approximation space volume_flux = (flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal) -surface_flux=(flux_fjordholm_etal, flux_nonconservative_fjordholm_etal) -solver = DGSEM(polydeg=6, surface_flux=surface_flux, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) +surface_flux = (flux_fjordholm_etal, flux_nonconservative_fjordholm_etal) +solver = DGSEM(polydeg = 6, surface_flux = surface_flux, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) ############################################################################### # This setup is for the curved, split form well-balancedness testing # Get the unstructured quad mesh from a file (downloads the file if not available locally) default_mesh_file = joinpath(@__DIR__, "mesh_alfven_wave_with_twist_and_flip.mesh") -isfile(default_mesh_file) || download("https://gist.githubusercontent.com/andrewwinters5000/8f8cd23df27fcd494553f2a89f3c1ba4/raw/85e3c8d976bbe57ca3d559d653087b0889535295/mesh_alfven_wave_with_twist_and_flip.mesh", - default_mesh_file) +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/8f8cd23df27fcd494553f2a89f3c1ba4/raw/85e3c8d976bbe57ca3d559d653087b0889535295/mesh_alfven_wave_with_twist_and_flip.mesh", + default_mesh_file) mesh_file = default_mesh_file -mesh = UnstructuredMesh2D(mesh_file, periodicity=true) +mesh = UnstructuredMesh2D(mesh_file, periodicity = true) # Create the semi discretization object semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) @@ -64,30 +65,33 @@ ode = semidiscretize(semi, tspan) # In contrast to the usual signature of initial conditions, this one get passed the # `element_id` explicitly. In particular, this initial conditions works as intended # only for the specific mesh loaded above! -function initial_condition_discontinuous_well_balancedness(x, t, element_id, equations::ShallowWaterEquations2D) - # Set the background values - H = equations.H0 - v1 = 0.0 - v2 = 0.0 - b = 0.0 - - # Setup a discontinuous bottom topography using the element id number - if element_id == 7 - b = 2.0 + 0.5 * sin(2.0 * pi * x[1]) + 0.5 * cos(2.0 * pi * x[2]) - end - - return prim2cons(SVector(H, v1, v2, b), equations) +function initial_condition_discontinuous_well_balancedness(x, t, element_id, + equations::ShallowWaterEquations2D) + # Set the background values + H = equations.H0 + v1 = 0.0 + v2 = 0.0 + b = 0.0 + + # Setup a discontinuous bottom topography using the element id number + if element_id == 7 + b = 2.0 + 0.5 * sin(2.0 * pi * x[1]) + 0.5 * cos(2.0 * pi * x[2]) + end + + return prim2cons(SVector(H, v1, v2, b), equations) end # point to the data we want to augment u = Trixi.wrap_array(ode.u0, semi) # reset the initial condition for element in eachelement(semi.solver, semi.cache) - for j in eachnode(semi.solver), i in eachnode(semi.solver) - x_node = Trixi.get_node_coords(semi.cache.elements.node_coordinates, equations, semi.solver, i, j, element) - u_node = initial_condition_discontinuous_well_balancedness(x_node, first(tspan), element, equations) - Trixi.set_node_vars!(u, u_node, equations, semi.solver, i, j, element) - end + for j in eachnode(semi.solver), i in eachnode(semi.solver) + x_node = Trixi.get_node_coords(semi.cache.elements.node_coordinates, equations, + semi.solver, i, j, element) + u_node = initial_condition_discontinuous_well_balancedness(x_node, first(tspan), + element, equations) + Trixi.set_node_vars!(u, u_node, equations, semi.solver, i, j, element) + end end ############################################################################### @@ -96,16 +100,16 @@ end summary_callback = SummaryCallback() analysis_interval = 1000 -analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(lake_at_rest_error,)) +analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + extra_analysis_integrals = (lake_at_rest_error,)) -alive_callback = AliveCallback(analysis_interval=analysis_interval) +alive_callback = AliveCallback(analysis_interval = analysis_interval) -save_solution = SaveSolutionCallback(interval=1000, - save_initial_solution=true, - save_final_solution=true) +save_solution = SaveSolutionCallback(interval = 1000, + save_initial_solution = true, + save_final_solution = true) -stepsize_callback = StepsizeCallback(cfl=3.0) +stepsize_callback = StepsizeCallback(cfl = 3.0) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, save_solution, stepsize_callback) @@ -113,7 +117,7 @@ callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, sav ############################################################################### # run the simulation -sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=1.0, # solve needs some value here but it will be overwritten by the stepsize_callback - save_everystep=false, callback=callbacks); +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); summary_callback() # print the timer summary diff --git a/examples/unstructured_2d_fdsbp/elixir_advection_basic.jl b/examples/unstructured_2d_fdsbp/elixir_advection_basic.jl new file mode 100644 index 00000000000..c181203e7a4 --- /dev/null +++ b/examples/unstructured_2d_fdsbp/elixir_advection_basic.jl @@ -0,0 +1,69 @@ + +using Downloads: download +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the linear advection equation + +advection_velocity = (0.2, -0.7) +equations = LinearScalarAdvectionEquation2D(advection_velocity) + +############################################################################### +# Get the FDSBP approximation operator + +D_SBP = derivative_operator(SummationByPartsOperators.MattssonAlmquistVanDerWeide2018Accurate(), + derivative_order = 1, accuracy_order = 4, + xmin = -1.0, xmax = 1.0, N = 15) +solver = FDSBP(D_SBP, + surface_integral = SurfaceIntegralStrongForm(flux_lax_friedrichs), + volume_integral = VolumeIntegralStrongForm()) + +############################################################################### +# Get the curved quad mesh from a file (downloads the file if not available locally) + +default_mesh_file = joinpath(@__DIR__, "mesh_periodic_square_with_twist.mesh") +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/12ce661d7c354c3d94c74b964b0f1c96/raw/8275b9a60c6e7ebbdea5fc4b4f091c47af3d5273/mesh_periodic_square_with_twist.mesh", + default_mesh_file) +mesh_file = default_mesh_file + +mesh = UnstructuredMesh2D(mesh_file, periodicity = true) + +############################################################################### +# create the semidiscretization object + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition_convergence_test, + solver) + +############################################################################### +# ODE solvers, callbacks etc. + +# Create ODE problem with time span from 0.0 to 1.0 +ode = semidiscretize(semi, (0.0, 1.0)) + +# At the beginning of the main loop, the SummaryCallback prints a summary of the simulation setup +# and resets the timers +summary_callback = SummaryCallback() + +# The AnalysisCallback allows to analyse the solution in regular intervals and prints the results +analysis_callback = AnalysisCallback(semi, interval = 100) + +# The SaveSolutionCallback allows to save the solution to a file in regular intervals +save_solution = SaveSolutionCallback(interval = 100, + solution_variables = cons2prim) + +# The StepsizeCallback handles the re-calculation of the maximum Δt after each time step +stepsize_callback = StepsizeCallback(cfl = 1.6) + +# Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver +callbacks = CallbackSet(summary_callback, analysis_callback, save_solution, + stepsize_callback) + +############################################################################### +# run the simulation + +sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 1.0, # solve needs some value here but it will be overwritten by the stepsize_callback + save_everystep = false, callback = callbacks); +summary_callback() # print the timer summary diff --git a/examples/unstructured_2d_fdsbp/elixir_euler_free_stream.jl b/examples/unstructured_2d_fdsbp/elixir_euler_free_stream.jl new file mode 100644 index 00000000000..7ada50c0c65 --- /dev/null +++ b/examples/unstructured_2d_fdsbp/elixir_euler_free_stream.jl @@ -0,0 +1,77 @@ + +using Downloads: download +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations + +equations = CompressibleEulerEquations2D(1.4) + +# Free-stream initial condition +initial_condition = initial_condition_constant + +# Boundary conditions for free-stream testing +boundary_condition_free_stream = BoundaryConditionDirichlet(initial_condition) +boundary_conditions = Dict(:Body => boundary_condition_free_stream, + :Button1 => boundary_condition_free_stream, + :Button2 => boundary_condition_free_stream, + :Eye1 => boundary_condition_free_stream, + :Eye2 => boundary_condition_free_stream, + :Smile => boundary_condition_free_stream, + :Bowtie => boundary_condition_free_stream) + +############################################################################### +# Get the FDSBP approximation space + +D_SBP = derivative_operator(SummationByPartsOperators.MattssonAlmquistVanDerWeide2018Accurate(), + derivative_order = 1, accuracy_order = 4, + xmin = -1.0, xmax = 1.0, N = 12) +solver = FDSBP(D_SBP, + surface_integral = SurfaceIntegralStrongForm(flux_hll), + volume_integral = VolumeIntegralStrongForm()) + +############################################################################### +# Get the curved quad mesh from a file (downloads the file if not available locally) + +default_mesh_file = joinpath(@__DIR__, "mesh_gingerbread_man.mesh") +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/2c6440b5f8a57db131061ad7aa78ee2b/raw/1f89fdf2c874ff678c78afb6fe8dc784bdfd421f/mesh_gingerbread_man.mesh", + default_mesh_file) +mesh_file = default_mesh_file + +mesh = UnstructuredMesh2D(mesh_file) + +############################################################################### +# create the semi discretization object + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + boundary_conditions = boundary_conditions) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 5.0) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true) + +callbacks = CallbackSet(summary_callback, analysis_callback, + alive_callback, save_solution) + +############################################################################### +# run the simulation + +# set small tolerances for the free-stream preservation test +sol = solve(ode, SSPRK43(), abstol = 1.0e-12, reltol = 1.0e-12, + save_everystep = false, callback = callbacks) +summary_callback() # print the timer summary diff --git a/examples/unstructured_2d_fdsbp/elixir_euler_source_terms.jl b/examples/unstructured_2d_fdsbp/elixir_euler_source_terms.jl new file mode 100644 index 00000000000..edcd221bf59 --- /dev/null +++ b/examples/unstructured_2d_fdsbp/elixir_euler_source_terms.jl @@ -0,0 +1,65 @@ + +using Downloads: download +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the compressible Euler equations + +equations = CompressibleEulerEquations2D(1.4) + +initial_condition = initial_condition_convergence_test + +############################################################################### +# Get the FDSBP approximation operator + +D_SBP = derivative_operator(SummationByPartsOperators.MattssonNordström2004(), + derivative_order = 1, accuracy_order = 4, + xmin = -1.0, xmax = 1.0, N = 10) +solver = FDSBP(D_SBP, + surface_integral = SurfaceIntegralStrongForm(flux_lax_friedrichs), + volume_integral = VolumeIntegralStrongForm()) + +############################################################################### +# Get the curved quad mesh from a file (downloads the file if not available locally) + +default_mesh_file = joinpath(@__DIR__, "mesh_periodic_square_with_twist.mesh") +isfile(default_mesh_file) || + download("https://gist.githubusercontent.com/andrewwinters5000/12ce661d7c354c3d94c74b964b0f1c96/raw/8275b9a60c6e7ebbdea5fc4b4f091c47af3d5273/mesh_periodic_square_with_twist.mesh", + default_mesh_file) +mesh_file = default_mesh_file + +mesh = UnstructuredMesh2D(mesh_file, periodicity = true) + +############################################################################### +# create the semi discretization object + +semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, + source_terms = source_terms_convergence_test) + +############################################################################### +# ODE solvers, callbacks etc. + +tspan = (0.0, 1.0) +ode = semidiscretize(semi, tspan) + +summary_callback = SummaryCallback() + +analysis_interval = 100 +analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + +alive_callback = AliveCallback(analysis_interval = analysis_interval) + +save_solution = SaveSolutionCallback(interval = 100, + save_initial_solution = true, + save_final_solution = true) + +callbacks = CallbackSet(summary_callback, analysis_callback, + alive_callback, save_solution) + +############################################################################### +# run the simulation + +sol = solve(ode, SSPRK43(), abstol = 1.0e-9, reltol = 1.0e-9, + save_everystep = false, callback = callbacks) +summary_callback() # print the timer summary diff --git a/ext/TrixiMakieExt.jl b/ext/TrixiMakieExt.jl index 8cd7576a6e5..301a7656da9 100644 --- a/ext/TrixiMakieExt.jl +++ b/ext/TrixiMakieExt.jl @@ -29,9 +29,7 @@ import Trixi: iplot, iplot! # First some utilities # Given a reference plotting triangulation, this function generates a plotting triangulation for # the entire global mesh. The output can be plotted using `Makie.mesh`. -function global_plotting_triangulation_makie(pds::PlotDataSeries{ - <:PlotData2DTriangulated - }; +function global_plotting_triangulation_makie(pds::PlotDataSeries{<:PlotData2DTriangulated}; set_z_coordinate_zero = false) @unpack variable_id = pds pd = pds.plot_data @@ -61,8 +59,7 @@ end # Returns a list of `Makie.Point`s which can be used to plot the mesh, or a solution "wireframe" # (e.g., a plot of the mesh lines but with the z-coordinate equal to the value of the solution). -function convert_PlotData2D_to_mesh_Points(pds::PlotDataSeries{<:PlotData2DTriangulated - }; +function convert_PlotData2D_to_mesh_Points(pds::PlotDataSeries{<:PlotData2DTriangulated}; set_z_coordinate_zero = false) @unpack variable_id = pds pd = pds.plot_data diff --git a/src/Trixi.jl b/src/Trixi.jl index ec4d20558e5..e18b2f6415c 100644 --- a/src/Trixi.jl +++ b/src/Trixi.jl @@ -37,7 +37,8 @@ using SciMLBase: CallbackSet, DiscreteCallback, import SciMLBase: get_du, get_tmp_cache, u_modified!, AbstractODEIntegrator, init, step!, check_error, get_proposed_dt, set_proposed_dt!, - terminate!, remake + terminate!, remake, add_tstop!, has_tstop, first_tstop + using CodeTracking: CodeTracking using ConstructionBase: ConstructionBase using DiffEqCallbacks: PeriodicCallback, PeriodicCallbackAffect @@ -70,6 +71,7 @@ using TriplotBase: TriplotBase using TriplotRecipes: DGTriPseudocolor @reexport using SimpleUnPack: @unpack using SimpleUnPack: @pack! +using DataStructures: BinaryHeap, FasterForward, extract_all! # finite difference SBP operators using SummationByPartsOperators: AbstractDerivativeOperator, @@ -139,6 +141,7 @@ export AcousticPerturbationEquations2D, CompressibleEulerEquations3D, CompressibleEulerMulticomponentEquations1D, CompressibleEulerMulticomponentEquations2D, + CompressibleEulerEquationsQuasi1D, IdealGlmMhdEquations1D, IdealGlmMhdEquations2D, IdealGlmMhdEquations3D, IdealGlmMhdMulticomponentEquations1D, IdealGlmMhdMulticomponentEquations2D, HyperbolicDiffusionEquations1D, HyperbolicDiffusionEquations2D, @@ -149,21 +152,25 @@ export AcousticPerturbationEquations2D, LatticeBoltzmannEquations2D, LatticeBoltzmannEquations3D, ShallowWaterEquations1D, ShallowWaterEquations2D, ShallowWaterTwoLayerEquations1D, ShallowWaterTwoLayerEquations2D, - LinearizedEulerEquations2D + ShallowWaterEquationsQuasi1D, + LinearizedEulerEquations2D, + PolytropicEulerEquations2D -export LaplaceDiffusion1D, LaplaceDiffusion2D, +export LaplaceDiffusion1D, LaplaceDiffusion2D, LaplaceDiffusion3D, CompressibleNavierStokesDiffusion1D, CompressibleNavierStokesDiffusion2D, CompressibleNavierStokesDiffusion3D -export GradientVariablesPrimitive, GradientVariablesEntropy +export GradientVariablesConservative, GradientVariablesPrimitive, GradientVariablesEntropy export flux, flux_central, flux_lax_friedrichs, flux_hll, flux_hllc, flux_hlle, flux_godunov, flux_chandrashekar, flux_ranocha, flux_derigs_etal, flux_hindenlang_gassner, - flux_nonconservative_powell, + flux_nonconservative_powell, flux_nonconservative_powell_local_symmetric, flux_kennedy_gruber, flux_shima_etal, flux_ec, - flux_fjordholm_etal, flux_nonconservative_fjordholm_etal, flux_es_fjordholm_etal, + flux_fjordholm_etal, flux_nonconservative_fjordholm_etal, flux_wintermeyer_etal, flux_nonconservative_wintermeyer_etal, + flux_es_ersing_etal, flux_nonconservative_ersing_etal, + flux_chan_etal, flux_nonconservative_chan_etal, flux_winters_etal, hydrostatic_reconstruction_audusse_etal, flux_nonconservative_audusse_etal, # TODO: TrixiShallowWater: move anything with "chen_noelle" to new file hydrostatic_reconstruction_chen_noelle, flux_nonconservative_chen_noelle, @@ -229,7 +236,7 @@ export DG, SurfaceIntegralUpwind, MortarL2 -export VolumeIntegralSubcellLimiting, +export VolumeIntegralSubcellLimiting, BoundsCheckCallback, SubcellLimiterIDP, SubcellLimiterIDPCorrection export nelements, nnodes, nvariables, @@ -253,12 +260,11 @@ export SummaryCallback, SteadyStateCallback, AnalysisCallback, AliveCallback, GlmSpeedCallback, LBMCollisionCallback, EulerAcousticsCouplingCallback, TrivialCallback, AnalysisCallbackCoupled -export load_mesh, load_time, load_timestep, load_dt +export load_mesh, load_time, load_timestep, load_timestep!, load_dt, + load_adaptive_time_integrator! export ControllerThreeLevel, ControllerThreeLevelCombined, - IndicatorLöhner, IndicatorLoehner, IndicatorMax, - IndicatorNeuralNetwork, NeuralNetworkPerssonPeraire, NeuralNetworkRayHesthaven, - NeuralNetworkCNN + IndicatorLöhner, IndicatorLoehner, IndicatorMax # TODO: TrixiShallowWater: move new limiter export PositivityPreservingLimiterZhangShu, PositivityPreservingLimiterShallowWater @@ -299,10 +305,6 @@ function __init__() end end - @require Flux="587475ba-b771-5e3f-ad9e-33799f191a9c" begin - using .Flux: params - end - # FIXME upstream. This is a hacky workaround for # https://github.com/trixi-framework/Trixi.jl/issues/628 # https://github.com/trixi-framework/Trixi.jl/issues/1185 diff --git a/src/auxiliary/math.jl b/src/auxiliary/math.jl index 4ecf7dd3fcc..38ea0bda8c8 100644 --- a/src/auxiliary/math.jl +++ b/src/auxiliary/math.jl @@ -211,4 +211,71 @@ Return `x` if `x` is negative, else zero. In other words, return @inline function negative_part(x) return min(x, zero(x)) end + +""" + 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 +- 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](https://doi.org/10.1007/s10543-019-00789-w) +- Agner Fog. + Lists of instruction latencies, throughputs and micro-operation breakdowns + for Intel, AMD, and VIA CPUs. + [https://www.agner.org/optimize/instruction_tables.pdf](https://www.agner.org/optimize/instruction_tables.pdf) +""" +@inline function stolarsky_mean(x, y, gamma) + epsilon_f2 = 1.0e-4 + f2 = (x * (x - 2 * y) + y * y) / (x * (x + 2 * y) + y * y) # f2 = f^2 + if f2 < epsilon_f2 + # convenience coefficients + c1 = (1 / 3) * (gamma - 2) + c2 = -(1 / 15) * (gamma + 1) * (gamma - 3) * c1 + c3 = -(1 / 21) * (2 * gamma * (gamma - 2) - 9) * c2 + return 0.5 * (x + y) * @evalpoly(f2, 1, c1, c2, c3) + else + return (gamma - 1) / gamma * (y^gamma - x^gamma) / + (y^(gamma - 1) - x^(gamma - 1)) + end +end end # @muladd diff --git a/src/auxiliary/p4est.jl b/src/auxiliary/p4est.jl index 968af339cbd..0b826254129 100644 --- a/src/auxiliary/p4est.jl +++ b/src/auxiliary/p4est.jl @@ -13,14 +13,20 @@ This function will check if `p4est` is already initialized and if yes, do nothing, thus it is safe to call it multiple times. """ function init_p4est() - p4est_package_id = P4est.package_id() - if p4est_package_id >= 0 - return nothing + # Only initialize p4est if P4est.jl can be used + if P4est.preferences_set_correctly() + p4est_package_id = P4est.package_id() + if p4est_package_id >= 0 + return nothing + end + + # Initialize `p4est` with log level ERROR to prevent a lot of output in AMR simulations + p4est_init(C_NULL, SC_LP_ERROR) + else + @warn "Preferences for P4est.jl are not set correctly. Until fixed, using `P4estMesh` will result in a crash. " * + "See also https://trixi-framework.github.io/Trixi.jl/stable/parallelization/#parallel_system_MPI" end - # Initialize `p4est` with log level ERROR to prevent a lot of output in AMR simulations - p4est_init(C_NULL, SC_LP_ERROR) - return nothing end diff --git a/src/auxiliary/precompile.jl b/src/auxiliary/precompile.jl index 7ed0e26b5ef..9cec502f6cb 100644 --- a/src/auxiliary/precompile.jl +++ b/src/auxiliary/precompile.jl @@ -186,8 +186,7 @@ function _precompile_manual_() Matrix{RealT}, # DerivativeMatrix #StaticArrays.SArray{Tuple{nnodes_,nnodes_},RealT,2,nnodes_^2}, - Matrix{RealT} - } + Matrix{RealT}} end function mortar_type_dgsem(RealT, nnodes_) @@ -197,8 +196,7 @@ function _precompile_manual_() Matrix{RealT}, # ReverseMatrix # StaticArrays.SArray{Tuple{nnodes_,nnodes_},RealT,2,nnodes_^2}, - Matrix{RealT} - } + Matrix{RealT}} end function analyzer_type_dgsem(RealT, nnodes_) @@ -208,8 +206,7 @@ function _precompile_manual_() # VectorT StaticArrays.SVector{nnodes_analysis, RealT}, # Vandermonde - Array{RealT, 2} - } + Array{RealT, 2}} end function adaptor_type_dgsem(RealT, nnodes_) @@ -242,8 +239,8 @@ function _precompile_manual_() @assert Base.precompile(Tuple{Core.kwftype(typeof(Trixi.Type)), NamedTuple{(:initial_refinement_level, :n_cells_max), Tuple{Int, Int}}, Type{TreeMesh}, - Tuple{RealT, RealT, RealT}, Tuple{RealT, RealT, RealT - }}) + Tuple{RealT, RealT, RealT}, + Tuple{RealT, RealT, RealT}}) end for TreeType in (SerialTree, ParallelTree), NDIMS in 1:3 @assert Base.precompile(Tuple{typeof(Trixi.initialize!), @@ -308,8 +305,8 @@ function _precompile_manual_() Base.precompile(Tuple{Type{LobattoLegendreBasis}, Int}) for RealT in (Float64,) Base.precompile(Tuple{Type{LobattoLegendreBasis}, RealT, Int}) - @assert Base.precompile(Tuple{typeof(Trixi.calc_dhat), Vector{RealT}, Vector{RealT} - }) + @assert Base.precompile(Tuple{typeof(Trixi.calc_dhat), Vector{RealT}, + Vector{RealT}}) @assert Base.precompile(Tuple{typeof(Trixi.calc_dsplit), Vector{RealT}, Vector{RealT}}) @assert Base.precompile(Tuple{typeof(Trixi.polynomial_derivative_matrix), @@ -332,10 +329,10 @@ function _precompile_manual_() @assert Base.precompile(Tuple{typeof(Trixi.calc_forward_lower), Int}) @assert Base.precompile(Tuple{typeof(Trixi.calc_reverse_upper), Int, Val{:gauss}}) @assert Base.precompile(Tuple{typeof(Trixi.calc_reverse_lower), Int, Val{:gauss}}) - @assert Base.precompile(Tuple{typeof(Trixi.calc_reverse_upper), Int, Val{:gauss_lobatto - }}) - @assert Base.precompile(Tuple{typeof(Trixi.calc_reverse_lower), Int, Val{:gauss_lobatto - }}) + @assert Base.precompile(Tuple{typeof(Trixi.calc_reverse_upper), Int, + Val{:gauss_lobatto}}) + @assert Base.precompile(Tuple{typeof(Trixi.calc_reverse_lower), Int, + Val{:gauss_lobatto}}) # Constructors: mortars, analyzers, adaptors for RealT in (Float64,), polydeg in 1:7 @@ -362,14 +359,12 @@ function _precompile_manual_() NamedTuple{(:interval, :save_final_restart), Tuple{Int, Bool}}, Type{SaveRestartCallback}}) @assert Base.precompile(Tuple{Core.kwftype(typeof(Trixi.Type)), - NamedTuple{ - (:interval, :save_initial_solution, + NamedTuple{(:interval, :save_initial_solution, :save_final_solution, :solution_variables), Tuple{Int, Bool, Bool, typeof(cons2cons)}}, Type{SaveSolutionCallback}}) @assert Base.precompile(Tuple{Core.kwftype(typeof(Trixi.Type)), - NamedTuple{ - (:interval, :save_initial_solution, + NamedTuple{(:interval, :save_initial_solution, :save_final_solution, :solution_variables), Tuple{Int, Bool, Bool, typeof(cons2prim)}}, Type{SaveSolutionCallback}}) @@ -385,8 +380,7 @@ function _precompile_manual_() # end # end @assert Base.precompile(Tuple{typeof(SummaryCallback)}) - @assert Base.precompile(Tuple{ - DiscreteCallback{typeof(Trixi.summary_callback), + @assert Base.precompile(Tuple{DiscreteCallback{typeof(Trixi.summary_callback), typeof(Trixi.summary_callback), typeof(Trixi.initialize_summary_callback), typeof(SciMLBase.FINALIZE_DEFAULT)}}) @@ -419,8 +413,8 @@ function _precompile_manual_() Trixi.ElementContainer2D{RealT, uEltype}}) @assert Base.precompile(Tuple{typeof(Trixi.init_mortars), Array{Int, 1}, TreeMesh{2, Trixi.SerialTree{2}}, - Trixi.ElementContainer2D{RealT, uEltype}, mortar_type - }) + Trixi.ElementContainer2D{RealT, uEltype}, + mortar_type}) @assert Base.precompile(Tuple{typeof(Trixi.save_mesh_file), TreeMesh{2, Trixi.SerialTree{2}}, String}) @@ -433,8 +427,8 @@ function _precompile_manual_() Trixi.ElementContainer2D{RealT, uEltype}}) @assert Base.precompile(Tuple{typeof(Trixi.init_mortars), Array{Int, 1}, TreeMesh{2, Trixi.ParallelTree{2}}, - Trixi.ElementContainer2D{RealT, uEltype}, mortar_type - }) + Trixi.ElementContainer2D{RealT, uEltype}, + mortar_type}) @assert Base.precompile(Tuple{typeof(Trixi.init_mpi_interfaces), Array{Int, 1}, TreeMesh{2, Trixi.ParallelTree{2}}, Trixi.ElementContainer2D{RealT, uEltype}}) @@ -450,8 +444,8 @@ function _precompile_manual_() Trixi.ElementContainer3D{RealT, uEltype}}) @assert Base.precompile(Tuple{typeof(Trixi.init_mortars), Array{Int, 1}, TreeMesh{3, Trixi.SerialTree{3}}, - Trixi.ElementContainer3D{RealT, uEltype}, mortar_type - }) + Trixi.ElementContainer3D{RealT, uEltype}, + mortar_type}) @assert Base.precompile(Tuple{typeof(Trixi.save_mesh_file), TreeMesh{3, Trixi.SerialTree{3}}, String}) end @@ -548,16 +542,10 @@ function _precompile_manual_() restart_callback_type}) for solution_variables in (cons2cons, cons2prim) - save_solution_callback_type = DiscreteCallback{ - SaveSolutionCallback{ - typeof(solution_variables) - }, - SaveSolutionCallback{ - typeof(solution_variables) - }, + save_solution_callback_type = DiscreteCallback{SaveSolutionCallback{typeof(solution_variables)}, + SaveSolutionCallback{typeof(solution_variables)}, typeof(Trixi.initialize!), - typeof(SciMLBase.FINALIZE_DEFAULT) - } + typeof(SciMLBase.FINALIZE_DEFAULT)} @assert Base.precompile(Tuple{typeof(show), Base.TTY, save_solution_callback_type}) @assert Base.precompile(Tuple{typeof(show), IOContext{Base.TTY}, diff --git a/src/auxiliary/special_elixirs.jl b/src/auxiliary/special_elixirs.jl index 25bca8939ce..5fdd9aea0c5 100644 --- a/src/auxiliary/special_elixirs.jl +++ b/src/auxiliary/special_elixirs.jl @@ -20,7 +20,7 @@ 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 +for ODEs, see the "Miscellaneous" section of the [documentation](https://docs.sciml.ai/DiffEqDocs/stable/basics/common_solver_opts/). # Examples @@ -36,6 +36,16 @@ julia> redirect_stdout(devnull) do ``` """ function trixi_include(mod::Module, elixir::AbstractString; kwargs...) + # Check that all kwargs exist as assignments + code = read(elixir, String) + expr = Meta.parse("begin \n$code \nend") + expr = insert_maxiters(expr) + + for (key, val) in kwargs + # This will throw an error when `key` is not found + find_assignment(expr, key) + end + # Print information on potential wait time only in non-parallel case if !mpi_isparallel() @info "You just called `trixi_include`. Julia may now compile the code, please be patient." @@ -243,6 +253,7 @@ end function find_assignment(expr, destination) # declare result to be able to assign to it in the closure local result + found = false # find explicit and keyword assignments walkexpr(expr) do x @@ -250,12 +261,17 @@ function find_assignment(expr, destination) if (x.head === Symbol("=") || x.head === :kw) && x.args[1] === Symbol(destination) result = x.args[2] + found = true # dump(x) end end return x end + if !found + throw(ArgumentError("assignment `$destination` not found in expression")) + end + result end @@ -274,17 +290,28 @@ function extract_initial_resolution(elixir, kwargs) return initial_refinement_level end catch e - if isa(e, UndefVarError) - # get cells_per_dimension from the elixir - cells_per_dimension = eval(find_assignment(expr, :cells_per_dimension)) - - if haskey(kwargs, :cells_per_dimension) - return kwargs[:cells_per_dimension] - else - return cells_per_dimension + # If `initial_refinement_level` is not found, we will get an `ArgumentError` + if isa(e, ArgumentError) + try + # get cells_per_dimension from the elixir + cells_per_dimension = eval(find_assignment(expr, :cells_per_dimension)) + + if haskey(kwargs, :cells_per_dimension) + return kwargs[:cells_per_dimension] + else + return cells_per_dimension + end + catch e2 + # If `cells_per_dimension` is not found either + if isa(e2, ArgumentError) + throw(ArgumentError("`convergence_test` requires the elixir to define " * + "`initial_refinement_level` or `cells_per_dimension`")) + else + rethrow() + end end else - throw(e) + rethrow() end end end diff --git a/src/auxiliary/t8code.jl b/src/auxiliary/t8code.jl index fffe213365b..99a8b8b6bb2 100644 --- a/src/auxiliary/t8code.jl +++ b/src/auxiliary/t8code.jl @@ -7,34 +7,40 @@ is already initialized and if yes, do nothing, thus it is safe to call it multiple times. """ function init_t8code() - t8code_package_id = t8_get_package_id() - if t8code_package_id >= 0 - return nothing - end + # Only initialize t8code if T8code.jl can be used + if T8code.preferences_set_correctly() + t8code_package_id = t8_get_package_id() + if t8code_package_id >= 0 + return nothing + end - # Initialize the sc library, has to happen before we initialize t8code. - let catch_signals = 0, print_backtrace = 0, log_handler = C_NULL - T8code.Libt8.sc_init(mpi_comm(), catch_signals, print_backtrace, log_handler, - T8code.Libt8.SC_LP_ERROR) - end + # Initialize the sc library, has to happen before we initialize t8code. + let catch_signals = 0, print_backtrace = 0, log_handler = C_NULL + T8code.Libt8.sc_init(mpi_comm(), catch_signals, print_backtrace, log_handler, + T8code.Libt8.SC_LP_ERROR) + end - if T8code.Libt8.p4est_is_initialized() == 0 - # Initialize `p4est` with log level ERROR to prevent a lot of output in AMR simulations - T8code.Libt8.p4est_init(C_NULL, T8code.Libt8.SC_LP_ERROR) - end + if T8code.Libt8.p4est_is_initialized() == 0 + # Initialize `p4est` with log level ERROR to prevent a lot of output in AMR simulations + T8code.Libt8.p4est_init(C_NULL, T8code.Libt8.SC_LP_ERROR) + end - # Initialize t8code with log level ERROR to prevent a lot of output in AMR simulations. - t8_init(T8code.Libt8.SC_LP_ERROR) - - if haskey(ENV, "TRIXI_T8CODE_SC_FINALIZE") - # Normally, `sc_finalize` should always be called during shutdown of an - # application. It checks whether there is still un-freed memory by t8code - # and/or T8code.jl and throws an exception if this is the case. For - # production runs this is not mandatory, but is helpful during - # development. Hence, this option is only activated when environment - # variable TRIXI_T8CODE_SC_FINALIZE exists. - @warn "T8code.jl: sc_finalize will be called during shutdown of Trixi.jl." - MPI.add_finalize_hook!(T8code.Libt8.sc_finalize) + # Initialize t8code with log level ERROR to prevent a lot of output in AMR simulations. + t8_init(T8code.Libt8.SC_LP_ERROR) + + if haskey(ENV, "TRIXI_T8CODE_SC_FINALIZE") + # Normally, `sc_finalize` should always be called during shutdown of an + # application. It checks whether there is still un-freed memory by t8code + # and/or T8code.jl and throws an exception if this is the case. For + # production runs this is not mandatory, but is helpful during + # development. Hence, this option is only activated when environment + # variable TRIXI_T8CODE_SC_FINALIZE exists. + @warn "T8code.jl: sc_finalize will be called during shutdown of Trixi.jl." + MPI.add_finalize_hook!(T8code.Libt8.sc_finalize) + end + else + @warn "Preferences for T8code.jl are not set correctly. Until fixed, using `T8codeMesh` will result in a crash. " * + "See also https://trixi-framework.github.io/Trixi.jl/stable/parallelization/#parallel_system_MPI" end return nothing diff --git a/src/callbacks_stage/callbacks_stage.jl b/src/callbacks_stage/callbacks_stage.jl index 976af327e6f..70d60de7914 100644 --- a/src/callbacks_stage/callbacks_stage.jl +++ b/src/callbacks_stage/callbacks_stage.jl @@ -7,6 +7,7 @@ include("positivity_zhang_shu.jl") include("subcell_limiter_idp_correction.jl") +include("subcell_bounds_check.jl") # TODO: TrixiShallowWater: move specific limiter file include("positivity_shallow_water.jl") end # @muladd diff --git a/src/callbacks_stage/subcell_bounds_check.jl b/src/callbacks_stage/subcell_bounds_check.jl new file mode 100644 index 00000000000..d7e30ab1621 --- /dev/null +++ b/src/callbacks_stage/subcell_bounds_check.jl @@ -0,0 +1,150 @@ +# By default, Julia/LLVM does not use fused multiply-add operations (FMAs). +# Since these FMAs can increase the performance of many numerical algorithms, +# we need to opt-in explicitly. +# See https://ranocha.de/blog/Optimizing_EC_Trixi for further details. +@muladd begin +#! format: noindent + +""" + BoundsCheckCallback(; output_directory="out", save_errors=false, interval=1) + +Subcell limiting techniques with [`SubcellLimiterIDP`](@ref) 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`](@ref). So, to check the final solution, this bounds check + callback must be called after the correction stage. +""" +struct BoundsCheckCallback + output_directory::String + save_errors::Bool + interval::Int +end + +function BoundsCheckCallback(; output_directory = "out", save_errors = false, + interval = 1) + BoundsCheckCallback(output_directory, save_errors, interval) +end + +function (callback::BoundsCheckCallback)(u_ode, integrator, stage) + mesh, equations, solver, cache = mesh_equations_solver_cache(integrator.p) + (; t, iter, alg) = integrator + u = wrap_array(u_ode, mesh, equations, solver, cache) + + save_errors = callback.save_errors && (callback.interval > 0) && + (stage == length(alg.c)) && + (iter % callback.interval == 0 || integrator.finalstep) + @trixi_timeit timer() "check_bounds" check_bounds(u, mesh, equations, solver, cache, + solver.volume_integral, t, + iter + 1, + callback.output_directory, + save_errors) +end + +function check_bounds(u, mesh, equations, solver, cache, + volume_integral::AbstractVolumeIntegral, t, iter, + output_directory, save_errors) + return nothing +end + +function check_bounds(u, mesh, equations, solver, cache, + volume_integral::VolumeIntegralSubcellLimiting, t, iter, + output_directory, save_errors) + check_bounds(u, mesh, equations, solver, cache, volume_integral.limiter, t, iter, + output_directory, save_errors) +end + +function init_callback(callback::BoundsCheckCallback, semi) + init_callback(callback, semi, semi.solver.volume_integral) +end + +init_callback(callback::BoundsCheckCallback, semi, volume_integral::AbstractVolumeIntegral) = nothing + +function init_callback(callback::BoundsCheckCallback, semi, + volume_integral::VolumeIntegralSubcellLimiting) + init_callback(callback, semi, volume_integral.limiter) +end + +function init_callback(callback::BoundsCheckCallback, semi, limiter::SubcellLimiterIDP) + if !callback.save_errors || (callback.interval == 0) + return nothing + end + + (; local_minmax, positivity) = limiter + (; output_directory) = callback + variables = varnames(cons2cons, semi.equations) + + mkpath(output_directory) + open("$output_directory/deviations.txt", "a") do f + print(f, "# iter, simu_time") + if local_minmax + for v in limiter.local_minmax_variables_cons + variable_string = string(variables[v]) + print(f, ", " * variable_string * "_min, " * variable_string * "_max") + end + end + if positivity + for v in limiter.positivity_variables_cons + if v in limiter.local_minmax_variables_cons + continue + end + print(f, ", " * string(variables[v]) * "_min") + end + end + println(f) + end + + return nothing +end + +function finalize_callback(callback::BoundsCheckCallback, semi) + finalize_callback(callback, semi, semi.solver.volume_integral) +end + +finalize_callback(callback::BoundsCheckCallback, semi, volume_integral::AbstractVolumeIntegral) = nothing + +function finalize_callback(callback::BoundsCheckCallback, semi, + volume_integral::VolumeIntegralSubcellLimiting) + finalize_callback(callback, semi, volume_integral.limiter) +end + +@inline function finalize_callback(callback::BoundsCheckCallback, semi, + limiter::SubcellLimiterIDP) + (; local_minmax, positivity) = limiter + (; idp_bounds_delta) = limiter.cache + variables = varnames(cons2cons, semi.equations) + + println("─"^100) + println("Maximum deviation from bounds:") + println("─"^100) + if local_minmax + for v in limiter.local_minmax_variables_cons + v_string = string(v) + println("$(variables[v]):") + println("-lower bound: ", idp_bounds_delta[Symbol(v_string, "_min")][2]) + println("-upper bound: ", idp_bounds_delta[Symbol(v_string, "_max")][2]) + end + end + if positivity + for v in limiter.positivity_variables_cons + if v in limiter.local_minmax_variables_cons + continue + end + println(string(variables[v]) * ":\n- positivity: ", + idp_bounds_delta[Symbol(string(v), "_min")][2]) + end + end + println("─"^100 * "\n") + + return nothing +end + +include("subcell_bounds_check_2d.jl") +end # @muladd diff --git a/src/callbacks_stage/subcell_bounds_check_2d.jl b/src/callbacks_stage/subcell_bounds_check_2d.jl new file mode 100644 index 00000000000..d52eb6edb9e --- /dev/null +++ b/src/callbacks_stage/subcell_bounds_check_2d.jl @@ -0,0 +1,81 @@ +# By default, Julia/LLVM does not use fused multiply-add operations (FMAs). +# Since these FMAs can increase the performance of many numerical algorithms, +# we need to opt-in explicitly. +# See https://ranocha.de/blog/Optimizing_EC_Trixi for further details. +@muladd begin +#! format: noindent + +@inline function check_bounds(u, mesh::AbstractMesh{2}, equations, solver, cache, + limiter::SubcellLimiterIDP, + time, iter, output_directory, save_errors) + (; local_minmax, positivity) = solver.volume_integral.limiter + (; variable_bounds) = limiter.cache.subcell_limiter_coefficients + (; idp_bounds_delta) = limiter.cache + + if local_minmax + for v in limiter.local_minmax_variables_cons + v_string = string(v) + key_min = Symbol(v_string, "_min") + key_max = Symbol(v_string, "_max") + deviation_min = idp_bounds_delta[key_min] + deviation_max = idp_bounds_delta[key_max] + for element in eachelement(solver, cache), j in eachnode(solver), + i in eachnode(solver) + + var = u[v, i, j, element] + deviation_min[1] = max(deviation_min[1], + variable_bounds[key_min][i, j, element] - var) + deviation_max[1] = max(deviation_max[1], + var - variable_bounds[key_max][i, j, element]) + end + deviation_min[2] = max(deviation_min[2], deviation_min[1]) + deviation_max[2] = max(deviation_max[2], deviation_max[1]) + end + end + if positivity + for v in limiter.positivity_variables_cons + if v in limiter.local_minmax_variables_cons + continue + end + key = Symbol(string(v), "_min") + deviation = idp_bounds_delta[key] + for element in eachelement(solver, cache), j in eachnode(solver), + i in eachnode(solver) + + var = u[v, i, j, element] + deviation[1] = max(deviation[1], + variable_bounds[key][i, j, element] - var) + end + deviation[2] = max(deviation[2], deviation[1]) + end + end + if save_errors + # Print to output file + open("$output_directory/deviations.txt", "a") do f + print(f, iter, ", ", time) + if local_minmax + for v in limiter.local_minmax_variables_cons + v_string = string(v) + print(f, ", ", idp_bounds_delta[Symbol(v_string, "_min")][1], ", ", + idp_bounds_delta[Symbol(v_string, "_max")][1]) + end + end + if positivity + for v in limiter.positivity_variables_cons + if v in limiter.local_minmax_variables_cons + continue + end + print(f, ", ", idp_bounds_delta[Symbol(string(v), "_min")][1]) + end + end + println(f) + end + # Reset first entries of idp_bounds_delta + for (key, _) in idp_bounds_delta + idp_bounds_delta[key][1] = zero(eltype(idp_bounds_delta[key][1])) + end + end + + return nothing +end +end # @muladd diff --git a/src/callbacks_stage/subcell_limiter_idp_correction_2d.jl b/src/callbacks_stage/subcell_limiter_idp_correction_2d.jl index f6b91444578..6f1723e2a98 100644 --- a/src/callbacks_stage/subcell_limiter_idp_correction_2d.jl +++ b/src/callbacks_stage/subcell_limiter_idp_correction_2d.jl @@ -7,7 +7,7 @@ function perform_idp_correction!(u, dt, mesh::TreeMesh2D, equations, dg, cache) @unpack inverse_weights = dg.basis - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.antidiffusive_fluxes + @unpack antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R = cache.antidiffusive_fluxes @unpack alpha1, alpha2 = dg.volume_integral.limiter.cache.subcell_limiter_coefficients @threaded for element in eachelement(dg, cache) @@ -17,16 +17,16 @@ function perform_idp_correction!(u, dt, mesh::TreeMesh2D, equations, dg, cache) for j in eachnode(dg), i in eachnode(dg) # Note: antidiffusive_flux1[v, i, xi, element] = antidiffusive_flux2[v, xi, i, element] = 0 for all i in 1:nnodes and xi in {1, nnodes+1} alpha_flux1 = (1 - alpha1[i, j, element]) * - get_node_vars(antidiffusive_flux1, equations, dg, i, j, + get_node_vars(antidiffusive_flux1_R, equations, dg, i, j, element) alpha_flux1_ip1 = (1 - alpha1[i + 1, j, element]) * - get_node_vars(antidiffusive_flux1, equations, dg, i + 1, + get_node_vars(antidiffusive_flux1_L, equations, dg, i + 1, j, element) alpha_flux2 = (1 - alpha2[i, j, element]) * - get_node_vars(antidiffusive_flux2, equations, dg, i, j, + get_node_vars(antidiffusive_flux2_R, equations, dg, i, j, element) alpha_flux2_jp1 = (1 - alpha2[i, j + 1, element]) * - get_node_vars(antidiffusive_flux2, equations, dg, i, + get_node_vars(antidiffusive_flux2_L, equations, dg, i, j + 1, element) for v in eachvariable(equations) diff --git a/src/callbacks_step/alive.jl b/src/callbacks_step/alive.jl index eeacd9681d8..9df7181521e 100644 --- a/src/callbacks_step/alive.jl +++ b/src/callbacks_step/alive.jl @@ -86,9 +86,15 @@ function (alive_callback::AliveCallback)(integrator) println("─"^100) println() elseif mpi_isroot() + t = integrator.t + t_initial = first(integrator.sol.prob.tspan) + t_final = last(integrator.sol.prob.tspan) + sim_time_percentage = (t - t_initial) / (t_final - t_initial) * 100 runtime_absolute = 1.0e-9 * (time_ns() - alive_callback.start_time) - @printf("#timesteps: %6d │ Δt: %.4e │ sim. time: %.4e │ run time: %.4e s\n", - integrator.stats.naccept, integrator.dt, integrator.t, runtime_absolute) + println(rpad(@sprintf("#timesteps: %6d │ Δt: %.4e │ sim. time: %.4e (%5.3f%%)", + integrator.stats.naccept, integrator.dt, t, + sim_time_percentage), 71) * + @sprintf("│ run time: %.4e s", runtime_absolute)) end # avoid re-evaluating possible FSAL stages diff --git a/src/callbacks_step/amr.jl b/src/callbacks_step/amr.jl index 4d80e6e1139..5854c8617c3 100644 --- a/src/callbacks_step/amr.jl +++ b/src/callbacks_step/amr.jl @@ -192,6 +192,16 @@ end amr_callback(u_ode, mesh_equations_solver_cache(semi)..., semi, t, iter; kwargs...) end +@inline function (amr_callback::AMRCallback)(u_ode::AbstractVector, + semi::SemidiscretizationHyperbolicParabolic, + t, iter; + kwargs...) + # Note that we don't `wrap_array` the vector `u_ode` to be able to `resize!` + # it when doing AMR while still dispatching on the `mesh` etc. + amr_callback(u_ode, mesh_equations_solver_cache(semi)..., semi.cache_parabolic, + semi, t, iter; kwargs...) +end + # `passive_args` is currently used for Euler with self-gravity to adapt the gravity solver # passively without querying its indicator, based on the assumption that both solvers use # the same mesh. That's a hack and should be improved in the future once we have more examples @@ -346,6 +356,154 @@ function (amr_callback::AMRCallback)(u_ode::AbstractVector, mesh::TreeMesh, return has_changed end +function (amr_callback::AMRCallback)(u_ode::AbstractVector, mesh::TreeMesh, + equations, dg::DG, + cache, cache_parabolic, + semi::SemidiscretizationHyperbolicParabolic, + t, iter; + only_refine = false, only_coarsen = false) + @unpack controller, adaptor = amr_callback + + u = wrap_array(u_ode, mesh, equations, dg, cache) + # Indicator kept based on hyperbolic variables + lambda = @trixi_timeit timer() "indicator" controller(u, mesh, equations, dg, cache, + t = t, iter = iter) + + if mpi_isparallel() + error("MPI has not been verified yet for parabolic AMR") + + # Collect lambda for all elements + lambda_global = Vector{eltype(lambda)}(undef, nelementsglobal(dg, cache)) + # Use parent because n_elements_by_rank is an OffsetArray + recvbuf = MPI.VBuffer(lambda_global, parent(cache.mpi_cache.n_elements_by_rank)) + MPI.Allgatherv!(lambda, recvbuf, mpi_comm()) + lambda = lambda_global + end + + leaf_cell_ids = leaf_cells(mesh.tree) + @boundscheck begin + @assert axes(lambda)==axes(leaf_cell_ids) ("Indicator (axes = $(axes(lambda))) and leaf cell (axes = $(axes(leaf_cell_ids))) arrays have different axes") + end + + @unpack to_refine, to_coarsen = amr_callback.amr_cache + empty!(to_refine) + empty!(to_coarsen) + for element in 1:length(lambda) + controller_value = lambda[element] + if controller_value > 0 + push!(to_refine, leaf_cell_ids[element]) + elseif controller_value < 0 + push!(to_coarsen, leaf_cell_ids[element]) + end + end + + @trixi_timeit timer() "refine" if !only_coarsen && !isempty(to_refine) + # refine mesh + refined_original_cells = @trixi_timeit timer() "mesh" refine!(mesh.tree, + to_refine) + + # Find all indices of elements whose cell ids are in refined_original_cells + # Note: This assumes same indices for hyperbolic and parabolic part. + elements_to_refine = findall(in(refined_original_cells), + cache.elements.cell_ids) + + # refine solver + @trixi_timeit timer() "solver" refine!(u_ode, adaptor, mesh, equations, dg, + cache, cache_parabolic, + elements_to_refine) + else + # If there is nothing to refine, create empty array for later use + refined_original_cells = Int[] + end + + @trixi_timeit timer() "coarsen" if !only_refine && !isempty(to_coarsen) + # Since the cells may have been shifted due to refinement, first we need to + # translate the old cell ids to the new cell ids + if !isempty(to_coarsen) + to_coarsen = original2refined(to_coarsen, refined_original_cells, mesh) + end + + # Next, determine the parent cells from which the fine cells are to be + # removed, since these are needed for the coarsen! function. However, since + # we only want to coarsen if *all* child cells are marked for coarsening, + # we count the coarsening indicators for each parent cell and only coarsen + # if all children are marked as such (i.e., where the count is 2^ndims). At + # the same time, check if a cell is marked for coarsening even though it is + # *not* a leaf cell -> this can only happen if it was refined due to 2:1 + # smoothing during the preceding refinement operation. + parents_to_coarsen = zeros(Int, length(mesh.tree)) + for cell_id in to_coarsen + # If cell has no parent, it cannot be coarsened + if !has_parent(mesh.tree, cell_id) + continue + end + + # If cell is not leaf (anymore), it cannot be coarsened + if !is_leaf(mesh.tree, cell_id) + continue + end + + # Increase count for parent cell + parent_id = mesh.tree.parent_ids[cell_id] + parents_to_coarsen[parent_id] += 1 + end + + # Extract only those parent cells for which all children should be coarsened + to_coarsen = collect(1:length(parents_to_coarsen))[parents_to_coarsen .== 2^ndims(mesh)] + + # Finally, coarsen mesh + coarsened_original_cells = @trixi_timeit timer() "mesh" coarsen!(mesh.tree, + to_coarsen) + + # Convert coarsened parent cell ids to the list of child cell ids that have + # been removed, since this is the information that is expected by the solver + removed_child_cells = zeros(Int, + n_children_per_cell(mesh.tree) * + length(coarsened_original_cells)) + for (index, coarse_cell_id) in enumerate(coarsened_original_cells) + for child in 1:n_children_per_cell(mesh.tree) + removed_child_cells[n_children_per_cell(mesh.tree) * (index - 1) + child] = coarse_cell_id + + child + end + end + + # Find all indices of elements whose cell ids are in removed_child_cells + # Note: This assumes same indices for hyperbolic and parabolic part. + elements_to_remove = findall(in(removed_child_cells), cache.elements.cell_ids) + + # coarsen solver + @trixi_timeit timer() "solver" coarsen!(u_ode, adaptor, mesh, equations, dg, + cache, cache_parabolic, + elements_to_remove) + else + # If there is nothing to coarsen, create empty array for later use + coarsened_original_cells = Int[] + end + + # Store whether there were any cells coarsened or refined + has_changed = !isempty(refined_original_cells) || !isempty(coarsened_original_cells) + if has_changed # TODO: Taal decide, where shall we set this? + # don't set it to has_changed since there can be changes from earlier calls + mesh.unsaved_changes = true + end + + # Dynamically balance computational load by first repartitioning the mesh and then redistributing the cells/elements + if has_changed && mpi_isparallel() && amr_callback.dynamic_load_balancing + error("MPI has not been verified yet for parabolic AMR") + + @trixi_timeit timer() "dynamic load balancing" begin + old_mpi_ranks_per_cell = copy(mesh.tree.mpi_ranks) + + partition!(mesh) + + rebalance_solver!(u_ode, mesh, equations, dg, cache, old_mpi_ranks_per_cell) + end + end + + # Return true if there were any cells coarsened or refined, otherwise false + return has_changed +end + # Copy controller values to quad user data storage, will be called below function copy_to_quad_iter_volume(info, user_data) info_pw = PointerWrapper(info) @@ -370,6 +528,103 @@ function copy_to_quad_iter_volume(info, user_data) return nothing end +# specialized callback which includes the `cache_parabolic` argument +function (amr_callback::AMRCallback)(u_ode::AbstractVector, mesh::P4estMesh, + equations, dg::DG, cache, cache_parabolic, + semi, + t, iter; + only_refine = false, only_coarsen = false, + passive_args = ()) + @unpack controller, adaptor = amr_callback + + u = wrap_array(u_ode, mesh, equations, dg, cache) + lambda = @trixi_timeit timer() "indicator" controller(u, mesh, equations, dg, cache, + t = t, iter = iter) + + @boundscheck begin + @assert axes(lambda)==(Base.OneTo(ncells(mesh)),) ("Indicator array (axes = $(axes(lambda))) and mesh cells (axes = $(Base.OneTo(ncells(mesh)))) have different axes") + end + + # Copy controller value of each quad to the quad's user data storage + iter_volume_c = cfunction(copy_to_quad_iter_volume, Val(ndims(mesh))) + + # The pointer to lambda will be interpreted as Ptr{Int} below + @assert lambda isa Vector{Int} + iterate_p4est(mesh.p4est, lambda; iter_volume_c = iter_volume_c) + + @trixi_timeit timer() "refine" if !only_coarsen + # Refine mesh + refined_original_cells = @trixi_timeit timer() "mesh" refine!(mesh) + + # Refine solver + @trixi_timeit timer() "solver" refine!(u_ode, adaptor, mesh, equations, dg, + cache, cache_parabolic, + refined_original_cells) + for (p_u_ode, p_mesh, p_equations, p_dg, p_cache) in passive_args + @trixi_timeit timer() "passive solver" refine!(p_u_ode, adaptor, p_mesh, + p_equations, + p_dg, p_cache, + refined_original_cells) + end + else + # If there is nothing to refine, create empty array for later use + refined_original_cells = Int[] + end + + @trixi_timeit timer() "coarsen" if !only_refine + # Coarsen mesh + coarsened_original_cells = @trixi_timeit timer() "mesh" coarsen!(mesh) + + # coarsen solver + @trixi_timeit timer() "solver" coarsen!(u_ode, adaptor, mesh, equations, dg, + cache, cache_parabolic, + coarsened_original_cells) + for (p_u_ode, p_mesh, p_equations, p_dg, p_cache) in passive_args + @trixi_timeit timer() "passive solver" coarsen!(p_u_ode, adaptor, p_mesh, + p_equations, + p_dg, p_cache, + coarsened_original_cells) + end + else + # If there is nothing to coarsen, create empty array for later use + coarsened_original_cells = Int[] + end + + # Store whether there were any cells coarsened or refined and perform load balancing + has_changed = !isempty(refined_original_cells) || !isempty(coarsened_original_cells) + # Check if mesh changed on other processes + if mpi_isparallel() + has_changed = MPI.Allreduce!(Ref(has_changed), |, mpi_comm())[] + end + + if has_changed # TODO: Taal decide, where shall we set this? + # don't set it to has_changed since there can be changes from earlier calls + mesh.unsaved_changes = true + + if mpi_isparallel() && amr_callback.dynamic_load_balancing + @trixi_timeit timer() "dynamic load balancing" begin + global_first_quadrant = unsafe_wrap(Array, + unsafe_load(mesh.p4est).global_first_quadrant, + mpi_nranks() + 1) + old_global_first_quadrant = copy(global_first_quadrant) + partition!(mesh) + rebalance_solver!(u_ode, mesh, equations, dg, cache, + old_global_first_quadrant) + end + end + + reinitialize_boundaries!(semi.boundary_conditions, cache) + # if the semidiscretization also stores parabolic boundary conditions, + # reinitialize them after each refinement step as well. + if hasproperty(semi, :boundary_conditions_parabolic) + reinitialize_boundaries!(semi.boundary_conditions_parabolic, cache) + end + end + + # Return true if there were any cells coarsened or refined, otherwise false + return has_changed +end + # 2D function cfunction(::typeof(copy_to_quad_iter_volume), ::Val{2}) @cfunction(copy_to_quad_iter_volume, Cvoid, diff --git a/src/callbacks_step/amr_dg1d.jl b/src/callbacks_step/amr_dg1d.jl index e31a74730ea..b4cd6a00271 100644 --- a/src/callbacks_step/amr_dg1d.jl +++ b/src/callbacks_step/amr_dg1d.jl @@ -76,6 +76,27 @@ function refine!(u_ode::AbstractVector, adaptor, mesh::TreeMesh{1}, return nothing end +function refine!(u_ode::AbstractVector, adaptor, mesh::TreeMesh{1}, + equations, dg::DGSEM, cache, cache_parabolic, + elements_to_refine) + # Call `refine!` for the hyperbolic part, which does the heavy lifting of + # actually transferring the solution to the refined cells + refine!(u_ode, adaptor, mesh, equations, dg, cache, elements_to_refine) + + # Resize parabolic helper variables + @unpack viscous_container = cache_parabolic + resize!(viscous_container, equations, dg, cache) + reinitialize_containers!(mesh, equations, dg, cache_parabolic) + + # Sanity check + @unpack interfaces = cache_parabolic + if isperiodic(mesh.tree) + @assert ninterfaces(interfaces)==1 * nelements(dg, cache_parabolic) ("For 1D and periodic domains, the number of interfaces must be the same as the number of elements") + end + + return nothing +end + # TODO: Taal compare performance of different implementations # Refine solution data u for an element, using L2 projection (interpolation) function refine_element!(u::AbstractArray{<:Any, 3}, element_id, @@ -201,6 +222,27 @@ function coarsen!(u_ode::AbstractVector, adaptor, mesh::TreeMesh{1}, return nothing end +function coarsen!(u_ode::AbstractVector, adaptor, mesh::TreeMesh{1}, + equations, dg::DGSEM, cache, cache_parabolic, + elements_to_remove) + # Call `coarsen!` for the hyperbolic part, which does the heavy lifting of + # actually transferring the solution to the coarsened cells + coarsen!(u_ode, adaptor, mesh, equations, dg, cache, elements_to_remove) + + # Resize parabolic helper variables + @unpack viscous_container = cache_parabolic + resize!(viscous_container, equations, dg, cache) + reinitialize_containers!(mesh, equations, dg, cache_parabolic) + + # Sanity check + @unpack interfaces = cache_parabolic + if isperiodic(mesh.tree) + @assert ninterfaces(interfaces)==1 * nelements(dg, cache_parabolic) ("For 1D and periodic domains, the number of interfaces must be the same as the number of elements") + end + + return nothing +end + # TODO: Taal compare performance of different implementations # Coarsen solution data u for two elements, using L2 projection function coarsen_elements!(u::AbstractArray{<:Any, 3}, element_id, diff --git a/src/callbacks_step/amr_dg2d.jl b/src/callbacks_step/amr_dg2d.jl index 5170a286e46..7cb9fee8f6e 100644 --- a/src/callbacks_step/amr_dg2d.jl +++ b/src/callbacks_step/amr_dg2d.jl @@ -136,6 +136,29 @@ function refine!(u_ode::AbstractVector, adaptor, mesh::Union{TreeMesh{2}, P4estM return nothing end +function refine!(u_ode::AbstractVector, adaptor, + mesh::Union{TreeMesh{2}, P4estMesh{2}, TreeMesh{3}}, + equations, dg::DGSEM, cache, cache_parabolic, + elements_to_refine) + # Call `refine!` for the hyperbolic part, which does the heavy lifting of + # actually transferring the solution to the refined cells + refine!(u_ode, adaptor, mesh, equations, dg, cache, elements_to_refine) + + # Resize parabolic helper variables + @unpack viscous_container = cache_parabolic + resize!(viscous_container, equations, dg, cache) + reinitialize_containers!(mesh, equations, dg, cache_parabolic) + + # Sanity check + if mesh isa TreeMesh && isperiodic(mesh.tree) && nmortars(cache.mortars) == 0 && + !mpi_isparallel() + @assert ninterfaces(cache_parabolic.interfaces)==ndims(mesh) * + nelements(dg, cache_parabolic) ("For $(ndims(mesh))D and periodic domains and conforming elements, the number of interfaces must be $(ndims(mesh)) times the number of elements") + end + + return nothing +end + # TODO: Taal compare performance of different implementations # Refine solution data u for an element, using L2 projection (interpolation) function refine_element!(u::AbstractArray{<:Any, 4}, element_id, @@ -275,6 +298,29 @@ function coarsen!(u_ode::AbstractVector, adaptor, return nothing end +function coarsen!(u_ode::AbstractVector, adaptor, + mesh::Union{TreeMesh{2}, P4estMesh{2}, TreeMesh{3}}, + equations, dg::DGSEM, cache, cache_parabolic, + elements_to_remove) + # Call `coarsen!` for the hyperbolic part, which does the heavy lifting of + # actually transferring the solution to the coarsened cells + coarsen!(u_ode, adaptor, mesh, equations, dg, cache, elements_to_remove) + + # Resize parabolic helper variables + @unpack viscous_container = cache_parabolic + resize!(viscous_container, equations, dg, cache) + reinitialize_containers!(mesh, equations, dg, cache_parabolic) + + # Sanity check + if mesh isa TreeMesh && isperiodic(mesh.tree) && nmortars(cache.mortars) == 0 && + !mpi_isparallel() + @assert ninterfaces(cache_parabolic.interfaces)==ndims(mesh) * + nelements(dg, cache_parabolic) ("For $(ndims(mesh))D and periodic domains and conforming elements, the number of interfaces must be $(ndims(mesh)) times the number of elements") + end + + return nothing +end + # TODO: Taal compare performance of different implementations # Coarsen solution data u for four elements, using L2 projection function coarsen_elements!(u::AbstractArray{<:Any, 4}, element_id, diff --git a/src/callbacks_step/analysis.jl b/src/callbacks_step/analysis.jl index fad42b11098..ba232032951 100644 --- a/src/callbacks_step/analysis.jl +++ b/src/callbacks_step/analysis.jl @@ -23,6 +23,13 @@ Additional errors can be computed, e.g. by passing `extra_analysis_errors = (:l2_error_primitive, :linf_error_primitive)` or `extra_analysis_errors = (:conservation_error,)`. +If you want to omit the computation (to safe compute-time) of the [`default_analysis_errors`](@ref), specify +`analysis_errors = Symbol[]`. +Note: `default_analysis_errors` are `:l2_error` and `:linf_error` for all equations. +If you want to compute `extra_analysis_errors` such as `:conservation_error` solely, i.e., +without `:l2_error, :linf_error` you need to specify +`analysis_errors = [:conservation_error]` instead of `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`](@ref), [`energy_kinetic`](@ref), [`energy_internal`](@ref), and [`energy_total`](@ref). @@ -232,6 +239,12 @@ function (analysis_callback::AnalysisCallback)(u_ode, du_ode, integrator, semi) @unpack dt, t = integrator iter = integrator.stats.naccept + # Compute the percentage of the simulation that is done + t = integrator.t + t_initial = first(integrator.sol.prob.tspan) + t_final = last(integrator.sol.prob.tspan) + sim_time_percentage = (t - t_initial) / (t_final - t_initial) * 100 + # Record performance measurements and compute performance index (PID) runtime_since_last_analysis = 1.0e-9 * (time_ns() - analysis_callback.start_time_last_analysis) @@ -291,13 +304,13 @@ function (analysis_callback::AnalysisCallback)(u_ode, du_ode, integrator, semi) " " * " └── GC time: " * @sprintf("%10.8e s (%5.3f%%)", gc_time_absolute, gc_time_percentage)) - mpi_println(" sim. time: " * @sprintf("%10.8e", t) * - " " * + mpi_println(rpad(" sim. time: " * + @sprintf("%10.8e (%5.3f%%)", t, sim_time_percentage), 46) * " time/DOF/rhs!: " * @sprintf("%10.8e s", runtime_relative)) mpi_println(" " * " " * " " * " PID: " * @sprintf("%10.8e s", performance_index)) - mpi_println(" #DOF: " * @sprintf("% 14d", ndofs(semi)) * + mpi_println(" #DOFs per field:" * @sprintf("% 14d", ndofs(semi)) * " " * " alloc'd memory: " * @sprintf("%14.3f MiB", memory_use)) mpi_println(" #elements: " * @@ -326,7 +339,8 @@ function (analysis_callback::AnalysisCallback)(u_ode, du_ode, integrator, semi) @notimeit timer() integrator.f(du_ode, u_ode, semi, t) u = wrap_array(u_ode, mesh, equations, solver, cache) du = wrap_array(du_ode, mesh, equations, solver, cache) - l2_error, linf_error = analysis_callback(io, du, u, u_ode, t, semi) + # Compute l2_error, linf_error + analysis_callback(io, du, u, u_ode, t, semi) mpi_println("─"^100) mpi_println() @@ -348,8 +362,7 @@ function (analysis_callback::AnalysisCallback)(u_ode, du_ode, integrator, semi) analysis_callback.start_time_last_analysis = time_ns() analysis_callback.ncalls_rhs_last_analysis = ncalls(semi.performance_counter) - # Return errors for EOC analysis - return l2_error, linf_error + return nothing end # This method is just called internally from `(analysis_callback::AnalysisCallback)(integrator)` @@ -371,28 +384,31 @@ function (analysis_callback::AnalysisCallback)(io, du, u, u_ode, t, semi) println() end - # Calculate L2/Linf errors, which are also returned - l2_error, linf_error = calc_error_norms(u_ode, t, analyzer, semi, cache_analysis) + if :l2_error in analysis_errors || :linf_error in analysis_errors + # Calculate L2/Linf errors + l2_error, linf_error = calc_error_norms(u_ode, t, analyzer, semi, + cache_analysis) - if mpi_isroot() - # L2 error - if :l2_error in analysis_errors - print(" L2 error: ") - for v in eachvariable(equations) - @printf(" % 10.8e", l2_error[v]) - @printf(io, " % 10.8e", l2_error[v]) + if mpi_isroot() + # L2 error + if :l2_error in analysis_errors + print(" L2 error: ") + for v in eachvariable(equations) + @printf(" % 10.8e", l2_error[v]) + @printf(io, " % 10.8e", l2_error[v]) + end + println() end - println() - end - # Linf error - if :linf_error in analysis_errors - print(" Linf error: ") - for v in eachvariable(equations) - @printf(" % 10.8e", linf_error[v]) - @printf(io, " % 10.8e", linf_error[v]) + # Linf error + if :linf_error in analysis_errors + print(" Linf error: ") + for v in eachvariable(equations) + @printf(" % 10.8e", linf_error[v]) + @printf(io, " % 10.8e", linf_error[v]) + end + println() end - println() end end @@ -471,7 +487,7 @@ function (analysis_callback::AnalysisCallback)(io, du, u, u_ode, t, semi) # additional integrals analyze_integrals(analysis_integrals, io, du, u, t, semi) - return l2_error, linf_error + return nothing end # Print level information only if AMR is enabled diff --git a/src/callbacks_step/analysis_dg2d.jl b/src/callbacks_step/analysis_dg2d.jl index aecabf0e4b7..a9e0cf87b0a 100644 --- a/src/callbacks_step/analysis_dg2d.jl +++ b/src/callbacks_step/analysis_dg2d.jl @@ -218,7 +218,7 @@ function integrate(func::Func, u, equations, equations_parabolic, dg::DGSEM, cache, cache_parabolic; normalize = true) where {Func} - gradients_x, gradients_y = cache_parabolic.gradients + gradients_x, gradients_y = cache_parabolic.viscous_container.gradients integrate_via_indices(u, mesh, equations, dg, cache; normalize = normalize) do u, i, j, element, equations, dg u_local = get_node_vars(u, equations, dg, i, j, element) diff --git a/src/callbacks_step/analysis_dg3d.jl b/src/callbacks_step/analysis_dg3d.jl index bc835e8a6a9..27e8a2b722f 100644 --- a/src/callbacks_step/analysis_dg3d.jl +++ b/src/callbacks_step/analysis_dg3d.jl @@ -236,7 +236,7 @@ function integrate(func::Func, u, equations, equations_parabolic, dg::DGSEM, cache, cache_parabolic; normalize = true) where {Func} - gradients_x, gradients_y, gradients_z = cache_parabolic.gradients + gradients_x, gradients_y, gradients_z = cache_parabolic.viscous_container.gradients integrate_via_indices(u, mesh, equations, dg, cache; normalize = normalize) do u, i, j, k, element, equations, dg u_local = get_node_vars(u, equations, dg, i, j, k, element) diff --git a/src/callbacks_step/averaging.jl b/src/callbacks_step/averaging.jl index 8d2dcfeaefe..efa71af9b91 100644 --- a/src/callbacks_step/averaging.jl +++ b/src/callbacks_step/averaging.jl @@ -52,8 +52,7 @@ function Base.show(io::IO, ::MIME"text/plain", end function AveragingCallback(semi::SemidiscretizationHyperbolic{<:Any, - <:CompressibleEulerEquations2D - }, + <:CompressibleEulerEquations2D}, tspan; output_directory = "out", filename = "averaging.h5") mesh, equations, solver, cache = mesh_equations_solver_cache(semi) mean_values = initialize_mean_values(mesh, equations, solver, cache) diff --git a/src/callbacks_step/euler_acoustics_coupling.jl b/src/callbacks_step/euler_acoustics_coupling.jl index ea33175d0c5..52dc55befdc 100644 --- a/src/callbacks_step/euler_acoustics_coupling.jl +++ b/src/callbacks_step/euler_acoustics_coupling.jl @@ -34,8 +34,8 @@ the [`AveragingCallback`](@ref). A direct-hybrid method for aeroacoustic analysis [DOI: 10.18154/RWTH-2017-04082](https://doi.org/10.18154/RWTH-2017-04082) """ -mutable struct EulerAcousticsCouplingCallback{RealT <: Real, MeanValues, IntegratorEuler - } +mutable struct EulerAcousticsCouplingCallback{RealT <: Real, MeanValues, + IntegratorEuler} stepsize_callback_acoustics::StepsizeCallback{RealT} stepsize_callback_euler::StepsizeCallback{RealT} mean_values::MeanValues @@ -85,8 +85,7 @@ The mean values for the acoustic perturbation equations are read from `averaging """ function EulerAcousticsCouplingCallback(ode_euler, averaging_callback::DiscreteCallback{<:Any, - <:AveragingCallback - }, + <:AveragingCallback}, alg, cfl_acoustics::Real, cfl_euler::Real; kwargs...) @unpack mean_values = averaging_callback.affect! diff --git a/src/callbacks_step/glm_speed_dg.jl b/src/callbacks_step/glm_speed_dg.jl index 0686c547a34..302aae356ab 100644 --- a/src/callbacks_step/glm_speed_dg.jl +++ b/src/callbacks_step/glm_speed_dg.jl @@ -7,8 +7,8 @@ function calc_dt_for_cleaning_speed(cfl::Real, mesh, equations::Union{AbstractIdealGlmMhdEquations, - AbstractIdealGlmMhdMulticomponentEquations - }, dg::DG, cache) + AbstractIdealGlmMhdMulticomponentEquations}, + dg::DG, cache) # compute time step for GLM linear advection equation with c_h=1 for the DG discretization on # Cartesian meshes max_scaled_speed_for_c_h = maximum(cache.elements.inverse_jacobian) * @@ -20,8 +20,7 @@ end function calc_dt_for_cleaning_speed(cfl::Real, mesh, equations::Union{AbstractIdealGlmMhdEquations, - AbstractIdealGlmMhdMulticomponentEquations - }, + AbstractIdealGlmMhdMulticomponentEquations}, dg::DGMulti, cache) rd = dg.basis md = mesh.md diff --git a/src/callbacks_step/save_restart.jl b/src/callbacks_step/save_restart.jl index f567a5c7fda..0d174d85805 100644 --- a/src/callbacks_step/save_restart.jl +++ b/src/callbacks_step/save_restart.jl @@ -105,6 +105,11 @@ function (restart_callback::SaveRestartCallback)(integrator) end save_restart_file(u_ode, t, dt, iter, semi, restart_callback) + # If using an adaptive time stepping scheme, store controller values for restart + if integrator.opts.adaptive + save_adaptive_time_integrator(integrator, integrator.opts.controller, + restart_callback) + end end # avoid re-evaluating possible FSAL stages @@ -141,6 +146,18 @@ function load_timestep(restart_file::AbstractString) end end +""" + 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`. +""" +function load_timestep!(integrator, restart_file::AbstractString) + integrator.iter = load_timestep(restart_file) + integrator.stats.naccept = integrator.iter +end + """ load_dt(restart_file::AbstractString) @@ -156,5 +173,36 @@ function load_restart_file(semi::AbstractSemidiscretization, restart_file) load_restart_file(mesh_equations_solver_cache(semi)..., restart_file) end +""" + 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`. +""" +function load_adaptive_time_integrator!(integrator, restart_file::AbstractString) + controller = integrator.opts.controller + # Read context information for controller + h5open(restart_file, "r") do file + # Ensure that the necessary information was saved + if !("time_integrator_qold" in keys(attributes(file))) || + !("time_integrator_dtpropose" in keys(attributes(file))) || + (hasproperty(controller, :err) && + !("time_integrator_controller_err" in keys(attributes(file)))) + error("Missing data in restart file: check the consistency of adaptive time controller with initial setup!") + end + # Load data that is required both for PIController and PIDController + integrator.qold = read(attributes(file)["time_integrator_qold"]) + integrator.dtpropose = read(attributes(file)["time_integrator_dtpropose"]) + # Accept step to use dtpropose already in the first step + integrator.accept_step = true + # Reevaluate integrator.fsal_first on the first step + integrator.reeval_fsal = true + # Load additional parameters for PIDController + if hasproperty(controller, :err) # Distinguish PIDController from PIController + controller.err[:] = read(attributes(file)["time_integrator_controller_err"]) + end + end +end + include("save_restart_dg.jl") end # @muladd diff --git a/src/callbacks_step/save_restart_dg.jl b/src/callbacks_step/save_restart_dg.jl index 8db6db2d2b8..cddeef77bb2 100644 --- a/src/callbacks_step/save_restart_dg.jl +++ b/src/callbacks_step/save_restart_dg.jl @@ -327,4 +327,28 @@ function load_restart_file_on_root(mesh::Union{ParallelTreeMesh, ParallelP4estMe return u_ode end + +# Store controller values for an adaptive time stepping scheme +function save_adaptive_time_integrator(integrator, + controller, restart_callback) + # Save only on root + if mpi_isroot() + @unpack output_directory = restart_callback + timestep = integrator.stats.naccept + + # Filename based on current time step + filename = joinpath(output_directory, @sprintf("restart_%06d.h5", timestep)) + + # Open file (preserve existing content) + h5open(filename, "r+") do file + # Add context information as attributes both for PIController and PIDController + attributes(file)["time_integrator_qold"] = integrator.qold + attributes(file)["time_integrator_dtpropose"] = integrator.dtpropose + # For PIDController is necessary to save additional parameters + if hasproperty(controller, :err) # Distinguish PIDController from PIController + attributes(file)["time_integrator_controller_err"] = controller.err + end + end + end +end end # @muladd diff --git a/src/callbacks_step/save_solution.jl b/src/callbacks_step/save_solution.jl index 14ea33368f8..c106fe69bcd 100644 --- a/src/callbacks_step/save_solution.jl +++ b/src/callbacks_step/save_solution.jl @@ -39,8 +39,7 @@ end function Base.show(io::IO, cb::DiscreteCallback{<:Any, - <:PeriodicCallbackAffect{<:SaveSolutionCallback - }}) + <:PeriodicCallbackAffect{<:SaveSolutionCallback}}) @nospecialize cb # reduce precompilation time save_solution_callback = cb.affect!.affect! @@ -71,8 +70,7 @@ end function Base.show(io::IO, ::MIME"text/plain", cb::DiscreteCallback{<:Any, - <:PeriodicCallbackAffect{<:SaveSolutionCallback - }}) + <:PeriodicCallbackAffect{<:SaveSolutionCallback}}) @nospecialize cb # reduce precompilation time if get(io, :compact, false) @@ -211,32 +209,39 @@ end get_element_variables!(element_variables, u_ode, semi) callbacks = integrator.opts.callback if callbacks isa CallbackSet - for cb in callbacks.continuous_callbacks + foreach(callbacks.continuous_callbacks) do cb get_element_variables!(element_variables, u_ode, semi, cb; t = integrator.t, iter = iter) end - for cb in callbacks.discrete_callbacks + foreach(callbacks.discrete_callbacks) do cb get_element_variables!(element_variables, u_ode, semi, cb; t = integrator.t, iter = iter) end end end + node_variables = Dict{Symbol, Any}() + @trixi_timeit timer() "get node variables" get_node_variables!(node_variables, + semi) + @trixi_timeit timer() "save solution" save_solution_file(u_ode, t, dt, iter, semi, solution_callback, element_variables, + node_variables, system = system) end @inline function save_solution_file(u_ode, t, dt, iter, semi::AbstractSemidiscretization, solution_callback, - element_variables = Dict{Symbol, Any}(); + element_variables = Dict{Symbol, Any}(), + node_variables = Dict{Symbol, Any}(); system = "") mesh, equations, solver, cache = mesh_equations_solver_cache(semi) u = wrap_array_native(u_ode, mesh, equations, solver, cache) save_solution_file(u, t, dt, iter, mesh, equations, solver, cache, solution_callback, - element_variables; system = system) + element_variables, + node_variables; system = system) end # TODO: Taal refactor, move save_mesh_file? diff --git a/src/callbacks_step/save_solution_dg.jl b/src/callbacks_step/save_solution_dg.jl index 6d5004ff65f..350aee7336a 100644 --- a/src/callbacks_step/save_solution_dg.jl +++ b/src/callbacks_step/save_solution_dg.jl @@ -10,7 +10,9 @@ function save_solution_file(u, time, dt, timestep, UnstructuredMesh2D, SerialP4estMesh, SerialT8codeMesh}, equations, dg::DG, cache, - solution_callback, element_variables = Dict{Symbol, Any}(); + solution_callback, + element_variables = Dict{Symbol, Any}(), + node_variables = Dict{Symbol, Any}(); system = "") @unpack output_directory, solution_variables = solution_callback @@ -31,8 +33,7 @@ function save_solution_file(u, time, dt, timestep, # compute the solution variables via broadcasting, and reinterpret the # result as a plain array of floating point numbers data = Array(reinterpret(eltype(u), - solution_variables.(reinterpret(SVector{ - nvariables(equations), + solution_variables.(reinterpret(SVector{nvariables(equations), eltype(u)}, u), Ref(equations)))) @@ -73,6 +74,16 @@ function save_solution_file(u, time, dt, timestep, var = file["element_variables_$v"] attributes(var)["name"] = string(key) end + + # Store node variables + for (v, (key, node_variable)) in enumerate(node_variables) + # Add to file + file["node_variables_$v"] = node_variable + + # Add variable name as attribute + var = file["node_variables_$v"] + attributes(var)["name"] = string(key) + end end return filename @@ -81,7 +92,9 @@ end function save_solution_file(u, time, dt, timestep, mesh::Union{ParallelTreeMesh, ParallelP4estMesh}, equations, dg::DG, cache, - solution_callback, element_variables = Dict{Symbol, Any}(); + solution_callback, + element_variables = Dict{Symbol, Any}(), + node_variables = Dict{Symbol, Any}(); system = "") @unpack output_directory, solution_variables = solution_callback @@ -102,8 +115,7 @@ function save_solution_file(u, time, dt, timestep, # compute the solution variables via broadcasting, and reinterpret the # result as a plain array of floating point numbers data = Array(reinterpret(eltype(u), - solution_variables.(reinterpret(SVector{ - nvariables(equations), + solution_variables.(reinterpret(SVector{nvariables(equations), eltype(u)}, u), Ref(equations)))) diff --git a/src/callbacks_step/summary.jl b/src/callbacks_step/summary.jl index 26981a58b73..566f2c03418 100644 --- a/src/callbacks_step/summary.jl +++ b/src/callbacks_step/summary.jl @@ -168,16 +168,17 @@ function initialize_summary_callback(cb::DiscreteCallback, u, t, integrator; callbacks = integrator.opts.callback if callbacks isa CallbackSet - for cb in callbacks.continuous_callbacks + foreach(callbacks.continuous_callbacks) do cb show(io_context, MIME"text/plain"(), cb) println(io, "\n") end - for cb in callbacks.discrete_callbacks + foreach(callbacks.discrete_callbacks) do cb # Do not show ourselves - cb.affect! === summary_callback && continue + cb.affect! === summary_callback && return nothing show(io_context, MIME"text/plain"(), cb) println(io, "\n") + return nothing end else show(io_context, MIME"text/plain"(), callbacks) diff --git a/src/equations/compressible_euler_1d.jl b/src/equations/compressible_euler_1d.jl index 9204989e8be..05c38ce791d 100644 --- a/src/equations/compressible_euler_1d.jl +++ b/src/equations/compressible_euler_1d.jl @@ -808,7 +808,7 @@ function flux_hllc(u_ll, u_rr, orientation::Integer, end """ - flux_hlle(u_ll, u_rr, orientation, equations::CompressibleEulerEquations1D) + 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 @@ -825,8 +825,8 @@ Compactly summarized: Numerical methods for conservation laws and related equations. [Link](https://metaphor.ethz.ch/x/2019/hs/401-4671-00L/literature/mishra_hyperbolic_pdes.pdf) """ -function flux_hlle(u_ll, u_rr, orientation::Integer, - equations::CompressibleEulerEquations1D) +@inline function min_max_speed_einfeldt(u_ll, u_rr, orientation::Integer, + equations::CompressibleEulerEquations1D) # Calculate primitive variables, enthalpy and speed of sound rho_ll, v_ll, p_ll = cons2prim(u_ll, equations) rho_rr, v_rr, p_rr = cons2prim(u_rr, equations) @@ -858,35 +858,7 @@ function flux_hlle(u_ll, u_rr, orientation::Integer, SsL = min(v_roe - c_roe, v_ll - beta * c_ll, zero(v_roe)) SsR = max(v_roe + c_roe, v_rr + beta * c_rr, zero(v_roe)) - if SsL >= 0.0 && SsR > 0.0 - # Positive supersonic speed - f_ll = flux(u_ll, orientation, equations) - - f1 = f_ll[1] - f2 = f_ll[2] - f3 = f_ll[3] - elseif SsR <= 0.0 && SsL < 0.0 - # Negative supersonic speed - f_rr = flux(u_rr, orientation, equations) - - f1 = f_rr[1] - f2 = f_rr[2] - f3 = f_rr[3] - else - # Subsonic case - # Compute left and right fluxes - f_ll = flux(u_ll, orientation, equations) - f_rr = flux(u_rr, orientation, equations) - - f1 = (SsR * f_ll[1] - SsL * f_rr[1] + SsL * SsR * (u_rr[1] - u_ll[1])) / - (SsR - SsL) - f2 = (SsR * f_ll[2] - SsL * f_rr[2] + SsL * SsR * (u_rr[2] - u_ll[2])) / - (SsR - SsL) - f3 = (SsR * f_ll[3] - SsL * f_rr[3] + SsL * SsR * (u_rr[3] - u_ll[3])) / - (SsR - SsL) - end - - return SVector(f1, f2, f3) + return SsL, SsR end @inline function max_abs_speeds(u, equations::CompressibleEulerEquations1D) diff --git a/src/equations/compressible_euler_2d.jl b/src/equations/compressible_euler_2d.jl index 27b92f41953..a992f99eaf4 100644 --- a/src/equations/compressible_euler_2d.jl +++ b/src/equations/compressible_euler_2d.jl @@ -1253,7 +1253,7 @@ function flux_hllc(u_ll, u_rr, orientation::Integer, end """ - flux_hlle(u_ll, u_rr, orientation, equations::CompressibleEulerEquations2D) + 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 @@ -1267,8 +1267,8 @@ of the numerical flux. On Godunov-type methods near low densities. [DOI: 10.1016/0021-9991(91)90211-3](https://doi.org/10.1016/0021-9991(91)90211-3) """ -function flux_hlle(u_ll, u_rr, orientation::Integer, - equations::CompressibleEulerEquations2D) +@inline function min_max_speed_einfeldt(u_ll, u_rr, orientation::Integer, + equations::CompressibleEulerEquations2D) # Calculate primitive variables, enthalpy and speed of sound rho_ll, v1_ll, v2_ll, p_ll = cons2prim(u_ll, equations) rho_rr, v1_rr, v2_rr, p_rr = cons2prim(u_rr, equations) @@ -1306,39 +1306,65 @@ function flux_hlle(u_ll, u_rr, orientation::Integer, SsR = max(v2_roe + c_roe, v2_rr + beta * c_rr, zero(v2_roe)) end - if SsL >= 0.0 && SsR > 0.0 - # Positive supersonic speed - f_ll = flux(u_ll, orientation, equations) + return SsL, SsR +end - f1 = f_ll[1] - f2 = f_ll[2] - f3 = f_ll[3] - f4 = f_ll[4] - elseif SsR <= 0.0 && SsL < 0.0 - # Negative supersonic speed - f_rr = flux(u_rr, orientation, equations) +""" + min_max_speed_einfeldt(u_ll, u_rr, normal_direction, equations::CompressibleEulerEquations2D) - f1 = f_rr[1] - f2 = f_rr[2] - f3 = f_rr[3] - f4 = f_rr[4] - else - # Subsonic case - # Compute left and right fluxes - f_ll = flux(u_ll, orientation, equations) - f_rr = flux(u_rr, orientation, equations) - - f1 = (SsR * f_ll[1] - SsL * f_rr[1] + SsL * SsR * (u_rr[1] - u_ll[1])) / - (SsR - SsL) - f2 = (SsR * f_ll[2] - SsL * f_rr[2] + SsL * SsR * (u_rr[2] - u_ll[2])) / - (SsR - SsL) - f3 = (SsR * f_ll[3] - SsL * f_rr[3] + SsL * SsR * (u_rr[3] - u_ll[3])) / - (SsR - SsL) - f4 = (SsR * f_ll[4] - SsL * f_rr[4] + SsL * SsR * (u_rr[4] - u_ll[4])) / - (SsR - SsL) - end +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. - return SVector(f1, f2, f3, f4) +- Bernd Einfeldt (1988) + On Godunov-type methods for gas dynamics. + [DOI: 10.1137/0725021](https://doi.org/10.1137/0725021) +- Bernd Einfeldt, Claus-Dieter Munz, Philip L. Roe and Björn Sjögreen (1991) + On Godunov-type methods near low densities. + [DOI: 10.1016/0021-9991(91)90211-3](https://doi.org/10.1016/0021-9991(91)90211-3) +""" +@inline function min_max_speed_einfeldt(u_ll, u_rr, normal_direction::AbstractVector, + equations::CompressibleEulerEquations2D) + # Calculate primitive variables, enthalpy and speed of sound + rho_ll, v1_ll, v2_ll, p_ll = cons2prim(u_ll, equations) + rho_rr, v1_rr, v2_rr, p_rr = cons2prim(u_rr, equations) + + v_dot_n_ll = v1_ll * normal_direction[1] + v2_ll * normal_direction[2] + v_dot_n_rr = v1_rr * normal_direction[1] + v2_rr * normal_direction[2] + + norm_ = norm(normal_direction) + + # `u_ll[4]` is total energy `rho_e_ll` on the left + H_ll = (u_ll[4] + p_ll) / rho_ll + c_ll = sqrt(equations.gamma * p_ll / rho_ll) * norm_ + + # `u_rr[4]` is total energy `rho_e_rr` on the right + H_rr = (u_rr[4] + p_rr) / rho_rr + c_rr = sqrt(equations.gamma * p_rr / rho_rr) * norm_ + + # Compute Roe averages + sqrt_rho_ll = sqrt(rho_ll) + sqrt_rho_rr = sqrt(rho_rr) + inv_sum_sqrt_rho = inv(sqrt_rho_ll + sqrt_rho_rr) + + v1_roe = (sqrt_rho_ll * v1_ll + sqrt_rho_rr * v1_rr) * inv_sum_sqrt_rho + v2_roe = (sqrt_rho_ll * v2_ll + sqrt_rho_rr * v2_rr) * inv_sum_sqrt_rho + v_roe = v1_roe * normal_direction[1] + v2_roe * normal_direction[2] + v_roe_mag = v1_roe^2 + v2_roe^2 + + H_roe = (sqrt_rho_ll * H_ll + sqrt_rho_rr * H_rr) * inv_sum_sqrt_rho + c_roe = sqrt((equations.gamma - 1) * (H_roe - 0.5 * v_roe_mag)) * norm_ + + # Compute convenience constant for positivity preservation, see + # https://doi.org/10.1016/0021-9991(91)90211-3 + beta = sqrt(0.5 * (equations.gamma - 1) / equations.gamma) + + # Estimate the edges of the Riemann fan (with positivity conservation) + SsL = min(v_roe - c_roe, v_dot_n_ll - beta * c_ll, zero(v_roe)) + SsR = max(v_roe + c_roe, v_dot_n_rr + beta * c_rr, zero(v_roe)) + + return SsL, SsR end @inline function max_abs_speeds(u, equations::CompressibleEulerEquations2D) diff --git a/src/equations/compressible_euler_3d.jl b/src/equations/compressible_euler_3d.jl index 7f25bde31fd..fc56f58025b 100644 --- a/src/equations/compressible_euler_3d.jl +++ b/src/equations/compressible_euler_3d.jl @@ -1322,7 +1322,7 @@ function flux_hllc(u_ll, u_rr, orientation::Integer, end """ - flux_hlle(u_ll, u_rr, orientation, equations::CompressibleEulerEquations3D) + 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 @@ -1336,8 +1336,8 @@ of the numerical flux. On Godunov-type methods near low densities. [DOI: 10.1016/0021-9991(91)90211-3](https://doi.org/10.1016/0021-9991(91)90211-3) """ -function flux_hlle(u_ll, u_rr, orientation::Integer, - equations::CompressibleEulerEquations3D) +@inline function min_max_speed_einfeldt(u_ll, u_rr, orientation::Integer, + equations::CompressibleEulerEquations3D) # Calculate primitive variables, enthalpy and speed of sound rho_ll, v1_ll, v2_ll, v3_ll, p_ll = cons2prim(u_ll, equations) rho_rr, v1_rr, v2_rr, v3_rr, p_rr = cons2prim(u_rr, equations) @@ -1379,43 +1379,69 @@ function flux_hlle(u_ll, u_rr, orientation::Integer, SsR = max(v3_roe + c_roe, v3_rr + beta * c_rr, zero(v3_roe)) end - if SsL >= 0.0 && SsR > 0.0 - # Positive supersonic speed - f_ll = flux(u_ll, orientation, equations) + return SsL, SsR +end - f1 = f_ll[1] - f2 = f_ll[2] - f3 = f_ll[3] - f4 = f_ll[4] - f5 = f_ll[5] - elseif SsR <= 0.0 && SsL < 0.0 - # Negative supersonic speed - f_rr = flux(u_rr, orientation, equations) +""" + min_max_speed_einfeldt(u_ll, u_rr, normal_direction, equations::CompressibleEulerEquations3D) - f1 = f_rr[1] - f2 = f_rr[2] - f3 = f_rr[3] - f4 = f_rr[4] - f5 = f_rr[5] - else - # Subsonic case - # Compute left and right fluxes - f_ll = flux(u_ll, orientation, equations) - f_rr = flux(u_rr, orientation, equations) - - f1 = (SsR * f_ll[1] - SsL * f_rr[1] + SsL * SsR * (u_rr[1] - u_ll[1])) / - (SsR - SsL) - f2 = (SsR * f_ll[2] - SsL * f_rr[2] + SsL * SsR * (u_rr[2] - u_ll[2])) / - (SsR - SsL) - f3 = (SsR * f_ll[3] - SsL * f_rr[3] + SsL * SsR * (u_rr[3] - u_ll[3])) / - (SsR - SsL) - f4 = (SsR * f_ll[4] - SsL * f_rr[4] + SsL * SsR * (u_rr[4] - u_ll[4])) / - (SsR - SsL) - f5 = (SsR * f_ll[5] - SsL * f_rr[5] + SsL * SsR * (u_rr[5] - u_ll[5])) / - (SsR - SsL) - end +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. - return SVector(f1, f2, f3, f4, f5) +- Bernd Einfeldt (1988) + On Godunov-type methods for gas dynamics. + [DOI: 10.1137/0725021](https://doi.org/10.1137/0725021) +- Bernd Einfeldt, Claus-Dieter Munz, Philip L. Roe and Björn Sjögreen (1991) + On Godunov-type methods near low densities. + [DOI: 10.1016/0021-9991(91)90211-3](https://doi.org/10.1016/0021-9991(91)90211-3) +""" +@inline function min_max_speed_einfeldt(u_ll, u_rr, normal_direction::AbstractVector, + equations::CompressibleEulerEquations3D) + # Calculate primitive variables, enthalpy and speed of sound + rho_ll, v1_ll, v2_ll, v3_ll, p_ll = cons2prim(u_ll, equations) + rho_rr, v1_rr, v2_rr, v3_rr, p_rr = cons2prim(u_rr, equations) + + v_dot_n_ll = v1_ll * normal_direction[1] + v2_ll * normal_direction[2] + + v3_ll * normal_direction[3] + v_dot_n_rr = v1_rr * normal_direction[1] + v2_rr * normal_direction[2] + + v3_rr * normal_direction[3] + + norm_ = norm(normal_direction) + + # `u_ll[5]` is total energy `rho_e_ll` on the left + H_ll = (u_ll[5] + p_ll) / rho_ll + c_ll = sqrt(equations.gamma * p_ll / rho_ll) * norm_ + + # `u_rr[5]` is total energy `rho_e_rr` on the right + H_rr = (u_rr[5] + p_rr) / rho_rr + c_rr = sqrt(equations.gamma * p_rr / rho_rr) * norm_ + + # Compute Roe averages + sqrt_rho_ll = sqrt(rho_ll) + sqrt_rho_rr = sqrt(rho_rr) + inv_sum_sqrt_rho = inv(sqrt_rho_ll + sqrt_rho_rr) + + v1_roe = (sqrt_rho_ll * v1_ll + sqrt_rho_rr * v1_rr) * inv_sum_sqrt_rho + v2_roe = (sqrt_rho_ll * v2_ll + sqrt_rho_rr * v2_rr) * inv_sum_sqrt_rho + v3_roe = (sqrt_rho_ll * v3_ll + sqrt_rho_rr * v3_rr) * inv_sum_sqrt_rho + v_roe = v1_roe * normal_direction[1] + v2_roe * normal_direction[2] + + v3_roe * normal_direction[3] + v_roe_mag = v1_roe^2 + v2_roe^2 + v3_roe^2 + + H_roe = (sqrt_rho_ll * H_ll + sqrt_rho_rr * H_rr) * inv_sum_sqrt_rho + c_roe = sqrt((equations.gamma - 1) * (H_roe - 0.5 * v_roe_mag)) * norm_ + + # Compute convenience constant for positivity preservation, see + # https://doi.org/10.1016/0021-9991(91)90211-3 + beta = sqrt(0.5 * (equations.gamma - 1) / equations.gamma) + + # Estimate the edges of the Riemann fan (with positivity conservation) + SsL = min(v_roe - c_roe, v_dot_n_ll - beta * c_ll, zero(v_roe)) + SsR = max(v_roe + c_roe, v_dot_n_rr + beta * c_rr, zero(v_roe)) + + return SsL, SsR end @inline function max_abs_speeds(u, equations::CompressibleEulerEquations3D) diff --git a/src/equations/compressible_euler_multicomponent_1d.jl b/src/equations/compressible_euler_multicomponent_1d.jl index 23ac222b976..6338e04c3ed 100644 --- a/src/equations/compressible_euler_multicomponent_1d.jl +++ b/src/equations/compressible_euler_multicomponent_1d.jl @@ -54,19 +54,15 @@ struct CompressibleEulerMulticomponentEquations1D{NVARS, NCOMP, RealT <: Real} < cv::SVector{NCOMP, RealT} cp::SVector{NCOMP, RealT} - function CompressibleEulerMulticomponentEquations1D{NVARS, NCOMP, RealT}(gammas::SVector{ - NCOMP, - RealT - }, - gas_constants::SVector{ - NCOMP, - RealT - }) where { - NVARS, - NCOMP, - RealT <: - Real - } + function CompressibleEulerMulticomponentEquations1D{NVARS, NCOMP, RealT}(gammas::SVector{NCOMP, + RealT}, + gas_constants::SVector{NCOMP, + RealT}) where { + NVARS, + NCOMP, + RealT <: + Real + } NCOMP >= 1 || throw(DimensionMismatch("`gammas` and `gas_constants` have to be filled with at least one value")) @@ -465,6 +461,7 @@ end # Convert conservative variables to entropy @inline function cons2entropy(u, equations::CompressibleEulerMulticomponentEquations1D) @unpack cv, gammas, gas_constants = equations + rho_v1, rho_e = u rho = density(u, equations) @@ -484,21 +481,86 @@ end s = log(p) - gamma * log(rho) - log(gas_constant) rho_p = rho / p T = (rho_e - 0.5 * rho * v_square) / (help1) - entrop_rho = SVector{ncomponents(equations), real(equations)}(gas_constant * - ((gamma - s) / - (gamma - 1.0) - - (0.5 * v_square * - rho_p)) + + entrop_rho = SVector{ncomponents(equations), real(equations)}((cv[i] * + (1 - log(T)) + + gas_constants[i] * + (1 + log(u[i + 2])) - + v1^2 / (2 * T)) for i in eachcomponent(equations)) w1 = gas_constant * v1 * rho_p - w2 = gas_constant * (-1.0 * rho_p) + w2 = gas_constant * (-rho_p) entrop_other = SVector{2, real(equations)}(w1, w2) return vcat(entrop_other, entrop_rho) end +# Convert entropy variables to conservative variables +@inline function entropy2cons(w, equations::CompressibleEulerMulticomponentEquations1D) + @unpack gammas, gas_constants, cv, cp = equations + T = -1 / w[2] + v1 = w[1] * T + cons_rho = SVector{ncomponents(equations), real(equations)}(exp(1 / + gas_constants[i] * + (-cv[i] * + log(-w[2]) - + cp[i] + w[i + 2] - + 0.5 * w[1]^2 / + w[2])) + for i in eachcomponent(equations)) + + rho = zero(cons_rho[1]) + help1 = zero(cons_rho[1]) + help2 = zero(cons_rho[1]) + p = zero(cons_rho[1]) + for i in eachcomponent(equations) + rho += cons_rho[i] + help1 += cons_rho[i] * cv[i] * gammas[i] + help2 += cons_rho[i] * cv[i] + p += cons_rho[i] * gas_constants[i] * T + end + u1 = rho * v1 + gamma = help1 / help2 + u2 = p / (gamma - 1) + 0.5 * rho * v1^2 + cons_other = SVector{2, real(equations)}(u1, u2) + return vcat(cons_other, cons_rho) +end + +@inline function total_entropy(u, equations::CompressibleEulerMulticomponentEquations1D) + @unpack cv, gammas, gas_constants = equations + rho_v1, rho_e = u + rho = density(u, equations) + T = temperature(u, equations) + + total_entropy = zero(u[1]) + for i in eachcomponent(equations) + total_entropy -= u[i + 2] * (cv[i] * log(T) - gas_constants[i] * log(u[i + 2])) + end + + return total_entropy +end + +@inline function temperature(u, equations::CompressibleEulerMulticomponentEquations1D) + @unpack cv, gammas, gas_constants = equations + + rho_v1, rho_e = u + + rho = density(u, equations) + help1 = zero(rho) + + for i in eachcomponent(equations) + help1 += u[i + 2] * cv[i] + end + + v1 = rho_v1 / rho + v_square = v1^2 + T = (rho_e - 0.5 * rho * v_square) / help1 + + return T +end + """ totalgamma(u, equations::CompressibleEulerMulticomponentEquations1D) diff --git a/src/equations/compressible_euler_multicomponent_2d.jl b/src/equations/compressible_euler_multicomponent_2d.jl index 7b437f4a1b4..60fce222f21 100644 --- a/src/equations/compressible_euler_multicomponent_2d.jl +++ b/src/equations/compressible_euler_multicomponent_2d.jl @@ -58,19 +58,15 @@ struct CompressibleEulerMulticomponentEquations2D{NVARS, NCOMP, RealT <: Real} < cv::SVector{NCOMP, RealT} cp::SVector{NCOMP, RealT} - function CompressibleEulerMulticomponentEquations2D{NVARS, NCOMP, RealT}(gammas::SVector{ - NCOMP, - RealT - }, - gas_constants::SVector{ - NCOMP, - RealT - }) where { - NVARS, - NCOMP, - RealT <: - Real - } + function CompressibleEulerMulticomponentEquations2D{NVARS, NCOMP, RealT}(gammas::SVector{NCOMP, + RealT}, + gas_constants::SVector{NCOMP, + RealT}) where { + NVARS, + NCOMP, + RealT <: + Real + } NCOMP >= 1 || throw(DimensionMismatch("`gammas` and `gas_constants` have to be filled with at least one value")) @@ -270,6 +266,29 @@ end return vcat(f_other, f_rho) end +# Calculate 1D flux for a single point +@inline function flux(u, normal_direction::AbstractVector, + equations::CompressibleEulerMulticomponentEquations2D) + rho_v1, rho_v2, rho_e = u + + rho = density(u, equations) + + v1 = rho_v1 / rho + v2 = rho_v2 / rho + v_normal = v1 * normal_direction[1] + v2 * normal_direction[2] + gamma = totalgamma(u, equations) + p = (gamma - 1) * (rho_e - 0.5 * rho * (v1^2 + v2^2)) + + f_rho = densities(u, v_normal, equations) + f1 = rho_v1 * v_normal + p * normal_direction[1] + f2 = rho_v2 * v_normal + p * normal_direction[2] + f3 = (rho_e + p) * v_normal + + f_other = SVector{3, real(equations)}(f1, f2, f3) + + return vcat(f_other, f_rho) +end + """ flux_chandrashekar(u_ll, u_rr, orientation, equations::CompressibleEulerMulticomponentEquations2D) @@ -446,6 +465,76 @@ See also return vcat(f_other, f_rho) end +@inline function flux_ranocha(u_ll, u_rr, normal_direction::AbstractVector, + equations::CompressibleEulerMulticomponentEquations2D) + # Unpack left and right state + @unpack gammas, gas_constants, cv = equations + rho_v1_ll, rho_v2_ll, rho_e_ll = u_ll + rho_v1_rr, rho_v2_rr, rho_e_rr = u_rr + rhok_mean = SVector{ncomponents(equations), real(equations)}(ln_mean(u_ll[i + 3], + u_rr[i + 3]) + for i in eachcomponent(equations)) + rhok_avg = SVector{ncomponents(equations), real(equations)}(0.5 * (u_ll[i + 3] + + u_rr[i + 3]) + for i in eachcomponent(equations)) + + # Iterating over all partial densities + rho_ll = density(u_ll, equations) + rho_rr = density(u_rr, equations) + + # Calculating gamma + gamma = totalgamma(0.5 * (u_ll + u_rr), equations) + inv_gamma_minus_one = 1 / (gamma - 1) + + # extract velocities + v1_ll = rho_v1_ll / rho_ll + v1_rr = rho_v1_rr / rho_rr + v1_avg = 0.5 * (v1_ll + v1_rr) + v2_ll = rho_v2_ll / rho_ll + v2_rr = rho_v2_rr / rho_rr + v2_avg = 0.5 * (v2_ll + v2_rr) + velocity_square_avg = 0.5 * (v1_ll * v1_rr + v2_ll * v2_rr) + v_dot_n_ll = v1_ll * normal_direction[1] + v2_ll * normal_direction[2] + v_dot_n_rr = v1_rr * normal_direction[1] + v2_rr * normal_direction[2] + + # helpful variables + help1_ll = zero(v1_ll) + help1_rr = zero(v1_rr) + enth_ll = zero(v1_ll) + enth_rr = zero(v1_rr) + for i in eachcomponent(equations) + enth_ll += u_ll[i + 3] * gas_constants[i] + enth_rr += u_rr[i + 3] * gas_constants[i] + help1_ll += u_ll[i + 3] * cv[i] + help1_rr += u_rr[i + 3] * cv[i] + end + + # temperature and pressure + T_ll = (rho_e_ll - 0.5 * rho_ll * (v1_ll^2 + v2_ll^2)) / help1_ll + T_rr = (rho_e_rr - 0.5 * rho_rr * (v1_rr^2 + v2_rr^2)) / help1_rr + p_ll = T_ll * enth_ll + p_rr = T_rr * enth_rr + p_avg = 0.5 * (p_ll + p_rr) + inv_rho_p_mean = p_ll * p_rr * inv_ln_mean(rho_ll * p_rr, rho_rr * p_ll) + + f_rho_sum = zero(T_rr) + f_rho = SVector{ncomponents(equations), real(equations)}(rhok_mean[i] * 0.5 * + (v_dot_n_ll + v_dot_n_rr) + for i in eachcomponent(equations)) + for i in eachcomponent(equations) + f_rho_sum += f_rho[i] + end + f1 = f_rho_sum * v1_avg + p_avg * normal_direction[1] + f2 = f_rho_sum * v2_avg + p_avg * normal_direction[2] + f3 = f_rho_sum * (velocity_square_avg + inv_rho_p_mean * inv_gamma_minus_one) + + 0.5 * (p_ll * v_dot_n_rr + p_rr * v_dot_n_ll) + + # momentum and energy flux + f_other = SVector(f1, f2, f3) + + return vcat(f_other, f_rho) +end + # Calculate maximum wave speed for local Lax-Friedrichs-type dissipation @inline function max_abs_speed_naive(u_ll, u_rr, orientation::Integer, equations::CompressibleEulerMulticomponentEquations2D) @@ -491,6 +580,50 @@ end return (abs(v1) + c, abs(v2) + c) end +@inline function rotate_to_x(u, normal_vector, + equations::CompressibleEulerMulticomponentEquations2D) + # cos and sin of the angle between the x-axis and the normalized normal_vector are + # the normalized vector's x and y coordinates respectively (see unit circle). + c = normal_vector[1] + s = normal_vector[2] + + # Apply the 2D rotation matrix with normal and tangent directions of the form + # [ n_1 n_2 0 0; + # t_1 t_2 0 0; + # 0 0 1 0 + # 0 0 0 1] + # where t_1 = -n_2 and t_2 = n_1 + + densities = @view u[4:end] + return SVector(c * u[1] + s * u[2], + -s * u[1] + c * u[2], + u[3], + densities...) +end + +# Called inside `FluxRotated` in `numerical_fluxes.jl` so the direction +# has been normalized prior to this back-rotation of the state vector +@inline function rotate_from_x(u, normal_vector, + equations::CompressibleEulerMulticomponentEquations2D) + # cos and sin of the angle between the x-axis and the normalized normal_vector are + # the normalized vector's x and y coordinates respectively (see unit circle). + c = normal_vector[1] + s = normal_vector[2] + + # Apply the 2D back-rotation matrix with normal and tangent directions of the form + # [ n_1 t_1 0 0; + # n_2 t_2 0 0; + # 0 0 1 0; + # 0 0 0 1 ] + # where t_1 = -n_2 and t_2 = n_1 + + densities = @view u[4:end] + return SVector(c * u[1] - s * u[2], + s * u[1] + c * u[2], + u[3], + densities...) +end + # Convert conservative variables to primitive @inline function cons2prim(u, equations::CompressibleEulerMulticomponentEquations2D) rho_v1, rho_v2, rho_e = u @@ -532,22 +665,57 @@ end s = log(p) - gamma * log(rho) - log(gas_constant) rho_p = rho / p T = (rho_e - 0.5 * rho * v_square) / (help1) - entrop_rho = SVector{ncomponents(equations), real(equations)}(gas_constant * - ((gamma - s) / - (gamma - 1.0) - - (0.5 * v_square * - rho_p)) + + entrop_rho = SVector{ncomponents(equations), real(equations)}((cv[i] * + (1 - log(T)) + + gas_constants[i] * + (1 + log(u[i + 3])) - + v_square / (2 * T)) for i in eachcomponent(equations)) w1 = gas_constant * v1 * rho_p w2 = gas_constant * v2 * rho_p - w3 = gas_constant * rho_p * (-1) + w3 = gas_constant * (-rho_p) entrop_other = SVector{3, real(equations)}(w1, w2, w3) return vcat(entrop_other, entrop_rho) end +# Convert entropy variables to conservative variables +@inline function entropy2cons(w, equations::CompressibleEulerMulticomponentEquations2D) + @unpack gammas, gas_constants, cp, cv = equations + T = -1 / w[3] + v1 = w[1] * T + v2 = w[2] * T + v_squared = v1^2 + v2^2 + cons_rho = SVector{ncomponents(equations), real(equations)}(exp((w[i + 3] - + cv[i] * + (1 - log(T)) + + v_squared / + (2 * T)) / + gas_constants[i] - + 1) + for i in eachcomponent(equations)) + + rho = zero(cons_rho[1]) + help1 = zero(cons_rho[1]) + help2 = zero(cons_rho[1]) + p = zero(cons_rho[1]) + for i in eachcomponent(equations) + rho += cons_rho[i] + help1 += cons_rho[i] * cv[i] * gammas[i] + help2 += cons_rho[i] * cv[i] + p += cons_rho[i] * gas_constants[i] * T + end + u1 = rho * v1 + u2 = rho * v2 + gamma = help1 / help2 + u3 = p / (gamma - 1) + 0.5 * rho * v_squared + cons_other = SVector{3, real(equations)}(u1, u2, u3) + return vcat(cons_other, cons_rho) +end + # Convert primitive to conservative variables @inline function prim2cons(prim, equations::CompressibleEulerMulticomponentEquations2D) @unpack cv, gammas = equations @@ -567,6 +735,39 @@ end return vcat(cons_other, cons_rho) end +@inline function total_entropy(u, equations::CompressibleEulerMulticomponentEquations2D) + @unpack cv, gammas, gas_constants = equations + rho = density(u, equations) + T = temperature(u, equations) + + total_entropy = zero(u[1]) + for i in eachcomponent(equations) + total_entropy -= u[i + 3] * (cv[i] * log(T) - gas_constants[i] * log(u[i + 3])) + end + + return total_entropy +end + +@inline function temperature(u, equations::CompressibleEulerMulticomponentEquations2D) + @unpack cv, gammas, gas_constants = equations + + rho_v1, rho_v2, rho_e = u + + rho = density(u, equations) + help1 = zero(rho) + + for i in eachcomponent(equations) + help1 += u[i + 3] * cv[i] + end + + v1 = rho_v1 / rho + v2 = rho_v2 / rho + v_square = v1^2 + v2^2 + T = (rho_e - 0.5 * rho * v_square) / help1 + + return T +end + """ totalgamma(u, equations::CompressibleEulerMulticomponentEquations2D) diff --git a/src/equations/compressible_euler_quasi_1d.jl b/src/equations/compressible_euler_quasi_1d.jl new file mode 100644 index 00000000000..0a543277ee4 --- /dev/null +++ b/src/equations/compressible_euler_quasi_1d.jl @@ -0,0 +1,328 @@ +# By default, Julia/LLVM does not use fused multiply-add operations (FMAs). +# Since these FMAs can increase the performance of many numerical algorithms, +# we need to opt-in explicitly. +# See https://ranocha.de/blog/Optimizing_EC_Trixi for further details. +@muladd begin +#! format: noindent + +@doc raw""" + CompressibleEulerEquationsQuasi1D(gamma) + +The quasi-1d compressible Euler equations (see Chan et al. [DOI: 10.48550/arXiv.2307.12089](https://doi.org/10.48550/arXiv.2307.12089) for details) +```math +\frac{\partial}{\partial t} +\begin{pmatrix} +a \rho \\ a \rho v_1 \\ a e +\end{pmatrix} ++ +\frac{\partial}{\partial x} +\begin{pmatrix} +a \rho v_1 \\ a \rho v_1^2 \\ a v_1 (e +p) +\end{pmatrix} ++ +a \frac{\partial}{\partial x} +\begin{pmatrix} +0 \\ p \\ 0 +\end{pmatrix} += +\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, +``a`` the (possibly) variable nozzle width, and +```math +p = (\gamma - 1) \left( e - \frac{1}{2} \rho v_1^2 \right) +``` +the pressure. + +The nozzle width function ``a(x)`` is set inside the initial condition routine +for a particular problem setup. To test the conservative form of the compressible Euler equations one can set the +nozzle width variable ``a`` to one. + +In addition to the unknowns, Trixi.jl currently stores the nozzle width values at the approximation points +despite being fixed in time. +This affects the implementation and use of these equations in various ways: +* The flux values corresponding to the nozzle width must be zero. +* The nozzle width values must be included when defining initial conditions, boundary conditions or + source terms. +* [`AnalysisCallback`](@ref) analyzes this variable. +* Trixi.jl's visualization tools will visualize the nozzle width by default. +""" +struct CompressibleEulerEquationsQuasi1D{RealT <: Real} <: + AbstractCompressibleEulerEquations{1, 4} + gamma::RealT # ratio of specific heats + inv_gamma_minus_one::RealT # = inv(gamma - 1); can be used to write slow divisions as fast multiplications + + function CompressibleEulerEquationsQuasi1D(gamma) + γ, inv_gamma_minus_one = promote(gamma, inv(gamma - 1)) + new{typeof(γ)}(γ, inv_gamma_minus_one) + end +end + +have_nonconservative_terms(::CompressibleEulerEquationsQuasi1D) = True() +function varnames(::typeof(cons2cons), ::CompressibleEulerEquationsQuasi1D) + ("a_rho", "a_rho_v1", "a_e", "a") +end +function varnames(::typeof(cons2prim), ::CompressibleEulerEquationsQuasi1D) + ("rho", "v1", "p", "a") +end + +""" + initial_condition_convergence_test(x, t, equations::CompressibleEulerEquationsQuasi1D) + +A smooth initial condition used for convergence tests in combination with +[`source_terms_convergence_test`](@ref) +(and [`BoundaryConditionDirichlet(initial_condition_convergence_test)`](@ref) in non-periodic domains). +""" +function initial_condition_convergence_test(x, t, + equations::CompressibleEulerEquationsQuasi1D) + c = 2 + A = 0.1 + L = 2 + f = 1 / L + ω = 2 * pi * f + ini = c + A * sin(ω * (x[1] - t)) + + rho = ini + v1 = 1.0 + e = ini^2 / rho + p = (equations.gamma - 1) * (e - 0.5 * rho * v1^2) + a = 1.5 - 0.5 * cos(x[1] * pi) + + return prim2cons(SVector(rho, v1, p, a), equations) +end + +""" + source_terms_convergence_test(u, x, t, equations::CompressibleEulerEquationsQuasi1D) + +Source terms used for convergence tests in combination with +[`initial_condition_convergence_test`](@ref) +(and [`BoundaryConditionDirichlet(initial_condition_convergence_test)`](@ref) in non-periodic domains). + +This manufactured solution source term is specifically designed for the mozzle width 'a(x) = 1.5 - 0.5 * cos(x[1] * pi)' +as defined in [`initial_condition_convergence_test`](@ref). +""" +@inline function source_terms_convergence_test(u, x, t, + equations::CompressibleEulerEquationsQuasi1D) + # Same settings as in `initial_condition_convergence_test`. + # Derivatives calculated with ForwardDiff.jl + c = 2 + A = 0.1 + L = 2 + f = 1 / L + ω = 2 * pi * f + x1, = x + ini(x1, t) = c + A * sin(ω * (x1 - t)) + + rho(x1, t) = ini(x1, t) + v1(x1, t) = 1.0 + e(x1, t) = ini(x1, t)^2 / rho(x1, t) + p1(x1, t) = (equations.gamma - 1) * (e(x1, t) - 0.5 * rho(x1, t) * v1(x1, t)^2) + a(x1, t) = 1.5 - 0.5 * cos(x1 * pi) + + arho(x1, t) = a(x1, t) * rho(x1, t) + arhou(x1, t) = arho(x1, t) * v1(x1, t) + aE(x1, t) = a(x1, t) * e(x1, t) + + darho_dt(x1, t) = ForwardDiff.derivative(t -> arho(x1, t), t) + darhou_dx(x1, t) = ForwardDiff.derivative(x1 -> arhou(x1, t), x1) + + arhouu(x1, t) = arhou(x1, t) * v1(x1, t) + darhou_dt(x1, t) = ForwardDiff.derivative(t -> arhou(x1, t), t) + darhouu_dx(x1, t) = ForwardDiff.derivative(x1 -> arhouu(x1, t), x1) + dp1_dx(x1, t) = ForwardDiff.derivative(x1 -> p1(x1, t), x1) + + auEp(x1, t) = a(x1, t) * v1(x1, t) * (e(x1, t) + p1(x1, t)) + daE_dt(x1, t) = ForwardDiff.derivative(t -> aE(x1, t), t) + dauEp_dx(x1, t) = ForwardDiff.derivative(x1 -> auEp(x1, t), x1) + + du1 = darho_dt(x1, t) + darhou_dx(x1, t) + du2 = darhou_dt(x1, t) + darhouu_dx(x1, t) + a(x1, t) * dp1_dx(x1, t) + du3 = daE_dt(x1, t) + dauEp_dx(x1, t) + + return SVector(du1, du2, du3, 0.0) +end + +# Calculate 1D flux for a single point +@inline function flux(u, orientation::Integer, + equations::CompressibleEulerEquationsQuasi1D) + a_rho, a_rho_v1, a_e, a = u + rho, v1, p, a = cons2prim(u, equations) + e = a_e / a + + # Ignore orientation since it is always "1" in 1D + f1 = a_rho_v1 + f2 = a_rho_v1 * v1 + f3 = a * v1 * (e + p) + + return SVector(f1, f2, f3, zero(eltype(u))) +end + +""" +@inline function flux_nonconservative_chan_etal(u_ll, u_rr, orientation::Integer, + equations::CompressibleEulerEquationsQuasi1D) + +Non-symmetric two-point volume flux discretizing the nonconservative (source) term +that contains the gradient of the pressure [`CompressibleEulerEquationsQuasi1D`](@ref) +and the nozzle 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](https://doi.org/10.48550/arXiv.2307.12089) +""" +@inline function flux_nonconservative_chan_etal(u_ll, u_rr, orientation::Integer, + equations::CompressibleEulerEquationsQuasi1D) + #Variables + _, _, p_ll, a_ll = cons2prim(u_ll, equations) + _, _, p_rr, _ = cons2prim(u_rr, equations) + + # For flux differencing using non-conservative terms, we return the + # non-conservative flux scaled by 2. This cancels with a factor of 0.5 + # in the arithmetic average of {p}. + p_avg = p_ll + p_rr + + z = zero(eltype(u_ll)) + + return SVector(z, a_ll * p_avg, z, z) +end + +""" +@inline function flux_chan_etal(u_ll, u_rr, orientation::Integer, + equations::CompressibleEulerEquationsQuasi1D) + +Conservative (symmetric) part of the entropy conservative flux for quasi 1D compressible Euler equations split form. +This flux is a generalization of [`flux_ranocha`](@ref) for [`CompressibleEulerEquations1D`](@ref). +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](https://doi.org/10.48550/arXiv.2307.12089) +""" +@inline function flux_chan_etal(u_ll, u_rr, orientation::Integer, + equations::CompressibleEulerEquationsQuasi1D) + # Unpack left and right state + rho_ll, v1_ll, p_ll, a_ll = cons2prim(u_ll, equations) + rho_rr, v1_rr, p_rr, a_rr = cons2prim(u_rr, equations) + + # Compute the necessary mean values + rho_mean = ln_mean(rho_ll, rho_rr) + # Algebraically equivalent to `inv_ln_mean(rho_ll / p_ll, rho_rr / p_rr)` + # in exact arithmetic since + # log((ϱₗ/pₗ) / (ϱᵣ/pᵣ)) / (ϱₗ/pₗ - ϱᵣ/pᵣ) + # = pₗ pᵣ log((ϱₗ pᵣ) / (ϱᵣ pₗ)) / (ϱₗ pᵣ - ϱᵣ pₗ) + inv_rho_p_mean = p_ll * p_rr * inv_ln_mean(rho_ll * p_rr, rho_rr * p_ll) + v1_avg = 0.5 * (v1_ll + v1_rr) + a_v1_avg = 0.5 * (a_ll * v1_ll + a_rr * v1_rr) + p_avg = 0.5 * (p_ll + p_rr) + velocity_square_avg = 0.5 * (v1_ll * v1_rr) + + # Calculate fluxes + # Ignore orientation since it is always "1" in 1D + f1 = rho_mean * a_v1_avg + f2 = rho_mean * a_v1_avg * v1_avg + f3 = f1 * (velocity_square_avg + inv_rho_p_mean * equations.inv_gamma_minus_one) + + 0.5 * (p_ll * a_rr * v1_rr + p_rr * a_ll * v1_ll) + + return SVector(f1, f2, f3, zero(eltype(u_ll))) +end + +# Calculate estimates for maximum wave speed for local Lax-Friedrichs-type dissipation as the +# maximum velocity magnitude plus the maximum speed of sound +@inline function max_abs_speed_naive(u_ll, u_rr, orientation::Integer, + equations::CompressibleEulerEquationsQuasi1D) + a_rho_ll, a_rho_v1_ll, a_e_ll, a_ll = u_ll + a_rho_rr, a_rho_v1_rr, a_e_rr, a_rr = u_rr + + # Calculate primitive variables and speed of sound + rho_ll = a_rho_ll / a_ll + e_ll = a_e_ll / a_ll + v1_ll = a_rho_v1_ll / a_rho_ll + v_mag_ll = abs(v1_ll) + p_ll = (equations.gamma - 1) * (e_ll - 0.5 * rho_ll * v_mag_ll^2) + c_ll = sqrt(equations.gamma * p_ll / rho_ll) + rho_rr = a_rho_rr / a_rr + e_rr = a_e_rr / a_rr + v1_rr = a_rho_v1_rr / a_rho_rr + v_mag_rr = abs(v1_rr) + p_rr = (equations.gamma - 1) * (e_rr - 0.5 * rho_rr * v_mag_rr^2) + c_rr = sqrt(equations.gamma * p_rr / rho_rr) + + λ_max = max(v_mag_ll, v_mag_rr) + max(c_ll, c_rr) +end + +@inline function max_abs_speeds(u, equations::CompressibleEulerEquationsQuasi1D) + a_rho, a_rho_v1, a_e, a = u + rho = a_rho / a + v1 = a_rho_v1 / a_rho + e = a_e / a + p = (equations.gamma - 1) * (e - 0.5 * rho * v1^2) + c = sqrt(equations.gamma * p / rho) + + return (abs(v1) + c,) +end + +# Convert conservative variables to primitive. We use the convention that the primitive +# variables for the quasi-1D equations are `(rho, v1, p)` (i.e., the same as the primitive +# variables for `CompressibleEulerEquations1D`) +@inline function cons2prim(u, equations::CompressibleEulerEquationsQuasi1D) + a_rho, a_rho_v1, a_e, a = u + q = cons2prim(SVector(a_rho, a_rho_v1, a_e) / a, + CompressibleEulerEquations1D(equations.gamma)) + + return SVector(q[1], q[2], q[3], a) +end + +# The entropy for the quasi-1D compressible Euler equations is the entropy for the +# 1D compressible Euler equations scaled by the channel width `a`. +@inline function entropy(u, equations::CompressibleEulerEquationsQuasi1D) + a_rho, a_rho_v1, a_e, a = u + q = a * entropy(SVector(a_rho, a_rho_v1, a_e) / a, + CompressibleEulerEquations1D(equations.gamma)) + + return SVector(q[1], q[2], q[3], a) +end + +# Convert conservative variables to entropy. The entropy variables for the +# quasi-1D compressible Euler equations are identical to the entropy variables +# for the standard Euler equations for an appropriate definition of `entropy`. +@inline function cons2entropy(u, equations::CompressibleEulerEquationsQuasi1D) + a_rho, a_rho_v1, a_e, a = u + w = cons2entropy(SVector(a_rho, a_rho_v1, a_e) / a, + CompressibleEulerEquations1D(equations.gamma)) + + # we follow the convention for other spatially-varying equations such as + # `ShallowWaterEquations1D` and return the spatially varying coefficient + # `a` as the final entropy variable. + return SVector(w[1], w[2], w[3], a) +end + +# Convert primitive to conservative variables +@inline function prim2cons(u, equations::CompressibleEulerEquationsQuasi1D) + rho, v1, p, a = u + q = prim2cons(u, CompressibleEulerEquations1D(equations.gamma)) + + return SVector(a * q[1], a * q[2], a * q[3], a) +end + +@inline function density(u, equations::CompressibleEulerEquationsQuasi1D) + a_rho, _, _, a = u + rho = a_rho / a + return rho +end + +@inline function pressure(u, equations::CompressibleEulerEquationsQuasi1D) + a_rho, a_rho_v1, a_e, a = u + return pressure(SVector(a_rho, a_rho_v1, a_e) / a, + CompressibleEulerEquations1D(equations.gamma)) +end + +@inline function density_pressure(u, equations::CompressibleEulerEquationsQuasi1D) + a_rho, a_rho_v1, a_e, a = u + return density_pressure(SVector(a_rho, a_rho_v1, a_e) / a, + CompressibleEulerEquations1D(equations.gamma)) +end +end # @muladd diff --git a/src/equations/compressible_navier_stokes.jl b/src/equations/compressible_navier_stokes.jl index af7897d4586..3059771197c 100644 --- a/src/equations/compressible_navier_stokes.jl +++ b/src/equations/compressible_navier_stokes.jl @@ -6,9 +6,6 @@ Creates a wall-type boundary conditions for the compressible Navier-Stokes equat 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. - -!!! warning "Experimental feature" - This is an experimental feature and may change in future releases. """ struct BoundaryConditionNavierStokesWall{V, H} boundary_condition_velocity::V @@ -52,9 +49,6 @@ struct Adiabatic{F} end """ -!!! warning "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 diff --git a/src/equations/compressible_navier_stokes_1d.jl b/src/equations/compressible_navier_stokes_1d.jl index dca846cac1e..d2c46ecc7d8 100644 --- a/src/equations/compressible_navier_stokes_1d.jl +++ b/src/equations/compressible_navier_stokes_1d.jl @@ -1,3 +1,10 @@ +# By default, Julia/LLVM does not use fused multiply-add operations (FMAs). +# Since these FMAs can increase the performance of many numerical algorithms, +# we need to opt-in explicitly. +# See https://ranocha.de/blog/Optimizing_EC_Trixi for further details. +@muladd begin +#! format: noindent + @doc raw""" CompressibleNavierStokesDiffusion1D(equations; mu, Pr, gradient_variables=GradientVariablesPrimitive()) @@ -72,13 +79,10 @@ where ```math w_2 = \frac{\rho v1}{p},\, w_3 = -\frac{\rho}{p} ``` - -!!! warning "Experimental code" - This code is experimental and may be changed or removed in any future release. """ struct CompressibleNavierStokesDiffusion1D{GradientVariables, RealT <: Real, E <: AbstractCompressibleEulerEquations{1}} <: - AbstractCompressibleNavierStokesDiffusion{1, 3} + AbstractCompressibleNavierStokesDiffusion{1, 3, GradientVariables} # TODO: parabolic # 1) For now save gamma and inv(gamma-1) again, but could potentially reuse them from the Euler equations # 2) Add NGRADS as a type parameter here and in AbstractEquationsParabolic, add `ngradients(...)` accessor function @@ -109,7 +113,8 @@ function CompressibleNavierStokesDiffusion1D(equations::CompressibleEulerEquatio CompressibleNavierStokesDiffusion1D{typeof(gradient_variables), typeof(gamma), typeof(equations)}(gamma, inv_gamma_minus_one, μ, Pr, kappa, - equations, gradient_variables) + equations, + gradient_variables) end # TODO: parabolic @@ -124,14 +129,10 @@ end # we specialize this function to compute gradients of primitive variables instead of # conservative variables. -function gradient_variable_transformation(::CompressibleNavierStokesDiffusion1D{ - GradientVariablesPrimitive - }) +function gradient_variable_transformation(::CompressibleNavierStokesDiffusion1D{GradientVariablesPrimitive}) cons2prim end -function gradient_variable_transformation(::CompressibleNavierStokesDiffusion1D{ - GradientVariablesEntropy - }) +function gradient_variable_transformation(::CompressibleNavierStokesDiffusion1D{GradientVariablesEntropy}) cons2entropy end @@ -196,17 +197,13 @@ end # For CNS, it is simplest to formulate the viscous terms in primitive variables, so we transform the transformed # variables into primitive variables. @inline function convert_transformed_to_primitive(u_transformed, - equations::CompressibleNavierStokesDiffusion1D{ - GradientVariablesPrimitive - }) + equations::CompressibleNavierStokesDiffusion1D{GradientVariablesPrimitive}) return u_transformed end # TODO: parabolic. Make this more efficient! @inline function convert_transformed_to_primitive(u_transformed, - equations::CompressibleNavierStokesDiffusion1D{ - GradientVariablesEntropy - }) + equations::CompressibleNavierStokesDiffusion1D{GradientVariablesEntropy}) # note: this uses CompressibleNavierStokesDiffusion1D versions of cons2prim and entropy2cons return cons2prim(entropy2cons(u_transformed, equations), equations) end @@ -217,17 +214,13 @@ end # Note, the first component of `gradient_entropy_vars` contains gradient(rho) which is unused. # TODO: parabolic; entropy stable viscous terms @inline function convert_derivative_to_primitive(u, gradient, - ::CompressibleNavierStokesDiffusion1D{ - GradientVariablesPrimitive - }) + ::CompressibleNavierStokesDiffusion1D{GradientVariablesPrimitive}) return gradient end # the first argument is always the "transformed" variables. @inline function convert_derivative_to_primitive(w, gradient_entropy_vars, - equations::CompressibleNavierStokesDiffusion1D{ - GradientVariablesEntropy - }) + equations::CompressibleNavierStokesDiffusion1D{GradientVariablesEntropy}) # TODO: parabolic. This is inefficient to pass in transformed variables but then transform them back. # We can fix this if we directly compute v1, v2, T from the entropy variables @@ -263,11 +256,10 @@ end u_inner, orientation::Integer, direction, - x, t, + x, + t, operator_type::Gradient, - equations::CompressibleNavierStokesDiffusion1D{ - GradientVariablesPrimitive - }) + equations::CompressibleNavierStokesDiffusion1D{GradientVariablesPrimitive}) v1 = boundary_condition.boundary_condition_velocity.boundary_value_function(x, t, equations) return SVector(u_inner[1], v1, u_inner[3]) @@ -278,11 +270,10 @@ end u_inner, orientation::Integer, direction, - x, t, + x, + t, operator_type::Divergence, - equations::CompressibleNavierStokesDiffusion1D{ - GradientVariablesPrimitive - }) + equations::CompressibleNavierStokesDiffusion1D{GradientVariablesPrimitive}) # rho, v1, v2, _ = u_inner normal_heat_flux = boundary_condition.boundary_condition_heat_flux.boundary_value_normal_flux_function(x, t, @@ -299,11 +290,10 @@ end u_inner, orientation::Integer, direction, - x, t, + x, + t, operator_type::Gradient, - equations::CompressibleNavierStokesDiffusion1D{ - GradientVariablesPrimitive - }) + equations::CompressibleNavierStokesDiffusion1D{GradientVariablesPrimitive}) v1 = boundary_condition.boundary_condition_velocity.boundary_value_function(x, t, equations) T = boundary_condition.boundary_condition_heat_flux.boundary_value_function(x, t, @@ -316,11 +306,10 @@ end u_inner, orientation::Integer, direction, - x, t, + x, + t, operator_type::Divergence, - equations::CompressibleNavierStokesDiffusion1D{ - GradientVariablesPrimitive - }) + equations::CompressibleNavierStokesDiffusion1D{GradientVariablesPrimitive}) return flux_inner end @@ -337,11 +326,10 @@ end w_inner, orientation::Integer, direction, - x, t, + x, + t, operator_type::Gradient, - equations::CompressibleNavierStokesDiffusion1D{ - GradientVariablesEntropy - }) + equations::CompressibleNavierStokesDiffusion1D{GradientVariablesEntropy}) v1 = boundary_condition.boundary_condition_velocity.boundary_value_function(x, t, equations) negative_rho_inv_p = w_inner[3] # w_3 = -rho / p @@ -354,11 +342,10 @@ end w_inner, orientation::Integer, direction, - x, t, + x, + t, operator_type::Divergence, - equations::CompressibleNavierStokesDiffusion1D{ - GradientVariablesEntropy - }) + equations::CompressibleNavierStokesDiffusion1D{GradientVariablesEntropy}) normal_heat_flux = boundary_condition.boundary_condition_heat_flux.boundary_value_normal_flux_function(x, t, equations) @@ -374,11 +361,10 @@ end w_inner, orientation::Integer, direction, - x, t, + x, + t, operator_type::Gradient, - equations::CompressibleNavierStokesDiffusion1D{ - GradientVariablesEntropy - }) + equations::CompressibleNavierStokesDiffusion1D{GradientVariablesEntropy}) v1 = boundary_condition.boundary_condition_velocity.boundary_value_function(x, t, equations) T = boundary_condition.boundary_condition_heat_flux.boundary_value_function(x, t, @@ -394,10 +380,10 @@ end w_inner, orientation::Integer, direction, - x, t, + x, + t, operator_type::Divergence, - equations::CompressibleNavierStokesDiffusion1D{ - GradientVariablesEntropy - }) + equations::CompressibleNavierStokesDiffusion1D{GradientVariablesEntropy}) return SVector(flux_inner[1], flux_inner[2], flux_inner[3]) end +end # @muladd diff --git a/src/equations/compressible_navier_stokes_2d.jl b/src/equations/compressible_navier_stokes_2d.jl index f762fe5d5ee..5df7c01ca5c 100644 --- a/src/equations/compressible_navier_stokes_2d.jl +++ b/src/equations/compressible_navier_stokes_2d.jl @@ -1,3 +1,10 @@ +# By default, Julia/LLVM does not use fused multiply-add operations (FMAs). +# Since these FMAs can increase the performance of many numerical algorithms, +# we need to opt-in explicitly. +# See https://ranocha.de/blog/Optimizing_EC_Trixi for further details. +@muladd begin +#! format: noindent + @doc raw""" CompressibleNavierStokesDiffusion2D(equations; mu, Pr, gradient_variables=GradientVariablesPrimitive()) @@ -72,13 +79,10 @@ where ```math w_2 = \frac{\rho v_1}{p},\, w_3 = \frac{\rho v_2}{p},\, w_4 = -\frac{\rho}{p} ``` - -!!! warning "Experimental code" - This code is experimental and may be changed or removed in any future release. """ struct CompressibleNavierStokesDiffusion2D{GradientVariables, RealT <: Real, E <: AbstractCompressibleEulerEquations{2}} <: - AbstractCompressibleNavierStokesDiffusion{2, 4} + AbstractCompressibleNavierStokesDiffusion{2, 4, GradientVariables} # TODO: parabolic # 1) For now save gamma and inv(gamma-1) again, but could potentially reuse them from the Euler equations # 2) Add NGRADS as a type parameter here and in AbstractEquationsParabolic, add `ngradients(...)` accessor function @@ -109,7 +113,8 @@ function CompressibleNavierStokesDiffusion2D(equations::CompressibleEulerEquatio CompressibleNavierStokesDiffusion2D{typeof(gradient_variables), typeof(gamma), typeof(equations)}(gamma, inv_gamma_minus_one, μ, Pr, kappa, - equations, gradient_variables) + equations, + gradient_variables) end # TODO: parabolic @@ -124,14 +129,10 @@ end # we specialize this function to compute gradients of primitive variables instead of # conservative variables. -function gradient_variable_transformation(::CompressibleNavierStokesDiffusion2D{ - GradientVariablesPrimitive - }) +function gradient_variable_transformation(::CompressibleNavierStokesDiffusion2D{GradientVariablesPrimitive}) cons2prim end -function gradient_variable_transformation(::CompressibleNavierStokesDiffusion2D{ - GradientVariablesEntropy - }) +function gradient_variable_transformation(::CompressibleNavierStokesDiffusion2D{GradientVariablesEntropy}) cons2entropy end @@ -218,17 +219,13 @@ end # For CNS, it is simplest to formulate the viscous terms in primitive variables, so we transform the transformed # variables into primitive variables. @inline function convert_transformed_to_primitive(u_transformed, - equations::CompressibleNavierStokesDiffusion2D{ - GradientVariablesPrimitive - }) + equations::CompressibleNavierStokesDiffusion2D{GradientVariablesPrimitive}) return u_transformed end # TODO: parabolic. Make this more efficient! @inline function convert_transformed_to_primitive(u_transformed, - equations::CompressibleNavierStokesDiffusion2D{ - GradientVariablesEntropy - }) + equations::CompressibleNavierStokesDiffusion2D{GradientVariablesEntropy}) # note: this uses CompressibleNavierStokesDiffusion2D versions of cons2prim and entropy2cons return cons2prim(entropy2cons(u_transformed, equations), equations) end @@ -239,17 +236,13 @@ end # Note, the first component of `gradient_entropy_vars` contains gradient(rho) which is unused. # TODO: parabolic; entropy stable viscous terms @inline function convert_derivative_to_primitive(u, gradient, - ::CompressibleNavierStokesDiffusion2D{ - GradientVariablesPrimitive - }) + ::CompressibleNavierStokesDiffusion2D{GradientVariablesPrimitive}) return gradient end # the first argument is always the "transformed" variables. @inline function convert_derivative_to_primitive(w, gradient_entropy_vars, - equations::CompressibleNavierStokesDiffusion2D{ - GradientVariablesEntropy - }) + equations::CompressibleNavierStokesDiffusion2D{GradientVariablesEntropy}) # TODO: parabolic. This is inefficient to pass in transformed variables but then transform them back. # We can fix this if we directly compute v1, v2, T from the entropy variables @@ -301,12 +294,12 @@ end <:Adiabatic})(flux_inner, u_inner, normal::AbstractVector, - x, t, + x, + t, operator_type::Gradient, - equations::CompressibleNavierStokesDiffusion2D{ - GradientVariablesPrimitive - }) - v1, v2 = boundary_condition.boundary_condition_velocity.boundary_value_function(x, t, + equations::CompressibleNavierStokesDiffusion2D{GradientVariablesPrimitive}) + v1, v2 = boundary_condition.boundary_condition_velocity.boundary_value_function(x, + t, equations) return SVector(u_inner[1], v1, v2, u_inner[4]) end @@ -315,16 +308,16 @@ end <:Adiabatic})(flux_inner, u_inner, normal::AbstractVector, - x, t, + x, + t, operator_type::Divergence, - equations::CompressibleNavierStokesDiffusion2D{ - GradientVariablesPrimitive - }) + equations::CompressibleNavierStokesDiffusion2D{GradientVariablesPrimitive}) # rho, v1, v2, _ = u_inner normal_heat_flux = boundary_condition.boundary_condition_heat_flux.boundary_value_normal_flux_function(x, t, equations) - v1, v2 = boundary_condition.boundary_condition_velocity.boundary_value_function(x, t, + v1, v2 = boundary_condition.boundary_condition_velocity.boundary_value_function(x, + t, equations) _, tau_1n, tau_2n, _ = flux_inner # extract fluxes for 2nd and 3rd equations normal_energy_flux = v1 * tau_1n + v2 * tau_2n + normal_heat_flux @@ -335,12 +328,12 @@ end <:Isothermal})(flux_inner, u_inner, normal::AbstractVector, - x, t, + x, + t, operator_type::Gradient, - equations::CompressibleNavierStokesDiffusion2D{ - GradientVariablesPrimitive - }) - v1, v2 = boundary_condition.boundary_condition_velocity.boundary_value_function(x, t, + equations::CompressibleNavierStokesDiffusion2D{GradientVariablesPrimitive}) + v1, v2 = boundary_condition.boundary_condition_velocity.boundary_value_function(x, + t, equations) T = boundary_condition.boundary_condition_heat_flux.boundary_value_function(x, t, equations) @@ -351,11 +344,10 @@ end <:Isothermal})(flux_inner, u_inner, normal::AbstractVector, - x, t, + x, + t, operator_type::Divergence, - equations::CompressibleNavierStokesDiffusion2D{ - GradientVariablesPrimitive - }) + equations::CompressibleNavierStokesDiffusion2D{GradientVariablesPrimitive}) return flux_inner end @@ -371,12 +363,12 @@ end <:Adiabatic})(flux_inner, w_inner, normal::AbstractVector, - x, t, + x, + t, operator_type::Gradient, - equations::CompressibleNavierStokesDiffusion2D{ - GradientVariablesEntropy - }) - v1, v2 = boundary_condition.boundary_condition_velocity.boundary_value_function(x, t, + equations::CompressibleNavierStokesDiffusion2D{GradientVariablesEntropy}) + v1, v2 = boundary_condition.boundary_condition_velocity.boundary_value_function(x, + t, equations) negative_rho_inv_p = w_inner[4] # w_4 = -rho / p return SVector(w_inner[1], -v1 * negative_rho_inv_p, -v2 * negative_rho_inv_p, @@ -388,15 +380,15 @@ end <:Adiabatic})(flux_inner, w_inner, normal::AbstractVector, - x, t, + x, + t, operator_type::Divergence, - equations::CompressibleNavierStokesDiffusion2D{ - GradientVariablesEntropy - }) + equations::CompressibleNavierStokesDiffusion2D{GradientVariablesEntropy}) normal_heat_flux = boundary_condition.boundary_condition_heat_flux.boundary_value_normal_flux_function(x, t, equations) - v1, v2 = boundary_condition.boundary_condition_velocity.boundary_value_function(x, t, + v1, v2 = boundary_condition.boundary_condition_velocity.boundary_value_function(x, + t, equations) _, tau_1n, tau_2n, _ = flux_inner # extract fluxes for 2nd and 3rd equations normal_energy_flux = v1 * tau_1n + v2 * tau_2n + normal_heat_flux @@ -407,12 +399,12 @@ end <:Isothermal})(flux_inner, w_inner, normal::AbstractVector, - x, t, + x, + t, operator_type::Gradient, - equations::CompressibleNavierStokesDiffusion2D{ - GradientVariablesEntropy - }) - v1, v2 = boundary_condition.boundary_condition_velocity.boundary_value_function(x, t, + equations::CompressibleNavierStokesDiffusion2D{GradientVariablesEntropy}) + v1, v2 = boundary_condition.boundary_condition_velocity.boundary_value_function(x, + t, equations) T = boundary_condition.boundary_condition_heat_flux.boundary_value_function(x, t, equations) @@ -426,10 +418,35 @@ end <:Isothermal})(flux_inner, w_inner, normal::AbstractVector, - x, t, + x, + t, operator_type::Divergence, - equations::CompressibleNavierStokesDiffusion2D{ - GradientVariablesEntropy - }) + equations::CompressibleNavierStokesDiffusion2D{GradientVariablesEntropy}) return SVector(flux_inner[1], flux_inner[2], flux_inner[3], flux_inner[4]) end + +# Dirichlet Boundary Condition for P4est mesh + +@inline function (boundary_condition::BoundaryConditionDirichlet)(flux_inner, + u_inner, + normal::AbstractVector, + x, t, + operator_type::Gradient, + equations::CompressibleNavierStokesDiffusion2D{GradientVariablesPrimitive}) + # BCs are usually specified as conservative variables so we convert them to primitive variables + # because the gradients are assumed to be with respect to the primitive variables + u_boundary = boundary_condition.boundary_value_function(x, t, equations) + + return cons2prim(u_boundary, equations) +end + +@inline function (boundary_condition::BoundaryConditionDirichlet)(flux_inner, + u_inner, + normal::AbstractVector, + x, t, + operator_type::Divergence, + equations::CompressibleNavierStokesDiffusion2D{GradientVariablesPrimitive}) + # for Dirichlet boundary conditions, we do not impose any conditions on the viscous fluxes + return flux_inner +end +end # @muladd diff --git a/src/equations/compressible_navier_stokes_3d.jl b/src/equations/compressible_navier_stokes_3d.jl index 166b53bf615..e5567ae5789 100644 --- a/src/equations/compressible_navier_stokes_3d.jl +++ b/src/equations/compressible_navier_stokes_3d.jl @@ -1,3 +1,10 @@ +# By default, Julia/LLVM does not use fused multiply-add operations (FMAs). +# Since these FMAs can increase the performance of many numerical algorithms, +# we need to opt-in explicitly. +# See https://ranocha.de/blog/Optimizing_EC_Trixi for further details. +@muladd begin +#! format: noindent + @doc raw""" CompressibleNavierStokesDiffusion3D(equations; mu, Pr, gradient_variables=GradientVariablesPrimitive()) @@ -72,13 +79,10 @@ where ```math 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} ``` - -!!! warning "Experimental code" - This code is experimental and may be changed or removed in any future release. """ struct CompressibleNavierStokesDiffusion3D{GradientVariables, RealT <: Real, E <: AbstractCompressibleEulerEquations{3}} <: - AbstractCompressibleNavierStokesDiffusion{3, 5} + AbstractCompressibleNavierStokesDiffusion{3, 5, GradientVariables} # TODO: parabolic # 1) For now save gamma and inv(gamma-1) again, but could potentially reuse them from the Euler equations # 2) Add NGRADS as a type parameter here and in AbstractEquationsParabolic, add `ngradients(...)` accessor function @@ -109,7 +113,8 @@ function CompressibleNavierStokesDiffusion3D(equations::CompressibleEulerEquatio CompressibleNavierStokesDiffusion3D{typeof(gradient_variables), typeof(gamma), typeof(equations)}(gamma, inv_gamma_minus_one, μ, Pr, kappa, - equations, gradient_variables) + equations, + gradient_variables) end # TODO: parabolic @@ -124,14 +129,10 @@ end # we specialize this function to compute gradients of primitive variables instead of # conservative variables. -function gradient_variable_transformation(::CompressibleNavierStokesDiffusion3D{ - GradientVariablesPrimitive - }) +function gradient_variable_transformation(::CompressibleNavierStokesDiffusion3D{GradientVariablesPrimitive}) cons2prim end -function gradient_variable_transformation(::CompressibleNavierStokesDiffusion3D{ - GradientVariablesEntropy - }) +function gradient_variable_transformation(::CompressibleNavierStokesDiffusion3D{GradientVariablesEntropy}) cons2entropy end @@ -244,17 +245,13 @@ end # For CNS, it is simplest to formulate the viscous terms in primitive variables, so we transform the transformed # variables into primitive variables. @inline function convert_transformed_to_primitive(u_transformed, - equations::CompressibleNavierStokesDiffusion3D{ - GradientVariablesPrimitive - }) + equations::CompressibleNavierStokesDiffusion3D{GradientVariablesPrimitive}) return u_transformed end # TODO: parabolic. Make this more efficient! @inline function convert_transformed_to_primitive(u_transformed, - equations::CompressibleNavierStokesDiffusion3D{ - GradientVariablesEntropy - }) + equations::CompressibleNavierStokesDiffusion3D{GradientVariablesEntropy}) # note: this uses CompressibleNavierStokesDiffusion3D versions of cons2prim and entropy2cons return cons2prim(entropy2cons(u_transformed, equations), equations) end @@ -265,17 +262,13 @@ end # Note, the first component of `gradient_entropy_vars` contains gradient(rho) which is unused. # TODO: parabolic; entropy stable viscous terms @inline function convert_derivative_to_primitive(u, gradient, - ::CompressibleNavierStokesDiffusion3D{ - GradientVariablesPrimitive - }) + ::CompressibleNavierStokesDiffusion3D{GradientVariablesPrimitive}) return gradient end # the first argument is always the "transformed" variables. @inline function convert_derivative_to_primitive(w, gradient_entropy_vars, - equations::CompressibleNavierStokesDiffusion3D{ - GradientVariablesEntropy - }) + equations::CompressibleNavierStokesDiffusion3D{GradientVariablesEntropy}) # TODO: parabolic. This is inefficient to pass in transformed variables but then transform them back. # We can fix this if we directly compute v1, v2, v3, T from the entropy variables @@ -319,9 +312,12 @@ end @inline function vorticity(u, gradients, equations::CompressibleNavierStokesDiffusion3D) # Ensure that we have velocity `gradients` by way of the `convert_gradient_variables` function. - _, dv1dx, dv2dx, dv3dx, _ = convert_derivative_to_primitive(u, gradients[1], equations) - _, dv1dy, dv2dy, dv3dy, _ = convert_derivative_to_primitive(u, gradients[2], equations) - _, dv1dz, dv2dz, dv3dz, _ = convert_derivative_to_primitive(u, gradients[3], equations) + _, dv1dx, dv2dx, dv3dx, _ = convert_derivative_to_primitive(u, gradients[1], + equations) + _, dv1dy, dv2dy, dv3dy, _ = convert_derivative_to_primitive(u, gradients[2], + equations) + _, dv1dz, dv2dz, dv3dz, _ = convert_derivative_to_primitive(u, gradients[3], + equations) return SVector(dv3dy - dv2dz, dv1dz - dv3dx, dv2dx - dv1dy) end @@ -330,11 +326,10 @@ end <:Adiabatic})(flux_inner, u_inner, normal::AbstractVector, - x, t, + x, + t, operator_type::Gradient, - equations::CompressibleNavierStokesDiffusion3D{ - GradientVariablesPrimitive - }) + equations::CompressibleNavierStokesDiffusion3D{GradientVariablesPrimitive}) v1, v2, v3 = boundary_condition.boundary_condition_velocity.boundary_value_function(x, t, equations) @@ -345,11 +340,10 @@ end <:Adiabatic})(flux_inner, u_inner, normal::AbstractVector, - x, t, + x, + t, operator_type::Divergence, - equations::CompressibleNavierStokesDiffusion3D{ - GradientVariablesPrimitive - }) + equations::CompressibleNavierStokesDiffusion3D{GradientVariablesPrimitive}) # rho, v1, v2, v3, _ = u_inner normal_heat_flux = boundary_condition.boundary_condition_heat_flux.boundary_value_normal_flux_function(x, t, @@ -367,11 +361,10 @@ end <:Isothermal})(flux_inner, u_inner, normal::AbstractVector, - x, t, + x, + t, operator_type::Gradient, - equations::CompressibleNavierStokesDiffusion3D{ - GradientVariablesPrimitive - }) + equations::CompressibleNavierStokesDiffusion3D{GradientVariablesPrimitive}) v1, v2, v3 = boundary_condition.boundary_condition_velocity.boundary_value_function(x, t, equations) @@ -384,11 +377,10 @@ end <:Isothermal})(flux_inner, u_inner, normal::AbstractVector, - x, t, + x, + t, operator_type::Divergence, - equations::CompressibleNavierStokesDiffusion3D{ - GradientVariablesPrimitive - }) + equations::CompressibleNavierStokesDiffusion3D{GradientVariablesPrimitive}) return flux_inner end @@ -404,11 +396,10 @@ end <:Adiabatic})(flux_inner, w_inner, normal::AbstractVector, - x, t, + x, + t, operator_type::Gradient, - equations::CompressibleNavierStokesDiffusion3D{ - GradientVariablesEntropy - }) + equations::CompressibleNavierStokesDiffusion3D{GradientVariablesEntropy}) v1, v2, v3 = boundary_condition.boundary_condition_velocity.boundary_value_function(x, t, equations) @@ -422,11 +413,10 @@ end <:Adiabatic})(flux_inner, w_inner, normal::AbstractVector, - x, t, + x, + t, operator_type::Divergence, - equations::CompressibleNavierStokesDiffusion3D{ - GradientVariablesEntropy - }) + equations::CompressibleNavierStokesDiffusion3D{GradientVariablesEntropy}) normal_heat_flux = boundary_condition.boundary_condition_heat_flux.boundary_value_normal_flux_function(x, t, equations) @@ -443,11 +433,10 @@ end <:Isothermal})(flux_inner, w_inner, normal::AbstractVector, - x, t, + x, + t, operator_type::Gradient, - equations::CompressibleNavierStokesDiffusion3D{ - GradientVariablesEntropy - }) + equations::CompressibleNavierStokesDiffusion3D{GradientVariablesEntropy}) v1, v2, v3 = boundary_condition.boundary_condition_velocity.boundary_value_function(x, t, equations) @@ -463,11 +452,11 @@ end <:Isothermal})(flux_inner, w_inner, normal::AbstractVector, - x, t, + x, + t, operator_type::Divergence, - equations::CompressibleNavierStokesDiffusion3D{ - GradientVariablesEntropy - }) + equations::CompressibleNavierStokesDiffusion3D{GradientVariablesEntropy}) return SVector(flux_inner[1], flux_inner[2], flux_inner[3], flux_inner[4], flux_inner[5]) end +end # @muladd diff --git a/src/equations/equations.jl b/src/equations/equations.jl index 90b2cd62191..7a3c326984d 100644 --- a/src/equations/equations.jl +++ b/src/equations/equations.jl @@ -42,6 +42,18 @@ Common choices of the `conversion_function` are [`cons2cons`](@ref) and """ function varnames end +# Return the index of `varname` in `varnames(solution_variables, equations)` if available. +# Otherwise, throw an error. +function get_variable_index(varname, equations; + solution_variables = cons2cons) + index = findfirst(==(varname), varnames(solution_variables, equations)) + if isnothing(index) + throw(ArgumentError("$varname is no valid variable.")) + end + + return index +end + # Add methods to show some information on systems of equations. function Base.show(io::IO, equations::AbstractEquations) # Since this is not performance-critical, we can use `@nospecialize` to reduce latency. @@ -75,8 +87,14 @@ end @inline Base.ndims(::AbstractEquations{NDIMS}) where {NDIMS} = NDIMS -# equations act like scalars in broadcasting -Base.broadcastable(equations::AbstractEquations) = Ref(equations) +# Equations act like scalars in broadcasting. +# Using `Ref(equations)` would be more convenient in some circumstances. +# However, this does not work with Julia v1.9.3 correctly due to a (performance) +# bug in Julia, see +# - https://github.com/trixi-framework/Trixi.jl/pull/1618 +# - https://github.com/JuliaLang/julia/issues/51118 +# Thus, we use the workaround below. +Base.broadcastable(equations::AbstractEquations) = (equations,) """ flux(u, orientation_or_normal, equations) @@ -202,6 +220,24 @@ struct BoundaryConditionNeumann{B} boundary_normal_flux_function::B end +""" + 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. +""" +struct NonConservativeLocal end + +""" + 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. +""" +struct NonConservativeSymmetric end + # set sensible default values that may be overwritten by specific equations """ have_nonconservative_terms(equations) @@ -214,9 +250,24 @@ example of equations with nonconservative terms. The return value will be `True()` or `False()` to allow dispatching on the return type. """ have_nonconservative_terms(::AbstractEquations) = False() +""" + 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). +""" +function n_nonconservative_terms end have_constant_speed(::AbstractEquations) = False() +""" + default_analysis_errors(equations) + +Default analysis errors (`:l2_error` and `:linf_error`) used by the +[`AnalysisCallback`](@ref). +""" default_analysis_errors(::AbstractEquations) = (:l2_error, :linf_error) + """ default_analysis_integrals(equations) @@ -350,6 +401,7 @@ include("shallow_water_1d.jl") include("shallow_water_2d.jl") include("shallow_water_two_layer_1d.jl") include("shallow_water_two_layer_2d.jl") +include("shallow_water_quasi_1d.jl") # CompressibleEulerEquations abstract type AbstractCompressibleEulerEquations{NDIMS, NVARS} <: @@ -357,6 +409,7 @@ abstract type AbstractCompressibleEulerEquations{NDIMS, NVARS} <: include("compressible_euler_1d.jl") include("compressible_euler_2d.jl") include("compressible_euler_3d.jl") +include("compressible_euler_quasi_1d.jl") # CompressibleEulerMulticomponentEquations abstract type AbstractCompressibleEulerMulticomponentEquations{NDIMS, NVARS, NCOMP} <: @@ -364,6 +417,11 @@ abstract type AbstractCompressibleEulerMulticomponentEquations{NDIMS, NVARS, NCO include("compressible_euler_multicomponent_1d.jl") include("compressible_euler_multicomponent_2d.jl") +# PolytropicEulerEquations +abstract type AbstractPolytropicEulerEquations{NDIMS, NVARS} <: + AbstractEquations{NDIMS, NVARS} end +include("polytropic_euler_2d.jl") + # Retrieve number of components from equation instance for the multicomponent case @inline function ncomponents(::AbstractCompressibleEulerMulticomponentEquations{NDIMS, NVARS, @@ -441,6 +499,6 @@ abstract type AbstractLinearizedEulerEquations{NDIMS, NVARS} <: AbstractEquations{NDIMS, NVARS} end include("linearized_euler_2d.jl") -abstract type AbstractEquationsParabolic{NDIMS, NVARS} <: +abstract type AbstractEquationsParabolic{NDIMS, NVARS, GradientVariables} <: AbstractEquations{NDIMS, NVARS} end end # @muladd diff --git a/src/equations/equations_parabolic.jl b/src/equations/equations_parabolic.jl index 66214025044..a063e9f2758 100644 --- a/src/equations/equations_parabolic.jl +++ b/src/equations/equations_parabolic.jl @@ -2,15 +2,21 @@ # specialize this function to compute gradients e.g., of primitive variables instead of conservative gradient_variable_transformation(::AbstractEquationsParabolic) = cons2cons +# By default, the gradients are taken with respect to the conservative variables. +# this is reflected by the type parameter `GradientVariablesConservative` in the abstract +# type `AbstractEquationsParabolic{NDIMS, NVARS, GradientVariablesConservative}`. +struct GradientVariablesConservative end + # Linear scalar diffusion for use in linear scalar advection-diffusion problems abstract type AbstractLaplaceDiffusion{NDIMS, NVARS} <: - AbstractEquationsParabolic{NDIMS, NVARS} end + AbstractEquationsParabolic{NDIMS, NVARS, GradientVariablesConservative} end include("laplace_diffusion_1d.jl") include("laplace_diffusion_2d.jl") +include("laplace_diffusion_3d.jl") # Compressible Navier-Stokes equations -abstract type AbstractCompressibleNavierStokesDiffusion{NDIMS, NVARS} <: - AbstractEquationsParabolic{NDIMS, NVARS} end +abstract type AbstractCompressibleNavierStokesDiffusion{NDIMS, NVARS, GradientVariables} <: + AbstractEquationsParabolic{NDIMS, NVARS, GradientVariables} end include("compressible_navier_stokes.jl") include("compressible_navier_stokes_1d.jl") include("compressible_navier_stokes_2d.jl") diff --git a/src/equations/ideal_glm_mhd_1d.jl b/src/equations/ideal_glm_mhd_1d.jl index 7e5c94c7bc3..5a523daf3f6 100644 --- a/src/equations/ideal_glm_mhd_1d.jl +++ b/src/equations/ideal_glm_mhd_1d.jl @@ -259,6 +259,152 @@ Hindenlang and Gassner (2019), extending [`flux_ranocha`](@ref) to the MHD equat return SVector(f1, f2, f3, f4, f5, f6, f7, f8) end +""" + flux_hllc(u_ll, u_rr, orientation, equations::IdealGlmMhdEquations1D) + +- Li (2005) +An HLLC Riemann solver for magneto-hydrodynamics +[DOI: 10.1016/j.jcp.2004.08.020](https://doi.org/10.1016/j.jcp.2004.08.020). +""" +function flux_hllc(u_ll, u_rr, orientation::Integer, + equations::IdealGlmMhdEquations1D) + # Unpack left and right states + rho_ll, v1_ll, v2_ll, v3_ll, p_ll, B1_ll, B2_ll, B3_ll = cons2prim(u_ll, equations) + rho_rr, v1_rr, v2_rr, v3_rr, p_rr, B1_rr, B2_rr, B3_rr = cons2prim(u_rr, equations) + + # Total pressure, i.e., thermal + magnetic pressures (eq. (12)) + p_tot_ll = p_ll + 0.5 * (B1_ll^2 + B2_ll^2 + B3_ll^2) + p_tot_rr = p_rr + 0.5 * (B1_rr^2 + B2_rr^2 + B3_rr^2) + + # Conserved variables + rho_v1_ll = u_ll[2] + rho_v2_ll = u_ll[3] + rho_v3_ll = u_ll[4] + + rho_v1_rr = u_rr[2] + rho_v2_rr = u_rr[3] + rho_v3_rr = u_rr[4] + + # Obtain left and right fluxes + f_ll = flux(u_ll, orientation, equations) + f_rr = flux(u_rr, orientation, equations) + + SsL, SsR = min_max_speed_einfeldt(u_ll, u_rr, orientation, equations) + sMu_L = SsL - v1_ll + sMu_R = SsR - v1_rr + if SsL >= 0 + f1 = f_ll[1] + f2 = f_ll[2] + f3 = f_ll[3] + f4 = f_ll[4] + f5 = f_ll[5] + f6 = f_ll[6] + f7 = f_ll[7] + f8 = f_ll[8] + elseif SsR <= 0 + f1 = f_rr[1] + f2 = f_rr[2] + f3 = f_rr[3] + f4 = f_rr[4] + f5 = f_rr[5] + f6 = f_rr[6] + f7 = f_rr[7] + f8 = f_rr[8] + else + # Compute the "HLLC-speed", eq. (14) from paper mentioned above + #= + SStar = (rho_rr * v1_rr * sMu_R - rho_ll * v1_ll * sMu_L + p_tot_ll - p_tot_rr - B1_ll^2 + B1_rr^2 ) / + (rho_rr * sMu_R - rho_ll * sMu_L) + =# + # Simplification for 1D: B1 is constant + SStar = (rho_rr * v1_rr * sMu_R - rho_ll * v1_ll * sMu_L + p_tot_ll - p_tot_rr) / + (rho_rr * sMu_R - rho_ll * sMu_L) + + Sdiff = SsR - SsL + + # Compute HLL values for vStar, BStar + # These correspond to eq. (28) and (30) from the referenced paper + # and the classic HLL intermediate state given by (2) + rho_HLL = (SsR * rho_rr - SsL * rho_ll - (f_rr[1] - f_ll[1])) / Sdiff + + v1Star = (SsR * rho_v1_rr - SsL * rho_v1_ll - (f_rr[2] - f_ll[2])) / + (Sdiff * rho_HLL) + v2Star = (SsR * rho_v2_rr - SsL * rho_v2_ll - (f_rr[3] - f_ll[3])) / + (Sdiff * rho_HLL) + v3Star = (SsR * rho_v3_rr - SsL * rho_v3_ll - (f_rr[4] - f_ll[4])) / + (Sdiff * rho_HLL) + + #B1Star = (SsR * B1_rr - SsL * B1_ll - (f_rr[6] - f_ll[6])) / Sdiff + # 1D B1 = constant => B1_ll = B1_rr = B1Star + B1Star = B1_ll + + B2Star = (SsR * B2_rr - SsL * B2_ll - (f_rr[7] - f_ll[7])) / Sdiff + B3Star = (SsR * B3_rr - SsL * B3_ll - (f_rr[8] - f_ll[8])) / Sdiff + if SsL <= SStar + SdiffStar = SsL - SStar + + densStar = rho_ll * sMu_L / SdiffStar # (19) + + mom_1_Star = densStar * SStar # (20) + mom_2_Star = densStar * v2_ll - + (B1Star * B2Star - B1_ll * B2_ll) / SdiffStar # (21) + mom_3_Star = densStar * v3_ll - + (B1Star * B3Star - B1_ll * B3_ll) / SdiffStar # (22) + + #p_tot_Star = rho_ll * sMu_L * (SStar - v1_ll) + p_tot_ll - B1_ll^2 + B1Star^2 # (17) + # 1D B1 = constant => B1_ll = B1_rr = B1Star + p_tot_Star = rho_ll * sMu_L * (SStar - v1_ll) + p_tot_ll # (17) + + enerStar = u_ll[5] * sMu_L / SdiffStar + + (p_tot_Star * SStar - p_tot_ll * v1_ll - (B1Star * + (B1Star * v1Star + B2Star * v2Star + B3Star * v3Star) - + B1_ll * (B1_ll * v1_ll + B2_ll * v2_ll + B3_ll * v3_ll))) / + SdiffStar # (23) + + # Classic HLLC update (32) + f1 = f_ll[1] + SsL * (densStar - u_ll[1]) + f2 = f_ll[2] + SsL * (mom_1_Star - u_ll[2]) + f3 = f_ll[3] + SsL * (mom_2_Star - u_ll[3]) + f4 = f_ll[4] + SsL * (mom_3_Star - u_ll[4]) + f5 = f_ll[5] + SsL * (enerStar - u_ll[5]) + f6 = f_ll[6] + SsL * (B1Star - u_ll[6]) + f7 = f_ll[7] + SsL * (B2Star - u_ll[7]) + f8 = f_ll[8] + SsL * (B3Star - u_ll[8]) + else # SStar <= Ssr + SdiffStar = SsR - SStar + + densStar = rho_rr * sMu_R / SdiffStar # (19) + + mom_1_Star = densStar * SStar # (20) + mom_2_Star = densStar * v2_rr - + (B1Star * B2Star - B1_rr * B2_rr) / SdiffStar # (21) + mom_3_Star = densStar * v3_rr - + (B1Star * B3Star - B1_rr * B3_rr) / SdiffStar # (22) + + #p_tot_Star = rho_rr * sMu_R * (SStar - v1_rr) + p_tot_rr - B1_rr^2 + B1Star^2 # (17) + # 1D B1 = constant => B1_ll = B1_rr = B1Star + p_tot_Star = rho_rr * sMu_R * (SStar - v1_rr) + p_tot_rr # (17) + + enerStar = u_rr[5] * sMu_R / SdiffStar + + (p_tot_Star * SStar - p_tot_rr * v1_rr - (B1Star * + (B1Star * v1Star + B2Star * v2Star + B3Star * v3Star) - + B1_rr * (B1_rr * v1_rr + B2_rr * v2_rr + B3_rr * v3_rr))) / + SdiffStar # (23) + + # Classic HLLC update (32) + f1 = f_rr[1] + SsR * (densStar - u_rr[1]) + f2 = f_rr[2] + SsR * (mom_1_Star - u_rr[2]) + f3 = f_rr[3] + SsR * (mom_2_Star - u_rr[3]) + f4 = f_rr[4] + SsR * (mom_3_Star - u_rr[4]) + f5 = f_rr[5] + SsR * (enerStar - u_rr[5]) + f6 = f_rr[6] + SsR * (B1Star - u_rr[6]) + f7 = f_rr[7] + SsR * (B2Star - u_rr[7]) + f8 = f_rr[8] + SsR * (B3Star - u_rr[8]) + end + end + return SVector(f1, f2, f3, f4, f5, f6, f7, f8) +end + # Calculate maximum wave speed for local Lax-Friedrichs-type dissipation @inline function max_abs_speed_naive(u_ll, u_rr, orientation::Integer, equations::IdealGlmMhdEquations1D) @@ -277,6 +423,22 @@ end λ_max = max(abs(v_ll), abs(v_rr)) + max(cf_ll, cf_rr) end +# Calculate estimates for minimum and maximum wave speeds for HLL-type fluxes +@inline function min_max_speed_naive(u_ll, u_rr, orientation::Integer, + equations::IdealGlmMhdEquations1D) + rho_ll, rho_v1_ll, _ = u_ll + rho_rr, rho_v1_rr, _ = u_rr + + # Calculate primitive variables + v1_ll = rho_v1_ll / rho_ll + v1_rr = rho_v1_rr / rho_rr + + λ_min = v1_ll - calc_fast_wavespeed(u_ll, orientation, equations) + λ_max = v1_rr + calc_fast_wavespeed(u_rr, orientation, equations) + + return λ_min, λ_max +end + # More refined estimates for minimum and maximum wave speeds for HLL-type fluxes @inline function min_max_speed_davis(u_ll, u_rr, orientation::Integer, equations::IdealGlmMhdEquations1D) @@ -298,15 +460,15 @@ end end """ - min_max_speed_naive(u_ll, u_rr, orientation::Integer, equations::IdealGlmMhdEquations1D) + min_max_speed_einfeldt(u_ll, u_rr, orientation::Integer, equations::IdealGlmMhdEquations1D) Calculate minimum and maximum wave speeds for HLL-type fluxes as in - Li (2005) An HLLC Riemann solver for magneto-hydrodynamics [DOI: 10.1016/j.jcp.2004.08.020](https://doi.org/10.1016/j.jcp.2004.08.020). """ -@inline function min_max_speed_naive(u_ll, u_rr, orientation::Integer, - equations::IdealGlmMhdEquations1D) +@inline function min_max_speed_einfeldt(u_ll, u_rr, orientation::Integer, + equations::IdealGlmMhdEquations1D) rho_ll, rho_v1_ll, _ = u_ll rho_rr, rho_v1_rr, _ = u_rr diff --git a/src/equations/ideal_glm_mhd_2d.jl b/src/equations/ideal_glm_mhd_2d.jl index 8fef1ee22c9..43d1991e34b 100644 --- a/src/equations/ideal_glm_mhd_2d.jl +++ b/src/equations/ideal_glm_mhd_2d.jl @@ -29,6 +29,8 @@ function IdealGlmMhdEquations2D(gamma; initial_c_h = convert(typeof(gamma), NaN) end have_nonconservative_terms(::IdealGlmMhdEquations2D) = True() +n_nonconservative_terms(::IdealGlmMhdEquations2D) = 2 + function varnames(::typeof(cons2cons), ::IdealGlmMhdEquations2D) ("rho", "rho_v1", "rho_v2", "rho_v3", "rho_e", "B1", "B2", "B3", "psi") end @@ -279,6 +281,194 @@ end return f end +""" + 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`](@ref). + +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 +nonconservative_type argument, employing multiple dispatch. They are used to +compute the subcell fluxes in dg_2d_subcell_limiters.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. +""" +@inline function flux_nonconservative_powell_local_symmetric(u_ll, u_rr, + orientation::Integer, + equations::IdealGlmMhdEquations2D) + rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, rho_e_ll, B1_ll, B2_ll, B3_ll, psi_ll = u_ll + rho_rr, rho_v1_rr, rho_v2_rr, rho_v3_rr, rho_e_rr, B1_rr, B2_rr, B3_rr, psi_rr = u_rr + + v1_ll = rho_v1_ll / rho_ll + v2_ll = rho_v2_ll / rho_ll + v3_ll = rho_v3_ll / rho_ll + v_dot_B_ll = v1_ll * B1_ll + v2_ll * B2_ll + v3_ll * B3_ll + + # Powell nonconservative term: (0, B_1, B_2, B_3, v⋅B, v_1, v_2, v_3, 0) + # Galilean nonconservative term: (0, 0, 0, 0, ψ v_{1,2}, 0, 0, 0, v_{1,2}) + psi_avg = (psi_ll + psi_rr) #* 0.5 # The flux is already multiplied by 0.5 wherever it is used in the code + if orientation == 1 + B1_avg = (B1_ll + B1_rr) #* 0.5 # The flux is already multiplied by 0.5 wherever it is used in the code + f = SVector(0, + B1_ll * B1_avg, + B2_ll * B1_avg, + B3_ll * B1_avg, + v_dot_B_ll * B1_avg + v1_ll * psi_ll * psi_avg, + v1_ll * B1_avg, + v2_ll * B1_avg, + v3_ll * B1_avg, + v1_ll * psi_avg) + else # orientation == 2 + B2_avg = (B2_ll + B2_rr) #* 0.5 # The flux is already multiplied by 0.5 wherever it is used in the code + f = SVector(0, + B1_ll * B2_avg, + B2_ll * B2_avg, + B3_ll * B2_avg, + v_dot_B_ll * B2_avg + v2_ll * psi_ll * psi_avg, + v1_ll * B2_avg, + v2_ll * B2_avg, + v3_ll * B2_avg, + v2_ll * psi_avg) + end + + return f +end + +""" + 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 dg_2d_subcell_limiters.jl. +""" +@inline function flux_nonconservative_powell_local_symmetric(u_ll, orientation::Integer, + equations::IdealGlmMhdEquations2D, + nonconservative_type::NonConservativeLocal, + nonconservative_term::Integer) + rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, rho_e_ll, B1_ll, B2_ll, B3_ll, psi_ll = u_ll + + if nonconservative_term == 1 + # Powell nonconservative term: (0, B_1, B_2, B_3, v⋅B, v_1, v_2, v_3, 0) + v1_ll = rho_v1_ll / rho_ll + v2_ll = rho_v2_ll / rho_ll + v3_ll = rho_v3_ll / rho_ll + v_dot_B_ll = v1_ll * B1_ll + v2_ll * B2_ll + v3_ll * B3_ll + f = SVector(0, + B1_ll, + B2_ll, + B3_ll, + v_dot_B_ll, + v1_ll, + v2_ll, + v3_ll, + 0) + else #nonconservative_term ==2 + # Galilean nonconservative term: (0, 0, 0, 0, ψ v_{1,2}, 0, 0, 0, v_{1,2}) + if orientation == 1 + v1_ll = rho_v1_ll / rho_ll + f = SVector(0, + 0, + 0, + 0, + v1_ll * psi_ll, + 0, + 0, + 0, + v1_ll) + else #orientation == 2 + v2_ll = rho_v2_ll / rho_ll + f = SVector(0, + 0, + 0, + 0, + v2_ll * psi_ll, + 0, + 0, + 0, + v2_ll) + end + end + return f +end + +""" + 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 dg_2d_subcell_limiters.jl. +""" +@inline function flux_nonconservative_powell_local_symmetric(u_ll, u_rr, + orientation::Integer, + equations::IdealGlmMhdEquations2D, + nonconservative_type::NonConservativeSymmetric, + nonconservative_term::Integer) + rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, rho_e_ll, B1_ll, B2_ll, B3_ll, psi_ll = u_ll + rho_rr, rho_v1_rr, rho_v2_rr, rho_v3_rr, rho_e_rr, B1_rr, B2_rr, B3_rr, psi_rr = u_rr + + if nonconservative_term == 1 + # Powell nonconservative term: (0, B_1, B_2, B_3, v⋅B, v_1, v_2, v_3, 0) + if orientation == 1 + B1_avg = (B1_ll + B1_rr)#* 0.5 # The flux is already multiplied by 0.5 wherever it is used in the code + f = SVector(0, + B1_avg, + B1_avg, + B1_avg, + B1_avg, + B1_avg, + B1_avg, + B1_avg, + 0) + else # orientation == 2 + B2_avg = (B2_ll + B2_rr)#* 0.5 # The flux is already multiplied by 0.5 wherever it is used in the code + f = SVector(0, + B2_avg, + B2_avg, + B2_avg, + B2_avg, + B2_avg, + B2_avg, + B2_avg, + 0) + end + else #nonconservative_term == 2 + # Galilean nonconservative term: (0, 0, 0, 0, ψ v_{1,2}, 0, 0, 0, v_{1,2}) + psi_avg = (psi_ll + psi_rr)#* 0.5 # The flux is already multiplied by 0.5 wherever it is used in the code + f = SVector(0, + 0, + 0, + 0, + psi_avg, + 0, + 0, + 0, + psi_avg) + end + + return f +end + """ flux_derigs_etal(u_ll, u_rr, orientation, equations::IdealGlmMhdEquations2D) @@ -585,6 +775,56 @@ end return max(abs(v_ll), abs(v_rr)) + max(cf_ll, cf_rr) end +# Calculate estimate for minimum and maximum wave speeds for HLL-type fluxes +@inline function min_max_speed_naive(u_ll, u_rr, orientation::Integer, + equations::IdealGlmMhdEquations2D) + rho_ll, rho_v1_ll, rho_v2_ll, _ = u_ll + rho_rr, rho_v1_rr, rho_v2_rr, _ = u_rr + + # Calculate primitive velocity variables + v1_ll = rho_v1_ll / rho_ll + v2_ll = rho_v2_ll / rho_ll + + v1_rr = rho_v1_rr / rho_rr + v2_rr = rho_v2_rr / rho_rr + + # Approximate the left-most and right-most eigenvalues in the Riemann fan + if orientation == 1 # x-direction + λ_min = v1_ll - calc_fast_wavespeed(u_ll, orientation, equations) + λ_max = v1_rr + calc_fast_wavespeed(u_rr, orientation, equations) + else # y-direction + λ_min = v2_ll - calc_fast_wavespeed(u_ll, orientation, equations) + λ_max = v2_rr + calc_fast_wavespeed(u_rr, orientation, equations) + end + + return λ_min, λ_max +end + +@inline function min_max_speed_naive(u_ll, u_rr, normal_direction::AbstractVector, + equations::IdealGlmMhdEquations2D) + rho_ll, rho_v1_ll, rho_v2_ll, _ = u_ll + rho_rr, rho_v1_rr, rho_v2_rr, _ = u_rr + + # Calculate primitive velocity variables + v1_ll = rho_v1_ll / rho_ll + v2_ll = rho_v2_ll / rho_ll + + v1_rr = rho_v1_rr / rho_rr + v2_rr = rho_v2_rr / rho_rr + + v_normal_ll = (v1_ll * normal_direction[1] + v2_ll * normal_direction[2]) + v_normal_rr = (v1_rr * normal_direction[1] + v2_rr * normal_direction[2]) + + c_f_ll = calc_fast_wavespeed(u_ll, normal_direction, equations) + c_f_rr = calc_fast_wavespeed(u_rr, normal_direction, equations) + + # Estimate the min/max eigenvalues in the normal direction + λ_min = min(v_normal_ll - c_f_ll, v_normal_rr - c_f_rr) + λ_max = max(v_normal_rr + c_f_rr, v_normal_rr + c_f_rr) + + return λ_min, λ_max +end + # More refined estimates for minimum and maximum wave speeds for HLL-type fluxes @inline function min_max_speed_davis(u_ll, u_rr, orientation::Integer, equations::IdealGlmMhdEquations2D) @@ -643,15 +883,15 @@ end end """ - min_max_speed_naive(u_ll, u_rr, orientation::Integer, equations::IdealGlmMhdEquations2D) + min_max_speed_einfeldt(u_ll, u_rr, orientation::Integer, equations::IdealGlmMhdEquations2D) Calculate minimum and maximum wave speeds for HLL-type fluxes as in - Li (2005) An HLLC Riemann solver for magneto-hydrodynamics [DOI: 10.1016/j.jcp.2004.08.020](https://doi.org/10.1016/j.jcp.2004.08.020). """ -@inline function min_max_speed_naive(u_ll, u_rr, orientation::Integer, - equations::IdealGlmMhdEquations2D) +@inline function min_max_speed_einfeldt(u_ll, u_rr, orientation::Integer, + equations::IdealGlmMhdEquations2D) rho_ll, rho_v1_ll, rho_v2_ll, _ = u_ll rho_rr, rho_v1_rr, rho_v2_rr, _ = u_rr @@ -680,8 +920,8 @@ Calculate minimum and maximum wave speeds for HLL-type fluxes as in return λ_min, λ_max end -@inline function min_max_speed_naive(u_ll, u_rr, normal_direction::AbstractVector, - equations::IdealGlmMhdEquations2D) +@inline function min_max_speed_einfeldt(u_ll, u_rr, normal_direction::AbstractVector, + equations::IdealGlmMhdEquations2D) rho_ll, rho_v1_ll, rho_v2_ll, _ = u_ll rho_rr, rho_v1_rr, rho_v2_rr, _ = u_rr diff --git a/src/equations/ideal_glm_mhd_3d.jl b/src/equations/ideal_glm_mhd_3d.jl index 09990837706..321e501b051 100644 --- a/src/equations/ideal_glm_mhd_3d.jl +++ b/src/equations/ideal_glm_mhd_3d.jl @@ -670,6 +670,64 @@ end return max(abs(v_ll), abs(v_rr)) + max(cf_ll, cf_rr) end +# Calculate estimate for minimum and maximum wave speeds for HLL-type fluxes +@inline function min_max_speed_naive(u_ll, u_rr, orientation::Integer, + equations::IdealGlmMhdEquations3D) + rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, _ = u_ll + rho_rr, rho_v1_rr, rho_v2_rr, rho_v3_rr, _ = u_rr + + # Calculate primitive variables and speed of sound + v1_ll = rho_v1_ll / rho_ll + v2_ll = rho_v2_ll / rho_ll + v3_ll = rho_v3_ll / rho_ll + + v1_rr = rho_v1_rr / rho_rr + v2_rr = rho_v2_rr / rho_rr + v3_rr = rho_v3_rr / rho_rr + + # Approximate the left-most and right-most eigenvalues in the Riemann fan + if orientation == 1 # x-direction + λ_min = v1_ll - calc_fast_wavespeed(u_ll, orientation, equations) + λ_max = v1_rr + calc_fast_wavespeed(u_rr, orientation, equations) + elseif orientation == 2 # y-direction + λ_min = v2_ll - calc_fast_wavespeed(u_ll, orientation, equations) + λ_max = v2_rr + calc_fast_wavespeed(u_rr, orientation, equations) + else # z-direction + λ_min = v3_ll - calc_fast_wavespeed(u_ll, orientation, equations) + λ_max = v3_rr + calc_fast_wavespeed(u_rr, orientation, equations) + end + + return λ_min, λ_max +end + +@inline function min_max_speed_naive(u_ll, u_rr, normal_direction::AbstractVector, + equations::IdealGlmMhdEquations3D) + rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, _ = u_ll + rho_rr, rho_v1_rr, rho_v2_rr, rho_v3_rr, _ = u_rr + + # Calculate primitive velocity variables + v1_ll = rho_v1_ll / rho_ll + v2_ll = rho_v2_ll / rho_ll + v3_ll = rho_v3_ll / rho_ll + + v1_rr = rho_v1_rr / rho_rr + v2_rr = rho_v2_rr / rho_rr + v3_rr = rho_v3_rr / rho_rr + + v_normal_ll = (v1_ll * normal_direction[1] + + v2_ll * normal_direction[2] + + v3_ll * normal_direction[3]) + v_normal_rr = (v1_rr * normal_direction[1] + + v2_rr * normal_direction[2] + + v3_rr * normal_direction[3]) + + # Estimate the min/max eigenvalues in the normal direction + λ_min = v_normal_ll - calc_fast_wavespeed(u_ll, normal_direction, equations) + λ_max = v_normal_rr + calc_fast_wavespeed(u_rr, normal_direction, equations) + + return λ_min, λ_max +end + # More refined estimates for minimum and maximum wave speeds for HLL-type fluxes @inline function min_max_speed_davis(u_ll, u_rr, orientation::Integer, equations::IdealGlmMhdEquations3D) @@ -742,15 +800,15 @@ end end """ - min_max_speed_naive(u_ll, u_rr, orientation_or_normal_direction, equations::IdealGlmMhdEquations3D) + min_max_speed_einfeldt(u_ll, u_rr, orientation_or_normal_direction, equations::IdealGlmMhdEquations3D) Calculate minimum and maximum wave speeds for HLL-type fluxes as in - Li (2005) An HLLC Riemann solver for magneto-hydrodynamics [DOI: 10.1016/j.jcp.2004.08.020](https://doi.org/10.1016/j.jcp.2004.08.020) """ -@inline function min_max_speed_naive(u_ll, u_rr, orientation::Integer, - equations::IdealGlmMhdEquations3D) +@inline function min_max_speed_einfeldt(u_ll, u_rr, orientation::Integer, + equations::IdealGlmMhdEquations3D) rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, _ = u_ll rho_rr, rho_v1_rr, rho_v2_rr, rho_v3_rr, _ = u_rr @@ -787,8 +845,8 @@ Calculate minimum and maximum wave speeds for HLL-type fluxes as in return λ_min, λ_max end -@inline function min_max_speed_naive(u_ll, u_rr, normal_direction::AbstractVector, - equations::IdealGlmMhdEquations3D) +@inline function min_max_speed_einfeldt(u_ll, u_rr, normal_direction::AbstractVector, + equations::IdealGlmMhdEquations3D) rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, _ = u_ll rho_rr, rho_v1_rr, rho_v2_rr, rho_v3_rr, _ = u_rr diff --git a/src/equations/ideal_glm_mhd_multicomponent_1d.jl b/src/equations/ideal_glm_mhd_multicomponent_1d.jl index 0efa6426448..dad7c27e86c 100644 --- a/src/equations/ideal_glm_mhd_multicomponent_1d.jl +++ b/src/equations/ideal_glm_mhd_multicomponent_1d.jl @@ -17,19 +17,15 @@ mutable struct IdealGlmMhdMulticomponentEquations1D{NVARS, NCOMP, RealT <: Real} cv::SVector{NCOMP, RealT} cp::SVector{NCOMP, RealT} - function IdealGlmMhdMulticomponentEquations1D{NVARS, NCOMP, RealT}(gammas::SVector{ - NCOMP, - RealT - }, - gas_constants::SVector{ - NCOMP, - RealT - }) where { - NVARS, - NCOMP, - RealT <: - Real - } + function IdealGlmMhdMulticomponentEquations1D{NVARS, NCOMP, RealT}(gammas::SVector{NCOMP, + RealT}, + gas_constants::SVector{NCOMP, + RealT}) where { + NVARS, + NCOMP, + RealT <: + Real + } NCOMP >= 1 || throw(DimensionMismatch("`gammas` and `gas_constants` have to be filled with at least one value")) diff --git a/src/equations/ideal_glm_mhd_multicomponent_2d.jl b/src/equations/ideal_glm_mhd_multicomponent_2d.jl index 9b0eeb411e8..a3a50c0485f 100644 --- a/src/equations/ideal_glm_mhd_multicomponent_2d.jl +++ b/src/equations/ideal_glm_mhd_multicomponent_2d.jl @@ -18,19 +18,15 @@ mutable struct IdealGlmMhdMulticomponentEquations2D{NVARS, NCOMP, RealT <: Real} cp::SVector{NCOMP, RealT} c_h::RealT # GLM cleaning speed - function IdealGlmMhdMulticomponentEquations2D{NVARS, NCOMP, RealT}(gammas::SVector{ - NCOMP, - RealT - }, - gas_constants::SVector{ - NCOMP, - RealT - }) where { - NVARS, - NCOMP, - RealT <: - Real - } + function IdealGlmMhdMulticomponentEquations2D{NVARS, NCOMP, RealT}(gammas::SVector{NCOMP, + RealT}, + gas_constants::SVector{NCOMP, + RealT}) where { + NVARS, + NCOMP, + RealT <: + Real + } NCOMP >= 1 || throw(DimensionMismatch("`gammas` and `gas_constants` have to be filled with at least one value")) diff --git a/src/equations/laplace_diffusion_2d.jl b/src/equations/laplace_diffusion_2d.jl index 3443e9c097b..b848633fbcb 100644 --- a/src/equations/laplace_diffusion_2d.jl +++ b/src/equations/laplace_diffusion_2d.jl @@ -18,7 +18,6 @@ function varnames(variable_mapping, equations_parabolic::LaplaceDiffusion2D) varnames(variable_mapping, equations_parabolic.equations_hyperbolic) end -# no orientation specified since the flux is vector-valued function flux(u, gradients, orientation::Integer, equations_parabolic::LaplaceDiffusion2D) dudx, dudy = gradients if orientation == 1 diff --git a/src/equations/laplace_diffusion_3d.jl b/src/equations/laplace_diffusion_3d.jl new file mode 100644 index 00000000000..457e742430b --- /dev/null +++ b/src/equations/laplace_diffusion_3d.jl @@ -0,0 +1,71 @@ +@doc raw""" + 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`. +""" +struct LaplaceDiffusion3D{E, N, T} <: AbstractLaplaceDiffusion{3, N} + diffusivity::T + equations_hyperbolic::E +end + +function LaplaceDiffusion3D(diffusivity, equations_hyperbolic) + LaplaceDiffusion3D{typeof(equations_hyperbolic), nvariables(equations_hyperbolic), + typeof(diffusivity)}(diffusivity, equations_hyperbolic) +end + +function varnames(variable_mapping, equations_parabolic::LaplaceDiffusion3D) + varnames(variable_mapping, equations_parabolic.equations_hyperbolic) +end + +function flux(u, gradients, orientation::Integer, equations_parabolic::LaplaceDiffusion3D) + dudx, dudy, dudz = gradients + if orientation == 1 + return SVector(equations_parabolic.diffusivity * dudx) + elseif orientation == 2 + return SVector(equations_parabolic.diffusivity * dudy) + else # if orientation == 3 + return SVector(equations_parabolic.diffusivity * dudz) + end +end + +# TODO: parabolic; should this remain in the equations file, be moved to solvers, or live in the elixir? +# The penalization depends on the solver, but also depends explicitly on physical parameters, +# and would probably need to be specialized for every different equation. +function penalty(u_outer, u_inner, inv_h, equations_parabolic::LaplaceDiffusion3D, + dg::ViscousFormulationLocalDG) + return dg.penalty_parameter * (u_outer - u_inner) * equations_parabolic.diffusivity +end + +# Dirichlet-type boundary condition for use with a parabolic solver in weak form +@inline function (boundary_condition::BoundaryConditionDirichlet)(flux_inner, u_inner, + normal::AbstractVector, + x, t, + operator_type::Gradient, + equations_parabolic::LaplaceDiffusion3D) + return boundary_condition.boundary_value_function(x, t, equations_parabolic) +end + +@inline function (boundary_condition::BoundaryConditionDirichlet)(flux_inner, u_inner, + normal::AbstractVector, + x, t, + operator_type::Divergence, + equations_parabolic::LaplaceDiffusion3D) + return flux_inner +end + +@inline function (boundary_condition::BoundaryConditionNeumann)(flux_inner, u_inner, + normal::AbstractVector, + x, t, + operator_type::Divergence, + equations_parabolic::LaplaceDiffusion3D) + return boundary_condition.boundary_normal_flux_function(x, t, equations_parabolic) +end + +@inline function (boundary_condition::BoundaryConditionNeumann)(flux_inner, u_inner, + normal::AbstractVector, + x, t, + operator_type::Gradient, + equations_parabolic::LaplaceDiffusion3D) + return flux_inner +end diff --git a/src/equations/numerical_fluxes.jl b/src/equations/numerical_fluxes.jl index 87010275f2c..44d523b6e89 100644 --- a/src/equations/numerical_fluxes.jl +++ b/src/equations/numerical_fluxes.jl @@ -61,6 +61,23 @@ struct FluxRotated{NumericalFlux} numerical_flux::NumericalFlux end +# Rotated surface flux computation (2D version) +@inline function (flux_rotated::FluxRotated)(u, + normal_direction::AbstractVector, + equations::AbstractEquations{2}) + @unpack numerical_flux = flux_rotated + + norm_ = norm(normal_direction) + # Normalize the vector without using `normalize` since we need to multiply by the `norm_` later + normal_vector = normal_direction / norm_ + + u_rotated = rotate_to_x(u, normal_vector, equations) + + f = numerical_flux(u_rotated, 1, equations) + + return rotate_from_x(f, normal_vector, equations) * norm_ +end + # Rotated surface flux computation (2D version) @inline function (flux_rotated::FluxRotated)(u_ll, u_rr, normal_direction::AbstractVector, @@ -181,10 +198,7 @@ function max_abs_speed_naive end end const FluxLaxFriedrichs{MaxAbsSpeed} = FluxPlusDissipation{typeof(flux_central), - DissipationLocalLaxFriedrichs{ - MaxAbsSpeed - } - } + DissipationLocalLaxFriedrichs{MaxAbsSpeed}} """ FluxLaxFriedrichs(max_abs_speed=max_abs_speed_naive) @@ -304,6 +318,14 @@ See [`FluxHLL`](@ref). """ const flux_hll = FluxHLL() +""" + flux_hlle + +See [`min_max_speed_einfeldt`](@ref). +This is a [`FluxHLL`](@ref)-type two-wave solver with special estimates of the wave speeds. +""" +const flux_hlle = FluxHLL(min_max_speed_einfeldt) + # TODO: TrixiShallowWater: move the chen_noelle flux structure to the new package # An empty version of the `min_max_speed_chen_noelle` function is declared here diff --git a/src/equations/polytropic_euler_2d.jl b/src/equations/polytropic_euler_2d.jl new file mode 100644 index 00000000000..f5d2f7b0bad --- /dev/null +++ b/src/equations/polytropic_euler_2d.jl @@ -0,0 +1,355 @@ +# By default, Julia/LLVM does not use fused multiply-add operations (FMAs). +# Since these FMAs can increase the performance of many numerical algorithms, +# we need to opt-in explicitly. +# See https://ranocha.de/blog/Optimizing_EC_Trixi for further details. +@muladd begin +#! format: noindent + +@doc raw""" + PolytropicEulerEquations2D(gamma, kappa) + +The polytropic Euler equations +```math +\frac{\partial}{\partial t} +\begin{pmatrix} +\rho \\ \rho v_1 \\ \rho v_2 +\end{pmatrix} ++ +\frac{\partial}{\partial x} +\begin{pmatrix} + \rho v_1 \\ \rho v_1^2 + \kappa\rho^\gamma \\ \rho v_1 v_2 +\end{pmatrix} ++ +\frac{\partial}{\partial y} +\begin{pmatrix} +\rho v_2 \\ \rho v_1 v_2 \\ \rho v_2^2 + \kappa\rho^\gamma +\end{pmatrix} += +\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`` and`v_2` the velocities and +```math +p = \kappa\rho^\gamma +``` +the pressure, which we replaced using this relation. +""" +struct PolytropicEulerEquations2D{RealT <: Real} <: + AbstractPolytropicEulerEquations{2, 3} + gamma::RealT # ratio of specific heats + kappa::RealT # fluid scaling factor + + function PolytropicEulerEquations2D(gamma, kappa) + gamma_, kappa_ = promote(gamma, kappa) + new{typeof(gamma_)}(gamma_, kappa_) + end +end + +function varnames(::typeof(cons2cons), ::PolytropicEulerEquations2D) + ("rho", "rho_v1", "rho_v2") +end +varnames(::typeof(cons2prim), ::PolytropicEulerEquations2D) = ("rho", "v1", "v2") + +""" + initial_condition_convergence_test(x, t, equations::PolytropicEulerEquations2D) + +Manufactured smooth initial condition used for convergence tests +in combination with [`source_terms_convergence_test`](@ref). +""" +function initial_condition_convergence_test(x, t, equations::PolytropicEulerEquations2D) + # manufactured initial condition from Winters (2019) [0.1007/s10543-019-00789-w] + # domain must be set to [0, 1] x [0, 1] + h = 8 + cos(2 * pi * x[1]) * sin(2 * pi * x[2]) * cos(2 * pi * t) + + return SVector(h, h / 2, 3 * h / 2) +end + +""" + source_terms_convergence_test(u, x, t, equations::PolytropicEulerEquations2D) + +Source terms used for convergence tests in combination with +[`initial_condition_convergence_test`](@ref). +""" +@inline function source_terms_convergence_test(u, x, t, + equations::PolytropicEulerEquations2D) + rho, v1, v2 = cons2prim(u, equations) + + # Residual from Winters (2019) [0.1007/s10543-019-00789-w] eq. (5.2). + h = 8 + cos(2 * pi * x[1]) * sin(2 * pi * x[2]) * cos(2 * pi * t) + h_t = -2 * pi * cos(2 * pi * x[1]) * sin(2 * pi * x[2]) * sin(2 * pi * t) + h_x = -2 * pi * sin(2 * pi * x[1]) * sin(2 * pi * x[2]) * cos(2 * pi * t) + h_y = 2 * pi * cos(2 * pi * x[1]) * cos(2 * pi * x[2]) * cos(2 * pi * t) + + rho_x = h_x + rho_y = h_y + + b = equations.kappa * equations.gamma * h^(equations.gamma - 1) + + r_1 = h_t + h_x / 2 + 3 / 2 * h_y + r_2 = h_t / 2 + h_x / 4 + b * rho_x + 3 / 4 * h_y + r_3 = 3 / 2 * h_t + 3 / 4 * h_x + 9 / 4 * h_y + b * rho_y + + return SVector(r_1, r_2, r_3) +end + +""" + 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](https://arxiv.org/abs/2008.12044) +""" +function initial_condition_weak_blast_wave(x, t, equations::PolytropicEulerEquations2D) + # Adapted MHD version of the weak blast wave from Hennemann & Gassner JCP paper 2020 (Sec. 6.3) + # Set up polar coordinates + inicenter = (0, 0) + x_norm = x[1] - inicenter[1] + y_norm = x[2] - inicenter[2] + r = sqrt(x_norm^2 + y_norm^2) + phi = atan(y_norm, x_norm) + + # Calculate primitive variables + rho = r > 0.5 ? 1.0 : 1.1691 + v1 = r > 0.5 ? 0.0 : 0.1882 * cos(phi) + v2 = r > 0.5 ? 0.0 : 0.1882 * sin(phi) + + return prim2cons(SVector(rho, v1, v2), equations) +end + +# Calculate 2D flux for a single point in the normal direction +# Note, this directional vector is not normalized +@inline function flux(u, normal_direction::AbstractVector, + equations::PolytropicEulerEquations2D) + rho, v1, v2 = cons2prim(u, equations) + p = pressure(u, equations) + + v_normal = v1 * normal_direction[1] + v2 * normal_direction[2] + rho_v_normal = rho * v_normal + f1 = rho_v_normal + f2 = rho_v_normal * v1 + p * normal_direction[1] + f3 = rho_v_normal * v2 + p * normal_direction[2] + return SVector(f1, f2, f3) +end + +# Calculate 2D flux for a single point +@inline function flux(u, orientation::Integer, equations::PolytropicEulerEquations2D) + _, v1, v2 = cons2prim(u, equations) + p = pressure(u, equations) + + rho_v1 = u[2] + rho_v2 = u[3] + + if orientation == 1 + f1 = rho_v1 + f2 = rho_v1 * v1 + p + f3 = rho_v1 * v2 + else + f1 = rho_v2 + f2 = rho_v2 * v1 + f3 = rho_v2 * v2 + p + end + return SVector(f1, f2, f3) +end + +""" + flux_winters_etal(u_ll, u_rr, orientation_or_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`](@ref). + +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](https://doi.org/10.1007/s10543-019-00789-w) +""" +@inline function flux_winters_etal(u_ll, u_rr, normal_direction::AbstractVector, + equations::PolytropicEulerEquations2D) + # Unpack left and right state + rho_ll, v1_ll, v2_ll = cons2prim(u_ll, equations) + rho_rr, v1_rr, v2_rr = cons2prim(u_rr, equations) + p_ll = equations.kappa * rho_ll^equations.gamma + p_rr = equations.kappa * rho_rr^equations.gamma + v_dot_n_ll = v1_ll * normal_direction[1] + v2_ll * normal_direction[2] + v_dot_n_rr = v1_rr * normal_direction[1] + v2_rr * normal_direction[2] + + # Compute the necessary mean values + if equations.gamma == 1.0 # isothermal gas + rho_mean = ln_mean(rho_ll, rho_rr) + else # equations.gamma > 1 # polytropic gas + rho_mean = stolarsky_mean(rho_ll, rho_rr, equations.gamma) + end + v1_avg = 0.5 * (v1_ll + v1_rr) + v2_avg = 0.5 * (v2_ll + v2_rr) + p_avg = 0.5 * (p_ll + p_rr) + + # Calculate fluxes depending on normal_direction + f1 = rho_mean * 0.5 * (v_dot_n_ll + v_dot_n_rr) + f2 = f1 * v1_avg + p_avg * normal_direction[1] + f3 = f1 * v2_avg + p_avg * normal_direction[2] + + return SVector(f1, f2, f3) +end + +@inline function flux_winters_etal(u_ll, u_rr, orientation::Integer, + equations::PolytropicEulerEquations2D) + # Unpack left and right state + rho_ll, v1_ll, v2_ll = cons2prim(u_ll, equations) + rho_rr, v1_rr, v2_rr = cons2prim(u_rr, equations) + p_ll = equations.kappa * rho_ll^equations.gamma + p_rr = equations.kappa * rho_rr^equations.gamma + + # Compute the necessary mean values + if equations.gamma == 1.0 # isothermal gas + rho_mean = ln_mean(rho_ll, rho_rr) + else # equations.gamma > 1 # polytropic gas + rho_mean = stolarsky_mean(rho_ll, rho_rr, equations.gamma) + end + v1_avg = 0.5 * (v1_ll + v1_rr) + v2_avg = 0.5 * (v2_ll + v2_rr) + p_avg = 0.5 * (p_ll + p_rr) + + if orientation == 1 # x-direction + f1 = rho_mean * 0.5 * (v1_ll + v1_rr) + f2 = f1 * v1_avg + p_avg + f3 = f1 * v2_avg + else # y-direction + f1 = rho_mean * 0.5 * (v2_ll + v2_rr) + f2 = f1 * v1_avg + f3 = f1 * v2_avg + p_avg + end + + return SVector(f1, f2, f3) +end + +@inline function min_max_speed_naive(u_ll, u_rr, normal_direction::AbstractVector, + equations::PolytropicEulerEquations2D) + rho_ll, v1_ll, v2_ll = cons2prim(u_ll, equations) + rho_rr, v1_rr, v2_rr = cons2prim(u_rr, equations) + p_ll = equations.kappa * rho_ll^equations.gamma + p_rr = equations.kappa * rho_rr^equations.gamma + + v_normal_ll = v1_ll * normal_direction[1] + v2_ll * normal_direction[2] + v_normal_rr = v1_rr * normal_direction[1] + v2_rr * normal_direction[2] + + norm_ = norm(normal_direction) + # The v_normals are already scaled by the norm + lambda_min = v_normal_ll - sqrt(equations.gamma * p_ll / rho_ll) * norm_ + lambda_max = v_normal_rr + sqrt(equations.gamma * p_rr / rho_rr) * norm_ + + return lambda_min, lambda_max +end + +# More refined estimates for minimum and maximum wave speeds for HLL-type fluxes +@inline function min_max_speed_davis(u_ll, u_rr, orientation::Integer, + equations::PolytropicEulerEquations2D) + rho_ll, v1_ll, v2_ll = cons2prim(u_ll, equations) + rho_rr, v1_rr, v2_rr = cons2prim(u_rr, equations) + # Pressure for polytropic Euler + p_ll = equations.kappa * rho_ll^equations.gamma + p_rr = equations.kappa * rho_rr^equations.gamma + + c_ll = sqrt(equations.gamma * p_ll / rho_ll) + c_rr = sqrt(equations.gamma * p_rr / rho_rr) + + if orientation == 1 # x-direction + λ_min = min(v1_ll - c_ll, v1_rr - c_rr) + λ_max = max(v1_ll + c_ll, v1_rr + c_rr) + else # y-direction + λ_min = min(v2_ll - c_ll, v2_rr - c_rr) + λ_max = max(v2_ll + c_ll, v2_rr + c_rr) + end + + return λ_min, λ_max +end + +# More refined estimates for minimum and maximum wave speeds for HLL-type fluxes +@inline function min_max_speed_davis(u_ll, u_rr, normal_direction::AbstractVector, + equations::PolytropicEulerEquations2D) + rho_ll, v1_ll, v2_ll = cons2prim(u_ll, equations) + rho_rr, v1_rr, v2_rr = cons2prim(u_rr, equations) + # Pressure for polytropic Euler + p_ll = equations.kappa * rho_ll^equations.gamma + p_rr = equations.kappa * rho_rr^equations.gamma + + norm_ = norm(normal_direction) + + c_ll = sqrt(equations.gamma * p_ll / rho_ll) * norm_ + c_rr = sqrt(equations.gamma * p_rr / rho_rr) * norm_ + + v_normal_ll = v1_ll * normal_direction[1] + v2_ll * normal_direction[2] + v_normal_rr = v1_rr * normal_direction[1] + v2_rr * normal_direction[2] + + # The v_normals are already scaled by the norm + λ_min = min(v_normal_ll - c_ll, v_normal_rr - c_rr) + λ_max = max(v_normal_ll + c_ll, v_normal_rr + c_rr) + + return λ_min, λ_max +end + +@inline function max_abs_speeds(u, equations::PolytropicEulerEquations2D) + rho, v1, v2 = cons2prim(u, equations) + c = sqrt(equations.gamma * equations.kappa * rho^(equations.gamma - 1)) + + return abs(v1) + c, abs(v2) + c +end + +# Convert conservative variables to primitive +@inline function cons2prim(u, equations::PolytropicEulerEquations2D) + rho, rho_v1, rho_v2 = u + + v1 = rho_v1 / rho + v2 = rho_v2 / rho + + return SVector(rho, v1, v2) +end + +# Convert conservative variables to entropy +@inline function cons2entropy(u, equations::PolytropicEulerEquations2D) + rho, rho_v1, rho_v2 = u + + v1 = rho_v1 / rho + v2 = rho_v2 / rho + v_square = v1^2 + v2^2 + p = pressure(u, equations) + # Form of the internal energy depends on gas type + if equations.gamma == 1.0 # isothermal gas + internal_energy = equations.kappa * log(rho) + else # equations.gamma > 1 # polytropic gas + internal_energy = equations.kappa * rho^(equations.gamma - 1) / + (equations.gamma - 1.0) + end + + w1 = internal_energy + p / rho - 0.5 * v_square + w2 = v1 + w3 = v2 + + return SVector(w1, w2, w3) +end + +# Convert primitive to conservative variables +@inline function prim2cons(prim, equations::PolytropicEulerEquations2D) + rho, v1, v2 = prim + rho_v1 = rho * v1 + rho_v2 = rho * v2 + return SVector(rho, rho_v1, rho_v2) +end + +@inline function density(u, equations::PolytropicEulerEquations2D) + rho = u[1] + return rho +end + +@inline function pressure(u, equations::PolytropicEulerEquations2D) + rho, rho_v1, rho_v2 = u + p = equations.kappa * rho^equations.gamma + return p +end +end # @muladd diff --git a/src/equations/shallow_water_1d.jl b/src/equations/shallow_water_1d.jl index 32782d5478c..25ce0fa79fe 100644 --- a/src/equations/shallow_water_1d.jl +++ b/src/equations/shallow_water_1d.jl @@ -380,6 +380,44 @@ Further details on the hydrostatic reconstruction and its motivation can be foun z) end +""" + flux_nonconservative_ersing_etal(u_ll, u_rr, orientation::Integer, + equations::ShallowWaterEquations1D) + +!!! warning "Experimental code" + This numerical flux is experimental and may change in any future release. + +Non-symmetric path-conservative two-point volume flux discretizing the nonconservative (source) term +that contains the gradient of the bottom topography [`ShallowWaterEquations1D`](@ref). + +This is a modified version of [`flux_nonconservative_wintermeyer_etal`](@ref) that gives entropy +conservation and well-balancedness in both the volume and surface when combined with +[`flux_wintermeyer_etal`](@ref). + +For further details see: +- Patrick Ersing, Andrew R. Winters (2023) + An entropy stable discontinuous Galerkin method for the two-layer shallow water equations on + curvilinear meshes + [DOI: 10.48550/arXiv.2306.12699](https://doi.org/10.48550/arXiv.2306.12699) +""" +@inline function flux_nonconservative_ersing_etal(u_ll, u_rr, orientation::Integer, + equations::ShallowWaterEquations1D) + # Pull the necessary left and right state information + h_ll = waterheight(u_ll, equations) + b_rr = u_rr[3] + b_ll = u_ll[3] + + # Calculate jump + b_jump = b_rr - b_ll + + z = zero(eltype(u_ll)) + + # Bottom gradient nonconservative term: (0, g h b_x, 0) + f = SVector(z, equations.gravity * h_ll * b_jump, z) + + return f +end + """ flux_fjordholm_etal(u_ll, u_rr, orientation, equations::ShallowWaterEquations1D) diff --git a/src/equations/shallow_water_2d.jl b/src/equations/shallow_water_2d.jl index a81fddeed49..e75c92a27d0 100644 --- a/src/equations/shallow_water_2d.jl +++ b/src/equations/shallow_water_2d.jl @@ -702,6 +702,74 @@ end return SVector(f1, f2, f3, f4) end +""" + flux_nonconservative_ersing_etal(u_ll, u_rr, orientation::Integer, + equations::ShallowWaterEquations2D) + flux_nonconservative_ersing_etal(u_ll, u_rr, + normal_direction_ll::AbstractVector, + normal_direction_average::AbstractVector, + equations::ShallowWaterEquations2D) + +!!! warning "Experimental code" + This numerical flux is experimental and may change in any future release. + +Non-symmetric path-conservative two-point volume flux discretizing the nonconservative (source) term +that contains the gradient of the bottom topography [`ShallowWaterEquations2D`](@ref). + +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 is a modified version of [`flux_nonconservative_wintermeyer_etal`](@ref) that gives entropy +conservation and well-balancedness in both the volume and surface when combined with +[`flux_wintermeyer_etal`](@ref). + +For further details see: +- Patrick Ersing, Andrew R. Winters (2023) + An entropy stable discontinuous Galerkin method for the two-layer shallow water equations on + curvilinear meshes + [DOI: 10.48550/arXiv.2306.12699](https://doi.org/10.48550/arXiv.2306.12699) +""" +@inline function flux_nonconservative_ersing_etal(u_ll, u_rr, orientation::Integer, + equations::ShallowWaterEquations2D) + # Pull the necessary left and right state information + h_ll = waterheight(u_ll, equations) + b_rr = u_rr[4] + b_ll = u_ll[4] + + # Calculate jump + b_jump = b_rr - b_ll + + z = zero(eltype(u_ll)) + # Bottom gradient nonconservative term: (0, g h b_x, g h b_y, 0) + if orientation == 1 + f = SVector(z, equations.gravity * h_ll * b_jump, z, z) + else # orientation == 2 + f = SVector(z, z, equations.gravity * h_ll * b_jump, z) + end + return f +end + +@inline function flux_nonconservative_ersing_etal(u_ll, u_rr, + normal_direction_ll::AbstractVector, + normal_direction_average::AbstractVector, + equations::ShallowWaterEquations2D) + # Pull the necessary left and right state information + h_ll = waterheight(u_ll, equations) + b_rr = u_rr[4] + b_ll = u_ll[4] + + # Calculate jump + b_jump = b_rr - b_ll + # Note this routine only uses the `normal_direction_average` and the average of the + # bottom topography to get a quadratic split form DG gradient on curved elements + return SVector(zero(eltype(u_ll)), + normal_direction_average[1] * equations.gravity * h_ll * b_jump, + normal_direction_average[2] * equations.gravity * h_ll * b_jump, + zero(eltype(u_ll))) +end + """ flux_fjordholm_etal(u_ll, u_rr, orientation_or_normal_direction, equations::ShallowWaterEquations2D) diff --git a/src/equations/shallow_water_quasi_1d.jl b/src/equations/shallow_water_quasi_1d.jl new file mode 100644 index 00000000000..d3935f0e75f --- /dev/null +++ b/src/equations/shallow_water_quasi_1d.jl @@ -0,0 +1,320 @@ +# By default, Julia/LLVM does not use fused multiply-add operations (FMAs). +# Since these FMAs can increase the performance of many numerical algorithms, +# we need to opt-in explicitly. +# See https://ranocha.de/blog/Optimizing_EC_Trixi for further details. +@muladd begin +#! format: noindent + +@doc raw""" + ShallowWaterEquationsQuasi1D(; gravity, H0 = 0, threshold_limiter = nothing threshold_wet = nothing) + +The quasi-1D shallow water equations (SWE). The equations are given by +```math +\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`](@ref) 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`](@ref) analyzes this variable. +* Trixi.jl's visualization tools will visualize the bottom topography and channel width by default. +""" +struct ShallowWaterEquationsQuasi1D{RealT <: Real} <: + AbstractShallowWaterEquations{1, 4} + gravity::RealT # gravitational constant + H0::RealT # constant "lake-at-rest" total water height + # `threshold_limiter` used in `PositivityPreservingLimiterShallowWater` on water height, + # as a (small) shift on the initial condition and cutoff before the next time step. + # Default is 500*eps() which in double precision is ≈1e-13. + threshold_limiter::RealT + # `threshold_wet` applied on water height to define when the flow is "wet" + # before calculating the numerical flux. + # Default is 5*eps() which in double precision is ≈1e-15. + threshold_wet::RealT +end + +# Allow for flexibility to set the gravitational constant within an elixir depending on the +# application where `gravity_constant=1.0` or `gravity_constant=9.81` are common values. +# The reference total water height H0 defaults to 0.0 but is used for the "lake-at-rest" +# well-balancedness test cases. +# Strict default values for thresholds that performed well in many numerical experiments +function ShallowWaterEquationsQuasi1D(; gravity_constant, H0 = zero(gravity_constant), + threshold_limiter = nothing, + threshold_wet = nothing) + T = promote_type(typeof(gravity_constant), typeof(H0)) + if threshold_limiter === nothing + threshold_limiter = 500 * eps(T) + end + if threshold_wet === nothing + threshold_wet = 5 * eps(T) + end + ShallowWaterEquationsQuasi1D(gravity_constant, H0, threshold_limiter, threshold_wet) +end + +have_nonconservative_terms(::ShallowWaterEquationsQuasi1D) = True() +function varnames(::typeof(cons2cons), ::ShallowWaterEquationsQuasi1D) + ("a_h", "a_h_v", "b", "a") +end +# Note, we use the total water height, H = h + b, as the first primitive variable for easier +# visualization and setting initial conditions +varnames(::typeof(cons2prim), ::ShallowWaterEquationsQuasi1D) = ("H", "v", "b", "a") + +# Set initial conditions at physical location `x` for time `t` +""" + initial_condition_convergence_test(x, t, equations::ShallowWaterEquationsQuasi1D) + +A smooth initial condition used for convergence tests in combination with +[`source_terms_convergence_test`](@ref) +(and [`BoundaryConditionDirichlet(initial_condition_convergence_test)`](@ref) in non-periodic domains). +""" +function initial_condition_convergence_test(x, t, + equations::ShallowWaterEquationsQuasi1D) + # generates a manufactured solution. + # some constants are chosen such that the function is periodic on the domain [0,sqrt(2)] + Omega = sqrt(2) * pi + H = 2.0 + 0.5 * sin(Omega * x[1] - t) + v = 0.25 + b = 0.2 - 0.05 * sin(Omega * x[1]) + a = 1 + 0.1 * cos(Omega * x[1]) + return prim2cons(SVector(H, v, b, a), equations) +end + +""" + source_terms_convergence_test(u, x, t, equations::ShallowWaterEquationsQuasi1D) + +Source terms used for convergence tests in combination with +[`initial_condition_convergence_test`](@ref) +(and [`BoundaryConditionDirichlet(initial_condition_convergence_test)`](@ref) 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`](@ref). +""" +@inline function source_terms_convergence_test(u, x, t, + equations::ShallowWaterEquationsQuasi1D) + # Same settings as in `initial_condition_convergence_test`. Some derivative simplify because + # this manufactured solution velocity is taken to be constant + Omega = sqrt(2) * pi + H = 2.0 + 0.5 * sin(Omega * x[1] - t) + H_x = 0.5 * cos(Omega * x[1] - t) * Omega + H_t = -0.5 * cos(Omega * x[1] - t) + + v = 0.25 + + b = 0.2 - 0.05 * sin(Omega * x[1]) + b_x = -0.05 * cos(Omega * x[1]) * Omega + + a = 1 + 0.1 * cos(Omega * x[1]) + a_x = -0.1 * sin(Omega * x[1]) * Omega + + du1 = a * H_t + v * (a_x * (H - b) + a * (H_x - b_x)) + du2 = v * du1 + a * (equations.gravity * (H - b) * H_x) + + return SVector(du1, du2, 0.0, 0.0) +end + +# Calculate 1D conservative flux for a single point +# Note, the bottom topography and channel width have no flux +@inline function flux(u, orientation::Integer, equations::ShallowWaterEquationsQuasi1D) + _, a_h_v, _, _ = u + v = velocity(u, equations) + + f1 = a_h_v + f2 = a_h_v * v + + return SVector(f1, f2, zero(eltype(u)), zero(eltype(u))) +end + +""" + 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`](@ref) +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](https://doi.org/10.48550/arXiv.2307.12089) +""" +@inline function flux_nonconservative_chan_etal(u_ll, u_rr, orientation::Integer, + equations::ShallowWaterEquationsQuasi1D) + a_h_ll, _, b_ll, a_ll = u_ll + a_h_rr, _, b_rr, a_rr = u_rr + + h_ll = waterheight(u_ll, equations) + h_rr = waterheight(u_rr, equations) + + z = zero(eltype(u_ll)) + + return SVector(z, equations.gravity * a_ll * h_ll * (h_rr + b_rr), z, z) +end + +""" + 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())`](@ref). + +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](https://doi.org/10.48550/arXiv.2307.12089) +""" +@inline function flux_chan_etal(u_ll, u_rr, orientation::Integer, + equations::ShallowWaterEquationsQuasi1D) + a_h_ll, a_h_v_ll, _, _ = u_ll + a_h_rr, a_h_v_rr, _, _ = u_rr + + v_ll = velocity(u_ll, equations) + v_rr = velocity(u_rr, equations) + + f1 = 0.5 * (a_h_v_ll + a_h_v_rr) + f2 = f1 * 0.5 * (v_ll + v_rr) + + return SVector(f1, f2, zero(eltype(u_ll)), zero(eltype(u_ll))) +end + +# Calculate maximum wave speed for local Lax-Friedrichs-type dissipation as the +# maximum velocity magnitude plus the maximum speed of sound +@inline function max_abs_speed_naive(u_ll, u_rr, orientation::Integer, + equations::ShallowWaterEquationsQuasi1D) + # Get the velocity quantities + v_ll = velocity(u_ll, equations) + v_rr = velocity(u_rr, equations) + + # Calculate the wave celerity on the left and right + h_ll = waterheight(u_ll, equations) + h_rr = waterheight(u_rr, equations) + c_ll = sqrt(equations.gravity * h_ll) + c_rr = sqrt(equations.gravity * h_rr) + + return max(abs(v_ll), abs(v_rr)) + max(c_ll, c_rr) +end + +# Specialized `DissipationLocalLaxFriedrichs` to avoid spurious dissipation in the bottom topography +# and channel width +@inline function (dissipation::DissipationLocalLaxFriedrichs)(u_ll, u_rr, + orientation_or_normal_direction, + equations::ShallowWaterEquationsQuasi1D) + λ = dissipation.max_abs_speed(u_ll, u_rr, orientation_or_normal_direction, + equations) + diss = -0.5 * λ * (u_rr - u_ll) + return SVector(diss[1], diss[2], zero(eltype(u_ll)), zero(eltype(u_ll))) +end + +@inline function max_abs_speeds(u, equations::ShallowWaterEquationsQuasi1D) + h = waterheight(u, equations) + v = velocity(u, equations) + + c = equations.gravity * sqrt(h) + return (abs(v) + c,) +end + +# Helper function to extract the velocity vector from the conservative variables +@inline function velocity(u, equations::ShallowWaterEquationsQuasi1D) + a_h, a_h_v, _, _ = u + + v = a_h_v / a_h + + return v +end + +# Convert conservative variables to primitive +@inline function cons2prim(u, equations::ShallowWaterEquationsQuasi1D) + a_h, _, b, a = u + h = a_h / a + H = h + b + v = velocity(u, equations) + return SVector(H, v, b, a) +end + +# Convert conservative variables to entropy variables +# Note, only the first two are the entropy variables, the third and fourth entries still +# just carry the bottom topography and channel width values for convenience +@inline function cons2entropy(u, equations::ShallowWaterEquationsQuasi1D) + a_h, a_h_v, b, a = u + h = waterheight(u, equations) + v = velocity(u, equations) + #entropy variables are the same as ones in standard shallow water equations + w1 = equations.gravity * (h + b) - 0.5 * v^2 + w2 = v + + return SVector(w1, w2, b, a) +end + +# Convert primitive to conservative variables +@inline function prim2cons(prim, equations::ShallowWaterEquationsQuasi1D) + H, v, b, a = prim + + a_h = a * (H - b) + a_h_v = a_h * v + return SVector(a_h, a_h_v, b, a) +end + +@inline function waterheight(u, equations::ShallowWaterEquationsQuasi1D) + return u[1] / u[4] +end + +# Entropy function for the shallow water equations is the total energy +@inline function entropy(cons, equations::ShallowWaterEquationsQuasi1D) + a = cons[4] + return a * energy_total(cons, equations) +end + +# Calculate total energy for a conservative state `cons` +@inline function energy_total(cons, equations::ShallowWaterEquationsQuasi1D) + a_h, a_h_v, b, a = cons + e = (a_h_v^2) / (2 * a * a_h) + 0.5 * equations.gravity * (a_h^2 / a) + + equations.gravity * a_h * b + return e +end + +# Calculate the error for the "lake-at-rest" test case where H = h+b should +# be a constant value over time. Note, assumes there is a single reference +# water height `H0` with which to compare. +# +# TODO: TrixiShallowWater: where should `threshold_limiter` live? May need +# to modify or have different versions of the `lake_at_rest_error` function +@inline function lake_at_rest_error(u, equations::ShallowWaterEquationsQuasi1D) + _, _, b, _ = u + h = waterheight(u, equations) + + # For well-balancedness testing with possible wet/dry regions the reference + # water height `H0` accounts for the possibility that the bottom topography + # can emerge out of the water as well as for the threshold offset to avoid + # division by a "hard" zero water heights as well. + H0_wet_dry = max(equations.H0, b + equations.threshold_limiter) + + return abs(H0_wet_dry - (h + b)) +end +end # @muladd diff --git a/src/equations/shallow_water_two_layer_1d.jl b/src/equations/shallow_water_two_layer_1d.jl index 4b64481cca3..42ff393593e 100644 --- a/src/equations/shallow_water_two_layer_1d.jl +++ b/src/equations/shallow_water_two_layer_1d.jl @@ -87,15 +87,15 @@ end have_nonconservative_terms(::ShallowWaterTwoLayerEquations1D) = True() function varnames(::typeof(cons2cons), ::ShallowWaterTwoLayerEquations1D) - ("h_upper", "h_v1_upper", - "h_lower", "h_v1_lower", "b") + ("h_upper", "h_v_upper", + "h_lower", "h_v_lower", "b") end # Note, we use the total water height, H_lower = h_upper + h_lower + b, and first layer total height # H_upper = h_upper + b as the first primitive variable for easier visualization and setting initial # conditions function varnames(::typeof(cons2prim), ::ShallowWaterTwoLayerEquations1D) - ("H_upper", "v1_upper", - "H_lower", "v1_lower", "b") + ("H_upper", "v_upper", + "H_lower", "v_lower", "b") end # Set initial conditions at physical location `x` for time `t` @@ -113,11 +113,11 @@ function initial_condition_convergence_test(x, t, H_lower = 2.0 + 0.1 * sin(ω * x[1] + t) H_upper = 4.0 + 0.1 * cos(ω * x[1] + t) - v1_lower = 1.0 - v1_upper = 0.9 + v_lower = 1.0 + v_upper = 0.9 b = 1.0 + 0.1 * cos(2.0 * ω * x[1]) - return prim2cons(SVector(H_upper, v1_upper, H_lower, v1_lower, b), equations) + return prim2cons(SVector(H_upper, v_upper, H_lower, v_lower, b), equations) end """ @@ -196,165 +196,77 @@ end # Note, the bottom topography has no flux @inline function flux(u, orientation::Integer, equations::ShallowWaterTwoLayerEquations1D) - h_upper, h_v1_upper, h_lower, h_v2_lower, _ = u + h_upper, h_v_upper, h_lower, h_v_lower, _ = u # Calculate velocities - v1_upper, v1_lower = velocity(u, equations) + v_upper, v_lower = velocity(u, equations) # Calculate pressure - p1 = 0.5 * equations.gravity * h_upper^2 - p2 = 0.5 * equations.gravity * h_lower^2 + p_upper = 0.5 * equations.gravity * h_upper^2 + p_lower = 0.5 * equations.gravity * h_lower^2 - f1 = h_v1_upper - f2 = h_v1_upper * v1_upper + p1 - f3 = h_v2_lower - f4 = h_v2_lower * v1_lower + p2 + f1 = h_v_upper + f2 = h_v_upper * v_upper + p_upper + f3 = h_v_lower + f4 = h_v_lower * v_lower + p_lower return SVector(f1, f2, f3, f4, zero(eltype(u))) end """ - flux_nonconservative_wintermeyer_etal(u_ll, u_rr, orientation::Integer, - equations::ShallowWaterTwoLayerEquations1D) + flux_nonconservative_ersing_etal(u_ll, u_rr, orientation::Integer, + equations::ShallowWaterTwoLayerEquations1D) !!! warning "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`](@ref) 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. +Non-symmetric path-conservative two-point volume flux discretizing the nonconservative (source) term +that contains the gradient of the bottom topography [`ShallowWaterTwoLayerEquations1D`](@ref) and an +additional term that couples the momentum of both layers. -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](https://doi.org/10.1016/j.jcp.2017.03.036) +This is a modified version of [`flux_nonconservative_wintermeyer_etal`](@ref) that gives entropy +conservation and well-balancedness in both the volume and surface when combined with +[`flux_wintermeyer_etal`](@ref). + +For further details see: +- Patrick Ersing, Andrew R. Winters (2023) + An entropy stable discontinuous Galerkin method for the two-layer shallow water equations on + curvilinear meshes + [DOI: 10.48550/arXiv.2306.12699](https://doi.org/10.48550/arXiv.2306.12699) """ -@inline function flux_nonconservative_wintermeyer_etal(u_ll, u_rr, - orientation::Integer, - equations::ShallowWaterTwoLayerEquations1D) +@inline function flux_nonconservative_ersing_etal(u_ll, u_rr, + orientation::Integer, + equations::ShallowWaterTwoLayerEquations1D) # Pull the necessary left and right state information h_upper_ll, h_lower_ll = waterheight(u_ll, equations) h_upper_rr, h_lower_rr = waterheight(u_rr, equations) b_rr = u_rr[5] + b_ll = u_ll[5] - z = zero(eltype(u_ll)) - - # Bottom gradient nonconservative term: (0, g*h_upper*(b+h_lower)_x, - # 0, g*h_lower*(b+r*h_upper)_x, 0) - f = SVector(z, - equations.gravity * h_upper_ll * (b_rr + h_lower_rr), - z, - equations.gravity * h_lower_ll * (b_rr + equations.r * h_upper_rr), - z) - return f -end - -""" - flux_nonconservative_fjordholm_etal(u_ll, u_rr, orientation::Integer, - equations::ShallowWaterTwoLayerEquations1D) - -!!! warning "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`](@ref). - -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](https://doi.org/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. -""" -@inline function flux_nonconservative_fjordholm_etal(u_ll, u_rr, - orientation::Integer, - equations::ShallowWaterTwoLayerEquations1D) - # Pull the necessary left and right state information - h_upper_ll, _, h_lower_ll, _, b_ll = u_ll - h_upper_rr, _, h_lower_rr, _, b_rr = u_rr - - # Create average and jump values - h_upper_average = 0.5 * (h_upper_ll + h_upper_rr) - h_lower_average = 0.5 * (h_lower_ll + h_lower_rr) - h_upper_jump = h_upper_rr - h_upper_ll - h_lower_jump = h_lower_rr - h_lower_ll - b_jump = b_rr - b_ll - - # Assign variables for constants for better readability - g = equations.gravity + # Calculate jumps + h_upper_jump = (h_upper_rr - h_upper_ll) + h_lower_jump = (h_lower_rr - h_lower_ll) + b_jump = (b_rr - b_ll) z = zero(eltype(u_ll)) # Bottom gradient nonconservative term: (0, g*h_upper*(b+h_lower)_x, # 0, g*h_lower*(b+r*h_upper)_x, 0) f = SVector(z, - g * h_upper_ll * (b_ll + h_lower_ll) + - g * h_upper_average * (b_jump + h_lower_jump), + equations.gravity * h_upper_ll * (b_jump + h_lower_jump), z, - g * h_lower_ll * (b_ll + equations.r * h_upper_ll) + - g * h_lower_average * (b_jump + - equations.r * h_upper_jump), + equations.gravity * h_lower_ll * (b_jump + equations.r * h_upper_jump), z) return f end -""" - 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`](@ref). - -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](https://doi.org/10.1016/j.jcp.2011.03.042) -and the application to two layers is shown in the paper: -- Ulrik Skre Fjordholm (2012) - Energy conservative and stable schemes for the two-layer shallow water equations. - [DOI: 10.1142/9789814417099_0039](https://doi.org/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. -""" -@inline function flux_fjordholm_etal(u_ll, u_rr, - orientation::Integer, - equations::ShallowWaterTwoLayerEquations1D) - # Unpack left and right state - h_upper_ll, h_lower_ll = waterheight(u_ll, equations) - v1_ll, v2_ll = velocity(u_ll, equations) - h_upper_rr, h_lower_rr = waterheight(u_rr, equations) - v1_rr, v2_rr = velocity(u_rr, equations) - - # Average each factor of products in flux - h_upper_avg = 0.5 * (h_upper_ll + h_upper_rr) - h_lower_avg = 0.5 * (h_lower_ll + h_lower_rr) - v1_avg = 0.5 * (v1_ll + v1_rr) - v2_avg = 0.5 * (v2_ll + v2_rr) - p1_avg = 0.25 * equations.gravity * (h_upper_ll^2 + h_upper_rr^2) - p2_avg = 0.25 * equations.gravity * (h_lower_ll^2 + h_lower_rr^2) - - # Calculate fluxes - f1 = h_upper_avg * v1_avg - f2 = f1 * v1_avg + p1_avg - f3 = h_lower_avg * v2_avg - f4 = f3 * v2_avg + p2_avg - - return SVector(f1, f2, f3, f4, zero(eltype(u_ll))) -end - """ 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`](@ref). To obtain the flux for the -two-layer shallow water equations the flux that is described in the paper for the normal shallow +When the bottom topography is nonzero this scheme will be well-balanced when used with the +nonconservative [`flux_nonconservative_ersing_etal`](@ref). 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: @@ -367,51 +279,48 @@ Further details are available in Theorem 1 of the paper: orientation::Integer, equations::ShallowWaterTwoLayerEquations1D) # Unpack left and right state - h_upper_ll, h_v1_upper_ll, h_lower_ll, h_v2_lower_ll, _ = u_ll - h_upper_rr, h_v1_upper_rr, h_lower_rr, h_v2_lower_rr, _ = u_rr + h_upper_ll, h_v_upper_ll, h_lower_ll, h_v_lower_ll, _ = u_ll + h_upper_rr, h_v_upper_rr, h_lower_rr, h_v_lower_rr, _ = u_rr # Get the velocities on either side - v1_ll, v2_ll = velocity(u_ll, equations) - v1_rr, v2_rr = velocity(u_rr, equations) + v_upper_ll, v_lower_ll = velocity(u_ll, equations) + v_upper_rr, v_lower_rr = velocity(u_rr, equations) # Average each factor of products in flux - v1_avg = 0.5 * (v1_ll + v1_rr) - v2_avg = 0.5 * (v2_ll + v2_rr) - p1_avg = 0.5 * equations.gravity * h_upper_ll * h_upper_rr - p2_avg = 0.5 * equations.gravity * h_lower_ll * h_lower_rr + v_upper_avg = 0.5 * (v_upper_ll + v_upper_rr) + v_lower_avg = 0.5 * (v_lower_ll + v_lower_rr) + p_upper_avg = 0.5 * equations.gravity * h_upper_ll * h_upper_rr + p_lower_avg = 0.5 * equations.gravity * h_lower_ll * h_lower_rr # Calculate fluxes - f1 = 0.5 * (h_v1_upper_ll + h_v1_upper_rr) - f2 = f1 * v1_avg + p1_avg - f3 = 0.5 * (h_v2_lower_ll + h_v2_lower_rr) - f4 = f3 * v2_avg + p2_avg + f1 = 0.5 * (h_v_upper_ll + h_v_upper_rr) + f2 = f1 * v_upper_avg + p_upper_avg + f3 = 0.5 * (h_v_lower_ll + h_v_lower_rr) + f4 = f3 * v_lower_avg + p_lower_avg return SVector(f1, f2, f3, f4, zero(eltype(u_ll))) end """ - 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`](@ref) 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](https://doi.org/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. + flux_es_ersing_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_wintermeyer_etal`](@ref) and adds a Lax-Friedrichs type dissipation dependent on the jump of +entropy variables. + +For further details see: +- Patrick Ersing, Andrew R. Winters (2023) + An entropy stable discontinuous Galerkin method for the two-layer shallow water equations on + curvilinear meshes + [DOI: 10.48550/arXiv.2306.12699](https://doi.org/10.48550/arXiv.2306.12699) """ -@inline function flux_es_fjordholm_etal(u_ll, u_rr, - orientation::Integer, - equations::ShallowWaterTwoLayerEquations1D) +@inline function flux_es_ersing_etal(u_ll, u_rr, + orientation::Integer, + equations::ShallowWaterTwoLayerEquations1D) # Compute entropy conservative flux but without the bottom topography - f_ec = flux_fjordholm_etal(u_ll, u_rr, - orientation, - equations) + f_ec = flux_wintermeyer_etal(u_ll, u_rr, + orientation, + equations) # Get maximum signal velocity λ = max_abs_speed_naive(u_ll, u_rr, orientation, equations) @@ -474,12 +383,12 @@ end orientation::Integer, equations::ShallowWaterTwoLayerEquations1D) # Unpack left and right state - h_upper_ll, h_v1_upper_ll, h_lower_ll, h_v2_lower_ll, _ = u_ll - h_upper_rr, h_v1_upper_rr, h_lower_rr, h_v2_lower_rr, _ = u_rr + h_upper_ll, h_v_upper_ll, h_lower_ll, h_v_lower_ll, _ = u_ll + h_upper_rr, h_v_upper_rr, h_lower_rr, h_v_lower_rr, _ = u_rr # Get the averaged velocity - v_m_ll = (h_v1_upper_ll + h_v2_lower_ll) / (h_upper_ll + h_lower_ll) - v_m_rr = (h_v1_upper_rr + h_v2_lower_rr) / (h_upper_rr + h_lower_rr) + v_m_ll = (h_v_upper_ll + h_v_lower_ll) / (h_upper_ll + h_lower_ll) + v_m_rr = (h_v_upper_rr + h_v_lower_rr) / (h_upper_rr + h_lower_rr) # Calculate the wave celerity on the left and right h_upper_ll, h_lower_ll = waterheight(u_ll, equations) @@ -503,10 +412,10 @@ end # Absolute speed of the barotropic mode @inline function max_abs_speeds(u, equations::ShallowWaterTwoLayerEquations1D) - h_upper, h_v1_upper, h_lower, h_v2_lower, _ = u + h_upper, h_v_upper, h_lower, h_v_lower, _ = u # Calculate averaged velocity of both layers - v_m = (h_v1_upper + h_v2_lower) / (h_upper + h_lower) + v_m = (h_v_upper + h_v_lower) / (h_upper + h_lower) c = sqrt(equations.gravity * (h_upper + h_lower)) return (abs(v_m) + c) @@ -514,11 +423,11 @@ end # Helper function to extract the velocity vector from the conservative variables @inline function velocity(u, equations::ShallowWaterTwoLayerEquations1D) - h_upper, h_v1_upper, h_lower, h_v2_lower, _ = u + h_upper, h_v_upper, h_lower, h_v_lower, _ = u - v1_upper = h_v1_upper / h_upper - v1_lower = h_v2_lower / h_lower - return SVector(v1_upper, v1_lower) + v_upper = h_v_upper / h_upper + v_lower = h_v_lower / h_lower + return SVector(v_upper, v_lower) end # Convert conservative variables to primitive @@ -527,8 +436,8 @@ end H_lower = h_lower + b H_upper = h_lower + h_upper + b - v1_upper, v1_lower = velocity(u, equations) - return SVector(H_upper, v1_upper, H_lower, v1_lower, b) + v_upper, v_lower = velocity(u, equations) + return SVector(H_upper, v_upper, H_lower, v_lower, b) end # Convert conservative variables to entropy variables @@ -536,26 +445,26 @@ end # bottom topography values for convenience @inline function cons2entropy(u, equations::ShallowWaterTwoLayerEquations1D) h_upper, _, h_lower, _, b = u - v1_upper, v1_lower = velocity(u, equations) - - w1 = equations.rho_upper * - (equations.gravity * (h_upper + h_lower + b) - 0.5 * v1_upper^2) - w2 = equations.rho_upper * v1_upper - w3 = equations.rho_lower * - (equations.gravity * (equations.r * h_upper + h_lower + b) - 0.5 * v1_lower^2) - w4 = equations.rho_lower * v1_lower + v_upper, v_lower = velocity(u, equations) + + w1 = (equations.rho_upper * + (equations.gravity * (h_upper + h_lower + b) - 0.5 * v_upper^2)) + w2 = equations.rho_upper * v_upper + w3 = (equations.rho_lower * + (equations.gravity * (equations.r * h_upper + h_lower + b) - 0.5 * v_lower^2)) + w4 = equations.rho_lower * v_lower return SVector(w1, w2, w3, w4, b) end # Convert primitive to conservative variables @inline function prim2cons(prim, equations::ShallowWaterTwoLayerEquations1D) - H_upper, v1_upper, H_lower, v1_lower, b = prim + H_upper, v_upper, H_lower, v_lower, b = prim h_lower = H_lower - b h_upper = H_upper - h_lower - b - h_v1_upper = h_upper * v1_upper - h_v2_lower = h_lower * v1_lower - return SVector(h_upper, h_v1_upper, h_lower, h_v2_lower, b) + h_v_upper = h_upper * v_upper + h_v_lower = h_lower * v_lower + return SVector(h_upper, h_v_upper, h_lower, h_v_lower, b) end @inline function waterheight(u, equations::ShallowWaterTwoLayerEquations1D) @@ -569,23 +478,23 @@ end # Calculate total energy for a conservative state `cons` @inline function energy_total(cons, equations::ShallowWaterTwoLayerEquations1D) - h_upper, h_v1_upper, h_lower, h_v2_lower, b = cons + h_upper, h_v_upper, h_lower, h_v_lower, b = cons # Set new variables for better readability g = equations.gravity rho_upper = equations.rho_upper rho_lower = equations.rho_lower - e = (0.5 * rho_upper * (h_v1_upper^2 / h_upper + g * h_upper^2) + - 0.5 * rho_lower * (h_v2_lower^2 / h_lower + g * h_lower^2) + + e = (0.5 * rho_upper * (h_v_upper^2 / h_upper + g * h_upper^2) + + 0.5 * rho_lower * (h_v_lower^2 / h_lower + g * h_lower^2) + g * rho_lower * h_lower * b + g * rho_upper * h_upper * (h_lower + b)) return e end # Calculate kinetic energy for a conservative state `cons` @inline function energy_kinetic(u, equations::ShallowWaterTwoLayerEquations1D) - h_upper, h_v1_upper, h_lower, h_v2_lower, _ = u - return 0.5 * equations.rho_upper * h_v1_upper^2 / h_upper + - 0.5 * equations.rho_lower * h_v2_lower^2 / h_lower + h_upper, h_v_upper, h_lower, h_v_lower, _ = u + return (0.5 * equations.rho_upper * h_v_upper^2 / h_upper + + 0.5 * equations.rho_lower * h_v_lower^2 / h_lower) end # Calculate potential energy for a conservative state `cons` diff --git a/src/equations/shallow_water_two_layer_2d.jl b/src/equations/shallow_water_two_layer_2d.jl index 87249e91948..a31d881f2ef 100644 --- a/src/equations/shallow_water_two_layer_2d.jl +++ b/src/equations/shallow_water_two_layer_2d.jl @@ -271,24 +271,24 @@ end v1_upper, v2_upper, v1_lower, v2_lower = velocity(u, equations) # Calculate pressure - p1 = 0.5 * equations.gravity * h_upper^2 - p2 = 0.5 * equations.gravity * h_lower^2 + p_upper = 0.5 * equations.gravity * h_upper^2 + p_lower = 0.5 * equations.gravity * h_lower^2 # Calculate fluxes depending on orientation if orientation == 1 f1 = h_v1_upper - f2 = h_v1_upper * v1_upper + p1 + f2 = h_v1_upper * v1_upper + p_upper f3 = h_v1_upper * v2_upper f4 = h_v1_lower - f5 = h_v1_lower * v1_lower + p2 + f5 = h_v1_lower * v1_lower + p_lower f6 = h_v1_lower * v2_lower else f1 = h_v2_upper f2 = h_v2_upper * v1_upper - f3 = h_v2_upper * v2_upper + p1 + f3 = h_v2_upper * v2_upper + p_upper f4 = h_v2_lower f5 = h_v2_lower * v1_lower - f6 = h_v2_lower * v2_lower + p2 + f6 = h_v2_lower * v2_lower + p_lower end return SVector(f1, f2, f3, f4, f5, f6, zero(eltype(u))) end @@ -305,44 +305,57 @@ end h_v_upper_normal = h_upper * v_normal_upper h_v_lower_normal = h_lower * v_normal_lower - p1 = 0.5 * equations.gravity * h_upper^2 - p2 = 0.5 * equations.gravity * h_lower^2 + p_upper = 0.5 * equations.gravity * h_upper^2 + p_lower = 0.5 * equations.gravity * h_lower^2 f1 = h_v_upper_normal - f2 = h_v_upper_normal * v1_upper + p1 * normal_direction[1] - f3 = h_v_upper_normal * v2_upper + p1 * normal_direction[2] + f2 = h_v_upper_normal * v1_upper + p_upper * normal_direction[1] + f3 = h_v_upper_normal * v2_upper + p_upper * normal_direction[2] f4 = h_v_lower_normal - f5 = h_v_lower_normal * v1_lower + p2 * normal_direction[1] - f6 = h_v_lower_normal * v2_lower + p2 * normal_direction[2] + f5 = h_v_lower_normal * v1_lower + p_lower * normal_direction[1] + f6 = h_v_lower_normal * v2_lower + p_lower * normal_direction[2] return SVector(f1, f2, f3, f4, f5, f6, zero(eltype(u))) end """ - flux_nonconservative_wintermeyer_etal(u_ll, u_rr, orientation::Integer, - equations::ShallowWaterTwoLayerEquations2D) + flux_nonconservative_ersing_etal(u_ll, u_rr, orientation::Integer, + equations::ShallowWaterTwoLayerEquations2D) + flux_nonconservative_ersing_etal(u_ll, u_rr, + normal_direction_ll::AbstractVector, + normal_direction_average::AbstractVector, + equations::ShallowWaterTwoLayerEquations2D) !!! warning "Experimental code" - This numerical flux is experimental and may change in any future release. + This numerical flux is experimental and may change in any future release. -Non-symmetric two-point volume flux discretizing the nonconservative (source) term +Non-symmetric path-conservative two-point volume flux discretizing the nonconservative (source) term that contains the gradient of the bottom topography [`ShallowWaterTwoLayerEquations2D`](@ref) 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. +additional term that couples the momentum of both layers. -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](https://doi.org/10.1016/j.jcp.2017.03.036) +This is a modified version of [`flux_nonconservative_wintermeyer_etal`](@ref) that gives entropy +conservation and well-balancedness in both the volume and surface when combined with +[`flux_wintermeyer_etal`](@ref). + +For further details see: +- Patrick Ersing, Andrew R. Winters (2023) + An entropy stable discontinuous Galerkin method for the two-layer shallow water equations on + curvilinear meshes + [DOI: 10.48550/arXiv.2306.12699](https://doi.org/10.48550/arXiv.2306.12699) """ -@inline function flux_nonconservative_wintermeyer_etal(u_ll, u_rr, - orientation::Integer, - equations::ShallowWaterTwoLayerEquations2D) +@inline function flux_nonconservative_ersing_etal(u_ll, u_rr, + orientation::Integer, + equations::ShallowWaterTwoLayerEquations2D) # Pull the necessary left and right state information h_upper_ll, h_lower_ll = waterheight(u_ll, equations) h_upper_rr, h_lower_rr = waterheight(u_rr, equations) b_rr = u_rr[7] + b_ll = u_ll[7] + + # Calculate jumps + h_upper_jump = (h_upper_rr - h_upper_ll) + h_lower_jump = (h_lower_rr - h_lower_ll) + b_jump = (b_rr - b_ll) z = zero(eltype(u_ll)) @@ -351,268 +364,64 @@ Further details are available in the paper: # g*h_lower*(b + r*h_upper)_y, 0) if orientation == 1 f = SVector(z, - equations.gravity * h_upper_ll * (b_rr + h_lower_rr), + equations.gravity * h_upper_ll * (b_jump + h_lower_jump), z, z, - equations.gravity * h_lower_ll * (b_rr + equations.r * h_upper_rr), + equations.gravity * h_lower_ll * + (b_jump + equations.r * h_upper_jump), z, z) else # orientation == 2 f = SVector(z, z, - equations.gravity * h_upper_ll * (b_rr + h_lower_rr), + equations.gravity * h_upper_ll * (b_jump + h_lower_jump), z, z, - equations.gravity * h_lower_ll * (b_rr + equations.r * h_upper_rr), + equations.gravity * h_lower_ll * + (b_jump + equations.r * h_upper_jump), z) end return f end -@inline function flux_nonconservative_wintermeyer_etal(u_ll, u_rr, - normal_direction_ll::AbstractVector, - normal_direction_average::AbstractVector, - equations::ShallowWaterTwoLayerEquations2D) +@inline function flux_nonconservative_ersing_etal(u_ll, u_rr, + normal_direction_ll::AbstractVector, + normal_direction_average::AbstractVector, + equations::ShallowWaterTwoLayerEquations2D) # Pull the necessary left and right state information h_upper_ll, h_lower_ll = waterheight(u_ll, equations) h_upper_rr, h_lower_rr = waterheight(u_rr, equations) b_rr = u_rr[7] + b_ll = u_ll[7] + + # Calculate jumps + h_upper_jump = (h_upper_rr - h_upper_ll) + h_lower_jump = (h_lower_rr - h_lower_ll) + b_jump = (b_rr - b_ll) # Note this routine only uses the `normal_direction_average` and the average of the # bottom topography to get a quadratic split form DG gradient on curved elements return SVector(zero(eltype(u_ll)), normal_direction_average[1] * equations.gravity * h_upper_ll * - (b_rr + h_lower_rr), + (b_jump + h_lower_jump), normal_direction_average[2] * equations.gravity * h_upper_ll * - (b_rr + h_lower_rr), + (b_jump + h_lower_jump), zero(eltype(u_ll)), normal_direction_average[1] * equations.gravity * h_lower_ll * - (b_rr + - equations.r * h_upper_rr), + (b_jump + equations.r * h_upper_jump), normal_direction_average[2] * equations.gravity * h_lower_ll * - (b_rr + - equations.r * h_upper_rr), + (b_jump + equations.r * h_upper_jump), zero(eltype(u_ll))) end -""" - flux_nonconservative_fjordholm_etal(u_ll, u_rr, orientation::Integer, - equations::ShallowWaterTwoLayerEquations2D) - -!!! warning "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`](@ref). - -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](https://doi.org/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. -""" -@inline function flux_nonconservative_fjordholm_etal(u_ll, u_rr, - orientation::Integer, - equations::ShallowWaterTwoLayerEquations2D) - # Pull the necessary left and right state information - h_upper_ll, h_v1_upper_ll, h_v2_upper_ll, h_lower_ll, h_v1_lower_ll, h_v2_lower_ll, b_ll = u_ll - h_upper_rr, h_v1_upper_rr, h_v2_upper_rr, h_lower_rr, h_v1_lower_rr, h_v2_lower_rr, b_rr = u_rr - - # Create average and jump values - h_upper_average = 0.5 * (h_upper_ll + h_upper_rr) - h_lower_average = 0.5 * (h_lower_ll + h_lower_rr) - h_upper_jump = h_upper_rr - h_upper_ll - h_lower_jump = h_lower_rr - h_lower_ll - b_jump = b_rr - b_ll - - # Assign variables for constants for better readability - g = equations.gravity - - # Bottom gradient nonconservative term: (0, g*h_upper*(b+h_lower)_x, g*h_upper*(b+h_lower)_y, 0, - # g*h_lower*(b+r*h_upper)_x, g*h_lower*(b+r*h_upper)_x, 0) - - # Includes two parts: - # (i) Diagonal (consistent) term from the volume flux that uses `b_ll` to avoid - # cross-averaging across a discontinuous bottom topography - # (ii) True surface part that uses `h_average` and `b_jump` to handle discontinuous bathymetry - z = zero(eltype(u_ll)) - if orientation == 1 - f = SVector(z, - g * h_upper_ll * (b_ll + h_lower_ll) + - g * h_upper_average * (b_jump + h_lower_jump), - z, z, - g * h_lower_ll * (b_ll + equations.r * h_upper_ll) + - g * h_lower_average * (b_jump + - equations.r * h_upper_jump), - z, z) - else # orientation == 2 - f = SVector(z, z, - g * h_upper_ll * (b_ll + h_lower_ll) + - g * h_upper_average * (b_jump + h_lower_jump), - z, z, - g * h_lower_ll * (b_ll + equations.r * h_upper_ll) + - g * h_lower_average * (b_jump + - equations.r * h_upper_jump), - z) - end - - return f -end - -@inline function flux_nonconservative_fjordholm_etal(u_ll, u_rr, - normal_direction_ll::AbstractVector, - normal_direction_average::AbstractVector, - equations::ShallowWaterTwoLayerEquations2D) - # Pull the necessary left and right state information - h_upper_ll, h_v1_upper_ll, h_v2_upper_ll, h_lower_ll, h_v1_lower_ll, h_v2_lower_ll, b_ll = u_ll - h_upper_rr, h_v1_upper_rr, h_v2_upper_rr, h_lower_rr, h_v1_lower_rr, h_v2_lower_rr, b_rr = u_rr - - # Create average and jump values - h_upper_average = 0.5 * (h_upper_ll + h_upper_rr) - h_lower_average = 0.5 * (h_lower_ll + h_lower_rr) - h_upper_jump = h_upper_rr - h_upper_ll - h_lower_jump = h_lower_rr - h_lower_ll - b_jump = b_rr - b_ll - - # Comes in two parts: - # (i) Diagonal (consistent) term from the volume flux that uses `normal_direction_average` - # but we use `b_ll` to avoid cross-averaging across a discontinuous bottom topography - f2 = normal_direction_average[1] * equations.gravity * h_upper_ll * - (b_ll + h_lower_ll) - f3 = normal_direction_average[2] * equations.gravity * h_upper_ll * - (b_ll + h_lower_ll) - f5 = normal_direction_average[1] * equations.gravity * h_lower_ll * - (b_ll + equations.r * h_upper_ll) - f6 = normal_direction_average[2] * equations.gravity * h_lower_ll * - (b_ll + equations.r * h_upper_ll) - # (ii) True surface part that uses `normal_direction_ll`, `h_average` and `b_jump` - # to handle discontinuous bathymetry - f2 += normal_direction_ll[1] * equations.gravity * h_upper_average * - (b_jump + h_lower_jump) - f3 += normal_direction_ll[2] * equations.gravity * h_upper_average * - (b_jump + h_lower_jump) - f5 += normal_direction_ll[1] * equations.gravity * h_lower_average * - (b_jump + - equations.r * h_upper_jump) - f6 += normal_direction_ll[2] * equations.gravity * h_lower_average * - (b_jump + - equations.r * h_upper_jump) - - # Continuity equations do not have a nonconservative flux - f1 = f4 = zero(eltype(u_ll)) - - return SVector(f1, f2, f3, f4, f5, f6, zero(eltype(u_ll))) -end - -""" - 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`](@ref). - -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](https://doi.org/10.1016/j.jcp.2011.03.042) -and the application to two layers is shown in the paper: -- Ulrik Skre Fjordholm (2012) - Energy conservative and stable schemes for the two-layer shallow water equations. - [DOI: 10.1142/9789814417099_0039](https://doi.org/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. -""" -@inline function flux_fjordholm_etal(u_ll, u_rr, - orientation::Integer, - equations::ShallowWaterTwoLayerEquations2D) - # Unpack left and right state - h_upper_ll, h_lower_ll = waterheight(u_ll, equations) - v1_upper_ll, v2_upper_ll, v1_lower_ll, v2_lower_ll = velocity(u_ll, equations) - h_upper_rr, h_lower_rr = waterheight(u_rr, equations) - v1_upper_rr, v2_upper_rr, v1_lower_rr, v2_lower_rr = velocity(u_rr, equations) - - # Average each factor of products in flux - h_upper_avg = 0.5 * (h_upper_ll + h_upper_rr) - h_lower_avg = 0.5 * (h_lower_ll + h_lower_rr) - v1_upper_avg = 0.5 * (v1_upper_ll + v1_upper_rr) - v1_lower_avg = 0.5 * (v1_lower_ll + v1_lower_rr) - v2_upper_avg = 0.5 * (v2_upper_ll + v2_upper_rr) - v2_lower_avg = 0.5 * (v2_lower_ll + v2_lower_rr) - p1_avg = 0.25 * equations.gravity * (h_upper_ll^2 + h_upper_rr^2) - p2_avg = 0.25 * equations.gravity * (h_lower_ll^2 + h_lower_rr^2) - - # Calculate fluxes depending on orientation - if orientation == 1 - f1 = h_upper_avg * v1_upper_avg - f2 = f1 * v1_upper_avg + p1_avg - f3 = f1 * v2_upper_avg - f4 = h_lower_avg * v1_lower_avg - f5 = f4 * v1_lower_avg + p2_avg - f6 = f4 * v2_lower_avg - else - f1 = h_upper_avg * v2_upper_avg - f2 = f1 * v1_upper_avg - f3 = f1 * v2_upper_avg + p1_avg - f4 = h_lower_avg * v2_lower_avg - f5 = f4 * v1_lower_avg - f6 = f4 * v2_lower_avg + p2_avg - end - - return SVector(f1, f2, f3, f4, f5, f6, zero(eltype(u_ll))) -end - -@inline function flux_fjordholm_etal(u_ll, u_rr, - normal_direction::AbstractVector, - equations::ShallowWaterTwoLayerEquations2D) - # Unpack left and right state - h_upper_ll, h_lower_ll = waterheight(u_ll, equations) - v1_upper_ll, v2_upper_ll, v1_lower_ll, v2_lower_ll = velocity(u_ll, equations) - h_upper_rr, h_lower_rr = waterheight(u_rr, equations) - v1_upper_rr, v2_upper_rr, v1_lower_rr, v2_lower_rr = velocity(u_rr, equations) - - # Compute velocity in normal direction - v_upper_dot_n_ll = v1_upper_ll * normal_direction[1] + - v2_upper_ll * normal_direction[2] - v_upper_dot_n_rr = v1_upper_rr * normal_direction[1] + - v2_upper_rr * normal_direction[2] - v_lower_dot_n_ll = v1_lower_ll * normal_direction[1] + - v2_lower_ll * normal_direction[2] - v_lower_dot_n_rr = v1_lower_rr * normal_direction[1] + - v2_lower_rr * normal_direction[2] - - # Average each factor of products in flux - h_upper_avg = 0.5 * (h_upper_ll + h_upper_rr) - h_lower_avg = 0.5 * (h_lower_ll + h_lower_rr) - v1_upper_avg = 0.5 * (v1_upper_ll + v1_upper_rr) - v1_lower_avg = 0.5 * (v1_lower_ll + v1_lower_rr) - v2_upper_avg = 0.5 * (v2_upper_ll + v2_upper_rr) - v2_lower_avg = 0.5 * (v2_lower_ll + v2_lower_rr) - p1_avg = 0.25 * equations.gravity * (h_upper_ll^2 + h_upper_rr^2) - p2_avg = 0.25 * equations.gravity * (h_lower_ll^2 + h_lower_rr^2) - v_upper_dot_n_avg = 0.5 * (v_upper_dot_n_ll + v_upper_dot_n_rr) - v_lower_dot_n_avg = 0.5 * (v_lower_dot_n_ll + v_lower_dot_n_rr) - - # Calculate fluxes depending on normal_direction - f1 = h_upper_avg * v_upper_dot_n_avg - f2 = f1 * v1_upper_avg + p1_avg * normal_direction[1] - f3 = f1 * v2_upper_avg + p1_avg * normal_direction[2] - f4 = h_lower_avg * v_lower_dot_n_avg - f5 = f4 * v1_lower_avg + p2_avg * normal_direction[1] - f6 = f4 * v2_lower_avg + p2_avg * normal_direction[2] - - return SVector(f1, f2, f3, f4, f5, f6, zero(eltype(u_ll))) -end - """ flux_wintermeyer_etal(u_ll, u_rr, orientation, equations::ShallowWaterTwoLayerEquations2D) + flux_wintermeyer_etal(u_ll, u_rr, + normal_direction::AbstractVector, + 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`](@ref). To obtain the flux for the -two-layer shallow water equations the flux that is described in the paper for the normal shallow +When the bottom topography is nonzero this scheme will be well-balanced when used with the +nonconservative [`flux_nonconservative_ersing_etal`](@ref). 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: @@ -637,24 +446,24 @@ Further details are available in Theorem 1 of the paper: v1_lower_avg = 0.5 * (v1_lower_ll + v1_lower_rr) v2_upper_avg = 0.5 * (v2_upper_ll + v2_upper_rr) v2_lower_avg = 0.5 * (v2_lower_ll + v2_lower_rr) - p1_avg = 0.5 * equations.gravity * h_upper_ll * h_upper_rr - p2_avg = 0.5 * equations.gravity * h_lower_ll * h_lower_rr + p_upper_avg = 0.5 * equations.gravity * h_upper_ll * h_upper_rr + p_lower_avg = 0.5 * equations.gravity * h_lower_ll * h_lower_rr # Calculate fluxes depending on orientation if orientation == 1 f1 = 0.5 * (h_v1_upper_ll + h_v1_upper_rr) - f2 = f1 * v1_upper_avg + p1_avg + f2 = f1 * v1_upper_avg + p_upper_avg f3 = f1 * v2_upper_avg f4 = 0.5 * (h_v1_lower_ll + h_v1_lower_rr) - f5 = f4 * v1_lower_avg + p2_avg + f5 = f4 * v1_lower_avg + p_lower_avg f6 = f4 * v2_lower_avg else f1 = 0.5 * (h_v2_upper_ll + h_v2_upper_rr) f2 = f1 * v1_upper_avg - f3 = f1 * v2_upper_avg + p1_avg + f3 = f1 * v2_upper_avg + p_upper_avg f4 = 0.5 * (h_v2_lower_ll + h_v2_lower_rr) f5 = f4 * v1_lower_avg - f6 = f4 * v2_lower_avg + p2_avg + f6 = f4 * v2_lower_avg + p_lower_avg end return SVector(f1, f2, f3, f4, f5, f6, zero(eltype(u_ll))) @@ -676,8 +485,8 @@ end v1_lower_avg = 0.5 * (v1_lower_ll + v1_lower_rr) v2_upper_avg = 0.5 * (v2_upper_ll + v2_upper_rr) v2_lower_avg = 0.5 * (v2_lower_ll + v2_lower_rr) - p1_avg = 0.5 * equations.gravity * h_upper_ll * h_upper_rr - p2_avg = 0.5 * equations.gravity * h_lower_ll * h_lower_rr + p_upper_avg = 0.5 * equations.gravity * h_upper_ll * h_upper_rr + p_lower_avg = 0.5 * equations.gravity * h_lower_ll * h_lower_rr h_v1_upper_avg = 0.5 * (h_v1_upper_ll + h_v1_upper_rr) h_v2_upper_avg = 0.5 * (h_v2_upper_ll + h_v2_upper_rr) h_v1_lower_avg = 0.5 * (h_v1_lower_ll + h_v1_lower_rr) @@ -685,38 +494,36 @@ end # Calculate fluxes depending on normal_direction f1 = h_v1_upper_avg * normal_direction[1] + h_v2_upper_avg * normal_direction[2] - f2 = f1 * v1_upper_avg + p1_avg * normal_direction[1] - f3 = f1 * v2_upper_avg + p1_avg * normal_direction[2] + f2 = f1 * v1_upper_avg + p_upper_avg * normal_direction[1] + f3 = f1 * v2_upper_avg + p_upper_avg * normal_direction[2] f4 = h_v1_lower_avg * normal_direction[1] + h_v2_lower_avg * normal_direction[2] - f5 = f4 * v1_lower_avg + p2_avg * normal_direction[1] - f6 = f4 * v2_lower_avg + p2_avg * normal_direction[2] + f5 = f4 * v1_lower_avg + p_lower_avg * normal_direction[1] + f6 = f4 * v2_lower_avg + p_lower_avg * normal_direction[2] return SVector(f1, f2, f3, f4, f5, f6, zero(eltype(u_ll))) end """ - 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`](@ref) 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](https://doi.org/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. + flux_es_ersing_etal(u_ll, u_rr, orientation_or_normal_direction, + equations::ShallowWaterTwoLayerEquations2D) + +Entropy stable surface flux for the two-layer shallow water equations. Uses the entropy conservative +[`flux_wintermeyer_etal`](@ref) and adds a Lax-Friedrichs type dissipation dependent on the jump of +entropy variables. + +For further details see: +- Patrick Ersing, Andrew R. Winters (2023) + An entropy stable discontinuous Galerkin method for the two-layer shallow water equations on + curvilinear meshes + [DOI: 10.48550/arXiv.2306.12699](https://doi.org/10.48550/arXiv.2306.12699) """ -@inline function flux_es_fjordholm_etal(u_ll, u_rr, - orientation_or_normal_direction, - equations::ShallowWaterTwoLayerEquations2D) +@inline function flux_es_ersing_etal(u_ll, u_rr, + orientation_or_normal_direction, + equations::ShallowWaterTwoLayerEquations2D) # Compute entropy conservative flux but without the bottom topography - f_ec = flux_fjordholm_etal(u_ll, u_rr, - orientation_or_normal_direction, - equations) + f_ec = flux_wintermeyer_etal(u_ll, u_rr, + orientation_or_normal_direction, + equations) # Get maximum signal velocity λ = max_abs_speed_naive(u_ll, u_rr, orientation_or_normal_direction, equations) @@ -926,12 +733,12 @@ end rho_lower = equations.rho_lower v1_upper, v2_upper, v1_lower, v2_lower = velocity(u, equations) - w1 = rho_upper * (equations.gravity * (h_upper + h_lower + b) + - -0.5 * (v1_upper^2 + v2_upper^2)) + w1 = (rho_upper * (equations.gravity * (h_upper + h_lower + b) + + -0.5 * (v1_upper^2 + v2_upper^2))) w2 = rho_upper * v1_upper w3 = rho_upper * v2_upper - w4 = rho_lower * (equations.gravity * (equations.r * h_upper + h_lower + b) + - -0.5 * (v1_lower^2 + v2_lower^2)) + w4 = (rho_lower * (equations.gravity * (equations.r * h_upper + h_lower + b) + + -0.5 * (v1_lower^2 + v2_lower^2))) w5 = rho_lower * v1_lower w6 = rho_lower * v2_lower return SVector(w1, w2, w3, w4, w5, w6, b) diff --git a/src/meshes/mesh_io.jl b/src/meshes/mesh_io.jl index b9895e7d454..337e33e6969 100644 --- a/src/meshes/mesh_io.jl +++ b/src/meshes/mesh_io.jl @@ -30,6 +30,7 @@ function save_mesh_file(mesh::TreeMesh, output_directory, timestep, attributes(file)["mesh_type"] = get_name(mesh) attributes(file)["ndims"] = ndims(mesh) attributes(file)["n_cells"] = n_cells + attributes(file)["capacity"] = mesh.tree.capacity attributes(file)["n_leaf_cells"] = count_leaf_cells(mesh.tree) attributes(file)["minimum_level"] = minimum_level(mesh.tree) attributes(file)["maximum_level"] = maximum_level(mesh.tree) @@ -249,10 +250,10 @@ function load_mesh_serial(mesh_file::AbstractString; n_cells_max, RealT) end if mesh_type == "TreeMesh" - n_cells = h5open(mesh_file, "r") do file - return read(attributes(file)["n_cells"]) + capacity = h5open(mesh_file, "r") do file + return read(attributes(file)["capacity"]) end - mesh = TreeMesh(SerialTree{ndims}, max(n_cells, n_cells_max)) + mesh = TreeMesh(SerialTree{ndims}, max(n_cells_max, capacity)) load_mesh!(mesh, mesh_file) elseif mesh_type == "StructuredMesh" size_, mapping_as_string = h5open(mesh_file, "r") do file @@ -263,32 +264,27 @@ function load_mesh_serial(mesh_file::AbstractString; n_cells_max, RealT) size = Tuple(size_) # TODO: `@eval` is evil - # A temporary workaround to evaluate the code that defines the domain mapping in a local scope. - # This prevents errors when multiple restart elixirs are executed in one session, where one - # defines `mapping` as a variable, while the other defines it as a function. # # This should be replaced with something more robust and secure, # see https://github.com/trixi-framework/Trixi.jl/issues/541). - expr = Meta.parse(mapping_as_string) - if expr.head == :toplevel - expr.head = :block - end - if ndims == 1 - mapping = @eval function (xi) - $expr + mapping = eval(Meta.parse("""function (xi) + $mapping_as_string mapping(xi) end + """)) elseif ndims == 2 - mapping = @eval function (xi, eta) - $expr + mapping = eval(Meta.parse("""function (xi, eta) + $mapping_as_string mapping(xi, eta) end + """)) else # ndims == 3 - mapping = @eval function (xi, eta, zeta) - $expr + mapping = eval(Meta.parse("""function (xi, eta, zeta) + $mapping_as_string mapping(xi, eta, zeta) end + """)) end mesh = StructuredMesh(size, mapping; RealT = RealT, unsaved_changes = false, diff --git a/src/meshes/structured_mesh.jl b/src/meshes/structured_mesh.jl index df067db833d..553aabbbc20 100644 --- a/src/meshes/structured_mesh.jl +++ b/src/meshes/structured_mesh.jl @@ -96,13 +96,17 @@ function StructuredMesh(cells_per_dimension, faces::Tuple; RealT = Float64, # Collect definitions of face functions in one string (separated by semicolons) face2substring(face) = code_string(face, ntuple(_ -> Float64, NDIMS - 1)) - join_semicolon(strings) = join(strings, "; ") + join_newline(strings) = join(strings, "\n") - faces_definition = faces .|> face2substring .|> string |> join_semicolon + faces_definition = faces .|> face2substring .|> string |> join_newline # Include faces definition in `mapping_as_string` to allow for evaluation # without knowing the face functions - mapping_as_string = "$faces_definition; faces = $(string(faces)); mapping = transfinite_mapping(faces)" + mapping_as_string = """ + $faces_definition + faces = $(string(faces)) + mapping = transfinite_mapping(faces) + """ return StructuredMesh(cells_per_dimension, mapping; RealT = RealT, periodicity = periodicity, @@ -123,13 +127,14 @@ Create a StructuredMesh that represents a uncurved structured mesh with a rectan """ function StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max; periodicity = true) - NDIMS = length(cells_per_dimension) RealT = promote_type(eltype(coordinates_min), eltype(coordinates_max)) mapping = coordinates2mapping(coordinates_min, coordinates_max) - mapping_as_string = "coordinates_min = $coordinates_min; " * - "coordinates_max = $coordinates_max; " * - "mapping = coordinates2mapping(coordinates_min, coordinates_max)" + mapping_as_string = """ + coordinates_min = $coordinates_min + coordinates_max = $coordinates_max + mapping = coordinates2mapping(coordinates_min, coordinates_max) + """ return StructuredMesh(cells_per_dimension, mapping; RealT = RealT, periodicity = periodicity, mapping_as_string = mapping_as_string) diff --git a/src/meshes/tree_mesh.jl b/src/meshes/tree_mesh.jl index 93ba982bce9..05699d17d16 100644 --- a/src/meshes/tree_mesh.jl +++ b/src/meshes/tree_mesh.jl @@ -199,6 +199,7 @@ function Base.show(io::IO, ::MIME"text/plain", "length" => mesh.tree.length_level_0, "periodicity" => mesh.tree.periodicity, "current #cells" => mesh.tree.length, + "#leaf-cells" => count_leaf_cells(mesh.tree), "maximum #cells" => mesh.tree.capacity, ] summary_box(io, "TreeMesh{" * string(NDIMS) * ", " * string(TreeType) * "}", diff --git a/src/meshes/unstructured_mesh.jl b/src/meshes/unstructured_mesh.jl index c370c0f25f8..fae52f834b3 100644 --- a/src/meshes/unstructured_mesh.jl +++ b/src/meshes/unstructured_mesh.jl @@ -15,8 +15,9 @@ An unstructured (possibly curved) quadrilateral mesh. All mesh information, neighbour coupling, and boundary curve information is read in from a mesh file `filename`. """ -mutable struct UnstructuredMesh2D{RealT <: Real, CurvedSurfaceT <: CurvedSurface{RealT} - } <: AbstractMesh{2} +mutable struct UnstructuredMesh2D{RealT <: Real, + CurvedSurfaceT <: CurvedSurface{RealT}} <: + AbstractMesh{2} filename :: String n_corners :: Int n_surfaces :: Int # total number of surfaces diff --git a/src/semidiscretization/semidiscretization.jl b/src/semidiscretization/semidiscretization.jl index c784f716426..fe7858e31ee 100644 --- a/src/semidiscretization/semidiscretization.jl +++ b/src/semidiscretization/semidiscretization.jl @@ -335,6 +335,10 @@ function get_element_variables!(element_variables, u_ode, get_element_variables!(element_variables, u, mesh_equations_solver_cache(semi)...) end +function get_node_variables!(node_variables, semi::AbstractSemidiscretization) + get_node_variables!(node_variables, mesh_equations_solver_cache(semi)...) +end + # To implement AMR and use OrdinaryDiffEq.jl etc., we have to be a bit creative. # Since the caches of the SciML ecosystem are immutable structs, we cannot simply # change the underlying arrays therein. Hence, to support changing the number of diff --git a/src/semidiscretization/semidiscretization_coupled.jl b/src/semidiscretization/semidiscretization_coupled.jl index b7adff78425..0941ae6a8ca 100644 --- a/src/semidiscretization/semidiscretization_coupled.jl +++ b/src/semidiscretization/semidiscretization_coupled.jl @@ -41,8 +41,9 @@ function SemidiscretizationCoupled(semis...) performance_counter = PerformanceCounter() - SemidiscretizationCoupled{typeof(semis), typeof(u_indices), typeof(performance_counter) - }(semis, u_indices, performance_counter) + SemidiscretizationCoupled{typeof(semis), typeof(u_indices), + typeof(performance_counter)}(semis, u_indices, + performance_counter) end function Base.show(io::IO, semi::SemidiscretizationCoupled) @@ -71,7 +72,7 @@ function Base.show(io::IO, ::MIME"text/plain", semi::SemidiscretizationCoupled) summary_line(increment_indent(io), "source terms", semi.semis[i].source_terms) summary_line(increment_indent(io), "solver", solver |> typeof |> nameof) end - summary_line(io, "total #DOFs", ndofs(semi)) + summary_line(io, "total #DOFs per field", ndofs(semi)) summary_footer(io) end end @@ -432,8 +433,7 @@ function allocate_coupled_boundary_condition(boundary_condition, direction, mesh end # In 2D -function allocate_coupled_boundary_condition(boundary_condition::BoundaryConditionCoupled{2 - }, +function allocate_coupled_boundary_condition(boundary_condition::BoundaryConditionCoupled{2}, direction, mesh, equations, dg::DGSEM) if direction in (1, 2) cell_size = size(mesh, 2) diff --git a/src/semidiscretization/semidiscretization_euler_acoustics.jl b/src/semidiscretization/semidiscretization_euler_acoustics.jl index 7608998c557..173523ff892 100644 --- a/src/semidiscretization/semidiscretization_euler_acoustics.jl +++ b/src/semidiscretization/semidiscretization_euler_acoustics.jl @@ -51,11 +51,11 @@ function SemidiscretizationEulerAcoustics(semi_acoustics::SemiAcoustics, semi_euler::SemiEuler; source_region = x -> true, weights = x -> 1.0) where - {Mesh, - SemiAcoustics <: - SemidiscretizationHyperbolic{Mesh, <:AbstractAcousticPerturbationEquations}, - SemiEuler <: - SemidiscretizationHyperbolic{Mesh, <:AbstractCompressibleEulerEquations}} + {Mesh, + SemiAcoustics <: + SemidiscretizationHyperbolic{Mesh, <:AbstractAcousticPerturbationEquations}, + SemiEuler <: + SemidiscretizationHyperbolic{Mesh, <:AbstractCompressibleEulerEquations}} cache = create_cache(SemidiscretizationEulerAcoustics, source_region, weights, mesh_equations_solver_cache(semi_acoustics)...) diff --git a/src/semidiscretization/semidiscretization_euler_gravity.jl b/src/semidiscretization/semidiscretization_euler_gravity.jl index 8fe9de1d2b2..4201344df80 100644 --- a/src/semidiscretization/semidiscretization_euler_gravity.jl +++ b/src/semidiscretization/semidiscretization_euler_gravity.jl @@ -117,11 +117,11 @@ Construct a semidiscretization of the compressible Euler equations with self-gra function SemidiscretizationEulerGravity(semi_euler::SemiEuler, semi_gravity::SemiGravity, parameters) where - {Mesh, - SemiEuler <: - SemidiscretizationHyperbolic{Mesh, <:AbstractCompressibleEulerEquations}, - SemiGravity <: - SemidiscretizationHyperbolic{Mesh, <:AbstractHyperbolicDiffusionEquations}} + {Mesh, + SemiEuler <: + SemidiscretizationHyperbolic{Mesh, <:AbstractCompressibleEulerEquations}, + SemiGravity <: + SemidiscretizationHyperbolic{Mesh, <:AbstractHyperbolicDiffusionEquations}} u_ode = compute_coefficients(zero(real(semi_gravity)), semi_gravity) du_ode = similar(u_ode) u_tmp1_ode = similar(u_ode) diff --git a/src/semidiscretization/semidiscretization_hyperbolic.jl b/src/semidiscretization/semidiscretization_hyperbolic.jl index 50b2c21c14e..7ebd758de37 100644 --- a/src/semidiscretization/semidiscretization_hyperbolic.jl +++ b/src/semidiscretization/semidiscretization_hyperbolic.jl @@ -29,17 +29,18 @@ struct SemidiscretizationHyperbolic{Mesh, Equations, InitialCondition, performance_counter::PerformanceCounter function SemidiscretizationHyperbolic{Mesh, Equations, InitialCondition, - BoundaryConditions, SourceTerms, Solver, Cache - }(mesh::Mesh, equations::Equations, - initial_condition::InitialCondition, - boundary_conditions::BoundaryConditions, - source_terms::SourceTerms, - solver::Solver, - cache::Cache) where {Mesh, Equations, - InitialCondition, - BoundaryConditions, - SourceTerms, Solver, - Cache} + BoundaryConditions, SourceTerms, Solver, + Cache}(mesh::Mesh, equations::Equations, + initial_condition::InitialCondition, + boundary_conditions::BoundaryConditions, + source_terms::SourceTerms, + solver::Solver, + cache::Cache) where {Mesh, Equations, + InitialCondition, + BoundaryConditions, + SourceTerms, + Solver, + Cache} @assert ndims(mesh) == ndims(equations) performance_counter = PerformanceCounter() @@ -243,7 +244,7 @@ function Base.show(io::IO, ::MIME"text/plain", semi::SemidiscretizationHyperboli summary_line(io, "source terms", semi.source_terms) summary_line(io, "solver", semi.solver |> typeof |> nameof) - summary_line(io, "total #DOFs", ndofs(semi)) + summary_line(io, "total #DOFs per field", ndofs(semi)) summary_footer(io) end end @@ -268,8 +269,7 @@ end function print_boundary_conditions(io, semi::SemiHypMeshBCSolver{<:Any, - <:UnstructuredSortedBoundaryTypes - }) + <:UnstructuredSortedBoundaryTypes}) @unpack boundary_conditions = semi @unpack boundary_dictionary = boundary_conditions summary_line(io, "boundary conditions", length(boundary_dictionary)) @@ -289,8 +289,7 @@ function print_boundary_conditions(io, semi::SemiHypMeshBCSolver{<:Any, <:NamedT end function print_boundary_conditions(io, - semi::SemiHypMeshBCSolver{ - <:Union{TreeMesh, + semi::SemiHypMeshBCSolver{<:Union{TreeMesh, StructuredMesh}, <:Union{Tuple, NamedTuple, AbstractArray}}) diff --git a/src/semidiscretization/semidiscretization_hyperbolic_parabolic.jl b/src/semidiscretization/semidiscretization_hyperbolic_parabolic.jl index b12ecadb58b..0f44941390a 100644 --- a/src/semidiscretization/semidiscretization_hyperbolic_parabolic.jl +++ b/src/semidiscretization/semidiscretization_hyperbolic_parabolic.jl @@ -45,30 +45,29 @@ struct SemidiscretizationHyperbolicParabolic{Mesh, Equations, EquationsParabolic BoundaryConditionsParabolic, SourceTerms, Solver, SolverParabolic, Cache, - CacheParabolic - }(mesh::Mesh, - equations::Equations, - equations_parabolic::EquationsParabolic, - initial_condition::InitialCondition, - boundary_conditions::BoundaryConditions, - boundary_conditions_parabolic::BoundaryConditionsParabolic, - source_terms::SourceTerms, - solver::Solver, - solver_parabolic::SolverParabolic, - cache::Cache, - cache_parabolic::CacheParabolic) where { - Mesh, - Equations, - EquationsParabolic, - InitialCondition, - BoundaryConditions, - BoundaryConditionsParabolic, - SourceTerms, - Solver, - SolverParabolic, - Cache, - CacheParabolic - } + CacheParabolic}(mesh::Mesh, + equations::Equations, + equations_parabolic::EquationsParabolic, + initial_condition::InitialCondition, + boundary_conditions::BoundaryConditions, + boundary_conditions_parabolic::BoundaryConditionsParabolic, + source_terms::SourceTerms, + solver::Solver, + solver_parabolic::SolverParabolic, + cache::Cache, + cache_parabolic::CacheParabolic) where { + Mesh, + Equations, + EquationsParabolic, + InitialCondition, + BoundaryConditions, + BoundaryConditionsParabolic, + SourceTerms, + Solver, + SolverParabolic, + Cache, + CacheParabolic + } @assert ndims(mesh) == ndims(equations) # Todo: assert nvariables(equations)==nvariables(equations_parabolic) @@ -228,7 +227,7 @@ function Base.show(io::IO, ::MIME"text/plain", summary_line(io, "source terms", semi.source_terms) summary_line(io, "solver", semi.solver |> typeof |> nameof) summary_line(io, "parabolic solver", semi.solver_parabolic |> typeof |> nameof) - summary_line(io, "total #DOFs", ndofs(semi)) + summary_line(io, "total #DOFs per field", ndofs(semi)) summary_footer(io) end end diff --git a/src/solvers/dg.jl b/src/solvers/dg.jl index 36bbc6de361..9b61df62cc3 100644 --- a/src/solvers/dg.jl +++ b/src/solvers/dg.jl @@ -12,6 +12,11 @@ function get_element_variables!(element_variables, u, mesh, equations, nothing end +function get_node_variables!(node_variables, mesh, equations, + volume_integral::AbstractVolumeIntegral, dg, cache) + nothing +end + """ VolumeIntegralStrongForm() @@ -35,6 +40,11 @@ standard textbooks. Nodal Discontinuous Galerkin Methods: Algorithms, Analysis, and Applications [doi: 10.1007/978-0-387-72067-8](https://doi.org/10.1007/978-0-387-72067-8) + +`VolumeIntegralWeakForm()` is only implemented for conserved terms as +non-conservative terms should always be discretized in conjunction with a flux-splitting scheme, +see [`VolumeIntegralFluxDifferencing`](@ref). +This treatment is required to achieve, e.g., entropy-stability or well-balancedness. """ struct VolumeIntegralWeakForm <: AbstractVolumeIntegral end @@ -181,6 +191,12 @@ end A subcell limiting volume integral type for DG methods based on subcell blending approaches with a low-order FV method. Used with limiter [`SubcellLimiterIDP`](@ref). +!!! note + Subcell limiting methods are not fully functional on non-conforming meshes. This is + mainly because the implementation assumes that low- and high-order schemes have the same + surface terms, which is not guaranteed for non-conforming meshes. The low-order scheme + with a high-order mortar is not invariant domain preserving. + !!! warning "Experimental implementation" This is an experimental feature and may change in future releases. """ @@ -214,6 +230,18 @@ function Base.show(io::IO, mime::MIME"text/plain", end end +function get_node_variables!(node_variables, mesh, equations, + volume_integral::VolumeIntegralSubcellLimiting, dg, cache) + # While for the element-wise limiting with `VolumeIntegralShockCapturingHG` the indicator is + # called here to get up-to-date values for IO, this is not easily possible in this case + # because the calculation is very integrated into the method. + # See also https://github.com/trixi-framework/Trixi.jl/pull/1611#discussion_r1334553206. + # Therefore, the coefficients at `t=t^{n-1}` are saved. Thus, the coefficients of the first + # stored solution (initial condition) are not yet defined and were manually set to `NaN`. + get_node_variables!(node_variables, volume_integral.limiter, volume_integral, + equations) +end + # TODO: FD. Should this definition live in a different file because it is # not strictly a DG method? """ @@ -387,7 +415,8 @@ function Base.show(io::IO, mime::MIME"text/plain", dg::DG) summary_line(io, "surface integral", dg.surface_integral |> typeof |> nameof) show(increment_indent(io), mime, dg.surface_integral) summary_line(io, "volume integral", dg.volume_integral |> typeof |> nameof) - if !(dg.volume_integral isa VolumeIntegralWeakForm) + if !(dg.volume_integral isa VolumeIntegralWeakForm) && + !(dg.volume_integral isa VolumeIntegralStrongForm) show(increment_indent(io), mime, dg.volume_integral) end summary_footer(io) @@ -403,6 +432,10 @@ function get_element_variables!(element_variables, u, mesh, equations, dg::DG, c dg, cache) end +function get_node_variables!(node_variables, mesh, equations, dg::DG, cache) + get_node_variables!(node_variables, mesh, equations, dg.volume_integral, dg, cache) +end + const MeshesDGSEM = Union{TreeMesh, StructuredMesh, UnstructuredMesh2D, P4estMesh, T8codeMesh} @@ -566,6 +599,7 @@ include("dgsem/dgsem.jl") # and boundary conditions weakly. Thus, these methods can re-use a lot of # functionality implemented for DGSEM. include("fdsbp_tree/fdsbp.jl") +include("fdsbp_unstructured/fdsbp.jl") function allocate_coefficients(mesh::AbstractMesh, equations, dg::DG, cache) # We must allocate a `Vector` in order to be able to `resize!` it (AMR). diff --git a/src/solvers/dgmulti/dg.jl b/src/solvers/dgmulti/dg.jl index bc76aa1a9d2..695260f4b9b 100644 --- a/src/solvers/dgmulti/dg.jl +++ b/src/solvers/dgmulti/dg.jl @@ -302,7 +302,12 @@ function calc_volume_integral!(du, u, mesh::DGMultiMesh, @threaded for e in eachelement(mesh, dg, cache) flux_values = local_values_threaded[Threads.threadid()] for i in eachdim(mesh) - flux_values .= flux.(view(u_values, :, e), i, equations) + # Here, the broadcasting operation does allocate + #flux_values .= flux.(view(u_values, :, e), i, equations) + # Use loop instead + for j in eachindex(flux_values) + flux_values[j] = flux(u_values[j, e], i, equations) + end for j in eachdim(mesh) apply_to_each_field(mul_by_accum!(weak_differentiation_matrices[j], dxidxhatj[i, j][1, e]), @@ -327,6 +332,7 @@ function calc_volume_integral!(du, u, mesh::DGMultiMesh{NDIMS, <:NonAffine}, @threaded for e in eachelement(mesh, dg, cache) flux_values = cache.flux_threaded[Threads.threadid()] for i in eachdim(mesh) + # Here, the broadcasting operation does not allocate flux_values[i] .= flux.(view(u_values, :, e), i, equations) end @@ -459,24 +465,13 @@ function calc_boundary_flux!(cache, t, boundary_conditions::BoundaryConditionPer nothing end -# "lispy tuple programming" instead of for loop for type stability function calc_boundary_flux!(cache, t, boundary_conditions, mesh, have_nonconservative_terms, equations, dg::DGMulti) - - # peel off first boundary condition - calc_single_boundary_flux!(cache, t, first(boundary_conditions), - first(keys(boundary_conditions)), - mesh, have_nonconservative_terms, equations, dg) - - # recurse on the remainder of the boundary conditions - calc_boundary_flux!(cache, t, Base.tail(boundary_conditions), - mesh, have_nonconservative_terms, equations, dg) -end - -# terminate recursion -function calc_boundary_flux!(cache, t, boundary_conditions::NamedTuple{(), Tuple{}}, - mesh, have_nonconservative_terms, equations, dg::DGMulti) - nothing + for (key, value) in zip(keys(boundary_conditions), boundary_conditions) + calc_single_boundary_flux!(cache, t, value, + key, + mesh, have_nonconservative_terms, equations, dg) + end end function calc_single_boundary_flux!(cache, t, boundary_condition, boundary_key, mesh, diff --git a/src/solvers/dgmulti/dg_parabolic.jl b/src/solvers/dgmulti/dg_parabolic.jl index 72dbe2c4256..7dfe4430244 100644 --- a/src/solvers/dgmulti/dg_parabolic.jl +++ b/src/solvers/dgmulti/dg_parabolic.jl @@ -62,9 +62,10 @@ end function transform_variables!(u_transformed, u, mesh, equations_parabolic::AbstractEquationsParabolic, dg::DGMulti, parabolic_scheme, cache, cache_parabolic) + transformation = gradient_variable_transformation(equations_parabolic) + @threaded for i in eachindex(u) - u_transformed[i] = gradient_variable_transformation(equations_parabolic)(u[i], - equations_parabolic) + u_transformed[i] = transformation(u[i], equations_parabolic) end end diff --git a/src/solvers/dgmulti/flux_differencing.jl b/src/solvers/dgmulti/flux_differencing.jl index 884a8fac43b..36aa50dff4e 100644 --- a/src/solvers/dgmulti/flux_differencing.jl +++ b/src/solvers/dgmulti/flux_differencing.jl @@ -88,8 +88,8 @@ end # Version for sparse operators and symmetric fluxes @inline function hadamard_sum!(du, - A::LinearAlgebra.Adjoint{<:Any, <:AbstractSparseMatrixCSC - }, + A::LinearAlgebra.Adjoint{<:Any, + <:AbstractSparseMatrixCSC}, flux_is_symmetric::True, volume_flux, orientation_or_normal_direction, u, equations) A_base = parent(A) # the adjoint of a SparseMatrixCSC is basically a SparseMatrixCSR @@ -122,8 +122,8 @@ end # Version for sparse operators and symmetric fluxes with curved meshes @inline function hadamard_sum!(du, - A::LinearAlgebra.Adjoint{<:Any, <:AbstractSparseMatrixCSC - }, + A::LinearAlgebra.Adjoint{<:Any, + <:AbstractSparseMatrixCSC}, flux_is_symmetric::True, volume_flux, normal_directions::AbstractVector{<:AbstractVector}, u, equations) @@ -161,8 +161,8 @@ end # TODO: DGMulti. Fix for curved meshes. # Version for sparse operators and non-symmetric fluxes @inline function hadamard_sum!(du, - A::LinearAlgebra.Adjoint{<:Any, <:AbstractSparseMatrixCSC - }, + A::LinearAlgebra.Adjoint{<:Any, + <:AbstractSparseMatrixCSC}, flux_is_symmetric::False, volume_flux, normal_direction::AbstractVector, u, equations) A_base = parent(A) # the adjoint of a SparseMatrixCSC is basically a SparseMatrixCSR diff --git a/src/solvers/dgmulti/flux_differencing_gauss_sbp.jl b/src/solvers/dgmulti/flux_differencing_gauss_sbp.jl index 2c5505cc4e9..9059caf87f6 100644 --- a/src/solvers/dgmulti/flux_differencing_gauss_sbp.jl +++ b/src/solvers/dgmulti/flux_differencing_gauss_sbp.jl @@ -380,9 +380,8 @@ function create_cache(mesh::DGMultiMesh, equations, # specialized operators to perform tensor product interpolation to faces for Gauss nodes interp_matrix_gauss_to_face = TensorProductGaussFaceOperator(Interpolation(), dg) - projection_matrix_gauss_to_face = TensorProductGaussFaceOperator(Projection{ - Static.False() - }(), dg) + projection_matrix_gauss_to_face = TensorProductGaussFaceOperator(Projection{Static.False()}(), + dg) # `LIFT` matrix for Gauss nodes - this is equivalent to `projection_matrix_gauss_to_face` scaled by `diagm(rd.wf)`, # where `rd.wf` are Gauss node face quadrature weights. diff --git a/src/solvers/dgmulti/sbp.jl b/src/solvers/dgmulti/sbp.jl index ba02d812041..232555e18b5 100644 --- a/src/solvers/dgmulti/sbp.jl +++ b/src/solvers/dgmulti/sbp.jl @@ -36,336 +36,32 @@ function DGMulti(element_type::AbstractElemShape, surface_integral = surface_integral, volume_integral = volume_integral) end -function construct_1d_operators(D::AbstractDerivativeOperator, tol) - nodes_1d = collect(grid(D)) - M = SummationByPartsOperators.mass_matrix(D) - if M isa UniformScaling - weights_1d = M * ones(Bool, length(nodes_1d)) - else - weights_1d = diag(M) - end - - # StartUpDG assumes nodes from -1 to +1. Thus, we need to re-scale everything. - # We can adjust the grid spacing as follows. - xmin = SummationByPartsOperators.xmin(D) - xmax = SummationByPartsOperators.xmax(D) - factor = 2 / (xmax - xmin) - @. nodes_1d = factor * (nodes_1d - xmin) - 1 - @. weights_1d = factor * weights_1d - - D_1d = droptol!(inv(factor) * sparse(D), tol) - I_1d = Diagonal(ones(Bool, length(nodes_1d))) - - return nodes_1d, weights_1d, D_1d, I_1d -end - -function StartUpDG.RefElemData(element_type::Line, - D::AbstractDerivativeOperator; - tol = 100 * eps()) - approximation_type = D - N = SummationByPartsOperators.accuracy_order(D) # kind of polynomial degree - - # 1D operators - nodes_1d, weights_1d, D_1d = construct_1d_operators(D, tol) - - # volume - rq = r = nodes_1d - wq = weights_1d - Dr = D_1d - M = Diagonal(wq) - Pq = LinearAlgebra.I - Vq = LinearAlgebra.I - - VDM = nothing # unused generalized Vandermonde matrix - - rst = (r,) - rstq = (rq,) - Drst = (Dr,) - - # face - face_vertices = StartUpDG.face_vertices(element_type) - face_mask = [1, length(nodes_1d)] - - rf = [-1.0; 1.0] - nrJ = [-1.0; 1.0] - wf = [1.0; 1.0] - if D isa AbstractPeriodicDerivativeOperator - # we do not need any face stuff for periodic operators - Vf = spzeros(length(wf), length(wq)) - else - Vf = sparse([1, 2], [1, length(nodes_1d)], [1.0, 1.0]) - end - LIFT = Diagonal(wq) \ (Vf' * Diagonal(wf)) - - rstf = (rf,) - nrstJ = (nrJ,) - - # low order interpolation nodes - r1 = StartUpDG.nodes(element_type, 1) - V1 = StartUpDG.vandermonde(element_type, 1, r) / - StartUpDG.vandermonde(element_type, 1, r1) - - return RefElemData(element_type, approximation_type, N, - face_vertices, V1, - rst, VDM, face_mask, - rst, LinearAlgebra.I, # plotting - rstq, wq, Vq, # quadrature - rstf, wf, Vf, nrstJ, # faces - M, Pq, Drst, LIFT) -end - -function StartUpDG.RefElemData(element_type::Quad, - D::AbstractDerivativeOperator; - tol = 100 * eps()) - approximation_type = D - N = SummationByPartsOperators.accuracy_order(D) # kind of polynomial degree - - # 1D operators - nodes_1d, weights_1d, D_1d, I_1d = construct_1d_operators(D, tol) - - # volume - s, r = vec.(StartUpDG.NodesAndModes.meshgrid(nodes_1d)) # this is to match - # ordering of nrstJ - rq = r - sq = s - wr, ws = vec.(StartUpDG.NodesAndModes.meshgrid(weights_1d)) - wq = wr .* ws - Dr = kron(I_1d, D_1d) - Ds = kron(D_1d, I_1d) - M = Diagonal(wq) - Pq = LinearAlgebra.I - Vq = LinearAlgebra.I - - VDM = nothing # unused generalized Vandermonde matrix - - rst = (r, s) - rstq = (rq, sq) - Drst = (Dr, Ds) - - # face - face_vertices = StartUpDG.face_vertices(element_type) - face_mask = vcat(StartUpDG.find_face_nodes(element_type, r, s)...) - - rf, sf, wf, nrJ, nsJ = StartUpDG.init_face_data(element_type, - quad_rule_face = (nodes_1d, weights_1d)) - if D isa AbstractPeriodicDerivativeOperator - # we do not need any face stuff for periodic operators - Vf = spzeros(length(wf), length(wq)) - else - Vf = sparse(eachindex(face_mask), face_mask, ones(Bool, length(face_mask))) - end - LIFT = Diagonal(wq) \ (Vf' * Diagonal(wf)) - - rstf = (rf, sf) - nrstJ = (nrJ, nsJ) - - # low order interpolation nodes - r1, s1 = StartUpDG.nodes(element_type, 1) - V1 = StartUpDG.vandermonde(element_type, 1, r, s) / - StartUpDG.vandermonde(element_type, 1, r1, s1) - - return RefElemData(element_type, approximation_type, N, - face_vertices, V1, - rst, VDM, face_mask, - rst, LinearAlgebra.I, # plotting - rstq, wq, Vq, # quadrature - rstf, wf, Vf, nrstJ, # faces - M, Pq, Drst, LIFT) -end - -function StartUpDG.RefElemData(element_type::Hex, - D::AbstractDerivativeOperator; - tol = 100 * eps()) - approximation_type = D - N = SummationByPartsOperators.accuracy_order(D) # kind of polynomial degree - - # 1D operators - nodes_1d, weights_1d, D_1d, I_1d = construct_1d_operators(D, tol) - - # volume - # to match ordering of nrstJ - s, r, t = vec.(StartUpDG.NodesAndModes.meshgrid(nodes_1d, nodes_1d, nodes_1d)) - rq = r - sq = s - tq = t - wr, ws, wt = vec.(StartUpDG.NodesAndModes.meshgrid(weights_1d, weights_1d, weights_1d)) - wq = wr .* ws .* wt - Dr = kron(I_1d, I_1d, D_1d) - Ds = kron(I_1d, D_1d, I_1d) - Dt = kron(D_1d, I_1d, I_1d) - M = Diagonal(wq) - Pq = LinearAlgebra.I - Vq = LinearAlgebra.I - - VDM = nothing # unused generalized Vandermonde matrix - - rst = (r, s, t) - rstq = (rq, sq, tq) - Drst = (Dr, Ds, Dt) - - # face - face_vertices = StartUpDG.face_vertices(element_type) - face_mask = vcat(StartUpDG.find_face_nodes(element_type, r, s, t)...) - - rf, sf, tf, wf, nrJ, nsJ, ntJ = let - rf, sf = vec.(StartUpDG.NodesAndModes.meshgrid(nodes_1d, nodes_1d)) - wr, ws = vec.(StartUpDG.NodesAndModes.meshgrid(weights_1d, weights_1d)) - wf = wr .* ws - StartUpDG.init_face_data(element_type, quad_rule_face = (rf, sf, wf)) - end - Vf = sparse(eachindex(face_mask), face_mask, ones(Bool, length(face_mask))) - LIFT = Diagonal(wq) \ (Vf' * Diagonal(wf)) - - rstf = (rf, sf, tf) - nrstJ = (nrJ, nsJ, ntJ) - - # low order interpolation nodes - r1, s1, t1 = StartUpDG.nodes(element_type, 1) - V1 = StartUpDG.vandermonde(element_type, 1, r, s, t) / - StartUpDG.vandermonde(element_type, 1, r1, s1, t1) - - return RefElemData(element_type, approximation_type, N, - face_vertices, V1, - rst, VDM, face_mask, - rst, LinearAlgebra.I, # plotting - rstq, wq, Vq, # quadrature - rstf, wf, Vf, nrstJ, # faces - M, Pq, Drst, LIFT) -end - -# specialized Hex constructor in 3D to reduce memory usage. -function StartUpDG.RefElemData(element_type::Hex, - D::AbstractPeriodicDerivativeOperator; - tol = 100 * eps()) - approximation_type = D - N = SummationByPartsOperators.accuracy_order(D) # kind of polynomial degree - - # 1D operators - nodes_1d, weights_1d, D_1d, I_1d = construct_1d_operators(D, tol) - - # volume - # to match ordering of nrstJ - s, r, t = vec.(StartUpDG.NodesAndModes.meshgrid(nodes_1d, nodes_1d, nodes_1d)) - rq = r - sq = s - tq = t - wr, ws, wt = vec.(StartUpDG.NodesAndModes.meshgrid(weights_1d, weights_1d, weights_1d)) - wq = wr .* ws .* wt - Dr = kron(I_1d, I_1d, D_1d) - Ds = kron(I_1d, D_1d, I_1d) - Dt = kron(D_1d, I_1d, I_1d) - M = Diagonal(wq) - Pq = LinearAlgebra.I - Vq = LinearAlgebra.I - - VDM = nothing # unused generalized Vandermonde matrix - - rst = (r, s, t) - rstq = (rq, sq, tq) - Drst = (Dr, Ds, Dt) - - # face - # We do not need any face data for periodic operators. Thus, we just - # pass `nothing` to save memory. - face_vertices = ntuple(_ -> nothing, 3) - face_mask = nothing - wf = nothing - rstf = ntuple(_ -> nothing, 3) - nrstJ = ntuple(_ -> nothing, 3) - Vf = nothing - LIFT = nothing - - # low order interpolation nodes - V1 = nothing # do not need to store V1, since we specialize StartUpDG.MeshData to avoid using it. - - return RefElemData(element_type, approximation_type, N, - face_vertices, V1, - rst, VDM, face_mask, - rst, LinearAlgebra.I, # plotting - rstq, wq, Vq, # quadrature - rstf, wf, Vf, nrstJ, # faces - M, Pq, Drst, LIFT) -end - -function Base.show(io::IO, mime::MIME"text/plain", - rd::RefElemData{NDIMS, ElementType, ApproximationType}) where {NDIMS, - ElementType <: - StartUpDG.AbstractElemShape, - ApproximationType <: - AbstractDerivativeOperator - } - @nospecialize rd - print(io, "RefElemData for an approximation using an ") - show(IOContext(io, :compact => true), rd.approximation_type) - print(io, " on $(rd.element_type) element") -end - -function Base.show(io::IO, - rd::RefElemData{NDIMS, ElementType, ApproximationType}) where {NDIMS, - ElementType <: - StartUpDG.AbstractElemShape, - ApproximationType <: - AbstractDerivativeOperator - } - @nospecialize rd - print(io, "RefElemData{", summary(rd.approximation_type), ", ", rd.element_type, "}") -end - -function StartUpDG.inverse_trace_constant(rd::RefElemData{NDIMS, ElementType, - ApproximationType}) where {NDIMS, - ElementType <: - Union{ - Line, - Quad, - Hex - }, - ApproximationType <: - AbstractDerivativeOperator - } - D = rd.approximation_type - - # the inverse trace constant is the maximum eigenvalue corresponding to - # M_f * v = λ * M * v - # where M_f is the face mass matrix and M is the volume mass matrix. - # Since M is diagonal and since M_f is just the boundary "mask" matrix - # (which extracts the first and last entries of a vector), the maximum - # eigenvalue is the inverse of the first or last mass matrix diagonal. - left_weight = SummationByPartsOperators.left_boundary_weight(D) - right_weight = SummationByPartsOperators.right_boundary_weight(D) - max_eigenvalue = max(inv(left_weight), inv(right_weight)) - - # For tensor product elements, the trace constant for higher dimensional - # elements is the one-dimensional trace constant multiplied by `NDIMS`. See - # "GPU-accelerated discontinuous Galerkin methods on hybrid meshes." - # Chan, Jesse, et al (2016), https://doi.org/10.1016/j.jcp.2016.04.003 - # for more details (specifically, Appendix A.1, Theorem A.4). - return NDIMS * max_eigenvalue -end - # type alias for specializing on a periodic SBP operator const DGMultiPeriodicFDSBP{NDIMS, ApproxType, ElemType} = DGMulti{NDIMS, ElemType, ApproxType, SurfaceIntegral, - VolumeIntegral - } where {NDIMS, ElemType, - ApproxType <: - SummationByPartsOperators.AbstractPeriodicDerivativeOperator, - SurfaceIntegral, - VolumeIntegral} + VolumeIntegral} where { + NDIMS, + ElemType, + ApproxType <: + SummationByPartsOperators.AbstractPeriodicDerivativeOperator, + SurfaceIntegral, + VolumeIntegral + } const DGMultiFluxDiffPeriodicFDSBP{NDIMS, ApproxType, ElemType} = DGMulti{NDIMS, ElemType, ApproxType, SurfaceIntegral, - VolumeIntegral - } where {NDIMS, - ElemType, - ApproxType <: - SummationByPartsOperators.AbstractPeriodicDerivativeOperator, - SurfaceIntegral <: - SurfaceIntegralWeakForm, - VolumeIntegral <: - VolumeIntegralFluxDifferencing - } + VolumeIntegral} where { + NDIMS, + ElemType, + ApproxType <: + SummationByPartsOperators.AbstractPeriodicDerivativeOperator, + SurfaceIntegral <: + SurfaceIntegralWeakForm, + VolumeIntegral <: + VolumeIntegralFluxDifferencing + } """ DGMultiMesh(dg::DGMulti) @@ -450,30 +146,6 @@ end @muladd begin #! format: noindent -# This is used in `estimate_dt`. `estimate_h` uses that `Jf / J = O(h^{NDIMS-1}) / O(h^{NDIMS}) = O(1/h)`. -# However, since we do not initialize `Jf` for periodic FDSBP operators, we specialize `estimate_h` -# based on the reference grid provided by SummationByPartsOperators.jl and information about the domain size -# provided by `md::MeshData``. -function StartUpDG.estimate_h(e, rd::RefElemData{NDIMS, ElementType, ApproximationType}, - md::MeshData) where {NDIMS, - ElementType <: - StartUpDG.AbstractElemShape, - ApproximationType <: - SummationByPartsOperators.AbstractPeriodicDerivativeOperator - } - D = rd.approximation_type - x = grid(D) - - # we assume all SummationByPartsOperators.jl reference grids are rescaled to [-1, 1] - xmin = SummationByPartsOperators.xmin(D) - xmax = SummationByPartsOperators.xmax(D) - factor = 2 / (xmax - xmin) - - # If the domain has size L^NDIMS, then `minimum(md.J)^(1 / NDIMS) = L`. - # WARNING: this is not a good estimate on anisotropic grids. - return minimum(diff(x)) * factor * minimum(md.J)^(1 / NDIMS) -end - # specialized for DGMultiPeriodicFDSBP since there are no face nodes # and thus no inverse trace constant for periodic domains. function estimate_dt(mesh::DGMultiMesh, dg::DGMultiPeriodicFDSBP) diff --git a/src/solvers/dgmulti/types.jl b/src/solvers/dgmulti/types.jl index fe6510856b0..813bc67061e 100644 --- a/src/solvers/dgmulti/types.jl +++ b/src/solvers/dgmulti/types.jl @@ -4,49 +4,46 @@ # `DGMulti` refers to both multiple DG types (polynomial/SBP, simplices/quads/hexes) as well as # the use of multi-dimensional operators in the solver. -const DGMulti{NDIMS, ElemType, ApproxType, SurfaceIntegral, VolumeIntegral} = DG{ - <:RefElemData{ - NDIMS, +const DGMulti{NDIMS, ElemType, ApproxType, SurfaceIntegral, VolumeIntegral} = DG{<:RefElemData{NDIMS, ElemType, - ApproxType - }, + ApproxType}, Mortar, SurfaceIntegral, - VolumeIntegral - } where { - Mortar - } + VolumeIntegral} where { + Mortar + } # Type aliases. The first parameter is `ApproxType` since it is more commonly used for dispatch. const DGMultiWeakForm{ApproxType, ElemType} = DGMulti{NDIMS, ElemType, ApproxType, <:SurfaceIntegralWeakForm, - <:VolumeIntegralWeakForm - } where {NDIMS} + <:VolumeIntegralWeakForm} where {NDIMS + } const DGMultiFluxDiff{ApproxType, ElemType} = DGMulti{NDIMS, ElemType, ApproxType, <:SurfaceIntegralWeakForm, - <:Union{ - VolumeIntegralFluxDifferencing, - VolumeIntegralShockCapturingHG - }} where {NDIMS} + <:Union{VolumeIntegralFluxDifferencing, + VolumeIntegralShockCapturingHG}} where { + NDIMS + } const DGMultiFluxDiffSBP{ApproxType, ElemType} = DGMulti{NDIMS, ElemType, ApproxType, <:SurfaceIntegralWeakForm, - <:Union{ - VolumeIntegralFluxDifferencing, - VolumeIntegralShockCapturingHG - } - } where {NDIMS, - ApproxType <: Union{SBP, - AbstractDerivativeOperator - }} + <:Union{VolumeIntegralFluxDifferencing, + VolumeIntegralShockCapturingHG}} where { + NDIMS, + ApproxType <: + Union{SBP, + AbstractDerivativeOperator} + } const DGMultiSBP{ApproxType, ElemType} = DGMulti{NDIMS, ElemType, ApproxType, - SurfaceIntegral, VolumeIntegral - } where {NDIMS, ElemType, - ApproxType <: Union{SBP, - AbstractDerivativeOperator}, - SurfaceIntegral, VolumeIntegral} + SurfaceIntegral, + VolumeIntegral} where {NDIMS, ElemType, + ApproxType <: + Union{SBP, + AbstractDerivativeOperator}, + SurfaceIntegral, + VolumeIntegral} # By default, Julia/LLVM does not use fused multiply-add operations (FMAs). # Since these FMAs can increase the performance of many numerical algorithms, @@ -433,15 +430,3 @@ function LinearAlgebra.mul!(b_in, A_kronecker::SimpleKronecker{3}, x_in) return nothing end end # @muladd - -# TODO: deprecations introduced in Trixi.jl v0.6 -@deprecate DGMultiMesh(dg::DGMulti{NDIMS}; cells_per_dimension, kwargs...) where {NDIMS} DGMultiMesh(dg, - cells_per_dimension; - kwargs...) - -# TODO: deprecations introduced in Trixi.jl v0.5 -@deprecate DGMultiMesh(vertex_coordinates, EToV, dg::DGMulti{NDIMS}; - kwargs...) where {NDIMS} DGMultiMesh(dg, vertex_coordinates, EToV; - kwargs...) -@deprecate DGMultiMesh(triangulateIO, dg::DGMulti{2, Tri}, boundary_dict::Dict{Symbol, Int}; - kwargs...) DGMultiMesh(dg, triangulateIO, boundary_dict; kwargs...) diff --git a/src/solvers/dgsem/basis_lobatto_legendre.jl b/src/solvers/dgsem/basis_lobatto_legendre.jl index 1b4e5446e44..6a92fd1c066 100644 --- a/src/solvers/dgsem/basis_lobatto_legendre.jl +++ b/src/solvers/dgsem/basis_lobatto_legendre.jl @@ -188,9 +188,9 @@ function MortarL2(basis::LobattoLegendreBasis) reverse_upper = Matrix{RealT}(reverse_upper_) reverse_lower = Matrix{RealT}(reverse_lower_) - LobattoLegendreMortarL2{RealT, nnodes_, typeof(forward_upper), typeof(reverse_upper) - }(forward_upper, forward_lower, - reverse_upper, reverse_lower) + LobattoLegendreMortarL2{RealT, nnodes_, typeof(forward_upper), + typeof(reverse_upper)}(forward_upper, forward_lower, + reverse_upper, reverse_lower) end function Base.show(io::IO, mortar::LobattoLegendreMortarL2) diff --git a/src/solvers/dgsem_p4est/containers.jl b/src/solvers/dgsem_p4est/containers.jl index 0176f5c6346..f9830d0011c 100644 --- a/src/solvers/dgsem_p4est/containers.jl +++ b/src/solvers/dgsem_p4est/containers.jl @@ -429,13 +429,17 @@ function reinitialize_containers!(mesh::P4estMesh, equations, dg::DGSEM, cache) @unpack boundaries = cache resize!(boundaries, required.boundaries) - # resize mortars container - @unpack mortars = cache - resize!(mortars, required.mortars) - - # re-initialize containers together to reduce - # the number of iterations over the mesh in `p4est` - init_surfaces!(interfaces, mortars, boundaries, mesh) + # re-initialize mortars container + if hasproperty(cache, :mortars) # cache_parabolic does not carry mortars + @unpack mortars = cache + resize!(mortars, required.mortars) + + # re-initialize containers together to reduce + # the number of iterations over the mesh in `p4est` + init_surfaces!(interfaces, mortars, boundaries, mesh) + else + init_surfaces!(interfaces, nothing, boundaries, mesh) + end end # A helper struct used in initialization methods below @@ -450,8 +454,7 @@ mutable struct InitSurfacesIterFaceUserData{Interfaces, Mortars, Boundaries, Mes end function InitSurfacesIterFaceUserData(interfaces, mortars, boundaries, mesh) - return InitSurfacesIterFaceUserData{ - typeof(interfaces), typeof(mortars), + return InitSurfacesIterFaceUserData{typeof(interfaces), typeof(mortars), typeof(boundaries), typeof(mesh)}(interfaces, 1, mortars, 1, boundaries, 1, diff --git a/src/solvers/dgsem_p4est/containers_parallel.jl b/src/solvers/dgsem_p4est/containers_parallel.jl index e7ee1f81478..7c7bd868457 100644 --- a/src/solvers/dgsem_p4est/containers_parallel.jl +++ b/src/solvers/dgsem_p4est/containers_parallel.jl @@ -266,8 +266,7 @@ end function ParallelInitSurfacesIterFaceUserData(interfaces, mortars, boundaries, mpi_interfaces, mpi_mortars, mesh) - return ParallelInitSurfacesIterFaceUserData{ - typeof(interfaces), typeof(mortars), + return ParallelInitSurfacesIterFaceUserData{typeof(interfaces), typeof(mortars), typeof(boundaries), typeof(mpi_interfaces), typeof(mpi_mortars), typeof(mesh)}(interfaces, diff --git a/src/solvers/dgsem_p4est/containers_parallel_2d.jl b/src/solvers/dgsem_p4est/containers_parallel_2d.jl index 8c39e4a69c8..d531d33821b 100644 --- a/src/solvers/dgsem_p4est/containers_parallel_2d.jl +++ b/src/solvers/dgsem_p4est/containers_parallel_2d.jl @@ -6,9 +6,7 @@ #! format: noindent # Initialize node_indices of MPI interface container -@inline function init_mpi_interface_node_indices!(mpi_interfaces::P4estMPIInterfaceContainer{ - 2 - }, +@inline function init_mpi_interface_node_indices!(mpi_interfaces::P4estMPIInterfaceContainer{2}, faces, local_side, orientation, mpi_interface_id) # Align interface in positive coordinate direction of primary element. diff --git a/src/solvers/dgsem_p4est/containers_parallel_3d.jl b/src/solvers/dgsem_p4est/containers_parallel_3d.jl index be4e2bfbfc9..56f0a543b97 100644 --- a/src/solvers/dgsem_p4est/containers_parallel_3d.jl +++ b/src/solvers/dgsem_p4est/containers_parallel_3d.jl @@ -6,9 +6,7 @@ #! format: noindent # Initialize node_indices of MPI interface container -@inline function init_mpi_interface_node_indices!(mpi_interfaces::P4estMPIInterfaceContainer{ - 3 - }, +@inline function init_mpi_interface_node_indices!(mpi_interfaces::P4estMPIInterfaceContainer{3}, faces, local_side, orientation, mpi_interface_id) # Align interface at the primary element (primary element has surface indices (:i_forward, :j_forward)). diff --git a/src/solvers/dgsem_p4est/dg_2d.jl b/src/solvers/dgsem_p4est/dg_2d.jl index 97b931fa325..36624f2ce8a 100644 --- a/src/solvers/dgsem_p4est/dg_2d.jl +++ b/src/solvers/dgsem_p4est/dg_2d.jl @@ -275,9 +275,9 @@ function prolong2boundaries!(cache, u, return nothing end -function calc_boundary_flux!(cache, t, boundary_condition, boundary_indexing, +function calc_boundary_flux!(cache, t, boundary_condition::BC, boundary_indexing, mesh::Union{P4estMesh{2}, T8codeMesh{2}}, - equations, surface_integral, dg::DG) + equations, surface_integral, dg::DG) where {BC} @unpack boundaries = cache @unpack surface_flux_values = cache.elements index_range = eachnode(dg) @@ -501,6 +501,11 @@ function calc_mortar_flux!(surface_flux_values, # copying in the correct orientation u_buffer = cache.u_threaded[Threads.threadid()] + # in calc_interface_flux!, the interface flux is computed once over each + # interface using the normal from the "primary" element. The result is then + # passed back to the "secondary" element, flipping the sign to account for the + # change in the normal direction. For mortars, this sign flip occurs in + # "mortar_fluxes_to_elements!" instead. mortar_fluxes_to_elements!(surface_flux_values, mesh, equations, mortar_l2, dg, cache, mortar, fstar, u_buffer) diff --git a/src/solvers/dgsem_p4est/dg_2d_parabolic.jl b/src/solvers/dgsem_p4est/dg_2d_parabolic.jl index a04523d2fb4..a7f3345168f 100644 --- a/src/solvers/dgsem_p4est/dg_2d_parabolic.jl +++ b/src/solvers/dgsem_p4est/dg_2d_parabolic.jl @@ -10,14 +10,11 @@ function create_cache_parabolic(mesh::P4estMesh{2}, equations_hyperbolic::Abstra interfaces = init_interfaces(mesh, equations_hyperbolic, dg.basis, elements) boundaries = init_boundaries(mesh, equations_hyperbolic, dg.basis, elements) - n_vars = nvariables(equations_hyperbolic) - n_elements = nelements(elements) - n_nodes = nnodes(dg.basis) # nodes in one direction - u_transformed = Array{uEltype}(undef, n_vars, n_nodes, n_nodes, n_elements) - gradients = ntuple(_ -> similar(u_transformed), ndims(mesh)) - flux_viscous = ntuple(_ -> similar(u_transformed), ndims(mesh)) + viscous_container = init_viscous_container_2d(nvariables(equations_hyperbolic), + nnodes(dg.basis), nelements(elements), + uEltype) - cache = (; elements, interfaces, boundaries, gradients, flux_viscous, u_transformed) + cache = (; elements, interfaces, boundaries, viscous_container) return cache end @@ -28,7 +25,8 @@ function rhs_parabolic!(du, u, t, mesh::P4estMesh{2}, equations_parabolic::AbstractEquationsParabolic, initial_condition, boundary_conditions_parabolic, source_terms, dg::DG, parabolic_scheme, cache, cache_parabolic) - (; u_transformed, gradients, flux_viscous) = cache_parabolic + @unpack viscous_container = cache_parabolic + @unpack u_transformed, gradients, flux_viscous = viscous_container # Convert conservative variables to a form more suitable for viscous flux calculations @trixi_timeit timer() "transform variables" begin @@ -96,8 +94,19 @@ function rhs_parabolic!(du, u, t, mesh::P4estMesh{2}, dg.surface_integral, dg) end - # TODO: parabolic; extend to mortars - @assert nmortars(dg, cache) == 0 + # Prolong solution to mortars (specialized for AbstractEquationsParabolic) + # !!! NOTE: we reuse the hyperbolic cache here since it contains "mortars" and "u_threaded". See https://github.com/trixi-framework/Trixi.jl/issues/1674 for a discussion + @trixi_timeit timer() "prolong2mortars" begin + prolong2mortars_divergence!(cache, flux_viscous, mesh, equations_parabolic, + dg.mortar, dg.surface_integral, dg) + end + + # Calculate mortar fluxes (specialized for AbstractEquationsParabolic) + @trixi_timeit timer() "mortar flux" begin + calc_mortar_flux_divergence!(cache_parabolic.elements.surface_flux_values, + mesh, equations_parabolic, dg.mortar, + dg.surface_integral, dg, cache) + end # Calculate surface integrals @trixi_timeit timer() "surface integral" begin @@ -178,14 +187,15 @@ function calc_gradient!(gradients, u_transformed, t, end end - # Prolong solution to interfaces + # Prolong solution to interfaces. + # This reuses `prolong2interfaces` for the purely hyperbolic case. @trixi_timeit timer() "prolong2interfaces" begin prolong2interfaces!(cache_parabolic, u_transformed, mesh, equations_parabolic, dg.surface_integral, dg) end - # Calculate interface fluxes for the gradient. This reuses P4est `calc_interface_flux!` along with a - # specialization for AbstractEquationsParabolic. + # Calculate interface fluxes for the gradient. + # This reuses `calc_interface_flux!` for the purely hyperbolic case. @trixi_timeit timer() "interface flux" begin calc_interface_flux!(cache_parabolic.elements.surface_flux_values, mesh, False(), # False() = no nonconservative terms @@ -204,8 +214,21 @@ function calc_gradient!(gradients, u_transformed, t, mesh, equations_parabolic, dg.surface_integral, dg) end - # TODO: parabolic; mortars - @assert nmortars(dg, cache) == 0 + # Prolong solution to mortars. This resues the hyperbolic version of `prolong2mortars` + @trixi_timeit timer() "prolong2mortars" begin + prolong2mortars!(cache, u_transformed, mesh, equations_parabolic, + dg.mortar, dg.surface_integral, dg) + end + + # Calculate mortar fluxes. This reuses the hyperbolic version of `calc_mortar_flux`, + # along with a specialization on `calc_mortar_flux!(fstar, ...)` and `mortar_fluxes_to_elements!` for + # AbstractEquationsParabolic. + @trixi_timeit timer() "mortar flux" begin + calc_mortar_flux!(cache_parabolic.elements.surface_flux_values, + mesh, False(), # False() = no nonconservative terms + equations_parabolic, + dg.mortar, dg.surface_integral, dg, cache) + end # Calculate surface integrals @trixi_timeit timer() "surface integral" begin @@ -305,6 +328,64 @@ function calc_gradient!(gradients, u_transformed, t, return nothing end +# This version is called during `calc_gradients!` and must be specialized because the +# flux for the gradient is {u}, which doesn't depend on the outward normal. Thus, +# you don't need to scale by 2 (e.g., the scaling factor in the normals (and in the +# contravariant vectors) along large/small elements across a non-conforming +# interface in 2D) and flip the sign when storing the mortar fluxes back +# into `surface_flux_values`. +@inline function mortar_fluxes_to_elements!(surface_flux_values, + mesh::Union{P4estMesh{2}, T8codeMesh{2}}, + equations::AbstractEquationsParabolic, + mortar_l2::LobattoLegendreMortarL2, + dg::DGSEM, cache, mortar, fstar, u_buffer) + @unpack neighbor_ids, node_indices = cache.mortars + # Copy solution small to small + small_indices = node_indices[1, mortar] + small_direction = indices2direction(small_indices) + + for position in 1:2 + element = neighbor_ids[position, mortar] + for i in eachnode(dg) + for v in eachvariable(equations) + surface_flux_values[v, i, small_direction, element] = fstar[position][v, + i] + end + end + end + + # Project small fluxes to large element. + multiply_dimensionwise!(u_buffer, + mortar_l2.reverse_upper, fstar[2], + mortar_l2.reverse_lower, fstar[1]) + + # Copy interpolated flux values from buffer to large element face in the + # correct orientation. + # Note that the index of the small sides will always run forward but + # the index of the large side might need to run backwards for flipped sides. + large_element = neighbor_ids[3, mortar] + large_indices = node_indices[2, mortar] + large_direction = indices2direction(large_indices) + + if :i_backward in large_indices + for i in eachnode(dg) + for v in eachvariable(equations) + surface_flux_values[v, end + 1 - i, large_direction, large_element] = u_buffer[v, + i] + end + end + else + for i in eachnode(dg) + for v in eachvariable(equations) + surface_flux_values[v, i, large_direction, large_element] = u_buffer[v, + i] + end + end + end + + return nothing +end + # This version is used for parabolic gradient computations @inline function calc_interface_flux!(surface_flux_values, mesh::P4estMesh{2}, nonconservative_terms::False, @@ -323,7 +404,7 @@ end flux_ = 0.5 * (u_ll + u_rr) # we assume that the gradient computations utilize a central flux - # Note that we don't flip the sign on the secondondary flux. This is because for parabolic terms, + # Note that we don't flip the sign on the secondary flux. This is because for parabolic terms, # the normals are not embedded in `flux_` for the parabolic gradient computations. for v in eachvariable(equations) surface_flux_values[v, primary_node_index, primary_direction_index, primary_element_index] = flux_[v] @@ -522,6 +603,163 @@ function calc_interface_flux!(surface_flux_values, return nothing end +function prolong2mortars_divergence!(cache, flux_viscous::Vector{Array{uEltype, 4}}, + mesh::Union{P4estMesh{2}, T8codeMesh{2}}, equations, + mortar_l2::LobattoLegendreMortarL2, + surface_integral, dg::DGSEM) where {uEltype <: Real} + @unpack neighbor_ids, node_indices = cache.mortars + @unpack contravariant_vectors = cache.elements + index_range = eachnode(dg) + + flux_viscous_x, flux_viscous_y = flux_viscous + + @threaded for mortar in eachmortar(dg, cache) + # Copy solution data from the small elements using "delayed indexing" with + # a start value and a step size to get the correct face and orientation. + small_indices = node_indices[1, mortar] + direction_index = indices2direction(small_indices) + + i_small_start, i_small_step = index_to_start_step_2d(small_indices[1], + index_range) + j_small_start, j_small_step = index_to_start_step_2d(small_indices[2], + index_range) + + for position in 1:2 + i_small = i_small_start + j_small = j_small_start + element = neighbor_ids[position, mortar] + for i in eachnode(dg) + normal_direction = get_normal_direction(direction_index, + contravariant_vectors, + i_small, j_small, element) + + for v in eachvariable(equations) + flux_viscous = SVector(flux_viscous_x[v, i_small, j_small, element], + flux_viscous_y[v, i_small, j_small, element]) + + cache.mortars.u[1, v, position, i, mortar] = dot(flux_viscous, + normal_direction) + end + i_small += i_small_step + j_small += j_small_step + end + end + + # Buffer to copy solution values of the large element in the correct orientation + # before interpolating + u_buffer = cache.u_threaded[Threads.threadid()] + + # Copy solution of large element face to buffer in the + # correct orientation + large_indices = node_indices[2, mortar] + direction_index = indices2direction(large_indices) + + i_large_start, i_large_step = index_to_start_step_2d(large_indices[1], + index_range) + j_large_start, j_large_step = index_to_start_step_2d(large_indices[2], + index_range) + + i_large = i_large_start + j_large = j_large_start + element = neighbor_ids[3, mortar] + for i in eachnode(dg) + normal_direction = get_normal_direction(direction_index, contravariant_vectors, + i_large, j_large, element) + + for v in eachvariable(equations) + flux_viscous = SVector(flux_viscous_x[v, i_large, j_large, element], + flux_viscous_y[v, i_large, j_large, element]) + + # We prolong the viscous flux dotted with respect the outward normal + # on the small element. We scale by -1/2 here because the normal + # direction on the large element is negative 2x that of the small + # element (these normal directions are "scaled" by the surface Jacobian) + u_buffer[v, i] = -0.5 * dot(flux_viscous, normal_direction) + end + i_large += i_large_step + j_large += j_large_step + end + + # Interpolate large element face data from buffer to small face locations + multiply_dimensionwise!(view(cache.mortars.u, 2, :, 1, :, mortar), + mortar_l2.forward_lower, + u_buffer) + multiply_dimensionwise!(view(cache.mortars.u, 2, :, 2, :, mortar), + mortar_l2.forward_upper, + u_buffer) + end + + return nothing +end + +# We specialize `calc_mortar_flux!` for the divergence part of +# the parabolic terms. +function calc_mortar_flux_divergence!(surface_flux_values, + mesh::Union{P4estMesh{2}, T8codeMesh{2}}, + equations::AbstractEquationsParabolic, + mortar_l2::LobattoLegendreMortarL2, + surface_integral, dg::DG, cache) + @unpack neighbor_ids, node_indices = cache.mortars + @unpack contravariant_vectors = cache.elements + @unpack fstar_upper_threaded, fstar_lower_threaded = cache + index_range = eachnode(dg) + + @threaded for mortar in eachmortar(dg, cache) + # Choose thread-specific pre-allocated container + fstar = (fstar_lower_threaded[Threads.threadid()], + fstar_upper_threaded[Threads.threadid()]) + + for position in 1:2 + for node in eachnode(dg) + for v in eachvariable(equations) + viscous_flux_normal_ll = cache.mortars.u[1, v, position, node, mortar] + viscous_flux_normal_rr = cache.mortars.u[2, v, position, node, mortar] + + # TODO: parabolic; only BR1 at the moment + fstar[position][v, node] = 0.5 * (viscous_flux_normal_ll + + viscous_flux_normal_rr) + end + end + end + + # Buffer to interpolate flux values of the large element to before + # copying in the correct orientation + u_buffer = cache.u_threaded[Threads.threadid()] + + # this reuses the hyperbolic version of `mortar_fluxes_to_elements!` + mortar_fluxes_to_elements!(surface_flux_values, + mesh, equations, mortar_l2, dg, cache, + mortar, fstar, u_buffer) + end + + return nothing +end + +# We structure `calc_interface_flux!` similarly to "calc_mortar_flux!" for +# hyperbolic equations with no nonconservative terms. +# The reasoning is that parabolic fluxes are treated like conservative +# terms (e.g., we compute a viscous conservative "flux") and thus no +# non-conservative terms are present. +@inline function calc_mortar_flux!(fstar, + mesh::Union{P4estMesh{2}, T8codeMesh{2}}, + nonconservative_terms::False, + equations::AbstractEquationsParabolic, + surface_integral, dg::DG, cache, + mortar_index, position_index, normal_direction, + node_index) + @unpack u = cache.mortars + @unpack surface_flux = surface_integral + + u_ll, u_rr = get_surface_node_vars(u, equations, dg, position_index, node_index, + mortar_index) + + # TODO: parabolic; only BR1 at the moment + flux_ = 0.5 * (u_ll + u_rr) + + # Copy flux to buffer + set_node_vars!(fstar[position_index], flux_, equations, dg, node_index) +end + # TODO: parabolic, finish implementing `calc_boundary_flux_gradients!` and `calc_boundary_flux_divergence!` function prolong2boundaries!(cache_parabolic, flux_viscous, mesh::P4estMesh{2}, @@ -565,8 +803,7 @@ end function calc_boundary_flux_gradients!(cache, t, boundary_condition::Union{BoundaryConditionPeriodic, - BoundaryConditionDoNothing - }, + BoundaryConditionDoNothing}, mesh::P4estMesh, equations, surface_integral, dg::DG) @assert isempty(eachboundary(dg, cache)) end diff --git a/src/solvers/dgsem_p4est/dg_3d.jl b/src/solvers/dgsem_p4est/dg_3d.jl index 9bde04d0813..5b3c5ae5ca8 100644 --- a/src/solvers/dgsem_p4est/dg_3d.jl +++ b/src/solvers/dgsem_p4est/dg_3d.jl @@ -580,6 +580,11 @@ function calc_mortar_flux!(surface_flux_values, # copying in the correct orientation u_buffer = cache.u_threaded[Threads.threadid()] + # in calc_interface_flux!, the interface flux is computed once over each + # interface using the normal from the "primary" element. The result is then + # passed back to the "secondary" element, flipping the sign to account for the + # change in the normal direction. For mortars, this sign flip occurs in + # "mortar_fluxes_to_elements!" instead. mortar_fluxes_to_elements!(surface_flux_values, mesh, equations, mortar_l2, dg, cache, mortar, fstar, u_buffer, fstar_tmp) diff --git a/src/solvers/dgsem_p4est/dg_3d_parabolic.jl b/src/solvers/dgsem_p4est/dg_3d_parabolic.jl index 2d26c1aff50..b06cdd42127 100644 --- a/src/solvers/dgsem_p4est/dg_3d_parabolic.jl +++ b/src/solvers/dgsem_p4est/dg_3d_parabolic.jl @@ -10,14 +10,11 @@ function create_cache_parabolic(mesh::P4estMesh{3}, equations_hyperbolic::Abstra interfaces = init_interfaces(mesh, equations_hyperbolic, dg.basis, elements) boundaries = init_boundaries(mesh, equations_hyperbolic, dg.basis, elements) - n_vars = nvariables(equations_hyperbolic) - n_elements = nelements(elements) - n_nodes = nnodes(dg.basis) # nodes in one direction - u_transformed = Array{uEltype}(undef, n_vars, n_nodes, n_nodes, n_nodes, n_elements) - gradients = ntuple(_ -> similar(u_transformed), ndims(mesh)) - flux_viscous = ntuple(_ -> similar(u_transformed), ndims(mesh)) + viscous_container = init_viscous_container_3d(nvariables(equations_hyperbolic), + nnodes(dg.basis), nelements(elements), + uEltype) - cache = (; elements, interfaces, boundaries, gradients, flux_viscous, u_transformed) + cache = (; elements, interfaces, boundaries, viscous_container) return cache end @@ -36,7 +33,8 @@ function rhs_parabolic!(du, u, t, mesh::P4estMesh{3}, equations_parabolic::AbstractEquationsParabolic, initial_condition, boundary_conditions_parabolic, source_terms, dg::DG, parabolic_scheme, cache, cache_parabolic) - @unpack u_transformed, gradients, flux_viscous = cache_parabolic + @unpack viscous_container = cache_parabolic + @unpack u_transformed, gradients, flux_viscous = viscous_container # Convert conservative variables to a form more suitable for viscous flux calculations @trixi_timeit timer() "transform variables" begin diff --git a/src/solvers/dgsem_p4est/dg_parallel.jl b/src/solvers/dgsem_p4est/dg_parallel.jl index 324bc7f3cd6..712ede2bfce 100644 --- a/src/solvers/dgsem_p4est/dg_parallel.jl +++ b/src/solvers/dgsem_p4est/dg_parallel.jl @@ -342,8 +342,7 @@ function InitNeighborRankConnectivityIterFaceUserData(mpi_interfaces, mpi_mortar global_mortar_ids = fill(-1, nmpimortars(mpi_mortars)) neighbor_ranks_mortar = Vector{Vector{Int}}(undef, nmpimortars(mpi_mortars)) - return InitNeighborRankConnectivityIterFaceUserData{ - typeof(mpi_interfaces), + return InitNeighborRankConnectivityIterFaceUserData{typeof(mpi_interfaces), typeof(mpi_mortars), typeof(mesh)}(mpi_interfaces, 1, global_interface_ids, diff --git a/src/solvers/dgsem_structured/containers.jl b/src/solvers/dgsem_structured/containers.jl index 41eabf7c6bf..8adf005b782 100644 --- a/src/solvers/dgsem_structured/containers.jl +++ b/src/solvers/dgsem_structured/containers.jl @@ -5,8 +5,8 @@ @muladd begin #! format: noindent -struct ElementContainer{NDIMS, RealT <: Real, uEltype <: Real, NDIMSP1, NDIMSP2, NDIMSP3 - } +struct ElementContainer{NDIMS, RealT <: Real, uEltype <: Real, NDIMSP1, NDIMSP2, + NDIMSP3} # Physical coordinates at each node node_coordinates::Array{RealT, NDIMSP2} # [orientation, node_i, node_j, node_k, element] # ID of neighbor element in negative direction in orientation diff --git a/src/solvers/dgsem_structured/dg_2d.jl b/src/solvers/dgsem_structured/dg_2d.jl index 3e8ce759b30..25a0eea096f 100644 --- a/src/solvers/dgsem_structured/dg_2d.jl +++ b/src/solvers/dgsem_structured/dg_2d.jl @@ -49,6 +49,13 @@ function rhs!(du, u, t, return nothing end +#= +`weak_form_kernel!` is only implemented for conserved terms as +non-conservative terms should always be discretized in conjunction with a flux-splitting scheme, +see `flux_differencing_kernel!`. +This treatment is required to achieve, e.g., entropy-stability or well-balancedness. +See also https://github.com/trixi-framework/Trixi.jl/issues/1671#issuecomment-1765644064 +=# @inline function weak_form_kernel!(du, u, element, mesh::Union{StructuredMesh{2}, UnstructuredMesh2D, diff --git a/src/solvers/dgsem_structured/dg_3d.jl b/src/solvers/dgsem_structured/dg_3d.jl index dad369735f0..1df9f408895 100644 --- a/src/solvers/dgsem_structured/dg_3d.jl +++ b/src/solvers/dgsem_structured/dg_3d.jl @@ -49,6 +49,13 @@ function rhs!(du, u, t, return nothing end +#= +`weak_form_kernel!` is only implemented for conserved terms as +non-conservative terms should always be discretized in conjunction with a flux-splitting scheme, +see `flux_differencing_kernel!`. +This treatment is required to achieve, e.g., entropy-stability or well-balancedness. +See also https://github.com/trixi-framework/Trixi.jl/issues/1671#issuecomment-1765644064 +=# @inline function weak_form_kernel!(du, u, element, mesh::Union{StructuredMesh{3}, P4estMesh{3}, diff --git a/src/solvers/dgsem_tree/container_viscous_1d.jl b/src/solvers/dgsem_tree/container_viscous_1d.jl new file mode 100644 index 00000000000..71c68dfc6df --- /dev/null +++ b/src/solvers/dgsem_tree/container_viscous_1d.jl @@ -0,0 +1,58 @@ +mutable struct ViscousContainer1D{uEltype <: Real} + u_transformed::Array{uEltype, 3} + gradients::Array{uEltype, 3} + flux_viscous::Array{uEltype, 3} + + # internal `resize!`able storage + _u_transformed::Vector{uEltype} + _gradients::Vector{uEltype} + _flux_viscous::Vector{uEltype} + + function ViscousContainer1D{uEltype}(n_vars::Integer, n_nodes::Integer, + n_elements::Integer) where {uEltype <: Real} + new(Array{uEltype, 3}(undef, n_vars, n_nodes, n_elements), + Array{uEltype, 3}(undef, n_vars, n_nodes, n_elements), + Array{uEltype, 3}(undef, n_vars, n_nodes, n_elements), + Vector{uEltype}(undef, n_vars * n_nodes * n_elements), + Vector{uEltype}(undef, n_vars * n_nodes * n_elements), + Vector{uEltype}(undef, n_vars * n_nodes * n_elements)) + end +end + +function init_viscous_container_1d(n_vars::Integer, n_nodes::Integer, + n_elements::Integer, + ::Type{uEltype}) where {uEltype <: Real} + return ViscousContainer1D{uEltype}(n_vars, n_nodes, n_elements) +end + +# Only one-dimensional `Array`s are `resize!`able in Julia. +# Hence, we use `Vector`s as internal storage and `resize!` +# them whenever needed. Then, we reuse the same memory by +# `unsafe_wrap`ping multi-dimensional `Array`s around the +# internal storage. +function Base.resize!(viscous_container::ViscousContainer1D, equations, dg, cache) + capacity = nvariables(equations) * nnodes(dg) * nelements(dg, cache) + resize!(viscous_container._u_transformed, capacity) + resize!(viscous_container._gradients, capacity) + resize!(viscous_container._flux_viscous, capacity) + + viscous_container.u_transformed = unsafe_wrap(Array, + pointer(viscous_container._u_transformed), + (nvariables(equations), + nnodes(dg), + nelements(dg, cache))) + + viscous_container.gradients = unsafe_wrap(Array, + pointer(viscous_container._gradients), + (nvariables(equations), + nnodes(dg), + nelements(dg, cache))) + + viscous_container.flux_viscous = unsafe_wrap(Array, + pointer(viscous_container._flux_viscous), + (nvariables(equations), + nnodes(dg), + nelements(dg, cache))) + + return nothing +end diff --git a/src/solvers/dgsem_tree/container_viscous_2d.jl b/src/solvers/dgsem_tree/container_viscous_2d.jl new file mode 100644 index 00000000000..bd7ff413af5 --- /dev/null +++ b/src/solvers/dgsem_tree/container_viscous_2d.jl @@ -0,0 +1,69 @@ +mutable struct ViscousContainer2D{uEltype <: Real} + u_transformed::Array{uEltype, 4} + # Using an outer fixed-size datastructure leads to nasty implementations, + # see https://github.com/trixi-framework/Trixi.jl/pull/1629#discussion_r1355293953. + # Also: This does not result in speed up compared to using tuples for the internal + # datastructures, see + # https://github.com/trixi-framework/Trixi.jl/pull/1629#discussion_r1363352188. + gradients::Vector{Array{uEltype, 4}} + flux_viscous::Vector{Array{uEltype, 4}} + + # internal `resize!`able storage + _u_transformed::Vector{uEltype} + # Use Tuple for outer, fixed-size datastructure + _gradients::Tuple{Vector{uEltype}, Vector{uEltype}} + _flux_viscous::Tuple{Vector{uEltype}, Vector{uEltype}} + + function ViscousContainer2D{uEltype}(n_vars::Integer, n_nodes::Integer, + n_elements::Integer) where {uEltype <: Real} + new(Array{uEltype, 4}(undef, n_vars, n_nodes, n_nodes, n_elements), + [Array{uEltype, 4}(undef, n_vars, n_nodes, n_nodes, n_elements) for _ in 1:2], + [Array{uEltype, 4}(undef, n_vars, n_nodes, n_nodes, n_elements) for _ in 1:2], + Vector{uEltype}(undef, n_vars * n_nodes^2 * n_elements), + (Vector{uEltype}(undef, n_vars * n_nodes^2 * n_elements), + Vector{uEltype}(undef, n_vars * n_nodes^2 * n_elements)), + (Vector{uEltype}(undef, n_vars * n_nodes^2 * n_elements), + Vector{uEltype}(undef, n_vars * n_nodes^2 * n_elements))) + end +end + +function init_viscous_container_2d(n_vars::Integer, n_nodes::Integer, + n_elements::Integer, + ::Type{uEltype}) where {uEltype <: Real} + return ViscousContainer2D{uEltype}(n_vars, n_nodes, n_elements) +end + +# Only one-dimensional `Array`s are `resize!`able in Julia. +# Hence, we use `Vector`s as internal storage and `resize!` +# them whenever needed. Then, we reuse the same memory by +# `unsafe_wrap`ping multi-dimensional `Array`s around the +# internal storage. +function Base.resize!(viscous_container::ViscousContainer2D, equations, dg, cache) + capacity = nvariables(equations) * nnodes(dg) * nnodes(dg) * nelements(dg, cache) + resize!(viscous_container._u_transformed, capacity) + for dim in 1:2 + resize!(viscous_container._gradients[dim], capacity) + resize!(viscous_container._flux_viscous[dim], capacity) + end + + viscous_container.u_transformed = unsafe_wrap(Array, + pointer(viscous_container._u_transformed), + (nvariables(equations), + nnodes(dg), nnodes(dg), + nelements(dg, cache))) + + for dim in 1:2 + viscous_container.gradients[dim] = unsafe_wrap(Array, + pointer(viscous_container._gradients[dim]), + (nvariables(equations), + nnodes(dg), nnodes(dg), + nelements(dg, cache))) + + viscous_container.flux_viscous[dim] = unsafe_wrap(Array, + pointer(viscous_container._flux_viscous[dim]), + (nvariables(equations), + nnodes(dg), nnodes(dg), + nelements(dg, cache))) + end + return nothing +end diff --git a/src/solvers/dgsem_tree/container_viscous_3d.jl b/src/solvers/dgsem_tree/container_viscous_3d.jl new file mode 100644 index 00000000000..64d283fe189 --- /dev/null +++ b/src/solvers/dgsem_tree/container_viscous_3d.jl @@ -0,0 +1,75 @@ +mutable struct ViscousContainer3D{uEltype <: Real} + u_transformed::Array{uEltype, 5} + # Using an outer fixed-size datastructure leads to nasty implementations, + # see https://github.com/trixi-framework/Trixi.jl/pull/1629#discussion_r1355293953. + # Also: This does not result in speed up compared to using tuples for the internal + # datastructures, see + # https://github.com/trixi-framework/Trixi.jl/pull/1629#discussion_r1363352188. + gradients::Vector{Array{uEltype, 5}} + flux_viscous::Vector{Array{uEltype, 5}} + + # internal `resize!`able storage + _u_transformed::Vector{uEltype} + # Use Tuple for outer, fixed-size datastructure + _gradients::Tuple{Vector{uEltype}, Vector{uEltype}, Vector{uEltype}} + _flux_viscous::Tuple{Vector{uEltype}, Vector{uEltype}, Vector{uEltype}} + + function ViscousContainer3D{uEltype}(n_vars::Integer, n_nodes::Integer, + n_elements::Integer) where {uEltype <: Real} + new(Array{uEltype, 5}(undef, n_vars, n_nodes, n_nodes, n_nodes, n_elements), + [Array{uEltype, 5}(undef, n_vars, n_nodes, n_nodes, n_nodes, n_elements) + for _ in 1:3], + [Array{uEltype, 5}(undef, n_vars, n_nodes, n_nodes, n_nodes, n_elements) + for _ in 1:3], + Vector{uEltype}(undef, n_vars * n_nodes^3 * n_elements), + (Vector{uEltype}(undef, n_vars * n_nodes^3 * n_elements), + Vector{uEltype}(undef, n_vars * n_nodes^3 * n_elements), + Vector{uEltype}(undef, n_vars * n_nodes^3 * n_elements)), + (Vector{uEltype}(undef, n_vars * n_nodes^3 * n_elements), + Vector{uEltype}(undef, n_vars * n_nodes^3 * n_elements), + Vector{uEltype}(undef, n_vars * n_nodes^3 * n_elements))) + end +end + +function init_viscous_container_3d(n_vars::Integer, n_nodes::Integer, + n_elements::Integer, + ::Type{uEltype}) where {uEltype <: Real} + return ViscousContainer3D{uEltype}(n_vars, n_nodes, n_elements) +end + +# Only one-dimensional `Array`s are `resize!`able in Julia. +# Hence, we use `Vector`s as internal storage and `resize!` +# them whenever needed. Then, we reuse the same memory by +# `unsafe_wrap`ping multi-dimensional `Array`s around the +# internal storage. +function Base.resize!(viscous_container::ViscousContainer3D, equations, dg, cache) + capacity = nvariables(equations) * nnodes(dg) * nnodes(dg) * nnodes(dg) * + nelements(dg, cache) + resize!(viscous_container._u_transformed, capacity) + for dim in 1:3 + resize!(viscous_container._gradients[dim], capacity) + resize!(viscous_container._flux_viscous[dim], capacity) + end + + viscous_container.u_transformed = unsafe_wrap(Array, + pointer(viscous_container._u_transformed), + (nvariables(equations), + nnodes(dg), nnodes(dg), nnodes(dg), + nelements(dg, cache))) + + for dim in 1:3 + viscous_container.gradients[dim] = unsafe_wrap(Array, + pointer(viscous_container._gradients[dim]), + (nvariables(equations), + nnodes(dg), nnodes(dg), nnodes(dg), + nelements(dg, cache))) + + viscous_container.flux_viscous[dim] = unsafe_wrap(Array, + pointer(viscous_container._flux_viscous[dim]), + (nvariables(equations), + nnodes(dg), nnodes(dg), + nnodes(dg), + nelements(dg, cache))) + end + return nothing +end diff --git a/src/solvers/dgsem_tree/containers.jl b/src/solvers/dgsem_tree/containers.jl index bba8b83b23a..3f05daf81d8 100644 --- a/src/solvers/dgsem_tree/containers.jl +++ b/src/solvers/dgsem_tree/containers.jl @@ -28,9 +28,11 @@ function reinitialize_containers!(mesh::TreeMesh, equations, dg::DGSEM, cache) init_boundaries!(boundaries, elements, mesh) # re-initialize mortars container - @unpack mortars = cache - resize!(mortars, count_required_mortars(mesh, leaf_cell_ids)) - init_mortars!(mortars, elements, mesh) + if hasproperty(cache, :mortars) # cache_parabolic does not carry mortars + @unpack mortars = cache + resize!(mortars, count_required_mortars(mesh, leaf_cell_ids)) + init_mortars!(mortars, elements, mesh) + end if mpi_isparallel() # re-initialize mpi_interfaces container diff --git a/src/solvers/dgsem_tree/containers_2d.jl b/src/solvers/dgsem_tree/containers_2d.jl index 9148b936312..4bfbddead9a 100644 --- a/src/solvers/dgsem_tree/containers_2d.jl +++ b/src/solvers/dgsem_tree/containers_2d.jl @@ -1266,11 +1266,15 @@ end # | # (i, j-1) mutable struct ContainerAntidiffusiveFlux2D{uEltype <: Real} - antidiffusive_flux1::Array{uEltype, 4} # [variables, i, j, elements] - antidiffusive_flux2::Array{uEltype, 4} # [variables, i, j, elements] + antidiffusive_flux1_L::Array{uEltype, 4} # [variables, i, j, elements] + antidiffusive_flux1_R::Array{uEltype, 4} # [variables, i, j, elements] + antidiffusive_flux2_L::Array{uEltype, 4} # [variables, i, j, elements] + antidiffusive_flux2_R::Array{uEltype, 4} # [variables, i, j, elements] # internal `resize!`able storage - _antidiffusive_flux1::Vector{uEltype} - _antidiffusive_flux2::Vector{uEltype} + _antidiffusive_flux1_L::Vector{uEltype} + _antidiffusive_flux1_R::Vector{uEltype} + _antidiffusive_flux2_L::Vector{uEltype} + _antidiffusive_flux2_R::Vector{uEltype} end function ContainerAntidiffusiveFlux2D{uEltype}(capacity::Integer, n_variables, @@ -1278,24 +1282,36 @@ function ContainerAntidiffusiveFlux2D{uEltype}(capacity::Integer, n_variables, nan_uEltype = convert(uEltype, NaN) # Initialize fields with defaults - _antidiffusive_flux1 = fill(nan_uEltype, - n_variables * (n_nodes + 1) * n_nodes * capacity) - antidiffusive_flux1 = unsafe_wrap(Array, pointer(_antidiffusive_flux1), - (n_variables, n_nodes + 1, n_nodes, capacity)) - - _antidiffusive_flux2 = fill(nan_uEltype, - n_variables * n_nodes * (n_nodes + 1) * capacity) - antidiffusive_flux2 = unsafe_wrap(Array, pointer(_antidiffusive_flux2), - (n_variables, n_nodes, n_nodes + 1, capacity)) - - return ContainerAntidiffusiveFlux2D{uEltype}(antidiffusive_flux1, - antidiffusive_flux2, - _antidiffusive_flux1, - _antidiffusive_flux2) + _antidiffusive_flux1_L = fill(nan_uEltype, + n_variables * (n_nodes + 1) * n_nodes * capacity) + antidiffusive_flux1_L = unsafe_wrap(Array, pointer(_antidiffusive_flux1_L), + (n_variables, n_nodes + 1, n_nodes, capacity)) + _antidiffusive_flux1_R = fill(nan_uEltype, + n_variables * (n_nodes + 1) * n_nodes * capacity) + antidiffusive_flux1_R = unsafe_wrap(Array, pointer(_antidiffusive_flux1_R), + (n_variables, n_nodes + 1, n_nodes, capacity)) + + _antidiffusive_flux2_L = fill(nan_uEltype, + n_variables * n_nodes * (n_nodes + 1) * capacity) + antidiffusive_flux2_L = unsafe_wrap(Array, pointer(_antidiffusive_flux2_L), + (n_variables, n_nodes, n_nodes + 1, capacity)) + _antidiffusive_flux2_R = fill(nan_uEltype, + n_variables * n_nodes * (n_nodes + 1) * capacity) + antidiffusive_flux2_R = unsafe_wrap(Array, pointer(_antidiffusive_flux2_R), + (n_variables, n_nodes, n_nodes + 1, capacity)) + + return ContainerAntidiffusiveFlux2D{uEltype}(antidiffusive_flux1_L, + antidiffusive_flux1_R, + antidiffusive_flux2_L, + antidiffusive_flux2_R, + _antidiffusive_flux1_L, + _antidiffusive_flux1_R, + _antidiffusive_flux2_L, + _antidiffusive_flux2_R) end -nvariables(fluxes::ContainerAntidiffusiveFlux2D) = size(fluxes.antidiffusive_flux1, 1) -nnodes(fluxes::ContainerAntidiffusiveFlux2D) = size(fluxes.antidiffusive_flux1, 3) +nvariables(fluxes::ContainerAntidiffusiveFlux2D) = size(fluxes.antidiffusive_flux1_L, 1) +nnodes(fluxes::ContainerAntidiffusiveFlux2D) = size(fluxes.antidiffusive_flux1_L, 3) # Only one-dimensional `Array`s are `resize!`able in Julia. # Hence, we use `Vector`s as internal storage and `resize!` @@ -1306,16 +1322,24 @@ function Base.resize!(fluxes::ContainerAntidiffusiveFlux2D, capacity) n_nodes = nnodes(fluxes) n_variables = nvariables(fluxes) - @unpack _antidiffusive_flux1, _antidiffusive_flux2 = fluxes - - resize!(_antidiffusive_flux1, n_variables * (n_nodes + 1) * n_nodes * capacity) - fluxes.antidiffusive_flux1 = unsafe_wrap(Array, pointer(_antidiffusive_flux1), - (n_variables, n_nodes + 1, n_nodes, - capacity)) - resize!(_antidiffusive_flux2, n_variables * n_nodes * (n_nodes + 1) * capacity) - fluxes.antidiffusive_flux2 = unsafe_wrap(Array, pointer(_antidiffusive_flux2), - (n_variables, n_nodes, n_nodes + 1, - capacity)) + @unpack _antidiffusive_flux1_L, _antidiffusive_flux2_L, _antidiffusive_flux1_R, _antidiffusive_flux2_R = fluxes + + resize!(_antidiffusive_flux1_L, n_variables * (n_nodes + 1) * n_nodes * capacity) + fluxes.antidiffusive_flux1_L = unsafe_wrap(Array, pointer(_antidiffusive_flux1_L), + (n_variables, n_nodes + 1, n_nodes, + capacity)) + resize!(_antidiffusive_flux1_R, n_variables * (n_nodes + 1) * n_nodes * capacity) + fluxes.antidiffusive_flux1_R = unsafe_wrap(Array, pointer(_antidiffusive_flux1_R), + (n_variables, n_nodes + 1, n_nodes, + capacity)) + resize!(_antidiffusive_flux2_L, n_variables * n_nodes * (n_nodes + 1) * capacity) + fluxes.antidiffusive_flux2_L = unsafe_wrap(Array, pointer(_antidiffusive_flux2_L), + (n_variables, n_nodes, n_nodes + 1, + capacity)) + resize!(_antidiffusive_flux2_R, n_variables * n_nodes * (n_nodes + 1) * capacity) + fluxes.antidiffusive_flux2_R = unsafe_wrap(Array, pointer(_antidiffusive_flux2_R), + (n_variables, n_nodes, n_nodes + 1, + capacity)) return nothing end @@ -1325,16 +1349,16 @@ mutable struct ContainerSubcellLimiterIDP2D{uEltype <: Real} alpha::Array{uEltype, 3} # [i, j, element] alpha1::Array{uEltype, 3} alpha2::Array{uEltype, 3} - variable_bounds::Vector{Array{uEltype, 3}} + variable_bounds::Dict{Symbol, Array{uEltype, 3}} # internal `resize!`able storage _alpha::Vector{uEltype} _alpha1::Vector{uEltype} _alpha2::Vector{uEltype} - _variable_bounds::Vector{Vector{uEltype}} + _variable_bounds::Dict{Symbol, Vector{uEltype}} end function ContainerSubcellLimiterIDP2D{uEltype}(capacity::Integer, n_nodes, - length) where {uEltype <: Real} + bound_keys) where {uEltype <: Real} nan_uEltype = convert(uEltype, NaN) # Initialize fields with defaults @@ -1345,12 +1369,12 @@ function ContainerSubcellLimiterIDP2D{uEltype}(capacity::Integer, n_nodes, _alpha2 = fill(nan_uEltype, n_nodes * (n_nodes + 1) * capacity) alpha2 = unsafe_wrap(Array, pointer(_alpha2), (n_nodes, n_nodes + 1, capacity)) - _variable_bounds = Vector{Vector{uEltype}}(undef, length) - variable_bounds = Vector{Array{uEltype, 3}}(undef, length) - for i in 1:length - _variable_bounds[i] = fill(nan_uEltype, n_nodes * n_nodes * capacity) - variable_bounds[i] = unsafe_wrap(Array, pointer(_variable_bounds[i]), - (n_nodes, n_nodes, capacity)) + _variable_bounds = Dict{Symbol, Vector{uEltype}}() + variable_bounds = Dict{Symbol, Array{uEltype, 3}}() + for key in bound_keys + _variable_bounds[key] = fill(nan_uEltype, n_nodes * n_nodes * capacity) + variable_bounds[key] = unsafe_wrap(Array, pointer(_variable_bounds[key]), + (n_nodes, n_nodes, capacity)) end return ContainerSubcellLimiterIDP2D{uEltype}(alpha, alpha1, alpha2, @@ -1369,9 +1393,10 @@ nnodes(container::ContainerSubcellLimiterIDP2D) = size(container.alpha, 1) function Base.resize!(container::ContainerSubcellLimiterIDP2D, capacity) n_nodes = nnodes(container) - @unpack _alpha, _alpha1, _alpha2 = container + (; _alpha, _alpha1, _alpha2) = container resize!(_alpha, n_nodes * n_nodes * capacity) container.alpha = unsafe_wrap(Array, pointer(_alpha), (n_nodes, n_nodes, capacity)) + container.alpha .= convert(eltype(container.alpha), NaN) resize!(_alpha1, (n_nodes + 1) * n_nodes * capacity) container.alpha1 = unsafe_wrap(Array, pointer(_alpha1), (n_nodes + 1, n_nodes, capacity)) @@ -1379,11 +1404,12 @@ function Base.resize!(container::ContainerSubcellLimiterIDP2D, capacity) container.alpha2 = unsafe_wrap(Array, pointer(_alpha2), (n_nodes, n_nodes + 1, capacity)) - @unpack _variable_bounds = container - for i in 1:length(_variable_bounds) - resize!(_variable_bounds[i], n_nodes * n_nodes * capacity) - container.variable_bounds[i] = unsafe_wrap(Array, pointer(_variable_bounds[i]), - (n_nodes, n_nodes, capacity)) + (; _variable_bounds) = container + for (key, _) in _variable_bounds + resize!(_variable_bounds[key], n_nodes * n_nodes * capacity) + container.variable_bounds[key] = unsafe_wrap(Array, + pointer(_variable_bounds[key]), + (n_nodes, n_nodes, capacity)) end return nothing diff --git a/src/solvers/dgsem_tree/containers_viscous.jl b/src/solvers/dgsem_tree/containers_viscous.jl new file mode 100644 index 00000000000..444f2cb7303 --- /dev/null +++ b/src/solvers/dgsem_tree/containers_viscous.jl @@ -0,0 +1,4 @@ +# Dimension-specific implementations +include("container_viscous_1d.jl") +include("container_viscous_2d.jl") +include("container_viscous_3d.jl") diff --git a/src/solvers/dgsem_tree/dg.jl b/src/solvers/dgsem_tree/dg.jl index 6e02bc1d94a..ef9a42b4c1a 100644 --- a/src/solvers/dgsem_tree/dg.jl +++ b/src/solvers/dgsem_tree/dg.jl @@ -54,6 +54,9 @@ include("containers.jl") # Dimension-agnostic parallel setup include("dg_parallel.jl") +# Helper structs for parabolic AMR +include("containers_viscous.jl") + # 1D DG implementation include("dg_1d.jl") include("dg_1d_parabolic.jl") diff --git a/src/solvers/dgsem_tree/dg_1d.jl b/src/solvers/dgsem_tree/dg_1d.jl index b5bb076f3b7..4a0747d1c09 100644 --- a/src/solvers/dgsem_tree/dg_1d.jl +++ b/src/solvers/dgsem_tree/dg_1d.jl @@ -144,6 +144,13 @@ function calc_volume_integral!(du, u, return nothing end +#= +`weak_form_kernel!` is only implemented for conserved terms as +non-conservative terms should always be discretized in conjunction with a flux-splitting scheme, +see `flux_differencing_kernel!`. +This treatment is required to achieve, e.g., entropy-stability or well-balancedness. +See also https://github.com/trixi-framework/Trixi.jl/issues/1671#issuecomment-1765644064 +=# @inline function weak_form_kernel!(du, u, element, mesh::Union{TreeMesh{1}, StructuredMesh{1}}, nonconservative_terms::False, equations, diff --git a/src/solvers/dgsem_tree/dg_1d_parabolic.jl b/src/solvers/dgsem_tree/dg_1d_parabolic.jl index c2aa75388c8..0017f9ca88e 100644 --- a/src/solvers/dgsem_tree/dg_1d_parabolic.jl +++ b/src/solvers/dgsem_tree/dg_1d_parabolic.jl @@ -17,7 +17,8 @@ function rhs_parabolic!(du, u, t, mesh::TreeMesh{1}, equations_parabolic::AbstractEquationsParabolic, initial_condition, boundary_conditions_parabolic, source_terms, dg::DG, parabolic_scheme, cache, cache_parabolic) - @unpack u_transformed, gradients, flux_viscous = cache_parabolic + @unpack viscous_container = cache_parabolic + @unpack u_transformed, gradients, flux_viscous = viscous_container # Convert conservative variables to a form more suitable for viscous flux calculations @trixi_timeit timer() "transform variables" begin @@ -105,12 +106,13 @@ end function transform_variables!(u_transformed, u, mesh::TreeMesh{1}, equations_parabolic::AbstractEquationsParabolic, dg::DG, parabolic_scheme, cache, cache_parabolic) + transformation = gradient_variable_transformation(equations_parabolic) + @threaded for element in eachelement(dg, cache) # Calculate volume terms in one element for i in eachnode(dg) u_node = get_node_vars(u, equations_parabolic, dg, i, element) - u_transformed_node = gradient_variable_transformation(equations_parabolic)(u_node, - equations_parabolic) + u_transformed_node = transformation(u_node, equations_parabolic) set_node_vars!(u_transformed, u_transformed_node, equations_parabolic, dg, i, element) end @@ -147,16 +149,18 @@ function prolong2interfaces!(cache_parabolic, flux_viscous, equations_parabolic::AbstractEquationsParabolic, surface_integral, dg::DG, cache) @unpack interfaces = cache_parabolic + @unpack neighbor_ids = interfaces + interfaces_u = interfaces.u @threaded for interface in eachinterface(dg, cache) - left_element = interfaces.neighbor_ids[1, interface] - right_element = interfaces.neighbor_ids[2, interface] + left_element = neighbor_ids[1, interface] + right_element = neighbor_ids[2, interface] # interface in x-direction for v in eachvariable(equations_parabolic) - # OBS! `interfaces.u` stores the interpolated *fluxes* and *not the solution*! - interfaces.u[1, v, interface] = flux_viscous[v, nnodes(dg), left_element] - interfaces.u[2, v, interface] = flux_viscous[v, 1, right_element] + # OBS! `interfaces_u` stores the interpolated *fluxes* and *not the solution*! + interfaces_u[1, v, interface] = flux_viscous[v, nnodes(dg), left_element] + interfaces_u[2, v, interface] = flux_viscous[v, 1, right_element] end end @@ -204,21 +208,22 @@ function prolong2boundaries!(cache_parabolic, flux_viscous, equations_parabolic::AbstractEquationsParabolic, surface_integral, dg::DG, cache) @unpack boundaries = cache_parabolic - @unpack neighbor_sides = boundaries + @unpack neighbor_sides, neighbor_ids = boundaries + boundaries_u = boundaries.u @threaded for boundary in eachboundary(dg, cache_parabolic) - element = boundaries.neighbor_ids[boundary] + element = neighbor_ids[boundary] if neighbor_sides[boundary] == 1 # element in -x direction of boundary for v in eachvariable(equations_parabolic) - # OBS! `boundaries.u` stores the interpolated *fluxes* and *not the solution*! - boundaries.u[1, v, boundary] = flux_viscous[v, nnodes(dg), element] + # OBS! `boundaries_u` stores the interpolated *fluxes* and *not the solution*! + boundaries_u[1, v, boundary] = flux_viscous[v, nnodes(dg), element] end else # Element in +x direction of boundary for v in eachvariable(equations_parabolic) - # OBS! `boundaries.u` stores the interpolated *fluxes* and *not the solution*! - boundaries.u[2, v, boundary] = flux_viscous[v, 1, element] + # OBS! `boundaries_u` stores the interpolated *fluxes* and *not the solution*! + boundaries_u[2, v, boundary] = flux_viscous[v, 1, element] end end end @@ -285,10 +290,8 @@ function calc_boundary_flux_gradients!(cache, t, 2, firsts[2], lasts[2]) end -function calc_boundary_flux_by_direction_gradient!(surface_flux_values::AbstractArray{ - <:Any, - 3 - }, +function calc_boundary_flux_by_direction_gradient!(surface_flux_values::AbstractArray{<:Any, + 3}, t, boundary_condition, equations_parabolic::AbstractEquationsParabolic, @@ -353,10 +356,8 @@ function calc_boundary_flux_divergence!(cache, t, dg, cache, 2, firsts[2], lasts[2]) end -function calc_boundary_flux_by_direction_divergence!(surface_flux_values::AbstractArray{ - <:Any, - 3 - }, +function calc_boundary_flux_by_direction_divergence!(surface_flux_values::AbstractArray{<:Any, + 3}, t, boundary_condition, equations_parabolic::AbstractEquationsParabolic, @@ -530,18 +531,15 @@ function create_cache_parabolic(mesh::TreeMesh{1}, elements = init_elements(leaf_cell_ids, mesh, equations_hyperbolic, dg.basis, RealT, uEltype) - n_vars = nvariables(equations_hyperbolic) - n_nodes = nnodes(elements) - n_elements = nelements(elements) - u_transformed = Array{uEltype}(undef, n_vars, n_nodes, n_elements) - gradients = similar(u_transformed) - flux_viscous = similar(u_transformed) - interfaces = init_interfaces(leaf_cell_ids, mesh, elements) boundaries = init_boundaries(leaf_cell_ids, mesh, elements) - cache = (; elements, interfaces, boundaries, gradients, flux_viscous, u_transformed) + viscous_container = init_viscous_container_1d(nvariables(equations_hyperbolic), + nnodes(elements), nelements(elements), + uEltype) + + cache = (; elements, interfaces, boundaries, viscous_container) return cache end @@ -552,8 +550,10 @@ end # where f(u) is the inviscid flux and g(u) is the viscous flux. function apply_jacobian_parabolic!(du, mesh::TreeMesh{1}, equations::AbstractEquationsParabolic, dg::DG, cache) + @unpack inverse_jacobian = cache.elements + @threaded for element in eachelement(dg, cache) - factor = cache.elements.inverse_jacobian[element] + factor = inverse_jacobian[element] for i in eachnode(dg) for v in eachvariable(equations) diff --git a/src/solvers/dgsem_tree/dg_2d.jl b/src/solvers/dgsem_tree/dg_2d.jl index c30d0a8e01a..547ed352ef3 100644 --- a/src/solvers/dgsem_tree/dg_2d.jl +++ b/src/solvers/dgsem_tree/dg_2d.jl @@ -194,6 +194,13 @@ function calc_volume_integral!(du, u, return nothing end +#= +`weak_form_kernel!` is only implemented for conserved terms as +non-conservative terms should always be discretized in conjunction with a flux-splitting scheme, +see `flux_differencing_kernel!`. +This treatment is required to achieve, e.g., entropy-stability or well-balancedness. +See also https://github.com/trixi-framework/Trixi.jl/issues/1671#issuecomment-1765644064 +=# @inline function weak_form_kernel!(du, u, element, mesh::TreeMesh{2}, nonconservative_terms::False, equations, @@ -384,8 +391,8 @@ end @inline function fv_kernel!(du, u, mesh::Union{TreeMesh{2}, StructuredMesh{2}, - UnstructuredMesh2D, P4estMesh{2}, T8codeMesh{2} - }, + UnstructuredMesh2D, P4estMesh{2}, + T8codeMesh{2}}, nonconservative_terms, equations, volume_flux_fv, dg::DGSEM, cache, element, alpha = true) @unpack fstar1_L_threaded, fstar1_R_threaded, fstar2_L_threaded, fstar2_R_threaded = cache diff --git a/src/solvers/dgsem_tree/dg_2d_parabolic.jl b/src/solvers/dgsem_tree/dg_2d_parabolic.jl index 0da25230380..3083ae30680 100644 --- a/src/solvers/dgsem_tree/dg_2d_parabolic.jl +++ b/src/solvers/dgsem_tree/dg_2d_parabolic.jl @@ -17,7 +17,8 @@ function rhs_parabolic!(du, u, t, mesh::TreeMesh{2}, equations_parabolic::AbstractEquationsParabolic, initial_condition, boundary_conditions_parabolic, source_terms, dg::DG, parabolic_scheme, cache, cache_parabolic) - (; u_transformed, gradients, flux_viscous) = cache_parabolic + @unpack viscous_container = cache_parabolic + @unpack u_transformed, gradients, flux_viscous = viscous_container # Convert conservative variables to a form more suitable for viscous flux calculations @trixi_timeit timer() "transform variables" begin @@ -118,12 +119,13 @@ end function transform_variables!(u_transformed, u, mesh::Union{TreeMesh{2}, P4estMesh{2}}, equations_parabolic::AbstractEquationsParabolic, dg::DG, parabolic_scheme, cache, cache_parabolic) + transformation = gradient_variable_transformation(equations_parabolic) + @threaded for element in eachelement(dg, cache) # Calculate volume terms in one element for j in eachnode(dg), i in eachnode(dg) u_node = get_node_vars(u, equations_parabolic, dg, i, j, element) - u_transformed_node = gradient_variable_transformation(equations_parabolic)(u_node, - equations_parabolic) + u_transformed_node = transformation(u_node, equations_parabolic) set_node_vars!(u_transformed, u_transformed_node, equations_parabolic, dg, i, j, element) end @@ -168,30 +170,31 @@ function prolong2interfaces!(cache_parabolic, flux_viscous, equations_parabolic::AbstractEquationsParabolic, surface_integral, dg::DG, cache) @unpack interfaces = cache_parabolic - @unpack orientations = interfaces + @unpack orientations, neighbor_ids = interfaces + interfaces_u = interfaces.u flux_viscous_x, flux_viscous_y = flux_viscous @threaded for interface in eachinterface(dg, cache) - left_element = interfaces.neighbor_ids[1, interface] - right_element = interfaces.neighbor_ids[2, interface] + left_element = neighbor_ids[1, interface] + right_element = neighbor_ids[2, interface] if orientations[interface] == 1 # interface in x-direction for j in eachnode(dg), v in eachvariable(equations_parabolic) - # OBS! `interfaces.u` stores the interpolated *fluxes* and *not the solution*! - interfaces.u[1, v, j, interface] = flux_viscous_x[v, nnodes(dg), j, + # OBS! `interfaces_u` stores the interpolated *fluxes* and *not the solution*! + interfaces_u[1, v, j, interface] = flux_viscous_x[v, nnodes(dg), j, left_element] - interfaces.u[2, v, j, interface] = flux_viscous_x[v, 1, j, + interfaces_u[2, v, j, interface] = flux_viscous_x[v, 1, j, right_element] end else # if orientations[interface] == 2 # interface in y-direction for i in eachnode(dg), v in eachvariable(equations_parabolic) - # OBS! `interfaces.u` stores the interpolated *fluxes* and *not the solution*! - interfaces.u[1, v, i, interface] = flux_viscous_y[v, i, nnodes(dg), + # OBS! `interfaces_u` stores the interpolated *fluxes* and *not the solution*! + interfaces_u[1, v, i, interface] = flux_viscous_y[v, i, nnodes(dg), left_element] - interfaces.u[2, v, i, interface] = flux_viscous_y[v, i, 1, + interfaces_u[2, v, i, interface] = flux_viscous_y[v, i, 1, right_element] end end @@ -244,25 +247,26 @@ function prolong2boundaries!(cache_parabolic, flux_viscous, equations_parabolic::AbstractEquationsParabolic, surface_integral, dg::DG, cache) @unpack boundaries = cache_parabolic - @unpack orientations, neighbor_sides = boundaries + @unpack orientations, neighbor_sides, neighbor_ids = boundaries + boundaries_u = boundaries.u flux_viscous_x, flux_viscous_y = flux_viscous @threaded for boundary in eachboundary(dg, cache_parabolic) - element = boundaries.neighbor_ids[boundary] + element = neighbor_ids[boundary] if orientations[boundary] == 1 # boundary in x-direction if neighbor_sides[boundary] == 1 # element in -x direction of boundary for l in eachnode(dg), v in eachvariable(equations_parabolic) - # OBS! `boundaries.u` stores the interpolated *fluxes* and *not the solution*! - boundaries.u[1, v, l, boundary] = flux_viscous_x[v, nnodes(dg), l, + # OBS! `boundaries_u` stores the interpolated *fluxes* and *not the solution*! + boundaries_u[1, v, l, boundary] = flux_viscous_x[v, nnodes(dg), l, element] end else # Element in +x direction of boundary for l in eachnode(dg), v in eachvariable(equations_parabolic) - # OBS! `boundaries.u` stores the interpolated *fluxes* and *not the solution*! - boundaries.u[2, v, l, boundary] = flux_viscous_x[v, 1, l, element] + # OBS! `boundaries_u` stores the interpolated *fluxes* and *not the solution*! + boundaries_u[2, v, l, boundary] = flux_viscous_x[v, 1, l, element] end end else # if orientations[boundary] == 2 @@ -270,15 +274,15 @@ function prolong2boundaries!(cache_parabolic, flux_viscous, if neighbor_sides[boundary] == 1 # element in -y direction of boundary for l in eachnode(dg), v in eachvariable(equations_parabolic) - # OBS! `boundaries.u` stores the interpolated *fluxes* and *not the solution*! - boundaries.u[1, v, l, boundary] = flux_viscous_y[v, l, nnodes(dg), + # OBS! `boundaries_u` stores the interpolated *fluxes* and *not the solution*! + boundaries_u[1, v, l, boundary] = flux_viscous_y[v, l, nnodes(dg), element] end else # element in +y direction of boundary for l in eachnode(dg), v in eachvariable(equations_parabolic) - # OBS! `boundaries.u` stores the interpolated *fluxes* and *not the solution*! - boundaries.u[2, v, l, boundary] = flux_viscous_y[v, l, 1, element] + # OBS! `boundaries_u` stores the interpolated *fluxes* and *not the solution*! + boundaries_u[2, v, l, boundary] = flux_viscous_y[v, l, 1, element] end end end @@ -287,7 +291,8 @@ function prolong2boundaries!(cache_parabolic, flux_viscous, return nothing end -function calc_viscous_fluxes!(flux_viscous, gradients, u_transformed, +function calc_viscous_fluxes!(flux_viscous, + gradients, u_transformed, mesh::Union{TreeMesh{2}, P4estMesh{2}}, equations_parabolic::AbstractEquationsParabolic, dg::DG, cache, cache_parabolic) @@ -379,10 +384,8 @@ function calc_boundary_flux_gradients!(cache, t, cache, 4, firsts[4], lasts[4]) end -function calc_boundary_flux_by_direction_gradient!(surface_flux_values::AbstractArray{ - <:Any, - 4 - }, +function calc_boundary_flux_by_direction_gradient!(surface_flux_values::AbstractArray{<:Any, + 4}, t, boundary_condition, equations_parabolic::AbstractEquationsParabolic, @@ -459,10 +462,8 @@ function calc_boundary_flux_divergence!(cache, t, dg, cache, 4, firsts[4], lasts[4]) end -function calc_boundary_flux_by_direction_divergence!(surface_flux_values::AbstractArray{ - <:Any, - 4 - }, +function calc_boundary_flux_by_direction_divergence!(surface_flux_values::AbstractArray{<:Any, + 4}, t, boundary_condition, equations_parabolic::AbstractEquationsParabolic, @@ -510,11 +511,16 @@ function calc_boundary_flux_by_direction_divergence!(surface_flux_values::Abstra return nothing end -function prolong2mortars!(cache, flux_viscous::Tuple{AbstractArray, AbstractArray}, +# `cache` is the hyperbolic cache, i.e., in particular not `cache_parabolic`. +# This is because mortar handling is done in the (hyperbolic) `cache`. +# Specialization `flux_viscous::Vector{Array{uEltype, 4}}` needed since +#`prolong2mortars!` in dg_2d.jl is used for both purely hyperbolic and +# hyperbolic-parabolic systems. +function prolong2mortars!(cache, flux_viscous::Vector{Array{uEltype, 4}}, mesh::TreeMesh{2}, equations_parabolic::AbstractEquationsParabolic, mortar_l2::LobattoLegendreMortarL2, surface_integral, - dg::DGSEM) + dg::DGSEM) where {uEltype <: Real} flux_viscous_x, flux_viscous_y = flux_viscous @threaded for mortar in eachmortar(dg, cache) large_element = cache.mortars.neighbor_ids[3, mortar] @@ -608,7 +614,7 @@ function prolong2mortars!(cache, flux_viscous::Tuple{AbstractArray, AbstractArra end # NOTE: Use analogy to "calc_mortar_flux!" for hyperbolic eqs with no nonconservative terms. -# Reasoning: "calc_interface_flux!" for parabolic part is implemented as the version for +# Reasoning: "calc_interface_flux!" for parabolic part is implemented as the version for # hyperbolic terms with conserved terms only, i.e., no nonconservative terms. function calc_mortar_flux!(surface_flux_values, mesh::TreeMesh{2}, @@ -906,21 +912,18 @@ function create_cache_parabolic(mesh::TreeMesh{2}, elements = init_elements(leaf_cell_ids, mesh, equations_hyperbolic, dg.basis, RealT, uEltype) - n_vars = nvariables(equations_hyperbolic) - n_nodes = nnodes(elements) - n_elements = nelements(elements) - u_transformed = Array{uEltype}(undef, n_vars, n_nodes, n_nodes, n_elements) - gradients = ntuple(_ -> similar(u_transformed), ndims(mesh)) - flux_viscous = ntuple(_ -> similar(u_transformed), ndims(mesh)) - interfaces = init_interfaces(leaf_cell_ids, mesh, elements) boundaries = init_boundaries(leaf_cell_ids, mesh, elements) # mortars = init_mortars(leaf_cell_ids, mesh, elements, dg.mortar) + viscous_container = init_viscous_container_2d(nvariables(equations_hyperbolic), + nnodes(elements), nelements(elements), + uEltype) + # cache = (; elements, interfaces, boundaries, mortars) - cache = (; elements, interfaces, boundaries, gradients, flux_viscous, u_transformed) + cache = (; elements, interfaces, boundaries, viscous_container) # Add specialized parts of the cache required to compute the mortars etc. # cache = (;cache..., create_cache(mesh, equations_parabolic, dg.mortar, uEltype)...) @@ -932,10 +935,12 @@ end # This is because the parabolic fluxes are assumed to be of the form # `du/dt + df/dx = dg/dx + source(x,t)`, # where f(u) is the inviscid flux and g(u) is the viscous flux. -function apply_jacobian_parabolic!(du, mesh::Union{TreeMesh{2}, P4estMesh{2}}, +function apply_jacobian_parabolic!(du, mesh::TreeMesh{2}, equations::AbstractEquationsParabolic, dg::DG, cache) + @unpack inverse_jacobian = cache.elements + @threaded for element in eachelement(dg, cache) - factor = cache.elements.inverse_jacobian[element] + factor = inverse_jacobian[element] for j in eachnode(dg), i in eachnode(dg) for v in eachvariable(equations) @@ -946,4 +951,22 @@ function apply_jacobian_parabolic!(du, mesh::Union{TreeMesh{2}, P4estMesh{2}}, return nothing end + +function apply_jacobian_parabolic!(du, mesh::P4estMesh{2}, + equations::AbstractEquationsParabolic, + dg::DG, cache) + @unpack inverse_jacobian = cache.elements + + @threaded for element in eachelement(dg, cache) + for j in eachnode(dg), i in eachnode(dg) + factor = inverse_jacobian[i, j, element] + + for v in eachvariable(equations) + du[v, i, j, element] *= factor + end + end + end + + return nothing +end end # @muladd diff --git a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl index 70ff346740d..2fc62f548d2 100644 --- a/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl +++ b/src/solvers/dgsem_tree/dg_2d_subcell_limiters.jl @@ -14,20 +14,45 @@ function create_cache(mesh::TreeMesh{2}, equations, A3dp1_x = Array{uEltype, 3} A3dp1_y = Array{uEltype, 3} A3d = Array{uEltype, 3} - - fhat1_threaded = A3dp1_x[A3dp1_x(undef, nvariables(equations), nnodes(dg) + 1, - nnodes(dg)) for _ in 1:Threads.nthreads()] - fhat2_threaded = A3dp1_y[A3dp1_y(undef, nvariables(equations), nnodes(dg), - nnodes(dg) + 1) for _ in 1:Threads.nthreads()] + A4d = Array{uEltype, 4} + + fhat1_L_threaded = A3dp1_x[A3dp1_x(undef, nvariables(equations), nnodes(dg) + 1, + nnodes(dg)) for _ in 1:Threads.nthreads()] + fhat2_L_threaded = A3dp1_y[A3dp1_y(undef, nvariables(equations), nnodes(dg), + nnodes(dg) + 1) for _ in 1:Threads.nthreads()] + fhat1_R_threaded = A3dp1_x[A3dp1_x(undef, nvariables(equations), nnodes(dg) + 1, + nnodes(dg)) for _ in 1:Threads.nthreads()] + fhat2_R_threaded = A3dp1_y[A3dp1_y(undef, nvariables(equations), nnodes(dg), + nnodes(dg) + 1) for _ in 1:Threads.nthreads()] flux_temp_threaded = A3d[A3d(undef, nvariables(equations), nnodes(dg), nnodes(dg)) for _ in 1:Threads.nthreads()] - + fhat_temp_threaded = A3d[A3d(undef, nvariables(equations), nnodes(dg), + nnodes(dg)) + for _ in 1:Threads.nthreads()] antidiffusive_fluxes = Trixi.ContainerAntidiffusiveFlux2D{uEltype}(0, nvariables(equations), nnodes(dg)) - return (; cache..., antidiffusive_fluxes, fhat1_threaded, fhat2_threaded, - flux_temp_threaded) + if have_nonconservative_terms(equations) == true + flux_nonconservative_temp_threaded = A4d[A4d(undef, nvariables(equations), + n_nonconservative_terms(equations), + nnodes(dg), nnodes(dg)) + for _ in 1:Threads.nthreads()] + fhat_nonconservative_temp_threaded = A4d[A4d(undef, nvariables(equations), + n_nonconservative_terms(equations), + nnodes(dg), nnodes(dg)) + for _ in 1:Threads.nthreads()] + phi_threaded = A4d[A4d(undef, nvariables(equations), + n_nonconservative_terms(equations), + nnodes(dg), nnodes(dg)) + for _ in 1:Threads.nthreads()] + cache = (; cache..., flux_nonconservative_temp_threaded, + fhat_nonconservative_temp_threaded, phi_threaded) + end + + return (; cache..., antidiffusive_fluxes, + fhat1_L_threaded, fhat2_L_threaded, fhat1_R_threaded, fhat2_R_threaded, + flux_temp_threaded, fhat_temp_threaded) end function calc_volume_integral!(du, u, @@ -47,19 +72,22 @@ end @inline function subcell_limiting_kernel!(du, u, element, mesh::TreeMesh{2}, - nonconservative_terms::False, equations, + nonconservative_terms, equations, volume_integral, limiter::SubcellLimiterIDP, dg::DGSEM, cache) @unpack inverse_weights = dg.basis @unpack volume_flux_dg, volume_flux_fv = volume_integral # high-order DG fluxes - @unpack fhat1_threaded, fhat2_threaded = cache + @unpack fhat1_L_threaded, fhat1_R_threaded, fhat2_L_threaded, fhat2_R_threaded = cache - fhat1 = fhat1_threaded[Threads.threadid()] - fhat2 = fhat2_threaded[Threads.threadid()] - calcflux_fhat!(fhat1, fhat2, u, mesh, - nonconservative_terms, equations, volume_flux_dg, dg, element, cache) + fhat1_L = fhat1_L_threaded[Threads.threadid()] + fhat1_R = fhat1_R_threaded[Threads.threadid()] + fhat2_L = fhat2_L_threaded[Threads.threadid()] + fhat2_R = fhat2_R_threaded[Threads.threadid()] + calcflux_fhat!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, u, mesh, + nonconservative_terms, equations, volume_flux_dg, dg, element, + cache) # low-order FV fluxes @unpack fstar1_L_threaded, fstar1_R_threaded, fstar2_L_threaded, fstar2_R_threaded = cache @@ -69,12 +97,14 @@ end fstar1_R = fstar1_R_threaded[Threads.threadid()] fstar2_R = fstar2_R_threaded[Threads.threadid()] calcflux_fv!(fstar1_L, fstar1_R, fstar2_L, fstar2_R, u, mesh, - nonconservative_terms, equations, volume_flux_fv, dg, element, cache) + nonconservative_terms, equations, volume_flux_fv, dg, element, + cache) # antidiffusive flux - calcflux_antidiffusive!(fhat1, fhat2, fstar1_L, fstar2_L, u, mesh, - nonconservative_terms, equations, limiter, dg, element, - cache) + calcflux_antidiffusive!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, + fstar1_L, fstar1_R, fstar2_L, fstar2_R, + u, mesh, nonconservative_terms, equations, limiter, dg, + element, cache) # Calculate volume integral contribution of low-order FV flux for j in eachnode(dg), i in eachnode(dg) @@ -93,7 +123,7 @@ end # (**without non-conservative terms**). # # See also `flux_differencing_kernel!`. -@inline function calcflux_fhat!(fhat1, fhat2, u, +@inline function calcflux_fhat!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, u, mesh::TreeMesh{2}, nonconservative_terms::False, equations, volume_flux, dg::DGSEM, element, cache) @@ -132,11 +162,14 @@ end end # FV-form flux `fhat` in x direction - fhat1[:, 1, :] .= zero(eltype(fhat1)) - fhat1[:, nnodes(dg) + 1, :] .= zero(eltype(fhat1)) + fhat1_L[:, 1, :] .= zero(eltype(fhat1_L)) + fhat1_L[:, nnodes(dg) + 1, :] .= zero(eltype(fhat1_L)) + fhat1_R[:, 1, :] .= zero(eltype(fhat1_R)) + fhat1_R[:, nnodes(dg) + 1, :] .= zero(eltype(fhat1_R)) for j in eachnode(dg), i in 1:(nnodes(dg) - 1), v in eachvariable(equations) - fhat1[v, i + 1, j] = fhat1[v, i, j] + weights[i] * flux_temp[v, i, j] + fhat1_L[v, i + 1, j] = fhat1_L[v, i, j] + weights[i] * flux_temp[v, i, j] + fhat1_R[v, i + 1, j] = fhat1_L[v, i + 1, j] end # Split form volume flux in orientation 2: y direction @@ -155,39 +188,296 @@ end end # FV-form flux `fhat` in y direction - fhat2[:, :, 1] .= zero(eltype(fhat2)) - fhat2[:, :, nnodes(dg) + 1] .= zero(eltype(fhat2)) + fhat2_L[:, :, 1] .= zero(eltype(fhat2_L)) + fhat2_L[:, :, nnodes(dg) + 1] .= zero(eltype(fhat2_L)) + fhat2_R[:, :, 1] .= zero(eltype(fhat2_R)) + fhat2_R[:, :, nnodes(dg) + 1] .= zero(eltype(fhat2_R)) for j in 1:(nnodes(dg) - 1), i in eachnode(dg), v in eachvariable(equations) - fhat2[v, i, j + 1] = fhat2[v, i, j] + weights[j] * flux_temp[v, i, j] + fhat2_L[v, i, j + 1] = fhat2_L[v, i, j] + weights[j] * flux_temp[v, i, j] + fhat2_R[v, i, j + 1] = fhat2_L[v, i, j + 1] end return nothing end -# Calculate the antidiffusive flux `antidiffusive_flux` as the subtraction between `fhat` and `fstar`. -@inline function calcflux_antidiffusive!(fhat1, fhat2, fstar1, fstar2, u, mesh, - nonconservative_terms, equations, +# Calculate the DG staggered volume fluxes `fhat` in subcell FV-form inside the element +# (**with non-conservative terms**). +# +# See also `flux_differencing_kernel!`. +# +# The calculation of the non-conservative staggered "fluxes" requires non-conservative +# terms that can be written as a product of local and a symmetric contributions. 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. +# +@inline function calcflux_fhat!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, u, + mesh::TreeMesh{2}, nonconservative_terms::True, + equations, + volume_flux, dg::DGSEM, element, cache) + @unpack weights, derivative_split = dg.basis + @unpack flux_temp_threaded, flux_nonconservative_temp_threaded = cache + @unpack fhat_temp_threaded, fhat_nonconservative_temp_threaded, phi_threaded = cache + + volume_flux_cons, volume_flux_noncons = volume_flux + + flux_temp = flux_temp_threaded[Threads.threadid()] + flux_noncons_temp = flux_nonconservative_temp_threaded[Threads.threadid()] + + fhat_temp = fhat_temp_threaded[Threads.threadid()] + fhat_noncons_temp = fhat_nonconservative_temp_threaded[Threads.threadid()] + phi = phi_threaded[Threads.threadid()] + + # The FV-form fluxes are calculated in a recursive manner, i.e.: + # fhat_(0,1) = w_0 * FVol_0, + # fhat_(j,j+1) = fhat_(j-1,j) + w_j * FVol_j, for j=1,...,N-1, + # with the split form volume fluxes FVol_j = -2 * sum_i=0^N D_ji f*_(j,i). + + # To use the symmetry of the `volume_flux`, the split form volume flux is precalculated + # like in `calc_volume_integral!` for the `VolumeIntegralFluxDifferencing` + # and saved in in `flux_temp`. + + # Split form volume flux in orientation 1: x direction + flux_temp .= zero(eltype(flux_temp)) + flux_noncons_temp .= zero(eltype(flux_noncons_temp)) + + for j in eachnode(dg), i in eachnode(dg) + u_node = get_node_vars(u, equations, dg, i, j, element) + + # All diagonal entries of `derivative_split` are zero. Thus, we can skip + # the computation of the diagonal terms. In addition, we use the symmetry + # of `volume_flux_cons` and `volume_flux_noncons` to save half of the possible two-point flux + # computations. + for ii in (i + 1):nnodes(dg) + u_node_ii = get_node_vars(u, equations, dg, ii, j, element) + flux1 = volume_flux_cons(u_node, u_node_ii, 1, equations) + multiply_add_to_node_vars!(flux_temp, derivative_split[i, ii], flux1, + equations, dg, i, j) + multiply_add_to_node_vars!(flux_temp, derivative_split[ii, i], flux1, + equations, dg, ii, j) + for noncons in 1:n_nonconservative_terms(equations) + # We multiply by 0.5 because that is done in other parts of Trixi + flux1_noncons = volume_flux_noncons(u_node, u_node_ii, 1, equations, + NonConservativeSymmetric(), noncons) + multiply_add_to_node_vars!(flux_noncons_temp, + 0.5 * derivative_split[i, ii], + flux1_noncons, + equations, dg, noncons, i, j) + multiply_add_to_node_vars!(flux_noncons_temp, + 0.5 * derivative_split[ii, i], + flux1_noncons, + equations, dg, noncons, ii, j) + end + end + end + + # FV-form flux `fhat` in x direction + fhat1_L[:, 1, :] .= zero(eltype(fhat1_L)) + fhat1_L[:, nnodes(dg) + 1, :] .= zero(eltype(fhat1_L)) + fhat1_R[:, 1, :] .= zero(eltype(fhat1_R)) + fhat1_R[:, nnodes(dg) + 1, :] .= zero(eltype(fhat1_R)) + + fhat_temp[:, 1, :] .= zero(eltype(fhat1_L)) + fhat_noncons_temp[:, :, 1, :] .= zero(eltype(fhat1_L)) + + # Compute local contribution to non-conservative flux + for j in eachnode(dg), i in eachnode(dg) + u_local = get_node_vars(u, equations, dg, i, j, element) + for noncons in 1:n_nonconservative_terms(equations) + set_node_vars!(phi, + volume_flux_noncons(u_local, 1, equations, + NonConservativeLocal(), noncons), + equations, dg, noncons, i, j) + end + end + + for j in eachnode(dg), i in 1:(nnodes(dg) - 1) + # Conservative part + for v in eachvariable(equations) + value = fhat_temp[v, i, j] + weights[i] * flux_temp[v, i, j] + fhat_temp[v, i + 1, j] = value + fhat1_L[v, i + 1, j] = value + fhat1_R[v, i + 1, j] = value + end + # Nonconservative part + for noncons in 1:n_nonconservative_terms(equations), + v in eachvariable(equations) + + value = fhat_noncons_temp[v, noncons, i, j] + + weights[i] * flux_noncons_temp[v, noncons, i, j] + fhat_noncons_temp[v, noncons, i + 1, j] = value + + fhat1_L[v, i + 1, j] = fhat1_L[v, i + 1, j] + phi[v, noncons, i, j] * value + fhat1_R[v, i + 1, j] = fhat1_R[v, i + 1, j] + + phi[v, noncons, i + 1, j] * value + end + end + + # Split form volume flux in orientation 2: y direction + flux_temp .= zero(eltype(flux_temp)) + flux_noncons_temp .= zero(eltype(flux_noncons_temp)) + + for j in eachnode(dg), i in eachnode(dg) + u_node = get_node_vars(u, equations, dg, i, j, element) + for jj in (j + 1):nnodes(dg) + u_node_jj = get_node_vars(u, equations, dg, i, jj, element) + flux2 = volume_flux_cons(u_node, u_node_jj, 2, equations) + multiply_add_to_node_vars!(flux_temp, derivative_split[j, jj], flux2, + equations, dg, i, j) + multiply_add_to_node_vars!(flux_temp, derivative_split[jj, j], flux2, + equations, dg, i, jj) + for noncons in 1:n_nonconservative_terms(equations) + # We multiply by 0.5 because that is done in other parts of Trixi + flux2_noncons = volume_flux_noncons(u_node, u_node_jj, 2, equations, + NonConservativeSymmetric(), noncons) + multiply_add_to_node_vars!(flux_noncons_temp, + 0.5 * derivative_split[j, jj], + flux2_noncons, + equations, dg, noncons, i, j) + multiply_add_to_node_vars!(flux_noncons_temp, + 0.5 * derivative_split[jj, j], + flux2_noncons, + equations, dg, noncons, i, jj) + end + end + end + + # FV-form flux `fhat` in y direction + fhat2_L[:, :, 1] .= zero(eltype(fhat2_L)) + fhat2_L[:, :, nnodes(dg) + 1] .= zero(eltype(fhat2_L)) + fhat2_R[:, :, 1] .= zero(eltype(fhat2_R)) + fhat2_R[:, :, nnodes(dg) + 1] .= zero(eltype(fhat2_R)) + + fhat_temp[:, :, 1] .= zero(eltype(fhat1_L)) + fhat_noncons_temp[:, :, :, 1] .= zero(eltype(fhat1_L)) + + # Compute local contribution to non-conservative flux + for j in eachnode(dg), i in eachnode(dg) + u_local = get_node_vars(u, equations, dg, i, j, element) + for noncons in 1:n_nonconservative_terms(equations) + set_node_vars!(phi, + volume_flux_noncons(u_local, 2, equations, + NonConservativeLocal(), noncons), + equations, dg, noncons, i, j) + end + end + + for j in 1:(nnodes(dg) - 1), i in eachnode(dg) + # Conservative part + for v in eachvariable(equations) + value = fhat_temp[v, i, j] + weights[j] * flux_temp[v, i, j] + fhat_temp[v, i, j + 1] = value + fhat2_L[v, i, j + 1] = value + fhat2_R[v, i, j + 1] = value + end + # Nonconservative part + for noncons in 1:n_nonconservative_terms(equations), + v in eachvariable(equations) + + value = fhat_noncons_temp[v, noncons, i, j] + + weights[j] * flux_noncons_temp[v, noncons, i, j] + fhat_noncons_temp[v, noncons, i, j + 1] = value + + fhat2_L[v, i, j + 1] = fhat2_L[v, i, j + 1] + phi[v, noncons, i, j] * value + fhat2_R[v, i, j + 1] = fhat2_R[v, i, j + 1] + + phi[v, noncons, i, j + 1] * value + end + end + + return nothing +end + +# Calculate the antidiffusive flux `antidiffusive_flux` as the subtraction between `fhat` and `fstar` for conservative systems. +@inline function calcflux_antidiffusive!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, + fstar1_L, fstar1_R, fstar2_L, fstar2_R, + u, mesh, + nonconservative_terms::False, equations, limiter::SubcellLimiterIDP, dg, element, cache) - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.antidiffusive_fluxes + @unpack antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R = cache.antidiffusive_fluxes for j in eachnode(dg), i in 2:nnodes(dg) for v in eachvariable(equations) - antidiffusive_flux1[v, i, j, element] = fhat1[v, i, j] - fstar1[v, i, j] + antidiffusive_flux1_L[v, i, j, element] = fhat1_L[v, i, j] - + fstar1_L[v, i, j] + antidiffusive_flux1_R[v, i, j, element] = antidiffusive_flux1_L[v, i, j, + element] end end for j in 2:nnodes(dg), i in eachnode(dg) for v in eachvariable(equations) - antidiffusive_flux2[v, i, j, element] = fhat2[v, i, j] - fstar2[v, i, j] + antidiffusive_flux2_L[v, i, j, element] = fhat2_L[v, i, j] - + fstar2_L[v, i, j] + antidiffusive_flux2_R[v, i, j, element] = antidiffusive_flux2_L[v, i, j, + element] end end - antidiffusive_flux1[:, 1, :, element] .= zero(eltype(antidiffusive_flux1)) - antidiffusive_flux1[:, nnodes(dg) + 1, :, element] .= zero(eltype(antidiffusive_flux1)) + antidiffusive_flux1_L[:, 1, :, element] .= zero(eltype(antidiffusive_flux1_L)) + antidiffusive_flux1_L[:, nnodes(dg) + 1, :, element] .= zero(eltype(antidiffusive_flux1_L)) + antidiffusive_flux1_R[:, 1, :, element] .= zero(eltype(antidiffusive_flux1_R)) + antidiffusive_flux1_R[:, nnodes(dg) + 1, :, element] .= zero(eltype(antidiffusive_flux1_R)) - antidiffusive_flux2[:, :, 1, element] .= zero(eltype(antidiffusive_flux2)) - antidiffusive_flux2[:, :, nnodes(dg) + 1, element] .= zero(eltype(antidiffusive_flux2)) + antidiffusive_flux2_L[:, :, 1, element] .= zero(eltype(antidiffusive_flux2_L)) + antidiffusive_flux2_L[:, :, nnodes(dg) + 1, element] .= zero(eltype(antidiffusive_flux2_L)) + antidiffusive_flux2_R[:, :, 1, element] .= zero(eltype(antidiffusive_flux2_R)) + antidiffusive_flux2_R[:, :, nnodes(dg) + 1, element] .= zero(eltype(antidiffusive_flux2_R)) return nothing end + +# Calculate the antidiffusive flux `antidiffusive_flux` as the subtraction between `fhat` and `fstar` for conservative systems. +@inline function calcflux_antidiffusive!(fhat1_L, fhat1_R, fhat2_L, fhat2_R, + fstar1_L, fstar1_R, fstar2_L, fstar2_R, + u, mesh, + nonconservative_terms::True, equations, + limiter::SubcellLimiterIDP, dg, element, cache) + @unpack antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R = cache.antidiffusive_fluxes + + for j in eachnode(dg), i in 2:nnodes(dg) + for v in eachvariable(equations) + antidiffusive_flux1_L[v, i, j, element] = fhat1_L[v, i, j] - + fstar1_L[v, i, j] + antidiffusive_flux1_R[v, i, j, element] = fhat1_R[v, i, j] - + fstar1_R[v, i, j] + end + end + for j in 2:nnodes(dg), i in eachnode(dg) + for v in eachvariable(equations) + antidiffusive_flux2_L[v, i, j, element] = fhat2_L[v, i, j] - + fstar2_L[v, i, j] + antidiffusive_flux2_R[v, i, j, element] = fhat2_R[v, i, j] - + fstar2_R[v, i, j] + end + end + + antidiffusive_flux1_L[:, 1, :, element] .= zero(eltype(antidiffusive_flux1_L)) + antidiffusive_flux1_L[:, nnodes(dg) + 1, :, element] .= zero(eltype(antidiffusive_flux1_L)) + antidiffusive_flux1_R[:, 1, :, element] .= zero(eltype(antidiffusive_flux1_R)) + antidiffusive_flux1_R[:, nnodes(dg) + 1, :, element] .= zero(eltype(antidiffusive_flux1_R)) + + antidiffusive_flux2_L[:, :, 1, element] .= zero(eltype(antidiffusive_flux2_L)) + antidiffusive_flux2_L[:, :, nnodes(dg) + 1, element] .= zero(eltype(antidiffusive_flux2_L)) + antidiffusive_flux2_R[:, :, 1, element] .= zero(eltype(antidiffusive_flux2_R)) + antidiffusive_flux2_R[:, :, nnodes(dg) + 1, element] .= zero(eltype(antidiffusive_flux2_R)) + + return nothing +end + +""" + get_boundary_outer_state(boundary_condition::BoundaryConditionDirichlet, + cache, t, equations, dg, indices...) +For subcell limiting, the calculation of local bounds for non-periodic domains require the boundary +outer state. This function returns the boundary value at time `t` and for node with spatial +indices `indices`. +""" +@inline function get_boundary_outer_state(boundary_condition::BoundaryConditionDirichlet, + cache, t, equations, dg, indices...) + (; node_coordinates) = cache.elements + + x = get_node_coords(node_coordinates, equations, dg, indices...) + u_outer = boundary_condition.boundary_value_function(x, t, equations) + + return u_outer +end end # @muladd diff --git a/src/solvers/dgsem_tree/dg_3d.jl b/src/solvers/dgsem_tree/dg_3d.jl index e84d0c53ade..02ff338e912 100644 --- a/src/solvers/dgsem_tree/dg_3d.jl +++ b/src/solvers/dgsem_tree/dg_3d.jl @@ -226,6 +226,13 @@ function calc_volume_integral!(du, u, return nothing end +#= +`weak_form_kernel!` is only implemented for conserved terms as +non-conservative terms should always be discretized in conjunction with a flux-splitting scheme, +see `flux_differencing_kernel!`. +This treatment is required to achieve, e.g., entropy-stability or well-balancedness. +See also https://github.com/trixi-framework/Trixi.jl/issues/1671#issuecomment-1765644064 +=# @inline function weak_form_kernel!(du, u, element, mesh::TreeMesh{3}, nonconservative_terms::False, equations, diff --git a/src/solvers/dgsem_tree/dg_3d_parabolic.jl b/src/solvers/dgsem_tree/dg_3d_parabolic.jl index 2745d312b37..9ad28c6aa8e 100644 --- a/src/solvers/dgsem_tree/dg_3d_parabolic.jl +++ b/src/solvers/dgsem_tree/dg_3d_parabolic.jl @@ -17,7 +17,8 @@ function rhs_parabolic!(du, u, t, mesh::TreeMesh{3}, equations_parabolic::AbstractEquationsParabolic, initial_condition, boundary_conditions_parabolic, source_terms, dg::DG, parabolic_scheme, cache, cache_parabolic) - @unpack u_transformed, gradients, flux_viscous = cache_parabolic + @unpack viscous_container = cache_parabolic + @unpack u_transformed, gradients, flux_viscous = viscous_container # Convert conservative variables to a form more suitable for viscous flux calculations @trixi_timeit timer() "transform variables" begin @@ -118,12 +119,13 @@ end function transform_variables!(u_transformed, u, mesh::Union{TreeMesh{3}, P4estMesh{3}}, equations_parabolic::AbstractEquationsParabolic, dg::DG, parabolic_scheme, cache, cache_parabolic) + transformation = gradient_variable_transformation(equations_parabolic) + @threaded for element in eachelement(dg, cache) # Calculate volume terms in one element for k in eachnode(dg), j in eachnode(dg), i in eachnode(dg) u_node = get_node_vars(u, equations_parabolic, dg, i, j, k, element) - u_transformed_node = gradient_variable_transformation(equations_parabolic)(u_node, - equations_parabolic) + u_transformed_node = transformation(u_node, equations_parabolic) set_node_vars!(u_transformed, u_transformed_node, equations_parabolic, dg, i, j, k, element) end @@ -175,43 +177,44 @@ function prolong2interfaces!(cache_parabolic, flux_viscous, equations_parabolic::AbstractEquationsParabolic, surface_integral, dg::DG, cache) @unpack interfaces = cache_parabolic - @unpack orientations = interfaces + @unpack orientations, neighbor_ids = interfaces + interfaces_u = interfaces.u flux_viscous_x, flux_viscous_y, flux_viscous_z = flux_viscous @threaded for interface in eachinterface(dg, cache) - left_element = interfaces.neighbor_ids[1, interface] - right_element = interfaces.neighbor_ids[2, interface] + left_element = neighbor_ids[1, interface] + right_element = neighbor_ids[2, interface] if orientations[interface] == 1 # interface in x-direction for k in eachnode(dg), j in eachnode(dg), v in eachvariable(equations_parabolic) - # OBS! `interfaces.u` stores the interpolated *fluxes* and *not the solution*! - interfaces.u[1, v, j, k, interface] = flux_viscous_x[v, nnodes(dg), j, + # OBS! `interfaces_u` stores the interpolated *fluxes* and *not the solution*! + interfaces_u[1, v, j, k, interface] = flux_viscous_x[v, nnodes(dg), j, k, left_element] - interfaces.u[2, v, j, k, interface] = flux_viscous_x[v, 1, j, k, + interfaces_u[2, v, j, k, interface] = flux_viscous_x[v, 1, j, k, right_element] end elseif orientations[interface] == 2 # interface in y-direction for k in eachnode(dg), i in eachnode(dg), v in eachvariable(equations_parabolic) - # OBS! `interfaces.u` stores the interpolated *fluxes* and *not the solution*! - interfaces.u[1, v, i, k, interface] = flux_viscous_y[v, i, nnodes(dg), + # OBS! `interfaces_u` stores the interpolated *fluxes* and *not the solution*! + interfaces_u[1, v, i, k, interface] = flux_viscous_y[v, i, nnodes(dg), k, left_element] - interfaces.u[2, v, i, k, interface] = flux_viscous_y[v, i, 1, k, + interfaces_u[2, v, i, k, interface] = flux_viscous_y[v, i, 1, k, right_element] end else # if orientations[interface] == 3 # interface in z-direction for j in eachnode(dg), i in eachnode(dg), v in eachvariable(equations_parabolic) - # OBS! `interfaces.u` stores the interpolated *fluxes* and *not the solution*! - interfaces.u[1, v, i, j, interface] = flux_viscous_z[v, i, j, + # OBS! `interfaces_u` stores the interpolated *fluxes* and *not the solution*! + interfaces_u[1, v, i, j, interface] = flux_viscous_z[v, i, j, nnodes(dg), left_element] - interfaces.u[2, v, i, j, interface] = flux_viscous_z[v, i, j, 1, + interfaces_u[2, v, i, j, interface] = flux_viscous_z[v, i, j, 1, right_element] end end @@ -265,11 +268,12 @@ function prolong2boundaries!(cache_parabolic, flux_viscous, equations_parabolic::AbstractEquationsParabolic, surface_integral, dg::DG, cache) @unpack boundaries = cache_parabolic - @unpack orientations, neighbor_sides = boundaries + @unpack orientations, neighbor_sides, neighbor_ids = boundaries + boundaries_u = boundaries.u flux_viscous_x, flux_viscous_y, flux_viscous_z = flux_viscous @threaded for boundary in eachboundary(dg, cache_parabolic) - element = boundaries.neighbor_ids[boundary] + element = neighbor_ids[boundary] if orientations[boundary] == 1 # boundary in x-direction @@ -277,15 +281,15 @@ function prolong2boundaries!(cache_parabolic, flux_viscous, # element in -x direction of boundary for k in eachnode(dg), j in eachnode(dg), v in eachvariable(equations_parabolic) - # OBS! `boundaries.u` stores the interpolated *fluxes* and *not the solution*! - boundaries.u[1, v, j, k, boundary] = flux_viscous_x[v, nnodes(dg), + # OBS! `boundaries_u` stores the interpolated *fluxes* and *not the solution*! + boundaries_u[1, v, j, k, boundary] = flux_viscous_x[v, nnodes(dg), j, k, element] end else # Element in +x direction of boundary for k in eachnode(dg), j in eachnode(dg), v in eachvariable(equations_parabolic) - # OBS! `boundaries.u` stores the interpolated *fluxes* and *not the solution*! - boundaries.u[2, v, j, k, boundary] = flux_viscous_x[v, 1, j, k, + # OBS! `boundaries_u` stores the interpolated *fluxes* and *not the solution*! + boundaries_u[2, v, j, k, boundary] = flux_viscous_x[v, 1, j, k, element] end end @@ -295,8 +299,8 @@ function prolong2boundaries!(cache_parabolic, flux_viscous, # element in -y direction of boundary for k in eachnode(dg), i in eachnode(dg), v in eachvariable(equations_parabolic) - # OBS! `boundaries.u` stores the interpolated *fluxes* and *not the solution*! - boundaries.u[1, v, i, k, boundary] = flux_viscous_y[v, i, + # OBS! `boundaries_u` stores the interpolated *fluxes* and *not the solution*! + boundaries_u[1, v, i, k, boundary] = flux_viscous_y[v, i, nnodes(dg), k, element] end @@ -304,8 +308,8 @@ function prolong2boundaries!(cache_parabolic, flux_viscous, # element in +y direction of boundary for k in eachnode(dg), i in eachnode(dg), v in eachvariable(equations_parabolic) - # OBS! `boundaries.u` stores the interpolated *fluxes* and *not the solution*! - boundaries.u[2, v, i, k, boundary] = flux_viscous_y[v, i, 1, k, + # OBS! `boundaries_u` stores the interpolated *fluxes* and *not the solution*! + boundaries_u[2, v, i, k, boundary] = flux_viscous_y[v, i, 1, k, element] end end @@ -315,8 +319,8 @@ function prolong2boundaries!(cache_parabolic, flux_viscous, # element in -z direction of boundary for j in eachnode(dg), i in eachnode(dg), v in eachvariable(equations_parabolic) - # OBS! `boundaries.u` stores the interpolated *fluxes* and *not the solution*! - boundaries.u[1, v, i, j, boundary] = flux_viscous_z[v, i, j, + # OBS! `boundaries_u` stores the interpolated *fluxes* and *not the solution*! + boundaries_u[1, v, i, j, boundary] = flux_viscous_z[v, i, j, nnodes(dg), element] end @@ -324,8 +328,8 @@ function prolong2boundaries!(cache_parabolic, flux_viscous, # element in +z direction of boundary for j in eachnode(dg), i in eachnode(dg), v in eachvariable(equations_parabolic) - # OBS! `boundaries.u` stores the interpolated *fluxes* and *not the solution*! - boundaries.u[2, v, i, j, boundary] = flux_viscous_z[v, i, j, 1, + # OBS! `boundaries_u` stores the interpolated *fluxes* and *not the solution*! + boundaries_u[2, v, i, j, boundary] = flux_viscous_z[v, i, j, 1, element] end end @@ -335,7 +339,8 @@ function prolong2boundaries!(cache_parabolic, flux_viscous, return nothing end -function calc_viscous_fluxes!(flux_viscous, gradients, u_transformed, +function calc_viscous_fluxes!(flux_viscous, + gradients, u_transformed, mesh::Union{TreeMesh{3}, P4estMesh{3}}, equations_parabolic::AbstractEquationsParabolic, dg::DG, cache, cache_parabolic) @@ -449,10 +454,8 @@ function calc_boundary_flux_gradients!(cache, t, 6, firsts[6], lasts[6]) end -function calc_boundary_flux_by_direction_gradient!(surface_flux_values::AbstractArray{ - <:Any, - 5 - }, +function calc_boundary_flux_by_direction_gradient!(surface_flux_values::AbstractArray{<:Any, + 5}, t, boundary_condition, equations_parabolic::AbstractEquationsParabolic, @@ -541,10 +544,8 @@ function calc_boundary_flux_divergence!(cache, t, dg, cache, 6, firsts[6], lasts[6]) end -function calc_boundary_flux_by_direction_divergence!(surface_flux_values::AbstractArray{ - <:Any, - 5 - }, +function calc_boundary_flux_by_direction_divergence!(surface_flux_values::AbstractArray{<:Any, + 5}, t, boundary_condition, equations_parabolic::AbstractEquationsParabolic, @@ -593,13 +594,17 @@ function calc_boundary_flux_by_direction_divergence!(surface_flux_values::Abstra return nothing end +# `cache` is the hyperbolic cache, i.e., in particular not `cache_parabolic`. +# This is because mortar handling is done in the (hyperbolic) `cache`. +# Specialization `flux_viscous::Vector{Array{uEltype, 4}}` needed since +#`prolong2mortars!` in dg_2d.jl is used for both purely hyperbolic and +# hyperbolic-parabolic systems. function prolong2mortars!(cache, - flux_viscous::Tuple{AbstractArray, AbstractArray, - AbstractArray}, + flux_viscous::Vector{Array{uEltype, 5}}, mesh::TreeMesh{3}, equations_parabolic::AbstractEquationsParabolic, mortar_l2::LobattoLegendreMortarL2, - surface_integral, dg::DGSEM) + surface_integral, dg::DGSEM) where {uEltype <: Real} # temporary buffer for projections @unpack fstar_tmp1_threaded = cache @@ -820,7 +825,7 @@ function prolong2mortars!(cache, end # NOTE: Use analogy to "calc_mortar_flux!" for hyperbolic eqs with no nonconservative terms. -# Reasoning: "calc_interface_flux!" for parabolic part is implemented as the version for +# Reasoning: "calc_interface_flux!" for parabolic part is implemented as the version for # hyperbolic terms with conserved terms only, i.e., no nonconservative terms. function calc_mortar_flux!(surface_flux_values, mesh::TreeMesh{3}, @@ -1096,21 +1101,18 @@ function create_cache_parabolic(mesh::TreeMesh{3}, elements = init_elements(leaf_cell_ids, mesh, equations_hyperbolic, dg.basis, RealT, uEltype) - n_vars = nvariables(equations_hyperbolic) - n_nodes = nnodes(elements) - n_elements = nelements(elements) - u_transformed = Array{uEltype}(undef, n_vars, n_nodes, n_nodes, n_nodes, n_elements) - gradients = ntuple(_ -> similar(u_transformed), ndims(mesh)) - flux_viscous = ntuple(_ -> similar(u_transformed), ndims(mesh)) - interfaces = init_interfaces(leaf_cell_ids, mesh, elements) boundaries = init_boundaries(leaf_cell_ids, mesh, elements) # mortars = init_mortars(leaf_cell_ids, mesh, elements, dg.mortar) + viscous_container = init_viscous_container_3d(nvariables(equations_hyperbolic), + nnodes(elements), nelements(elements), + uEltype) + # cache = (; elements, interfaces, boundaries, mortars) - cache = (; elements, interfaces, boundaries, gradients, flux_viscous, u_transformed) + cache = (; elements, interfaces, boundaries, viscous_container) # Add specialized parts of the cache required to compute the mortars etc. # cache = (;cache..., create_cache(mesh, equations_parabolic, dg.mortar, uEltype)...) @@ -1122,10 +1124,13 @@ end # This is because the parabolic fluxes are assumed to be of the form # `du/dt + df/dx = dg/dx + source(x,t)`, # where f(u) is the inviscid flux and g(u) is the viscous flux. -function apply_jacobian_parabolic!(du, mesh::Union{TreeMesh{3}, P4estMesh{3}}, - equations::AbstractEquationsParabolic, dg::DG, cache) +function apply_jacobian_parabolic!(du, mesh::TreeMesh{3}, + equations::AbstractEquationsParabolic, + dg::DG, cache) + @unpack inverse_jacobian = cache.elements + @threaded for element in eachelement(dg, cache) - factor = cache.elements.inverse_jacobian[element] + factor = inverse_jacobian[element] for k in eachnode(dg), j in eachnode(dg), i in eachnode(dg) for v in eachvariable(equations) @@ -1136,4 +1141,22 @@ function apply_jacobian_parabolic!(du, mesh::Union{TreeMesh{3}, P4estMesh{3}}, return nothing end + +function apply_jacobian_parabolic!(du, mesh::P4estMesh{3}, + equations::AbstractEquationsParabolic, + dg::DG, cache) + @unpack inverse_jacobian = cache.elements + + @threaded for element in eachelement(dg, cache) + for k in eachnode(dg), j in eachnode(dg), i in eachnode(dg) + factor = inverse_jacobian[i, j, k, element] + + for v in eachvariable(equations) + du[v, i, j, k, element] *= factor + end + end + end + + return nothing +end end # @muladd diff --git a/src/solvers/dgsem_tree/indicators.jl b/src/solvers/dgsem_tree/indicators.jl index 4b83e9c1a9e..bb9109f2762 100644 --- a/src/solvers/dgsem_tree/indicators.jl +++ b/src/solvers/dgsem_tree/indicators.jl @@ -332,199 +332,4 @@ function Base.show(io::IO, ::MIME"text/plain", indicator::IndicatorMax) summary_box(io, "IndicatorMax", setup) end end - -""" - 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](https://doi.org/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](https://doi.org/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. - -!!! warning "Experimental implementation" - This is an experimental feature and may change in future releases. - -""" -struct IndicatorNeuralNetwork{IndicatorType, RealT <: Real, Variable, Chain, Cache} <: - AbstractIndicator - indicator_type::IndicatorType - alpha_max::RealT - alpha_min::RealT - alpha_smooth::Bool - alpha_continuous::Bool - alpha_amr::Bool - variable::Variable - network::Chain - cache::Cache -end - -# this method is used when the indicator is constructed as for shock-capturing volume integrals -function IndicatorNeuralNetwork(equations::AbstractEquations, basis; - indicator_type, - alpha_max = 0.5, - alpha_min = 0.001, - alpha_smooth = true, - alpha_continuous = true, - alpha_amr = false, - variable, - network) - alpha_max, alpha_min = promote(alpha_max, alpha_min) - IndicatorType = typeof(indicator_type) - cache = create_cache(IndicatorNeuralNetwork{IndicatorType}, equations, basis) - IndicatorNeuralNetwork{IndicatorType, typeof(alpha_max), typeof(variable), - typeof(network), typeof(cache)}(indicator_type, alpha_max, - alpha_min, alpha_smooth, - alpha_continuous, alpha_amr, - variable, - network, cache) -end - -# this method is used when the indicator is constructed as for AMR -function IndicatorNeuralNetwork(semi::AbstractSemidiscretization; - indicator_type, - alpha_max = 0.5, - alpha_min = 0.001, - alpha_smooth = true, - alpha_continuous = true, - alpha_amr = true, - variable, - network) - alpha_max, alpha_min = promote(alpha_max, alpha_min) - IndicatorType = typeof(indicator_type) - cache = create_cache(IndicatorNeuralNetwork{IndicatorType}, semi) - IndicatorNeuralNetwork{IndicatorType, typeof(alpha_max), typeof(variable), - typeof(network), typeof(cache)}(indicator_type, alpha_max, - alpha_min, alpha_smooth, - alpha_continuous, alpha_amr, - variable, - network, cache) -end - -function Base.show(io::IO, indicator::IndicatorNeuralNetwork) - @nospecialize indicator # reduce precompilation time - - print(io, "IndicatorNeuralNetwork(") - print(io, indicator.indicator_type) - print(io, ", alpha_max=", indicator.alpha_max) - print(io, ", alpha_min=", indicator.alpha_min) - print(io, ", alpha_smooth=", indicator.alpha_smooth) - print(io, ", alpha_continuous=", indicator.alpha_continuous) - print(io, indicator.variable) - print(io, ")") -end - -function Base.show(io::IO, ::MIME"text/plain", indicator::IndicatorNeuralNetwork) - @nospecialize indicator # reduce precompilation time - - if get(io, :compact, false) - show(io, indicator) - else - setup = [ - "indicator type" => indicator.indicator_type, - "max. α" => indicator.alpha_max, - "min. α" => indicator.alpha_min, - "smooth α" => (indicator.alpha_smooth ? "yes" : "no"), - "continuous α" => (indicator.alpha_continuous ? "yes" : "no"), - "indicator variable" => indicator.variable, - ] - summary_box(io, "IndicatorNeuralNetwork", setup) - end -end - -# Convert probability for troubled cell to indicator value for shockcapturing/AMR -@inline function probability_to_indicator(probability_troubled_cell, alpha_continuous, - alpha_amr, - alpha_min, alpha_max) - # Initialize indicator to zero - alpha_element = zero(probability_troubled_cell) - - if alpha_continuous && !alpha_amr - # Set good cells to 0 and troubled cells to continuous value of the network prediction - if probability_troubled_cell > 0.5 - alpha_element = probability_troubled_cell - else - alpha_element = zero(probability_troubled_cell) - end - - # Take care of the case close to pure FV - if alpha_element > 1 - alpha_min - alpha_element = one(alpha_element) - end - - # Scale the probability for a troubled cell (in [0,1]) to the maximum allowed alpha - alpha_element *= alpha_max - elseif !alpha_continuous && !alpha_amr - # Set good cells to 0 and troubled cells to 1 - if probability_troubled_cell > 0.5 - alpha_element = alpha_max - else - alpha_element = zero(alpha_max) - end - elseif alpha_amr - # The entire continuous output of the neural network is used for AMR - alpha_element = probability_troubled_cell - - # Scale the probability for a troubled cell (in [0,1]) to the maximum allowed alpha - alpha_element *= alpha_max - end - - return alpha_element -end - -""" - NeuralNetworkPerssonPeraire - -Indicator type for creating an `IndicatorNeuralNetwork` indicator. - -!!! warning "Experimental implementation" - This is an experimental feature and may change in future releases. - -See also: [`IndicatorNeuralNetwork`](@ref) -""" -struct NeuralNetworkPerssonPeraire end - -""" - NeuralNetworkRayHesthaven - -Indicator type for creating an `IndicatorNeuralNetwork` indicator. - -!!! warning "Experimental implementation" - This is an experimental feature and may change in future releases. - -See also: [`IndicatorNeuralNetwork`](@ref) -""" -struct NeuralNetworkRayHesthaven end - -""" - NeuralNetworkCNN - -Indicator type for creating an `IndicatorNeuralNetwork` indicator. - -!!! warning "Experimental implementation" - This is an experimental feature and may change in future releases. - -See also: [`IndicatorNeuralNetwork`](@ref) -""" -struct NeuralNetworkCNN end end # @muladd diff --git a/src/solvers/dgsem_tree/indicators_1d.jl b/src/solvers/dgsem_tree/indicators_1d.jl index 8b57348861c..dff87bfe06c 100644 --- a/src/solvers/dgsem_tree/indicators_1d.jl +++ b/src/solvers/dgsem_tree/indicators_1d.jl @@ -29,8 +29,8 @@ end # full FV element. # # TODO: TrixiShallowWater: move new indicator type -function (indicator_hg::IndicatorHennemannGassnerShallowWater)(u::AbstractArray{<:Any, 3 - }, +function (indicator_hg::IndicatorHennemannGassnerShallowWater)(u::AbstractArray{<:Any, + 3}, mesh, equations::ShallowWaterEquations1D, dg::DGSEM, cache; @@ -289,6 +289,7 @@ function (indicator_max::IndicatorMax)(u::AbstractArray{<:Any, 3}, kwargs...) @unpack alpha, indicator_threaded = indicator_max.cache resize!(alpha, nelements(dg, cache)) + indicator_variable = indicator_max.variable @threaded for element in eachelement(dg, cache) indicator = indicator_threaded[Threads.threadid()] @@ -296,7 +297,7 @@ function (indicator_max::IndicatorMax)(u::AbstractArray{<:Any, 3}, # Calculate indicator variables at Gauss-Lobatto nodes for i in eachnode(dg) u_local = get_node_vars(u, equations, dg, i, element) - indicator[i] = indicator_max.variable(u_local, equations) + indicator[i] = indicator_variable(u_local, equations) end alpha[element] = maximum(indicator) @@ -304,222 +305,4 @@ function (indicator_max::IndicatorMax)(u::AbstractArray{<:Any, 3}, return alpha end - -# this method is used when the indicator is constructed as for shock-capturing volume integrals -# empty cache is default -function create_cache(::Type{<:IndicatorNeuralNetwork}, - equations::AbstractEquations{1}, basis::LobattoLegendreBasis) - return NamedTuple() -end - -# cache for NeuralNetworkPerssonPeraire-type indicator -function create_cache(::Type{IndicatorNeuralNetwork{NeuralNetworkPerssonPeraire}}, - equations::AbstractEquations{1}, basis::LobattoLegendreBasis) - alpha = Vector{real(basis)}() - alpha_tmp = similar(alpha) - A = Array{real(basis), ndims(equations)} - - prototype = A(undef, nnodes(basis)) - indicator_threaded = [similar(prototype) for _ in 1:Threads.nthreads()] - modal_threaded = [similar(prototype) for _ in 1:Threads.nthreads()] - - return (; alpha, alpha_tmp, indicator_threaded, modal_threaded) -end - -# cache for NeuralNetworkRayHesthaven-type indicator -function create_cache(::Type{IndicatorNeuralNetwork{NeuralNetworkRayHesthaven}}, - equations::AbstractEquations{1}, basis::LobattoLegendreBasis) - alpha = Vector{real(basis)}() - alpha_tmp = similar(alpha) - A = Array{real(basis), ndims(equations)} - - prototype = A(undef, nnodes(basis)) - indicator_threaded = [similar(prototype) for _ in 1:Threads.nthreads()] - neighbor_ids = Vector{Int}(undef, 2) - - return (; alpha, alpha_tmp, indicator_threaded, neighbor_ids) -end - -# this method is used when the indicator is constructed as for AMR -function create_cache(typ::Type{<:IndicatorNeuralNetwork}, - mesh, equations::AbstractEquations{1}, dg::DGSEM, cache) - create_cache(typ, equations, dg.basis) -end - -function (indicator_ann::IndicatorNeuralNetwork{NeuralNetworkPerssonPeraire})(u::AbstractArray{ - <:Any, - 3 - }, - mesh, - equations, - dg::DGSEM, - cache; - kwargs...) - @unpack indicator_type, alpha_max, alpha_min, alpha_smooth, alpha_continuous, alpha_amr, variable, network = indicator_ann - - @unpack alpha, alpha_tmp, indicator_threaded, modal_threaded = indicator_ann.cache - # TODO: Taal refactor, when to `resize!` stuff changed possibly by AMR? - # Shall we implement `resize!(semi::AbstractSemidiscretization, new_size)` - # or just `resize!` whenever we call the relevant methods as we do now? - resize!(alpha, nelements(dg, cache)) - if alpha_smooth - resize!(alpha_tmp, nelements(dg, cache)) - end - - @threaded for element in eachelement(dg, cache) - indicator = indicator_threaded[Threads.threadid()] - modal = modal_threaded[Threads.threadid()] - - # Calculate indicator variables at Gauss-Lobatto nodes - for i in eachnode(dg) - u_local = get_node_vars(u, equations, dg, i, element) - indicator[i] = indicator_ann.variable(u_local, equations) - end - - # Convert to modal representation - multiply_scalar_dimensionwise!(modal, dg.basis.inverse_vandermonde_legendre, - indicator) - - # Calculate total energies for all modes, without highest, without two highest - total_energy = zero(eltype(modal)) - for i in 1:nnodes(dg) - total_energy += modal[i]^2 - end - total_energy_clip1 = zero(eltype(modal)) - for i in 1:(nnodes(dg) - 1) - total_energy_clip1 += modal[i]^2 - end - total_energy_clip2 = zero(eltype(modal)) - for i in 1:(nnodes(dg) - 2) - total_energy_clip2 += modal[i]^2 - end - - # Calculate energy in highest modes - X1 = (total_energy - total_energy_clip1) / total_energy - X2 = (total_energy_clip1 - total_energy_clip2) / total_energy_clip1 - - # There are two versions of the network: - # The first one only takes the highest energy modes as input, the second one also the number of - # nodes. Automatically use the correct input by checking the number of inputs of the network. - if size(params(network)[1], 2) == 2 - network_input = SVector(X1, X2) - elseif size(params(network)[1], 2) == 3 - network_input = SVector(X1, X2, nnodes(dg)) - end - - # Scale input data - network_input = network_input / - max(maximum(abs, network_input), one(eltype(network_input))) - probability_troubled_cell = network(network_input)[1] - - # Compute indicator value - alpha[element] = probability_to_indicator(probability_troubled_cell, - alpha_continuous, - alpha_amr, alpha_min, alpha_max) - end - - if alpha_smooth - apply_smoothing!(mesh, alpha, alpha_tmp, dg, cache) - end - - return alpha -end - -function (indicator_ann::IndicatorNeuralNetwork{NeuralNetworkRayHesthaven})(u::AbstractArray{ - <:Any, - 3 - }, - mesh, - equations, - dg::DGSEM, - cache; - kwargs...) - @unpack indicator_type, alpha_max, alpha_min, alpha_smooth, alpha_continuous, alpha_amr, variable, network = indicator_ann - - @unpack alpha, alpha_tmp, indicator_threaded, neighbor_ids = indicator_ann.cache - # TODO: Taal refactor, when to `resize!` stuff changed possibly by AMR? - # Shall we implement `resize!(semi::AbstractSemidiscretization, new_size)` - # or just `resize!` whenever we call the relevant methods as we do now? - resize!(alpha, nelements(dg, cache)) - if alpha_smooth - resize!(alpha_tmp, nelements(dg, cache)) - end - - c2e = zeros(Int, length(mesh.tree)) - for element in eachelement(dg, cache) - c2e[cache.elements.cell_ids[element]] = element - end - - @threaded for element in eachelement(dg, cache) - indicator = indicator_threaded[Threads.threadid()] - cell_id = cache.elements.cell_ids[element] - - for direction in eachdirection(mesh.tree) - if !has_any_neighbor(mesh.tree, cell_id, direction) - neighbor_ids[direction] = element - continue - end - if has_neighbor(mesh.tree, cell_id, direction) - neighbor_cell_id = mesh.tree.neighbor_ids[direction, cell_id] - if has_children(mesh.tree, neighbor_cell_id) # Cell has small neighbor - if direction == 1 - neighbor_ids[direction] = c2e[mesh.tree.child_ids[2, - neighbor_cell_id]] - else - neighbor_ids[direction] = c2e[mesh.tree.child_ids[1, - neighbor_cell_id]] - end - else # Cell has same refinement level neighbor - neighbor_ids[direction] = c2e[neighbor_cell_id] - end - else # Cell is small and has large neighbor - parent_id = mesh.tree.parent_ids[cell_id] - neighbor_cell_id = mesh.tree.neighbor_ids[direction, parent_id] - neighbor_ids[direction] = c2e[neighbor_cell_id] - end - end - - # Calculate indicator variables at Gauss-Lobatto nodes - for i in eachnode(dg) - u_local = get_node_vars(u, equations, dg, i, element) - indicator[i] = indicator_ann.variable(u_local, equations) - end - - # Cell average and interface values of the cell - X2 = sum(indicator) / nnodes(dg) - X4 = indicator[1] - X5 = indicator[end] - - # Calculate indicator variables from left neighboring cell at Gauss-Lobatto nodes - for i in eachnode(dg) - u_local = get_node_vars(u, equations, dg, i, neighbor_ids[1]) - indicator[i] = indicator_ann.variable(u_local, equations) - end - X1 = sum(indicator) / nnodes(dg) - - # Calculate indicator variables from right neighboring cell at Gauss-Lobatto nodes - for i in eachnode(dg) - u_local = get_node_vars(u, equations, dg, i, neighbor_ids[2]) - indicator[i] = indicator_ann.variable(u_local, equations) - end - X3 = sum(indicator) / nnodes(dg) - network_input = SVector(X1, X2, X3, X4, X5) - - # Scale input data - network_input = network_input / - max(maximum(abs, network_input), one(eltype(network_input))) - probability_troubled_cell = network(network_input)[1] - - # Compute indicator value - alpha[element] = probability_to_indicator(probability_troubled_cell, - alpha_continuous, - alpha_amr, alpha_min, alpha_max) - end - - if alpha_smooth - apply_smoothing!(mesh, alpha, alpha_tmp, dg, cache) - end - - return alpha -end end # @muladd diff --git a/src/solvers/dgsem_tree/indicators_2d.jl b/src/solvers/dgsem_tree/indicators_2d.jl index 2f34e0eb661..fa8ed481eb9 100644 --- a/src/solvers/dgsem_tree/indicators_2d.jl +++ b/src/solvers/dgsem_tree/indicators_2d.jl @@ -33,8 +33,8 @@ end # full FV element. # # TODO: TrixiShallowWater: move new indicator type -function (indicator_hg::IndicatorHennemannGassnerShallowWater)(u::AbstractArray{<:Any, 4 - }, +function (indicator_hg::IndicatorHennemannGassnerShallowWater)(u::AbstractArray{<:Any, + 4}, mesh, equations::ShallowWaterEquations2D, dg::DGSEM, cache; @@ -323,6 +323,7 @@ function (indicator_max::IndicatorMax)(u::AbstractArray{<:Any, 4}, kwargs...) @unpack alpha, indicator_threaded = indicator_max.cache resize!(alpha, nelements(dg, cache)) + indicator_variable = indicator_max.variable @threaded for element in eachelement(dg, cache) indicator = indicator_threaded[Threads.threadid()] @@ -330,7 +331,7 @@ function (indicator_max::IndicatorMax)(u::AbstractArray{<:Any, 4}, # Calculate indicator variables at Gauss-Lobatto nodes for j in eachnode(dg), i in eachnode(dg) u_local = get_node_vars(u, equations, dg, i, j, element) - indicator[i, j] = indicator_max.variable(u_local, equations) + indicator[i, j] = indicator_variable(u_local, equations) end alpha[element] = maximum(indicator) @@ -338,355 +339,4 @@ function (indicator_max::IndicatorMax)(u::AbstractArray{<:Any, 4}, return alpha end - -# this method is used when the indicator is constructed as for shock-capturing volume integrals -# empty cache is default -function create_cache(::Type{IndicatorNeuralNetwork}, - equations::AbstractEquations{2}, basis::LobattoLegendreBasis) - return NamedTuple() -end - -# cache for NeuralNetworkPerssonPeraire-type indicator -function create_cache(::Type{IndicatorNeuralNetwork{NeuralNetworkPerssonPeraire}}, - equations::AbstractEquations{2}, basis::LobattoLegendreBasis) - alpha = Vector{real(basis)}() - alpha_tmp = similar(alpha) - A = Array{real(basis), ndims(equations)} - - @assert nnodes(basis)>=4 "Indicator only works for nnodes >= 4 (polydeg > 2)" - - prototype = A(undef, nnodes(basis), nnodes(basis)) - indicator_threaded = [similar(prototype) for _ in 1:Threads.nthreads()] - modal_threaded = [similar(prototype) for _ in 1:Threads.nthreads()] - modal_tmp1_threaded = [similar(prototype) for _ in 1:Threads.nthreads()] - - return (; alpha, alpha_tmp, indicator_threaded, modal_threaded, modal_tmp1_threaded) -end - -# cache for NeuralNetworkRayHesthaven-type indicator -function create_cache(::Type{IndicatorNeuralNetwork{NeuralNetworkRayHesthaven}}, - equations::AbstractEquations{2}, basis::LobattoLegendreBasis) - alpha = Vector{real(basis)}() - alpha_tmp = similar(alpha) - A = Array{real(basis), ndims(equations)} - - prototype = A(undef, nnodes(basis), nnodes(basis)) - indicator_threaded = [similar(prototype) for _ in 1:Threads.nthreads()] - modal_threaded = [similar(prototype) for _ in 1:Threads.nthreads()] - modal_tmp1_threaded = [similar(prototype) for _ in 1:Threads.nthreads()] - - network_input = Vector{Float64}(undef, 15) - neighbor_ids = Array{Int64}(undef, 8) - neighbor_mean = Array{Float64}(undef, 4, 3) - - return (; alpha, alpha_tmp, indicator_threaded, modal_threaded, modal_tmp1_threaded, - network_input, neighbor_ids, neighbor_mean) -end - -# cache for NeuralNetworkCNN-type indicator -function create_cache(::Type{IndicatorNeuralNetwork{NeuralNetworkCNN}}, - equations::AbstractEquations{2}, basis::LobattoLegendreBasis) - alpha = Vector{real(basis)}() - alpha_tmp = similar(alpha) - A = Array{real(basis), ndims(equations)} - - prototype = A(undef, nnodes(basis), nnodes(basis)) - indicator_threaded = [similar(prototype) for _ in 1:Threads.nthreads()] - n_cnn = 4 - nodes, _ = gauss_lobatto_nodes_weights(nnodes(basis)) - cnn_nodes, _ = gauss_lobatto_nodes_weights(n_cnn) - vandermonde = polynomial_interpolation_matrix(nodes, cnn_nodes) - network_input = Array{Float32}(undef, n_cnn, n_cnn, 1, 1) - - return (; alpha, alpha_tmp, indicator_threaded, nodes, cnn_nodes, vandermonde, - network_input) -end - -# this method is used when the indicator is constructed as for AMR -function create_cache(typ::Type{<:IndicatorNeuralNetwork}, - mesh, equations::AbstractEquations{2}, dg::DGSEM, cache) - create_cache(typ, equations, dg.basis) -end - -function (indicator_ann::IndicatorNeuralNetwork{NeuralNetworkPerssonPeraire})(u, - mesh::TreeMesh{ - 2 - }, - equations, - dg::DGSEM, - cache; - kwargs...) - @unpack indicator_type, alpha_max, alpha_min, alpha_smooth, alpha_continuous, alpha_amr, variable, network = indicator_ann - - @unpack alpha, alpha_tmp, indicator_threaded, modal_threaded, modal_tmp1_threaded = indicator_ann.cache - # TODO: Taal refactor, when to `resize!` stuff changed possibly by AMR? - # Shall we implement `resize!(semi::AbstractSemidiscretization, new_size)` - # or just `resize!` whenever we call the relevant methods as we do now? - resize!(alpha, nelements(dg, cache)) - if alpha_smooth - resize!(alpha_tmp, nelements(dg, cache)) - end - - @threaded for element in eachelement(dg, cache) - indicator = indicator_threaded[Threads.threadid()] - modal = modal_threaded[Threads.threadid()] - modal_tmp1 = modal_tmp1_threaded[Threads.threadid()] - - # Calculate indicator variables at Gauss-Lobatto nodes - for j in eachnode(dg), i in eachnode(dg) - u_local = get_node_vars(u, equations, dg, i, j, element) - indicator[i, j] = indicator_ann.variable(u_local, equations) - end - - # Convert to modal representation - multiply_scalar_dimensionwise!(modal, dg.basis.inverse_vandermonde_legendre, - indicator, modal_tmp1) - - # Calculate total energies for all modes, without highest, without two highest - total_energy = zero(eltype(modal)) - for j in 1:nnodes(dg), i in 1:nnodes(dg) - total_energy += modal[i, j]^2 - end - total_energy_clip1 = zero(eltype(modal)) - for j in 1:(nnodes(dg) - 1), i in 1:(nnodes(dg) - 1) - total_energy_clip1 += modal[i, j]^2 - end - total_energy_clip2 = zero(eltype(modal)) - for j in 1:(nnodes(dg) - 2), i in 1:(nnodes(dg) - 2) - total_energy_clip2 += modal[i, j]^2 - end - total_energy_clip3 = zero(eltype(modal)) - for j in 1:(nnodes(dg) - 3), i in 1:(nnodes(dg) - 3) - total_energy_clip3 += modal[i, j]^2 - end - - # Calculate energy in higher modes and polynomial degree for the network input - X1 = (total_energy - total_energy_clip1) / total_energy - X2 = (total_energy_clip1 - total_energy_clip2) / total_energy_clip1 - X3 = (total_energy_clip2 - total_energy_clip3) / total_energy_clip2 - X4 = nnodes(dg) - network_input = SVector(X1, X2, X3, X4) - - # Scale input data - network_input = network_input / - max(maximum(abs, network_input), one(eltype(network_input))) - probability_troubled_cell = network(network_input)[1] - - # Compute indicator value - alpha[element] = probability_to_indicator(probability_troubled_cell, - alpha_continuous, - alpha_amr, alpha_min, alpha_max) - end - - if alpha_smooth - apply_smoothing!(mesh, alpha, alpha_tmp, dg, cache) - end - - return alpha -end - -function (indicator_ann::IndicatorNeuralNetwork{NeuralNetworkRayHesthaven})(u, - mesh::TreeMesh{ - 2 - }, - equations, - dg::DGSEM, - cache; - kwargs...) - @unpack indicator_type, alpha_max, alpha_min, alpha_smooth, alpha_continuous, alpha_amr, variable, network = indicator_ann - - @unpack alpha, alpha_tmp, indicator_threaded, modal_threaded, modal_tmp1_threaded, network_input, neighbor_ids, neighbor_mean = indicator_ann.cache #X, network_input - # TODO: Taal refactor, when to `resize!` stuff changed possibly by AMR? - # Shall we implement `resize!(semi::AbstractSemidiscretization, new_size)` - # or just `resize!` whenever we call the relevant methods as we do now? - resize!(alpha, nelements(dg, cache)) - if alpha_smooth - resize!(alpha_tmp, nelements(dg, cache)) - end - - c2e = zeros(Int, length(mesh.tree)) - for element in eachelement(dg, cache) - c2e[cache.elements.cell_ids[element]] = element - end - - X = Array{Float64}(undef, 3, nelements(dg, cache)) - - @threaded for element in eachelement(dg, cache) - indicator = indicator_threaded[Threads.threadid()] - modal = modal_threaded[Threads.threadid()] - modal_tmp1 = modal_tmp1_threaded[Threads.threadid()] - - # Calculate indicator variables at Gauss-Lobatto nodes - for j in eachnode(dg), i in eachnode(dg) - u_local = get_node_vars(u, equations, dg, i, j, element) - indicator[i, j] = indicator_ann.variable(u_local, equations) - end - - # Convert to modal representation - multiply_scalar_dimensionwise!(modal, dg.basis.inverse_vandermonde_legendre, - indicator, modal_tmp1) - # Save linear modal coefficients for the network input - X[1, element] = modal[1, 1] - X[2, element] = modal[1, 2] - X[3, element] = modal[2, 1] - end - - @threaded for element in eachelement(dg, cache) - cell_id = cache.elements.cell_ids[element] - - network_input[1] = X[1, element] - network_input[2] = X[2, element] - network_input[3] = X[3, element] - - for direction in eachdirection(mesh.tree) - if direction == 1 # -x - dir = 4 - elseif direction == 2 # +x - dir = 1 - elseif direction == 3 # -y - dir = 3 - elseif direction == 4 # +y - dir = 2 - end - - # Of no neighbor exists and current cell is not small - if !has_any_neighbor(mesh.tree, cell_id, direction) - network_input[3 * dir + 1] = X[1, element] - network_input[3 * dir + 2] = X[2, element] - network_input[3 * dir + 3] = X[3, element] - continue - end - - # Get Input data from neighbors - if has_neighbor(mesh.tree, cell_id, direction) - neighbor_cell_id = mesh.tree.neighbor_ids[direction, cell_id] - if has_children(mesh.tree, neighbor_cell_id) # Cell has small neighbor - # Mean over 4 neighbor cells - neighbor_ids[1] = mesh.tree.child_ids[1, neighbor_cell_id] - neighbor_ids[2] = mesh.tree.child_ids[2, neighbor_cell_id] - neighbor_ids[3] = mesh.tree.child_ids[3, neighbor_cell_id] - neighbor_ids[4] = mesh.tree.child_ids[4, neighbor_cell_id] - - for i in 1:4 - if has_children(mesh.tree, neighbor_ids[i]) - neighbor_ids5 = c2e[mesh.tree.child_ids[1, neighbor_ids[i]]] - neighbor_ids6 = c2e[mesh.tree.child_ids[2, neighbor_ids[i]]] - neighbor_ids7 = c2e[mesh.tree.child_ids[3, neighbor_ids[i]]] - neighbor_ids8 = c2e[mesh.tree.child_ids[4, neighbor_ids[i]]] - - neighbor_mean[i, 1] = (X[1, neighbor_ids5] + - X[1, neighbor_ids6] + - X[1, neighbor_ids7] + - X[1, neighbor_ids8]) / 4 - neighbor_mean[i, 2] = (X[2, neighbor_ids5] + - X[2, neighbor_ids6] + - X[2, neighbor_ids7] + - X[2, neighbor_ids8]) / 4 - neighbor_mean[i, 3] = (X[3, neighbor_ids5] + - X[3, neighbor_ids6] + - X[3, neighbor_ids7] + - X[3, neighbor_ids8]) / 4 - else - neighbor_id = c2e[neighbor_ids[i]] - neighbor_mean[i, 1] = X[1, neighbor_id] - neighbor_mean[i, 2] = X[2, neighbor_id] - neighbor_mean[i, 3] = X[3, neighbor_id] - end - end - network_input[3 * dir + 1] = (neighbor_mean[1, 1] + - neighbor_mean[2, 1] + - neighbor_mean[3, 1] + - neighbor_mean[4, 1]) / 4 - network_input[3 * dir + 2] = (neighbor_mean[1, 2] + - neighbor_mean[2, 2] + - neighbor_mean[3, 2] + - neighbor_mean[4, 2]) / 4 - network_input[3 * dir + 3] = (neighbor_mean[1, 3] + - neighbor_mean[2, 3] + - neighbor_mean[3, 3] + - neighbor_mean[4, 3]) / 4 - - else # Cell has same refinement level neighbor - neighbor_id = c2e[neighbor_cell_id] - network_input[3 * dir + 1] = X[1, neighbor_id] - network_input[3 * dir + 2] = X[2, neighbor_id] - network_input[3 * dir + 3] = X[3, neighbor_id] - end - else # Cell is small and has large neighbor - parent_id = mesh.tree.parent_ids[cell_id] - neighbor_id = c2e[mesh.tree.neighbor_ids[direction, parent_id]] - - network_input[3 * dir + 1] = X[1, neighbor_id] - network_input[3 * dir + 2] = X[2, neighbor_id] - network_input[3 * dir + 3] = X[3, neighbor_id] - end - end - - # Scale input data - network_input = network_input / - max(maximum(abs, network_input), one(eltype(network_input))) - probability_troubled_cell = network(network_input)[1] - - # Compute indicator value - alpha[element] = probability_to_indicator(probability_troubled_cell, - alpha_continuous, - alpha_amr, alpha_min, alpha_max) - end - - if alpha_smooth - apply_smoothing!(mesh, alpha, alpha_tmp, dg, cache) - end - - return alpha -end - -function (indicator_ann::IndicatorNeuralNetwork{NeuralNetworkCNN})(u, mesh::TreeMesh{2}, - equations, dg::DGSEM, - cache; kwargs...) - @unpack indicator_type, alpha_max, alpha_min, alpha_smooth, alpha_continuous, alpha_amr, variable, network = indicator_ann - - @unpack alpha, alpha_tmp, indicator_threaded, nodes, cnn_nodes, vandermonde, network_input = indicator_ann.cache - # TODO: Taal refactor, when to `resize!` stuff changed possibly by AMR? - # Shall we implement `resize!(semi::AbstractSemidiscretization, new_size)` - # or just `resize!` whenever we call the relevant methods as we do now? - resize!(alpha, nelements(dg, cache)) - if alpha_smooth - resize!(alpha_tmp, nelements(dg, cache)) - end - - @threaded for element in eachelement(dg, cache) - indicator = indicator_threaded[Threads.threadid()] - - # Calculate indicator variables at Gauss-Lobatto nodes - for j in eachnode(dg), i in eachnode(dg) - u_local = get_node_vars(u, equations, dg, i, j, element) - indicator[i, j] = indicator_ann.variable(u_local, equations) - end - - # Interpolate nodal data to 4x4 LGL nodes - for j in 1:4, i in 1:4 - acc = zero(eltype(indicator)) - for jj in eachnode(dg), ii in eachnode(dg) - acc += vandermonde[i, ii] * indicator[ii, jj] * vandermonde[j, jj] - end - network_input[i, j, 1, 1] = acc - end - - # Scale input data - network_input = network_input / - max(maximum(abs, network_input), one(eltype(network_input))) - probability_troubled_cell = network(network_input)[1] - - # Compute indicator value - alpha[element] = probability_to_indicator(probability_troubled_cell, - alpha_continuous, - alpha_amr, alpha_min, alpha_max) - end - - if alpha_smooth - apply_smoothing!(mesh, alpha, alpha_tmp, dg, cache) - end - - return alpha -end end # @muladd diff --git a/src/solvers/dgsem_tree/indicators_3d.jl b/src/solvers/dgsem_tree/indicators_3d.jl index 61d7f770dc7..a11a8e06e4b 100644 --- a/src/solvers/dgsem_tree/indicators_3d.jl +++ b/src/solvers/dgsem_tree/indicators_3d.jl @@ -235,6 +235,7 @@ function (indicator_max::IndicatorMax)(u::AbstractArray{<:Any, 5}, kwargs...) @unpack alpha, indicator_threaded = indicator_max.cache resize!(alpha, nelements(dg, cache)) + indicator_variable = indicator_max.variable @threaded for element in eachelement(dg, cache) indicator = indicator_threaded[Threads.threadid()] @@ -242,7 +243,7 @@ function (indicator_max::IndicatorMax)(u::AbstractArray{<:Any, 5}, # Calculate indicator variables at Gauss-Lobatto nodes for k in eachnode(dg), j in eachnode(dg), i in eachnode(dg) u_local = get_node_vars(u, equations, dg, i, j, k, element) - indicator[i, j, k] = indicator_max.variable(u_local, equations) + indicator[i, j, k] = indicator_variable(u_local, equations) end alpha[element] = maximum(indicator) diff --git a/src/solvers/dgsem_tree/subcell_limiters.jl b/src/solvers/dgsem_tree/subcell_limiters.jl index 3a707de3bc7..055e7ce24a4 100644 --- a/src/solvers/dgsem_tree/subcell_limiters.jl +++ b/src/solvers/dgsem_tree/subcell_limiters.jl @@ -14,19 +14,24 @@ end """ SubcellLimiterIDP(equations::AbstractEquations, basis; - positivity_variables_cons = [], + local_minmax_variables_cons = String[], + positivity_variables_cons = String[], positivity_correction_factor = 0.1) Subcell invariant domain preserving (IDP) limiting used with [`VolumeIntegralSubcellLimiting`](@ref) including: -- positivity limiting for conservative variables (`positivity_variables_cons`) +- Local maximum/minimum Zalesak-type limiting for conservative variables (`local_minmax_variables_cons`) +- Positivity limiting for conservative variables (`positivity_variables_cons`) + +Conservative variables to be limited are passed as a vector of strings, e.g. `local_minmax_variables_cons = ["rho"]` +and `positivity_variables_cons = ["rho"]`. 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`](@ref) only work together. - Without the callback, no limiting takes place, leading to a standard flux-differencing DGSEM scheme. + Without the callback, no correction takes place, leading to a standard low-order FV scheme. ## References @@ -41,63 +46,104 @@ The bounds are calculated using the low-order FV solution. The positivity limite This is an experimental feature and may change in future releases. """ struct SubcellLimiterIDP{RealT <: Real, Cache} <: AbstractSubcellLimiter + local_minmax::Bool + local_minmax_variables_cons::Vector{Int} # Local mininum/maximum principles for conservative variables positivity::Bool positivity_variables_cons::Vector{Int} # Positivity for conservative variables positivity_correction_factor::RealT cache::Cache end -# this method is used when the indicator is constructed as for shock-capturing volume integrals +# this method is used when the limiter is constructed as for shock-capturing volume integrals function SubcellLimiterIDP(equations::AbstractEquations, basis; - positivity_variables_cons = [], + local_minmax_variables_cons = String[], + positivity_variables_cons = String[], positivity_correction_factor = 0.1) + local_minmax = (length(local_minmax_variables_cons) > 0) positivity = (length(positivity_variables_cons) > 0) - number_bounds = length(positivity_variables_cons) - cache = create_cache(SubcellLimiterIDP, equations, basis, number_bounds) + local_minmax_variables_cons_ = get_variable_index.(local_minmax_variables_cons, + equations) + positivity_variables_cons_ = get_variable_index.(positivity_variables_cons, + equations) + + bound_keys = () + if local_minmax + for v in local_minmax_variables_cons_ + v_string = string(v) + bound_keys = (bound_keys..., Symbol(v_string, "_min"), + Symbol(v_string, "_max")) + end + end + for v in positivity_variables_cons_ + if !(v in local_minmax_variables_cons_) + bound_keys = (bound_keys..., Symbol(string(v), "_min")) + end + end + + cache = create_cache(SubcellLimiterIDP, equations, basis, bound_keys) - SubcellLimiterIDP{typeof(positivity_correction_factor), typeof(cache)}(positivity, - positivity_variables_cons, - positivity_correction_factor, - cache) + SubcellLimiterIDP{typeof(positivity_correction_factor), + typeof(cache)}(local_minmax, local_minmax_variables_cons_, + positivity, positivity_variables_cons_, + positivity_correction_factor, cache) end function Base.show(io::IO, limiter::SubcellLimiterIDP) @nospecialize limiter # reduce precompilation time - @unpack positivity = limiter + (; local_minmax, positivity) = limiter print(io, "SubcellLimiterIDP(") - if !(positivity) + if !(local_minmax || positivity) print(io, "No limiter selected => pure DG method") else print(io, "limiter=(") + local_minmax && print(io, "min/max limiting, ") positivity && print(io, "positivity") print(io, "), ") end + print(io, "Local bounds with FV solution") print(io, ")") end function Base.show(io::IO, ::MIME"text/plain", limiter::SubcellLimiterIDP) @nospecialize limiter # reduce precompilation time - @unpack positivity = limiter + (; local_minmax, positivity) = limiter if get(io, :compact, false) show(io, limiter) else - if !(positivity) + if !(local_minmax || positivity) setup = ["limiter" => "No limiter selected => pure DG method"] else setup = ["limiter" => ""] + if local_minmax + setup = [ + setup..., + "" => "local maximum/minimum bounds for conservative variables $(limiter.local_minmax_variables_cons)", + ] + end if positivity - string = "positivity with conservative variables $(limiter.positivity_variables_cons)" + string = "positivity for conservative variables $(limiter.positivity_variables_cons)" setup = [setup..., "" => string] setup = [ setup..., "" => " positivity correction factor = $(limiter.positivity_correction_factor)", ] end + setup = [ + setup..., + "Local bounds" => "FV solution", + ] end summary_box(io, "SubcellLimiterIDP", setup) end end + +function get_node_variables!(node_variables, limiter::SubcellLimiterIDP, + ::VolumeIntegralSubcellLimiting, equations) + node_variables[:limiting_coefficient] = limiter.cache.subcell_limiter_coefficients.alpha + + return nothing +end end # @muladd diff --git a/src/solvers/dgsem_tree/subcell_limiters_2d.jl b/src/solvers/dgsem_tree/subcell_limiters_2d.jl index 09ab84ed11a..384f4178bc9 100644 --- a/src/solvers/dgsem_tree/subcell_limiters_2d.jl +++ b/src/solvers/dgsem_tree/subcell_limiters_2d.jl @@ -6,17 +6,21 @@ #! format: noindent # this method is used when the limiter is constructed as for shock-capturing volume integrals -function create_cache(indicator::Type{SubcellLimiterIDP}, - equations::AbstractEquations{2}, - basis::LobattoLegendreBasis, number_bounds) - subcell_limiter_coefficients = Trixi.ContainerSubcellLimiterIDP2D{real(basis) - }(0, - nnodes(basis), - number_bounds) +function create_cache(limiter::Type{SubcellLimiterIDP}, equations::AbstractEquations{2}, + basis::LobattoLegendreBasis, bound_keys) + subcell_limiter_coefficients = Trixi.ContainerSubcellLimiterIDP2D{real(basis)}(0, + nnodes(basis), + bound_keys) - cache = (; subcell_limiter_coefficients) + # Memory for bounds checking routine with `BoundsCheckCallback`. + # The first entry of each vector contains the maximum deviation since the last export. + # The second one contains the total maximum deviation. + idp_bounds_delta = Dict{Symbol, Vector{real(basis)}}() + for key in bound_keys + idp_bounds_delta[key] = zeros(real(basis), 2) + end - return cache + return (; subcell_limiter_coefficients, idp_bounds_delta) end function (limiter::SubcellLimiterIDP)(u::AbstractArray{<:Any, 4}, semi, dg::DGSEM, t, @@ -25,9 +29,12 @@ function (limiter::SubcellLimiterIDP)(u::AbstractArray{<:Any, 4}, semi, dg::DGSE @unpack alpha = limiter.cache.subcell_limiter_coefficients alpha .= zero(eltype(alpha)) + if limiter.local_minmax + @trixi_timeit timer() "local min/max limiting" idp_local_minmax!(alpha, limiter, + u, t, dt, semi) + end if limiter.positivity - @trixi_timeit timer() "positivity" idp_positivity!(alpha, limiter, u, dt, - semi) + @trixi_timeit timer() "positivity" idp_positivity!(alpha, limiter, u, dt, semi) end # Calculate alpha1 and alpha2 @@ -48,24 +55,190 @@ function (limiter::SubcellLimiterIDP)(u::AbstractArray{<:Any, 4}, semi, dg::DGSE return nothing end +@inline function calc_bounds_twosided!(var_min, var_max, variable, u, t, semi) + mesh, equations, dg, cache = mesh_equations_solver_cache(semi) + # Calc bounds inside elements + @threaded for element in eachelement(dg, cache) + var_min[:, :, element] .= typemax(eltype(var_min)) + var_max[:, :, element] .= typemin(eltype(var_max)) + # Calculate bounds at Gauss-Lobatto nodes using u + for j in eachnode(dg), i in eachnode(dg) + var = u[variable, i, j, element] + var_min[i, j, element] = min(var_min[i, j, element], var) + var_max[i, j, element] = max(var_max[i, j, element], var) + + if i > 1 + var_min[i - 1, j, element] = min(var_min[i - 1, j, element], var) + var_max[i - 1, j, element] = max(var_max[i - 1, j, element], var) + end + if i < nnodes(dg) + var_min[i + 1, j, element] = min(var_min[i + 1, j, element], var) + var_max[i + 1, j, element] = max(var_max[i + 1, j, element], var) + end + if j > 1 + var_min[i, j - 1, element] = min(var_min[i, j - 1, element], var) + var_max[i, j - 1, element] = max(var_max[i, j - 1, element], var) + end + if j < nnodes(dg) + var_min[i, j + 1, element] = min(var_min[i, j + 1, element], var) + var_max[i, j + 1, element] = max(var_max[i, j + 1, element], var) + end + end + end + + # Values at element boundary + calc_bounds_twosided_interface!(var_min, var_max, variable, u, t, semi, mesh) +end + +@inline function calc_bounds_twosided_interface!(var_min, var_max, variable, u, t, semi, + mesh::TreeMesh2D) + _, equations, dg, cache = mesh_equations_solver_cache(semi) + (; boundary_conditions) = semi + # Calc bounds at interfaces and periodic boundaries + for interface in eachinterface(dg, cache) + # Get neighboring element ids + left = cache.interfaces.neighbor_ids[1, interface] + right = cache.interfaces.neighbor_ids[2, interface] + + orientation = cache.interfaces.orientations[interface] + + for i in eachnode(dg) + index_left = (nnodes(dg), i) + index_right = (1, i) + if orientation == 2 + index_left = reverse(index_left) + index_right = reverse(index_right) + end + var_left = u[variable, index_left..., left] + var_right = u[variable, index_right..., right] + + var_min[index_right..., right] = min(var_min[index_right..., right], + var_left) + var_max[index_right..., right] = max(var_max[index_right..., right], + var_left) + + var_min[index_left..., left] = min(var_min[index_left..., left], var_right) + var_max[index_left..., left] = max(var_max[index_left..., left], var_right) + end + end + + # Calc bounds at physical boundaries + for boundary in eachboundary(dg, cache) + element = cache.boundaries.neighbor_ids[boundary] + orientation = cache.boundaries.orientations[boundary] + neighbor_side = cache.boundaries.neighbor_sides[boundary] + + for i in eachnode(dg) + if neighbor_side == 2 # Element is on the right, boundary on the left + index = (1, i) + boundary_index = 1 + else # Element is on the left, boundary on the right + index = (nnodes(dg), i) + boundary_index = 2 + end + if orientation == 2 + index = reverse(index) + boundary_index += 2 + end + u_outer = get_boundary_outer_state(boundary_conditions[boundary_index], + cache, t, equations, dg, + index..., element) + var_outer = u_outer[variable] + + var_min[index..., element] = min(var_min[index..., element], var_outer) + var_max[index..., element] = max(var_max[index..., element], var_outer) + end + end + + return nothing +end + +@inline function idp_local_minmax!(alpha, limiter, u, t, dt, semi) + for variable in limiter.local_minmax_variables_cons + idp_local_minmax!(alpha, limiter, u, t, dt, semi, variable) + end + + return nothing +end + +@inline function idp_local_minmax!(alpha, limiter, u, t, dt, semi, variable) + _, _, dg, cache = mesh_equations_solver_cache(semi) + (; antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R) = cache.antidiffusive_fluxes + (; inverse_weights) = dg.basis + + (; variable_bounds) = limiter.cache.subcell_limiter_coefficients + variable_string = string(variable) + var_min = variable_bounds[Symbol(variable_string, "_min")] + var_max = variable_bounds[Symbol(variable_string, "_max")] + calc_bounds_twosided!(var_min, var_max, variable, u, t, semi) + + @threaded for element in eachelement(dg, semi.cache) + inverse_jacobian = cache.elements.inverse_jacobian[element] + for j in eachnode(dg), i in eachnode(dg) + var = u[variable, i, j, element] + # Real Zalesak type limiter + # * Zalesak (1979). "Fully multidimensional flux-corrected transport algorithms for fluids" + # * Kuzmin et al. (2010). "Failsafe flux limiting and constrained data projections for equations of gas dynamics" + # Note: The Zalesak limiter has to be computed, even if the state is valid, because the correction is + # for each interface, not each node + + Qp = max(0, (var_max[i, j, element] - var) / dt) + Qm = min(0, (var_min[i, j, element] - var) / dt) + + # Calculate Pp and Pm + # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. + val_flux1_local = inverse_weights[i] * + antidiffusive_flux1_R[variable, i, j, element] + val_flux1_local_ip1 = -inverse_weights[i] * + antidiffusive_flux1_L[variable, i + 1, j, element] + val_flux2_local = inverse_weights[j] * + antidiffusive_flux2_R[variable, i, j, element] + val_flux2_local_jp1 = -inverse_weights[j] * + antidiffusive_flux2_L[variable, i, j + 1, element] + + Pp = max(0, val_flux1_local) + max(0, val_flux1_local_ip1) + + max(0, val_flux2_local) + max(0, val_flux2_local_jp1) + Pm = min(0, val_flux1_local) + min(0, val_flux1_local_ip1) + + min(0, val_flux2_local) + min(0, val_flux2_local_jp1) + + Qp = max(0, (var_max[i, j, element] - var) / dt) + Qm = min(0, (var_min[i, j, element] - var) / dt) + + Pp = inverse_jacobian * Pp + Pm = inverse_jacobian * Pm + + # Compute blending coefficient avoiding division by zero + # (as in paper of [Guermond, Nazarov, Popov, Thomas] (4.8)) + Qp = abs(Qp) / + (abs(Pp) + eps(typeof(Qp)) * 100 * abs(var_max[i, j, element])) + Qm = abs(Qm) / + (abs(Pm) + eps(typeof(Qm)) * 100 * abs(var_max[i, j, element])) + + # Calculate alpha at nodes + alpha[i, j, element] = max(alpha[i, j, element], 1 - min(1, Qp, Qm)) + end + end + + return nothing +end + @inline function idp_positivity!(alpha, limiter, u, dt, semi) # Conservative variables - for (index, variable) in enumerate(limiter.positivity_variables_cons) - idp_positivity!(alpha, limiter, u, dt, semi, variable, index) + for variable in limiter.positivity_variables_cons + idp_positivity!(alpha, limiter, u, dt, semi, variable) end return nothing end -@inline function idp_positivity!(alpha, limiter, u, dt, semi, variable, index) +@inline function idp_positivity!(alpha, limiter, u, dt, semi, variable) mesh, equations, dg, cache = mesh_equations_solver_cache(semi) - @unpack antidiffusive_flux1, antidiffusive_flux2 = cache.antidiffusive_fluxes - @unpack inverse_weights = dg.basis - @unpack positivity_correction_factor = limiter + (; antidiffusive_flux1_L, antidiffusive_flux2_L, antidiffusive_flux1_R, antidiffusive_flux2_R) = cache.antidiffusive_fluxes + (; inverse_weights) = dg.basis + (; positivity_correction_factor) = limiter - @unpack variable_bounds = limiter.cache.subcell_limiter_coefficients - - var_min = variable_bounds[index] + (; variable_bounds) = limiter.cache.subcell_limiter_coefficients + var_min = variable_bounds[Symbol(string(variable), "_min")] @threaded for element in eachelement(dg, semi.cache) inverse_jacobian = cache.elements.inverse_jacobian[element] @@ -76,6 +249,13 @@ end end # Compute bound + if limiter.local_minmax && + variable in limiter.local_minmax_variables_cons && + var_min[i, j, element] >= positivity_correction_factor * var + # Local limiting is more restrictive that positivity limiting + # => Skip positivity limiting for this node + continue + end var_min[i, j, element] = positivity_correction_factor * var # Real one-sided Zalesak-type limiter @@ -88,13 +268,13 @@ end # Calculate Pm # Note: Boundaries of antidiffusive_flux1/2 are constant 0, so they make no difference here. val_flux1_local = inverse_weights[i] * - antidiffusive_flux1[variable, i, j, element] + antidiffusive_flux1_R[variable, i, j, element] val_flux1_local_ip1 = -inverse_weights[i] * - antidiffusive_flux1[variable, i + 1, j, element] + antidiffusive_flux1_L[variable, i + 1, j, element] val_flux2_local = inverse_weights[j] * - antidiffusive_flux2[variable, i, j, element] + antidiffusive_flux2_R[variable, i, j, element] val_flux2_local_jp1 = -inverse_weights[j] * - antidiffusive_flux2[variable, i, j + 1, element] + antidiffusive_flux2_L[variable, i, j + 1, element] Pm = min(0, val_flux1_local) + min(0, val_flux1_local_ip1) + min(0, val_flux2_local) + min(0, val_flux2_local_jp1) diff --git a/src/solvers/dgsem_unstructured/containers_2d.jl b/src/solvers/dgsem_unstructured/containers_2d.jl index 13eeaeabffb..f51dd09801b 100644 --- a/src/solvers/dgsem_unstructured/containers_2d.jl +++ b/src/solvers/dgsem_unstructured/containers_2d.jl @@ -45,7 +45,7 @@ end eachelement(elements::UnstructuredElementContainer2D) Return an iterator over the indices that specify the location in relevant data structures -for the elements in `elements`. +for the elements in `elements`. In particular, not the elements themselves are returned. """ @inline function eachelement(elements::UnstructuredElementContainer2D) @@ -84,24 +84,25 @@ function init_elements!(elements::UnstructuredElementContainer2D, mesh, basis) # loop through elements and call the correct constructor based on whether the element is curved for element in eachelement(elements) if mesh.element_is_curved[element] - init_element!(elements, element, basis.nodes, + init_element!(elements, element, basis, view(mesh.surface_curves, :, element)) else # straight sided element for i in 1:4, j in 1:2 # pull the (x,y) values of these corners out of the global corners array four_corners[i, j] = mesh.corners[j, mesh.element_node_ids[i, element]] end - init_element!(elements, element, basis.nodes, four_corners) + init_element!(elements, element, basis, four_corners) end end end # initialize all the values in the container of a general element (either straight sided or curved) -function init_element!(elements, element, nodes, corners_or_surface_curves) - calc_node_coordinates!(elements.node_coordinates, element, nodes, +function init_element!(elements, element, basis::LobattoLegendreBasis, + corners_or_surface_curves) + calc_node_coordinates!(elements.node_coordinates, element, get_nodes(basis), corners_or_surface_curves) - calc_metric_terms!(elements.jacobian_matrix, element, nodes, + calc_metric_terms!(elements.jacobian_matrix, element, get_nodes(basis), corners_or_surface_curves) calc_inverse_jacobian!(elements.inverse_jacobian, element, elements.jacobian_matrix) @@ -109,7 +110,7 @@ function init_element!(elements, element, nodes, corners_or_surface_curves) calc_contravariant_vectors!(elements.contravariant_vectors, element, elements.jacobian_matrix) - calc_normal_directions!(elements.normal_directions, element, nodes, + calc_normal_directions!(elements.normal_directions, element, get_nodes(basis), corners_or_surface_curves) return elements diff --git a/src/solvers/dgsem_unstructured/dg_2d.jl b/src/solvers/dgsem_unstructured/dg_2d.jl index 7b8dafdddd2..b12a96c4c31 100644 --- a/src/solvers/dgsem_unstructured/dg_2d.jl +++ b/src/solvers/dgsem_unstructured/dg_2d.jl @@ -357,9 +357,9 @@ function calc_boundary_flux_by_type!(cache, t, BCs::Tuple{}, BC_indices::Tuple{} nothing end -function calc_boundary_flux!(cache, t, boundary_condition, boundary_indexing, +function calc_boundary_flux!(cache, t, boundary_condition::BC, boundary_indexing, mesh::UnstructuredMesh2D, equations, - surface_integral, dg::DG) + surface_integral, dg::DG) where {BC} @unpack surface_flux_values = cache.elements @unpack element_id, element_side_id = cache.boundaries diff --git a/src/solvers/dgsem_unstructured/sort_boundary_conditions.jl b/src/solvers/dgsem_unstructured/sort_boundary_conditions.jl index cad5542aae3..b5388cadc8b 100644 --- a/src/solvers/dgsem_unstructured/sort_boundary_conditions.jl +++ b/src/solvers/dgsem_unstructured/sort_boundary_conditions.jl @@ -56,7 +56,8 @@ function initialize!(boundary_types_container::UnstructuredSortedBoundaryTypes{N for key in keys(boundary_dictionary) if !(key in all_names) println(stderr, - "ERROR: Key $(repr(key)) is not a valid boundary name") + "ERROR: Key $(repr(key)) is not a valid boundary name. " * + "Valid names are $all_names.") MPI.Abort(mpi_comm(), 1) end end @@ -67,7 +68,8 @@ function initialize!(boundary_types_container::UnstructuredSortedBoundaryTypes{N else for key in keys(boundary_dictionary) if !(key in unique_names) - error("Key $(repr(key)) is not a valid boundary name") + error("Key $(repr(key)) is not a valid boundary name. " * + "Valid names are $unique_names.") end end end diff --git a/src/solvers/fdsbp_tree/fdsbp_2d.jl b/src/solvers/fdsbp_tree/fdsbp_2d.jl index beff605629a..09d18cecd75 100644 --- a/src/solvers/fdsbp_tree/fdsbp_2d.jl +++ b/src/solvers/fdsbp_tree/fdsbp_2d.jl @@ -9,7 +9,7 @@ #! format: noindent # 2D caches -function create_cache(mesh::TreeMesh{2}, equations, +function create_cache(mesh::Union{TreeMesh{2}, UnstructuredMesh2D}, equations, volume_integral::VolumeIntegralStrongForm, dg, uEltype) prototype = Array{SVector{nvariables(equations), uEltype}, ndims(mesh)}(undef, ntuple(_ -> nnodes(dg), diff --git a/src/solvers/fdsbp_unstructured/containers_2d.jl b/src/solvers/fdsbp_unstructured/containers_2d.jl new file mode 100644 index 00000000000..3857c2d8a20 --- /dev/null +++ b/src/solvers/fdsbp_unstructured/containers_2d.jl @@ -0,0 +1,124 @@ +# !!! warning "Experimental implementation (curvilinear FDSBP)" +# This is an experimental feature and may change in future releases. + +# By default, Julia/LLVM does not use fused multiply-add operations (FMAs). +# Since these FMAs can increase the performance of many numerical algorithms, +# we need to opt-in explicitly. +# See https://ranocha.de/blog/Optimizing_EC_Trixi for further details. +@muladd begin +#! format: noindent + +# initialize all the values in the container of a general FD block (either straight sided or curved) +# OBS! Requires the SBP derivative matrix in order to compute metric terms that are free-stream preserving +function init_element!(elements, element, basis::AbstractDerivativeOperator, + corners_or_surface_curves) + calc_node_coordinates!(elements.node_coordinates, element, get_nodes(basis), + corners_or_surface_curves) + + calc_metric_terms!(elements.jacobian_matrix, element, basis, + elements.node_coordinates) + + calc_inverse_jacobian!(elements.inverse_jacobian, element, elements.jacobian_matrix) + + calc_contravariant_vectors!(elements.contravariant_vectors, element, + elements.jacobian_matrix) + + calc_normal_directions!(elements.normal_directions, element, + elements.jacobian_matrix) + + return elements +end + +# construct the metric terms for a FDSBP element "block". Directly use the derivative matrix +# applied to the node coordinates. +# TODO: FD; How to make this work for the upwind solver because basis has three available derivative matrices +function calc_metric_terms!(jacobian_matrix, element, D_SBP::AbstractDerivativeOperator, + node_coordinates) + + # storage format: + # jacobian_matrix[1,1,:,:,:] <- X_xi + # jacobian_matrix[1,2,:,:,:] <- X_eta + # jacobian_matrix[2,1,:,:,:] <- Y_xi + # jacobian_matrix[2,2,:,:,:] <- Y_eta + + # Compute the xi derivatives by applying D on the left + # This is basically the same as + # jacobian_matrix[1, 1, :, :, element] = Matrix(D_SBP) * node_coordinates[1, :, :, element] + # but uses only matrix-vector products instead of a matrix-matrix product. + for j in eachnode(D_SBP) + mul!(view(jacobian_matrix, 1, 1, :, j, element), D_SBP, + view(node_coordinates, 1, :, j, element)) + end + # jacobian_matrix[2, 1, :, :, element] = Matrix(D_SBP) * node_coordinates[2, :, :, element] + for j in eachnode(D_SBP) + mul!(view(jacobian_matrix, 2, 1, :, j, element), D_SBP, + view(node_coordinates, 2, :, j, element)) + end + + # Compute the eta derivatives by applying transpose of D on the right + # jacobian_matrix[1, 2, :, :, element] = node_coordinates[1, :, :, element] * Matrix(D_SBP)' + for i in eachnode(D_SBP) + mul!(view(jacobian_matrix, 1, 2, i, :, element), D_SBP, + view(node_coordinates, 1, i, :, element)) + end + # jacobian_matrix[2, 2, :, :, element] = node_coordinates[2, :, :, element] * Matrix(D_SBP)' + for i in eachnode(D_SBP) + mul!(view(jacobian_matrix, 2, 2, i, :, element), D_SBP, + view(node_coordinates, 2, i, :, element)) + end + + return jacobian_matrix +end + +# construct the normal direction vectors (but not actually normalized) for a curved sided FDSBP element "block" +# normalization occurs on the fly during the surface flux computation +# OBS! This assumes that the boundary points are included. +function calc_normal_directions!(normal_directions, element, jacobian_matrix) + + # normal directions on the boundary for the left (local side 4) and right (local side 2) + N = size(jacobian_matrix, 4) + for j in 1:N + # +x side or side 2 in the local indexing + X_xi = jacobian_matrix[1, 1, N, j, element] + X_eta = jacobian_matrix[1, 2, N, j, element] + Y_xi = jacobian_matrix[2, 1, N, j, element] + Y_eta = jacobian_matrix[2, 2, N, j, element] + Jtemp = X_xi * Y_eta - X_eta * Y_xi + normal_directions[1, j, 2, element] = sign(Jtemp) * (Y_eta) + normal_directions[2, j, 2, element] = sign(Jtemp) * (-X_eta) + + # -x side or side 4 in the local indexing + X_xi = jacobian_matrix[1, 1, 1, j, element] + X_eta = jacobian_matrix[1, 2, 1, j, element] + Y_xi = jacobian_matrix[2, 1, 1, j, element] + Y_eta = jacobian_matrix[2, 2, 1, j, element] + Jtemp = X_xi * Y_eta - X_eta * Y_xi + normal_directions[1, j, 4, element] = -sign(Jtemp) * (Y_eta) + normal_directions[2, j, 4, element] = -sign(Jtemp) * (-X_eta) + end + + # normal directions on the boundary for the top (local side 3) and bottom (local side 1) + N = size(jacobian_matrix, 3) + for i in 1:N + # -y side or side 1 in the local indexing + X_xi = jacobian_matrix[1, 1, i, 1, element] + X_eta = jacobian_matrix[1, 2, i, 1, element] + Y_xi = jacobian_matrix[2, 1, i, 1, element] + Y_eta = jacobian_matrix[2, 2, i, 1, element] + Jtemp = X_xi * Y_eta - X_eta * Y_xi + normal_directions[1, i, 1, element] = -sign(Jtemp) * (-Y_xi) + normal_directions[2, i, 1, element] = -sign(Jtemp) * (X_xi) + + # +y side or side 3 in the local indexing + X_xi = jacobian_matrix[1, 1, i, N, element] + X_eta = jacobian_matrix[1, 2, i, N, element] + Y_xi = jacobian_matrix[2, 1, i, N, element] + Y_eta = jacobian_matrix[2, 2, i, N, element] + Jtemp = X_xi * Y_eta - X_eta * Y_xi + normal_directions[1, i, 3, element] = sign(Jtemp) * (-Y_xi) + normal_directions[2, i, 3, element] = sign(Jtemp) * (X_xi) + end + + return normal_directions +end +end # @muladd diff --git a/src/solvers/fdsbp_unstructured/fdsbp.jl b/src/solvers/fdsbp_unstructured/fdsbp.jl new file mode 100644 index 00000000000..dee9776abb7 --- /dev/null +++ b/src/solvers/fdsbp_unstructured/fdsbp.jl @@ -0,0 +1,14 @@ +# !!! warning "Experimental implementation (curvilinear FDSBP)" +# This is an experimental feature and may change in future releases. + +# By default, Julia/LLVM does not use fused multiply-add operations (FMAs). +# Since these FMAs can increase the performance of many numerical algorithms, +# we need to opt-in explicitly. +# See https://ranocha.de/blog/Optimizing_EC_Trixi for further details. +@muladd begin +#! format: noindent + +# dimension specific curvilinear implementations and data structures +include("containers_2d.jl") +include("fdsbp_2d.jl") +end # @muladd diff --git a/src/solvers/fdsbp_unstructured/fdsbp_2d.jl b/src/solvers/fdsbp_unstructured/fdsbp_2d.jl new file mode 100644 index 00000000000..b459f4c42cc --- /dev/null +++ b/src/solvers/fdsbp_unstructured/fdsbp_2d.jl @@ -0,0 +1,219 @@ +# !!! warning "Experimental implementation (curvilinear FDSBP)" +# This is an experimental feature and may change in future releases. + +# By default, Julia/LLVM does not use fused multiply-add operations (FMAs). +# Since these FMAs can increase the performance of many numerical algorithms, +# we need to opt-in explicitly. +# See https://ranocha.de/blog/Optimizing_EC_Trixi for further details. +@muladd begin +#! format: noindent + +# 2D unstructured cache +function create_cache(mesh::UnstructuredMesh2D, equations, dg::FDSBP, RealT, uEltype) + elements = init_elements(mesh, equations, dg.basis, RealT, uEltype) + + interfaces = init_interfaces(mesh, elements) + + boundaries = init_boundaries(mesh, elements) + + cache = (; elements, interfaces, boundaries) + + # Add specialized parts of the cache required to for efficient flux computations + cache = (; cache..., + create_cache(mesh, equations, dg.volume_integral, dg, uEltype)...) + + return cache +end + +# TODO: FD; Upwind versions of surface / volume integral + +# 2D volume integral contributions for `VolumeIntegralStrongForm` +# OBS! This is the standard (not de-aliased) form of the volume integral. +# So it is not provably stable for variable coefficients due to the the metric terms. +@inline function calc_volume_integral!(du, u, + mesh::UnstructuredMesh2D, + nonconservative_terms::False, equations, + volume_integral::VolumeIntegralStrongForm, + dg::FDSBP, cache) + D = dg.basis # SBP derivative operator + @unpack f_threaded = cache + @unpack contravariant_vectors = cache.elements + + # SBP operators from SummationByPartsOperators.jl implement the basic interface + # of matrix-vector multiplication. Thus, we pass an "array of structures", + # packing all variables per node in an `SVector`. + if nvariables(equations) == 1 + # `reinterpret(reshape, ...)` removes the leading dimension only if more + # than one variable is used. + u_vectors = reshape(reinterpret(SVector{nvariables(equations), eltype(u)}, u), + nnodes(dg), nnodes(dg), nelements(dg, cache)) + du_vectors = reshape(reinterpret(SVector{nvariables(equations), eltype(du)}, + du), + nnodes(dg), nnodes(dg), nelements(dg, cache)) + else + u_vectors = reinterpret(reshape, SVector{nvariables(equations), eltype(u)}, u) + du_vectors = reinterpret(reshape, SVector{nvariables(equations), eltype(du)}, + du) + end + + # Use the tensor product structure to compute the discrete derivatives of + # the contravariant fluxes line-by-line and add them to `du` for each element. + @threaded for element in eachelement(dg, cache) + f_element = f_threaded[Threads.threadid()] + u_element = view(u_vectors, :, :, element) + + # x direction + for j in eachnode(dg) + for i in eachnode(dg) + Ja1 = get_contravariant_vector(1, contravariant_vectors, i, j, element) + f_element[i, j] = flux(u_element[i, j], Ja1, equations) + end + mul!(view(du_vectors, :, j, element), D, view(f_element, :, j), + one(eltype(du)), one(eltype(du))) + end + + # y direction + for i in eachnode(dg) + for j in eachnode(dg) + Ja2 = get_contravariant_vector(2, contravariant_vectors, i, j, element) + f_element[i, j] = flux(u_element[i, j], Ja2, equations) + end + mul!(view(du_vectors, i, :, element), D, view(f_element, i, :), + one(eltype(du)), one(eltype(du))) + end + end + + return nothing +end + +# Note! The local side numbering for the unstructured quadrilateral element implementation differs +# from the structured TreeMesh or StructuredMesh local side numbering: +# +# TreeMesh/StructuredMesh sides versus UnstructuredMesh sides +# 4 3 +# ----------------- ----------------- +# | | | | +# | ^ eta | | ^ eta | +# 1 | | | 2 4 | | | 2 +# | | | | | | +# | ---> xi | | ---> xi | +# ----------------- ----------------- +# 3 1 +# Therefore, we require a different surface integral routine here despite their similar structure. +# Also, the normal directions are already outward pointing for `UnstructuredMesh2D` so all the +# surface contributions are added. +function calc_surface_integral!(du, u, mesh::UnstructuredMesh2D, + equations, surface_integral::SurfaceIntegralStrongForm, + dg::DG, cache) + inv_weight_left = inv(left_boundary_weight(dg.basis)) + inv_weight_right = inv(right_boundary_weight(dg.basis)) + @unpack normal_directions, surface_flux_values = cache.elements + + @threaded for element in eachelement(dg, cache) + for l in eachnode(dg) + # surface at -x + u_node = get_node_vars(u, equations, dg, 1, l, element) + # compute internal flux in normal direction on side 4 + outward_direction = get_node_coords(normal_directions, equations, dg, l, 4, + element) + f_node = flux(u_node, outward_direction, equations) + f_num = get_node_vars(surface_flux_values, equations, dg, l, 4, element) + multiply_add_to_node_vars!(du, inv_weight_left, (f_num - f_node), + equations, dg, 1, l, element) + + # surface at +x + u_node = get_node_vars(u, equations, dg, nnodes(dg), l, element) + # compute internal flux in normal direction on side 2 + outward_direction = get_node_coords(normal_directions, equations, dg, l, 2, + element) + f_node = flux(u_node, outward_direction, equations) + f_num = get_node_vars(surface_flux_values, equations, dg, l, 2, element) + multiply_add_to_node_vars!(du, inv_weight_right, (f_num - f_node), + equations, dg, nnodes(dg), l, element) + + # surface at -y + u_node = get_node_vars(u, equations, dg, l, 1, element) + # compute internal flux in normal direction on side 1 + outward_direction = get_node_coords(normal_directions, equations, dg, l, 1, + element) + f_node = flux(u_node, outward_direction, equations) + f_num = get_node_vars(surface_flux_values, equations, dg, l, 1, element) + multiply_add_to_node_vars!(du, inv_weight_left, (f_num - f_node), + equations, dg, l, 1, element) + + # surface at +y + u_node = get_node_vars(u, equations, dg, l, nnodes(dg), element) + # compute internal flux in normal direction on side 3 + outward_direction = get_node_coords(normal_directions, equations, dg, l, 3, + element) + f_node = flux(u_node, outward_direction, equations) + f_num = get_node_vars(surface_flux_values, equations, dg, l, 3, element) + multiply_add_to_node_vars!(du, inv_weight_right, (f_num - f_node), + equations, dg, l, nnodes(dg), element) + end + end + + return nothing +end + +# AnalysisCallback +function integrate_via_indices(func::Func, u, + mesh::UnstructuredMesh2D, equations, + dg::FDSBP, cache, args...; normalize = true) where {Func} + # TODO: FD. This is rather inefficient right now and allocates... + weights = diag(SummationByPartsOperators.mass_matrix(dg.basis)) + + # Initialize integral with zeros of the right shape + integral = zero(func(u, 1, 1, 1, equations, dg, args...)) + total_volume = zero(real(mesh)) + + # Use quadrature to numerically integrate over entire domain + for element in eachelement(dg, cache) + for j in eachnode(dg), i in eachnode(dg) + volume_jacobian = abs(inv(cache.elements.inverse_jacobian[i, j, element])) + integral += volume_jacobian * weights[i] * weights[j] * + func(u, i, j, element, equations, dg, args...) + total_volume += volume_jacobian * weights[i] * weights[j] + end + end + + # Normalize with total volume + if normalize + integral = integral / total_volume + end + + return integral +end + +function calc_error_norms(func, u, t, analyzer, + mesh::UnstructuredMesh2D, equations, initial_condition, + dg::FDSBP, cache, cache_analysis) + # TODO: FD. This is rather inefficient right now and allocates... + weights = diag(SummationByPartsOperators.mass_matrix(dg.basis)) + @unpack node_coordinates, inverse_jacobian = cache.elements + + # Set up data structures + l2_error = zero(func(get_node_vars(u, equations, dg, 1, 1, 1), equations)) + linf_error = copy(l2_error) + total_volume = zero(real(mesh)) + + # Iterate over all elements for error calculations + for element in eachelement(dg, cache) + for j in eachnode(analyzer), i in eachnode(analyzer) + volume_jacobian = abs(inv(cache.elements.inverse_jacobian[i, j, element])) + u_exact = initial_condition(get_node_coords(node_coordinates, equations, dg, + i, j, element), t, equations) + diff = func(u_exact, equations) - + func(get_node_vars(u, equations, dg, i, j, element), equations) + l2_error += diff .^ 2 * (weights[i] * weights[j] * volume_jacobian) + linf_error = @. max(linf_error, abs(diff)) + total_volume += weights[i] * weights[j] * volume_jacobian + end + end + + # For L2 error, divide by total volume + l2_error = @. sqrt(l2_error / total_volume) + + return l2_error, linf_error +end +end # @muladd diff --git a/src/time_integration/methods_2N.jl b/src/time_integration/methods_2N.jl index 557e8272128..f3b09b01e97 100644 --- a/src/time_integration/methods_2N.jl +++ b/src/time_integration/methods_2N.jl @@ -119,10 +119,10 @@ function solve(ode::ODEProblem, alg::T; # initialize callbacks if callback isa CallbackSet - for cb in callback.continuous_callbacks + foreach(callback.continuous_callbacks) do cb error("unsupported") end - for cb in callback.discrete_callbacks + foreach(callback.discrete_callbacks) do cb cb.initialize(cb, integrator.u, integrator.t, integrator) end elseif !isnothing(callback) @@ -172,10 +172,11 @@ function solve!(integrator::SimpleIntegrator2N) # handle callbacks if callbacks isa CallbackSet - for cb in callbacks.discrete_callbacks + foreach(callbacks.discrete_callbacks) do cb if cb.condition(integrator.u, integrator.t, integrator) cb.affect!(integrator) end + return nothing end end @@ -203,6 +204,11 @@ function set_proposed_dt!(integrator::SimpleIntegrator2N, dt) integrator.dt = dt end +# Required e.g. for `glm_speed_callback` +function get_proposed_dt(integrator::SimpleIntegrator2N) + return integrator.dt +end + # stop the time integration function terminate!(integrator::SimpleIntegrator2N) integrator.finalstep = true diff --git a/src/time_integration/methods_3Sstar.jl b/src/time_integration/methods_3Sstar.jl index 03232c04122..7b70466606c 100644 --- a/src/time_integration/methods_3Sstar.jl +++ b/src/time_integration/methods_3Sstar.jl @@ -189,10 +189,10 @@ function solve(ode::ODEProblem, alg::T; # initialize callbacks if callback isa CallbackSet - for cb in callback.continuous_callbacks + foreach(callback.continuous_callbacks) do cb error("unsupported") end - for cb in callback.discrete_callbacks + foreach(callback.discrete_callbacks) do cb cb.initialize(cb, integrator.u, integrator.t, integrator) end elseif !isnothing(callback) @@ -248,10 +248,11 @@ function solve!(integrator::SimpleIntegrator3Sstar) # handle callbacks if callbacks isa CallbackSet - for cb in callbacks.discrete_callbacks + foreach(callbacks.discrete_callbacks) do cb if cb.condition(integrator.u, integrator.t, integrator) cb.affect!(integrator) end + return nothing end end @@ -281,6 +282,11 @@ function set_proposed_dt!(integrator::SimpleIntegrator3Sstar, dt) integrator.dt = dt end +# Required e.g. for `glm_speed_callback` +function get_proposed_dt(integrator::SimpleIntegrator3Sstar) + return integrator.dt +end + # stop the time integration function terminate!(integrator::SimpleIntegrator3Sstar) integrator.finalstep = true diff --git a/src/time_integration/methods_SSP.jl b/src/time_integration/methods_SSP.jl index 8ecad69748b..9d1e06488b4 100644 --- a/src/time_integration/methods_SSP.jl +++ b/src/time_integration/methods_SSP.jl @@ -24,14 +24,21 @@ The third-order SSP Runge-Kutta method of Shu and Osher. This is an experimental feature and may change in future releases. """ struct SimpleSSPRK33{StageCallbacks} <: SimpleAlgorithmSSP - a::SVector{3, Float64} - b::SVector{3, Float64} + numerator_a::SVector{3, Float64} + numerator_b::SVector{3, Float64} + denominator::SVector{3, Float64} c::SVector{3, Float64} stage_callbacks::StageCallbacks function SimpleSSPRK33(; stage_callbacks = ()) - a = SVector(0.0, 3 / 4, 1 / 3) - b = SVector(1.0, 1 / 4, 2 / 3) + # Mathematically speaking, it is not necessary for the algorithm to split the factors + # into numerator and denominator. Otherwise, however, rounding errors of the order of + # the machine accuracy will occur, which will add up over time and thus endanger the + # conservation of the simulation. + # See also https://github.com/trixi-framework/Trixi.jl/pull/1640. + numerator_a = SVector(0.0, 3.0, 1.0) # a = numerator_a / denominator + numerator_b = SVector(1.0, 1.0, 2.0) # b = numerator_b / denominator + denominator = SVector(1.0, 4.0, 3.0) c = SVector(0.0, 1.0, 1 / 2) # Butcher tableau @@ -42,22 +49,31 @@ struct SimpleSSPRK33{StageCallbacks} <: SimpleAlgorithmSSP # -------------------- # b | 1/6 1/6 2/3 - new{typeof(stage_callbacks)}(a, b, c, stage_callbacks) + new{typeof(stage_callbacks)}(numerator_a, numerator_b, denominator, c, + stage_callbacks) end end # This struct is needed to fake https://github.com/SciML/OrdinaryDiffEq.jl/blob/0c2048a502101647ac35faabd80da8a5645beac7/src/integrators/type.jl#L1 -mutable struct SimpleIntegratorSSPOptions{Callback} +mutable struct SimpleIntegratorSSPOptions{Callback, TStops} callback::Callback # callbacks; used in Trixi adaptive::Bool # whether the algorithm is adaptive; ignored dtmax::Float64 # ignored maxiters::Int # maximal number of time steps - tstops::Vector{Float64} # tstops from https://diffeq.sciml.ai/v6.8/basics/common_solver_opts/#Output-Control-1; ignored + tstops::TStops # tstops from https://diffeq.sciml.ai/v6.8/basics/common_solver_opts/#Output-Control-1; ignored end function SimpleIntegratorSSPOptions(callback, tspan; maxiters = typemax(Int), kwargs...) - SimpleIntegratorSSPOptions{typeof(callback)}(callback, false, Inf, maxiters, - [last(tspan)]) + tstops_internal = BinaryHeap{eltype(tspan)}(FasterForward()) + # We add last(tspan) to make sure that the time integration stops at the end time + push!(tstops_internal, last(tspan)) + # We add 2 * last(tspan) because add_tstop!(integrator, t) is only called by DiffEqCallbacks.jl if tstops contains a time that is larger than t + # (https://github.com/SciML/DiffEqCallbacks.jl/blob/025dfe99029bd0f30a2e027582744528eb92cd24/src/iterative_and_periodic.jl#L92) + push!(tstops_internal, 2 * last(tspan)) + SimpleIntegratorSSPOptions{typeof(callback), typeof(tstops_internal)}(callback, + false, Inf, + maxiters, + tstops_internal) end # This struct is needed to fake https://github.com/SciML/OrdinaryDiffEq.jl/blob/0c2048a502101647ac35faabd80da8a5645beac7/src/integrators/type.jl#L77 @@ -70,6 +86,7 @@ mutable struct SimpleIntegratorSSP{RealT <: Real, uType, Params, Sol, F, Alg, du::uType r0::uType t::RealT + tdir::RealT dt::RealT # current time step dtcache::RealT # ignored iter::Int # current number of time steps (iteration) @@ -79,8 +96,29 @@ mutable struct SimpleIntegratorSSP{RealT <: Real, uType, Params, Sol, F, Alg, alg::Alg opts::SimpleIntegratorSSPOptions finalstep::Bool # added for convenience + dtchangeable::Bool + force_stepfail::Bool end +""" + add_tstop!(integrator::SimpleIntegratorSSP, t) +Add a time stop during the time integration process. +This function is called after the periodic SaveSolutionCallback to specify the next stop to save the solution. +""" +function add_tstop!(integrator::SimpleIntegratorSSP, t) + integrator.tdir * (t - integrator.t) < zero(integrator.t) && + error("Tried to add a tstop that is behind the current time. This is strictly forbidden") + # We need to remove the first entry of tstops when a new entry is added. + # Otherwise, the simulation gets stuck at the previous tstop and dt is adjusted to zero. + if length(integrator.opts.tstops) > 1 + pop!(integrator.opts.tstops) + end + push!(integrator.opts.tstops, integrator.tdir * t) +end + +has_tstop(integrator::SimpleIntegratorSSP) = !isempty(integrator.opts.tstops) +first_tstop(integrator::SimpleIntegratorSSP) = first(integrator.opts.tstops) + # Forward integrator.stats.naccept to integrator.iter (see GitHub PR#771) function Base.getproperty(integrator::SimpleIntegratorSSP, field::Symbol) if field === :stats @@ -105,21 +143,23 @@ function solve(ode::ODEProblem, alg = SimpleSSPRK33()::SimpleAlgorithmSSP; du = similar(u) r0 = similar(u) t = first(ode.tspan) + tdir = sign(ode.tspan[end] - ode.tspan[1]) iter = 0 - integrator = SimpleIntegratorSSP(u, du, r0, t, dt, zero(dt), iter, ode.p, + integrator = SimpleIntegratorSSP(u, du, r0, t, tdir, dt, zero(dt), iter, ode.p, (prob = ode,), ode.f, alg, SimpleIntegratorSSPOptions(callback, ode.tspan; - kwargs...), false) + kwargs...), + false, true, false) # resize container resize!(integrator.p, nelements(integrator.p.solver, integrator.p.cache)) # initialize callbacks if callback isa CallbackSet - for cb in callback.continuous_callbacks + foreach(callback.continuous_callbacks) do cb error("unsupported") end - for cb in callback.discrete_callbacks + foreach(callback.discrete_callbacks) do cb cb.initialize(cb, integrator.u, integrator.t, integrator) end elseif !isnothing(callback) @@ -140,7 +180,7 @@ function solve!(integrator::SimpleIntegratorSSP) callbacks = integrator.opts.callback integrator.finalstep = false - while !integrator.finalstep + @trixi_timeit timer() "main loop" while !integrator.finalstep if isnan(integrator.dt) error("time step size `dt` is NaN") end @@ -152,6 +192,8 @@ function solve!(integrator::SimpleIntegratorSSP) terminate!(integrator) end + modify_dt_for_tstops!(integrator) + @. integrator.r0 = integrator.u for stage in eachindex(alg.c) t_stage = integrator.t + integrator.dt * alg.c[stage] @@ -166,7 +208,9 @@ function solve!(integrator::SimpleIntegratorSSP) end # perform convex combination - @. integrator.u = alg.a[stage] * integrator.r0 + alg.b[stage] * integrator.u + @. integrator.u = (alg.numerator_a[stage] * integrator.r0 + + alg.numerator_b[stage] * integrator.u) / + alg.denominator[stage] end integrator.iter += 1 @@ -174,7 +218,7 @@ function solve!(integrator::SimpleIntegratorSSP) # handle callbacks if callbacks isa CallbackSet - for cb in callbacks.discrete_callbacks + foreach(callbacks.discrete_callbacks) do cb if cb.condition(integrator.u, integrator.t, integrator) cb.affect!(integrator) end @@ -188,6 +232,10 @@ function solve!(integrator::SimpleIntegratorSSP) end end + # Empty the tstops array. + # This cannot be done in terminate!(integrator::SimpleIntegratorSSP) because DiffEqCallbacks.PeriodicCallbackAffect would return at error. + extract_all!(integrator.opts.tstops) + for stage_callback in alg.stage_callbacks finalize_callback(stage_callback, integrator.p) end @@ -208,10 +256,38 @@ function set_proposed_dt!(integrator::SimpleIntegratorSSP, dt) integrator.dt = dt end +# used by adaptive timestepping algorithms in DiffEq +function get_proposed_dt(integrator::SimpleIntegratorSSP) + return integrator.dt +end + # stop the time integration function terminate!(integrator::SimpleIntegratorSSP) integrator.finalstep = true - empty!(integrator.opts.tstops) +end + +""" + modify_dt_for_tstops!(integrator::SimpleIntegratorSSP) +Modify the time-step size to match the time stops specified in integrator.opts.tstops. +To avoid adding OrdinaryDiffEq to Trixi's dependencies, this routine is a copy of +https://github.com/SciML/OrdinaryDiffEq.jl/blob/d76335281c540ee5a6d1bd8bb634713e004f62ee/src/integrators/integrator_utils.jl#L38-L54 +""" +function modify_dt_for_tstops!(integrator::SimpleIntegratorSSP) + if has_tstop(integrator) + tdir_t = integrator.tdir * integrator.t + tdir_tstop = first_tstop(integrator) + if integrator.opts.adaptive + integrator.dt = integrator.tdir * + min(abs(integrator.dt), abs(tdir_tstop - tdir_t)) # step! to the end + elseif iszero(integrator.dtcache) && integrator.dtchangeable + integrator.dt = integrator.tdir * abs(tdir_tstop - tdir_t) + elseif integrator.dtchangeable && !integrator.force_stepfail + # always try to step! with dtcache, but lower if a tstop + # however, if force_stepfail then don't set to dtcache, and no tstop worry + integrator.dt = integrator.tdir * + min(abs(integrator.dtcache), abs(tdir_tstop - tdir_t)) # step! to the end + end + end end # used for AMR @@ -221,7 +297,9 @@ function Base.resize!(integrator::SimpleIntegratorSSP, new_size) resize!(integrator.r0, new_size) # Resize container - resize!(integrator.p, new_size) + # new_size = n_variables * n_nodes^n_dims * n_elements + n_elements = nelements(integrator.p.solver, integrator.p.cache) + resize!(integrator.p, n_elements) end function Base.resize!(semi::AbstractSemidiscretization, new_size) diff --git a/src/visualization/recipes_plots.jl b/src/visualization/recipes_plots.jl index d15f7e542e1..0e9b5a66a8d 100644 --- a/src/visualization/recipes_plots.jl +++ b/src/visualization/recipes_plots.jl @@ -57,11 +57,8 @@ end # Visualize the mesh in a 2D plot # # Note: This is an experimental feature and may be changed in future releases without notice. -RecipesBase.@recipe function f(pm::PlotMesh{ - <:PlotData2DCartesian{<:Any, - <:AbstractVector{ - <:AbstractVector - }}}) +RecipesBase.@recipe function f(pm::PlotMesh{<:PlotData2DCartesian{<:Any, + <:AbstractVector{<:AbstractVector}}}) @unpack plot_data = pm @unpack x, y, mesh_vertices_x, mesh_vertices_y = plot_data diff --git a/test/Project.toml b/test/Project.toml index 7115a19b441..ecae0ac0900 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -1,17 +1,7 @@ -[compat] -BSON = "0.3.3" -CairoMakie = "0.6, 0.7, 0.8, 0.9, 0.10" -Flux = "0.13 - 0.13.12" # TODO: Return to "0.13" once https://github.com/FluxML/Flux.jl/issues/2204 is resolved -ForwardDiff = "0.10" -MPI = "0.20" -OrdinaryDiffEq = "6.49.1" -Plots = "1.16" - [deps] -BSON = "fbb218c0-5317-5bc6-957e-2ee96dd4b1f0" +Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0" Downloads = "f43a241f-c20a-4ad4-852c-f6b1247861c6" -Flux = "587475ba-b771-5e3f-ad9e-33799f191a9c" ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" MPI = "da04e1cc-30fd-572f-bb4f-1f8673147195" @@ -21,6 +11,19 @@ Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" +[compat] +Aqua = "0.8" +CairoMakie = "0.6, 0.7, 0.8, 0.9, 0.10" +Downloads = "1" +ForwardDiff = "0.10" +LinearAlgebra = "1" +MPI = "0.20" +OrdinaryDiffEq = "6.49.1" +Plots = "1.16" +Printf = "1" +Random = "1" +Test = "1" + [preferences.OrdinaryDiffEq] PrecompileAutoSpecialize = false PrecompileAutoSwitch = false diff --git a/test/coverage/coverage.jl b/test/coverage/coverage.jl index fbe89acf702..5f1ae8af8fc 100644 --- a/test/coverage/coverage.jl +++ b/test/coverage/coverage.jl @@ -9,28 +9,28 @@ const lcov_info_file = "lcov.info" # Change path to root directory cd(joinpath(@__DIR__, "..", "..")) do - # Process coverage files - processed = process_folder("src") - - # Uncomment the following line once Codecov support is enabled - # Codecov.submit_local(processed) - - # Calculate coverage - covered_lines, total_lines = get_summary(processed) - percentage = covered_lines / total_lines * 100 - - # Print coverage in a format that can be easily parsed - println("($(percentage)%) covered") - - # Try to generate a coverage report - isdir(report_dir) || mkdir(report_dir) - tracefile = joinpath(report_dir, lcov_info_file) - Coverage.LCOV.writefile(tracefile, processed) - branch = strip(read(`git rev-parse --abbrev-ref HEAD`, String)) - commit = strip(read(`git rev-parse --short HEAD`, String)) - title = "commit $(commit) on branch $(branch)" - run(`genhtml -t $(title) -o $(report_dir) $(tracefile)`) - - # Clean up .cov files - clean_folder("src") + # Process coverage files + processed = process_folder("src") + + # Uncomment the following line once Codecov support is enabled + # Codecov.submit_local(processed) + + # Calculate coverage + covered_lines, total_lines = get_summary(processed) + percentage = covered_lines / total_lines * 100 + + # Print coverage in a format that can be easily parsed + println("($(percentage)%) covered") + + # Try to generate a coverage report + isdir(report_dir) || mkdir(report_dir) + tracefile = joinpath(report_dir, lcov_info_file) + Coverage.LCOV.writefile(tracefile, processed) + branch = strip(read(`git rev-parse --abbrev-ref HEAD`, String)) + commit = strip(read(`git rev-parse --short HEAD`, String)) + title = "commit $(commit) on branch $(branch)" + run(`genhtml -t $(title) -o $(report_dir) $(tracefile)`) + + # Clean up .cov files + clean_folder("src") end diff --git a/test/runtests.jl b/test/runtests.jl index 55ea552a350..49f0977bb70 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -113,6 +113,7 @@ const TRIXI_NTHREADS = clamp(Sys.CPU_THREADS, 2, 3) @time if TRIXI_TEST == "all" || TRIXI_TEST == "misc_part2" include("test_special_elixirs.jl") + include("test_aqua.jl") end @time if TRIXI_TEST == "all" || TRIXI_TEST == "performance_specializations_part1" diff --git a/test/test_aqua.jl b/test/test_aqua.jl new file mode 100644 index 00000000000..93457caba28 --- /dev/null +++ b/test/test_aqua.jl @@ -0,0 +1,18 @@ +module TestAqua + +using Aqua +using Test +using Trixi + +include("test_trixi.jl") + +@timed_testset "Aqua.jl" begin + Aqua.test_all(Trixi, + ambiguities = false, + # exceptions necessary for adding a new method `StartUpDG.estimate_h` + # in src/solvers/dgmulti/sbp.jl + piracies = (treat_as_own = [Trixi.StartUpDG.RefElemData, + Trixi.StartUpDG.MeshData],)) +end + +end #module diff --git a/test/test_dgmulti_1d.jl b/test/test_dgmulti_1d.jl index 7cc31c33040..79ad64075b4 100644 --- a/test/test_dgmulti_1d.jl +++ b/test/test_dgmulti_1d.jl @@ -9,78 +9,162 @@ EXAMPLES_DIR = joinpath(examples_dir(), "dgmulti_1d") # Start with a clean environment: remove Trixi.jl output directory if it exists outdir = "out" -isdir(outdir) && rm(outdir, recursive=true) +isdir(outdir) && rm(outdir, recursive = true) @testset "DGMulti 1D" begin +#! format: noindent - @trixi_testset "elixir_advection_gauss_sbp.jl " begin +@trixi_testset "elixir_advection_gauss_sbp.jl " begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_gauss_sbp.jl"), - cells_per_dimension = (8,), - l2 = [2.9953644500009865e-5], - linf = [4.467840577382365e-5] - ) - end + cells_per_dimension=(8,), + l2=[2.9953644500009865e-5], + linf=[4.467840577382365e-5]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_flux_diff.jl " begin +@trixi_testset "elixir_euler_flux_diff.jl " begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_flux_diff.jl"), - cells_per_dimension = (16,), - # division by sqrt(2.0) corresponds to normalization by the square root of the size of the domain - l2 = [7.853842541289665e-7, 9.609905503440606e-7, 2.832322219966481e-6] ./ sqrt(2.0), - linf = [1.5003758788711963e-6, 1.802998748523521e-6, 4.83599270806323e-6] - ) - end + cells_per_dimension=(16,), + # division by sqrt(2.0) corresponds to normalization by the square root of the size of the domain + l2=[ + 7.853842541289665e-7, + 9.609905503440606e-7, + 2.832322219966481e-6, + ] ./ sqrt(2.0), + linf=[ + 1.5003758788711963e-6, + 1.802998748523521e-6, + 4.83599270806323e-6, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_flux_diff.jl (convergence)" begin - mean_convergence = convergence_test(@__MODULE__, joinpath(EXAMPLES_DIR, "elixir_euler_flux_diff.jl"), 3) - @test isapprox(mean_convergence[:l2], [4.1558759698638434, 3.977911306037128, 4.041421206468769], rtol=0.05) - end +@trixi_testset "elixir_euler_flux_diff.jl (convergence)" begin + mean_convergence = convergence_test(@__MODULE__, + joinpath(EXAMPLES_DIR, + "elixir_euler_flux_diff.jl"), 3) + @test isapprox(mean_convergence[:l2], + [4.1558759698638434, 3.977911306037128, 4.041421206468769], + rtol = 0.05) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_flux_diff.jl (SBP) " begin +@trixi_testset "elixir_euler_flux_diff.jl (SBP) " begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_flux_diff.jl"), - cells_per_dimension = (16,), - approximation_type = SBP(), - l2 = [6.437827414849647e-6, 2.1840558851820947e-6, 1.3245669629438228e-5], - linf = [2.0715843751295537e-5, 8.519520630301258e-6, 4.2642194098885255e-5] - ) - end + cells_per_dimension=(16,), + approximation_type=SBP(), + l2=[ + 6.437827414849647e-6, + 2.1840558851820947e-6, + 1.3245669629438228e-5, + ], + linf=[ + 2.0715843751295537e-5, + 8.519520630301258e-6, + 4.2642194098885255e-5, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_flux_diff.jl (FD SBP)" begin +@trixi_testset "elixir_euler_flux_diff.jl (FD SBP)" begin + global D = derivative_operator(SummationByPartsOperators.MattssonNordström2004(), + derivative_order = 1, + accuracy_order = 4, + xmin = 0.0, xmax = 1.0, + N = 16) @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_flux_diff.jl"), - cells_per_dimension = (4,), - approximation_type = derivative_operator( - SummationByPartsOperators.MattssonNordström2004(), - derivative_order=1, accuracy_order=4, - xmin=0.0, xmax=1.0, N=16), - l2 = [1.8684509287853788e-5, 1.0641411823379635e-5, 5.178010291876143e-5], - linf = [6.933493585936645e-5, 3.0277366229292113e-5, 0.0002220020568932668] - ) + cells_per_dimension=(4,), + approximation_type=D, + l2=[ + 1.8684509287853788e-5, + 1.0641411823379635e-5, + 5.178010291876143e-5, + ], + linf=[ + 6.933493585936645e-5, + 3.0277366229292113e-5, + 0.0002220020568932668, + ]) show(stdout, semi.solver.basis) show(stdout, MIME"text/plain"(), semi.solver.basis) - end + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_fdsbp_periodic.jl" begin +@trixi_testset "elixir_euler_fdsbp_periodic.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_fdsbp_periodic.jl"), - l2 = [9.146929180585711e-7, 1.8997616878017292e-6, 3.991417702211889e-6], - linf = [1.7321089884614338e-6, 3.3252888855805907e-6, 6.5252787737613005e-6] - ) + l2=[ + 9.146929180585711e-7, + 1.8997616878017292e-6, + 3.991417702211889e-6, + ], + linf=[ + 1.7321089884614338e-6, + 3.3252888855805907e-6, + 6.5252787737613005e-6, + ]) show(stdout, semi.solver.basis) show(stdout, MIME"text/plain"(), semi.solver.basis) - end + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "DGMulti with periodic SBP unit test" begin +@trixi_testset "DGMulti with periodic SBP unit test" begin # see https://github.com/trixi-framework/Trixi.jl/pull/1013 - dg = DGMulti(element_type = Line(), - approximation_type = periodic_derivative_operator( - derivative_order=1, accuracy_order=4, xmin=-5.0, xmax=10.0, N=50)) + global D = periodic_derivative_operator(derivative_order = 1, + accuracy_order = 4, + xmin = -5.0, + xmax = 10.0, N = 50) + dg = DGMulti(element_type = Line(), approximation_type = D) mesh = DGMultiMesh(dg) @test mapreduce(isapprox, &, mesh.md.xyz, dg.basis.rst) # check to make sure nodes are rescaled to [-1, 1] @test minimum(dg.basis.rst[1]) ≈ -1 - @test maximum(dg.basis.rst[1]) ≈ 1 atol=0.35 - end + @test maximum(dg.basis.rst[1])≈1 atol=0.35 +end end # Clean up afterwards: delete Trixi.jl output directory -@test_nowarn isdir(outdir) && rm(outdir, recursive=true) +@test_nowarn isdir(outdir) && rm(outdir, recursive = true) end # module diff --git a/test/test_dgmulti_2d.jl b/test/test_dgmulti_2d.jl index 861e30045ce..892c8ed37f0 100644 --- a/test/test_dgmulti_2d.jl +++ b/test/test_dgmulti_2d.jl @@ -9,357 +9,943 @@ EXAMPLES_DIR = joinpath(examples_dir(), "dgmulti_2d") # Start with a clean environment: remove Trixi.jl output directory if it exists outdir = "out" -isdir(outdir) && rm(outdir, recursive=true) +isdir(outdir) && rm(outdir, recursive = true) @testset "DGMulti 2D" begin +#! format: noindent - @trixi_testset "elixir_euler_weakform.jl" begin +@trixi_testset "elixir_euler_weakform.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_weakform.jl"), - cells_per_dimension = (4, 4), - # division by 2.0 corresponds to normalization by the square root of the size of the domain - l2 = [0.0013536930300254945, 0.0014315603442106193, 0.001431560344211359, 0.0047393341007602625] ./ 2.0, - linf = [0.001514260921466004, 0.0020623991944839215, 0.002062399194485476, 0.004897700392503701] - ) - end - - @trixi_testset "elixir_euler_weakform.jl (SBP)" begin + cells_per_dimension=(4, 4), + # division by 2.0 corresponds to normalization by the square root of the size of the domain + l2=[ + 0.0013536930300254945, + 0.0014315603442106193, + 0.001431560344211359, + 0.0047393341007602625, + ] ./ 2.0, + linf=[ + 0.001514260921466004, + 0.0020623991944839215, + 0.002062399194485476, + 0.004897700392503701, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_weakform.jl (SBP)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_weakform.jl"), - cells_per_dimension = (4, 4), - approximation_type = SBP(), - # division by 2.0 corresponds to normalization by the square root of the size of the domain - l2 = [0.0074706882014934735, 0.005306220583603261, 0.005306220583613591, 0.014724842607716771] ./ 2.0, - linf = [0.021563604940952885, 0.01359397832530762, 0.013593978324845324, 0.03270995869587523] - ) - end - - @trixi_testset "elixir_euler_weakform.jl (Quadrilateral elements)" begin + cells_per_dimension=(4, 4), + approximation_type=SBP(), + # division by 2.0 corresponds to normalization by the square root of the size of the domain + l2=[ + 0.0074706882014934735, + 0.005306220583603261, + 0.005306220583613591, + 0.014724842607716771, + ] ./ 2.0, + linf=[ + 0.021563604940952885, + 0.01359397832530762, + 0.013593978324845324, + 0.03270995869587523, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_weakform.jl (Quadrilateral elements)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_weakform.jl"), - cells_per_dimension = (4, 4), - element_type = Quad(), - # division by 2.0 corresponds to normalization by the square root of the size of the domain - l2 = [0.00031892254415307093, 0.00033637562986771894, 0.0003363756298680649, 0.0011100259064243145] ./ 2.0, - linf = [0.001073298211445639, 0.0013568139808282087, 0.0013568139808290969, 0.0032249020004324613] - ) - end - - @trixi_testset "elixir_euler_weakform.jl (EC) " begin + cells_per_dimension=(4, 4), + element_type=Quad(), + # division by 2.0 corresponds to normalization by the square root of the size of the domain + l2=[ + 0.00031892254415307093, + 0.00033637562986771894, + 0.0003363756298680649, + 0.0011100259064243145, + ] ./ 2.0, + linf=[ + 0.001073298211445639, + 0.0013568139808282087, + 0.0013568139808290969, + 0.0032249020004324613, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_weakform.jl (EC) " begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_weakform.jl"), - cells_per_dimension = (4, 4), - volume_integral = VolumeIntegralFluxDifferencing(flux_ranocha), - surface_integral = SurfaceIntegralWeakForm(flux_ranocha), - # division by 2.0 corresponds to normalization by the square root of the size of the domain - l2 = [0.007801417730672109, 0.00708583561714128, 0.0070858356171393, 0.015217574294198809] ./ 2.0, - linf = [0.011572828457858897, 0.013965298735070686, 0.01396529873508534, 0.04227683691807904] - ) - end - - @trixi_testset "elixir_euler_weakform.jl (SBP, EC)" begin + cells_per_dimension=(4, 4), + volume_integral=VolumeIntegralFluxDifferencing(flux_ranocha), + surface_integral=SurfaceIntegralWeakForm(flux_ranocha), + # division by 2.0 corresponds to normalization by the square root of the size of the domain + l2=[ + 0.007801417730672109, + 0.00708583561714128, + 0.0070858356171393, + 0.015217574294198809, + ] ./ 2.0, + linf=[ + 0.011572828457858897, + 0.013965298735070686, + 0.01396529873508534, + 0.04227683691807904, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_weakform.jl (SBP, EC)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_weakform.jl"), - cells_per_dimension = (4, 4), - volume_integral = VolumeIntegralFluxDifferencing(flux_ranocha), - surface_integral = SurfaceIntegralWeakForm(flux_ranocha), - approximation_type = SBP(), - # division by 2.0 corresponds to normalization by the square root of the size of the domain - l2 = [0.01280067571168776, 0.010607599608273302, 0.010607599608239775, 0.026408338014056548] ./ 2.0, - linf = [0.037983023185674814, 0.05321027922533417, 0.05321027922608157, 0.13392025411844033] - ) - end - - @trixi_testset "elixir_euler_weakform.jl (Quadrilateral elements, SBP, EC)" begin + cells_per_dimension=(4, 4), + volume_integral=VolumeIntegralFluxDifferencing(flux_ranocha), + surface_integral=SurfaceIntegralWeakForm(flux_ranocha), + approximation_type=SBP(), + # division by 2.0 corresponds to normalization by the square root of the size of the domain + l2=[ + 0.01280067571168776, + 0.010607599608273302, + 0.010607599608239775, + 0.026408338014056548, + ] ./ 2.0, + linf=[ + 0.037983023185674814, + 0.05321027922533417, + 0.05321027922608157, + 0.13392025411844033, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_weakform.jl (Quadrilateral elements, SBP, EC)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_weakform.jl"), - cells_per_dimension = (4, 4), - element_type = Quad(), - volume_integral = VolumeIntegralFluxDifferencing(flux_ranocha), - surface_integral = SurfaceIntegralWeakForm(flux_ranocha), - approximation_type = SBP(), - # division by 2.0 corresponds to normalization by the square root of the size of the domain - l2 = [0.0029373718090697975, 0.0030629360605489465, 0.003062936060545615, 0.0068486089344859755] ./ 2.0, - linf = [0.01360165305316885, 0.01267402847925303, 0.012674028479251254, 0.02210545278615017] - ) - end - - @trixi_testset "elixir_euler_bilinear.jl (Bilinear quadrilateral elements, SBP, flux differencing)" begin + cells_per_dimension=(4, 4), + element_type=Quad(), + volume_integral=VolumeIntegralFluxDifferencing(flux_ranocha), + surface_integral=SurfaceIntegralWeakForm(flux_ranocha), + approximation_type=SBP(), + # division by 2.0 corresponds to normalization by the square root of the size of the domain + l2=[ + 0.0029373718090697975, + 0.0030629360605489465, + 0.003062936060545615, + 0.0068486089344859755, + ] ./ 2.0, + linf=[ + 0.01360165305316885, + 0.01267402847925303, + 0.012674028479251254, + 0.02210545278615017, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_bilinear.jl (Bilinear quadrilateral elements, SBP, flux differencing)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_bilinear.jl"), - l2 = [1.0259435706215337e-5, 9.014090233720625e-6, 9.014090233223014e-6, 2.738953587401793e-5], - linf = [7.362609083649829e-5, 6.874188055272512e-5, 6.874188052830021e-5, 0.0001912435192696904] - ) - end + l2=[ + 1.0259435706215337e-5, + 9.014090233720625e-6, + 9.014090233223014e-6, + 2.738953587401793e-5, + ], + linf=[ + 7.362609083649829e-5, + 6.874188055272512e-5, + 6.874188052830021e-5, + 0.0001912435192696904, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_curved.jl (Quadrilateral elements, SBP, flux differencing)" begin +@trixi_testset "elixir_euler_curved.jl (Quadrilateral elements, SBP, flux differencing)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_curved.jl"), - l2 = [1.720476068165337e-5, 1.592168205710526e-5, 1.592168205812963e-5, 4.894094865697305e-5], - linf = [0.00010525416930584619, 0.00010003778091061122, 0.00010003778085621029, 0.00036426282101720275] - ) - end + l2=[ + 1.720476068165337e-5, + 1.592168205710526e-5, + 1.592168205812963e-5, + 4.894094865697305e-5, + ], + linf=[ + 0.00010525416930584619, + 0.00010003778091061122, + 0.00010003778085621029, + 0.00036426282101720275, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_curved.jl (Quadrilateral elements, GaussSBP, flux differencing)" begin +@trixi_testset "elixir_euler_curved.jl (Quadrilateral elements, GaussSBP, flux differencing)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_curved.jl"), - approximation_type = GaussSBP(), - l2 = [3.4666312079259457e-6, 3.4392774480368986e-6, 3.439277447953705e-6, 1.0965598424665836e-5], - linf = [1.1327280377004811e-5, 1.1343911926253725e-5, 1.1343911906935844e-5, 3.679582619220412e-5], - rtol = 2 * sqrt(eps()) - ) - end - - @trixi_testset "elixir_euler_curved.jl (Triangular elements, Polynomial, weak formulation)" begin + approximation_type=GaussSBP(), + l2=[ + 3.4666312079259457e-6, + 3.4392774480368986e-6, + 3.439277447953705e-6, + 1.0965598424665836e-5, + ], + linf=[ + 1.1327280377004811e-5, + 1.1343911926253725e-5, + 1.1343911906935844e-5, + 3.679582619220412e-5, + ], + rtol=2 * sqrt(eps())) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_curved.jl (Triangular elements, Polynomial, weak formulation)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_curved.jl"), - element_type = Tri(), approximation_type = Polynomial(), volume_integral = VolumeIntegralWeakForm(), - l2 = [7.905498158659466e-6, 8.731690809663625e-6, 8.731690811576996e-6, 2.9113296018693953e-5], - linf = [3.298811230090237e-5, 4.032272476939269e-5, 4.032272526011127e-5, 0.00012013725458537294] - ) - end + element_type=Tri(), approximation_type=Polynomial(), + volume_integral=VolumeIntegralWeakForm(), + l2=[ + 7.905498158659466e-6, + 8.731690809663625e-6, + 8.731690811576996e-6, + 2.9113296018693953e-5, + ], + linf=[ + 3.298811230090237e-5, + 4.032272476939269e-5, + 4.032272526011127e-5, + 0.00012013725458537294, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_hohqmesh.jl (Quadrilateral elements, SBP, flux differencing)" begin +@trixi_testset "elixir_euler_hohqmesh.jl (Quadrilateral elements, SBP, flux differencing)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_hohqmesh.jl"), - l2 = [0.0008153911341517156, 0.0007768159701964676, 0.00047902606811690694, 0.0015551846076348535], - linf = [0.0029301131365355726, 0.0034427051471457304, 0.0028721569841545502, 0.011125365074589944] - ) - end + l2=[ + 0.0008153911341517156, + 0.0007768159701964676, + 0.00047902606811690694, + 0.0015551846076348535, + ], + linf=[ + 0.0029301131365355726, + 0.0034427051471457304, + 0.0028721569841545502, + 0.011125365074589944, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_weakform.jl (convergence)" begin - mean_convergence = convergence_test(@__MODULE__, joinpath(EXAMPLES_DIR, "elixir_euler_weakform.jl"), 2) - @test isapprox(mean_convergence[:l2], [4.243843382379403, 4.128314378833922, 4.128314378397532, 4.081366752807379], rtol=0.05) - end +@trixi_testset "elixir_euler_weakform.jl (convergence)" begin + mean_convergence = convergence_test(@__MODULE__, + joinpath(EXAMPLES_DIR, + "elixir_euler_weakform.jl"), 2) + @test isapprox(mean_convergence[:l2], + [ + 4.243843382379403, + 4.128314378833922, + 4.128314378397532, + 4.081366752807379, + ], rtol = 0.05) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_weakform_periodic.jl" begin +@trixi_testset "elixir_euler_weakform_periodic.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_weakform_periodic.jl"), - # division by 2.0 corresponds to normalization by the square root of the size of the domain - l2 = [0.0014986508075708323, 0.001528523420746786, 0.0015285234207473158, 0.004846505183839211] ./ 2.0, - linf = [0.0015062108658376872, 0.0019373508504645365, 0.0019373508504538783, 0.004742686826709086] - ) - end + # division by 2.0 corresponds to normalization by the square root of the size of the domain + l2=[ + 0.0014986508075708323, + 0.001528523420746786, + 0.0015285234207473158, + 0.004846505183839211, + ] ./ 2.0, + linf=[ + 0.0015062108658376872, + 0.0019373508504645365, + 0.0019373508504538783, + 0.004742686826709086, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_triangulate_pkg_mesh.jl" begin +@trixi_testset "elixir_euler_triangulate_pkg_mesh.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_triangulate_pkg_mesh.jl"), - l2 = [2.344080455438114e-6, 1.8610038753097983e-6, 2.4095165666095305e-6, 6.373308158814308e-6], - linf = [2.5099852761334418e-5, 2.2683684021362893e-5, 2.6180448559287584e-5, 5.5752932611508044e-5] - ) - end - - @trixi_testset "elixir_euler_kelvin_helmholtz_instability.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_kelvin_helmholtz_instability.jl"), - cells_per_dimension = (32, 32), tspan = (0.0, 0.2), - # division by 2.0 corresponds to normalization by the square root of the size of the domain - l2 = [0.11140378947116614, 0.06598161188703612, 0.10448953167839563, 0.16023209181809595] ./ 2.0, - linf = [0.24033843177853664, 0.1659992245272325, 0.1235468309508845, 0.26911424973147735] - ) - end - - @trixi_testset "elixir_euler_kelvin_helmholtz_instability.jl (Quadrilateral elements, GaussSBP)" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_kelvin_helmholtz_instability.jl"), - cells_per_dimension = (32, 32), element_type = Quad(), approximation_type=GaussSBP(), tspan = (0.0, 0.2), - # division by 2.0 corresponds to normalization by the square root of the size of the domain - l2 = [0.11141270656347146, 0.06598888014584121, 0.1044902203749932, 0.16023037364774995] ./ 2.0, - linf = [0.2414760062126462, 0.1662111846065654, 0.12344140473946856, 0.26978428189564774] - ) - end - - @trixi_testset "elixir_euler_rayleigh_taylor_instability.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_rayleigh_taylor_instability.jl"), - cells_per_dimension = (8, 8), tspan = (0.0, 0.2), - l2 = [0.0709665896982514, 0.005182828752164663, 0.013832655585206478, 0.03247013800580221], - linf = [0.4783963902824797, 0.022527207050681054, 0.040307056293369226, 0.0852365428206836] - ) - end - - @trixi_testset "elixir_euler_brown_minion_vortex.jl" begin + l2=[ + 2.344080455438114e-6, + 1.8610038753097983e-6, + 2.4095165666095305e-6, + 6.373308158814308e-6, + ], + linf=[ + 2.5099852761334418e-5, + 2.2683684021362893e-5, + 2.6180448559287584e-5, + 5.5752932611508044e-5, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_kelvin_helmholtz_instability.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_kelvin_helmholtz_instability.jl"), + cells_per_dimension=(32, 32), tspan=(0.0, 0.2), + # division by 2.0 corresponds to normalization by the square root of the size of the domain + l2=[ + 0.11140378947116614, + 0.06598161188703612, + 0.10448953167839563, + 0.16023209181809595, + ] ./ 2.0, + linf=[ + 0.24033843177853664, + 0.1659992245272325, + 0.1235468309508845, + 0.26911424973147735, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_kelvin_helmholtz_instability.jl (Quadrilateral elements, GaussSBP)" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_kelvin_helmholtz_instability.jl"), + cells_per_dimension=(32, 32), element_type=Quad(), + approximation_type=GaussSBP(), tspan=(0.0, 0.2), + # division by 2.0 corresponds to normalization by the square root of the size of the domain + l2=[ + 0.11141270656347146, + 0.06598888014584121, + 0.1044902203749932, + 0.16023037364774995, + ] ./ 2.0, + linf=[ + 0.2414760062126462, + 0.1662111846065654, + 0.12344140473946856, + 0.26978428189564774, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_rayleigh_taylor_instability.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_rayleigh_taylor_instability.jl"), + cells_per_dimension=(8, 8), tspan=(0.0, 0.2), + l2=[ + 0.0709665896982514, + 0.005182828752164663, + 0.013832655585206478, + 0.03247013800580221, + ], + linf=[ + 0.4783963902824797, + 0.022527207050681054, + 0.040307056293369226, + 0.0852365428206836, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_brown_minion_vortex.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_brown_minion_vortex.jl"), - cells_per_dimension = 4, tspan = (0.0, 0.1), - l2 = [0.006680001611078062, 0.02151676347585447, 0.010696524235364626, 0.15052841129694647], - linf = [0.01544756362800248, 0.09517304772476806, 0.021957154972646383, 0.33773439650806303] - ) - end + cells_per_dimension=4, tspan=(0.0, 0.1), + l2=[ + 0.006680001611078062, + 0.02151676347585447, + 0.010696524235364626, + 0.15052841129694647, + ], + linf=[ + 0.01544756362800248, + 0.09517304772476806, + 0.021957154972646383, + 0.33773439650806303, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_shockcapturing.jl" begin +@trixi_testset "elixir_euler_shockcapturing.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_shockcapturing.jl"), - cells_per_dimension = 4, tspan = (0.0, 0.1), - l2 = [0.05685148333985476, 0.04308122135907089, 0.043081221359070915, 0.21098131003847664], - linf = [0.2360672306096051, 0.16684417686971842, 0.1668441768697189, 0.8572572782118661] - ) - end + cells_per_dimension=4, tspan=(0.0, 0.1), + l2=[ + 0.05685148333985476, + 0.04308122135907089, + 0.043081221359070915, + 0.21098131003847664, + ], + linf=[ + 0.2360672306096051, + 0.16684417686971842, + 0.1668441768697189, + 0.8572572782118661, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_shockcapturing_curved.jl" begin +@trixi_testset "elixir_euler_shockcapturing_curved.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_shockcapturing_curved.jl"), - cells_per_dimension = 4, tspan = (0.0, 0.1), - l2 = [0.05565849298766252, 0.042322816017256494, 0.042322816017256466, 0.2064212098324083], - linf = [0.23633287875008924, 0.16930148707515683, 0.16930148707515688, 0.8587706761131937] - ) - end - + cells_per_dimension=4, tspan=(0.0, 0.1), + l2=[ + 0.05565849298766252, + 0.042322816017256494, + 0.042322816017256466, + 0.2064212098324083, + ], + linf=[ + 0.23633287875008924, + 0.16930148707515683, + 0.16930148707515688, + 0.8587706761131937, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_weakform.jl (FD SBP)" begin +@trixi_testset "elixir_euler_weakform.jl (FD SBP)" begin + global D = derivative_operator(SummationByPartsOperators.MattssonNordström2004(), + derivative_order = 1, + accuracy_order = 4, + xmin = 0.0, xmax = 1.0, + N = 12) @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_weakform.jl"), - cells_per_dimension = (2, 2), - element_type = Quad(), - cfl = 1.0, - approximation_type = derivative_operator( - SummationByPartsOperators.MattssonNordström2004(), - derivative_order=1, accuracy_order=4, - xmin=0.0, xmax=1.0, N=12), - # division by 2.0 corresponds to normalization by the square root of the size of the domain - l2 = [0.0008966318978421226, 0.0011418826379110242, 0.001141882637910878, 0.0030918374335671393] ./ 2.0, - linf = [0.0015281525343109337, 0.00162430960401716, 0.0016243096040242655, 0.004447503691245913] - ) - end - - @trixi_testset "elixir_euler_weakform.jl (FD SBP, EC)" begin + cells_per_dimension=(2, 2), + element_type=Quad(), + cfl=1.0, + approximation_type=D, + # division by 2.0 corresponds to normalization by the square root of the size of the domain + l2=[ + 0.0008966318978421226, + 0.0011418826379110242, + 0.001141882637910878, + 0.0030918374335671393, + ] ./ 2.0, + linf=[ + 0.0015281525343109337, + 0.00162430960401716, + 0.0016243096040242655, + 0.004447503691245913, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_weakform.jl (FD SBP, EC)" begin + global D = derivative_operator(SummationByPartsOperators.MattssonNordström2004(), + derivative_order = 1, + accuracy_order = 4, + xmin = 0.0, xmax = 1.0, + N = 12) @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_weakform.jl"), - cells_per_dimension = (2, 2), - element_type = Quad(), - cfl = 1.0, - approximation_type = derivative_operator( - SummationByPartsOperators.MattssonNordström2004(), - derivative_order=1, accuracy_order=4, - xmin=0.0, xmax=1.0, N=12), - volume_integral = VolumeIntegralFluxDifferencing(flux_ranocha), - surface_integral = SurfaceIntegralWeakForm(flux_ranocha), - # division by 2.0 corresponds to normalization by the square root of the size of the domain - l2 = [0.0014018725496871129, 0.0015887007320868913, 0.001588700732086329, 0.003870926821031202] ./ 2.0, - linf = [0.0029541996523780867, 0.0034520465226108854, 0.003452046522624652, 0.007677153211004928] - ) - end - - @trixi_testset "elixir_euler_fdsbp_periodic.jl" begin + cells_per_dimension=(2, 2), + element_type=Quad(), + cfl=1.0, + approximation_type=D, + volume_integral=VolumeIntegralFluxDifferencing(flux_ranocha), + surface_integral=SurfaceIntegralWeakForm(flux_ranocha), + # division by 2.0 corresponds to normalization by the square root of the size of the domain + l2=[ + 0.0014018725496871129, + 0.0015887007320868913, + 0.001588700732086329, + 0.003870926821031202, + ] ./ 2.0, + linf=[ + 0.0029541996523780867, + 0.0034520465226108854, + 0.003452046522624652, + 0.007677153211004928, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_fdsbp_periodic.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_fdsbp_periodic.jl"), - l2 = [1.3333320340010056e-6, 2.044834627970641e-6, 2.044834627855601e-6, 5.282189803559564e-6], - linf = [2.7000151718858945e-6, 3.988595028259212e-6, 3.9885950273710336e-6, 8.848583042286862e-6] - ) - end + l2=[ + 1.3333320340010056e-6, + 2.044834627970641e-6, + 2.044834627855601e-6, + 5.282189803559564e-6, + ], + linf=[ + 2.7000151718858945e-6, + 3.988595028259212e-6, + 3.9885950273710336e-6, + 8.848583042286862e-6, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_fdsbp_periodic.jl (arbitrary reference domain)" begin +@trixi_testset "elixir_euler_fdsbp_periodic.jl (arbitrary reference domain)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_fdsbp_periodic.jl"), - xmin=-200.0, xmax=100.0 #= parameters for reference interval =#, - l2 = [1.333332034149886e-6, 2.0448346280892024e-6, 2.0448346279766305e-6, 5.282189803510037e-6], - linf = [2.700015170553627e-6, 3.988595024262409e-6, 3.988595024928543e-6, 8.84858303740188e-6] - ) - end + xmin=-200.0, xmax=100.0, #= parameters for reference interval =# + l2=[ + 1.333332034149886e-6, + 2.0448346280892024e-6, + 2.0448346279766305e-6, + 5.282189803510037e-6, + ], + linf=[ + 2.700015170553627e-6, + 3.988595024262409e-6, + 3.988595024928543e-6, + 8.84858303740188e-6, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_fdsbp_periodic.jl (arbitrary reference and physical domains)" begin +@trixi_testset "elixir_euler_fdsbp_periodic.jl (arbitrary reference and physical domains)" begin + global D = periodic_derivative_operator(derivative_order = 1, + accuracy_order = 4, + xmin = -200.0, + xmax = 100.0, + N = 100) @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_fdsbp_periodic.jl"), - approximation_type = periodic_derivative_operator( - derivative_order=1, accuracy_order=4, xmin=-200.0, xmax=100.0, N=100), - coordinates_min=(-3.0, -4.0), coordinates_max=(0.0, -1.0), - l2 = [0.07318831033918516, 0.10039910610067465, 0.1003991061006748, 0.2642450566234564], - linf = [0.36081081739439735, 0.5244468027020845, 0.5244468027020814, 1.2210130256735705] - ) - end - - @trixi_testset "elixir_euler_fdsbp_periodic.jl (CGSEM)" begin + approximation_type=D, + coordinates_min=(-3.0, -4.0), coordinates_max=(0.0, -1.0), + l2=[ + 0.07318831033918516, + 0.10039910610067465, + 0.1003991061006748, + 0.2642450566234564, + ], + linf=[ + 0.36081081739439735, + 0.5244468027020845, + 0.5244468027020814, + 1.2210130256735705, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_fdsbp_periodic.jl (CGSEM)" begin + D_local = SummationByPartsOperators.legendre_derivative_operator(xmin = 0.0, + xmax = 1.0, + N = 4) + mesh_local = SummationByPartsOperators.UniformPeriodicMesh1D(xmin = -1.0, + xmax = 1.0, + Nx = 10) + global D = SummationByPartsOperators.couple_continuously(D_local, mesh_local) @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_fdsbp_periodic.jl"), - approximation_type = SummationByPartsOperators.couple_continuously( - SummationByPartsOperators.legendre_derivative_operator(xmin=0.0, xmax=1.0, N=4), - SummationByPartsOperators.UniformPeriodicMesh1D(xmin=-1.0, xmax=1.0, Nx=10)), - l2 = [1.5440402410017893e-5, 1.4913189903083485e-5, 1.4913189902797073e-5, 2.6104615985156992e-5], - linf = [4.16334345412217e-5, 5.067812788173143e-5, 5.067812786885284e-5, 9.887976803746312e-5] - ) - end - - @trixi_testset "elixir_mhd_weak_blast_wave.jl (Quad)" begin + approximation_type=D, + l2=[ + 1.5440402410017893e-5, + 1.4913189903083485e-5, + 1.4913189902797073e-5, + 2.6104615985156992e-5, + ], + linf=[ + 4.16334345412217e-5, + 5.067812788173143e-5, + 5.067812786885284e-5, + 9.887976803746312e-5, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_mhd_weak_blast_wave.jl (Quad)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_weak_blast_wave.jl"), - cells_per_dimension = 4, - l2 = [0.03906769915509508, 0.04923079758984701, 0.049230797589847136, 0.02660348840973283, - 0.18054907061740028, 0.019195256934309846, 0.019195256934310016, 0.027856113419468087, - 0.0016567799774264065], - linf = [0.16447597822733662, 0.244157345789029, 0.24415734578903472, 0.11982440036793476, - 0.7450328339751362, 0.06357382685763713, 0.0635738268576378, 0.1058830287485999, - 0.005740591170062146] - ) - end - - @trixi_testset "elixir_mhd_weak_blast_wave.jl (Tri)" begin + cells_per_dimension=4, + l2=[0.03906769915509508, 0.04923079758984701, + 0.049230797589847136, 0.02660348840973283, + 0.18054907061740028, 0.019195256934309846, + 0.019195256934310016, 0.027856113419468087, + 0.0016567799774264065], + linf=[0.16447597822733662, 0.244157345789029, + 0.24415734578903472, 0.11982440036793476, + 0.7450328339751362, 0.06357382685763713, 0.0635738268576378, + 0.1058830287485999, + 0.005740591170062146]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_mhd_weak_blast_wave.jl (Tri)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_weak_blast_wave.jl"), - cells_per_dimension = 4, element_type = Tri(), - l2 = [0.03372468091254386, 0.03971626483409167, 0.03971626483409208, 0.021427571421535722, - 0.15079331840847413, 0.015716300366650286, 0.015716300366652128, 0.022365252076279075, - 0.0009232971979900358], - linf = [0.16290247390873458, 0.2256891306641319, 0.2256891306641336, 0.09476017042552534, - 0.6906308908961734, 0.05349939593012487, 0.05349939593013042, 0.08830587480616725, - 0.0029551359803035027] - ) - end - - @trixi_testset "elixir_mhd_weak_blast_wave_SBP.jl (Quad)" begin + cells_per_dimension=4, element_type=Tri(), + l2=[0.03372468091254386, 0.03971626483409167, + 0.03971626483409208, 0.021427571421535722, + 0.15079331840847413, 0.015716300366650286, + 0.015716300366652128, 0.022365252076279075, + 0.0009232971979900358], + linf=[0.16290247390873458, 0.2256891306641319, + 0.2256891306641336, 0.09476017042552534, + 0.6906308908961734, 0.05349939593012487, + 0.05349939593013042, 0.08830587480616725, + 0.0029551359803035027]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_mhd_weak_blast_wave_SBP.jl (Quad)" begin # These setups do not pass CI reliably, see # https://github.com/trixi-framework/Trixi.jl/pull/880 and # https://github.com/trixi-framework/Trixi.jl/issues/881 - @test_skip @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_weak_blast_wave_SBP.jl"), - cells_per_dimension = 4, - # division by 2.0 corresponds to normalization by the square root of the size of the domain - l2 = [0.15825983698241494, 0.19897219694837923, 0.19784182473275247, 0.10482833997417325, - 0.7310752391255246, 0.07374056714564853, 0.07371172293240634, 0.10782032253431281, - 0.004921676235111545] ./ 2.0, - linf = [0.1765644464978685, 0.2627803272865769, 0.26358136695848144, 0.12347681727447984, - 0.7733289736898254, 0.06695360844467957, 0.06650382120802623, 0.10885097000919097, - 0.007212567638078835] - ) - end - - @trixi_testset "elixir_mhd_weak_blast_wave_SBP.jl (Tri)" begin + @test_skip @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_mhd_weak_blast_wave_SBP.jl"), + cells_per_dimension=4, + # division by 2.0 corresponds to normalization by the square root of the size of the domain + l2=[0.15825983698241494, 0.19897219694837923, + 0.19784182473275247, 0.10482833997417325, + 0.7310752391255246, 0.07374056714564853, + 0.07371172293240634, 0.10782032253431281, + 0.004921676235111545] ./ 2.0, + linf=[0.1765644464978685, 0.2627803272865769, + 0.26358136695848144, 0.12347681727447984, + 0.7733289736898254, 0.06695360844467957, + 0.06650382120802623, 0.10885097000919097, + 0.007212567638078835]) +end + +@trixi_testset "elixir_mhd_weak_blast_wave_SBP.jl (Tri)" begin # These setups do not pass CI reliably, see # https://github.com/trixi-framework/Trixi.jl/pull/880 and # https://github.com/trixi-framework/Trixi.jl/issues/881 - @test_skip @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_weak_blast_wave_SBP.jl"), - cells_per_dimension = 4, element_type=Tri(), tspan = (0.0, 0.2), - # division by 2.0 corresponds to normalization by the square root of the size of the domain - l2 = [0.13825044764021147, 0.15472815448314997, 0.1549093274293255, 0.053103596213755405, - 0.7246162776815603, 0.07730777596615901, 0.07733438386480523, 0.109893463921706, - 0.00617678167062838] ./ 2.0, - linf = [0.22701306227317952, 0.2905255794821543, 0.2912409425436937, 0.08051361477962096, - 1.0842974228656006, 0.07866000368926784, 0.0786646354518149, 0.1614896380292925, - 0.010358210347485542] - ) - end - - @trixi_testset "elixir_mhd_reflective_wall.jl (Quad)" begin + @test_skip @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_mhd_weak_blast_wave_SBP.jl"), + cells_per_dimension=4, element_type=Tri(), + tspan=(0.0, 0.2), + # division by 2.0 corresponds to normalization by the square root of the size of the domain + l2=[0.13825044764021147, 0.15472815448314997, + 0.1549093274293255, 0.053103596213755405, + 0.7246162776815603, 0.07730777596615901, + 0.07733438386480523, 0.109893463921706, + 0.00617678167062838] ./ 2.0, + linf=[0.22701306227317952, 0.2905255794821543, + 0.2912409425436937, 0.08051361477962096, + 1.0842974228656006, 0.07866000368926784, + 0.0786646354518149, 0.1614896380292925, + 0.010358210347485542]) +end + +@trixi_testset "elixir_mhd_reflective_wall.jl (Quad)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_reflective_wall.jl"), - cells_per_dimension = 4, - l2 = [0.0036019536614619687, 0.001734097206958611, 0.008375221008997178, 0.0, 0.028596796602124414, 0.0018573693138866614, 0.0020807798141551166, 0.0, 5.301188920230166e-5], - linf = [0.01692601228199253, 0.009369662298436778, 0.04145169295835428, 0.0, 0.11569908670112738, 0.00984964453299233, 0.01141708032148614, 0.0, 0.0002992631411931389] - ) - end + cells_per_dimension=4, + l2=[ + 0.0036019536614619687, + 0.001734097206958611, + 0.008375221008997178, + 0.0, + 0.028596796602124414, + 0.0018573693138866614, + 0.0020807798141551166, + 0.0, + 5.301188920230166e-5, + ], + linf=[ + 0.01692601228199253, + 0.009369662298436778, + 0.04145169295835428, + 0.0, + 0.11569908670112738, + 0.00984964453299233, + 0.01141708032148614, + 0.0, + 0.0002992631411931389, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_shallowwater_source_terms.jl (Quad, SBP)" begin +@trixi_testset "elixir_shallowwater_source_terms.jl (Quad, SBP)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_source_terms.jl"), - cells_per_dimension = 8, element_type = Quad(), approximation_type = SBP(), - l2 = [0.0020316462913319046, 0.023669019044882247, 0.03446194752754684, 1.9333465252381796e-15], - linf = [0.010385010095182778, 0.08750628939565086, 0.12088392994348407, 9.325873406851315e-15] - ) - end + cells_per_dimension=8, element_type=Quad(), + approximation_type=SBP(), + l2=[ + 0.0020316462913319046, + 0.023669019044882247, + 0.03446194752754684, + 1.9333465252381796e-15, + ], + linf=[ + 0.010385010095182778, + 0.08750628939565086, + 0.12088392994348407, + 9.325873406851315e-15, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_shallowwater_source_terms.jl (Tri, SBP)" begin +@trixi_testset "elixir_shallowwater_source_terms.jl (Tri, SBP)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_source_terms.jl"), - cells_per_dimension = 8, element_type = Tri(), approximation_type = SBP(), - l2 = [0.004180680322490383, 0.07026192411558974, 0.11815151697006446, 2.329788936151192e-15], - linf = [0.02076003852980346, 0.29169601664914424, 0.5674183379872275, 1.1546319456101628e-14] - ) - end + cells_per_dimension=8, element_type=Tri(), + approximation_type=SBP(), + l2=[ + 0.004180680322490383, + 0.07026192411558974, + 0.11815151697006446, + 2.329788936151192e-15, + ], + linf=[ + 0.02076003852980346, + 0.29169601664914424, + 0.5674183379872275, + 1.1546319456101628e-14, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_shallowwater_source_terms.jl (Tri, Polynomial)" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_source_terms.jl"), - cells_per_dimension = 8, element_type = Tri(), approximation_type = Polynomial(), - # The last l2, linf error are the L2 projection error in approximating `b`, so they are not - # zero for general non-collocated quadrature rules (e.g., for `element_type=Tri()`, `polydeg > 2`). - l2 = [0.0008309356912456799, 0.01522451288799231, 0.016033969387208476, 1.2820247308150876e-5], - linf = [0.001888045014140971, 0.05466838692127718, 0.06345885709961152, 3.3989933098554914e-5] - ) - end - - @trixi_testset "elixir_shallowwater_source_terms.jl (Quad, Polynomial)" begin +@trixi_testset "elixir_shallowwater_source_terms.jl (Tri, Polynomial)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_source_terms.jl"), - cells_per_dimension = 8, element_type = Quad(), approximation_type = Polynomial(), - # The last l2, linf error are the L2 projection error in approximating `b`. However, this is zero - # for `Quad()` elements with `Polynomial()` approximations because the quadrature rule defaults to - # a `(polydeg + 1)`-point Gauss quadrature rule in each coordinate (in general, StartUpDG.jl defaults - # to the quadrature rule with the fewest number of points which exactly integrates the mass matrix). - l2 = [7.460461950323111e-5, 0.003685589808444905, 0.0039101604749887785, 2.0636891126652983e-15], - linf = [0.000259995400729629, 0.0072236204211630906, 0.010364675200833062, 1.021405182655144e-14] - ) - end - - + cells_per_dimension=8, element_type=Tri(), + approximation_type=Polynomial(), + # The last l2, linf error are the L2 projection error in approximating `b`, so they are not + # zero for general non-collocated quadrature rules (e.g., for `element_type=Tri()`, `polydeg > 2`). + l2=[ + 0.0008309356912456799, + 0.01522451288799231, + 0.016033969387208476, + 1.2820247308150876e-5, + ], + linf=[ + 0.001888045014140971, + 0.05466838692127718, + 0.06345885709961152, + 3.3989933098554914e-5, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end end +@trixi_testset "elixir_shallowwater_source_terms.jl (Quad, Polynomial)" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_source_terms.jl"), + cells_per_dimension=8, element_type=Quad(), + approximation_type=Polynomial(), + # The last l2, linf error are the L2 projection error in approximating `b`. However, this is zero + # for `Quad()` elements with `Polynomial()` approximations because the quadrature rule defaults to + # a `(polydeg + 1)`-point Gauss quadrature rule in each coordinate (in general, StartUpDG.jl defaults + # to the quadrature rule with the fewest number of points which exactly integrates the mass matrix). + l2=[ + 7.460461950323111e-5, + 0.003685589808444905, + 0.0039101604749887785, + 2.0636891126652983e-15, + ], + linf=[ + 0.000259995400729629, + 0.0072236204211630906, + 0.010364675200833062, + 1.021405182655144e-14, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end +end # Clean up afterwards: delete Trixi.jl output directory -@test_nowarn isdir(outdir) && rm(outdir, recursive=true) +@test_nowarn isdir(outdir) && rm(outdir, recursive = true) end # module diff --git a/test/test_dgmulti_3d.jl b/test/test_dgmulti_3d.jl index 68fa1d13304..3a1db255484 100644 --- a/test/test_dgmulti_3d.jl +++ b/test/test_dgmulti_3d.jl @@ -9,141 +9,402 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "dgmulti_3d") # Start with a clean environment: remove Trixi.jl output directory if it exists outdir = "out" -isdir(outdir) && rm(outdir, recursive=true) +isdir(outdir) && rm(outdir, recursive = true) @testset "DGMulti 3D" begin - # 3d tet/hex tests - @trixi_testset "elixir_euler_weakform.jl" begin +#! format: noindent + +# 3d tet/hex tests +@trixi_testset "elixir_euler_weakform.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_weakform.jl"), - # division by sqrt(8.0) corresponds to normalization by the square root of the size of the domain - l2 = [0.0010029534292051608, 0.0011682205957721673, 0.001072975385793516, 0.000997247778892257, 0.0039364354651358294] ./ sqrt(8), - linf = [0.003660737033303718, 0.005625620600749226, 0.0030566354814669516, 0.0041580358824311325, 0.019326660236036464] - ) - end + # division by sqrt(8.0) corresponds to normalization by the square root of the size of the domain + l2=[ + 0.0010029534292051608, + 0.0011682205957721673, + 0.001072975385793516, + 0.000997247778892257, + 0.0039364354651358294, + ] ./ sqrt(8), + linf=[ + 0.003660737033303718, + 0.005625620600749226, + 0.0030566354814669516, + 0.0041580358824311325, + 0.019326660236036464, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_weakform.jl (EC)" begin +@trixi_testset "elixir_euler_weakform.jl (EC)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_weakform.jl"), - surface_integral = SurfaceIntegralWeakForm(flux_ranocha), - volume_integral = VolumeIntegralFluxDifferencing(flux_ranocha), - # division by sqrt(8.0) corresponds to normalization by the square root of the size of the domain - l2 = [0.014932088450136542, 0.017080219613061526, 0.016589517840793006, 0.015905000907070196, 0.03903416208587798] ./ sqrt(8), - linf = [0.06856547797256729, 0.08225664880340489, 0.06925055630951782, 0.06913016119820181, 0.19161418499621874] - ) - end - - @trixi_testset "elixir_euler_weakform.jl (Hexahedral elements)" begin + surface_integral=SurfaceIntegralWeakForm(flux_ranocha), + volume_integral=VolumeIntegralFluxDifferencing(flux_ranocha), + # division by sqrt(8.0) corresponds to normalization by the square root of the size of the domain + l2=[ + 0.014932088450136542, + 0.017080219613061526, + 0.016589517840793006, + 0.015905000907070196, + 0.03903416208587798, + ] ./ sqrt(8), + linf=[ + 0.06856547797256729, + 0.08225664880340489, + 0.06925055630951782, + 0.06913016119820181, + 0.19161418499621874, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_weakform.jl (Hexahedral elements)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_weakform.jl"), - element_type = Hex(), - # division by sqrt(8.0) corresponds to normalization by the square root of the size of the domain - l2 = [0.00030580190715769566, 0.00040146357607439464, 0.00040146357607564597, 0.000401463576075708, 0.0015749412434154315] ./ sqrt(8), - linf = [0.00036910287847780054, 0.00042659774184228283, 0.0004265977427213574, 0.00042659774250686233, 0.00143803344597071] - ) - end - - @trixi_testset "elixir_euler_curved.jl (Hex elements, SBP, flux differencing)" begin + element_type=Hex(), + # division by sqrt(8.0) corresponds to normalization by the square root of the size of the domain + l2=[ + 0.00030580190715769566, + 0.00040146357607439464, + 0.00040146357607564597, + 0.000401463576075708, + 0.0015749412434154315, + ] ./ sqrt(8), + linf=[ + 0.00036910287847780054, + 0.00042659774184228283, + 0.0004265977427213574, + 0.00042659774250686233, + 0.00143803344597071, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_curved.jl (Hex elements, SBP, flux differencing)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_curved.jl"), - l2 = [0.018354883045936066, 0.024412704052042846, 0.024408520416087945, 0.01816314570880129, 0.039342805507972006], - linf = [0.14862225990775757, 0.28952368161864683, 0.2912054484817035, 0.1456603133854122, 0.3315354586775472] - ) - end + l2=[ + 0.018354883045936066, + 0.024412704052042846, + 0.024408520416087945, + 0.01816314570880129, + 0.039342805507972006, + ], + linf=[ + 0.14862225990775757, + 0.28952368161864683, + 0.2912054484817035, + 0.1456603133854122, + 0.3315354586775472, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_curved.jl (Hex elements, GaussSBP, flux differencing)" begin +@trixi_testset "elixir_euler_curved.jl (Hex elements, GaussSBP, flux differencing)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_curved.jl"), - approximation_type=GaussSBP(), - l2 = [0.002631131519508634, 0.0029144224044954105, 0.002913889110662827, 0.002615140832314194, 0.006881528610614373], - linf = [0.020996114874140215, 0.021314522450134543, 0.021288322783006297, 0.020273381695435244, 0.052598740390024545] - ) - end + approximation_type=GaussSBP(), + l2=[ + 0.002631131519508634, + 0.0029144224044954105, + 0.002913889110662827, + 0.002615140832314194, + 0.006881528610614373, + ], + linf=[ + 0.020996114874140215, + 0.021314522450134543, + 0.021288322783006297, + 0.020273381695435244, + 0.052598740390024545, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_weakform_periodic.jl" begin +@trixi_testset "elixir_euler_weakform_periodic.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_weakform_periodic.jl"), - # division by sqrt(8.0) corresponds to normalization by the square root of the size of the domain - l2 = [0.0010317074322517949, 0.0012277090547035293, 0.0011273991123913515, 0.0010418496196130177, 0.004058878478404962] ./ sqrt(8), - linf = [0.003227752881827861, 0.005620317864620361, 0.0030514833972379307, 0.003987027618439498, 0.019282224709831652] - ) - end + # division by sqrt(8.0) corresponds to normalization by the square root of the size of the domain + l2=[ + 0.0010317074322517949, + 0.0012277090547035293, + 0.0011273991123913515, + 0.0010418496196130177, + 0.004058878478404962, + ] ./ sqrt(8), + linf=[ + 0.003227752881827861, + 0.005620317864620361, + 0.0030514833972379307, + 0.003987027618439498, + 0.019282224709831652, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_weakform_periodic.jl (Hexahedral elements)" begin +@trixi_testset "elixir_euler_weakform_periodic.jl (Hexahedral elements)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_weakform_periodic.jl"), - element_type = Hex(), - # division by sqrt(8.0) corresponds to normalization by the square root of the size of the domain - l2 = [0.00034230612468547436, 0.00044397204714598747, 0.0004439720471461567, 0.0004439720471464591, 0.0016639410646990126] ./ sqrt(8), - linf = [0.0003674374460325147, 0.0004253921341716982, 0.0004253921340786615, 0.0004253921340831024, 0.0014333414071048267] - ) - end - - @trixi_testset "elixir_euler_weakform_periodic.jl (Hexahedral elements, SBP, EC)" begin + element_type=Hex(), + # division by sqrt(8.0) corresponds to normalization by the square root of the size of the domain + l2=[ + 0.00034230612468547436, + 0.00044397204714598747, + 0.0004439720471461567, + 0.0004439720471464591, + 0.0016639410646990126, + ] ./ sqrt(8), + linf=[ + 0.0003674374460325147, + 0.0004253921341716982, + 0.0004253921340786615, + 0.0004253921340831024, + 0.0014333414071048267, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_weakform_periodic.jl (Hexahedral elements, SBP, EC)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_weakform_periodic.jl"), - element_type = Hex(), - volume_integral = VolumeIntegralFluxDifferencing(flux_ranocha), - surface_integral = SurfaceIntegralWeakForm(flux_ranocha), - approximation_type = SBP(), - # division by sqrt(8.0) corresponds to normalization by the square root of the size of the domain - l2 = [0.001712443468716032, 0.002491315550718859, 0.0024913155507195303, 0.002491315550720031, 0.008585818982343299] ./ sqrt(8), - linf = [0.003810078279323559, 0.004998778644230928, 0.004998778643986235, 0.0049987786444081195, 0.016455044373650196] - ) - end - - @trixi_testset "elixir_euler_taylor_green_vortex.jl" begin + element_type=Hex(), + volume_integral=VolumeIntegralFluxDifferencing(flux_ranocha), + surface_integral=SurfaceIntegralWeakForm(flux_ranocha), + approximation_type=SBP(), + # division by sqrt(8.0) corresponds to normalization by the square root of the size of the domain + l2=[ + 0.001712443468716032, + 0.002491315550718859, + 0.0024913155507195303, + 0.002491315550720031, + 0.008585818982343299, + ] ./ sqrt(8), + linf=[ + 0.003810078279323559, + 0.004998778644230928, + 0.004998778643986235, + 0.0049987786444081195, + 0.016455044373650196, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_taylor_green_vortex.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_taylor_green_vortex.jl"), - polydeg = 3, tspan = (0.0, 1.0), cells_per_dimension = (2, 2, 2), - l2 = [0.0003612827827560599, 0.06219350883951729, 0.062193508839503864, 0.08121963221634831, 0.07082703570808184], - linf = [0.0007893509649821162, 0.1481953939988877, 0.14819539399791176, 0.14847291108358926, 0.21313533492212855] - ) - end + polydeg=3, tspan=(0.0, 1.0), cells_per_dimension=(2, 2, 2), + l2=[ + 0.0003612827827560599, + 0.06219350883951729, + 0.062193508839503864, + 0.08121963221634831, + 0.07082703570808184, + ], + linf=[ + 0.0007893509649821162, + 0.1481953939988877, + 0.14819539399791176, + 0.14847291108358926, + 0.21313533492212855, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_taylor_green_vortex.jl (GaussSBP)" begin +@trixi_testset "elixir_euler_taylor_green_vortex.jl (GaussSBP)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_taylor_green_vortex.jl"), - polydeg = 3, approximation_type = GaussSBP(), tspan = (0.0, 1.0), cells_per_dimension = (2, 2, 2), - l2 = [0.00036128278275524326, 0.062193508839511434, 0.06219350883949677, 0.08121963221635205, 0.07082703570765223], - linf = [0.000789350964946367, 0.14819539399525805, 0.14819539399590542, 0.14847291107658706, 0.21313533492059378] - ) - end + polydeg=3, approximation_type=GaussSBP(), tspan=(0.0, 1.0), + cells_per_dimension=(2, 2, 2), + l2=[ + 0.00036128278275524326, + 0.062193508839511434, + 0.06219350883949677, + 0.08121963221635205, + 0.07082703570765223, + ], + linf=[ + 0.000789350964946367, + 0.14819539399525805, + 0.14819539399590542, + 0.14847291107658706, + 0.21313533492059378, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_weakform_periodic.jl (FD SBP)" begin +@trixi_testset "elixir_euler_weakform_periodic.jl (FD SBP)" begin + global D = derivative_operator(SummationByPartsOperators.MattssonNordström2004(), + derivative_order = 1, + accuracy_order = 2, + xmin = 0.0, xmax = 1.0, + N = 8) @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_weakform_periodic.jl"), - element_type = Hex(), - cells_per_dimension = (2, 2, 2), - approximation_type = derivative_operator( - SummationByPartsOperators.MattssonNordström2004(), - derivative_order=1, accuracy_order=2, - xmin=0.0, xmax=1.0, N=8), - l2 = [0.0024092707138829925, 0.003318758964118284, 0.0033187589641182386, 0.003318758964118252, 0.012689348410504253], - linf = [0.006118565824207778, 0.008486456080185167, 0.008486456080180282, 0.008486456080185611, 0.035113544599208346] - ) - end - - @trixi_testset "elixir_euler_weakform_periodic.jl (FD SBP, EC)" begin + element_type=Hex(), + cells_per_dimension=(2, 2, 2), + approximation_type=D, + l2=[ + 0.0024092707138829925, + 0.003318758964118284, + 0.0033187589641182386, + 0.003318758964118252, + 0.012689348410504253, + ], + linf=[ + 0.006118565824207778, + 0.008486456080185167, + 0.008486456080180282, + 0.008486456080185611, + 0.035113544599208346, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_weakform_periodic.jl (FD SBP, EC)" begin + global D = derivative_operator(SummationByPartsOperators.MattssonNordström2004(), + derivative_order = 1, + accuracy_order = 2, + xmin = 0.0, xmax = 1.0, + N = 8) @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_weakform_periodic.jl"), - element_type = Hex(), - cells_per_dimension = (2, 2, 2), - approximation_type = derivative_operator( - SummationByPartsOperators.MattssonNordström2004(), - derivative_order=1, accuracy_order=2, - xmin=0.0, xmax=1.0, N=8), - volume_integral = VolumeIntegralFluxDifferencing(flux_ranocha), - surface_integral = SurfaceIntegralWeakForm(flux_ranocha), - l2 = [0.0034543609010604407, 0.004944363692625066, 0.0049443636926250435, 0.004944363692625037, 0.01788695279620914], - linf = [0.013861851418853988, 0.02126572106620328, 0.021265721066209053, 0.021265721066210386, 0.0771455289446683] - ) - end - - @trixi_testset "elixir_euler_fdsbp_periodic.jl" begin + element_type=Hex(), + cells_per_dimension=(2, 2, 2), + approximation_type=D, + volume_integral=VolumeIntegralFluxDifferencing(flux_ranocha), + surface_integral=SurfaceIntegralWeakForm(flux_ranocha), + l2=[ + 0.0034543609010604407, + 0.004944363692625066, + 0.0049443636926250435, + 0.004944363692625037, + 0.01788695279620914, + ], + linf=[ + 0.013861851418853988, + 0.02126572106620328, + 0.021265721066209053, + 0.021265721066210386, + 0.0771455289446683, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_fdsbp_periodic.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_fdsbp_periodic.jl"), - l2 = [7.561896970325353e-5, 6.884047859361093e-5, 6.884047859363204e-5, 6.884047859361148e-5, 0.000201107274617457], - linf = [0.0001337520020225913, 0.00011571467799287305, 0.0001157146779990903, 0.00011571467799376123, 0.0003446082308800058] - ) - end + l2=[ + 7.561896970325353e-5, + 6.884047859361093e-5, + 6.884047859363204e-5, + 6.884047859361148e-5, + 0.000201107274617457, + ], + linf=[ + 0.0001337520020225913, + 0.00011571467799287305, + 0.0001157146779990903, + 0.00011571467799376123, + 0.0003446082308800058, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_advection_tensor_wedge.jl" begin +@trixi_testset "elixir_advection_tensor_wedge.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_tensor_wedge.jl"), - l2 = [2.30487910e-04] , - linf = [6.31795281e-04] ) - end - + l2=[2.30487910e-04], + linf=[6.31795281e-04]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end end # Clean up afterwards: delete Trixi.jl output directory -@test_nowarn isdir(outdir) && rm(outdir, recursive=true) +@test_nowarn isdir(outdir) && rm(outdir, recursive = true) end # module diff --git a/test/test_mpi.jl b/test/test_mpi.jl index 34febf7e268..ad1ba4e835d 100644 --- a/test/test_mpi.jl +++ b/test/test_mpi.jl @@ -7,7 +7,7 @@ include("test_trixi.jl") # Start with a clean environment: remove Trixi.jl output directory if it exists outdir = "out" -Trixi.mpi_isroot() && isdir(outdir) && rm(outdir, recursive=true) +Trixi.mpi_isroot() && isdir(outdir) && rm(outdir, recursive = true) # CI with MPI and some tests fails often on Windows. Thus, we check whether this # is the case here. We use GitHub Actions, so we can check whether we run CI @@ -16,33 +16,32 @@ Trixi.mpi_isroot() && isdir(outdir) && rm(outdir, recursive=true) CI_ON_WINDOWS = (get(ENV, "GITHUB_ACTIONS", false) == "true") && Sys.iswindows() @testset "MPI" begin - # TreeMesh tests - include("test_mpi_tree.jl") - - # P4estMesh tests - include("test_mpi_p4est_2d.jl") - if !CI_ON_WINDOWS # see comment on `CI_ON_WINDOWS` above - include("test_mpi_p4est_3d.jl") - end + # TreeMesh tests + include("test_mpi_tree.jl") + + # P4estMesh tests + include("test_mpi_p4est_2d.jl") + if !CI_ON_WINDOWS # see comment on `CI_ON_WINDOWS` above + include("test_mpi_p4est_3d.jl") + end end # MPI - @trixi_testset "MPI supporting functionality" begin - using OrdinaryDiffEq - - t = 0.5 - let u = 1.0 - @test ode_norm(u, t) ≈ OrdinaryDiffEq.ODE_DEFAULT_NORM(u, t) - end - let u = [1.0, -2.0] - @test ode_norm(u, t) ≈ OrdinaryDiffEq.ODE_DEFAULT_NORM(u, t) - end - let u = [SVector(1.0, -2.0), SVector(0.5, -0.1)] - @test ode_norm(u, t) ≈ OrdinaryDiffEq.ODE_DEFAULT_NORM(u, t) - end + using OrdinaryDiffEq + + t = 0.5 + let u = 1.0 + @test ode_norm(u, t) ≈ OrdinaryDiffEq.ODE_DEFAULT_NORM(u, t) + end + let u = [1.0, -2.0] + @test ode_norm(u, t) ≈ OrdinaryDiffEq.ODE_DEFAULT_NORM(u, t) + end + let u = [SVector(1.0, -2.0), SVector(0.5, -0.1)] + @test ode_norm(u, t) ≈ OrdinaryDiffEq.ODE_DEFAULT_NORM(u, t) + end end # MPI supporting functionality # Clean up afterwards: delete Trixi.jl output directory -Trixi.mpi_isroot() && @test_nowarn rm(outdir, recursive=true) +Trixi.mpi_isroot() && @test_nowarn rm(outdir, recursive = true) end # module diff --git a/test/test_mpi_p4est_2d.jl b/test/test_mpi_p4est_2d.jl index 4023997eaf3..da90537fcfd 100644 --- a/test/test_mpi_p4est_2d.jl +++ b/test/test_mpi_p4est_2d.jl @@ -8,70 +8,90 @@ include("test_trixi.jl") const EXAMPLES_DIR = pkgdir(Trixi, "examples", "p4est_2d_dgsem") @testset "P4estMesh MPI 2D" begin +#! format: noindent # Run basic tests @testset "Examples 2D" begin - # Linear scalar advection - @trixi_testset "elixir_advection_basic.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_basic.jl"), - # Expected errors are exactly the same as with TreeMesh! - l2 = [8.311947673061856e-6], - linf = [6.627000273229378e-5]) + # Linear scalar advection + @trixi_testset "elixir_advection_basic.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_basic.jl"), + # Expected errors are exactly the same as with TreeMesh! + l2=[8.311947673061856e-6], + linf=[6.627000273229378e-5]) - @testset "error-based step size control" begin - Trixi.mpi_isroot() && println("-"^100) - Trixi.mpi_isroot() && println("elixir_advection_basic.jl with error-based step size control") + @testset "error-based step size control" begin + Trixi.mpi_isroot() && println("-"^100) + Trixi.mpi_isroot() && + println("elixir_advection_basic.jl with error-based step size control") - sol = solve(ode, RDPK3SpFSAL35(); abstol=1.0e-4, reltol=1.0e-4, - ode_default_options()..., callback=callbacks); summary_callback() - errors = analysis_callback(sol) - if Trixi.mpi_isroot() - @test errors.l2 ≈ [3.3022040342579066e-5] rtol=1.0e-4 - @test errors.linf ≈ [0.00011787417954578494] rtol=1.0e-4 - end + sol = solve(ode, RDPK3SpFSAL35(); abstol = 1.0e-4, reltol = 1.0e-4, + ode_default_options()..., callback = callbacks) + summary_callback() + errors = analysis_callback(sol) + if Trixi.mpi_isroot() + @test errors.l2≈[3.3022040342579066e-5] rtol=1.0e-4 + @test errors.linf≈[0.00011787417954578494] rtol=1.0e-4 + end + end end - end - @trixi_testset "elixir_advection_nonconforming_flag.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_nonconforming_flag.jl"), - l2 = [3.198940059144588e-5], - linf = [0.00030636069494005547]) - end + @trixi_testset "elixir_advection_nonconforming_flag.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_advection_nonconforming_flag.jl"), + l2=[3.198940059144588e-5], + linf=[0.00030636069494005547]) + end - @trixi_testset "elixir_advection_unstructured_flag.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_unstructured_flag.jl"), - l2 = [0.0005379687442422346], - linf = [0.007438525029884735]) - end + @trixi_testset "elixir_advection_unstructured_flag.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_advection_unstructured_flag.jl"), + l2=[0.0005379687442422346], + linf=[0.007438525029884735]) + end - @trixi_testset "elixir_advection_amr_solution_independent.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_amr_solution_independent.jl"), - # Expected errors are exactly the same as with TreeMesh! - l2 = [4.949660644033807e-5], - linf = [0.0004867846262313763], - coverage_override = (maxiters=6,)) - end + @trixi_testset "elixir_advection_amr_solution_independent.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_advection_amr_solution_independent.jl"), + # Expected errors are exactly the same as with TreeMesh! + l2=[4.949660644033807e-5], + linf=[0.0004867846262313763], + coverage_override=(maxiters = 6,)) + end - @trixi_testset "elixir_advection_amr_unstructured_flag.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_amr_unstructured_flag.jl"), - l2 = [0.0012766060609964525], - linf = [0.01750280631586159], - coverage_override = (maxiters=6,)) - end + @trixi_testset "elixir_advection_amr_unstructured_flag.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_advection_amr_unstructured_flag.jl"), + l2=[0.0012766060609964525], + linf=[0.01750280631586159], + coverage_override=(maxiters = 6,)) + end - @trixi_testset "elixir_advection_restart.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_restart.jl"), - l2 = [4.507575525876275e-6], - linf = [6.21489667023134e-5]) - end + @trixi_testset "elixir_advection_restart.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_restart.jl"), + l2=[4.507575525876275e-6], + linf=[6.21489667023134e-5], + # With the default `maxiters = 1` in coverage tests, + # there would be no time steps after the restart. + coverage_override=(maxiters = 100_000,)) + end - @trixi_testset "elixir_euler_source_terms_nonconforming_unstructured_flag.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms_nonconforming_unstructured_flag.jl"), - l2 = [0.0034516244508588046, 0.0023420334036925493, 0.0024261923964557187, 0.004731710454271893], - linf = [0.04155789011775046, 0.024772109862748914, 0.03759938693042297, 0.08039824959535657]) - end + @trixi_testset "elixir_euler_source_terms_nonconforming_unstructured_flag.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_source_terms_nonconforming_unstructured_flag.jl"), + l2=[ + 0.0034516244508588046, + 0.0023420334036925493, + 0.0024261923964557187, + 0.004731710454271893, + ], + linf=[ + 0.04155789011775046, + 0.024772109862748914, + 0.03759938693042297, + 0.08039824959535657, + ]) + end end - end # P4estMesh MPI end # module diff --git a/test/test_mpi_p4est_3d.jl b/test/test_mpi_p4est_3d.jl index f92feb1eed9..75f43650082 100644 --- a/test/test_mpi_p4est_3d.jl +++ b/test/test_mpi_p4est_3d.jl @@ -8,90 +8,153 @@ include("test_trixi.jl") const EXAMPLES_DIR = pkgdir(Trixi, "examples", "p4est_3d_dgsem") @testset "P4estMesh MPI 3D" begin +#! format: noindent # Run basic tests @testset "Examples 3D" begin - # Linear scalar advection - @trixi_testset "elixir_advection_basic.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_basic.jl"), - # Expected errors are exactly the same as with TreeMesh! - l2 = [0.00016263963870641478], - linf = [0.0014537194925779984]) - - @testset "error-based step size control" begin - Trixi.mpi_isroot() && println("-"^100) - Trixi.mpi_isroot() && println("elixir_advection_basic.jl with error-based step size control") - - sol = solve(ode, RDPK3SpFSAL35(); abstol=1.0e-4, reltol=1.0e-4, - ode_default_options()..., callback=callbacks); summary_callback() - errors = analysis_callback(sol) - if Trixi.mpi_isroot() - @test errors.l2 ≈ [0.00016800412839949264] rtol=1.0e-4 - @test errors.linf ≈ [0.0014548839020096516] rtol=1.0e-4 - end + # Linear scalar advection + @trixi_testset "elixir_advection_basic.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_basic.jl"), + # Expected errors are exactly the same as with TreeMesh! + l2=[0.00016263963870641478], + linf=[0.0014537194925779984]) + + @testset "error-based step size control" begin + Trixi.mpi_isroot() && println("-"^100) + Trixi.mpi_isroot() && + println("elixir_advection_basic.jl with error-based step size control") + + sol = solve(ode, RDPK3SpFSAL35(); abstol = 1.0e-4, reltol = 1.0e-4, + ode_default_options()..., callback = callbacks) + summary_callback() + errors = analysis_callback(sol) + if Trixi.mpi_isroot() + @test errors.l2≈[0.00016800412839949264] rtol=1.0e-4 + @test errors.linf≈[0.0014548839020096516] rtol=1.0e-4 + end + end + end + + @trixi_testset "elixir_advection_amr.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_amr.jl"), + # Expected errors are exactly the same as with TreeMesh! + l2=[9.773852895157622e-6], + linf=[0.0005853874124926162], + # override values are different from the serial tests to ensure each process holds at least + # one element, otherwise OrdinaryDiffEq fails during initialization + coverage_override=(maxiters = 6, + initial_refinement_level = 2, + base_level = 2, med_level = 3, + max_level = 4)) + end + + @trixi_testset "elixir_advection_amr_unstructured_curved.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_advection_amr_unstructured_curved.jl"), + l2=[1.6236411810065552e-5], + linf=[0.0010554006923731395], + tspan=(0.0, 1.0), + coverage_override=(maxiters = 6, + initial_refinement_level = 0, + base_level = 0, med_level = 1, + max_level = 2)) + end + + @trixi_testset "elixir_advection_restart.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_restart.jl"), + l2=[0.002590388934758452], + linf=[0.01840757696885409], + # With the default `maxiters = 1` in coverage tests, + # there would be no time steps after the restart. + coverage_override=(maxiters = 100_000,)) + end + + @trixi_testset "elixir_advection_cubed_sphere.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_cubed_sphere.jl"), + l2=[0.002006918015656413], + linf=[0.027655117058380085]) end - end - - @trixi_testset "elixir_advection_amr.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_amr.jl"), - # Expected errors are exactly the same as with TreeMesh! - l2 = [9.773852895157622e-6], - linf = [0.0005853874124926162], - # override values are different from the serial tests to ensure each process holds at least - # one element, otherwise OrdinaryDiffEq fails during initialization - coverage_override = (maxiters=6, initial_refinement_level=2, base_level=2, med_level=3, max_level=4)) - end - - @trixi_testset "elixir_advection_amr_unstructured_curved.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_amr_unstructured_curved.jl"), - l2 = [1.6236411810065552e-5], - linf = [0.0010554006923731395], - tspan = (0.0, 1.0), - coverage_override = (maxiters=6, initial_refinement_level=0, base_level=0, med_level=1, max_level=2)) - end - - @trixi_testset "elixir_advection_restart.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_restart.jl"), - l2 = [0.002590388934758452], - linf = [0.01840757696885409]) - end - - @trixi_testset "elixir_advection_cubed_sphere.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_cubed_sphere.jl"), - l2 = [0.002006918015656413], - linf = [0.027655117058380085]) - end - - # Compressible Euler - @trixi_testset "elixir_euler_source_terms_nonconforming_unstructured_curved.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms_nonconforming_unstructured_curved.jl"), - l2 = [4.070355207909268e-5, 4.4993257426833716e-5, 5.10588457841744e-5, 5.102840924036687e-5, 0.00019986264001630542], - linf = [0.0016987332417202072, 0.003622956808262634, 0.002029576258317789, 0.0024206977281964193, 0.008526972236273522], - tspan = (0.0, 0.01)) - end - - @trixi_testset "elixir_euler_source_terms_nonperiodic.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms_nonperiodic.jl"), - l2 = [0.0015106060984283647, 0.0014733349038567685, 0.00147333490385685, 0.001473334903856929, 0.0028149479453087093], - linf = [0.008070806335238156, 0.009007245083113125, 0.009007245083121784, 0.009007245083102688, 0.01562861968368434], - tspan = (0.0, 1.0)) - end - - @trixi_testset "elixir_euler_ec.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_ec.jl"), - l2 = [0.010380390326164493, 0.006192950051354618, 0.005970674274073704, 0.005965831290564327, 0.02628875593094754], - linf = [0.3326911600075694, 0.2824952141320467, 0.41401037398065543, 0.45574161423218573, 0.8099577682187109], - tspan = (0.0, 0.2), - coverage_override = (polydeg=3,)) # Prevent long compile time in CI - end - - @trixi_testset "elixir_euler_source_terms_nonperiodic_hohqmesh.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms_nonperiodic_hohqmesh.jl"), - l2 = [0.0042023406458005464, 0.004122532789279737, 0.0042448149597303616, 0.0036361316700401765, 0.007389845952982495], - linf = [0.04530610539892499, 0.02765695110527666, 0.05670295599308606, 0.048396544302230504, 0.1154589758186293]) - end -end + # Compressible Euler + @trixi_testset "elixir_euler_source_terms_nonconforming_unstructured_curved.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_source_terms_nonconforming_unstructured_curved.jl"), + l2=[ + 4.070355207909268e-5, + 4.4993257426833716e-5, + 5.10588457841744e-5, + 5.102840924036687e-5, + 0.00019986264001630542, + ], + linf=[ + 0.0016987332417202072, + 0.003622956808262634, + 0.002029576258317789, + 0.0024206977281964193, + 0.008526972236273522, + ], + tspan=(0.0, 0.01)) + end + + @trixi_testset "elixir_euler_source_terms_nonperiodic.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_source_terms_nonperiodic.jl"), + l2=[ + 0.0015106060984283647, + 0.0014733349038567685, + 0.00147333490385685, + 0.001473334903856929, + 0.0028149479453087093, + ], + linf=[ + 0.008070806335238156, + 0.009007245083113125, + 0.009007245083121784, + 0.009007245083102688, + 0.01562861968368434, + ], + tspan=(0.0, 1.0)) + end + + @trixi_testset "elixir_euler_ec.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_ec.jl"), + l2=[ + 0.010380390326164493, + 0.006192950051354618, + 0.005970674274073704, + 0.005965831290564327, + 0.02628875593094754, + ], + linf=[ + 0.3326911600075694, + 0.2824952141320467, + 0.41401037398065543, + 0.45574161423218573, + 0.8099577682187109, + ], + tspan=(0.0, 0.2), + coverage_override=(polydeg = 3,)) # Prevent long compile time in CI + end + + @trixi_testset "elixir_euler_source_terms_nonperiodic_hohqmesh.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_source_terms_nonperiodic_hohqmesh.jl"), + l2=[ + 0.0042023406458005464, + 0.004122532789279737, + 0.0042448149597303616, + 0.0036361316700401765, + 0.007389845952982495, + ], + linf=[ + 0.04530610539892499, + 0.02765695110527666, + 0.05670295599308606, + 0.048396544302230504, + 0.1154589758186293, + ]) + end +end end # P4estMesh MPI end # module diff --git a/test/test_mpi_tree.jl b/test/test_mpi_tree.jl index 8403fcf1b04..0831f6a1313 100644 --- a/test/test_mpi_tree.jl +++ b/test/test_mpi_tree.jl @@ -11,186 +11,334 @@ const EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") CI_ON_WINDOWS = (get(ENV, "GITHUB_ACTIONS", false) == "true") && Sys.iswindows() @testset "TreeMesh MPI" begin +#! format: noindent # Run basic tests @testset "Examples 2D" begin - # Linear scalar advection - @trixi_testset "elixir_advection_basic.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_basic.jl"), - # Expected errors are exactly the same as in the serial test! - l2 = [8.311947673061856e-6], - linf = [6.627000273229378e-5]) - end - - @trixi_testset "elixir_advection_restart.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_restart.jl"), - # Expected errors are exactly the same as in the serial test! - l2 = [7.81674284320524e-6], - linf = [6.314906965243505e-5]) - end - - @trixi_testset "elixir_advection_mortar.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_mortar.jl"), - # Expected errors are exactly the same as in the serial test! - l2 = [0.0015188466707237375], - linf = [0.008446655719187679]) - end - - @trixi_testset "elixir_advection_amr.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_amr.jl"), - # Expected errors are exactly the same as in the serial test! - l2 = [4.913300828257469e-5], - linf = [0.00045263895394385967], - coverage_override = (maxiters=6,)) - end - - @trixi_testset "elixir_advection_amr_nonperiodic.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_amr_nonperiodic.jl"), - # Expected errors are exactly the same as in the serial test! - l2 = [3.2207388565869075e-5], - linf = [0.0007508059772436404], - coverage_override = (maxiters=6,)) - end - - # Linear scalar advection with AMR - # These example files are only for testing purposes and have no practical use - @trixi_testset "elixir_advection_amr_refine_twice.jl" begin - # Here, we also test that SaveSolutionCallback prints multiple mesh files with AMR - # Start with a clean environment: remove Trixi.jl output directory if it exists - outdir = "out" - isdir(outdir) && rm(outdir, recursive=true) - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_amr_refine_twice.jl"), - l2 = [0.00020547512522578292], - linf = [0.007831753383083506], - coverage_override = (maxiters=6,)) - meshfiles = filter(file -> endswith(file,".h5") && startswith(file,"mesh"), readdir(outdir)) - @test length(meshfiles) > 1 - end - - @trixi_testset "elixir_advection_amr_coarsen_twice.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_amr_coarsen_twice.jl"), - l2 = [0.0014321062757891826], - linf = [0.0253454486893413], - coverage_override = (maxiters=6,)) - end - - # Hyperbolic diffusion - if !CI_ON_WINDOWS # see comment on `CI_ON_WINDOWS` in `test/test_mpi.jl` - @trixi_testset "elixir_hypdiff_lax_friedrichs.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_hypdiff_lax_friedrichs.jl"), - l2 = [0.00015687751816056159, 0.001025986772217084, 0.0010259867722169909], - linf = [0.0011986956416591976, 0.006423873516411049, 0.006423873516411049]) - end - end - - @trixi_testset "elixir_hypdiff_harmonic_nonperiodic.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_hypdiff_harmonic_nonperiodic.jl"), - l2 = [8.61813235543625e-8, 5.619399844542781e-7, 5.6193998447443e-7], - linf = [1.124861862180196e-6, 8.622436471039663e-6, 8.622436470151484e-6]) - end - - @trixi_testset "elixir_hypdiff_nonperiodic.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_hypdiff_nonperiodic.jl"), - l2 = [8.523077653955306e-6, 2.8779323653065056e-5, 5.4549427691297846e-5], - linf = [5.5227409524905013e-5, 0.0001454489597927185, 0.00032396328684569653]) - end - - if !CI_ON_WINDOWS # see comment on `CI_ON_WINDOWS` in `test/test_mpi.jl` - @trixi_testset "elixir_hypdiff_godunov.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_hypdiff_godunov.jl"), - l2 = [5.868147556427088e-6, 3.80517927324465e-5, 3.805179273249344e-5], - linf = [3.701965498725812e-5, 0.0002122422943138247, 0.00021224229431116015], - atol = 2.0e-12 #= required for CI on macOS =#) - end - end - - - # Compressible Euler - # Note: Some tests here have manually increased relative tolerances since reduction via MPI can - # slightly change the L2 error norms (different floating point truncation errors) - if !CI_ON_WINDOWS # see comment on `CI_ON_WINDOWS` in `test/test_mpi.jl` - @trixi_testset "elixir_euler_source_terms.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms.jl"), - l2 = [9.321181253186009e-7, 1.4181210743438511e-6, 1.4181210743487851e-6, 4.824553091276693e-6], - linf = [9.577246529612893e-6, 1.1707525976012434e-5, 1.1707525976456523e-5, 4.8869615580926506e-5], - rtol = 2000*sqrt(eps())) - end - end - - # This example file is only for testing purposes and has no practical use - if !CI_ON_WINDOWS # see comment on `CI_ON_WINDOWS` in `test/test_mpi.jl` - @trixi_testset "elixir_euler_source_terms_amr_refine_coarsen.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms_amr_refine_coarsen.jl"), - l2 = [4.8226610349853444e-5, 4.117706709270575e-5, 4.1177067092959676e-5, 0.00012205252427437389], - linf = [0.0003543874851490436, 0.0002973166773747593, 0.0002973166773760916, 0.001154106793870291], - # Let this test run until the end to cover the time-dependent lines - # of the indicator and the MPI-specific AMR code. - coverage_override = (maxiters=10^5,)) - end - end - - if !CI_ON_WINDOWS # see comment on `CI_ON_WINDOWS` in `test/test_mpi.jl` - @trixi_testset "elixir_euler_source_terms_nonperiodic.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms_nonperiodic.jl"), - l2 = [2.259440511766445e-6, 2.318888155713922e-6, 2.3188881557894307e-6, 6.3327863238858925e-6], - linf = [1.498738264560373e-5, 1.9182011928187137e-5, 1.918201192685487e-5, 6.0526717141407005e-5], - rtol = 0.001) - end - end - - if !CI_ON_WINDOWS # see comment on `CI_ON_WINDOWS` in `test/test_mpi.jl` - @trixi_testset "elixir_euler_ec.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_ec.jl"), - l2 = [0.061751715597716854, 0.05018223615408711, 0.05018989446443463, 0.225871559730513], - linf = [0.29347582879608825, 0.31081249232844693, 0.3107380389947736, 1.0540358049885143]) - - @testset "error-based step size control" begin - Trixi.mpi_isroot() && println("-"^100) - Trixi.mpi_isroot() && println("elixir_euler_ec.jl with error-based step size control") - - sol = solve(ode, RDPK3SpFSAL35(); abstol=1.0e-4, reltol=1.0e-4, - ode_default_options()..., callback=callbacks); summary_callback() - errors = analysis_callback(sol) - if Trixi.mpi_isroot() - @test errors.l2 ≈ [0.061653630426688116, 0.05006930431098764, 0.05007694316484242, 0.22550689872331683] rtol=1.0e-4 - @test errors.linf ≈ [0.28516937484583693, 0.2983633696512788, 0.297812036335975, 1.027368795517512] rtol=1.0e-4 + # Linear scalar advection + @trixi_testset "elixir_advection_basic.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_basic.jl"), + # Expected errors are exactly the same as in the serial test! + l2=[8.311947673061856e-6], + linf=[6.627000273229378e-5]) + end + + @trixi_testset "elixir_advection_restart.jl" begin + using OrdinaryDiffEq: RDPK3SpFSAL49 + Trixi.mpi_isroot() && println("═"^100) + Trixi.mpi_isroot() && + println(joinpath(EXAMPLES_DIR, "elixir_advection_extended.jl")) + trixi_include(@__MODULE__, + joinpath(EXAMPLES_DIR, "elixir_advection_extended.jl"), + alg = RDPK3SpFSAL49(), tspan = (0.0, 10.0)) + l2_expected, linf_expected = analysis_callback(sol) + + Trixi.mpi_isroot() && println("═"^100) + Trixi.mpi_isroot() && + println(joinpath(EXAMPLES_DIR, "elixir_advection_restart.jl")) + # Errors are exactly the same as in the elixir_advection_extended.jl + trixi_include(@__MODULE__, + joinpath(EXAMPLES_DIR, "elixir_advection_restart.jl"), + alg = RDPK3SpFSAL49()) + l2_actual, linf_actual = analysis_callback(sol) + + Trixi.mpi_isroot() && @test l2_actual == l2_expected + Trixi.mpi_isroot() && @test linf_actual == linf_expected + end + + @trixi_testset "elixir_advection_mortar.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_mortar.jl"), + # Expected errors are exactly the same as in the serial test! + l2=[0.0015188466707237375], + linf=[0.008446655719187679]) + end + + @trixi_testset "elixir_advection_amr.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_amr.jl"), + # Expected errors are exactly the same as in the serial test! + l2=[4.913300828257469e-5], + linf=[0.00045263895394385967], + coverage_override=(maxiters = 6,)) + end + + @trixi_testset "elixir_advection_amr_nonperiodic.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_advection_amr_nonperiodic.jl"), + # Expected errors are exactly the same as in the serial test! + l2=[3.2207388565869075e-5], + linf=[0.0007508059772436404], + coverage_override=(maxiters = 6,)) + end + + # Linear scalar advection with AMR + # These example files are only for testing purposes and have no practical use + @trixi_testset "elixir_advection_amr_refine_twice.jl" begin + # Here, we also test that SaveSolutionCallback prints multiple mesh files with AMR + # Start with a clean environment: remove Trixi.jl output directory if it exists + outdir = "out" + isdir(outdir) && rm(outdir, recursive = true) + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_advection_amr_refine_twice.jl"), + l2=[0.00020547512522578292], + linf=[0.007831753383083506], + coverage_override=(maxiters = 6,)) + meshfiles = filter(file -> endswith(file, ".h5") && startswith(file, "mesh"), + readdir(outdir)) + @test length(meshfiles) > 1 + end + + @trixi_testset "elixir_advection_amr_coarsen_twice.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_advection_amr_coarsen_twice.jl"), + l2=[0.0014321062757891826], + linf=[0.0253454486893413], + coverage_override=(maxiters = 6,)) + end + + # Hyperbolic diffusion + if !CI_ON_WINDOWS # see comment on `CI_ON_WINDOWS` in `test/test_mpi.jl` + @trixi_testset "elixir_hypdiff_lax_friedrichs.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_hypdiff_lax_friedrichs.jl"), + l2=[ + 0.00015687751816056159, + 0.001025986772217084, + 0.0010259867722169909, + ], + linf=[ + 0.0011986956416591976, + 0.006423873516411049, + 0.006423873516411049, + ]) end - end - end - end - - @trixi_testset "elixir_euler_vortex.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_vortex.jl"), - l2 = [0.00013492249515826863, 0.006615696236378061, 0.006782108219800376, 0.016393831451740604], - linf = [0.0020782600954247776, 0.08150078921935999, 0.08663621974991986, 0.2829930622010579], - rtol = 0.001) - end - - @trixi_testset "elixir_euler_vortex_mortar.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_vortex_mortar.jl"), - # Expected errors are exactly the same as in the serial test! - l2 = [0.0017208369388227673, 0.09628684992237334, 0.09620157717330868, 0.1758809552387432], - linf = [0.021869936355319086, 0.9956698009442038, 1.0002507727219028, 2.223249697515648]) - end - - @trixi_testset "elixir_euler_vortex_amr.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_vortex_amr.jl"), - # Expected errors are exactly the same as in the serial test! - l2 = [5.051719943432265e-5, 0.0022574259317084747, 0.0021755998463189713, 0.004346492398617521], - linf = [0.0012880114865917447, 0.03857193149447702, 0.031090457959835893, 0.12125130332971423], - coverage_override = (maxiters=6,)) - end - - if !CI_ON_WINDOWS # see comment on `CI_ON_WINDOWS` in `test/test_mpi.jl` - @trixi_testset "elixir_euler_vortex_shockcapturing.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_vortex_shockcapturing.jl"), - l2 = [0.0017158367642679273, 0.09619888722871434, 0.09616432767924141, 0.17553381166255197], - linf = [0.021853862449723982, 0.9878047229255944, 0.9880191167111795, 2.2154030488035588], - rtol = 0.001) - end - end -end + end + + @trixi_testset "elixir_hypdiff_harmonic_nonperiodic.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_hypdiff_harmonic_nonperiodic.jl"), + l2=[ + 8.61813235543625e-8, + 5.619399844542781e-7, + 5.6193998447443e-7, + ], + linf=[ + 1.124861862180196e-6, + 8.622436471039663e-6, + 8.622436470151484e-6, + ]) + end + + @trixi_testset "elixir_hypdiff_nonperiodic.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_hypdiff_nonperiodic.jl"), + l2=[ + 8.523077653955306e-6, + 2.8779323653065056e-5, + 5.4549427691297846e-5, + ], + linf=[ + 5.5227409524905013e-5, + 0.0001454489597927185, + 0.00032396328684569653, + ]) + end + + if !CI_ON_WINDOWS # see comment on `CI_ON_WINDOWS` in `test/test_mpi.jl` + @trixi_testset "elixir_hypdiff_godunov.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_hypdiff_godunov.jl"), + l2=[ + 5.868147556427088e-6, + 3.80517927324465e-5, + 3.805179273249344e-5, + ], + linf=[ + 3.701965498725812e-5, + 0.0002122422943138247, + 0.00021224229431116015, + ], + atol=2.0e-12) #= required for CI on macOS =# + end + end + + # Compressible Euler + # Note: Some tests here have manually increased relative tolerances since reduction via MPI can + # slightly change the L2 error norms (different floating point truncation errors) + if !CI_ON_WINDOWS # see comment on `CI_ON_WINDOWS` in `test/test_mpi.jl` + @trixi_testset "elixir_euler_source_terms.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms.jl"), + l2=[ + 9.321181253186009e-7, + 1.4181210743438511e-6, + 1.4181210743487851e-6, + 4.824553091276693e-6, + ], + linf=[ + 9.577246529612893e-6, + 1.1707525976012434e-5, + 1.1707525976456523e-5, + 4.8869615580926506e-5, + ], + rtol=2000 * sqrt(eps())) + end + end + + # This example file is only for testing purposes and has no practical use + if !CI_ON_WINDOWS # see comment on `CI_ON_WINDOWS` in `test/test_mpi.jl` + @trixi_testset "elixir_euler_source_terms_amr_refine_coarsen.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_source_terms_amr_refine_coarsen.jl"), + l2=[ + 4.8226610349853444e-5, + 4.117706709270575e-5, + 4.1177067092959676e-5, + 0.00012205252427437389, + ], + linf=[ + 0.0003543874851490436, + 0.0002973166773747593, + 0.0002973166773760916, + 0.001154106793870291, + ], + # Let this test run until the end to cover the time-dependent lines + # of the indicator and the MPI-specific AMR code. + coverage_override=(maxiters = 10^5,)) + end + end + + if !CI_ON_WINDOWS # see comment on `CI_ON_WINDOWS` in `test/test_mpi.jl` + @trixi_testset "elixir_euler_source_terms_nonperiodic.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_source_terms_nonperiodic.jl"), + l2=[ + 2.259440511766445e-6, + 2.318888155713922e-6, + 2.3188881557894307e-6, + 6.3327863238858925e-6, + ], + linf=[ + 1.498738264560373e-5, + 1.9182011928187137e-5, + 1.918201192685487e-5, + 6.0526717141407005e-5, + ], + rtol=0.001) + end + end + + if !CI_ON_WINDOWS # see comment on `CI_ON_WINDOWS` in `test/test_mpi.jl` + @trixi_testset "elixir_euler_ec.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_ec.jl"), + l2=[ + 0.061751715597716854, + 0.05018223615408711, + 0.05018989446443463, + 0.225871559730513, + ], + linf=[ + 0.29347582879608825, + 0.31081249232844693, + 0.3107380389947736, + 1.0540358049885143, + ]) + + @testset "error-based step size control" begin + Trixi.mpi_isroot() && println("-"^100) + Trixi.mpi_isroot() && + println("elixir_euler_ec.jl with error-based step size control") + sol = solve(ode, RDPK3SpFSAL35(); abstol = 1.0e-4, reltol = 1.0e-4, + ode_default_options()..., callback = callbacks) + summary_callback() + errors = analysis_callback(sol) + if Trixi.mpi_isroot() + @test errors.l2≈[ + 0.061653630426688116, + 0.05006930431098764, + 0.05007694316484242, + 0.22550689872331683, + ] rtol=1.0e-4 + @test errors.linf≈[ + 0.28516937484583693, + 0.2983633696512788, + 0.297812036335975, + 1.027368795517512, + ] rtol=1.0e-4 + end + end + end + end + + @trixi_testset "elixir_euler_vortex.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_vortex.jl"), + l2=[ + 0.00013492249515826863, + 0.006615696236378061, + 0.006782108219800376, + 0.016393831451740604, + ], + linf=[ + 0.0020782600954247776, + 0.08150078921935999, + 0.08663621974991986, + 0.2829930622010579, + ], + rtol=0.001) + end + + @trixi_testset "elixir_euler_vortex_mortar.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_vortex_mortar.jl"), + # Expected errors are exactly the same as in the serial test! + l2=[ + 0.0017208369388227673, + 0.09628684992237334, + 0.09620157717330868, + 0.1758809552387432, + ], + linf=[ + 0.021869936355319086, + 0.9956698009442038, + 1.0002507727219028, + 2.223249697515648, + ]) + end + + @trixi_testset "elixir_euler_vortex_amr.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_vortex_amr.jl"), + # Expected errors are exactly the same as in the serial test! + l2=[ + 5.051719943432265e-5, + 0.0022574259317084747, + 0.0021755998463189713, + 0.004346492398617521, + ], + linf=[ + 0.0012880114865917447, + 0.03857193149447702, + 0.031090457959835893, + 0.12125130332971423, + ], + coverage_override=(maxiters = 6,)) + end + + if !CI_ON_WINDOWS # see comment on `CI_ON_WINDOWS` in `test/test_mpi.jl` + @trixi_testset "elixir_euler_vortex_shockcapturing.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_vortex_shockcapturing.jl"), + l2=[ + 0.0017158367642679273, + 0.09619888722871434, + 0.09616432767924141, + 0.17553381166255197, + ], + linf=[ + 0.021853862449723982, + 0.9878047229255944, + 0.9880191167111795, + 2.2154030488035588, + ], + rtol=0.001) + end + end +end end # TreeMesh MPI end # module diff --git a/test/test_p4est_2d.jl b/test/test_p4est_2d.jl index c4ce2619e15..db34aecc168 100644 --- a/test/test_p4est_2d.jl +++ b/test/test_p4est_2d.jl @@ -9,169 +9,484 @@ EXAMPLES_DIR = joinpath(examples_dir(), "p4est_2d_dgsem") # Start with a clean environment: remove Trixi.jl output directory if it exists outdir = "out" -isdir(outdir) && rm(outdir, recursive=true) +isdir(outdir) && rm(outdir, recursive = true) @testset "P4estMesh2D" begin - @trixi_testset "elixir_advection_basic.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_basic.jl"), - # Expected errors are exactly the same as with TreeMesh! - l2 = [8.311947673061856e-6], - linf = [6.627000273229378e-5]) - end +#! format: noindent - @trixi_testset "elixir_advection_nonconforming_flag.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_nonconforming_flag.jl"), - l2 = [3.198940059144588e-5], - linf = [0.00030636069494005547]) +@trixi_testset "elixir_advection_basic.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_basic.jl"), + # Expected errors are exactly the same as with TreeMesh! + l2=[8.311947673061856e-6], + linf=[6.627000273229378e-5]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - # Ensure that we do not have excessive memory allocations +@trixi_testset "elixir_advection_nonconforming_flag.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_advection_nonconforming_flag.jl"), + l2=[3.198940059144588e-5], + linf=[0.00030636069494005547]) + # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 end - end +end - @trixi_testset "elixir_advection_unstructured_flag.jl" begin +@trixi_testset "elixir_advection_unstructured_flag.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_unstructured_flag.jl"), - l2 = [0.0005379687442422346], - linf = [0.007438525029884735]) - end - - @trixi_testset "elixir_advection_amr_solution_independent.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_amr_solution_independent.jl"), - # Expected errors are exactly the same as with StructuredMesh! - l2 = [4.949660644033807e-5], - linf = [0.0004867846262313763], - coverage_override = (maxiters=6,)) - end - - @trixi_testset "elixir_advection_amr_unstructured_flag.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_amr_unstructured_flag.jl"), - l2 = [0.0012766060609964525], - linf = [0.01750280631586159], - coverage_override = (maxiters=6,)) - end - - @trixi_testset "elixir_advection_restart.jl" begin + l2=[0.0005379687442422346], + linf=[0.007438525029884735]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_advection_amr_solution_independent.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_advection_amr_solution_independent.jl"), + # Expected errors are exactly the same as with StructuredMesh! + l2=[4.949660644033807e-5], + linf=[0.0004867846262313763], + coverage_override=(maxiters = 6,)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_advection_amr_unstructured_flag.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_advection_amr_unstructured_flag.jl"), + l2=[0.0012766060609964525], + linf=[0.01750280631586159], + coverage_override=(maxiters = 6,)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_advection_restart.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_restart.jl"), - l2 = [4.507575525876275e-6], - linf = [6.21489667023134e-5]) - end + l2=[4.507575525876275e-6], + linf=[6.21489667023134e-5], + # With the default `maxiters = 1` in coverage tests, + # there would be no time steps after the restart. + coverage_override=(maxiters = 100_000,)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_source_terms_nonconforming_unstructured_flag.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms_nonconforming_unstructured_flag.jl"), - l2 = [0.0034516244508588046, 0.0023420334036925493, 0.0024261923964557187, 0.004731710454271893], - linf = [0.04155789011775046, 0.024772109862748914, 0.03759938693042297, 0.08039824959535657]) - end +@trixi_testset "elixir_euler_source_terms_nonconforming_unstructured_flag.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_source_terms_nonconforming_unstructured_flag.jl"), + l2=[ + 0.0034516244508588046, + 0.0023420334036925493, + 0.0024261923964557187, + 0.004731710454271893, + ], + linf=[ + 0.04155789011775046, + 0.024772109862748914, + 0.03759938693042297, + 0.08039824959535657, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_free_stream.jl" begin +@trixi_testset "elixir_euler_free_stream.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_free_stream.jl"), - l2 = [2.063350241405049e-15, 1.8571016296925367e-14, 3.1769447886391905e-14, 1.4104095258528071e-14], - linf = [1.9539925233402755e-14, 2e-12, 4.8e-12, 4e-12], - atol = 2.0e-12, # required to make CI tests pass on macOS - ) - end + l2=[ + 2.063350241405049e-15, + 1.8571016296925367e-14, + 3.1769447886391905e-14, + 1.4104095258528071e-14, + ], + linf=[1.9539925233402755e-14, 2e-12, 4.8e-12, 4e-12], + atol=2.0e-12,) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_shockcapturing_ec.jl" begin +@trixi_testset "elixir_euler_shockcapturing_ec.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_shockcapturing_ec.jl"), - l2 = [9.53984675e-02, 1.05633455e-01, 1.05636158e-01, 3.50747237e-01], - linf = [2.94357464e-01, 4.07893014e-01, 3.97334516e-01, 1.08142520e+00], - tspan = (0.0, 1.0)) - end + l2=[ + 9.53984675e-02, + 1.05633455e-01, + 1.05636158e-01, + 3.50747237e-01, + ], + linf=[ + 2.94357464e-01, + 4.07893014e-01, + 3.97334516e-01, + 1.08142520e+00, + ], + tspan=(0.0, 1.0)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_sedov.jl" begin +@trixi_testset "elixir_euler_sedov.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov.jl"), - l2 = [3.76149952e-01, 2.46970327e-01, 2.46970327e-01, 1.28889042e+00], - linf = [1.22139001e+00, 1.17742626e+00, 1.17742626e+00, 6.20638482e+00], - tspan = (0.0, 0.3)) - end + l2=[ + 3.76149952e-01, + 2.46970327e-01, + 2.46970327e-01, + 1.28889042e+00, + ], + linf=[ + 1.22139001e+00, + 1.17742626e+00, + 1.17742626e+00, + 6.20638482e+00, + ], + tspan=(0.0, 0.3)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_blast_wave_amr.jl" begin +@trixi_testset "elixir_euler_sedov.jl (HLLE)" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov.jl"), + l2=[ + 0.40853279043747015, + 0.25356771650524296, + 0.2535677165052422, + 1.2984601729572691, + ], + linf=[ + 1.3840909333784284, + 1.3077772519086124, + 1.3077772519086157, + 6.298798630968632, + ], + surface_flux=flux_hlle, + tspan=(0.0, 0.3)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_blast_wave_amr.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave_amr.jl"), - l2 = [6.32183914e-01, 3.86914231e-01, 3.86869171e-01, 1.06575688e+00], - linf = [2.76020890e+00, 2.32659890e+00, 2.32580837e+00, 2.15778188e+00], - tspan = (0.0, 0.3), - coverage_override = (maxiters=6,)) - end + l2=[ + 6.32183914e-01, + 3.86914231e-01, + 3.86869171e-01, + 1.06575688e+00, + ], + linf=[ + 2.76020890e+00, + 2.32659890e+00, + 2.32580837e+00, + 2.15778188e+00, + ], + tspan=(0.0, 0.3), + coverage_override=(maxiters = 6,)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_wall_bc_amr.jl" begin +@trixi_testset "elixir_euler_wall_bc_amr.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_wall_bc_amr.jl"), - l2 = [0.020291447969983396, 0.017479614254319948, 0.011387644425613437, 0.0514420126021293], - linf = [0.3582779022370579, 0.32073537890751663, 0.221818049107692, 0.9209559420400415], - tspan = (0.0, 0.15)) - end + l2=[ + 0.020291447969983396, + 0.017479614254319948, + 0.011387644425613437, + 0.0514420126021293, + ], + linf=[ + 0.3582779022370579, + 0.32073537890751663, + 0.221818049107692, + 0.9209559420400415, + ], + tspan=(0.0, 0.15)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_forward_step_amr.jl" begin +@trixi_testset "elixir_euler_forward_step_amr.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_forward_step_amr.jl"), - l2 = [0.004194875320833303, 0.003785140699353966, 0.0013696609105790351, 0.03265268616046424], - linf = [2.0585399781442852, 2.213428805506876, 3.862362410419163, 17.75187237459251], - tspan = (0.0, 0.0001), - rtol = 1.0e-7, - skip_coverage=true) - end - - @trixi_testset "elixir_euler_double_mach_amr.jl" begin + l2=[ + 0.004194875320833303, + 0.003785140699353966, + 0.0013696609105790351, + 0.03265268616046424, + ], + linf=[ + 2.0585399781442852, + 2.213428805506876, + 3.862362410419163, + 17.75187237459251, + ], + tspan=(0.0, 0.0001), + rtol=1.0e-7, + skip_coverage=true) + if @isdefined sol # Skipped in coverage run + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end + end +end + +@trixi_testset "elixir_euler_double_mach_amr.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_double_mach_amr.jl"), - l2 = [0.051359355290192046, 0.4266034859911273, 0.2438304855475594, 4.11487176105527], - linf = [6.902000373057003, 53.95714139820832, 24.241610279839758, 561.0630401858057], - tspan = (0.0, 0.0001), - skip_coverage=true) - end + l2=[ + 0.051359355290192046, + 0.4266034859911273, + 0.2438304855475594, + 4.11487176105527, + ], + linf=[ + 6.902000373057003, + 53.95714139820832, + 24.241610279839758, + 561.0630401858057, + ], + tspan=(0.0, 0.0001), + skip_coverage=true) + if @isdefined sol # Skipped in coverage run + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end + end +end - @trixi_testset "elixir_euler_supersonic_cylinder.jl" begin +@trixi_testset "elixir_euler_supersonic_cylinder.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_supersonic_cylinder.jl"), - l2 = [0.026798021911954406, 0.05118546368109259, 0.03206703583774831, 0.19680026567208672], - linf = [3.653905721692421, 4.285035711361009, 6.8544353186357645, 31.748244912257533], - tspan = (0.0, 0.001), - skip_coverage=true) - end + l2=[ + 0.026798021911954406, + 0.05118546368109259, + 0.03206703583774831, + 0.19680026567208672, + ], + linf=[ + 3.653905721692421, + 4.285035711361009, + 6.8544353186357645, + 31.748244912257533, + ], + tspan=(0.0, 0.001), + skip_coverage=true) + if @isdefined sol # Skipped in coverage run + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end + end +end - @trixi_testset "elixir_eulergravity_convergence.jl" begin +@trixi_testset "elixir_eulergravity_convergence.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulergravity_convergence.jl"), - l2 = [0.00024871265138964204, 0.0003370077102132591, 0.0003370077102131964, 0.0007231525513793697], - linf = [0.0015813032944647087, 0.0020494288423820173, 0.0020494288423824614, 0.004793821195083758], - tspan = (0.0, 0.1)) - end + l2=[ + 0.00024871265138964204, + 0.0003370077102132591, + 0.0003370077102131964, + 0.0007231525513793697, + ], + linf=[ + 0.0015813032944647087, + 0.0020494288423820173, + 0.0020494288423824614, + 0.004793821195083758, + ], + tspan=(0.0, 0.1)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_shallowwater_source_terms.jl" begin +@trixi_testset "elixir_shallowwater_source_terms.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_source_terms.jl"), - l2 = [9.168126407325352e-5, 0.0009795410115453788, 0.002546408320320785, 3.941189812642317e-6], - linf = [0.0009903782521019089, 0.0059752684687262025, 0.010941106525454103, 1.2129488214718265e-5], - tspan = (0.0, 0.1)) - end + l2=[ + 9.168126407325352e-5, + 0.0009795410115453788, + 0.002546408320320785, + 3.941189812642317e-6, + ], + linf=[ + 0.0009903782521019089, + 0.0059752684687262025, + 0.010941106525454103, + 1.2129488214718265e-5, + ], + tspan=(0.0, 0.1)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_mhd_alfven_wave.jl" begin +@trixi_testset "elixir_mhd_alfven_wave.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_alfven_wave.jl"), - l2 = [1.0513414461545583e-5, 1.0517900957166411e-6, 1.0517900957304043e-6, 1.511816606372376e-6, - 1.0443997728645063e-6, 7.879639064990798e-7, 7.879639065049896e-7, 1.0628631669056271e-6, - 4.3382328912336153e-7], - linf = [4.255466285174592e-5, 1.0029706745823264e-5, 1.0029706747467781e-5, 1.2122265939010224e-5, - 5.4791097160444835e-6, 5.18922042269665e-6, 5.189220422141538e-6, 9.552667261422676e-6, - 1.4237578427628152e-6]) - end - - @trixi_testset "elixir_mhd_rotor.jl" begin + l2=[1.0513414461545583e-5, 1.0517900957166411e-6, + 1.0517900957304043e-6, 1.511816606372376e-6, + 1.0443997728645063e-6, 7.879639064990798e-7, + 7.879639065049896e-7, 1.0628631669056271e-6, + 4.3382328912336153e-7], + linf=[4.255466285174592e-5, 1.0029706745823264e-5, + 1.0029706747467781e-5, 1.2122265939010224e-5, + 5.4791097160444835e-6, 5.18922042269665e-6, + 5.189220422141538e-6, 9.552667261422676e-6, + 1.4237578427628152e-6]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_mhd_rotor.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_rotor.jl"), - l2 = [0.4552084651735862, 0.8918048264575757, 0.832471223081887, 0.0, - 0.9801264164951583, 0.10475690769435382, 0.1555132409149897, 0.0, - 2.0597079362763556e-5], - linf = [10.194181233788775, 18.25472397868819, 10.031307436191334, 0.0, - 19.647239392277378, 1.3938810140985936, 1.8724965294853084, 0.0, - 0.0016290067532561904], - tspan = (0.0, 0.02)) - end - - @trixi_testset "elixir_linearizedeuler_gaussian_source.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_linearizedeuler_gaussian_source.jl"), - l2 = [0.006047938590548741, 0.0040953286019907035, 0.004222698522497298, 0.006269492499336128], - linf = [0.06386175207349379, 0.0378926444850457, 0.041759728067967065, 0.06430136016259067]) - end + l2=[0.4552084651735862, 0.8918048264575757, 0.832471223081887, + 0.0, + 0.9801264164951583, 0.10475690769435382, 0.1555132409149897, + 0.0, + 2.0597079362763556e-5], + linf=[10.194181233788775, 18.25472397868819, 10.031307436191334, + 0.0, + 19.647239392277378, 1.3938810140985936, 1.8724965294853084, + 0.0, + 0.0016290067532561904], + tspan=(0.0, 0.02)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_linearizedeuler_gaussian_source.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_linearizedeuler_gaussian_source.jl"), + l2=[ + 0.006047938590548741, + 0.0040953286019907035, + 0.004222698522497298, + 0.006269492499336128, + ], + linf=[ + 0.06386175207349379, + 0.0378926444850457, + 0.041759728067967065, + 0.06430136016259067, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end end # Clean up afterwards: delete Trixi.jl output directory -@test_nowarn rm(outdir, recursive=true) +@test_nowarn rm(outdir, recursive = true) end # module diff --git a/test/test_p4est_3d.jl b/test/test_p4est_3d.jl index f22e98456ae..f2467f30204 100644 --- a/test/test_p4est_3d.jl +++ b/test/test_p4est_3d.jl @@ -9,168 +9,484 @@ EXAMPLES_DIR = joinpath(examples_dir(), "p4est_3d_dgsem") # Start with a clean environment: remove Trixi.jl output directory if it exists outdir = "out" -isdir(outdir) && rm(outdir, recursive=true) +isdir(outdir) && rm(outdir, recursive = true) @testset "P4estMesh3D" begin - @trixi_testset "elixir_advection_basic.jl" begin +#! format: noindent + +@trixi_testset "elixir_advection_basic.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_basic.jl"), - # Expected errors are exactly the same as with TreeMesh! - l2 = [0.00016263963870641478], - linf = [0.0014537194925779984]) - end - - @trixi_testset "elixir_advection_unstructured_curved.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_unstructured_curved.jl"), - l2 = [0.0004750004258546538], - linf = [0.026527551737137167]) - end - - @trixi_testset "elixir_advection_nonconforming.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_nonconforming.jl"), - l2 = [0.00253595715323843], - linf = [0.016486952252155795]) + # Expected errors are exactly the same as with TreeMesh! + l2=[0.00016263963870641478], + linf=[0.0014537194925779984]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - # Ensure that we do not have excessive memory allocations +@trixi_testset "elixir_advection_unstructured_curved.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_advection_unstructured_curved.jl"), + l2=[0.0004750004258546538], + linf=[0.026527551737137167]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_advection_nonconforming.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_nonconforming.jl"), + l2=[0.00253595715323843], + linf=[0.016486952252155795]) + # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 end - end +end - @trixi_testset "elixir_advection_amr.jl" begin +@trixi_testset "elixir_advection_amr.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_amr.jl"), - # Expected errors are exactly the same as with TreeMesh! - l2 = [9.773852895157622e-6], - linf = [0.0005853874124926162], - coverage_override = (maxiters=6, initial_refinement_level=1, base_level=1, med_level=2, max_level=3)) - end - - @trixi_testset "elixir_advection_amr_unstructured_curved.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_amr_unstructured_curved.jl"), - l2 = [1.6236411810065552e-5], - linf = [0.0010554006923731395], - tspan = (0.0, 1.0), - coverage_override = (maxiters=6, initial_refinement_level=0, base_level=0, med_level=1, max_level=2)) - end - - @trixi_testset "elixir_advection_cubed_sphere.jl" begin + # Expected errors are exactly the same as with TreeMesh! + l2=[9.773852895157622e-6], + linf=[0.0005853874124926162], + coverage_override=(maxiters = 6, initial_refinement_level = 1, + base_level = 1, med_level = 2, max_level = 3)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_advection_amr_unstructured_curved.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_advection_amr_unstructured_curved.jl"), + l2=[1.6236411810065552e-5], + linf=[0.0010554006923731395], + tspan=(0.0, 1.0), + coverage_override=(maxiters = 6, initial_refinement_level = 0, + base_level = 0, med_level = 1, max_level = 2)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_advection_cubed_sphere.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_cubed_sphere.jl"), - l2 = [0.002006918015656413], - linf = [0.027655117058380085]) - end + l2=[0.002006918015656413], + linf=[0.027655117058380085]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_advection_restart.jl" begin +@trixi_testset "elixir_advection_restart.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_restart.jl"), - l2 = [0.002590388934758452], - linf = [0.01840757696885409]) - end - - @trixi_testset "elixir_euler_source_terms_nonconforming_unstructured_curved.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms_nonconforming_unstructured_curved.jl"), - l2 = [4.070355207909268e-5, 4.4993257426833716e-5, 5.10588457841744e-5, 5.102840924036687e-5, 0.00019986264001630542], - linf = [0.0016987332417202072, 0.003622956808262634, 0.002029576258317789, 0.0024206977281964193, 0.008526972236273522], - tspan = (0.0, 0.01)) - end - - @trixi_testset "elixir_euler_source_terms_nonperiodic.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms_nonperiodic.jl"), - l2 = [0.0015106060984283647, 0.0014733349038567685, 0.00147333490385685, 0.001473334903856929, 0.0028149479453087093], - linf = [0.008070806335238156, 0.009007245083113125, 0.009007245083121784, 0.009007245083102688, 0.01562861968368434], - tspan = (0.0, 1.0)) - end - - @trixi_testset "elixir_euler_free_stream.jl" begin + l2=[0.002590388934758452], + linf=[0.01840757696885409], + # With the default `maxiters = 1` in coverage tests, + # there would be no time steps after the restart. + coverage_override=(maxiters = 100_000,)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_source_terms_nonconforming_unstructured_curved.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_source_terms_nonconforming_unstructured_curved.jl"), + l2=[ + 4.070355207909268e-5, + 4.4993257426833716e-5, + 5.10588457841744e-5, + 5.102840924036687e-5, + 0.00019986264001630542, + ], + linf=[ + 0.0016987332417202072, + 0.003622956808262634, + 0.002029576258317789, + 0.0024206977281964193, + 0.008526972236273522, + ], + tspan=(0.0, 0.01)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_source_terms_nonperiodic.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_source_terms_nonperiodic.jl"), + l2=[ + 0.0015106060984283647, + 0.0014733349038567685, + 0.00147333490385685, + 0.001473334903856929, + 0.0028149479453087093, + ], + linf=[ + 0.008070806335238156, + 0.009007245083113125, + 0.009007245083121784, + 0.009007245083102688, + 0.01562861968368434, + ], + tspan=(0.0, 1.0)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_free_stream.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_free_stream.jl"), - l2 = [5.162664597942288e-15, 1.941857343642486e-14, 2.0232366394187278e-14, 2.3381518645408552e-14, 7.083114561232324e-14], - linf = [7.269740365245525e-13, 3.289868377720495e-12, 4.440087186807773e-12, 3.8686831516088205e-12, 9.412914891981927e-12], - tspan = (0.0, 0.03)) - end + l2=[ + 5.162664597942288e-15, + 1.941857343642486e-14, + 2.0232366394187278e-14, + 2.3381518645408552e-14, + 7.083114561232324e-14, + ], + linf=[ + 7.269740365245525e-13, + 3.289868377720495e-12, + 4.440087186807773e-12, + 3.8686831516088205e-12, + 9.412914891981927e-12, + ], + tspan=(0.0, 0.03)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_free_stream_extruded.jl" begin +@trixi_testset "elixir_euler_free_stream_extruded.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_free_stream_extruded.jl"), - l2 = [8.444868392439035e-16, 4.889826056731442e-15, 2.2921260987087585e-15, 4.268460455702414e-15, 1.1356712092620279e-14], - linf = [7.749356711883593e-14, 2.8792246364872653e-13, 1.1121659149182506e-13, 3.3228975127030935e-13, 9.592326932761353e-13], - tspan=(0.0, 0.1)) - end + l2=[ + 8.444868392439035e-16, + 4.889826056731442e-15, + 2.2921260987087585e-15, + 4.268460455702414e-15, + 1.1356712092620279e-14, + ], + linf=[ + 7.749356711883593e-14, + 2.8792246364872653e-13, + 1.1121659149182506e-13, + 3.3228975127030935e-13, + 9.592326932761353e-13, + ], + tspan=(0.0, 0.1)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_ec.jl" begin +@trixi_testset "elixir_euler_ec.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_ec.jl"), - l2 = [0.010380390326164493, 0.006192950051354618, 0.005970674274073704, 0.005965831290564327, 0.02628875593094754], - linf = [0.3326911600075694, 0.2824952141320467, 0.41401037398065543, 0.45574161423218573, 0.8099577682187109], - tspan = (0.0, 0.2), - coverage_override = (polydeg=3,)) # Prevent long compile time in CI - end + l2=[ + 0.010380390326164493, + 0.006192950051354618, + 0.005970674274073704, + 0.005965831290564327, + 0.02628875593094754, + ], + linf=[ + 0.3326911600075694, + 0.2824952141320467, + 0.41401037398065543, + 0.45574161423218573, + 0.8099577682187109, + ], + tspan=(0.0, 0.2), + coverage_override=(polydeg = 3,)) # Prevent long compile time in CI + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_sedov.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov.jl"), + l2=[ + 7.82070951e-02, + 4.33260474e-02, + 4.33260474e-02, + 4.33260474e-02, + 3.75260911e-01, + ], + linf=[ + 7.45329845e-01, + 3.21754792e-01, + 3.21754792e-01, + 3.21754792e-01, + 4.76151527e+00, + ], + tspan=(0.0, 0.3), + coverage_override=(polydeg = 3,)) # Prevent long compile time in CI + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_sedov.jl" begin +@trixi_testset "elixir_euler_sedov.jl (HLLE)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov.jl"), - l2 = [7.82070951e-02, 4.33260474e-02, 4.33260474e-02, 4.33260474e-02, 3.75260911e-01], - linf = [7.45329845e-01, 3.21754792e-01, 3.21754792e-01, 3.21754792e-01, 4.76151527e+00], - tspan = (0.0, 0.3), - coverage_override = (polydeg=3,)) # Prevent long compile time in CI - end - - @trixi_testset "elixir_euler_source_terms_nonconforming_earth.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms_nonconforming_earth.jl"), - l2 = [6.040180337738628e-6, 5.4254175153621895e-6, 5.677698851333843e-6, 5.8017136892469794e-6, 1.3637854615117974e-5], - linf = [0.00013996924184311865, 0.00013681539559939893, 0.00013681539539733834, 0.00013681539541021692, 0.00016833038543762058], - # Decrease tolerance of adaptive time stepping to get similar results across different systems - abstol=1.0e-11, reltol=1.0e-11, - coverage_override = (trees_per_cube_face=(1, 1), polydeg=3)) # Prevent long compile time in CI - end - - @trixi_testset "elixir_euler_circular_wind_nonconforming.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_circular_wind_nonconforming.jl"), - l2 = [1.573832094977477e-7, 3.863090659429634e-5, 3.867293305754584e-5, 3.686550296950078e-5, 0.05508968493733932], - linf = [2.2695202613887133e-6, 0.0005314968179916946, 0.0005314969614147458, 0.0005130280733059617, 0.7944959432352334], - tspan = (0.0, 2e2), - coverage_override = (trees_per_cube_face=(1, 1), polydeg=3)) # Prevent long compile time in CI - end - - @trixi_testset "elixir_euler_baroclinic_instability.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_baroclinic_instability.jl"), - l2 = [6.725065410642336e-7, 0.00021710117340245454, 0.000438679759422352, 0.00020836356588024185, 0.07602006689579247], - linf = [1.9101671995258585e-5, 0.029803626911022396, 0.04847630924006063, 0.022001371349740104, 4.847761006938526], - tspan = (0.0, 1e2), - # Decrease tolerance of adaptive time stepping to get similar results across different systems - abstol=1.0e-9, reltol=1.0e-9, - coverage_override = (trees_per_cube_face=(1, 1), polydeg=3)) # Prevent long compile time in CI - end - - @trixi_testset "elixir_euler_source_terms_nonperiodic_hohqmesh.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms_nonperiodic_hohqmesh.jl"), - l2 = [0.0042023406458005464, 0.004122532789279737, 0.0042448149597303616, 0.0036361316700401765, 0.007389845952982495], - linf = [0.04530610539892499, 0.02765695110527666, 0.05670295599308606, 0.048396544302230504, 0.1154589758186293]) - end - - @trixi_testset "elixir_mhd_alfven_wave_nonconforming.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_alfven_wave_nonconforming.jl"), - l2 = [0.00019018725889431733, 0.0006523517707148006, 0.0002401595437705759, 0.0007796920661427565, - 0.0007095787460334334, 0.0006558819731628876, 0.0003565026134076906, 0.0007904654548841712, - 9.437300326448332e-7], - linf = [0.0012482306861187897, 0.006408776208178299, 0.0016845452099629663, 0.0068711236542984555, - 0.004626581522263695, 0.006614624811393632, 0.0030068344747734566, 0.008277825749754025, - 1.3475027166309006e-5], - tspan = (0.0, 0.25), - coverage_override = (trees_per_dimension=(1, 1, 1),)) - end - - @trixi_testset "elixir_mhd_shockcapturing_amr.jl" begin + l2=[ + 0.09946224487902565, + 0.04863386374672001, + 0.048633863746720116, + 0.04863386374672032, + 0.3751015774232693, + ], + linf=[ + 0.789241521871487, + 0.42046970270100276, + 0.42046970270100276, + 0.4204697027010028, + 4.730877375538398, + ], + tspan=(0.0, 0.3), + surface_flux=flux_hlle) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_source_terms_nonconforming_earth.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_source_terms_nonconforming_earth.jl"), + l2=[ + 6.040180337738628e-6, + 5.4254175153621895e-6, + 5.677698851333843e-6, + 5.8017136892469794e-6, + 1.3637854615117974e-5, + ], + linf=[ + 0.00013996924184311865, + 0.00013681539559939893, + 0.00013681539539733834, + 0.00013681539541021692, + 0.00016833038543762058, + ], + # Decrease tolerance of adaptive time stepping to get similar results across different systems + abstol=1.0e-11, reltol=1.0e-11, + coverage_override=(trees_per_cube_face = (1, 1), polydeg = 3)) # Prevent long compile time in CI + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_circular_wind_nonconforming.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_circular_wind_nonconforming.jl"), + l2=[ + 1.573832094977477e-7, + 3.863090659429634e-5, + 3.867293305754584e-5, + 3.686550296950078e-5, + 0.05508968493733932, + ], + linf=[ + 2.2695202613887133e-6, + 0.0005314968179916946, + 0.0005314969614147458, + 0.0005130280733059617, + 0.7944959432352334, + ], + tspan=(0.0, 2e2), + coverage_override=(trees_per_cube_face = (1, 1), polydeg = 3)) # Prevent long compile time in CI + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_baroclinic_instability.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_baroclinic_instability.jl"), + l2=[ + 6.725065410642336e-7, + 0.00021710117340245454, + 0.000438679759422352, + 0.00020836356588024185, + 0.07602006689579247, + ], + linf=[ + 1.9101671995258585e-5, + 0.029803626911022396, + 0.04847630924006063, + 0.022001371349740104, + 4.847761006938526, + ], + tspan=(0.0, 1e2), + # Decrease tolerance of adaptive time stepping to get similar results across different systems + abstol=1.0e-9, reltol=1.0e-9, + coverage_override=(trees_per_cube_face = (1, 1), polydeg = 3)) # Prevent long compile time in CI + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_source_terms_nonperiodic_hohqmesh.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_source_terms_nonperiodic_hohqmesh.jl"), + l2=[ + 0.0042023406458005464, + 0.004122532789279737, + 0.0042448149597303616, + 0.0036361316700401765, + 0.007389845952982495, + ], + linf=[ + 0.04530610539892499, + 0.02765695110527666, + 0.05670295599308606, + 0.048396544302230504, + 0.1154589758186293, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_mhd_alfven_wave_nonconforming.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_mhd_alfven_wave_nonconforming.jl"), + l2=[0.00019018725889431733, 0.0006523517707148006, + 0.0002401595437705759, 0.0007796920661427565, + 0.0007095787460334334, 0.0006558819731628876, + 0.0003565026134076906, 0.0007904654548841712, + 9.437300326448332e-7], + linf=[0.0012482306861187897, 0.006408776208178299, + 0.0016845452099629663, 0.0068711236542984555, + 0.004626581522263695, 0.006614624811393632, + 0.0030068344747734566, 0.008277825749754025, + 1.3475027166309006e-5], + tspan=(0.0, 0.25), + coverage_override=(trees_per_dimension = (1, 1, 1),)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_mhd_shockcapturing_amr.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_shockcapturing_amr.jl"), - l2 = [0.006298541670176575, 0.0064368506652601265, 0.007108729762852636, 0.006530420607206385, - 0.02061185869237284, 0.005562033787605515, 0.007571716276627825, 0.005571862660453231, - 3.909755063709152e-6], - linf = [0.20904054009050665, 0.18622917151105936, 0.2347957890323218, 0.19432508025509926, - 0.6858860133405615, 0.15172116633332622, 0.22432820727833747, 0.16805989780225183, - 0.000535219040687628], - tspan = (0.0, 0.04), - coverage_override = (maxiters=6, initial_refinement_level=1, base_level=1, max_level=2)) - end + l2=[0.006298541670176575, 0.0064368506652601265, + 0.007108729762852636, 0.006530420607206385, + 0.02061185869237284, 0.005562033787605515, + 0.007571716276627825, 0.005571862660453231, + 3.909755063709152e-6], + linf=[0.20904054009050665, 0.18622917151105936, + 0.2347957890323218, 0.19432508025509926, + 0.6858860133405615, 0.15172116633332622, + 0.22432820727833747, 0.16805989780225183, + 0.000535219040687628], + tspan=(0.0, 0.04), + coverage_override=(maxiters = 6, initial_refinement_level = 1, + base_level = 1, max_level = 2)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end end # Clean up afterwards: delete Trixi.jl output directory -@test_nowarn rm(outdir, recursive=true) +@test_nowarn rm(outdir, recursive = true) end # module diff --git a/test/test_paper_self_gravitating_gas_dynamics.jl b/test/test_paper_self_gravitating_gas_dynamics.jl index 6a35543fe47..10b4f93ad74 100644 --- a/test/test_paper_self_gravitating_gas_dynamics.jl +++ b/test/test_paper_self_gravitating_gas_dynamics.jl @@ -7,127 +7,352 @@ include("test_trixi.jl") # Start with a clean environment: remove Trixi.jl output directory if it exists outdir = "out" -isdir(outdir) && rm(outdir, recursive=true) +isdir(outdir) && rm(outdir, recursive = true) const EXAMPLES_DIR = pkgdir(Trixi, "examples", "paper_self_gravitating_gas_dynamics") # Numerical examples from the Euler-gravity paper @testset "paper_self_gravitating_gas_dynamics" begin - @trixi_testset "elixir_euler_convergence.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_convergence.jl"), - l2 = [0.0001740977055972079, 0.0003369355182519592, 0.0003369355182518708, 0.0006099171220334989], - linf = [0.001079347149189669, 0.0018836938381321389, 0.001883693838132583, 0.003971575376718217]) - end +#! format: noindent - @trixi_testset "elixir_euler_convergence.jl with polydeg=4" begin +@trixi_testset "elixir_euler_convergence.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_convergence.jl"), - l2 = [1.7187201161597772e-5, 2.678065111772951e-5, 2.678065111783027e-5, 4.952504160091526e-5], - linf = [0.0001501749544159381, 0.00016549482504535362, 0.00016549482504601976, 0.0004372960291432193], - polydeg = 4) - end + l2=[ + 0.0001740977055972079, + 0.0003369355182519592, + 0.0003369355182518708, + 0.0006099171220334989, + ], + linf=[ + 0.001079347149189669, + 0.0018836938381321389, + 0.001883693838132583, + 0.003971575376718217, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end +@trixi_testset "elixir_euler_convergence.jl with polydeg=4" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_convergence.jl"), + l2=[ + 1.7187201161597772e-5, + 2.678065111772951e-5, + 2.678065111783027e-5, + 4.952504160091526e-5, + ], + linf=[ + 0.0001501749544159381, + 0.00016549482504535362, + 0.00016549482504601976, + 0.0004372960291432193, + ], + polydeg=4) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_hypdiff_convergence.jl" begin +@trixi_testset "elixir_hypdiff_convergence.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_hypdiff_convergence.jl"), - l2 = [0.003154024896093942, 0.012394432074951856, 0.02185973823794725], - linf = [0.01731850928579215, 0.07843510773347553, 0.11242300176349201]) - end + l2=[ + 0.003154024896093942, + 0.012394432074951856, + 0.02185973823794725, + ], + linf=[ + 0.01731850928579215, + 0.07843510773347553, + 0.11242300176349201, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_hypdiff_convergence.jl with polydeg=4" begin +@trixi_testset "elixir_hypdiff_convergence.jl with polydeg=4" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_hypdiff_convergence.jl"), - l2 = [0.0002511283012128458, 0.0008808243846610255, 0.0016313343228567005], - linf = [0.0017290715087938668, 0.003129184465704738, 0.01000728849316701], - polydeg = 4) - end - + l2=[ + 0.0002511283012128458, + 0.0008808243846610255, + 0.0016313343228567005, + ], + linf=[ + 0.0017290715087938668, + 0.003129184465704738, + 0.01000728849316701, + ], + polydeg=4) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_eulergravity_convergence.jl" begin +@trixi_testset "elixir_eulergravity_convergence.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulergravity_convergence.jl"), - l2 = [0.00024871265138964204, 0.0003370077102132591, 0.0003370077102131964, 0.0007231525513793697], - linf = [0.0015813032944647087, 0.0020494288423820173, 0.0020494288423824614, 0.004793821195083758], - tspan = (0.0, 0.1)) - end + l2=[ + 0.00024871265138964204, + 0.0003370077102132591, + 0.0003370077102131964, + 0.0007231525513793697, + ], + linf=[ + 0.0015813032944647087, + 0.0020494288423820173, + 0.0020494288423824614, + 0.004793821195083758, + ], + tspan=(0.0, 0.1)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_eulergravity_convergence.jl with polydeg=4" begin +@trixi_testset "elixir_eulergravity_convergence.jl with polydeg=4" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulergravity_convergence.jl"), - l2 = [1.9537712148648045e-5, 2.7564396197947587e-5, 2.7564396197967635e-5, 5.688838772067586e-5], - linf = [0.00012335710672761735, 0.00020086268350816283, 0.00020086268350727465, 0.0004962155455632278], - tspan = (0.0, 0.1), polydeg = 4) - end + l2=[ + 1.9537712148648045e-5, + 2.7564396197947587e-5, + 2.7564396197967635e-5, + 5.688838772067586e-5, + ], + linf=[ + 0.00012335710672761735, + 0.00020086268350816283, + 0.00020086268350727465, + 0.0004962155455632278, + ], + tspan=(0.0, 0.1), polydeg=4) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_eulergravity_convergence.jl with 1st order RK3S*" begin +@trixi_testset "elixir_eulergravity_convergence.jl with 1st order RK3S*" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulergravity_convergence.jl"), - l2 = [0.00024871265138959434, 0.000337007710281087, 0.0003370077102811394, 0.0007231525515231289], - linf = [0.0015813032941613958, 0.002049428843978518, 0.0020494288439798503, 0.004793821198143977], - tspan = (0.0, 0.1), timestep_gravity=Trixi.timestep_gravity_erk51_3Sstar!) - end + l2=[ + 0.00024871265138959434, + 0.000337007710281087, + 0.0003370077102811394, + 0.0007231525515231289, + ], + linf=[ + 0.0015813032941613958, + 0.002049428843978518, + 0.0020494288439798503, + 0.004793821198143977, + ], + tspan=(0.0, 0.1), + timestep_gravity=Trixi.timestep_gravity_erk51_3Sstar!) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_eulergravity_convergence.jl with 3rd order RK3S*" begin +@trixi_testset "elixir_eulergravity_convergence.jl with 3rd order RK3S*" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulergravity_convergence.jl"), - l2 = [0.0002487126513894034, 0.00033700771023049785, 0.00033700771023048245, 0.0007231525514158737], - linf = [0.0015813032943847727, 0.002049428842844314, 0.0020494288428452023, 0.004793821195971937], - tspan = (0.0, 0.1), timestep_gravity=Trixi.timestep_gravity_erk53_3Sstar!) - end - - - @trixi_testset "elixir_eulergravity_jeans_instability.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulergravity_jeans_instability.jl"), - l2 = [10733.63378538114, 13356.780607423452, 1.6722844879795038e-6, 26834.076821148774], - linf = [15194.296424901113, 18881.481685044182, 6.809726988008751e-6, 37972.99700513482], - tspan = (0.0, 0.1), - atol = 4.0e-6 # the background field is reatively large, so this corresponds to our usual atol - ) - end - - @trixi_testset "elixir_eulergravity_jeans_instability.jl with RK3S*" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulergravity_jeans_instability.jl"), - l2 = [10734.598193238024, 13358.217234481384, 1.911011743371934e-6, 26836.487841241516], - linf = [15195.661004798487, 18883.512035906537, 7.867948710816926e-6, 37976.408478975296], - tspan = (0.0, 0.1), - atol = 4.0e-6, # the background field is reatively large, so this corresponds to our usual atol - parameters=ParametersEulerGravity(background_density=1.5e7, - gravitational_constant=6.674e-8, - cfl=2.4, - resid_tol=1.0e-4, - n_iterations_max=1000, - timestep_gravity=timestep_gravity_erk52_3Sstar!)) - end - - @trixi_testset "Printing" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulergravity_jeans_instability.jl"), - tspan = (0.0, 1.0e-5), - parameters=ParametersEulerGravity(background_density=1.5e7, - gravitational_constant=6.674e-8, - cfl=2.4, - resid_tol=1.0e-4, - n_iterations_max=1000, - timestep_gravity=timestep_gravity_erk52_3Sstar!)) + l2=[ + 0.0002487126513894034, + 0.00033700771023049785, + 0.00033700771023048245, + 0.0007231525514158737, + ], + linf=[ + 0.0015813032943847727, + 0.002049428842844314, + 0.0020494288428452023, + 0.004793821195971937, + ], + tspan=(0.0, 0.1), + timestep_gravity=Trixi.timestep_gravity_erk53_3Sstar!) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_eulergravity_jeans_instability.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_eulergravity_jeans_instability.jl"), + l2=[ + 10733.63378538114, + 13356.780607423452, + 1.6722844879795038e-6, + 26834.076821148774, + ], + linf=[ + 15194.296424901113, + 18881.481685044182, + 6.809726988008751e-6, + 37972.99700513482, + ], + tspan=(0.0, 0.1), + atol=4.0e-6) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_eulergravity_jeans_instability.jl with RK3S*" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_eulergravity_jeans_instability.jl"), + l2=[ + 10734.598193238024, + 13358.217234481384, + 1.911011743371934e-6, + 26836.487841241516, + ], + linf=[ + 15195.661004798487, + 18883.512035906537, + 7.867948710816926e-6, + 37976.408478975296, + ], + tspan=(0.0, 0.1), + atol=4.0e-6, # the background field is reatively large, so this corresponds to our usual atol + parameters=ParametersEulerGravity(background_density = 1.5e7, + gravitational_constant = 6.674e-8, + cfl = 2.4, + resid_tol = 1.0e-4, + n_iterations_max = 1000, + timestep_gravity = timestep_gravity_erk52_3Sstar!)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "Printing" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_eulergravity_jeans_instability.jl"), + tspan=(0.0, 1.0e-5), + parameters=ParametersEulerGravity(background_density = 1.5e7, + gravitational_constant = 6.674e-8, + cfl = 2.4, + resid_tol = 1.0e-4, + n_iterations_max = 1000, + timestep_gravity = timestep_gravity_erk52_3Sstar!)) show(stdout, parameters) show(stdout, semi) show(stdout, semi_euler.boundary_conditions) show(stdout, TrivialCallback()) show(stdout, equations_euler) - end - - - @trixi_testset "elixir_eulergravity_sedov_blast_wave.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulergravity_sedov_blast_wave.jl"), - l2 = [0.046315994852653024, 0.0650818006233669, 0.06508180062336677, 0.4896707211656037], - linf = [2.3874843337593776, 4.07876384374792, 4.07876384374792, 16.23914384809855], - tspan = (0.0, 0.05), - coverage_override = (maxiters=2,)) - end - - @trixi_testset "elixir_eulergravity_sedov_blast_wave.jl with ref-level=8 and no AMR" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulergravity_sedov_blast_wave.jl"), - l2 = [0.00289222135995042, 0.013724813590853825, 0.013724813590853832, 0.05822904710548214], - linf = [0.26361780693997594, 1.3908873830688688, 1.3908873830688688, 4.066701303607613], - tspan = (0.0, 0.005), initial_refinement_level=8, amr_callback=TrivialCallback()) - end + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_eulergravity_sedov_blast_wave.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_eulergravity_sedov_blast_wave.jl"), + l2=[ + 0.046315994852653024, + 0.0650818006233669, + 0.06508180062336677, + 0.4896707211656037, + ], + linf=[ + 2.3874843337593776, + 4.07876384374792, + 4.07876384374792, + 16.23914384809855, + ], + tspan=(0.0, 0.05), + coverage_override=(maxiters = 2,)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_eulergravity_sedov_blast_wave.jl with ref-level=8 and no AMR" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_eulergravity_sedov_blast_wave.jl"), + l2=[ + 0.00289222135995042, + 0.013724813590853825, + 0.013724813590853832, + 0.05822904710548214, + ], + linf=[ + 0.26361780693997594, + 1.3908873830688688, + 1.3908873830688688, + 4.066701303607613, + ], + tspan=(0.0, 0.005), initial_refinement_level=8, + amr_callback=TrivialCallback()) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end end # Clean up afterwards: delete Trixi.jl output directory -@test_nowarn rm(outdir, recursive=true) +@test_nowarn rm(outdir, recursive = true) end #module diff --git a/test/test_parabolic_1d.jl b/test/test_parabolic_1d.jl index 06a55100d62..c1cfec052fe 100644 --- a/test/test_parabolic_1d.jl +++ b/test/test_parabolic_1d.jl @@ -5,57 +5,217 @@ using Trixi include("test_trixi.jl") - # Start with a clean environment: remove Trixi output directory if it exists outdir = "out" -isdir(outdir) && rm(outdir, recursive=true) +isdir(outdir) && rm(outdir, recursive = true) @testset "SemidiscretizationHyperbolicParabolic (1D)" begin +#! format: noindent + +@trixi_testset "TreeMesh1D: elixir_advection_diffusion.jl" begin + @test_trixi_include(joinpath(examples_dir(), "tree_1d_dgsem", + "elixir_advection_diffusion.jl"), + initial_refinement_level=4, tspan=(0.0, 0.4), polydeg=3, + l2=[8.389498188525518e-06], + linf=[2.847421658558336e-05]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "TreeMesh1D: elixir_advection_diffusion.jl" begin - @test_trixi_include(joinpath(examples_dir(), "tree_1d_dgsem", "elixir_advection_diffusion.jl"), - initial_refinement_level = 4, tspan=(0.0, 0.4), polydeg=3, - l2 = [8.389498188525518e-06], - linf = [2.847421658558336e-05] - ) - end - - @trixi_testset "TreeMesh1D: elixir_navierstokes_convergence_periodic.jl" begin - @test_trixi_include(joinpath(examples_dir(), "tree_1d_dgsem", "elixir_navierstokes_convergence_periodic.jl"), - l2 = [0.0001133835907077494, 6.226282245610444e-5, 0.0002820171699999139], - linf = [0.0006255102377159538, 0.00036195501456059986, 0.0016147729485886941] - ) - end - - @trixi_testset "TreeMesh1D: elixir_navierstokes_convergence_periodic.jl: GradientVariablesEntropy" begin - @test_trixi_include(joinpath(examples_dir(), "tree_1d_dgsem", "elixir_navierstokes_convergence_periodic.jl"), - equations_parabolic = CompressibleNavierStokesDiffusion1D(equations, mu=mu(), - Prandtl=prandtl_number(), - gradient_variables = GradientVariablesEntropy()), - l2 = [0.00011310615871043463, 6.216495207074201e-5, 0.00028195843110817814], - linf = [0.0006240837363233886, 0.0003616694320713876, 0.0016147339542413874] - ) - end - - @trixi_testset "TreeMesh1D: elixir_navierstokes_convergence_walls.jl" begin - @test_trixi_include(joinpath(examples_dir(), "tree_1d_dgsem", "elixir_navierstokes_convergence_walls.jl"), - l2 = [0.00047023310868269237, 0.00032181736027057234, 0.0014966266486095025], - linf = [0.002996375101363302, 0.002863904256059634, 0.012691132946258676] - ) - end - - @trixi_testset "TreeMesh1D: elixir_navierstokes_convergence_walls.jl: GradientVariablesEntropy" begin - @test_trixi_include(joinpath(examples_dir(), "tree_1d_dgsem", "elixir_navierstokes_convergence_walls.jl"), - equations_parabolic = CompressibleNavierStokesDiffusion1D(equations, mu=mu(), - Prandtl=prandtl_number(), - gradient_variables = GradientVariablesEntropy()), - l2 = [0.0004608500483647771, 0.00032431091222851285, 0.0015159733360626845], - linf = [0.002754803146635787, 0.0028567714697580906, 0.012941794048176192] - ) - end +@trixi_testset "TreeMesh1D: elixir_advection_diffusion.jl (AMR)" begin + @test_trixi_include(joinpath(examples_dir(), "tree_1d_dgsem", + "elixir_advection_diffusion.jl"), + tspan=(0.0, 0.0), initial_refinement_level=5) + tspan = (0.0, 1.0) + ode = semidiscretize(semi, tspan) + amr_controller = ControllerThreeLevel(semi, IndicatorMax(semi, variable = first), + base_level = 4, + med_level = 5, med_threshold = 0.1, + max_level = 6, max_threshold = 0.6) + amr_callback = AMRCallback(semi, amr_controller, + interval = 5, + adapt_initial_condition = true) + + # Create a CallbackSet to collect all callbacks such that they can be passed to the ODE solver + callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, + amr_callback) + sol = solve(ode, KenCarp4(autodiff = false), abstol = time_abs_tol, + reltol = time_int_tol, + save_everystep = false, callback = callbacks) + l2_error, linf_error = analysis_callback(sol) + @test l2_error ≈ [6.4878111416468355e-6] + @test linf_error ≈ [3.258075790424364e-5] + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "TreeMesh1D: elixir_navierstokes_convergence_periodic.jl" begin + @test_trixi_include(joinpath(examples_dir(), "tree_1d_dgsem", + "elixir_navierstokes_convergence_periodic.jl"), + l2=[ + 0.0001133835907077494, + 6.226282245610444e-5, + 0.0002820171699999139, + ], + linf=[ + 0.0006255102377159538, + 0.00036195501456059986, + 0.0016147729485886941, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "TreeMesh1D: elixir_navierstokes_convergence_periodic.jl: GradientVariablesEntropy" begin + @test_trixi_include(joinpath(examples_dir(), "tree_1d_dgsem", + "elixir_navierstokes_convergence_periodic.jl"), + equations_parabolic=CompressibleNavierStokesDiffusion1D(equations, + mu = mu(), + Prandtl = prandtl_number(), + gradient_variables = GradientVariablesEntropy()), + l2=[ + 0.00011310615871043463, + 6.216495207074201e-5, + 0.00028195843110817814, + ], + linf=[ + 0.0006240837363233886, + 0.0003616694320713876, + 0.0016147339542413874, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "TreeMesh1D: elixir_navierstokes_convergence_walls.jl" begin + @test_trixi_include(joinpath(examples_dir(), "tree_1d_dgsem", + "elixir_navierstokes_convergence_walls.jl"), + l2=[ + 0.00047023310868269237, + 0.00032181736027057234, + 0.0014966266486095025, + ], + linf=[ + 0.002996375101363302, + 0.002863904256059634, + 0.012691132946258676, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "TreeMesh1D: elixir_navierstokes_convergence_walls.jl: GradientVariablesEntropy" begin + @test_trixi_include(joinpath(examples_dir(), "tree_1d_dgsem", + "elixir_navierstokes_convergence_walls.jl"), + equations_parabolic=CompressibleNavierStokesDiffusion1D(equations, + mu = mu(), + Prandtl = prandtl_number(), + gradient_variables = GradientVariablesEntropy()), + l2=[ + 0.0004608500483647771, + 0.00032431091222851285, + 0.0015159733360626845, + ], + linf=[ + 0.002754803146635787, + 0.0028567714697580906, + 0.012941794048176192, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "TreeMesh1D: elixir_navierstokes_convergence_walls_amr.jl" begin + @test_trixi_include(joinpath(examples_dir(), "tree_1d_dgsem", + "elixir_navierstokes_convergence_walls_amr.jl"), + equations_parabolic=CompressibleNavierStokesDiffusion1D(equations, + mu = mu(), + Prandtl = prandtl_number()), + l2=[ + 2.5278824700860636e-5, + 2.5540078777006958e-5, + 0.00012118655083858043, + ], + linf=[ + 0.0001466387075579334, + 0.00019422427462629705, + 0.0009556446847707178, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "TreeMesh1D: elixir_navierstokes_convergence_walls_amr.jl: GradientVariablesEntropy" begin + @test_trixi_include(joinpath(examples_dir(), "tree_1d_dgsem", + "elixir_navierstokes_convergence_walls_amr.jl"), + equations_parabolic=CompressibleNavierStokesDiffusion1D(equations, + mu = mu(), + Prandtl = prandtl_number(), + gradient_variables = GradientVariablesEntropy()), + l2=[ + 2.459359632523962e-5, + 2.3928390718460263e-5, + 0.00011252414117082376, + ], + linf=[ + 0.0001185052018830568, + 0.00018987717854305393, + 0.0009597503607920999, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end end # Clean up afterwards: delete Trixi output directory -@test_nowarn isdir(outdir) && rm(outdir, recursive=true) +@test_nowarn isdir(outdir) && rm(outdir, recursive = true) end # module diff --git a/test/test_parabolic_2d.jl b/test/test_parabolic_2d.jl index 1564a33dc41..6632cd0bb27 100644 --- a/test/test_parabolic_2d.jl +++ b/test/test_parabolic_2d.jl @@ -5,19 +5,19 @@ using Trixi include("test_trixi.jl") - # Start with a clean environment: remove Trixi.jl output directory if it exists outdir = "out" -isdir(outdir) && rm(outdir, recursive=true) +isdir(outdir) && rm(outdir, recursive = true) @testset "SemidiscretizationHyperbolicParabolic (2D)" begin +#! format: noindent - @trixi_testset "DGMulti 2D rhs_parabolic!" begin - +@trixi_testset "DGMulti 2D rhs_parabolic!" begin dg = DGMulti(polydeg = 2, element_type = Quad(), approximation_type = Polynomial(), surface_integral = SurfaceIntegralWeakForm(flux_central), volume_integral = VolumeIntegralWeakForm()) - mesh = DGMultiMesh(dg, cells_per_dimension=(2, 2)) + cells_per_dimension = (2, 2) + mesh = DGMultiMesh(dg, cells_per_dimension) # test with polynomial initial condition x^2 * y # test if we recover the exact second derivative @@ -26,7 +26,8 @@ isdir(outdir) && rm(outdir, recursive=true) equations = LinearScalarAdvectionEquation2D(1.0, 1.0) equations_parabolic = LaplaceDiffusion2D(1.0, equations) - semi = SemidiscretizationHyperbolicParabolic(mesh, equations, equations_parabolic, initial_condition, dg) + semi = SemidiscretizationHyperbolicParabolic(mesh, equations, equations_parabolic, + initial_condition, dg) @test_nowarn_mod show(stdout, semi) @test_nowarn_mod show(stdout, MIME"text/plain"(), semi) @test_nowarn_mod show(stdout, boundary_condition_do_nothing) @@ -46,7 +47,7 @@ isdir(outdir) && rm(outdir, recursive=true) @unpack cache, cache_parabolic, equations_parabolic = semi @unpack gradients = cache_parabolic for dim in eachindex(gradients) - fill!(gradients[dim], zero(eltype(gradients[dim]))) + fill!(gradients[dim], zero(eltype(gradients[dim]))) end t = 0.0 @@ -55,7 +56,7 @@ isdir(outdir) && rm(outdir, recursive=true) boundary_condition_periodic, dg, cache, cache_parabolic) @unpack x, y, xq, yq = mesh.md @test getindex.(gradients[1], 1) ≈ 2 * xq .* yq - @test getindex.(gradients[2], 1) ≈ xq.^2 + @test getindex.(gradients[2], 1) ≈ xq .^ 2 u_flux = similar.(gradients) Trixi.calc_viscous_fluxes!(u_flux, ode.u0, gradients, mesh, equations_parabolic, @@ -64,242 +65,633 @@ isdir(outdir) && rm(outdir, recursive=true) @test u_flux[2] ≈ gradients[2] du = similar(ode.u0) - Trixi.calc_divergence!(du, ode.u0, t, u_flux, mesh, equations_parabolic, boundary_condition_periodic, + Trixi.calc_divergence!(du, ode.u0, t, u_flux, mesh, equations_parabolic, + boundary_condition_periodic, dg, semi.solver_parabolic, cache, cache_parabolic) @test getindex.(du, 1) ≈ 2 * y - end - - @trixi_testset "DGMulti: elixir_advection_diffusion.jl" begin - @test_trixi_include(joinpath(examples_dir(), "dgmulti_2d", "elixir_advection_diffusion.jl"), - cells_per_dimension = (4, 4), tspan=(0.0, 0.1), - l2 = [0.2485803335154642], - linf = [1.079606969242132] - ) - end - - @trixi_testset "DGMulti: elixir_advection_diffusion_periodic.jl" begin - @test_trixi_include(joinpath(examples_dir(), "dgmulti_2d", "elixir_advection_diffusion_periodic.jl"), - cells_per_dimension = (4, 4), tspan=(0.0, 0.1), - l2 = [0.03180371984888462], - linf = [0.2136821621370909] - ) - end - - @trixi_testset "DGMulti: elixir_advection_diffusion_nonperiodic.jl" begin - @test_trixi_include(joinpath(examples_dir(), "dgmulti_2d", "elixir_advection_diffusion_nonperiodic.jl"), - cells_per_dimension = (4, 4), tspan=(0.0, 0.1), - l2 = [0.002123168335604323], - linf = [0.00963640423513712] - ) - end - - @trixi_testset "DGMulti: elixir_navierstokes_convergence.jl" begin - @test_trixi_include(joinpath(examples_dir(), "dgmulti_2d", "elixir_navierstokes_convergence.jl"), - cells_per_dimension = (4, 4), tspan=(0.0, 0.1), - l2 = [0.0015355076812510957, 0.0033843168272696756, 0.0036531858107443434, 0.009948436427519214], - linf = [0.005522560467190019, 0.013425258500730508, 0.013962115643482154, 0.027483102120502423] - ) - end - - @trixi_testset "DGMulti: elixir_navierstokes_convergence_curved.jl" begin - @test_trixi_include(joinpath(examples_dir(), "dgmulti_2d", "elixir_navierstokes_convergence_curved.jl"), - cells_per_dimension = (4, 4), tspan=(0.0, 0.1), - l2 = [0.004255101916146187, 0.011118488923215765, 0.011281831283462686, 0.03573656447388509], - linf = [0.015071710669706473, 0.04103132025858458, 0.03990424085750277, 0.1309401718598764], - ) - end - - @trixi_testset "DGMulti: elixir_navierstokes_lid_driven_cavity.jl" begin - @test_trixi_include(joinpath(examples_dir(), "dgmulti_2d", "elixir_navierstokes_lid_driven_cavity.jl"), - cells_per_dimension = (4, 4), tspan=(0.0, 0.5), - l2 = [0.00022156125227115747, 0.028318325921401, 0.009509168701070296, 0.028267900513550506], - linf = [0.001562278941298234, 0.14886653390744856, 0.0716323565533752, 0.19472785105241996] - ) - end - - @trixi_testset "TreeMesh2D: elixir_advection_diffusion.jl" begin - @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", "elixir_advection_diffusion.jl"), - initial_refinement_level = 2, tspan=(0.0, 0.4), polydeg=5, - l2 = [4.0915532997994255e-6], - linf = [2.3040850347877395e-5] - ) - end - - @trixi_testset "TreeMesh2D: elixir_advection_diffusion.jl (Refined mesh)" begin - @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", "elixir_advection_diffusion.jl"), - tspan=(0.0, 0.0)) - LLID = Trixi.local_leaf_cells(mesh.tree) - num_leafs = length(LLID) - @assert num_leafs % 8 == 0 - Trixi.refine!(mesh.tree, LLID[1:Int(num_leafs/8)]) - tspan=(0.0, 1.5) - semi = SemidiscretizationHyperbolicParabolic(mesh, - (equations, equations_parabolic), - initial_condition, solver; - boundary_conditions=(boundary_conditions, +end + +@trixi_testset "DGMulti: elixir_advection_diffusion.jl" begin + @test_trixi_include(joinpath(examples_dir(), "dgmulti_2d", + "elixir_advection_diffusion.jl"), + cells_per_dimension=(4, 4), tspan=(0.0, 0.1), + l2=[0.2485803335154642], + linf=[1.079606969242132]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "DGMulti: elixir_advection_diffusion_periodic.jl" begin + @test_trixi_include(joinpath(examples_dir(), "dgmulti_2d", + "elixir_advection_diffusion_periodic.jl"), + cells_per_dimension=(4, 4), tspan=(0.0, 0.1), + l2=[0.03180371984888462], + linf=[0.2136821621370909]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "DGMulti: elixir_advection_diffusion_nonperiodic.jl" begin + @test_trixi_include(joinpath(examples_dir(), "dgmulti_2d", + "elixir_advection_diffusion_nonperiodic.jl"), + cells_per_dimension=(4, 4), tspan=(0.0, 0.1), + l2=[0.002123168335604323], + linf=[0.00963640423513712]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "DGMulti: elixir_navierstokes_convergence.jl" begin + @test_trixi_include(joinpath(examples_dir(), "dgmulti_2d", + "elixir_navierstokes_convergence.jl"), + cells_per_dimension=(4, 4), tspan=(0.0, 0.1), + l2=[ + 0.0015355076812510957, + 0.0033843168272696756, + 0.0036531858107443434, + 0.009948436427519214, + ], + linf=[ + 0.005522560467190019, + 0.013425258500730508, + 0.013962115643482154, + 0.027483102120502423, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "DGMulti: elixir_navierstokes_convergence_curved.jl" begin + @test_trixi_include(joinpath(examples_dir(), "dgmulti_2d", + "elixir_navierstokes_convergence_curved.jl"), + cells_per_dimension=(4, 4), tspan=(0.0, 0.1), + l2=[ + 0.004255101916146187, + 0.011118488923215765, + 0.011281831283462686, + 0.03573656447388509, + ], + linf=[ + 0.015071710669706473, + 0.04103132025858458, + 0.03990424085750277, + 0.1309401718598764, + ],) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "DGMulti: elixir_navierstokes_lid_driven_cavity.jl" begin + @test_trixi_include(joinpath(examples_dir(), "dgmulti_2d", + "elixir_navierstokes_lid_driven_cavity.jl"), + cells_per_dimension=(4, 4), tspan=(0.0, 0.5), + l2=[ + 0.00022156125227115747, + 0.028318325921401, + 0.009509168701070296, + 0.028267900513550506, + ], + linf=[ + 0.001562278941298234, + 0.14886653390744856, + 0.0716323565533752, + 0.19472785105241996, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "TreeMesh2D: elixir_advection_diffusion.jl" begin + @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", + "elixir_advection_diffusion.jl"), + initial_refinement_level=2, tspan=(0.0, 0.4), polydeg=5, + l2=[4.0915532997994255e-6], + linf=[2.3040850347877395e-5]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "TreeMesh2D: elixir_advection_diffusion.jl (Refined mesh)" begin + @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", + "elixir_advection_diffusion.jl"), + tspan=(0.0, 0.0)) + LLID = Trixi.local_leaf_cells(mesh.tree) + num_leafs = length(LLID) + @assert num_leafs % 8 == 0 + Trixi.refine!(mesh.tree, LLID[1:Int(num_leafs / 8)]) + tspan = (0.0, 1.5) + semi = SemidiscretizationHyperbolicParabolic(mesh, + (equations, equations_parabolic), + initial_condition, solver; + boundary_conditions = (boundary_conditions, boundary_conditions_parabolic)) - ode = semidiscretize(semi, tspan) - analysis_callback = AnalysisCallback(semi, interval=analysis_interval) - callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) - sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, - ode_default_options()..., callback=callbacks) - ac_sol = analysis_callback(sol) - @test ac_sol.l2[1] ≈ 1.67452550744728e-6 - @test ac_sol.linf[1] ≈ 7.905059166368744e-6 - - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) + ode = semidiscretize(semi, tspan) + analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) + sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + ode_default_options()..., callback = callbacks) + l2_error, linf_error = analysis_callback(sol) + @test l2_error ≈ [1.67452550744728e-6] + @test linf_error ≈ [7.905059166368744e-6] + + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 100 @test (@allocated Trixi.rhs_parabolic!(du_ode, u_ode, semi, t)) < 100 - end - end - - @trixi_testset "TreeMesh2D: elixir_advection_diffusion_nonperiodic.jl" begin - @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", "elixir_advection_diffusion_nonperiodic.jl"), - initial_refinement_level = 2, tspan=(0.0, 0.1), - l2 = [0.007646800618485118], - linf = [0.10067621050468958] - ) - end - - @trixi_testset "TreeMesh2D: elixir_navierstokes_convergence.jl" begin - @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", "elixir_navierstokes_convergence.jl"), - initial_refinement_level = 2, tspan=(0.0, 0.1), - analysis_callback = AnalysisCallback(semi, interval=analysis_interval, - extra_analysis_integrals=(energy_kinetic, - energy_internal, - enstrophy)), - l2 = [0.002111672530658797, 0.0034322351490857846, 0.0038742528195910416, 0.012469246082568561], - linf = [0.012006418939223495, 0.035520871209746126, 0.024512747492231427, 0.11191122588756564] - ) - end - - @trixi_testset "TreeMesh2D: elixir_navierstokes_convergence.jl (isothermal walls)" begin - @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", "elixir_navierstokes_convergence.jl"), - initial_refinement_level = 2, tspan=(0.0, 0.1), - heat_bc_top_bottom=Isothermal((x, t, equations) -> Trixi.temperature(initial_condition_navier_stokes_convergence_test(x, t, equations), equations)), - l2 = [0.002103629650383915, 0.003435843933396454, 0.00386735987813341, 0.012670355349235728], - linf = [0.012006261793147788, 0.03550212518982032, 0.025107947319661185, 0.11647078036571124] - ) - end - - @trixi_testset "TreeMesh2D: elixir_navierstokes_convergence.jl (Entropy gradient variables)" begin - @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", "elixir_navierstokes_convergence.jl"), - initial_refinement_level=2, tspan=(0.0, 0.1), gradient_variables=GradientVariablesEntropy(), - l2 = [0.0021403742517389513, 0.0034258287094908572, 0.0038915122886898517, 0.012506862343013842], - linf = [0.012244412004628336, 0.03507559186162224, 0.024580892345558894, 0.11425600758350107] - ) - end - - @trixi_testset "TreeMesh2D: elixir_navierstokes_convergence.jl (Entropy gradient variables, isothermal walls)" begin - @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", "elixir_navierstokes_convergence.jl"), - initial_refinement_level=2, tspan=(0.0, 0.1), gradient_variables=GradientVariablesEntropy(), - heat_bc_top_bottom=Isothermal((x, t, equations) -> Trixi.temperature(initial_condition_navier_stokes_convergence_test(x, t, equations), equations)), - l2 = [0.0021349737347844907, 0.0034301388278203033, 0.0038928324474291572, 0.012693611436230873], - linf = [0.01224423627586213, 0.035054066314102905, 0.025099598504931965, 0.11795616324751634] - ) - end - - @trixi_testset "TreeMesh2D: elixir_navierstokes_convergence.jl (flux differencing)" begin - @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", "elixir_navierstokes_convergence.jl"), - initial_refinement_level = 2, tspan=(0.0, 0.1), - volume_integral=VolumeIntegralFluxDifferencing(flux_central), - l2 = [0.0021116725306633594, 0.0034322351490827557, 0.0038742528196093542, 0.012469246082526909], - linf = [0.012006418939291663, 0.035520871209594115, 0.024512747491801577, 0.11191122588591007] - ) - end - - @trixi_testset "TreeMesh2D: elixir_navierstokes_convergence.jl (Refined mesh)" begin - @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", "elixir_navierstokes_convergence.jl"), - tspan=(0.0, 0.0), initial_refinement_level=3) - LLID = Trixi.local_leaf_cells(mesh.tree) - num_leafs = length(LLID) - @assert num_leafs % 4 == 0 - Trixi.refine!(mesh.tree, LLID[1:Int(num_leafs/4)]) - tspan=(0.0, 0.5) - semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver; - boundary_conditions=(boundary_conditions, boundary_conditions_parabolic), - source_terms=source_terms_navier_stokes_convergence_test) - ode = semidiscretize(semi, tspan) - analysis_callback = AnalysisCallback(semi, interval=analysis_interval) - callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) - sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, dt = 1e-5, - ode_default_options()..., callback=callbacks) - ac_sol = analysis_callback(sol) - @test ac_sol.l2 ≈ [0.00024296959173852447; 0.0002093263158670915; 0.0005390572390977262; 0.00026753561392341537] - @test ac_sol.linf ≈ [0.0016210102053424436; 0.002593287648655501; 0.002953907343823712; 0.002077119120180271] - end - - @trixi_testset "TreeMesh2D: elixir_navierstokes_lid_driven_cavity.jl" begin - @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", "elixir_navierstokes_lid_driven_cavity.jl"), - initial_refinement_level = 2, tspan=(0.0, 0.5), - l2 = [0.00015144571529699053, 0.018766076072331623, 0.007065070765652574, 0.0208399005734258], - linf = [0.0014523369373669048, 0.12366779944955864, 0.05532450997115432, 0.16099927805328207] - ) - end - - @trixi_testset "TreeMesh2D: elixir_navierstokes_taylor_green_vortex.jl" begin - @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", "elixir_navierstokes_taylor_green_vortex.jl"), - l2 = [0.0009279657228109691, 0.012454661988687185, 0.012454661988689886, 0.030487112728612178], - linf = [0.002435582543096171, 0.024824039368199546, 0.024824039368212758, 0.06731583711777489] - ) - end - - @trixi_testset "P4estMesh2D: elixir_advection_diffusion_periodic.jl" begin - @test_trixi_include(joinpath(examples_dir(), "p4est_2d_dgsem", "elixir_advection_diffusion_periodic.jl"), - trees_per_dimension = (1, 1), initial_refinement_level = 2, tspan=(0.0, 0.5), - l2 = [0.0023754695605828443], - linf = [0.008154128363741964] - ) - end - - @trixi_testset "P4estMesh2D: elixir_advection_diffusion_periodic_curved.jl" begin - @test_trixi_include(joinpath(examples_dir(), "p4est_2d_dgsem", "elixir_advection_diffusion_periodic_curved.jl"), - trees_per_dimension = (1, 1), initial_refinement_level = 2, tspan=(0.0, 0.5), - l2 = [0.012380458938507371], - linf = [0.10860506906472567] - ) - end - - @trixi_testset "P4estMesh2D: elixir_advection_diffusion_periodic_curved.jl" begin - @test_trixi_include(joinpath(examples_dir(), "p4est_2d_dgsem", "elixir_advection_diffusion_periodic_curved.jl"), - trees_per_dimension = (1, 1), initial_refinement_level = 2, tspan=(0.0, 0.5), - l2 = [0.012380458938507371], - linf = [0.10860506906472567] - ) - end - - @trixi_testset "P4estMesh2D: elixir_advection_diffusion_nonperiodic_curved.jl" begin - @test_trixi_include(joinpath(examples_dir(), "p4est_2d_dgsem", "elixir_advection_diffusion_nonperiodic_curved.jl"), - trees_per_dimension = (1, 1), initial_refinement_level = 2, tspan=(0.0, 0.5), - l2 = [0.04933902988507035], - linf = [0.2550261714590271] - ) - end - - @trixi_testset "P4estMesh2D: elixir_navierstokes_convergence.jl" begin - @test_trixi_include(joinpath(examples_dir(), "p4est_2d_dgsem", "elixir_navierstokes_convergence.jl"), - initial_refinement_level = 1, tspan=(0.0, 0.2), - l2 = [0.0003811978985836709, 0.0005874314969169538, 0.0009142898787923481, 0.0011613918899727263], - linf = [0.0021633623982135752, 0.009484348274135372, 0.004231572066492217, 0.011661660275365193] - ) - end - - @trixi_testset "P4estMesh2D: elixir_navierstokes_lid_driven_cavity.jl" begin - @test_trixi_include(joinpath(examples_dir(), "p4est_2d_dgsem", "elixir_navierstokes_lid_driven_cavity.jl"), - initial_refinement_level = 2, tspan=(0.0, 0.5), - l2 = [0.00028716166408816073, 0.08101204560401647, 0.02099595625377768, 0.05008149754143295], - linf = [0.014804500261322406, 0.9513271652357098, 0.7223919625994717, 1.4846907331004786] - ) - end + end +end + +@trixi_testset "TreeMesh2D: elixir_advection_diffusion_nonperiodic.jl" begin + @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", + "elixir_advection_diffusion_nonperiodic.jl"), + initial_refinement_level=2, tspan=(0.0, 0.1), + l2=[0.007646800618485118], + linf=[0.10067621050468958]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "TreeMesh2D: elixir_navierstokes_convergence.jl" begin + @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", + "elixir_navierstokes_convergence.jl"), + initial_refinement_level=2, tspan=(0.0, 0.1), + analysis_callback=AnalysisCallback(semi, + interval = analysis_interval, + extra_analysis_integrals = (energy_kinetic, + energy_internal, + enstrophy)), + l2=[ + 0.002111672530658797, + 0.0034322351490857846, + 0.0038742528195910416, + 0.012469246082568561, + ], + linf=[ + 0.012006418939223495, + 0.035520871209746126, + 0.024512747492231427, + 0.11191122588756564, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "TreeMesh2D: elixir_navierstokes_convergence.jl (isothermal walls)" begin + @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", + "elixir_navierstokes_convergence.jl"), + initial_refinement_level=2, tspan=(0.0, 0.1), + heat_bc_top_bottom=Isothermal((x, t, equations) -> Trixi.temperature(initial_condition_navier_stokes_convergence_test(x, + t, + equations), + equations)), + l2=[ + 0.002103629650383915, + 0.003435843933396454, + 0.00386735987813341, + 0.012670355349235728, + ], + linf=[ + 0.012006261793147788, + 0.03550212518982032, + 0.025107947319661185, + 0.11647078036571124, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "TreeMesh2D: elixir_navierstokes_convergence.jl (Entropy gradient variables)" begin + @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", + "elixir_navierstokes_convergence.jl"), + initial_refinement_level=2, tspan=(0.0, 0.1), + gradient_variables=GradientVariablesEntropy(), + l2=[ + 0.0021403742517389513, + 0.0034258287094908572, + 0.0038915122886898517, + 0.012506862343013842, + ], + linf=[ + 0.012244412004628336, + 0.03507559186162224, + 0.024580892345558894, + 0.11425600758350107, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "TreeMesh2D: elixir_navierstokes_convergence.jl (Entropy gradient variables, isothermal walls)" begin + @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", + "elixir_navierstokes_convergence.jl"), + initial_refinement_level=2, tspan=(0.0, 0.1), + gradient_variables=GradientVariablesEntropy(), + heat_bc_top_bottom=Isothermal((x, t, equations) -> Trixi.temperature(initial_condition_navier_stokes_convergence_test(x, + t, + equations), + equations)), + l2=[ + 0.0021349737347844907, + 0.0034301388278203033, + 0.0038928324474291572, + 0.012693611436230873, + ], + linf=[ + 0.01224423627586213, + 0.035054066314102905, + 0.025099598504931965, + 0.11795616324751634, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "TreeMesh2D: elixir_navierstokes_convergence.jl (flux differencing)" begin + @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", + "elixir_navierstokes_convergence.jl"), + initial_refinement_level=2, tspan=(0.0, 0.1), + volume_integral=VolumeIntegralFluxDifferencing(flux_central), + l2=[ + 0.0021116725306633594, + 0.0034322351490827557, + 0.0038742528196093542, + 0.012469246082526909, + ], + linf=[ + 0.012006418939291663, + 0.035520871209594115, + 0.024512747491801577, + 0.11191122588591007, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "TreeMesh2D: elixir_navierstokes_convergence.jl (Refined mesh)" begin + @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", + "elixir_navierstokes_convergence.jl"), + tspan=(0.0, 0.0), initial_refinement_level=3) + LLID = Trixi.local_leaf_cells(mesh.tree) + num_leafs = length(LLID) + @assert num_leafs % 4 == 0 + Trixi.refine!(mesh.tree, LLID[1:Int(num_leafs / 4)]) + tspan = (0.0, 0.5) + semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, solver; + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic), + source_terms = source_terms_navier_stokes_convergence_test) + ode = semidiscretize(semi, tspan) + analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) + sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + dt = 1e-5, + ode_default_options()..., callback = callbacks) + l2_error, linf_error = analysis_callback(sol) + @test l2_error ≈ + [0.00024296959173852447; 0.0002093263158670915; 0.0005390572390977262; + 0.00026753561392341537] + @test linf_error ≈ + [0.0016210102053424436; 0.002593287648655501; 0.002953907343823712; + 0.002077119120180271] + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "TreeMesh2D: elixir_navierstokes_lid_driven_cavity.jl" begin + @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", + "elixir_navierstokes_lid_driven_cavity.jl"), + initial_refinement_level=2, tspan=(0.0, 0.5), + l2=[ + 0.00015144571529699053, + 0.018766076072331623, + 0.007065070765652574, + 0.0208399005734258, + ], + linf=[ + 0.0014523369373669048, + 0.12366779944955864, + 0.05532450997115432, + 0.16099927805328207, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "TreeMesh2D: elixir_navierstokes_shearlayer_amr.jl" begin + @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", + "elixir_navierstokes_shearlayer_amr.jl"), + l2=[ + 0.00526017743452336, + 0.4130430692895672, + 0.4310996183791349, + 1.1544344171604635, + ], + linf=[ + 0.03492185879198495, + 1.392635891671335, + 1.357551616406459, + 8.713760873018146, + ], + tspan=(0.0, 0.7)) +end + +@trixi_testset "P4estMesh2D: elixir_advection_diffusion_periodic.jl" begin + @test_trixi_include(joinpath(examples_dir(), "p4est_2d_dgsem", + "elixir_advection_diffusion_periodic.jl"), + trees_per_dimension=(1, 1), initial_refinement_level=2, + tspan=(0.0, 0.5), + l2=[0.0023754695605828443], + linf=[0.008154128363741964]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "P4estMesh2D: elixir_advection_diffusion_periodic.jl" begin + @test_trixi_include(joinpath(examples_dir(), "p4est_2d_dgsem", + "elixir_advection_diffusion_periodic.jl"), + trees_per_dimension=(1, 1), initial_refinement_level=2, + tspan=(0.0, 0.5), + l2=[0.0023754695605828443], + linf=[0.008154128363741964]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "P4estMesh2D: elixir_advection_diffusion_periodic_curved.jl" begin + @test_trixi_include(joinpath(examples_dir(), "p4est_2d_dgsem", + "elixir_advection_diffusion_periodic_curved.jl"), + trees_per_dimension=(1, 1), initial_refinement_level=2, + tspan=(0.0, 0.5), + l2=[0.006708147442490916], + linf=[0.04807038397976693]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end +@trixi_testset "P4estMesh2D: elixir_advection_diffusion_periodic_amr.jl" begin + @test_trixi_include(joinpath(examples_dir(), "p4est_2d_dgsem", + "elixir_advection_diffusion_periodic_amr.jl"), + tspan=(0.0, 0.01), + l2=[0.014715887539773128], + linf=[0.2285802791900049]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "P4estMesh2D: elixir_advection_diffusion_nonperiodic_amr.jl" begin + @test_trixi_include(joinpath(examples_dir(), "p4est_2d_dgsem", + "elixir_advection_diffusion_nonperiodic_amr.jl"), + tspan=(0.0, 0.01), + l2=[0.00793438523666649], + linf=[0.11030633127144573]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "P4estMesh2D: elixir_advection_diffusion_nonperiodic_curved.jl" begin + @test_trixi_include(joinpath(examples_dir(), "p4est_2d_dgsem", + "elixir_advection_diffusion_nonperiodic_curved.jl"), + trees_per_dimension=(1, 1), initial_refinement_level=2, + tspan=(0.0, 0.5), + l2=[0.00919917034843865], + linf=[0.14186297438393505]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "P4estMesh2D: elixir_navierstokes_convergence.jl" begin + @test_trixi_include(joinpath(examples_dir(), "p4est_2d_dgsem", + "elixir_navierstokes_convergence.jl"), + initial_refinement_level=1, tspan=(0.0, 0.2), + l2=[ + 0.0003811978985836709, + 0.0005874314969169538, + 0.0009142898787923481, + 0.0011613918899727263, + ], + linf=[ + 0.0021633623982135752, + 0.009484348274135372, + 0.004231572066492217, + 0.011661660275365193, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "P4estMesh2D: elixir_navierstokes_convergence_nonperiodic.jl" begin + @test_trixi_include(joinpath(examples_dir(), "p4est_2d_dgsem", + "elixir_navierstokes_convergence_nonperiodic.jl"), + initial_refinement_level=1, tspan=(0.0, 0.2), + l2=[ + 0.00040364962558511795, + 0.0005869762481506936, + 0.00091488537427274, + 0.0011984191566376762, + ], + linf=[ + 0.0024993634941723464, + 0.009487866203944725, + 0.004505829506628117, + 0.011634902776245681, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "P4estMesh2D: elixir_navierstokes_lid_driven_cavity.jl" begin + @test_trixi_include(joinpath(examples_dir(), "p4est_2d_dgsem", + "elixir_navierstokes_lid_driven_cavity.jl"), + initial_refinement_level=2, tspan=(0.0, 0.5), + l2=[ + 0.00028716166408816073, + 0.08101204560401647, + 0.02099595625377768, + 0.05008149754143295, + ], + linf=[ + 0.014804500261322406, + 0.9513271652357098, + 0.7223919625994717, + 1.4846907331004786, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "P4estMesh2D: elixir_navierstokes_lid_driven_cavity_amr.jl" begin + @test_trixi_include(joinpath(examples_dir(), "p4est_2d_dgsem", + "elixir_navierstokes_lid_driven_cavity_amr.jl"), + tspan=(0.0, 1.0), + l2=[ + 0.0005323841980601085, 0.07892044543547208, + 0.02909671646389337, 0.11717468256112017, + ], + linf=[ + 0.006045292737899444, 0.9233292581786228, + 0.7982129977236198, 1.6864546235292153, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end end # Clean up afterwards: delete Trixi.jl output directory -@test_nowarn isdir(outdir) && rm(outdir, recursive=true) +@test_nowarn isdir(outdir) && rm(outdir, recursive = true) end # module diff --git a/test/test_parabolic_3d.jl b/test/test_parabolic_3d.jl index d607962afa0..d6c720cf0d9 100644 --- a/test/test_parabolic_3d.jl +++ b/test/test_parabolic_3d.jl @@ -7,159 +7,439 @@ include("test_trixi.jl") # Start with a clean environment: remove Trixi.jl output directory if it exists outdir = "out" -isdir(outdir) && rm(outdir, recursive=true) +isdir(outdir) && rm(outdir, recursive = true) @testset "SemidiscretizationHyperbolicParabolic (3D)" begin +#! format: noindent - @trixi_testset "DGMulti: elixir_navierstokes_convergence.jl" begin - @test_trixi_include(joinpath(examples_dir(), "dgmulti_3d", "elixir_navierstokes_convergence.jl"), - cells_per_dimension = (4, 4, 4), tspan=(0.0, 0.1), - l2 = [0.0005532847115849239, 0.000659263490965341, 0.0007776436127362806, 0.0006592634909662951, 0.0038073628897809185], - linf = [0.0017039861523615585, 0.002628561703560073, 0.003531057425112172, 0.0026285617036090336, 0.015587829540351095] - ) - end - - @trixi_testset "DGMulti: elixir_navierstokes_convergence_curved.jl" begin - @test_trixi_include(joinpath(examples_dir(), "dgmulti_3d", "elixir_navierstokes_convergence_curved.jl"), - cells_per_dimension = (4, 4, 4), tspan=(0.0, 0.1), - l2 = [0.0014027227251207474, 0.0021322235533273513, 0.0027873741447455194, 0.0024587473070627423, 0.00997836818019202], - linf = [0.006341750402837576, 0.010306014252246865, 0.01520740250924979, 0.010968264045485565, 0.047454389831591115] - ) - end - - @trixi_testset "DGMulti: elixir_navierstokes_taylor_green_vortex.jl" begin - @test_trixi_include(joinpath(examples_dir(), "dgmulti_3d", "elixir_navierstokes_taylor_green_vortex.jl"), - cells_per_dimension = (4, 4, 4), tspan=(0.0, 0.25), - l2 = [0.0001825713444029892, 0.015589736382772248, 0.015589736382771884, 0.021943924667273653, 0.01927370280244222], - linf = [0.0006268463584697681, 0.03218881662749007, 0.03218881662697948, 0.053872495395614256, 0.05183822000984151] - ) - end - - @trixi_testset "TreeMesh3D: elixir_navierstokes_convergence.jl" begin - @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", "elixir_navierstokes_convergence.jl"), - initial_refinement_level = 2, tspan=(0.0, 0.1), - l2 = [0.0019582188528512257, 0.002653449504302844, 0.002898264205184629, 0.002653449504302853, 0.009511572365085706], - linf = [0.013680656759085918, 0.0356910450154318, 0.023526343547736236, 0.035691045015431855, 0.11482570604041165] - ) - end - - @trixi_testset "TreeMesh3D: elixir_navierstokes_convergence.jl (isothermal walls)" begin - @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", "elixir_navierstokes_convergence.jl"), - initial_refinement_level = 2, tspan=(0.0, 0.1), - heat_bc_top_bottom=Isothermal((x, t, equations) -> Trixi.temperature(initial_condition_navier_stokes_convergence_test(x, t, equations), equations)), - l2 = [0.00195468651965362, 0.0026554367897028506, 0.002892730402724066, 0.002655436789702817, 0.009596351796609566], - linf = [0.013680508110645473, 0.035673446359424356, 0.024024936779729028, 0.03567344635942474, 0.11839497110809383] - ) - end - - @trixi_testset "TreeMesh3D: elixir_navierstokes_convergence.jl (Entropy gradient variables)" begin - @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", "elixir_navierstokes_convergence.jl"), - initial_refinement_level=2, tspan=(0.0, 0.1), gradient_variables=GradientVariablesEntropy(), - l2 = [0.0019770444875099307, 0.0026524750946399327, 0.00290860030832445, 0.0026524750946399396, 0.009509568981439294], - linf = [0.01387936112914212, 0.03526260609304053, 0.023554197097368997, 0.035262606093040896, 0.11719963716509518] - ) - end - - @trixi_testset "TreeMesh3D: elixir_navierstokes_convergence.jl (Entropy gradient variables, isothermal walls)" begin - @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", "elixir_navierstokes_convergence.jl"), - initial_refinement_level=2, tspan=(0.0, 0.1), gradient_variables=GradientVariablesEntropy(), - heat_bc_top_bottom=Isothermal((x, t, equations) -> Trixi.temperature(initial_condition_navier_stokes_convergence_test(x, t, equations), equations)), - l2 = [0.001974631423398113, 0.002654768259143932, 0.002907031063651286, 0.002654768259143901, 0.009587792882971452], - linf = [0.01387919380137137, 0.035244084526358944, 0.02398614622061363, 0.03524408452635828, 0.12005056512506407] - ) - end - - @trixi_testset "TreeMesh3D: elixir_navierstokes_convergence.jl (flux differencing)" begin - @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", "elixir_navierstokes_convergence.jl"), - initial_refinement_level = 2, tspan=(0.0, 0.1), - volume_integral=VolumeIntegralFluxDifferencing(flux_central), - l2 = [0.0019582188528180213, 0.002653449504301736, 0.0028982642051960006, 0.0026534495043017384, 0.009511572364811033], - linf = [0.013680656758949583, 0.035691045015224444, 0.02352634354676752, 0.035691045015223424, 0.11482570603751441] - ) - end - - @trixi_testset "TreeMesh3D: elixir_navierstokes_convergence.jl (Refined mesh)" begin - @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", "elixir_navierstokes_convergence.jl"), - tspan=(0.0, 0.0)) - LLID = Trixi.local_leaf_cells(mesh.tree) - num_leafs = length(LLID) - @assert num_leafs % 16 == 0 - Trixi.refine!(mesh.tree, LLID[1:Int(num_leafs/16)]) - tspan=(0.0, 1.0) - semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), initial_condition, solver; - boundary_conditions=(boundary_conditions, boundary_conditions_parabolic), - source_terms=source_terms_navier_stokes_convergence_test) - ode = semidiscretize(semi, tspan) - analysis_callback = AnalysisCallback(semi, interval=analysis_interval) - callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) - sol = solve(ode, RDPK3SpFSAL49(); abstol=time_int_tol, reltol=time_int_tol, dt = 1e-5, - ode_default_options()..., callback=callbacks) - ac_sol = analysis_callback(sol) - @test ac_sol.l2 ≈ [0.0003991794175622818; 0.0008853745163670504; 0.0010658655552066817; 0.0008785559918324284; 0.001403163458422815] - @test ac_sol.linf ≈ [0.0035306410538458177; 0.01505692306169911; 0.008862444161110705; 0.015065647972869856; 0.030402714743065218] - end - - @trixi_testset "TreeMesh3D: elixir_navierstokes_taylor_green_vortex.jl" begin - @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", "elixir_navierstokes_taylor_green_vortex.jl"), - initial_refinement_level = 2, tspan=(0.0, 0.25), - l2 = [0.00024173250389635442, 0.015684268393762454, 0.01568426839376248, 0.021991909545192333, 0.02825413672911425], - linf = [0.0008410587892853094, 0.04740176181772552, 0.04740176181772507, 0.07483494924031157, 0.150181591534448] - ) - end - - @trixi_testset "TreeMesh3D: elixir_navierstokes_taylor_green_vortex.jl (Refined mesh)" begin - @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", "elixir_navierstokes_taylor_green_vortex.jl"), - tspan=(0.0, 0.0)) - LLID = Trixi.local_leaf_cells(mesh.tree) - num_leafs = length(LLID) - @assert num_leafs % 32 == 0 - Trixi.refine!(mesh.tree, LLID[1:Int(num_leafs/32)]) - tspan=(0.0, 10.0) - semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), - initial_condition, solver) - ode = semidiscretize(semi, tspan) - analysis_callback = AnalysisCallback(semi, interval=analysis_interval, save_analysis=true, - extra_analysis_integrals=(energy_kinetic, +@trixi_testset "DGMulti: elixir_navierstokes_convergence.jl" begin + @test_trixi_include(joinpath(examples_dir(), "dgmulti_3d", + "elixir_navierstokes_convergence.jl"), + cells_per_dimension=(4, 4, 4), tspan=(0.0, 0.1), + l2=[ + 0.0005532847115849239, + 0.000659263490965341, + 0.0007776436127362806, + 0.0006592634909662951, + 0.0038073628897809185, + ], + linf=[ + 0.0017039861523615585, + 0.002628561703560073, + 0.003531057425112172, + 0.0026285617036090336, + 0.015587829540351095, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "DGMulti: elixir_navierstokes_convergence_curved.jl" begin + @test_trixi_include(joinpath(examples_dir(), "dgmulti_3d", + "elixir_navierstokes_convergence_curved.jl"), + cells_per_dimension=(4, 4, 4), tspan=(0.0, 0.1), + l2=[ + 0.0014027227251207474, + 0.0021322235533273513, + 0.0027873741447455194, + 0.0024587473070627423, + 0.00997836818019202, + ], + linf=[ + 0.006341750402837576, + 0.010306014252246865, + 0.01520740250924979, + 0.010968264045485565, + 0.047454389831591115, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "DGMulti: elixir_navierstokes_taylor_green_vortex.jl" begin + @test_trixi_include(joinpath(examples_dir(), "dgmulti_3d", + "elixir_navierstokes_taylor_green_vortex.jl"), + cells_per_dimension=(4, 4, 4), tspan=(0.0, 0.25), + l2=[ + 0.0001825713444029892, + 0.015589736382772248, + 0.015589736382771884, + 0.021943924667273653, + 0.01927370280244222, + ], + linf=[ + 0.0006268463584697681, + 0.03218881662749007, + 0.03218881662697948, + 0.053872495395614256, + 0.05183822000984151, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "TreeMesh3D: elixir_navierstokes_convergence.jl" begin + @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", + "elixir_navierstokes_convergence.jl"), + initial_refinement_level=2, tspan=(0.0, 0.1), + l2=[ + 0.0019582188528512257, + 0.002653449504302844, + 0.002898264205184629, + 0.002653449504302853, + 0.009511572365085706, + ], + linf=[ + 0.013680656759085918, + 0.0356910450154318, + 0.023526343547736236, + 0.035691045015431855, + 0.11482570604041165, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "TreeMesh3D: elixir_navierstokes_convergence.jl (isothermal walls)" begin + @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", + "elixir_navierstokes_convergence.jl"), + initial_refinement_level=2, tspan=(0.0, 0.1), + heat_bc_top_bottom=Isothermal((x, t, equations) -> Trixi.temperature(initial_condition_navier_stokes_convergence_test(x, + t, + equations), + equations)), + l2=[ + 0.00195468651965362, + 0.0026554367897028506, + 0.002892730402724066, + 0.002655436789702817, + 0.009596351796609566, + ], + linf=[ + 0.013680508110645473, + 0.035673446359424356, + 0.024024936779729028, + 0.03567344635942474, + 0.11839497110809383, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "TreeMesh3D: elixir_navierstokes_convergence.jl (Entropy gradient variables)" begin + @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", + "elixir_navierstokes_convergence.jl"), + initial_refinement_level=2, tspan=(0.0, 0.1), + gradient_variables=GradientVariablesEntropy(), + l2=[ + 0.0019770444875099307, + 0.0026524750946399327, + 0.00290860030832445, + 0.0026524750946399396, + 0.009509568981439294, + ], + linf=[ + 0.01387936112914212, + 0.03526260609304053, + 0.023554197097368997, + 0.035262606093040896, + 0.11719963716509518, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "TreeMesh3D: elixir_navierstokes_convergence.jl (Entropy gradient variables, isothermal walls)" begin + @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", + "elixir_navierstokes_convergence.jl"), + initial_refinement_level=2, tspan=(0.0, 0.1), + gradient_variables=GradientVariablesEntropy(), + heat_bc_top_bottom=Isothermal((x, t, equations) -> Trixi.temperature(initial_condition_navier_stokes_convergence_test(x, + t, + equations), + equations)), + l2=[ + 0.001974631423398113, + 0.002654768259143932, + 0.002907031063651286, + 0.002654768259143901, + 0.009587792882971452, + ], + linf=[ + 0.01387919380137137, + 0.035244084526358944, + 0.02398614622061363, + 0.03524408452635828, + 0.12005056512506407, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "TreeMesh3D: elixir_navierstokes_convergence.jl (flux differencing)" begin + @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", + "elixir_navierstokes_convergence.jl"), + initial_refinement_level=2, tspan=(0.0, 0.1), + volume_integral=VolumeIntegralFluxDifferencing(flux_central), + l2=[ + 0.0019582188528180213, + 0.002653449504301736, + 0.0028982642051960006, + 0.0026534495043017384, + 0.009511572364811033, + ], + linf=[ + 0.013680656758949583, + 0.035691045015224444, + 0.02352634354676752, + 0.035691045015223424, + 0.11482570603751441, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "TreeMesh3D: elixir_navierstokes_convergence.jl (Refined mesh)" begin + @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", + "elixir_navierstokes_convergence.jl"), + tspan=(0.0, 0.0)) + LLID = Trixi.local_leaf_cells(mesh.tree) + num_leafs = length(LLID) + @assert num_leafs % 16 == 0 + Trixi.refine!(mesh.tree, LLID[1:Int(num_leafs / 16)]) + tspan = (0.0, 0.25) + semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, solver; + boundary_conditions = (boundary_conditions, + boundary_conditions_parabolic), + source_terms = source_terms_navier_stokes_convergence_test) + ode = semidiscretize(semi, tspan) + analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) + sol = solve(ode, RDPK3SpFSAL49(); abstol = time_int_tol, reltol = time_int_tol, + dt = 1e-5, + ode_default_options()..., callback = callbacks) + l2_error, linf_error = analysis_callback(sol) + @test l2_error ≈ [ + 0.0003109336253407314, + 0.0006473493036803503, + 0.0007705277238213672, + 0.0006280517917198335, + 0.000903927789884075, + ] + @test linf_error ≈ [ + 0.0023694155365339142, + 0.010634932622402863, + 0.006772070862236412, + 0.010640551561726901, + 0.019256819038719897, + ] + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "TreeMesh3D: elixir_navierstokes_taylor_green_vortex.jl" begin + @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", + "elixir_navierstokes_taylor_green_vortex.jl"), + initial_refinement_level=2, tspan=(0.0, 0.25), + l2=[ + 0.00024173250389635442, + 0.015684268393762454, + 0.01568426839376248, + 0.021991909545192333, + 0.02825413672911425, + ], + linf=[ + 0.0008410587892853094, + 0.04740176181772552, + 0.04740176181772507, + 0.07483494924031157, + 0.150181591534448, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "TreeMesh3D: elixir_navierstokes_taylor_green_vortex.jl (Refined mesh)" begin + @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", + "elixir_navierstokes_taylor_green_vortex.jl"), + tspan=(0.0, 0.0)) + LLID = Trixi.local_leaf_cells(mesh.tree) + num_leafs = length(LLID) + @assert num_leafs % 32 == 0 + Trixi.refine!(mesh.tree, LLID[1:Int(num_leafs / 32)]) + tspan = (0.0, 0.1) + semi = SemidiscretizationHyperbolicParabolic(mesh, (equations, equations_parabolic), + initial_condition, solver) + ode = semidiscretize(semi, tspan) + analysis_callback = AnalysisCallback(semi, interval = analysis_interval, + save_analysis = true, + extra_analysis_integrals = (energy_kinetic, energy_internal, enstrophy)) - callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) - # Use CarpenterKennedy2N54 since `RDPK3SpFSAL49` gives slightly different results on different machines - sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), - dt=5e-3, - save_everystep=false, callback=callbacks); - ac_sol = analysis_callback(sol) - @test ac_sol.l2 ≈ [0.0013666103707729502; 0.2313581629543744; 0.2308164306264533; 0.17460246787819503; 0.28121914446544005] - @test ac_sol.linf ≈ [0.006938093883741336; 1.028235074139312; 1.0345438209717241; 1.0821111605203542; 1.2669636522564645] - - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) + callbacks = CallbackSet(summary_callback, alive_callback, analysis_callback) + # Use CarpenterKennedy2N54 since `RDPK3SpFSAL49` gives slightly different results on different machines + sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + dt = 5e-3, + save_everystep = false, callback = callbacks) + l2_error, linf_error = analysis_callback(sol) + @test l2_error ≈ [ + 7.314319856736271e-5, + 0.006266480163542894, + 0.006266489911815533, + 0.008829222305770226, + 0.0032859166842329228, + ] + @test linf_error ≈ [ + 0.0002943968186086554, + 0.013876261980614757, + 0.013883619864959451, + 0.025201279960491936, + 0.018679364985388247, + ] + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 100 @test (@allocated Trixi.rhs_parabolic!(du_ode, u_ode, semi, t)) < 100 - end - end - - @trixi_testset "P4estMesh3D: elixir_navierstokes_convergence.jl" begin - @test_trixi_include(joinpath(examples_dir(), "p4est_3d_dgsem", "elixir_navierstokes_convergence.jl"), - initial_refinement_level = 2, tspan=(0.0, 0.1), - l2 = [0.00026599105554982194, 0.000461877794472316, 0.0005424899076052261, 0.0004618777944723191, 0.0015846392581126832], - linf = [0.0025241668929956163, 0.006308461681816373, 0.004334939663169113, 0.006308461681804009, 0.03176343480493493] - ) - end - - @trixi_testset "P4estMesh3D: elixir_navierstokes_taylor_green_vortex.jl" begin - @test_trixi_include(joinpath(examples_dir(), "p4est_3d_dgsem", "elixir_navierstokes_taylor_green_vortex.jl"), - initial_refinement_level = 2, tspan=(0.0, 0.25), - l2 = [0.0001547509861140407, 0.015637861347119624, 0.015637861347119687, 0.022024699158522523, 0.009711013505930812], - linf = [0.0006696415247340326, 0.03442565722527785, 0.03442565722577423, 0.06295407168705314, 0.032857472756916195] - ) - end + end +end + +@trixi_testset "P4estMesh3D: elixir_navierstokes_convergence.jl" begin + @test_trixi_include(joinpath(examples_dir(), "p4est_3d_dgsem", + "elixir_navierstokes_convergence.jl"), + initial_refinement_level=2, tspan=(0.0, 0.1), + l2=[ + 0.00026599105554982194, + 0.000461877794472316, + 0.0005424899076052261, + 0.0004618777944723191, + 0.0015846392581126832, + ], + linf=[ + 0.0025241668929956163, + 0.006308461681816373, + 0.004334939663169113, + 0.006308461681804009, + 0.03176343480493493, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "P4estMesh3D: elixir_navierstokes_taylor_green_vortex.jl" begin + @test_trixi_include(joinpath(examples_dir(), "p4est_3d_dgsem", + "elixir_navierstokes_taylor_green_vortex.jl"), + initial_refinement_level=2, tspan=(0.0, 0.25), + l2=[ + 0.0001547509861140407, + 0.015637861347119624, + 0.015637861347119687, + 0.022024699158522523, + 0.009711013505930812, + ], + linf=[ + 0.0006696415247340326, + 0.03442565722527785, + 0.03442565722577423, + 0.06295407168705314, + 0.032857472756916195, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "TreeMesh3D: elixir_advection_diffusion_amr.jl" begin + @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", + "elixir_advection_diffusion_amr.jl"), + l2=[0.000355780485397024], + linf=[0.0010810770271614256]) +end + +@trixi_testset "TreeMesh3D: elixir_advection_diffusion_nonperiodic.jl" begin + @test_trixi_include(joinpath(examples_dir(), "tree_3d_dgsem", + "elixir_advection_diffusion_nonperiodic.jl"), + l2=[0.0009808996243280868], + linf=[0.01732621559135459]) +end end # Clean up afterwards: delete Trixi.jl output directory -@test_nowarn isdir(outdir) && rm(outdir, recursive=true) +@test_nowarn isdir(outdir) && rm(outdir, recursive = true) -end # module \ No newline at end of file +end # module diff --git a/test/test_performance_specializations_2d.jl b/test/test_performance_specializations_2d.jl index eaf2a66e84f..4fd39c78f64 100644 --- a/test/test_performance_specializations_2d.jl +++ b/test/test_performance_specializations_2d.jl @@ -7,169 +7,171 @@ include("test_trixi.jl") # Start with a clean environment: remove Trixi.jl output directory if it exists outdir = "out" -isdir(outdir) && rm(outdir, recursive=true) - +isdir(outdir) && rm(outdir, recursive = true) @testset "Performance specializations 2D" begin - @timed_testset "TreeMesh2D, flux_shima_etal_turbo" begin +#! format: noindent + +@timed_testset "TreeMesh2D, flux_shima_etal_turbo" begin trixi_include(@__MODULE__, - joinpath(examples_dir(), "tree_2d_dgsem", "elixir_euler_ec.jl"), - initial_refinement_level=0, tspan=(0.0, 0.0), polydeg=3, - volume_flux=flux_shima_etal_turbo, surface_flux=flux_shima_etal_turbo) + joinpath(examples_dir(), "tree_2d_dgsem", "elixir_euler_ec.jl"), + initial_refinement_level = 0, tspan = (0.0, 0.0), polydeg = 3, + volume_flux = flux_shima_etal_turbo, + surface_flux = flux_shima_etal_turbo) u_ode = copy(sol.u[end]) du_ode = zero(u_ode) # Preserve original memory since it will be `unsafe_wrap`ped and might # thus otherwise be garbage collected GC.@preserve u_ode du_ode begin - u = Trixi.wrap_array(u_ode, semi) - du = Trixi.wrap_array(du_ode, semi) - nonconservative_terms = Trixi.have_nonconservative_terms(semi.equations) - - # Call the optimized default version - du .= 0 - Trixi.flux_differencing_kernel!( - du, u, 1, semi.mesh, - nonconservative_terms, semi.equations, - semi.solver.volume_integral.volume_flux, semi.solver, semi.cache, true) - du_specialized = du[:, :, :, 1] - - # Call the plain version - note the argument type `Function` of - # `semi.solver.volume_integral.volume_flux` - du .= 0 - invoke(Trixi.flux_differencing_kernel!, - Tuple{typeof(du), typeof(u), Integer, typeof(semi.mesh), - typeof(nonconservative_terms), typeof(semi.equations), - Function, typeof(semi.solver), typeof(semi.cache), Bool}, - du, u, 1, semi.mesh, - nonconservative_terms, semi.equations, - semi.solver.volume_integral.volume_flux, semi.solver, semi.cache, true) - du_baseline = du[:, :, :, 1] - - @test du_specialized ≈ du_baseline + u = Trixi.wrap_array(u_ode, semi) + du = Trixi.wrap_array(du_ode, semi) + nonconservative_terms = Trixi.have_nonconservative_terms(semi.equations) + + # Call the optimized default version + du .= 0 + Trixi.flux_differencing_kernel!(du, u, 1, semi.mesh, + nonconservative_terms, semi.equations, + semi.solver.volume_integral.volume_flux, + semi.solver, semi.cache, true) + du_specialized = du[:, :, :, 1] + + # Call the plain version - note the argument type `Function` of + # `semi.solver.volume_integral.volume_flux` + du .= 0 + invoke(Trixi.flux_differencing_kernel!, + Tuple{typeof(du), typeof(u), Integer, typeof(semi.mesh), + typeof(nonconservative_terms), typeof(semi.equations), + Function, typeof(semi.solver), typeof(semi.cache), Bool}, + du, u, 1, semi.mesh, + nonconservative_terms, semi.equations, + semi.solver.volume_integral.volume_flux, semi.solver, semi.cache, true) + du_baseline = du[:, :, :, 1] + + @test du_specialized ≈ du_baseline end - end +end - @timed_testset "TreeMesh2D, flux_ranocha_turbo" begin +@timed_testset "TreeMesh2D, flux_ranocha_turbo" begin trixi_include(@__MODULE__, - joinpath(examples_dir(), "tree_2d_dgsem", "elixir_euler_ec.jl"), - initial_refinement_level=0, tspan=(0.0, 0.0), polydeg=3, - volume_flux=flux_ranocha_turbo, surface_flux=flux_ranocha_turbo) + joinpath(examples_dir(), "tree_2d_dgsem", "elixir_euler_ec.jl"), + initial_refinement_level = 0, tspan = (0.0, 0.0), polydeg = 3, + volume_flux = flux_ranocha_turbo, surface_flux = flux_ranocha_turbo) u_ode = copy(sol.u[end]) du_ode = zero(u_ode) # Preserve original memory since it will be `unsafe_wrap`ped and might # thus otherwise be garbage collected GC.@preserve u_ode du_ode begin - u = Trixi.wrap_array(u_ode, semi) - du = Trixi.wrap_array(du_ode, semi) - nonconservative_terms = Trixi.have_nonconservative_terms(semi.equations) - - # Call the optimized default version - du .= 0 - Trixi.flux_differencing_kernel!( - du, u, 1, semi.mesh, - nonconservative_terms, semi.equations, - semi.solver.volume_integral.volume_flux, semi.solver, semi.cache, true) - du_specialized = du[:, :, :, 1] - - # Call the plain version - note the argument type `Function` of - # `semi.solver.volume_integral.volume_flux` - du .= 0 - invoke(Trixi.flux_differencing_kernel!, - Tuple{typeof(du), typeof(u), Integer, typeof(semi.mesh), - typeof(nonconservative_terms), typeof(semi.equations), - Function, typeof(semi.solver), typeof(semi.cache), Bool}, - du, u, 1, semi.mesh, - nonconservative_terms, semi.equations, - semi.solver.volume_integral.volume_flux, semi.solver, semi.cache, true) - du_baseline = du[:, :, :, 1] - - @test du_specialized ≈ du_baseline + u = Trixi.wrap_array(u_ode, semi) + du = Trixi.wrap_array(du_ode, semi) + nonconservative_terms = Trixi.have_nonconservative_terms(semi.equations) + + # Call the optimized default version + du .= 0 + Trixi.flux_differencing_kernel!(du, u, 1, semi.mesh, + nonconservative_terms, semi.equations, + semi.solver.volume_integral.volume_flux, + semi.solver, semi.cache, true) + du_specialized = du[:, :, :, 1] + + # Call the plain version - note the argument type `Function` of + # `semi.solver.volume_integral.volume_flux` + du .= 0 + invoke(Trixi.flux_differencing_kernel!, + Tuple{typeof(du), typeof(u), Integer, typeof(semi.mesh), + typeof(nonconservative_terms), typeof(semi.equations), + Function, typeof(semi.solver), typeof(semi.cache), Bool}, + du, u, 1, semi.mesh, + nonconservative_terms, semi.equations, + semi.solver.volume_integral.volume_flux, semi.solver, semi.cache, true) + du_baseline = du[:, :, :, 1] + + @test du_specialized ≈ du_baseline end - end +end - @timed_testset "StructuredMesh2D, flux_shima_etal_turbo" begin +@timed_testset "StructuredMesh2D, flux_shima_etal_turbo" begin trixi_include(@__MODULE__, - joinpath(examples_dir(), "structured_2d_dgsem", "elixir_euler_ec.jl"), - cells_per_dimension=(1, 1), tspan=(0.0, 0.0), polydeg=3, - volume_flux=flux_shima_etal_turbo, surface_flux=flux_shima_etal_turbo) + joinpath(examples_dir(), "structured_2d_dgsem", "elixir_euler_ec.jl"), + cells_per_dimension = (1, 1), tspan = (0.0, 0.0), polydeg = 3, + volume_flux = flux_shima_etal_turbo, + surface_flux = flux_shima_etal_turbo) u_ode = copy(sol.u[end]) du_ode = zero(u_ode) # Preserve original memory since it will be `unsafe_wrap`ped and might # thus otherwise be garbage collected GC.@preserve u_ode du_ode begin - u = Trixi.wrap_array(u_ode, semi) - du = Trixi.wrap_array(du_ode, semi) - nonconservative_terms = Trixi.have_nonconservative_terms(semi.equations) - - # Call the optimized default version - du .= 0 - Trixi.flux_differencing_kernel!( - du, u, 1, semi.mesh, - nonconservative_terms, semi.equations, - semi.solver.volume_integral.volume_flux, semi.solver, semi.cache, true) - du_specialized = du[:, :, :, 1] - - # Call the plain version - note the argument type `Function` of - # `semi.solver.volume_integral.volume_flux` - du .= 0 - invoke(Trixi.flux_differencing_kernel!, - Tuple{typeof(du), typeof(u), Integer, typeof(semi.mesh), - typeof(nonconservative_terms), typeof(semi.equations), - Function, typeof(semi.solver), typeof(semi.cache), Bool}, - du, u, 1, semi.mesh, - nonconservative_terms, semi.equations, - semi.solver.volume_integral.volume_flux, semi.solver, semi.cache, true) - du_baseline = du[:, :, :, 1] - - @test du_specialized ≈ du_baseline + u = Trixi.wrap_array(u_ode, semi) + du = Trixi.wrap_array(du_ode, semi) + nonconservative_terms = Trixi.have_nonconservative_terms(semi.equations) + + # Call the optimized default version + du .= 0 + Trixi.flux_differencing_kernel!(du, u, 1, semi.mesh, + nonconservative_terms, semi.equations, + semi.solver.volume_integral.volume_flux, + semi.solver, semi.cache, true) + du_specialized = du[:, :, :, 1] + + # Call the plain version - note the argument type `Function` of + # `semi.solver.volume_integral.volume_flux` + du .= 0 + invoke(Trixi.flux_differencing_kernel!, + Tuple{typeof(du), typeof(u), Integer, typeof(semi.mesh), + typeof(nonconservative_terms), typeof(semi.equations), + Function, typeof(semi.solver), typeof(semi.cache), Bool}, + du, u, 1, semi.mesh, + nonconservative_terms, semi.equations, + semi.solver.volume_integral.volume_flux, semi.solver, semi.cache, true) + du_baseline = du[:, :, :, 1] + + @test du_specialized ≈ du_baseline end - end +end - @timed_testset "StructuredMesh2D, flux_ranocha_turbo" begin +@timed_testset "StructuredMesh2D, flux_ranocha_turbo" begin trixi_include(@__MODULE__, - joinpath(examples_dir(), "structured_2d_dgsem", "elixir_euler_ec.jl"), - cells_per_dimension=(1, 1), tspan=(0.0, 0.0), polydeg=3, - volume_flux=flux_ranocha_turbo, surface_flux=flux_ranocha_turbo) + joinpath(examples_dir(), "structured_2d_dgsem", "elixir_euler_ec.jl"), + cells_per_dimension = (1, 1), tspan = (0.0, 0.0), polydeg = 3, + volume_flux = flux_ranocha_turbo, surface_flux = flux_ranocha_turbo) u_ode = copy(sol.u[end]) du_ode = zero(u_ode) # Preserve original memory since it will be `unsafe_wrap`ped and might # thus otherwise be garbage collected GC.@preserve u_ode du_ode begin - u = Trixi.wrap_array(u_ode, semi) - du = Trixi.wrap_array(du_ode, semi) - nonconservative_terms = Trixi.have_nonconservative_terms(semi.equations) - - # Call the optimized default version - du .= 0 - Trixi.flux_differencing_kernel!( - du, u, 1, semi.mesh, - nonconservative_terms, semi.equations, - semi.solver.volume_integral.volume_flux, semi.solver, semi.cache, true) - du_specialized = du[:, :, :, 1] - - # Call the plain version - note the argument type `Function` of - # `semi.solver.volume_integral.volume_flux` - du .= 0 - invoke(Trixi.flux_differencing_kernel!, - Tuple{typeof(du), typeof(u), Integer, typeof(semi.mesh), - typeof(nonconservative_terms), typeof(semi.equations), - Function, typeof(semi.solver), typeof(semi.cache), Bool}, - du, u, 1, semi.mesh, - nonconservative_terms, semi.equations, - semi.solver.volume_integral.volume_flux, semi.solver, semi.cache, true) - du_baseline = du[:, :, :, 1] - - @test du_specialized ≈ du_baseline + u = Trixi.wrap_array(u_ode, semi) + du = Trixi.wrap_array(du_ode, semi) + nonconservative_terms = Trixi.have_nonconservative_terms(semi.equations) + + # Call the optimized default version + du .= 0 + Trixi.flux_differencing_kernel!(du, u, 1, semi.mesh, + nonconservative_terms, semi.equations, + semi.solver.volume_integral.volume_flux, + semi.solver, semi.cache, true) + du_specialized = du[:, :, :, 1] + + # Call the plain version - note the argument type `Function` of + # `semi.solver.volume_integral.volume_flux` + du .= 0 + invoke(Trixi.flux_differencing_kernel!, + Tuple{typeof(du), typeof(u), Integer, typeof(semi.mesh), + typeof(nonconservative_terms), typeof(semi.equations), + Function, typeof(semi.solver), typeof(semi.cache), Bool}, + du, u, 1, semi.mesh, + nonconservative_terms, semi.equations, + semi.solver.volume_integral.volume_flux, semi.solver, semi.cache, true) + du_baseline = du[:, :, :, 1] + + @test du_specialized ≈ du_baseline end - end end - +end # Clean up afterwards: delete Trixi.jl output directory -@test_nowarn rm(outdir, recursive=true) +@test_nowarn rm(outdir, recursive = true) end #module diff --git a/test/test_performance_specializations_3d.jl b/test/test_performance_specializations_3d.jl index f767930996a..929fc7e3621 100644 --- a/test/test_performance_specializations_3d.jl +++ b/test/test_performance_specializations_3d.jl @@ -7,169 +7,171 @@ include("test_trixi.jl") # Start with a clean environment: remove Trixi.jl output directory if it exists outdir = "out" -isdir(outdir) && rm(outdir, recursive=true) - +isdir(outdir) && rm(outdir, recursive = true) @testset "Performance specializations 3D" begin - @timed_testset "TreeMesh3D, flux_shima_etal_turbo" begin +#! format: noindent + +@timed_testset "TreeMesh3D, flux_shima_etal_turbo" begin trixi_include(@__MODULE__, - joinpath(examples_dir(), "tree_3d_dgsem", "elixir_euler_ec.jl"), - initial_refinement_level=0, tspan=(0.0, 0.0), polydeg=3, - volume_flux=flux_shima_etal_turbo, surface_flux=flux_shima_etal_turbo) + joinpath(examples_dir(), "tree_3d_dgsem", "elixir_euler_ec.jl"), + initial_refinement_level = 0, tspan = (0.0, 0.0), polydeg = 3, + volume_flux = flux_shima_etal_turbo, + surface_flux = flux_shima_etal_turbo) u_ode = copy(sol.u[end]) du_ode = zero(u_ode) # Preserve original memory since it will be `unsafe_wrap`ped and might # thus otherwise be garbage collected GC.@preserve u_ode du_ode begin - u = Trixi.wrap_array(u_ode, semi) - du = Trixi.wrap_array(du_ode, semi) - nonconservative_terms = Trixi.have_nonconservative_terms(semi.equations) - - # Call the optimized default version - du .= 0 - Trixi.flux_differencing_kernel!( - du, u, 1, semi.mesh, - nonconservative_terms, semi.equations, - semi.solver.volume_integral.volume_flux, semi.solver, semi.cache, true) - du_specialized = du[:, :, :, :, 1] - - # Call the plain version - note the argument type `Function` of - # `semi.solver.volume_integral.volume_flux` - du .= 0 - invoke(Trixi.flux_differencing_kernel!, - Tuple{typeof(du), typeof(u), Integer, typeof(semi.mesh), - typeof(nonconservative_terms), typeof(semi.equations), - Function, typeof(semi.solver), typeof(semi.cache), Bool}, - du, u, 1, semi.mesh, - nonconservative_terms, semi.equations, - semi.solver.volume_integral.volume_flux, semi.solver, semi.cache, true) - du_baseline = du[:, :, :, :, 1] - - @test du_specialized ≈ du_baseline + u = Trixi.wrap_array(u_ode, semi) + du = Trixi.wrap_array(du_ode, semi) + nonconservative_terms = Trixi.have_nonconservative_terms(semi.equations) + + # Call the optimized default version + du .= 0 + Trixi.flux_differencing_kernel!(du, u, 1, semi.mesh, + nonconservative_terms, semi.equations, + semi.solver.volume_integral.volume_flux, + semi.solver, semi.cache, true) + du_specialized = du[:, :, :, :, 1] + + # Call the plain version - note the argument type `Function` of + # `semi.solver.volume_integral.volume_flux` + du .= 0 + invoke(Trixi.flux_differencing_kernel!, + Tuple{typeof(du), typeof(u), Integer, typeof(semi.mesh), + typeof(nonconservative_terms), typeof(semi.equations), + Function, typeof(semi.solver), typeof(semi.cache), Bool}, + du, u, 1, semi.mesh, + nonconservative_terms, semi.equations, + semi.solver.volume_integral.volume_flux, semi.solver, semi.cache, true) + du_baseline = du[:, :, :, :, 1] + + @test du_specialized ≈ du_baseline end - end +end - @timed_testset "TreeMesh3D, flux_ranocha_turbo" begin +@timed_testset "TreeMesh3D, flux_ranocha_turbo" begin trixi_include(@__MODULE__, - joinpath(examples_dir(), "tree_3d_dgsem", "elixir_euler_ec.jl"), - initial_refinement_level=0, tspan=(0.0, 0.0), polydeg=3, - volume_flux=flux_ranocha_turbo, surface_flux=flux_ranocha_turbo) + joinpath(examples_dir(), "tree_3d_dgsem", "elixir_euler_ec.jl"), + initial_refinement_level = 0, tspan = (0.0, 0.0), polydeg = 3, + volume_flux = flux_ranocha_turbo, surface_flux = flux_ranocha_turbo) u_ode = copy(sol.u[end]) du_ode = zero(u_ode) # Preserve original memory since it will be `unsafe_wrap`ped and might # thus otherwise be garbage collected GC.@preserve u_ode du_ode begin - u = Trixi.wrap_array(u_ode, semi) - du = Trixi.wrap_array(du_ode, semi) - nonconservative_terms = Trixi.have_nonconservative_terms(semi.equations) - - # Call the optimized default version - du .= 0 - Trixi.flux_differencing_kernel!( - du, u, 1, semi.mesh, - nonconservative_terms, semi.equations, - semi.solver.volume_integral.volume_flux, semi.solver, semi.cache, true) - du_specialized = du[:, :, :, :, 1] - - # Call the plain version - note the argument type `Function` of - # `semi.solver.volume_integral.volume_flux` - du .= 0 - invoke(Trixi.flux_differencing_kernel!, - Tuple{typeof(du), typeof(u), Integer, typeof(semi.mesh), - typeof(nonconservative_terms), typeof(semi.equations), - Function, typeof(semi.solver), typeof(semi.cache), Bool}, - du, u, 1, semi.mesh, - nonconservative_terms, semi.equations, - semi.solver.volume_integral.volume_flux, semi.solver, semi.cache, true) - du_baseline = du[:, :, :, :, 1] - - @test du_specialized ≈ du_baseline + u = Trixi.wrap_array(u_ode, semi) + du = Trixi.wrap_array(du_ode, semi) + nonconservative_terms = Trixi.have_nonconservative_terms(semi.equations) + + # Call the optimized default version + du .= 0 + Trixi.flux_differencing_kernel!(du, u, 1, semi.mesh, + nonconservative_terms, semi.equations, + semi.solver.volume_integral.volume_flux, + semi.solver, semi.cache, true) + du_specialized = du[:, :, :, :, 1] + + # Call the plain version - note the argument type `Function` of + # `semi.solver.volume_integral.volume_flux` + du .= 0 + invoke(Trixi.flux_differencing_kernel!, + Tuple{typeof(du), typeof(u), Integer, typeof(semi.mesh), + typeof(nonconservative_terms), typeof(semi.equations), + Function, typeof(semi.solver), typeof(semi.cache), Bool}, + du, u, 1, semi.mesh, + nonconservative_terms, semi.equations, + semi.solver.volume_integral.volume_flux, semi.solver, semi.cache, true) + du_baseline = du[:, :, :, :, 1] + + @test du_specialized ≈ du_baseline end - end +end - @timed_testset "StructuredMesh3D, flux_shima_etal_turbo" begin +@timed_testset "StructuredMesh3D, flux_shima_etal_turbo" begin trixi_include(@__MODULE__, - joinpath(examples_dir(), "structured_3d_dgsem", "elixir_euler_ec.jl"), - cells_per_dimension=(1, 1, 1), tspan=(0.0, 0.0), polydeg=3, - volume_flux=flux_shima_etal_turbo, surface_flux=flux_shima_etal_turbo) + joinpath(examples_dir(), "structured_3d_dgsem", "elixir_euler_ec.jl"), + cells_per_dimension = (1, 1, 1), tspan = (0.0, 0.0), polydeg = 3, + volume_flux = flux_shima_etal_turbo, + surface_flux = flux_shima_etal_turbo) u_ode = copy(sol.u[end]) du_ode = zero(u_ode) # Preserve original memory since it will be `unsafe_wrap`ped and might # thus otherwise be garbage collected GC.@preserve u_ode du_ode begin - u = Trixi.wrap_array(u_ode, semi) - du = Trixi.wrap_array(du_ode, semi) - nonconservative_terms = Trixi.have_nonconservative_terms(semi.equations) - - # Call the optimized default version - du .= 0 - Trixi.flux_differencing_kernel!( - du, u, 1, semi.mesh, - nonconservative_terms, semi.equations, - semi.solver.volume_integral.volume_flux, semi.solver, semi.cache, true) - du_specialized = du[:, :, :, :, 1] - - # Call the plain version - note the argument type `Function` of - # `semi.solver.volume_integral.volume_flux` - du .= 0 - invoke(Trixi.flux_differencing_kernel!, - Tuple{typeof(du), typeof(u), Integer, typeof(semi.mesh), - typeof(nonconservative_terms), typeof(semi.equations), - Function, typeof(semi.solver), typeof(semi.cache), Bool}, - du, u, 1, semi.mesh, - nonconservative_terms, semi.equations, - semi.solver.volume_integral.volume_flux, semi.solver, semi.cache, true) - du_baseline = du[:, :, :, :, 1] - - @test du_specialized ≈ du_baseline + u = Trixi.wrap_array(u_ode, semi) + du = Trixi.wrap_array(du_ode, semi) + nonconservative_terms = Trixi.have_nonconservative_terms(semi.equations) + + # Call the optimized default version + du .= 0 + Trixi.flux_differencing_kernel!(du, u, 1, semi.mesh, + nonconservative_terms, semi.equations, + semi.solver.volume_integral.volume_flux, + semi.solver, semi.cache, true) + du_specialized = du[:, :, :, :, 1] + + # Call the plain version - note the argument type `Function` of + # `semi.solver.volume_integral.volume_flux` + du .= 0 + invoke(Trixi.flux_differencing_kernel!, + Tuple{typeof(du), typeof(u), Integer, typeof(semi.mesh), + typeof(nonconservative_terms), typeof(semi.equations), + Function, typeof(semi.solver), typeof(semi.cache), Bool}, + du, u, 1, semi.mesh, + nonconservative_terms, semi.equations, + semi.solver.volume_integral.volume_flux, semi.solver, semi.cache, true) + du_baseline = du[:, :, :, :, 1] + + @test du_specialized ≈ du_baseline end - end +end - @timed_testset "StructuredMesh3D, flux_ranocha_turbo" begin +@timed_testset "StructuredMesh3D, flux_ranocha_turbo" begin trixi_include(@__MODULE__, - joinpath(examples_dir(), "structured_3d_dgsem", "elixir_euler_ec.jl"), - cells_per_dimension=(1, 1, 1), tspan=(0.0, 0.0), polydeg=3, - volume_flux=flux_ranocha_turbo, surface_flux=flux_ranocha_turbo) + joinpath(examples_dir(), "structured_3d_dgsem", "elixir_euler_ec.jl"), + cells_per_dimension = (1, 1, 1), tspan = (0.0, 0.0), polydeg = 3, + volume_flux = flux_ranocha_turbo, surface_flux = flux_ranocha_turbo) u_ode = copy(sol.u[end]) du_ode = zero(u_ode) # Preserve original memory since it will be `unsafe_wrap`ped and might # thus otherwise be garbage collected GC.@preserve u_ode du_ode begin - u = Trixi.wrap_array(u_ode, semi) - du = Trixi.wrap_array(du_ode, semi) - nonconservative_terms = Trixi.have_nonconservative_terms(semi.equations) - - # Call the optimized default version - du .= 0 - Trixi.flux_differencing_kernel!( - du, u, 1, semi.mesh, - nonconservative_terms, semi.equations, - semi.solver.volume_integral.volume_flux, semi.solver, semi.cache, true) - du_specialized = du[:, :, :, :, 1] - - # Call the plain version - note the argument type `Function` of - # `semi.solver.volume_integral.volume_flux` - du .= 0 - invoke(Trixi.flux_differencing_kernel!, - Tuple{typeof(du), typeof(u), Integer, typeof(semi.mesh), - typeof(nonconservative_terms), typeof(semi.equations), - Function, typeof(semi.solver), typeof(semi.cache), Bool}, - du, u, 1, semi.mesh, - nonconservative_terms, semi.equations, - semi.solver.volume_integral.volume_flux, semi.solver, semi.cache, true) - du_baseline = du[:, :, :, :, 1] - - @test du_specialized ≈ du_baseline + u = Trixi.wrap_array(u_ode, semi) + du = Trixi.wrap_array(du_ode, semi) + nonconservative_terms = Trixi.have_nonconservative_terms(semi.equations) + + # Call the optimized default version + du .= 0 + Trixi.flux_differencing_kernel!(du, u, 1, semi.mesh, + nonconservative_terms, semi.equations, + semi.solver.volume_integral.volume_flux, + semi.solver, semi.cache, true) + du_specialized = du[:, :, :, :, 1] + + # Call the plain version - note the argument type `Function` of + # `semi.solver.volume_integral.volume_flux` + du .= 0 + invoke(Trixi.flux_differencing_kernel!, + Tuple{typeof(du), typeof(u), Integer, typeof(semi.mesh), + typeof(nonconservative_terms), typeof(semi.equations), + Function, typeof(semi.solver), typeof(semi.cache), Bool}, + du, u, 1, semi.mesh, + nonconservative_terms, semi.equations, + semi.solver.volume_integral.volume_flux, semi.solver, semi.cache, true) + du_baseline = du[:, :, :, :, 1] + + @test du_specialized ≈ du_baseline end - end end - +end # Clean up afterwards: delete Trixi.jl output directory -@test_nowarn rm(outdir, recursive=true) +@test_nowarn rm(outdir, recursive = true) end #module diff --git a/test/test_special_elixirs.jl b/test/test_special_elixirs.jl index c05dfbdfca1..ba670a6025e 100644 --- a/test/test_special_elixirs.jl +++ b/test/test_special_elixirs.jl @@ -10,7 +10,7 @@ include("test_trixi.jl") # Start with a clean environment: remove Trixi.jl output directory if it exists outdir = "out" -isdir(outdir) && rm(outdir, recursive=true) +isdir(outdir) && rm(outdir, recursive = true) const EXAMPLES_DIR = pkgdir(Trixi, "examples") @@ -18,66 +18,113 @@ cmd = string(Base.julia_cmd()) coverage = occursin("--code-coverage", cmd) && !occursin("--code-coverage=none", cmd) @testset "Special elixirs" begin - @testset "Convergence test" begin +#! format: noindent + +@testset "Convergence test" begin if !coverage - @timed_testset "tree_2d_dgsem" begin - mean_convergence = convergence_test(@__MODULE__, joinpath(EXAMPLES_DIR, "tree_2d_dgsem", "elixir_advection_extended.jl"), 3, initial_refinement_level=2) - @test isapprox(mean_convergence[:l2], [4.0], rtol=0.05) - end - - @timed_testset "structured_2d_dgsem" begin - mean_convergence = convergence_test(@__MODULE__, joinpath(EXAMPLES_DIR, "structured_2d_dgsem", "elixir_advection_extended.jl"), 3, cells_per_dimension=(5, 9)) - @test isapprox(mean_convergence[:l2], [4.0], rtol=0.05) - end - - @timed_testset "structured_2d_dgsem coupled" begin - mean_convergence = convergence_test(@__MODULE__, joinpath(EXAMPLES_DIR, "structured_2d_dgsem", "elixir_advection_coupled.jl"), 3) - @test isapprox(mean_convergence[1][:l2], [4.0], rtol=0.05) - @test isapprox(mean_convergence[2][:l2], [4.0], rtol=0.05) - end - - @timed_testset "p4est_2d_dgsem" begin - # Run convergence test on unrefined mesh - no_refine = @cfunction((p4est, which_tree, quadrant) -> Cint(0), Cint, (Ptr{Trixi.p4est_t}, Ptr{Trixi.p4est_topidx_t}, Ptr{Trixi.p4est_quadrant_t})) - mean_convergence = convergence_test(@__MODULE__, joinpath(EXAMPLES_DIR, "p4est_2d_dgsem", "elixir_euler_source_terms_nonconforming_unstructured_flag.jl"), 2, refine_fn_c=no_refine) - @test isapprox(mean_convergence[:linf], [3.2, 3.2, 4.0, 3.7], rtol=0.05) - end - - @timed_testset "structured_3d_dgsem" begin - mean_convergence = convergence_test(@__MODULE__, joinpath(EXAMPLES_DIR, "structured_3d_dgsem", "elixir_advection_basic.jl"), 2, cells_per_dimension=(7, 4, 5)) - @test isapprox(mean_convergence[:l2], [4.0], rtol=0.05) - end - - @timed_testset "p4est_3d_dgsem" begin - mean_convergence = convergence_test(@__MODULE__, joinpath(EXAMPLES_DIR, "p4est_3d_dgsem", "elixir_advection_unstructured_curved.jl"), 2, initial_refinement_level=0) - @test isapprox(mean_convergence[:l2], [2.7], rtol=0.05) - end - - @timed_testset "paper_self_gravitating_gas_dynamics" begin - mean_convergence = convergence_test(@__MODULE__, joinpath(EXAMPLES_DIR, "paper_self_gravitating_gas_dynamics", "elixir_eulergravity_convergence.jl"), 2, tspan=(0.0, 0.25), initial_refinement_level=1) - @test isapprox(mean_convergence[:l2], 4 * ones(4), atol=0.4) - end + @timed_testset "tree_2d_dgsem" begin + mean_convergence = convergence_test(@__MODULE__, + joinpath(EXAMPLES_DIR, "tree_2d_dgsem", + "elixir_advection_extended.jl"), + 3, initial_refinement_level = 2) + @test isapprox(mean_convergence[:l2], [4.0], rtol = 0.05) + end + + @timed_testset "structured_2d_dgsem" begin + mean_convergence = convergence_test(@__MODULE__, + joinpath(EXAMPLES_DIR, + "structured_2d_dgsem", + "elixir_advection_extended.jl"), + 3, cells_per_dimension = (5, 9)) + @test isapprox(mean_convergence[:l2], [4.0], rtol = 0.05) + end + + @timed_testset "structured_2d_dgsem coupled" begin + mean_convergence = convergence_test(@__MODULE__, + joinpath(EXAMPLES_DIR, + "structured_2d_dgsem", + "elixir_advection_coupled.jl"), + 3) + @test isapprox(mean_convergence[1][:l2], [4.0], rtol = 0.05) + @test isapprox(mean_convergence[2][:l2], [4.0], rtol = 0.05) + end + + @timed_testset "p4est_2d_dgsem" begin + # Run convergence test on unrefined mesh + no_refine = @cfunction((p4est, which_tree, quadrant)->Cint(0), Cint, + (Ptr{Trixi.p4est_t}, Ptr{Trixi.p4est_topidx_t}, + Ptr{Trixi.p4est_quadrant_t})) + mean_convergence = convergence_test(@__MODULE__, + joinpath(EXAMPLES_DIR, "p4est_2d_dgsem", + "elixir_euler_source_terms_nonconforming_unstructured_flag.jl"), + 2, refine_fn_c = no_refine) + @test isapprox(mean_convergence[:linf], [3.2, 3.2, 4.0, 3.7], rtol = 0.05) + end + + @timed_testset "structured_3d_dgsem" begin + mean_convergence = convergence_test(@__MODULE__, + joinpath(EXAMPLES_DIR, + "structured_3d_dgsem", + "elixir_advection_basic.jl"), + 2, cells_per_dimension = (7, 4, 5)) + @test isapprox(mean_convergence[:l2], [4.0], rtol = 0.05) + end + + @timed_testset "p4est_3d_dgsem" begin + mean_convergence = convergence_test(@__MODULE__, + joinpath(EXAMPLES_DIR, "p4est_3d_dgsem", + "elixir_advection_unstructured_curved.jl"), + 2, initial_refinement_level = 0) + @test isapprox(mean_convergence[:l2], [2.7], rtol = 0.05) + end + + @timed_testset "paper_self_gravitating_gas_dynamics" begin + mean_convergence = convergence_test(@__MODULE__, + joinpath(EXAMPLES_DIR, + "paper_self_gravitating_gas_dynamics", + "elixir_eulergravity_convergence.jl"), + 2, tspan = (0.0, 0.25), + initial_refinement_level = 1) + @test isapprox(mean_convergence[:l2], 4 * ones(4), atol = 0.4) + end else - # Without coverage, just run simple convergence tests to cover - # the convergence test logic - @test_nowarn_mod convergence_test(@__MODULE__, joinpath(EXAMPLES_DIR, "tree_2d_dgsem", "elixir_advection_basic.jl"), 2, tspan=(0.0, 0.01)) - @test_nowarn_mod convergence_test(@__MODULE__, joinpath(EXAMPLES_DIR, "tree_2d_dgsem", "elixir_advection_extended.jl"), 2, initial_refinement_level=0, tspan=(0.0, 0.1)) - @test_nowarn_mod convergence_test(@__MODULE__, joinpath(EXAMPLES_DIR, "structured_2d_dgsem", "elixir_advection_basic.jl"), 2, tspan=(0.0, 0.01)) - @test_nowarn_mod convergence_test(@__MODULE__, joinpath(EXAMPLES_DIR, "structured_2d_dgsem", "elixir_advection_coupled.jl"), 2, tspan=(0.0, 0.01)) - @test_nowarn_mod convergence_test(@__MODULE__, joinpath(EXAMPLES_DIR, "structured_2d_dgsem", "elixir_advection_extended.jl"), 2, cells_per_dimension=(1, 1), tspan=(0.0, 0.1)) + # Without coverage, just run simple convergence tests to cover + # the convergence test logic + @test_nowarn_mod convergence_test(@__MODULE__, + joinpath(EXAMPLES_DIR, "tree_2d_dgsem", + "elixir_advection_basic.jl"), 2) + @test_nowarn_mod convergence_test(@__MODULE__, + joinpath(EXAMPLES_DIR, "tree_2d_dgsem", + "elixir_advection_extended.jl"), 2, + initial_refinement_level = 0, + tspan = (0.0, 0.1)) + @test_nowarn_mod convergence_test(@__MODULE__, + joinpath(EXAMPLES_DIR, "structured_2d_dgsem", + "elixir_advection_basic.jl"), 2) + @test_nowarn_mod convergence_test(@__MODULE__, + joinpath(EXAMPLES_DIR, "structured_2d_dgsem", + "elixir_advection_coupled.jl"), 2) + @test_nowarn_mod convergence_test(@__MODULE__, + joinpath(EXAMPLES_DIR, "structured_2d_dgsem", + "elixir_advection_extended.jl"), 2, + cells_per_dimension = (1, 1), + tspan = (0.0, 0.1)) end - end - +end - @timed_testset "Test linear structure (2D)" begin - trixi_include(@__MODULE__, joinpath(EXAMPLES_DIR, "tree_2d_dgsem", "elixir_advection_extended.jl"), - tspan=(0.0, 0.0), initial_refinement_level=2) +@timed_testset "Test linear structure (2D)" begin + trixi_include(@__MODULE__, + joinpath(EXAMPLES_DIR, "tree_2d_dgsem", + "elixir_advection_extended.jl"), + tspan = (0.0, 0.0), initial_refinement_level = 2) A, b = linear_structure(semi) λ = eigvals(Matrix(A)) @test maximum(real, λ) < 10 * sqrt(eps(real(semi))) - trixi_include(@__MODULE__, joinpath(EXAMPLES_DIR, "tree_2d_dgsem", "elixir_hypdiff_lax_friedrichs.jl"), - tspan=(0.0, 0.0), initial_refinement_level=2) + trixi_include(@__MODULE__, + joinpath(EXAMPLES_DIR, "tree_2d_dgsem", + "elixir_hypdiff_lax_friedrichs.jl"), + tspan = (0.0, 0.0), initial_refinement_level = 2) A, b = linear_structure(semi) λ = eigvals(Matrix(A)) @test maximum(real, λ) < 10 * sqrt(eps(real(semi))) @@ -87,122 +134,143 @@ coverage = occursin("--code-coverage", cmd) && !occursin("--code-coverage=none", Ax = A * x @. b = 2 * b + x @test A * x ≈ Ax - end - +end - @testset "Test Jacobian of DG (2D)" begin +@testset "Test Jacobian of DG (2D)" begin @timed_testset "Linear advection" begin - trixi_include(@__MODULE__, joinpath(EXAMPLES_DIR, "tree_2d_dgsem", "elixir_advection_extended.jl"), - tspan=(0.0, 0.0), initial_refinement_level=2) - A, _ = linear_structure(semi) - - J = jacobian_ad_forward(semi) - @test Matrix(A) ≈ J - λ = eigvals(J) - @test maximum(real, λ) < 10 * sqrt(eps(real(semi))) - - J = jacobian_fd(semi) - @test Matrix(A) ≈ J - λ = eigvals(J) - @test maximum(real, λ) < 10 * sqrt(eps(real(semi))) + trixi_include(@__MODULE__, + joinpath(EXAMPLES_DIR, "tree_2d_dgsem", + "elixir_advection_extended.jl"), + tspan = (0.0, 0.0), initial_refinement_level = 2) + A, _ = linear_structure(semi) + + J = jacobian_ad_forward(semi) + @test Matrix(A) ≈ J + λ = eigvals(J) + @test maximum(real, λ) < 10 * sqrt(eps(real(semi))) + + J = jacobian_fd(semi) + @test Matrix(A) ≈ J + λ = eigvals(J) + @test maximum(real, λ) < 10 * sqrt(eps(real(semi))) end @timed_testset "Linear advection-diffusion" begin - trixi_include(@__MODULE__, joinpath(EXAMPLES_DIR, "tree_2d_dgsem", "elixir_advection_diffusion.jl"), - tspan=(0.0, 0.0), initial_refinement_level=2) + trixi_include(@__MODULE__, + joinpath(EXAMPLES_DIR, "tree_2d_dgsem", + "elixir_advection_diffusion.jl"), + tspan = (0.0, 0.0), initial_refinement_level = 2) - J = jacobian_ad_forward(semi) - λ = eigvals(J) - @test maximum(real, λ) < 10 * sqrt(eps(real(semi))) + J = jacobian_ad_forward(semi) + λ = eigvals(J) + @test maximum(real, λ) < 10 * sqrt(eps(real(semi))) end @timed_testset "Compressible Euler equations" begin - trixi_include(@__MODULE__, joinpath(EXAMPLES_DIR, "tree_2d_dgsem", "elixir_euler_density_wave.jl"), - tspan=(0.0, 0.0), initial_refinement_level=1) + trixi_include(@__MODULE__, + joinpath(EXAMPLES_DIR, "tree_2d_dgsem", + "elixir_euler_density_wave.jl"), + tspan = (0.0, 0.0), initial_refinement_level = 1) - J = jacobian_ad_forward(semi) - λ = eigvals(J) - @test maximum(real, λ) < 7.0e-7 - - J = jacobian_fd(semi) - λ = eigvals(J) - @test maximum(real, λ) < 7.0e-3 + J = jacobian_ad_forward(semi) + λ = eigvals(J) + @test maximum(real, λ) < 7.0e-7 - # This does not work yet because of the indicators... - @test_skip begin - trixi_include(@__MODULE__, joinpath(EXAMPLES_DIR, "tree_2d_dgsem", "elixir_euler_shockcapturing.jl"), - tspan=(0.0, 0.0), initial_refinement_level=1) - jacobian_ad_forward(semi) - end + J = jacobian_fd(semi) + λ = eigvals(J) + @test maximum(real, λ) < 7.0e-3 + + # This does not work yet because of the indicators... + @test_skip begin + trixi_include(@__MODULE__, + joinpath(EXAMPLES_DIR, "tree_2d_dgsem", + "elixir_euler_shockcapturing.jl"), + tspan = (0.0, 0.0), initial_refinement_level = 1) + jacobian_ad_forward(semi) + end - @timed_testset "DGMulti (weak form)" begin - gamma = 1.4 - equations = CompressibleEulerEquations2D(gamma) - initial_condition = initial_condition_density_wave + @timed_testset "DGMulti (weak form)" begin + gamma = 1.4 + equations = CompressibleEulerEquations2D(gamma) + initial_condition = initial_condition_density_wave - solver = DGMulti(polydeg = 5, element_type = Quad(), approximation_type = SBP(), - surface_integral = SurfaceIntegralWeakForm(flux_central), - volume_integral = VolumeIntegralWeakForm()) + solver = DGMulti(polydeg = 5, element_type = Quad(), + approximation_type = SBP(), + surface_integral = SurfaceIntegralWeakForm(flux_central), + volume_integral = VolumeIntegralWeakForm()) - # DGMultiMesh is on [-1, 1]^ndims by default - mesh = DGMultiMesh(solver, cells_per_dimension=(2, 2), periodicity=(true, true)) + # DGMultiMesh is on [-1, 1]^ndims by default + cells_per_dimension = (2, 2) + mesh = DGMultiMesh(solver, cells_per_dimension, + periodicity = (true, true)) - semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, + solver) - J = jacobian_ad_forward(semi) - λ = eigvals(J) - @test maximum(real, λ) < 7.0e-7 - end + J = jacobian_ad_forward(semi) + λ = eigvals(J) + @test maximum(real, λ) < 7.0e-7 + end - @timed_testset "DGMulti (SBP, flux differencing)" begin - gamma = 1.4 - equations = CompressibleEulerEquations2D(gamma) - initial_condition = initial_condition_density_wave + @timed_testset "DGMulti (SBP, flux differencing)" begin + gamma = 1.4 + equations = CompressibleEulerEquations2D(gamma) + initial_condition = initial_condition_density_wave - solver = DGMulti(polydeg = 5, element_type = Quad(), approximation_type = SBP(), - surface_integral = SurfaceIntegralWeakForm(flux_central), - volume_integral = VolumeIntegralFluxDifferencing(flux_central)) + solver = DGMulti(polydeg = 5, element_type = Quad(), + approximation_type = SBP(), + surface_integral = SurfaceIntegralWeakForm(flux_central), + volume_integral = VolumeIntegralFluxDifferencing(flux_central)) - # DGMultiMesh is on [-1, 1]^ndims by default - mesh = DGMultiMesh(solver, cells_per_dimension=(2, 2), periodicity=(true, true)) + # DGMultiMesh is on [-1, 1]^ndims by default + cells_per_dimension = (2, 2) + mesh = DGMultiMesh(solver, cells_per_dimension, + periodicity = (true, true)) - semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) + semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, + solver) - J = jacobian_ad_forward(semi) - λ = eigvals(J) - @test maximum(real, λ) < 7.0e-7 - end + J = jacobian_ad_forward(semi) + λ = eigvals(J) + @test maximum(real, λ) < 7.0e-7 + end end @timed_testset "Navier-Stokes" begin - trixi_include(@__MODULE__, joinpath(EXAMPLES_DIR, "tree_2d_dgsem", "elixir_navierstokes_taylor_green_vortex.jl"), - tspan=(0.0, 0.0), initial_refinement_level=2) + trixi_include(@__MODULE__, + joinpath(EXAMPLES_DIR, "tree_2d_dgsem", + "elixir_navierstokes_taylor_green_vortex.jl"), + tspan = (0.0, 0.0), initial_refinement_level = 2) - J = jacobian_ad_forward(semi) - λ = eigvals(J) - @test maximum(real, λ) < 0.2 + J = jacobian_ad_forward(semi) + λ = eigvals(J) + @test maximum(real, λ) < 0.2 end @timed_testset "MHD" begin - trixi_include(@__MODULE__, joinpath(EXAMPLES_DIR, "tree_2d_dgsem", "elixir_mhd_alfven_wave.jl"), - tspan=(0.0, 0.0), initial_refinement_level=0) - @test_nowarn jacobian_ad_forward(semi) + trixi_include(@__MODULE__, + joinpath(EXAMPLES_DIR, "tree_2d_dgsem", + "elixir_mhd_alfven_wave.jl"), + tspan = (0.0, 0.0), initial_refinement_level = 0) + @test_nowarn jacobian_ad_forward(semi) end - end - +end - @timed_testset "Test linear structure (3D)" begin - trixi_include(@__MODULE__, joinpath(EXAMPLES_DIR, "tree_3d_dgsem", "elixir_advection_extended.jl"), - tspan=(0.0, 0.0), initial_refinement_level=1) +@timed_testset "Test linear structure (3D)" begin + trixi_include(@__MODULE__, + joinpath(EXAMPLES_DIR, "tree_3d_dgsem", + "elixir_advection_extended.jl"), + tspan = (0.0, 0.0), initial_refinement_level = 1) A, b = linear_structure(semi) λ = eigvals(Matrix(A)) @test maximum(real, λ) < 10 * sqrt(eps(real(semi))) - end - +end - @timed_testset "Test Jacobian of DG (3D)" begin - trixi_include(@__MODULE__, joinpath(EXAMPLES_DIR, "tree_3d_dgsem", "elixir_advection_extended.jl"), - tspan=(0.0, 0.0), initial_refinement_level=1) +@timed_testset "Test Jacobian of DG (3D)" begin + trixi_include(@__MODULE__, + joinpath(EXAMPLES_DIR, "tree_3d_dgsem", + "elixir_advection_extended.jl"), + tspan = (0.0, 0.0), initial_refinement_level = 1) A, _ = linear_structure(semi) J = jacobian_ad_forward(semi) @@ -210,76 +278,77 @@ coverage = occursin("--code-coverage", cmd) && !occursin("--code-coverage=none", J = jacobian_fd(semi) @test Matrix(A) ≈ J - end - +end - @testset "AD using ForwardDiff" begin +@testset "AD using ForwardDiff" begin @timed_testset "Euler equations 1D" begin - function entropy_at_final_time(k) # k is the wave number of the initial condition - equations = CompressibleEulerEquations1D(1.4) - mesh = TreeMesh((-1.0,), (1.0,), initial_refinement_level=3, n_cells_max=10^4) - solver = DGSEM(3, flux_hll, VolumeIntegralFluxDifferencing(flux_ranocha)) - initial_condition = (x, t, equations) -> begin - rho = 2 + sinpi(k * sum(x)) - v1 = 0.1 - p = 10.0 - return prim2cons(SVector(rho, v1, p), equations) + function entropy_at_final_time(k) # k is the wave number of the initial condition + equations = CompressibleEulerEquations1D(1.4) + mesh = TreeMesh((-1.0,), (1.0,), initial_refinement_level = 3, + n_cells_max = 10^4) + solver = DGSEM(3, flux_hll, VolumeIntegralFluxDifferencing(flux_ranocha)) + initial_condition = (x, t, equations) -> begin + rho = 2 + sinpi(k * sum(x)) + v1 = 0.1 + p = 10.0 + return prim2cons(SVector(rho, v1, p), equations) + end + semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, + solver, + uEltype = typeof(k)) + ode = semidiscretize(semi, (0.0, 1.0)) + summary_callback = SummaryCallback() + analysis_interval = 100 + analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + alive_callback = AliveCallback(analysis_interval = analysis_interval) + callbacks = CallbackSet(summary_callback, + analysis_callback, + alive_callback) + sol = solve(ode, SSPRK43(), callback = callbacks) + Trixi.integrate(entropy, sol.u[end], semi) end - semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - uEltype=typeof(k)) - ode = semidiscretize(semi, (0.0, 1.0)) - summary_callback = SummaryCallback() - analysis_interval = 100 - analysis_callback = AnalysisCallback(semi, interval=analysis_interval) - alive_callback = AliveCallback(analysis_interval=analysis_interval) - callbacks = CallbackSet( - summary_callback, - analysis_callback, - alive_callback - ) - sol = solve(ode, SSPRK43(), callback=callbacks) - Trixi.integrate(entropy, sol.u[end], semi) - end - ForwardDiff.derivative(entropy_at_final_time, 1.0) ≈ -0.4524664696235628 + ForwardDiff.derivative(entropy_at_final_time, 1.0) ≈ -0.4524664696235628 end @timed_testset "Linear advection 2D" begin - function energy_at_final_time(k) # k is the wave number of the initial condition - equations = LinearScalarAdvectionEquation2D(0.2, -0.7) - mesh = TreeMesh((-1.0, -1.0), (1.0, 1.0), initial_refinement_level=3, n_cells_max=10^4) - solver = DGSEM(3, flux_lax_friedrichs) - initial_condition = (x, t, equation) -> begin - x_trans = Trixi.x_trans_periodic_2d(x - equation.advection_velocity * t) - return SVector(sinpi(k * sum(x_trans))) + function energy_at_final_time(k) # k is the wave number of the initial condition + equations = LinearScalarAdvectionEquation2D(0.2, -0.7) + mesh = TreeMesh((-1.0, -1.0), (1.0, 1.0), initial_refinement_level = 3, + n_cells_max = 10^4) + solver = DGSEM(3, flux_lax_friedrichs) + initial_condition = (x, t, equation) -> begin + x_trans = Trixi.x_trans_periodic_2d(x - equation.advection_velocity * t) + return SVector(sinpi(k * sum(x_trans))) + end + semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, + solver, + uEltype = typeof(k)) + ode = semidiscretize(semi, (0.0, 1.0)) + summary_callback = SummaryCallback() + analysis_interval = 100 + analysis_callback = AnalysisCallback(semi, interval = analysis_interval) + alive_callback = AliveCallback(analysis_interval = analysis_interval) + stepsize_callback = StepsizeCallback(cfl = 1.6) + callbacks = CallbackSet(summary_callback, + analysis_callback, + alive_callback, + stepsize_callback) + sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false), + save_everystep = false, adaptive = false, dt = 1.0, + callback = callbacks) + Trixi.integrate(energy_total, sol.u[end], semi) end - semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, - uEltype=typeof(k)) - ode = semidiscretize(semi, (0.0, 1.0)) - summary_callback = SummaryCallback() - analysis_interval = 100 - analysis_callback = AnalysisCallback(semi, interval=analysis_interval) - alive_callback = AliveCallback(analysis_interval=analysis_interval) - stepsize_callback = StepsizeCallback(cfl=1.6) - callbacks = CallbackSet( - summary_callback, - analysis_callback, - alive_callback, - stepsize_callback - ) - sol = solve(ode, CarpenterKennedy2N54(williamson_condition=false), save_everystep=false, adaptive=false, dt=1.0, callback=callbacks) - Trixi.integrate(energy_total, sol.u[end], semi) - end - ForwardDiff.derivative(energy_at_final_time, 1.0) ≈ 1.4388628342896945e-5 + ForwardDiff.derivative(energy_at_final_time, 1.0) ≈ 1.4388628342896945e-5 end @timed_testset "elixir_euler_ad.jl" begin - @test_trixi_include(joinpath(examples_dir(), "special_elixirs", "elixir_euler_ad.jl")) + @test_nowarn_mod trixi_include(joinpath(examples_dir(), "special_elixirs", + "elixir_euler_ad.jl")) end - end end - +end # Clean up afterwards: delete Trixi.jl output directory -@test_nowarn rm(outdir, recursive=true) +@test_nowarn rm(outdir, recursive = true) end #module diff --git a/test/test_structured_1d.jl b/test/test_structured_1d.jl index d280e2a5e01..f0eecfa9acd 100644 --- a/test/test_structured_1d.jl +++ b/test/test_structured_1d.jl @@ -9,59 +9,138 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "structured_1d_dgsem") # Start with a clean environment: remove Trixi.jl output directory if it exists outdir = "out" -isdir(outdir) && rm(outdir, recursive=true) +isdir(outdir) && rm(outdir, recursive = true) @testset "StructuredMesh1D" begin - @trixi_testset "elixir_advection_basic.jl" begin +#! format: noindent + +@trixi_testset "elixir_advection_basic.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_basic.jl"), - # Expected errors are exactly the same as with TreeMesh! - l2 = [6.0388296447998465e-6], - linf = [3.217887726258972e-5]) - end + # Expected errors are exactly the same as with TreeMesh! + l2=[6.0388296447998465e-6], + linf=[3.217887726258972e-5]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_advection_nonperiodic.jl" begin +@trixi_testset "elixir_advection_nonperiodic.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_nonperiodic.jl"), - l2 = [5.641921365468918e-5], - linf = [0.00021049780975179733]) - end + l2=[5.641921365468918e-5], + linf=[0.00021049780975179733]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_advection_shockcapturing.jl" begin +@trixi_testset "elixir_advection_shockcapturing.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_shockcapturing.jl"), - l2 = [0.08015029105233593], - linf = [0.610709468736576], - atol = 1.0e-5) - end + l2=[0.08015029105233593], + linf=[0.610709468736576], + atol=1.0e-5) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_sedov.jl" begin +@trixi_testset "elixir_euler_sedov.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov.jl"), - l2 = [3.67478226e-01, 3.49491179e-01, 8.08910759e-01], - linf = [1.58971947e+00, 1.59812384e+00, 1.94732969e+00], - tspan = (0.0, 0.3)) - end + l2=[3.67478226e-01, 3.49491179e-01, 8.08910759e-01], + linf=[1.58971947e+00, 1.59812384e+00, 1.94732969e+00], + tspan=(0.0, 0.3)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_sedov_hll_davis.jl" begin +@trixi_testset "elixir_euler_sedov_hll_davis.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov.jl"), - l2 = [1.278661029299215, 0.0663853410742763, 0.9585741943783386], - linf = [3.1661064228547255, 0.16256363944708607, 2.667676158812806], - tspan = (0.0, 12.5), - surface_flux = FluxHLL(min_max_speed_davis)) - end + l2=[1.278661029299215, 0.0663853410742763, 0.9585741943783386], + linf=[ + 3.1661064228547255, + 0.16256363944708607, + 2.667676158812806, + ], + tspan=(0.0, 12.5), + surface_flux=FluxHLL(min_max_speed_davis)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_source_terms.jl" begin +@trixi_testset "elixir_euler_source_terms.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms.jl"), - # Expected errors are exactly the same as with TreeMesh! - l2 = [2.2527950196212703e-8, 1.8187357193835156e-8, 7.705669939973104e-8], - linf = [1.6205433861493646e-7, 1.465427772462391e-7, 5.372255111879554e-7]) - end + # Expected errors are exactly the same as with TreeMesh! + l2=[ + 2.2527950196212703e-8, + 1.8187357193835156e-8, + 7.705669939973104e-8, + ], + linf=[ + 1.6205433861493646e-7, + 1.465427772462391e-7, + 5.372255111879554e-7, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_source_terms_nonperiodic.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms_nonperiodic.jl"), - l2 = [3.8099996914101204e-6, 1.6745575717106341e-6, 7.732189531480852e-6], - linf = [1.2971473393186272e-5, 9.270328934274374e-6, 3.092514399671842e-5]) - end +@trixi_testset "elixir_euler_source_terms_nonperiodic.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_source_terms_nonperiodic.jl"), + l2=[ + 3.8099996914101204e-6, + 1.6745575717106341e-6, + 7.732189531480852e-6, + ], + linf=[ + 1.2971473393186272e-5, + 9.270328934274374e-6, + 3.092514399671842e-5, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end end # Clean up afterwards: delete Trixi.jl output directory -@test_nowarn rm(outdir, recursive=true) +@test_nowarn rm(outdir, recursive = true) end # module diff --git a/test/test_structured_2d.jl b/test/test_structured_2d.jl index 75937ba82ad..1addc29e3e6 100644 --- a/test/test_structured_2d.jl +++ b/test/test_structured_2d.jl @@ -11,300 +11,955 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "structured_2d_dgsem") # Start with a clean environment: remove Trixi.jl output directory if it exists outdir = "out" -isdir(outdir) && rm(outdir, recursive=true) +isdir(outdir) && rm(outdir, recursive = true) @testset "StructuredMesh2D" begin - @trixi_testset "elixir_advection_basic.jl" begin +#! format: noindent + +@trixi_testset "elixir_advection_basic.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_basic.jl"), - # Expected errors are exactly the same as with TreeMesh! - l2 = [8.311947673061856e-6], - linf = [6.627000273229378e-5]) - end + # Expected errors are exactly the same as with TreeMesh! + l2=[8.311947673061856e-6], + linf=[6.627000273229378e-5]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_advection_coupled.jl" begin +@trixi_testset "elixir_advection_coupled.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_coupled.jl"), - l2 = [7.816742843181738e-6, 7.816742843196112e-6], - linf = [6.314906965543265e-5, 6.314906965410039e-5], - coverage_override = (maxiters=10^5,)) + l2=[7.816742843181738e-6, 7.816742843196112e-6], + linf=[6.314906965543265e-5, 6.314906965410039e-5], + coverage_override=(maxiters = 10^5,)) @testset "analysis_callback(sol) for AnalysisCallbackCoupled" begin - errors = analysis_callback(sol) - @test errors.l2 ≈ [7.816742843181738e-6, 7.816742843196112e-6] rtol=1.0e-4 - @test errors.linf ≈ [6.314906965543265e-5, 6.314906965410039e-5] rtol=1.0e-4 + errors = analysis_callback(sol) + @test errors.l2≈[7.816742843181738e-6, 7.816742843196112e-6] rtol=1.0e-4 + @test errors.linf≈[6.314906965543265e-5, 6.314906965410039e-5] rtol=1.0e-4 + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end end - end +end - @trixi_testset "elixir_advection_extended.jl" begin +@trixi_testset "elixir_advection_extended.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_extended.jl"), - l2 = [4.220397559713772e-6], - linf = [3.477948874874848e-5]) - end + l2=[4.220397559713772e-6], + linf=[3.477948874874848e-5]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_advection_extended.jl with polydeg=4" begin +@trixi_testset "elixir_advection_extended.jl with polydeg=4" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_extended.jl"), - l2 = [5.32996976442737e-7], - linf = [4.1344662966569246e-6], - atol = 1e-12, # required to make CI tests pass on macOS - cells_per_dimension = (16, 23), - polydeg = 4, - cfl = 1.4) - end - - @testset "elixir_advection_rotated.jl" begin + l2=[5.32996976442737e-7], + linf=[4.1344662966569246e-6], + atol=1e-12, # required to make CI tests pass on macOS + cells_per_dimension=(16, 23), + polydeg=4, + cfl=1.4) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@testset "elixir_advection_rotated.jl" begin @trixi_testset "elixir_advection_rotated.jl with α = 0.0" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_rotated.jl"), - # Expected errors are exactly the same as in elixir_advection_basic! - l2 = [8.311947673061856e-6], - linf = [6.627000273229378e-5], - alpha = 0.0) + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_rotated.jl"), + # Expected errors are exactly the same as in elixir_advection_basic! + l2=[8.311947673061856e-6], + linf=[6.627000273229378e-5], + alpha=0.0) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end end @trixi_testset "elixir_advection_rotated.jl with α = 0.1" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_rotated.jl"), - # Expected errors differ only slightly from elixir_advection_basic! - l2 = [8.3122750550501e-6], - linf = [6.626802581322089e-5], - alpha = 0.1) + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_rotated.jl"), + # Expected errors differ only slightly from elixir_advection_basic! + l2=[8.3122750550501e-6], + linf=[6.626802581322089e-5], + alpha=0.1) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end end @trixi_testset "elixir_advection_rotated.jl with α = 0.5 * pi" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_rotated.jl"), - # Expected errors are exactly the same as in elixir_advection_basic! - l2 = [8.311947673061856e-6], - linf = [6.627000273229378e-5], - alpha = 0.5 * pi) + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_rotated.jl"), + # Expected errors are exactly the same as in elixir_advection_basic! + l2=[8.311947673061856e-6], + linf=[6.627000273229378e-5], + alpha=0.5 * pi) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end end - end +end - @trixi_testset "elixir_advection_parallelogram.jl" begin +@trixi_testset "elixir_advection_parallelogram.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_parallelogram.jl"), - # Expected errors are exactly the same as in elixir_advection_basic! - l2 = [8.311947673061856e-6], - linf = [6.627000273229378e-5]) - end + # Expected errors are exactly the same as in elixir_advection_basic! + l2=[8.311947673061856e-6], + linf=[6.627000273229378e-5]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_advection_waving_flag.jl" begin +@trixi_testset "elixir_advection_waving_flag.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_waving_flag.jl"), - l2 = [0.00018553859900545866], - linf = [0.0016167719118129753]) - end + l2=[0.00018553859900545866], + linf=[0.0016167719118129753]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_advection_free_stream.jl" begin +@trixi_testset "elixir_advection_free_stream.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_free_stream.jl"), - l2 = [6.8925194184204476e-15], - linf = [9.903189379656396e-14]) - end + l2=[6.8925194184204476e-15], + linf=[9.903189379656396e-14]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_advection_nonperiodic.jl" begin +@trixi_testset "elixir_advection_nonperiodic.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_nonperiodic.jl"), - l2 = [0.00025552740731641223], - linf = [0.007252625722805939]) - end + l2=[0.00025552740731641223], + linf=[0.007252625722805939]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_advection_restart.jl" begin +@trixi_testset "elixir_advection_restart.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_restart.jl"), - l2 = [4.219208035582454e-6], - linf = [3.438434404412494e-5]) - end + l2=[4.219208035582454e-6], + linf=[3.438434404412494e-5], + # With the default `maxiters = 1` in coverage tests, + # there would be no time steps after the restart. + coverage_override=(maxiters = 100_000,)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_advection_restart.jl with waving flag mesh" begin +@trixi_testset "elixir_advection_restart.jl with waving flag mesh" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_restart.jl"), - l2 = [0.00016265538265929818], - linf = [0.0015194252169410394], - rtol = 5.0e-5, # Higher tolerance to make tests pass in CI (in particular with macOS) - elixir_file="elixir_advection_waving_flag.jl", - restart_file="restart_000021.h5") - end - - @trixi_testset "elixir_advection_restart.jl with free stream mesh" begin + l2=[0.00016265538265929818], + linf=[0.0015194252169410394], + rtol=5.0e-5, # Higher tolerance to make tests pass in CI (in particular with macOS) + elixir_file="elixir_advection_waving_flag.jl", + restart_file="restart_000021.h5", + # With the default `maxiters = 1` in coverage tests, + # there would be no time steps after the restart. + coverage_override=(maxiters = 100_000,)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_advection_restart.jl with free stream mesh" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_restart.jl"), - l2 = [7.841217436552029e-15], - linf = [1.0857981180834031e-13], - elixir_file="elixir_advection_free_stream.jl", - restart_file="restart_000036.h5") - end + l2=[7.841217436552029e-15], + linf=[1.0857981180834031e-13], + elixir_file="elixir_advection_free_stream.jl", + restart_file="restart_000036.h5", + # With the default `maxiters = 1` in coverage tests, + # there would be no time steps after the restart. + coverage_override=(maxiters = 100_000,)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_eulermulti_convergence_ec.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulermulti_convergence_ec.jl"), + l2=[ + 1.5123651627525257e-5, + 1.51236516273878e-5, + 2.4544918394022538e-5, + 5.904791661362391e-6, + 1.1809583322724782e-5, + ], + linf=[ + 8.393471747591974e-5, + 8.393471748258108e-5, + 0.00015028562494778797, + 3.504466610437795e-5, + 7.00893322087559e-5, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_source_terms.jl" begin +@trixi_testset "elixir_euler_source_terms.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms.jl"), - # Expected errors are exactly the same as with TreeMesh! - l2 = [9.321181253186009e-7, 1.4181210743438511e-6, 1.4181210743487851e-6, 4.824553091276693e-6], - linf = [9.577246529612893e-6, 1.1707525976012434e-5, 1.1707525976456523e-5, 4.8869615580926506e-5]) - end + # Expected errors are exactly the same as with TreeMesh! + l2=[ + 9.321181253186009e-7, + 1.4181210743438511e-6, + 1.4181210743487851e-6, + 4.824553091276693e-6, + ], + linf=[ + 9.577246529612893e-6, + 1.1707525976012434e-5, + 1.1707525976456523e-5, + 4.8869615580926506e-5, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @testset "elixir_euler_source_terms_rotated.jl" begin +@testset "elixir_euler_source_terms_rotated.jl" begin @trixi_testset "elixir_euler_source_terms_rotated.jl with α = 0.0" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms_rotated.jl"), - # Expected errors are exactly the same as in elixir_euler_source_terms! - l2 = [9.321181253186009e-7, 1.4181210743438511e-6, 1.4181210743487851e-6, 4.824553091276693e-6], - linf = [9.577246529612893e-6, 1.1707525976012434e-5, 1.1707525976456523e-5, 4.8869615580926506e-5], - alpha = 0.0) + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_source_terms_rotated.jl"), + # Expected errors are exactly the same as in elixir_euler_source_terms! + l2=[ + 9.321181253186009e-7, + 1.4181210743438511e-6, + 1.4181210743487851e-6, + 4.824553091276693e-6, + ], + linf=[ + 9.577246529612893e-6, + 1.1707525976012434e-5, + 1.1707525976456523e-5, + 4.8869615580926506e-5, + ], + alpha=0.0) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end end @trixi_testset "elixir_euler_source_terms_rotated.jl with α = 0.1" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms_rotated.jl"), - # Expected errors differ only slightly from elixir_euler_source_terms! - l2 = [9.321188057029291e-7, 1.3195106906473365e-6, 1.510307360354032e-6, 4.82455408101712e-6], - linf = [9.57723626271445e-6, 1.0480225511866337e-5, 1.2817828088262928e-5, 4.886962393513272e-5], - alpha = 0.1) + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_source_terms_rotated.jl"), + # Expected errors differ only slightly from elixir_euler_source_terms! + l2=[ + 9.321188057029291e-7, + 1.3195106906473365e-6, + 1.510307360354032e-6, + 4.82455408101712e-6, + ], + linf=[ + 9.57723626271445e-6, + 1.0480225511866337e-5, + 1.2817828088262928e-5, + 4.886962393513272e-5, + ], + alpha=0.1) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end end @trixi_testset "elixir_euler_source_terms_rotated.jl with α = 0.2 * pi" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms_rotated.jl"), - # Expected errors differ only slightly from elixir_euler_source_terms! - l2 = [9.32127973957391e-7, 8.477824799744325e-7, 1.8175286311402784e-6, 4.824562453521076e-6], - linf = [9.576898420737834e-6, 5.057704352218195e-6, 1.635260719945464e-5, 4.886978754825577e-5], - alpha = 0.2 * pi) + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_source_terms_rotated.jl"), + # Expected errors differ only slightly from elixir_euler_source_terms! + l2=[ + 9.32127973957391e-7, + 8.477824799744325e-7, + 1.8175286311402784e-6, + 4.824562453521076e-6, + ], + linf=[ + 9.576898420737834e-6, + 5.057704352218195e-6, + 1.635260719945464e-5, + 4.886978754825577e-5, + ], + alpha=0.2 * pi) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end end @trixi_testset "elixir_euler_source_terms_rotated.jl with α = 0.5 * pi" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms_rotated.jl"), - # Expected errors are exactly the same as in elixir_euler_source_terms! - l2 = [9.321181253186009e-7, 1.4181210743438511e-6, 1.4181210743487851e-6, 4.824553091276693e-6], - linf = [9.577246529612893e-6, 1.1707525976012434e-5, 1.1707525976456523e-5, 4.8869615580926506e-5], - alpha = 0.5 * pi) - end - end - - @trixi_testset "elixir_euler_source_terms_parallelogram.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms_parallelogram.jl"), - l2 = [1.1167802955144833e-5, 1.0805775514153104e-5, 1.953188337010932e-5, 5.5033856574857146e-5], - linf = [8.297006495561199e-5, 8.663281475951301e-5, 0.00012264160606778596, 0.00041818802502024965]) - end - - @trixi_testset "elixir_euler_source_terms_waving_flag.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms_waving_flag.jl"), - l2 = [2.991891317562739e-5, 3.6063177168283174e-5, 2.7082941743640572e-5, 0.00011414695350996946], - linf = [0.0002437454930492855, 0.0003438936171968887, 0.00024217622945688078, 0.001266380414757684]) - end - - @trixi_testset "elixir_euler_free_stream.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_source_terms_rotated.jl"), + # Expected errors are exactly the same as in elixir_euler_source_terms! + l2=[ + 9.321181253186009e-7, + 1.4181210743438511e-6, + 1.4181210743487851e-6, + 4.824553091276693e-6, + ], + linf=[ + 9.577246529612893e-6, + 1.1707525976012434e-5, + 1.1707525976456523e-5, + 4.8869615580926506e-5, + ], + alpha=0.5 * pi) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end + end +end + +@trixi_testset "elixir_euler_source_terms_parallelogram.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_source_terms_parallelogram.jl"), + l2=[ + 1.1167802955144833e-5, + 1.0805775514153104e-5, + 1.953188337010932e-5, + 5.5033856574857146e-5, + ], + linf=[ + 8.297006495561199e-5, + 8.663281475951301e-5, + 0.00012264160606778596, + 0.00041818802502024965, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_source_terms_waving_flag.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_source_terms_waving_flag.jl"), + l2=[ + 2.991891317562739e-5, + 3.6063177168283174e-5, + 2.7082941743640572e-5, + 0.00011414695350996946, + ], + linf=[ + 0.0002437454930492855, + 0.0003438936171968887, + 0.00024217622945688078, + 0.001266380414757684, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_free_stream.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_free_stream.jl"), - l2 = [2.063350241405049e-15, 1.8571016296925367e-14, 3.1769447886391905e-14, 1.4104095258528071e-14], - linf = [1.9539925233402755e-14, 2.9791447087035294e-13, 6.502853810985698e-13, 2.7000623958883807e-13], - atol = 7.0e-13) - end + l2=[ + 2.063350241405049e-15, + 1.8571016296925367e-14, + 3.1769447886391905e-14, + 1.4104095258528071e-14, + ], + linf=[ + 1.9539925233402755e-14, + 2.9791447087035294e-13, + 6.502853810985698e-13, + 2.7000623958883807e-13, + ], + atol=7.0e-13) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_free_stream.jl with FluxRotated(flux_lax_friedrichs)" begin +@trixi_testset "elixir_euler_free_stream.jl with FluxRotated(flux_lax_friedrichs)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_free_stream.jl"), - surface_flux=FluxRotated(flux_lax_friedrichs), - l2 = [2.063350241405049e-15, 1.8571016296925367e-14, 3.1769447886391905e-14, 1.4104095258528071e-14], - linf = [1.9539925233402755e-14, 2.9791447087035294e-13, 6.502853810985698e-13, 2.7000623958883807e-13], - atol = 7.0e-13) - end - - @trixi_testset "elixir_euler_source_terms_nonperiodic.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms_nonperiodic.jl"), - l2 = [2.259440511901724e-6, 2.3188881559075347e-6, 2.3188881559568146e-6, 6.332786324137878e-6], - linf = [1.4987382622067003e-5, 1.918201192063762e-5, 1.918201192019353e-5, 6.052671713430158e-5]) - end - - @trixi_testset "elixir_euler_ec.jl" begin + surface_flux=FluxRotated(flux_lax_friedrichs), + l2=[ + 2.063350241405049e-15, + 1.8571016296925367e-14, + 3.1769447886391905e-14, + 1.4104095258528071e-14, + ], + linf=[ + 1.9539925233402755e-14, + 2.9791447087035294e-13, + 6.502853810985698e-13, + 2.7000623958883807e-13, + ], + atol=7.0e-13) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_source_terms_nonperiodic.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_source_terms_nonperiodic.jl"), + l2=[ + 2.259440511901724e-6, + 2.3188881559075347e-6, + 2.3188881559568146e-6, + 6.332786324137878e-6, + ], + linf=[ + 1.4987382622067003e-5, + 1.918201192063762e-5, + 1.918201192019353e-5, + 6.052671713430158e-5, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_ec.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_ec.jl"), - l2 = [0.03774907669925568, 0.02845190575242045, 0.028262802829412605, 0.13785915638851698], - linf = [0.3368296929764073, 0.27644083771519773, 0.27990039685141377, 1.1971436487402016], - tspan = (0.0, 0.3)) - end + l2=[ + 0.03774907669925568, + 0.02845190575242045, + 0.028262802829412605, + 0.13785915638851698, + ], + linf=[ + 0.3368296929764073, + 0.27644083771519773, + 0.27990039685141377, + 1.1971436487402016, + ], + tspan=(0.0, 0.3)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_sedov.jl" begin +@trixi_testset "elixir_euler_sedov.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov.jl"), - l2 = [3.69856202e-01, 2.35242180e-01, 2.41444928e-01, 1.28807120e+00], - linf = [1.82786223e+00, 1.30452904e+00, 1.40347257e+00, 6.21791658e+00], - tspan = (0.0, 0.3)) - end - - @trixi_testset "elixir_euler_rayleigh_taylor_instability.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_rayleigh_taylor_instability.jl"), - l2 = [0.06365630381017849, 0.007166887387738937, 0.002878708825497772, 0.010247678114070121], - linf = [0.4799214336153155, 0.024595483032220266, 0.02059808120543466, 0.03190756362943725], - cells_per_dimension = (8,8), - tspan = (0.0, 0.3)) - end - - @trixi_testset "elixir_hypdiff_nonperiodic.jl" begin + l2=[ + 3.69856202e-01, + 2.35242180e-01, + 2.41444928e-01, + 1.28807120e+00, + ], + linf=[ + 1.82786223e+00, + 1.30452904e+00, + 1.40347257e+00, + 6.21791658e+00, + ], + tspan=(0.0, 0.3)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_rayleigh_taylor_instability.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_rayleigh_taylor_instability.jl"), + l2=[ + 0.06365630381017849, + 0.007166887387738937, + 0.002878708825497772, + 0.010247678114070121, + ], + linf=[ + 0.4799214336153155, + 0.024595483032220266, + 0.02059808120543466, + 0.03190756362943725, + ], + cells_per_dimension=(8, 8), + tspan=(0.0, 0.3)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_eulerpolytropic_convergence.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulerpolytropic_convergence.jl"), + l2=[ + 0.0016688820596537988, + 0.0025921681885685425, + 0.003280950351435014, + ], + linf=[ + 0.010994679664394269, + 0.01331197845637, + 0.020080117011346488, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_eulerpolytropic_convergence.jl: HLL(Davis)" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulerpolytropic_convergence.jl"), + solver=DGSEM(polydeg = 3, + surface_flux = FluxHLL(min_max_speed_davis), + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)), + l2=[ + 0.0016689832177644243, 0.0025920263793104445, + 0.003281074494629298, + ], + linf=[ + 0.01099488320190023, 0.013309526619350365, + 0.02008032661117909, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_eulerpolytropic_ec.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulerpolytropic_ec.jl"), + l2=[ + 0.03647890611450939, + 0.025284915444045052, + 0.025340697771609126, + ], + linf=[ + 0.32516731565355583, + 0.37509762516540046, + 0.29812843284727336, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_eulerpolytropic_isothermal_wave.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_eulerpolytropic_isothermal_wave.jl"), + l2=[ + 0.004998778491726366, + 0.004998916000294425, + 9.259136963058664e-17, + ], + linf=[ + 0.010001103673834888, + 0.010051165098399503, + 7.623942913643681e-16, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_eulerpolytropic_wave.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulerpolytropic_wave.jl"), + l2=[ + 0.23642682112204072, + 0.20904264390331334, + 8.174982691297391e-17, + ], + linf=[ + 0.4848250368349989, + 0.253350873815695, + 4.984552457753618e-16, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_hypdiff_nonperiodic.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_hypdiff_nonperiodic.jl"), - l2 = [0.8799744480157664, 0.8535008397034816, 0.7851383019164209], - linf = [1.0771947577311836, 1.9143913544309838, 2.149549109115789], - tspan = (0.0, 0.1), - coverage_override = (polydeg=3,)) # Prevent long compile time in CI - end - - @trixi_testset "elixir_hypdiff_harmonic_nonperiodic.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_hypdiff_harmonic_nonperiodic.jl"), - l2 = [0.19357947606509474, 0.47041398037626814, 0.4704139803762686], - linf = [0.35026352556630114, 0.8344372248051408, 0.8344372248051408], - tspan = (0.0, 0.1), - coverage_override = (polydeg=3,)) # Prevent long compile time in CI - end - - @trixi_testset "elixir_mhd_ec.jl" begin + l2=[0.8799744480157664, 0.8535008397034816, 0.7851383019164209], + linf=[1.0771947577311836, 1.9143913544309838, 2.149549109115789], + tspan=(0.0, 0.1), + coverage_override=(polydeg = 3,)) # Prevent long compile time in CI + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 + end +end + +@trixi_testset "elixir_hypdiff_harmonic_nonperiodic.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_hypdiff_harmonic_nonperiodic.jl"), + l2=[ + 0.19357947606509474, + 0.47041398037626814, + 0.4704139803762686, + ], + linf=[ + 0.35026352556630114, + 0.8344372248051408, + 0.8344372248051408, + ], + tspan=(0.0, 0.1), + coverage_override=(polydeg = 3,)) # Prevent long compile time in CI + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_mhd_ec.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_ec.jl"), - l2 = [0.04937480811868297, 0.06117033019988596, 0.060998028674664716, 0.03155145889799417, - 0.2319175391388658, 0.02476283192966346, 0.024483244374818587, 0.035439957899127385, - 0.0016022148194667542], - linf = [0.24749024430983746, 0.2990608279625713, 0.3966937932860247, 0.22265033744519683, - 0.9757376320946505, 0.12123736788315098, 0.12837436699267113, 0.17793825293524734, - 0.03460761690059514], - tspan = (0.0, 0.3)) - end - - @trixi_testset "elixir_mhd_alfven_wave.jl" begin + l2=[0.04937480811868297, 0.06117033019988596, + 0.060998028674664716, 0.03155145889799417, + 0.2319175391388658, 0.02476283192966346, + 0.024483244374818587, 0.035439957899127385, + 0.0016022148194667542], + linf=[0.24749024430983746, 0.2990608279625713, + 0.3966937932860247, 0.22265033744519683, + 0.9757376320946505, 0.12123736788315098, + 0.12837436699267113, 0.17793825293524734, + 0.03460761690059514], + tspan=(0.0, 0.3)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_mhd_alfven_wave.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_alfven_wave.jl"), - l2 = [0.02890769490562535, 0.0062599448721613205, 0.005650300017676721, 0.007334415940022972, - 0.00490446035599909, 0.007202284100220619, 0.007003258686714405, 0.006734267830082687, - 0.004253003868791559], - linf = [0.17517380432288565, 0.06197353710696667, 0.038494840938641646, 0.05293345499813148, - 0.03817506476831778, 0.042847170999492534, 0.03761563456810613, 0.048184237474911844, - 0.04114666955364693], - tspan = (0.0, 1.0)) - end - - @trixi_testset "elixir_shallowwater_source_terms.jl" begin + l2=[0.02890769490562535, 0.0062599448721613205, + 0.005650300017676721, 0.007334415940022972, + 0.00490446035599909, 0.007202284100220619, + 0.007003258686714405, 0.006734267830082687, + 0.004253003868791559], + linf=[0.17517380432288565, 0.06197353710696667, + 0.038494840938641646, 0.05293345499813148, + 0.03817506476831778, 0.042847170999492534, + 0.03761563456810613, 0.048184237474911844, + 0.04114666955364693], + tspan=(0.0, 1.0)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_shallowwater_source_terms.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_source_terms.jl"), - l2 = [0.0017285599436729316, 0.025584610912606776, 0.028373834961180594, 6.274146767730866e-5], - linf = [0.012972309788264802, 0.108283714215621, 0.15831585777928936, 0.00018196759554722775], - tspan = (0.0, 0.05)) - end + l2=[ + 0.0017285599436729316, + 0.025584610912606776, + 0.028373834961180594, + 6.274146767730866e-5, + ], + linf=[ + 0.012972309788264802, + 0.108283714215621, + 0.15831585777928936, + 0.00018196759554722775, + ], + tspan=(0.0, 0.05)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_shallowwater_well_balanced.jl" begin +@trixi_testset "elixir_shallowwater_well_balanced.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_well_balanced.jl"), - l2 = [0.7920927046419308, 9.92129670988898e-15, 1.0118635033124588e-14, 0.7920927046419308], - linf = [2.408429868800133, 5.5835419986809516e-14, 5.448874313931364e-14, 2.4084298688001335], - tspan = (0.0, 0.25)) - end - - @trixi_testset "elixir_shallowwater_well_balanced_wet_dry.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_well_balanced_wet_dry.jl"), - l2 = [0.019731646454942086, 1.0694532773278277e-14, 1.1969913383405568e-14, 0.0771517260037954], - linf = [0.4999999999998892, 6.067153702623552e-14, 4.4849667259339357e-14, 1.9999999999999993], - tspan = (0.0, 0.25)) - end - - @trixi_testset "elixir_shallowwater_conical_island.jl" begin + l2=[ + 0.7920927046419308, + 9.92129670988898e-15, + 1.0118635033124588e-14, + 0.7920927046419308, + ], + linf=[ + 2.408429868800133, + 5.5835419986809516e-14, + 5.448874313931364e-14, + 2.4084298688001335, + ], + tspan=(0.0, 0.25)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_shallowwater_well_balanced_wet_dry.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_shallowwater_well_balanced_wet_dry.jl"), + l2=[ + 0.019731646454942086, + 1.0694532773278277e-14, + 1.1969913383405568e-14, + 0.0771517260037954, + ], + linf=[ + 0.4999999999998892, + 6.067153702623552e-14, + 4.4849667259339357e-14, + 1.9999999999999993, + ], + tspan=(0.0, 0.25)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_shallowwater_conical_island.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_conical_island.jl"), - l2 = [0.04593154164306353, 0.1644534881916908, 0.16445348819169076, 0.0011537702354532122], - linf = [0.21100717610846442, 0.9501592344310412, 0.950159234431041, 0.021790250683516296], - tspan = (0.0, 0.025)) - end + l2=[ + 0.04593154164306353, + 0.1644534881916908, + 0.16445348819169076, + 0.0011537702354532122, + ], + linf=[ + 0.21100717610846442, + 0.9501592344310412, + 0.950159234431041, + 0.021790250683516296, + ], + tspan=(0.0, 0.025)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_shallowwater_parabolic_bowl.jl" begin +@trixi_testset "elixir_shallowwater_parabolic_bowl.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_parabolic_bowl.jl"), - l2 = [0.00015285369980313484, 1.9536806395943226e-5, 9.936906607758672e-5, 5.0686313334616055e-15], - linf = [0.003316119030459211, 0.0005075409427972817, 0.001986721761060583, 4.701794509287538e-14], - tspan = (0.0, 0.025), cells_per_dimension = (40, 40)) - end + l2=[ + 0.00015285369980313484, + 1.9536806395943226e-5, + 9.936906607758672e-5, + 5.0686313334616055e-15, + ], + linf=[ + 0.003316119030459211, + 0.0005075409427972817, + 0.001986721761060583, + 4.701794509287538e-14, + ], + tspan=(0.0, 0.025), cells_per_dimension=(40, 40)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_mhd_ec_shockcapturing.jl" begin +@trixi_testset "elixir_mhd_ec_shockcapturing.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_ec_shockcapturing.jl"), - l2 = [0.0364192725149364, 0.0426667193422069, 0.04261673001449095, 0.025884071405646924, - 0.16181626564020496, 0.017346518770783536, 0.017291573200291104, 0.026856206495339655, - 0.0007443858043598808], - linf = [0.25144373906033013, 0.32881947152723745, 0.3053266801502693, 0.20989755319972866, - 0.9927517314507455, 0.1105172121361323, 0.1257708104676617, 0.1628334844841588, - 0.02624301627479052]) - end + l2=[0.0364192725149364, 0.0426667193422069, 0.04261673001449095, + 0.025884071405646924, + 0.16181626564020496, 0.017346518770783536, + 0.017291573200291104, 0.026856206495339655, + 0.0007443858043598808], + linf=[0.25144373906033013, 0.32881947152723745, + 0.3053266801502693, 0.20989755319972866, + 0.9927517314507455, 0.1105172121361323, 0.1257708104676617, + 0.1628334844841588, + 0.02624301627479052]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end end # Clean up afterwards: delete Trixi.jl output directory -@test_nowarn rm(outdir, recursive=true) +@test_nowarn rm(outdir, recursive = true) end # module diff --git a/test/test_structured_3d.jl b/test/test_structured_3d.jl index 124c073f2d6..a52c459d6be 100644 --- a/test/test_structured_3d.jl +++ b/test/test_structured_3d.jl @@ -9,128 +9,334 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "structured_3d_dgsem") # Start with a clean environment: remove Trixi.jl output directory if it exists outdir = "out" -isdir(outdir) && rm(outdir, recursive=true) +isdir(outdir) && rm(outdir, recursive = true) @testset "Structured mesh" begin - @trixi_testset "elixir_advection_basic.jl" begin +#! format: noindent + +@trixi_testset "elixir_advection_basic.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_basic.jl"), - # Expected errors are exactly the same as with TreeMesh! - l2 = [0.00016263963870641478], - linf = [0.0014537194925779984]) - end + # Expected errors are exactly the same as with TreeMesh! + l2=[0.00016263963870641478], + linf=[0.0014537194925779984]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_advection_free_stream.jl" begin +@trixi_testset "elixir_advection_free_stream.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_free_stream.jl"), - l2 = [1.2908196366970896e-14], - linf = [1.0262901639634947e-12], - atol = 8e-13, # required to make tests pass on Windows - ) - end - - @trixi_testset "elixir_advection_nonperiodic_curved.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_nonperiodic_curved.jl"), - l2 = [0.0004483892474201268], - linf = [0.009201820593762955]) - end - - @trixi_testset "elixir_advection_restart.jl" begin + l2=[1.2908196366970896e-14], + linf=[1.0262901639634947e-12], + atol=8e-13,) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_advection_nonperiodic_curved.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_advection_nonperiodic_curved.jl"), + l2=[0.0004483892474201268], + linf=[0.009201820593762955]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_advection_restart.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_restart.jl"), - l2 = [0.0025903889347585777], - linf = [0.018407576968841655]) - end + l2=[0.0025903889347585777], + linf=[0.018407576968841655], + # With the default `maxiters = 1` in coverage tests, + # there would be no time steps after the restart. + coverage_override=(maxiters = 100_000,)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_source_terms.jl" begin +@trixi_testset "elixir_euler_source_terms.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms.jl"), - # Expected errors are exactly the same as with TreeMesh! - l2 = [0.010385936842224346, 0.009776048833895767, 0.00977604883389591, 0.009776048833895733, 0.01506687097416608], - linf = [0.03285848350791731, 0.0321792316408982, 0.032179231640894645, 0.032179231640895534, 0.0655408023333299]) - end + # Expected errors are exactly the same as with TreeMesh! + l2=[ + 0.010385936842224346, + 0.009776048833895767, + 0.00977604883389591, + 0.009776048833895733, + 0.01506687097416608, + ], + linf=[ + 0.03285848350791731, + 0.0321792316408982, + 0.032179231640894645, + 0.032179231640895534, + 0.0655408023333299, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_free_stream.jl" begin +@trixi_testset "elixir_euler_free_stream.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_free_stream.jl"), - l2 = [2.8815700334367128e-15, 9.361915278236651e-15, 9.95614203619935e-15, 1.6809941842374106e-14, 1.4815037041566735e-14], - linf = [4.1300296516055823e-14, 2.0444756998472258e-13, 1.0133560657266116e-13, 2.0627943797535409e-13, 2.8954616482224083e-13]) - end + l2=[ + 2.8815700334367128e-15, + 9.361915278236651e-15, + 9.95614203619935e-15, + 1.6809941842374106e-14, + 1.4815037041566735e-14, + ], + linf=[ + 4.1300296516055823e-14, + 2.0444756998472258e-13, + 1.0133560657266116e-13, + 2.0627943797535409e-13, + 2.8954616482224083e-13, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_free_stream.jl with FluxRotated(flux_lax_friedrichs)" begin +@trixi_testset "elixir_euler_free_stream.jl with FluxRotated(flux_lax_friedrichs)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_free_stream.jl"), - surface_flux=FluxRotated(flux_lax_friedrichs), - l2 = [2.8815700334367128e-15, 9.361915278236651e-15, 9.95614203619935e-15, 1.6809941842374106e-14, 1.4815037041566735e-14], - linf = [4.1300296516055823e-14, 2.0444756998472258e-13, 1.0133560657266116e-13, 2.0627943797535409e-13, 2.8954616482224083e-13]) - end - - @trixi_testset "elixir_euler_source_terms_nonperiodic_curved.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms_nonperiodic_curved.jl"), - l2 = [0.0032940531178824463, 0.003275679548217804, 0.0030020672748714084, 0.00324007343451744, 0.005721986362580164], - linf = [0.03156756290660656, 0.033597629023726316, 0.02095783702361409, 0.03353574465232212, 0.05873635745032857]) - end - - @trixi_testset "elixir_euler_ec.jl" begin + surface_flux=FluxRotated(flux_lax_friedrichs), + l2=[ + 2.8815700334367128e-15, + 9.361915278236651e-15, + 9.95614203619935e-15, + 1.6809941842374106e-14, + 1.4815037041566735e-14, + ], + linf=[ + 4.1300296516055823e-14, + 2.0444756998472258e-13, + 1.0133560657266116e-13, + 2.0627943797535409e-13, + 2.8954616482224083e-13, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_source_terms_nonperiodic_curved.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_source_terms_nonperiodic_curved.jl"), + l2=[ + 0.0032940531178824463, + 0.003275679548217804, + 0.0030020672748714084, + 0.00324007343451744, + 0.005721986362580164, + ], + linf=[ + 0.03156756290660656, + 0.033597629023726316, + 0.02095783702361409, + 0.03353574465232212, + 0.05873635745032857, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_ec.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_ec.jl"), - l2 = [0.011367083018614027, 0.007022020327490176, 0.006759580335962235, 0.006820337637760632, 0.02912659127566544], - linf = [0.2761764220925329, 0.20286331858055706, 0.18763944865434593, 0.19313636558790004, 0.707563913727584], - tspan = (0.0, 0.25), - coverage_override = (polydeg=3,)) # Prevent long compile time in CI - end + l2=[ + 0.011367083018614027, + 0.007022020327490176, + 0.006759580335962235, + 0.006820337637760632, + 0.02912659127566544, + ], + linf=[ + 0.2761764220925329, + 0.20286331858055706, + 0.18763944865434593, + 0.19313636558790004, + 0.707563913727584, + ], + tspan=(0.0, 0.25), + coverage_override=(polydeg = 3,)) # Prevent long compile time in CI + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_sedov.jl" begin +@trixi_testset "elixir_euler_sedov.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov.jl"), - l2 = [5.30310390e-02, 2.53167260e-02, 2.64276438e-02, 2.52195992e-02, 3.56830295e-01], - linf = [6.16356950e-01, 2.50600049e-01, 2.74796377e-01, 2.46448217e-01, 4.77888479e+00], - tspan = (0.0, 0.3)) - end + l2=[ + 5.30310390e-02, + 2.53167260e-02, + 2.64276438e-02, + 2.52195992e-02, + 3.56830295e-01, + ], + linf=[ + 6.16356950e-01, + 2.50600049e-01, + 2.74796377e-01, + 2.46448217e-01, + 4.77888479e+00, + ], + tspan=(0.0, 0.3)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_mhd_ec.jl" begin +@trixi_testset "elixir_mhd_ec.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_ec.jl"), - l2 = [0.009082353036644902, 0.007128360240528109, 0.006970330025996491, 0.006898850266874514, - 0.03302008823756457, 0.003203389099143526, 0.003077498677885352, 0.0030740006760477624, - 4.192129696970217e-5], - linf = [0.2883946030582689, 0.25956437344015054, 0.2614364943543665, 0.24617277938134657, - 1.1370443512475847, 0.1278041831463388, 0.13347391885068594, 0.1457563463643099, - 0.0021174246048172563], - tspan = (0.0, 0.25)) - end - - @trixi_testset "elixir_mhd_alfven_wave.jl" begin + l2=[0.009082353036644902, 0.007128360240528109, + 0.006970330025996491, 0.006898850266874514, + 0.03302008823756457, 0.003203389099143526, + 0.003077498677885352, 0.0030740006760477624, + 4.192129696970217e-5], + linf=[0.2883946030582689, 0.25956437344015054, + 0.2614364943543665, 0.24617277938134657, + 1.1370443512475847, 0.1278041831463388, 0.13347391885068594, + 0.1457563463643099, + 0.0021174246048172563], + tspan=(0.0, 0.25)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_mhd_alfven_wave.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_alfven_wave.jl"), - l2 = [0.003015476175153681, 0.00145499403283373, 0.0009125744757935803, 0.0017703080480578979, - 0.0013046447673965966, 0.0014564863387645508, 0.0013332311430907598, 0.001647832598455728, - 0.0013647609788548722], - linf = [0.027510637768610846, 0.02797062834945721, 0.01274249949295704, 0.038940694415543736, - 0.02200825678588325, 0.03167600959583505, 0.021420957993862344, 0.03386589835999665, - 0.01888303191983353], - # Use same polydeg as everything else to prevent long compile times in CI - coverage_override = (polydeg=3,)) - end - - @trixi_testset "elixir_mhd_alfven_wave.jl with flux_lax_friedrichs" begin + l2=[0.003015476175153681, 0.00145499403283373, + 0.0009125744757935803, 0.0017703080480578979, + 0.0013046447673965966, 0.0014564863387645508, + 0.0013332311430907598, 0.001647832598455728, + 0.0013647609788548722], + linf=[0.027510637768610846, 0.02797062834945721, + 0.01274249949295704, 0.038940694415543736, + 0.02200825678588325, 0.03167600959583505, + 0.021420957993862344, 0.03386589835999665, + 0.01888303191983353], + # Use same polydeg as everything else to prevent long compile times in CI + coverage_override=(polydeg = 3,)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_mhd_alfven_wave.jl with flux_lax_friedrichs" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_alfven_wave.jl"), - l2 = [0.003047854479955232, 0.0014572199588782184, 0.0009093737183251411, 0.0017937548694553895, - 0.0013010437110755424, 0.0014545607744895874, 0.001328514015121245, 0.001671342529206066, - 0.0013653963058149186], - linf = [0.027719103797310463, 0.027570111789910784, 0.012561901006903103, 0.03903568568480584, - 0.021311996934554767, 0.03154849824135775, 0.020996033645485412, 0.03403185137382961, - 0.019488952445771597], - surface_flux = (flux_lax_friedrichs, flux_nonconservative_powell), - # Use same polydeg as everything else to prevent long compile times in CI - coverage_override = (polydeg=3,)) - end - - @trixi_testset "elixir_mhd_ec_shockcapturing.jl" begin + l2=[0.003047854479955232, 0.0014572199588782184, + 0.0009093737183251411, 0.0017937548694553895, + 0.0013010437110755424, 0.0014545607744895874, + 0.001328514015121245, 0.001671342529206066, + 0.0013653963058149186], + linf=[0.027719103797310463, 0.027570111789910784, + 0.012561901006903103, 0.03903568568480584, + 0.021311996934554767, 0.03154849824135775, + 0.020996033645485412, 0.03403185137382961, + 0.019488952445771597], + surface_flux=(flux_lax_friedrichs, flux_nonconservative_powell), + # Use same polydeg as everything else to prevent long compile times in CI + coverage_override=(polydeg = 3,)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_mhd_ec_shockcapturing.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_ec_shockcapturing.jl"), - l2 = [0.009352631220872144, 0.008058649103542618, 0.008027041293333663, 0.008071417851552725, - 0.034909149665869485, 0.00393019428600812, 0.0039219074393817, 0.003906321245184237, - 4.197255300781248e-5], - linf = [0.30749098250807516, 0.2679008863509767, 0.271243087484388, 0.26545396569129537, - 0.9620950892188596, 0.18163281157498123, 0.15995708312378454, 0.17918221526906408, - 0.015138346608166353], - tspan = (0.0, 0.25), - # Use same polydeg as everything else to prevent long compile times in CI - coverage_override = (polydeg=3,)) - end + l2=[0.009352631220872144, 0.008058649103542618, + 0.008027041293333663, 0.008071417851552725, + 0.034909149665869485, 0.00393019428600812, + 0.0039219074393817, 0.003906321245184237, + 4.197255300781248e-5], + linf=[0.30749098250807516, 0.2679008863509767, + 0.271243087484388, 0.26545396569129537, + 0.9620950892188596, 0.18163281157498123, + 0.15995708312378454, 0.17918221526906408, + 0.015138346608166353], + tspan=(0.0, 0.25), + # Use same polydeg as everything else to prevent long compile times in CI + coverage_override=(polydeg = 3,)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end end # Clean up afterwards: delete Trixi.jl output directory -@test_nowarn rm(outdir, recursive=true) +@test_nowarn rm(outdir, recursive = true) end # module diff --git a/test/test_t8code_2d.jl b/test/test_t8code_2d.jl index 4f222dcb336..b3e19471323 100644 --- a/test/test_t8code_2d.jl +++ b/test/test_t8code_2d.jl @@ -13,175 +13,265 @@ isdir(outdir) && rm(outdir, recursive = true) mkdir(outdir) @testset "T8codeMesh2D" begin - @trixi_testset "test save_mesh_file" begin - @test_throws Exception begin - # Save mesh file support will be added in the future. The following - # lines of code are here for satisfying code coverage. - - # Create dummy mesh. - mesh = T8codeMesh((1, 1), polydeg = 1, - mapping = Trixi.coordinates2mapping((-1.0, -1.0), (1.0, 1.0)), - initial_refinement_level = 1) - - # This call throws an error. - Trixi.save_mesh_file(mesh, "dummy") - end +#! format: noindent + +@trixi_testset "test save_mesh_file" begin + @test_throws Exception begin + # Save mesh file support will be added in the future. The following + # lines of code are here for satisfying code coverage. + + # Create dummy mesh. + mesh = T8codeMesh((1, 1), polydeg = 1, + mapping = Trixi.coordinates2mapping((-1.0, -1.0), (1.0, 1.0)), + initial_refinement_level = 1) + + # This call throws an error. + Trixi.save_mesh_file(mesh, "dummy") end +end - @trixi_testset "elixir_advection_basic.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_basic.jl"), - # Expected errors are exactly the same as with TreeMesh! - l2=[8.311947673061856e-6], - linf=[6.627000273229378e-5]) +@trixi_testset "elixir_advection_basic.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_basic.jl"), + # Expected errors are exactly the same as with TreeMesh! + l2=[8.311947673061856e-6], + linf=[6.627000273229378e-5]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 end +end - @trixi_testset "elixir_advection_nonconforming_flag.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, - "elixir_advection_nonconforming_flag.jl"), - l2=[3.198940059144588e-5], - linf=[0.00030636069494005547]) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 - end +@trixi_testset "elixir_advection_nonconforming_flag.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_advection_nonconforming_flag.jl"), + l2=[3.198940059144588e-5], + linf=[0.00030636069494005547]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 end +end - @trixi_testset "elixir_advection_unstructured_flag.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_unstructured_flag.jl"), - l2=[0.0005379687442422346], - linf=[0.007438525029884735]) +@trixi_testset "elixir_advection_unstructured_flag.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_unstructured_flag.jl"), + l2=[0.0005379687442422346], + linf=[0.007438525029884735]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 end +end - @trixi_testset "elixir_advection_amr_unstructured_flag.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, - "elixir_advection_amr_unstructured_flag.jl"), - l2=[0.001993165013217687], - linf=[0.032891018571625796], - coverage_override=(maxiters = 6,)) +@trixi_testset "elixir_advection_amr_unstructured_flag.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_advection_amr_unstructured_flag.jl"), + l2=[0.001993165013217687], + linf=[0.032891018571625796], + coverage_override=(maxiters = 6,)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 end +end - @trixi_testset "elixir_advection_amr_solution_independent.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, - "elixir_advection_amr_solution_independent.jl"), - # Expected errors are exactly the same as with StructuredMesh! - l2=[4.949660644033807e-5], - linf=[0.0004867846262313763], - coverage_override=(maxiters = 6,)) +@trixi_testset "elixir_advection_amr_solution_independent.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_advection_amr_solution_independent.jl"), + # Expected errors are exactly the same as with StructuredMesh! + l2=[4.949660644033807e-5], + linf=[0.0004867846262313763], + coverage_override=(maxiters = 6,)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 end +end - @trixi_testset "elixir_euler_source_terms_nonconforming_unstructured_flag.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, - "elixir_euler_source_terms_nonconforming_unstructured_flag.jl"), - l2=[ - 0.0034516244508588046, - 0.0023420334036925493, - 0.0024261923964557187, - 0.004731710454271893, - ], - linf=[ - 0.04155789011775046, - 0.024772109862748914, - 0.03759938693042297, - 0.08039824959535657, - ]) +@trixi_testset "elixir_euler_source_terms_nonconforming_unstructured_flag.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_source_terms_nonconforming_unstructured_flag.jl"), + l2=[ + 0.0034516244508588046, + 0.0023420334036925493, + 0.0024261923964557187, + 0.004731710454271893, + ], + linf=[ + 0.04155789011775046, + 0.024772109862748914, + 0.03759938693042297, + 0.08039824959535657, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 end +end - @trixi_testset "elixir_euler_free_stream.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_free_stream.jl"), - l2=[ - 2.063350241405049e-15, - 1.8571016296925367e-14, - 3.1769447886391905e-14, - 1.4104095258528071e-14, - ], - linf=[1.9539925233402755e-14, 2e-12, 4.8e-12, 4e-12], - atol=2.0e-12,) +@trixi_testset "elixir_euler_free_stream.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_free_stream.jl"), + l2=[ + 2.063350241405049e-15, + 1.8571016296925367e-14, + 3.1769447886391905e-14, + 1.4104095258528071e-14, + ], + linf=[1.9539925233402755e-14, 2e-12, 4.8e-12, 4e-12], + atol=2.0e-12,) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 end +end - @trixi_testset "elixir_euler_shockcapturing_ec.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_shockcapturing_ec.jl"), - l2=[ - 9.53984675e-02, - 1.05633455e-01, - 1.05636158e-01, - 3.50747237e-01, - ], - linf=[ - 2.94357464e-01, - 4.07893014e-01, - 3.97334516e-01, - 1.08142520e+00, - ], - tspan=(0.0, 1.0)) +@trixi_testset "elixir_euler_shockcapturing_ec.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_shockcapturing_ec.jl"), + l2=[ + 9.53984675e-02, + 1.05633455e-01, + 1.05636158e-01, + 3.50747237e-01, + ], + linf=[ + 2.94357464e-01, + 4.07893014e-01, + 3.97334516e-01, + 1.08142520e+00, + ], + tspan=(0.0, 1.0)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 end +end - @trixi_testset "elixir_euler_sedov.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov.jl"), - l2=[ - 3.76149952e-01, - 2.46970327e-01, - 2.46970327e-01, - 1.28889042e+00, - ], - linf=[ - 1.22139001e+00, - 1.17742626e+00, - 1.17742626e+00, - 6.20638482e+00, - ], - tspan=(0.0, 0.3)) +@trixi_testset "elixir_euler_sedov.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov.jl"), + l2=[ + 3.76149952e-01, + 2.46970327e-01, + 2.46970327e-01, + 1.28889042e+00, + ], + linf=[ + 1.22139001e+00, + 1.17742626e+00, + 1.17742626e+00, + 6.20638482e+00, + ], + tspan=(0.0, 0.3)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 end +end - @trixi_testset "elixir_shallowwater_source_terms.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_source_terms.jl"), - l2=[ - 9.168126407325352e-5, - 0.0009795410115453788, - 0.002546408320320785, - 3.941189812642317e-6, - ], - linf=[ - 0.0009903782521019089, - 0.0059752684687262025, - 0.010941106525454103, - 1.2129488214718265e-5, - ], - tspan=(0.0, 0.1)) +@trixi_testset "elixir_shallowwater_source_terms.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_source_terms.jl"), + l2=[ + 9.168126407325352e-5, + 0.0009795410115453788, + 0.002546408320320785, + 3.941189812642317e-6, + ], + linf=[ + 0.0009903782521019089, + 0.0059752684687262025, + 0.010941106525454103, + 1.2129488214718265e-5, + ], + tspan=(0.0, 0.1)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 end +end - @trixi_testset "elixir_mhd_alfven_wave.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_alfven_wave.jl"), - l2=[1.0513414461545583e-5, 1.0517900957166411e-6, - 1.0517900957304043e-6, 1.511816606372376e-6, - 1.0443997728645063e-6, 7.879639064990798e-7, - 7.879639065049896e-7, 1.0628631669056271e-6, - 4.3382328912336153e-7], - linf=[4.255466285174592e-5, 1.0029706745823264e-5, - 1.0029706747467781e-5, 1.2122265939010224e-5, - 5.4791097160444835e-6, 5.18922042269665e-6, - 5.189220422141538e-6, 9.552667261422676e-6, - 1.4237578427628152e-6]) +@trixi_testset "elixir_mhd_alfven_wave.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_alfven_wave.jl"), + l2=[1.0513414461545583e-5, 1.0517900957166411e-6, + 1.0517900957304043e-6, 1.511816606372376e-6, + 1.0443997728645063e-6, 7.879639064990798e-7, + 7.879639065049896e-7, 1.0628631669056271e-6, + 4.3382328912336153e-7], + linf=[4.255466285174592e-5, 1.0029706745823264e-5, + 1.0029706747467781e-5, 1.2122265939010224e-5, + 5.4791097160444835e-6, 5.18922042269665e-6, + 5.189220422141538e-6, 9.552667261422676e-6, + 1.4237578427628152e-6]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 end +end - @trixi_testset "elixir_mhd_rotor.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_rotor.jl"), - l2=[0.44211360369891683, 0.8805178316216257, 0.8262710688468049, - 0.0, - 0.9616090460973586, 0.10386643568745411, - 0.15403457366543802, 0.0, - 2.8399715649715473e-5], - linf=[10.04369305341599, 17.995640564998403, 9.576041548174265, - 0.0, - 19.429658884314534, 1.3821395681242314, 1.818559351543182, - 0.0, - 0.002261930217575465], - tspan=(0.0, 0.02)) +@trixi_testset "elixir_mhd_rotor.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_rotor.jl"), + l2=[0.44211360369891683, 0.8805178316216257, 0.8262710688468049, + 0.0, + 0.9616090460973586, 0.10386643568745411, + 0.15403457366543802, 0.0, + 2.8399715649715473e-5], + linf=[10.04369305341599, 17.995640564998403, 9.576041548174265, + 0.0, + 19.429658884314534, 1.3821395681242314, 1.818559351543182, + 0.0, + 0.002261930217575465], + tspan=(0.0, 0.02)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 end end +end # Clean up afterwards: delete Trixi.jl output directory @test_nowarn rm(outdir, recursive = true) diff --git a/test/test_threaded.jl b/test/test_threaded.jl index 9b30836d0ed..dbbcbf4c7ce 100644 --- a/test/test_threaded.jl +++ b/test/test_threaded.jl @@ -7,327 +7,469 @@ include("test_trixi.jl") # Start with a clean environment: remove Trixi.jl output directory if it exists outdir = "out" -Trixi.mpi_isroot() && isdir(outdir) && rm(outdir, recursive=true) +Trixi.mpi_isroot() && isdir(outdir) && rm(outdir, recursive = true) @testset "Threaded tests" begin - @testset "TreeMesh" begin +#! format: noindent + +@testset "TreeMesh" begin @trixi_testset "elixir_advection_restart.jl" begin - @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", "elixir_advection_restart.jl"), - # Expected errors are exactly the same as in the serial test! - l2 = [7.81674284320524e-6], - linf = [6.314906965243505e-5]) + elixir = joinpath(examples_dir(), "tree_2d_dgsem", + "elixir_advection_extended.jl") + Trixi.mpi_isroot() && println("═"^100) + Trixi.mpi_isroot() && println(elixir) + trixi_include(@__MODULE__, elixir, tspan = (0.0, 10.0)) + l2_expected, linf_expected = analysis_callback(sol) + + elixir = joinpath(examples_dir(), "tree_2d_dgsem", + "elixir_advection_restart.jl") + Trixi.mpi_isroot() && println("═"^100) + Trixi.mpi_isroot() && println(elixir) + # Errors are exactly the same as in the elixir_advection_extended.jl + trixi_include(@__MODULE__, elixir) + l2_actual, linf_actual = analysis_callback(sol) + + Trixi.mpi_isroot() && @test l2_actual == l2_expected + Trixi.mpi_isroot() && @test linf_actual == linf_expected # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 5000 + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 5000 end end @trixi_testset "elixir_advection_restart.jl with threaded time integration" begin - @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", "elixir_advection_restart.jl"), - alg = CarpenterKennedy2N54(williamson_condition = false, thread = OrdinaryDiffEq.True()), - # Expected errors are exactly the same as in the serial test! - l2 = [7.81674284320524e-6], - linf = [6.314906965243505e-5]) + @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", + "elixir_advection_restart.jl"), + alg=CarpenterKennedy2N54(williamson_condition = false, + thread = OrdinaryDiffEq.True()), + # Expected errors are exactly the same as in the serial test! + l2=[8.005068880114254e-6], + linf=[6.39093577996519e-5]) end @trixi_testset "elixir_advection_amr_refine_twice.jl" begin - @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", "elixir_advection_amr_refine_twice.jl"), - l2 = [0.00020547512522578292], - linf = [0.007831753383083506]) + @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", + "elixir_advection_amr_refine_twice.jl"), + l2=[0.00020547512522578292], + linf=[0.007831753383083506]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 5000 + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 5000 end end @trixi_testset "elixir_advection_amr_coarsen_twice.jl" begin - @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", "elixir_advection_amr_coarsen_twice.jl"), - l2 = [0.0014321062757891826], - linf = [0.0253454486893413]) + @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", + "elixir_advection_amr_coarsen_twice.jl"), + l2=[0.0014321062757891826], + linf=[0.0253454486893413]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 5000 + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 5000 end end @trixi_testset "elixir_euler_source_terms_nonperiodic.jl" begin - @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", "elixir_euler_source_terms_nonperiodic.jl"), - l2 = [2.259440511766445e-6, 2.318888155713922e-6, 2.3188881557894307e-6, 6.3327863238858925e-6], - linf = [1.498738264560373e-5, 1.9182011928187137e-5, 1.918201192685487e-5, 6.0526717141407005e-5], - rtol = 0.001) + @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", + "elixir_euler_source_terms_nonperiodic.jl"), + l2=[ + 2.259440511766445e-6, + 2.318888155713922e-6, + 2.3188881557894307e-6, + 6.3327863238858925e-6, + ], + linf=[ + 1.498738264560373e-5, + 1.9182011928187137e-5, + 1.918201192685487e-5, + 6.0526717141407005e-5, + ], + rtol=0.001) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 5000 + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 5000 end end @trixi_testset "elixir_euler_ec.jl" begin - @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", "elixir_euler_ec.jl"), - l2 = [0.061751715597716854, 0.05018223615408711, 0.05018989446443463, 0.225871559730513], - linf = [0.29347582879608825, 0.31081249232844693, 0.3107380389947736, 1.0540358049885143]) + @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", + "elixir_euler_ec.jl"), + l2=[ + 0.061751715597716854, + 0.05018223615408711, + 0.05018989446443463, + 0.225871559730513, + ], + linf=[ + 0.29347582879608825, + 0.31081249232844693, + 0.3107380389947736, + 1.0540358049885143, + ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 5000 + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 5000 end end @trixi_testset "elixir_advection_diffusion.jl" begin - @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", "elixir_advection_diffusion.jl"), - initial_refinement_level = 2, tspan = (0.0, 0.4), polydeg = 5, - alg = RDPK3SpFSAL49(thread = OrdinaryDiffEq.True()), - l2 = [4.0915532997994255e-6], - linf = [2.3040850347877395e-5] - ) - - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 5000 - end + @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", + "elixir_advection_diffusion.jl"), + initial_refinement_level=2, tspan=(0.0, 0.4), polydeg=5, + alg=RDPK3SpFSAL49(thread = OrdinaryDiffEq.True()), + l2=[4.0915532997994255e-6], + linf=[2.3040850347877395e-5]) + + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 5000 + end end @trixi_testset "FDSBP, elixir_advection_extended.jl" begin - @test_trixi_include(joinpath(examples_dir(), "tree_2d_fdsbp", "elixir_advection_extended.jl"), - l2 = [2.898644263922225e-6], - linf = [8.491517930142578e-6], - rtol = 1.0e-7) # These results change a little bit and depend on the CI system - - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 5000 - end + @test_trixi_include(joinpath(examples_dir(), "tree_2d_fdsbp", + "elixir_advection_extended.jl"), + l2=[2.898644263922225e-6], + linf=[8.491517930142578e-6], + rtol=1.0e-7) # These results change a little bit and depend on the CI system + + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 5000 + end end @trixi_testset "FDSBP, elixir_euler_convergence.jl" begin - @test_trixi_include(joinpath(examples_dir(), "tree_2d_fdsbp", "elixir_euler_convergence.jl"), - l2 = [1.7088389997042244e-6, 1.7437997855125774e-6, 1.7437997855350776e-6, 5.457223460127621e-6], - linf = [9.796504903736292e-6, 9.614745892783105e-6, 9.614745892783105e-6, 4.026107182575345e-5], - tspan = (0.0, 0.1)) - - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 5000 - end - end - end + @test_trixi_include(joinpath(examples_dir(), "tree_2d_fdsbp", + "elixir_euler_convergence.jl"), + l2=[ + 1.7088389997042244e-6, + 1.7437997855125774e-6, + 1.7437997855350776e-6, + 5.457223460127621e-6, + ], + linf=[ + 9.796504903736292e-6, + 9.614745892783105e-6, + 9.614745892783105e-6, + 4.026107182575345e-5, + ], + tspan=(0.0, 0.1)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 5000 + end + end +end - @testset "StructuredMesh" begin +@testset "StructuredMesh" begin @trixi_testset "elixir_advection_restart.jl with waving flag mesh" begin - @test_trixi_include(joinpath(examples_dir(), "structured_2d_dgsem", "elixir_advection_restart.jl"), - l2 = [0.00016265538265929818], - linf = [0.0015194252169410394], - rtol = 5.0e-5, # Higher tolerance to make tests pass in CI (in particular with macOS) - elixir_file="elixir_advection_waving_flag.jl", - restart_file="restart_000021.h5") + @test_trixi_include(joinpath(examples_dir(), "structured_2d_dgsem", + "elixir_advection_restart.jl"), + l2=[0.00016265538265929818], + linf=[0.0015194252169410394], + rtol=5.0e-5, # Higher tolerance to make tests pass in CI (in particular with macOS) + elixir_file="elixir_advection_waving_flag.jl", + restart_file="restart_000021.h5", + # With the default `maxiters = 1` in coverage tests, + # there would be no time steps after the restart. + coverage_override=(maxiters = 100_000,)) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 5000 + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 5000 end end @trixi_testset "elixir_mhd_ec.jl" begin - @test_trixi_include(joinpath(examples_dir(), "structured_2d_dgsem", "elixir_mhd_ec.jl"), - l2 = [0.04937480811868297, 0.06117033019988596, 0.060998028674664716, 0.03155145889799417, - 0.2319175391388658, 0.02476283192966346, 0.024483244374818587, 0.035439957899127385, - 0.0016022148194667542], - linf = [0.24749024430983746, 0.2990608279625713, 0.3966937932860247, 0.22265033744519683, - 0.9757376320946505, 0.12123736788315098, 0.12837436699267113, 0.17793825293524734, - 0.03460761690059514], - tspan = (0.0, 0.3)) + @test_trixi_include(joinpath(examples_dir(), "structured_2d_dgsem", + "elixir_mhd_ec.jl"), + l2=[0.04937480811868297, 0.06117033019988596, + 0.060998028674664716, 0.03155145889799417, + 0.2319175391388658, 0.02476283192966346, + 0.024483244374818587, 0.035439957899127385, + 0.0016022148194667542], + linf=[0.24749024430983746, 0.2990608279625713, + 0.3966937932860247, 0.22265033744519683, + 0.9757376320946505, 0.12123736788315098, + 0.12837436699267113, 0.17793825293524734, + 0.03460761690059514], + tspan=(0.0, 0.3)) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 5000 + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 5000 end end - end - +end - @testset "UnstructuredMesh" begin +@testset "UnstructuredMesh" begin @trixi_testset "elixir_acoustics_gauss_wall.jl" begin - @test_trixi_include(joinpath(examples_dir(), "unstructured_2d_dgsem", "elixir_acoustics_gauss_wall.jl"), - l2 = [0.029330394861252995, 0.029345079728907965, 0.03803795043486467, 0.0, - 7.175152371650832e-16, 1.4350304743301665e-15, 1.4350304743301665e-15], - linf = [0.36236334472179443, 0.3690785638275256, 0.8475748723784078, 0.0, - 8.881784197001252e-16, 1.7763568394002505e-15, 1.7763568394002505e-15], - tspan = (0.0, 5.0)) + @test_trixi_include(joinpath(examples_dir(), "unstructured_2d_dgsem", + "elixir_acoustics_gauss_wall.jl"), + l2=[0.029330394861252995, 0.029345079728907965, + 0.03803795043486467, 0.0, + 7.175152371650832e-16, 1.4350304743301665e-15, + 1.4350304743301665e-15], + linf=[0.36236334472179443, 0.3690785638275256, + 0.8475748723784078, 0.0, + 8.881784197001252e-16, 1.7763568394002505e-15, + 1.7763568394002505e-15], + tspan=(0.0, 5.0)) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 5000 + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 5000 end end - end - +end - @testset "P4estMesh" begin +@testset "P4estMesh" begin @trixi_testset "elixir_euler_source_terms_nonconforming_unstructured_flag.jl" begin - @test_trixi_include(joinpath(examples_dir(), "p4est_2d_dgsem", "elixir_euler_source_terms_nonconforming_unstructured_flag.jl"), - l2 = [0.0034516244508588046, 0.0023420334036925493, 0.0024261923964557187, 0.004731710454271893], - linf = [0.04155789011775046, 0.024772109862748914, 0.03759938693042297, 0.08039824959535657]) + @test_trixi_include(joinpath(examples_dir(), "p4est_2d_dgsem", + "elixir_euler_source_terms_nonconforming_unstructured_flag.jl"), + l2=[ + 0.0034516244508588046, + 0.0023420334036925493, + 0.0024261923964557187, + 0.004731710454271893, + ], + linf=[ + 0.04155789011775046, + 0.024772109862748914, + 0.03759938693042297, + 0.08039824959535657, + ]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 5000 + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 5000 end end @trixi_testset "elixir_eulergravity_convergence.jl" begin - @test_trixi_include(joinpath(examples_dir(), "p4est_2d_dgsem", "elixir_eulergravity_convergence.jl"), - l2 = [0.00024871265138964204, 0.0003370077102132591, 0.0003370077102131964, 0.0007231525513793697], - linf = [0.0015813032944647087, 0.0020494288423820173, 0.0020494288423824614, 0.004793821195083758], - tspan = (0.0, 0.1)) + @test_trixi_include(joinpath(examples_dir(), "p4est_2d_dgsem", + "elixir_eulergravity_convergence.jl"), + l2=[ + 0.00024871265138964204, + 0.0003370077102132591, + 0.0003370077102131964, + 0.0007231525513793697, + ], + linf=[ + 0.0015813032944647087, + 0.0020494288423820173, + 0.0020494288423824614, + 0.004793821195083758, + ], + tspan=(0.0, 0.1)) end - end - +end - @testset "T8codeMesh" begin +@testset "T8codeMesh" begin @trixi_testset "elixir_euler_source_terms_nonconforming_unstructured_flag.jl" begin - @test_trixi_include(joinpath(examples_dir(), "t8code_2d_dgsem", "elixir_euler_source_terms_nonconforming_unstructured_flag.jl"), - l2 = [0.0034516244508588046, 0.0023420334036925493, 0.0024261923964557187, 0.004731710454271893], - linf = [0.04155789011775046, 0.024772109862748914, 0.03759938693042297, 0.08039824959535657]) + @test_trixi_include(joinpath(examples_dir(), "t8code_2d_dgsem", + "elixir_euler_source_terms_nonconforming_unstructured_flag.jl"), + l2=[ + 0.0034516244508588046, + 0.0023420334036925493, + 0.0024261923964557187, + 0.004731710454271893, + ], + linf=[ + 0.04155789011775046, + 0.024772109862748914, + 0.03759938693042297, + 0.08039824959535657, + ]) end @trixi_testset "elixir_eulergravity_convergence.jl" begin - @test_trixi_include(joinpath(examples_dir(), "t8code_2d_dgsem", "elixir_eulergravity_convergence.jl"), - l2 = [0.00024871265138964204, 0.0003370077102132591, 0.0003370077102131964, 0.0007231525513793697], - linf = [0.0015813032944647087, 0.0020494288423820173, 0.0020494288423824614, 0.004793821195083758], - tspan = (0.0, 0.1)) + @test_trixi_include(joinpath(examples_dir(), "t8code_2d_dgsem", + "elixir_eulergravity_convergence.jl"), + l2=[ + 0.00024871265138964204, + 0.0003370077102132591, + 0.0003370077102131964, + 0.0007231525513793697, + ], + linf=[ + 0.0015813032944647087, + 0.0020494288423820173, + 0.0020494288423824614, + 0.004793821195083758, + ], + tspan=(0.0, 0.1)) end - end - +end - @testset "DGMulti" begin +@testset "DGMulti" begin @trixi_testset "elixir_euler_weakform.jl (SBP, EC)" begin - @test_trixi_include(joinpath(examples_dir(), "dgmulti_2d", "elixir_euler_weakform.jl"), - cells_per_dimension = (4, 4), - volume_integral = VolumeIntegralFluxDifferencing(flux_ranocha), - surface_integral = SurfaceIntegralWeakForm(flux_ranocha), - approximation_type = SBP(), - l2 = [0.006400337855843578, 0.005303799804137764, 0.005303799804119745, 0.013204169007030144], - linf = [0.03798302318566282, 0.05321027922532284, 0.05321027922605448, 0.13392025411839015], - ) - - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 5000 - end + @test_trixi_include(joinpath(examples_dir(), "dgmulti_2d", + "elixir_euler_weakform.jl"), + cells_per_dimension=(4, 4), + volume_integral=VolumeIntegralFluxDifferencing(flux_ranocha), + surface_integral=SurfaceIntegralWeakForm(flux_ranocha), + approximation_type=SBP(), + l2=[ + 0.006400337855843578, + 0.005303799804137764, + 0.005303799804119745, + 0.013204169007030144, + ], + linf=[ + 0.03798302318566282, + 0.05321027922532284, + 0.05321027922605448, + 0.13392025411839015, + ],) + + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 5000 + end end @trixi_testset "elixir_euler_curved.jl with threaded time integration" begin - @test_trixi_include(joinpath(examples_dir(), "dgmulti_2d", "elixir_euler_curved.jl"), - alg = RDPK3SpFSAL49(thread = OrdinaryDiffEq.True()), - l2 = [1.720476068165337e-5, 1.592168205710526e-5, 1.592168205812963e-5, 4.894094865697305e-5], - linf = [0.00010525416930584619, 0.00010003778091061122, 0.00010003778085621029, 0.00036426282101720275] - ) - - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 5000 - end + @test_trixi_include(joinpath(examples_dir(), "dgmulti_2d", + "elixir_euler_curved.jl"), + alg=RDPK3SpFSAL49(thread = OrdinaryDiffEq.True()), + l2=[ + 1.720476068165337e-5, + 1.592168205710526e-5, + 1.592168205812963e-5, + 4.894094865697305e-5, + ], + linf=[ + 0.00010525416930584619, + 0.00010003778091061122, + 0.00010003778085621029, + 0.00036426282101720275, + ]) + + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 5000 + end end @trixi_testset "elixir_euler_triangulate_pkg_mesh.jl" begin - @test_trixi_include(joinpath(examples_dir(), "dgmulti_2d", "elixir_euler_triangulate_pkg_mesh.jl"), - l2 = [2.344080455438114e-6, 1.8610038753097983e-6, 2.4095165666095305e-6, 6.373308158814308e-6], - linf = [2.5099852761334418e-5, 2.2683684021362893e-5, 2.6180448559287584e-5, 5.5752932611508044e-5] - ) - - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - if (Threads.nthreads() < 2) || (VERSION < v"1.9") - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 5000 - else - @test_broken (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 5000 + @test_trixi_include(joinpath(examples_dir(), "dgmulti_2d", + "elixir_euler_triangulate_pkg_mesh.jl"), + l2=[ + 2.344080455438114e-6, + 1.8610038753097983e-6, + 2.4095165666095305e-6, + 6.373308158814308e-6, + ], + linf=[ + 2.5099852761334418e-5, + 2.2683684021362893e-5, + 2.6180448559287584e-5, + 5.5752932611508044e-5, + ]) + + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 5000 end - end end @trixi_testset "elixir_euler_fdsbp_periodic.jl" begin - @test_trixi_include(joinpath(examples_dir(), "dgmulti_2d", "elixir_euler_fdsbp_periodic.jl"), - l2 = [1.3333320340010056e-6, 2.044834627970641e-6, 2.044834627855601e-6, 5.282189803559564e-6], - linf = [2.7000151718858945e-6, 3.988595028259212e-6, 3.9885950273710336e-6, 8.848583042286862e-6] - ) - - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 5000 - end + @test_trixi_include(joinpath(examples_dir(), "dgmulti_2d", + "elixir_euler_fdsbp_periodic.jl"), + l2=[ + 1.3333320340010056e-6, + 2.044834627970641e-6, + 2.044834627855601e-6, + 5.282189803559564e-6, + ], + linf=[ + 2.7000151718858945e-6, + 3.988595028259212e-6, + 3.9885950273710336e-6, + 8.848583042286862e-6, + ]) + + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 5000 + end end - end +end end # Clean up afterwards: delete Trixi.jl output directory -Trixi.mpi_isroot() && isdir(outdir) && @test_nowarn rm(outdir, recursive=true) +Trixi.mpi_isroot() && isdir(outdir) && @test_nowarn rm(outdir, recursive = true) end # module diff --git a/test/test_tree_1d.jl b/test/test_tree_1d.jl index 7737a93a15a..4654f6313f7 100644 --- a/test/test_tree_1d.jl +++ b/test/test_tree_1d.jl @@ -9,275 +9,289 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_1d_dgsem") # Start with a clean environment: remove Trixi.jl output directory if it exists outdir = "out" -isdir(outdir) && rm(outdir, recursive=true) +isdir(outdir) && rm(outdir, recursive = true) @testset "TreeMesh1D" begin +#! format: noindent # Run basic tests @testset "Examples 1D" begin - # Linear scalar advection - include("test_tree_1d_advection.jl") + # Linear scalar advection + include("test_tree_1d_advection.jl") - # Burgers - include("test_tree_1d_burgers.jl") + # Burgers + include("test_tree_1d_burgers.jl") - # Hyperbolic diffusion - include("test_tree_1d_hypdiff.jl") + # Hyperbolic diffusion + include("test_tree_1d_hypdiff.jl") - # Compressible Euler - include("test_tree_1d_euler.jl") + # Compressible Euler + include("test_tree_1d_euler.jl") - # Compressible Euler Multicomponent - include("test_tree_1d_eulermulti.jl") + # Compressible Euler Multicomponent + include("test_tree_1d_eulermulti.jl") - # MHD - include("test_tree_1d_mhd.jl") + # MHD + include("test_tree_1d_mhd.jl") - # MHD Multicomponent - include("test_tree_1d_mhdmulti.jl") + # MHD Multicomponent + include("test_tree_1d_mhdmulti.jl") - # Compressible Euler with self-gravity - include("test_tree_1d_eulergravity.jl") + # Compressible Euler with self-gravity + include("test_tree_1d_eulergravity.jl") - # Shallow water - include("test_tree_1d_shallowwater.jl") - # Two-layer Shallow Water - include("test_tree_1d_shallowwater_twolayer.jl") + # Shallow water + include("test_tree_1d_shallowwater.jl") + # Two-layer Shallow Water + include("test_tree_1d_shallowwater_twolayer.jl") - # FDSBP methods on the TreeMesh - include("test_tree_1d_fdsbp.jl") + # FDSBP methods on the TreeMesh + include("test_tree_1d_fdsbp.jl") end # Coverage test for all initial conditions @testset "Tests for initial conditions" begin - # Linear scalar advection - @trixi_testset "elixir_advection_extended.jl with initial_condition_sin" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_extended.jl"), - l2 = [0.00017373554109980247], - linf = [0.0006021275678165239], - maxiters = 1, - initial_condition = Trixi.initial_condition_sin) - end - - @trixi_testset "elixir_advection_extended.jl with initial_condition_constant" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_extended.jl"), - l2 = [2.441369287653687e-16], - linf = [4.440892098500626e-16], - maxiters = 1, - initial_condition = initial_condition_constant) - end - - @trixi_testset "elixir_advection_extended.jl with initial_condition_linear_x" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_extended.jl"), - l2 = [1.9882464973192864e-16], - linf = [1.4432899320127035e-15], - maxiters = 1, - initial_condition = Trixi.initial_condition_linear_x, - boundary_conditions = Trixi.boundary_condition_linear_x, - periodicity=false) - end - - @trixi_testset "elixir_advection_extended.jl with initial_condition_convergence_test" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_extended.jl"), - l2 = [6.1803596620800215e-6], - linf = [2.4858560899509996e-5], - maxiters = 1, - initial_condition = initial_condition_convergence_test, - boundary_conditions = BoundaryConditionDirichlet(initial_condition_convergence_test), - periodicity=false) - end -end + # Linear scalar advection + @trixi_testset "elixir_advection_extended.jl with initial_condition_sin" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_extended.jl"), + l2=[0.00017373554109980247], + linf=[0.0006021275678165239], + maxiters=1, + initial_condition=Trixi.initial_condition_sin) + end + + @trixi_testset "elixir_advection_extended.jl with initial_condition_constant" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_extended.jl"), + l2=[2.441369287653687e-16], + linf=[4.440892098500626e-16], + maxiters=1, + initial_condition=initial_condition_constant) + end + + @trixi_testset "elixir_advection_extended.jl with initial_condition_linear_x" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_extended.jl"), + l2=[1.9882464973192864e-16], + linf=[1.4432899320127035e-15], + maxiters=1, + initial_condition=Trixi.initial_condition_linear_x, + boundary_conditions=Trixi.boundary_condition_linear_x, + periodicity=false) + end + @trixi_testset "elixir_advection_extended.jl with initial_condition_convergence_test" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_extended.jl"), + l2=[6.1803596620800215e-6], + linf=[2.4858560899509996e-5], + maxiters=1, + initial_condition=initial_condition_convergence_test, + boundary_conditions=BoundaryConditionDirichlet(initial_condition_convergence_test), + periodicity=false) + end +end @testset "Displaying components 1D" begin - @test_nowarn include(joinpath(EXAMPLES_DIR, "elixir_advection_amr.jl")) - - # test both short and long printing formats - @test_nowarn show(mesh); println() - @test_nowarn println(mesh) - @test_nowarn display(mesh) - - @test_nowarn show(equations); println() - @test_nowarn println(equations) - @test_nowarn display(equations) - - @test_nowarn show(solver); println() - @test_nowarn println(solver) - @test_nowarn display(solver) - - @test_nowarn show(solver.basis); println() - @test_nowarn println(solver.basis) - @test_nowarn display(solver.basis) - - @test_nowarn show(solver.mortar); println() - @test_nowarn println(solver.mortar) - @test_nowarn display(solver.mortar) - - @test_nowarn show(solver.volume_integral); println() - @test_nowarn println(solver.volume_integral) - @test_nowarn display(solver.volume_integral) - - @test_nowarn show(semi); println() - @test_nowarn println(semi) - @test_nowarn display(semi) - - @test_nowarn show(summary_callback); println() - @test_nowarn println(summary_callback) - @test_nowarn display(summary_callback) - - @test_nowarn show(amr_controller); println() - @test_nowarn println(amr_controller) - @test_nowarn display(amr_controller) - - @test_nowarn show(amr_callback); println() - @test_nowarn println(amr_callback) - @test_nowarn display(amr_callback) - - @test_nowarn show(stepsize_callback); println() - @test_nowarn println(stepsize_callback) - @test_nowarn display(stepsize_callback) - - @test_nowarn show(save_solution); println() - @test_nowarn println(save_solution) - @test_nowarn display(save_solution) - - @test_nowarn show(analysis_callback); println() - @test_nowarn println(analysis_callback) - @test_nowarn display(analysis_callback) - - @test_nowarn show(alive_callback); println() - @test_nowarn println(alive_callback) - @test_nowarn display(alive_callback) - - @test_nowarn println(callbacks) - - # Check whether all output is suppressed if the summary, analysis and alive - # callbacks are set to the TrivialCallback(). Modelled using `@test_nowarn` - # as basis. - let fname = tempname() - try - open(fname, "w") do f - redirect_stderr(f) do - trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_extended.jl"), - summary_callback=TrivialCallback(), - analysis_callback=TrivialCallback(), - alive_callback=TrivialCallback()) + @test_nowarn include(joinpath(EXAMPLES_DIR, "elixir_advection_amr.jl")) + + # test both short and long printing formats + @test_nowarn show(mesh) + println() + @test_nowarn println(mesh) + @test_nowarn display(mesh) + + @test_nowarn show(equations) + println() + @test_nowarn println(equations) + @test_nowarn display(equations) + + @test_nowarn show(solver) + println() + @test_nowarn println(solver) + @test_nowarn display(solver) + + @test_nowarn show(solver.basis) + println() + @test_nowarn println(solver.basis) + @test_nowarn display(solver.basis) + + @test_nowarn show(solver.mortar) + println() + @test_nowarn println(solver.mortar) + @test_nowarn display(solver.mortar) + + @test_nowarn show(solver.volume_integral) + println() + @test_nowarn println(solver.volume_integral) + @test_nowarn display(solver.volume_integral) + + @test_nowarn show(semi) + println() + @test_nowarn println(semi) + @test_nowarn display(semi) + + @test_nowarn show(summary_callback) + println() + @test_nowarn println(summary_callback) + @test_nowarn display(summary_callback) + + @test_nowarn show(amr_controller) + println() + @test_nowarn println(amr_controller) + @test_nowarn display(amr_controller) + + @test_nowarn show(amr_callback) + println() + @test_nowarn println(amr_callback) + @test_nowarn display(amr_callback) + + @test_nowarn show(stepsize_callback) + println() + @test_nowarn println(stepsize_callback) + @test_nowarn display(stepsize_callback) + + @test_nowarn show(save_solution) + println() + @test_nowarn println(save_solution) + @test_nowarn display(save_solution) + + @test_nowarn show(analysis_callback) + println() + @test_nowarn println(analysis_callback) + @test_nowarn display(analysis_callback) + + @test_nowarn show(alive_callback) + println() + @test_nowarn println(alive_callback) + @test_nowarn display(alive_callback) + + @test_nowarn println(callbacks) + + # Check whether all output is suppressed if the summary, analysis and alive + # callbacks are set to the TrivialCallback(). Modelled using `@test_nowarn` + # as basis. + let fname = tempname() + try + open(fname, "w") do f + redirect_stderr(f) do + trixi_include(joinpath(EXAMPLES_DIR, + "elixir_advection_extended.jl"), + summary_callback = TrivialCallback(), + analysis_callback = TrivialCallback(), + alive_callback = TrivialCallback()) + end + end + output = read(fname, String) + output = replace(output, + "[ Info: You just called `trixi_include`. Julia may now compile the code, please be patient.\n" => "") + @test isempty(output) + finally + rm(fname, force = true) end - end - output = read(fname, String) - output = replace(output, "[ Info: You just called `trixi_include`. Julia may now compile the code, please be patient.\n" => "") - @test isempty(output) - finally - rm(fname, force=true) end - end end - @testset "Additional tests in 1D" begin - @testset "compressible Euler" begin - eqn = CompressibleEulerEquations1D(1.4) + @testset "compressible Euler" begin + eqn = CompressibleEulerEquations1D(1.4) - @test isapprox(Trixi.entropy_thermodynamic([1.0, 2.0, 20.0], eqn), 1.9740810260220094) - @test isapprox(Trixi.entropy_math([1.0, 2.0, 20.0], eqn), -4.935202565055024) - @test isapprox(Trixi.entropy([1.0, 2.0, 20.0], eqn), -4.935202565055024) + @test isapprox(Trixi.entropy_thermodynamic([1.0, 2.0, 20.0], eqn), + 1.9740810260220094) + @test isapprox(Trixi.entropy_math([1.0, 2.0, 20.0], eqn), -4.935202565055024) + @test isapprox(Trixi.entropy([1.0, 2.0, 20.0], eqn), -4.935202565055024) - @test isapprox(energy_total([1.0, 2.0, 20.0], eqn), 20.0) - @test isapprox(energy_kinetic([1.0, 2.0, 20.0], eqn), 2.0) - @test isapprox(energy_internal([1.0, 2.0, 20.0], eqn), 18.0) - end + @test isapprox(energy_total([1.0, 2.0, 20.0], eqn), 20.0) + @test isapprox(energy_kinetic([1.0, 2.0, 20.0], eqn), 2.0) + @test isapprox(energy_internal([1.0, 2.0, 20.0], eqn), 18.0) + end end @trixi_testset "Nonconservative terms in 1D (linear advection)" begin - # Same setup as docs/src/adding_new_equations/nonconservative_advection.md + # Same setup as docs/src/adding_new_equations/nonconservative_advection.md - # Define new physics - using Trixi - using Trixi: AbstractEquations, get_node_vars - - # Since there is no native support for variable coefficients, we use two - # variables: one for the basic unknown `u` and another one for the coefficient `a` - struct NonconservativeLinearAdvectionEquation <: AbstractEquations{1 #= spatial dimension =#, - 2 #= two variables (u,a) =#} - end - - Trixi.varnames(::typeof(cons2cons), ::NonconservativeLinearAdvectionEquation) = ("scalar", "advection_velocity") - - Trixi.default_analysis_integrals(::NonconservativeLinearAdvectionEquation) = () + # Define new physics + using Trixi + using Trixi: AbstractEquations, get_node_vars + # Since there is no native support for variable coefficients, we use two + # variables: one for the basic unknown `u` and another one for the coefficient `a` + struct NonconservativeLinearAdvectionEquation <: AbstractEquations{1, #= spatial dimension =# + 2} #= two variables (u,a) =# + end - # The conservative part of the flux is zero - Trixi.flux(u, orientation, equation::NonconservativeLinearAdvectionEquation) = zero(u) + Trixi.varnames(::typeof(cons2cons), ::NonconservativeLinearAdvectionEquation) = ("scalar", + "advection_velocity") - # Calculate maximum wave speed for local Lax-Friedrichs-type dissipation - function Trixi.max_abs_speed_naive(u_ll, u_rr, orientation::Integer, ::NonconservativeLinearAdvectionEquation) - _, advection_velocity_ll = u_ll - _, advection_velocity_rr = u_rr + Trixi.default_analysis_integrals(::NonconservativeLinearAdvectionEquation) = () - return max(abs(advection_velocity_ll), abs(advection_velocity_rr)) - end + # The conservative part of the flux is zero + Trixi.flux(u, orientation, equation::NonconservativeLinearAdvectionEquation) = zero(u) + # Calculate maximum wave speed for local Lax-Friedrichs-type dissipation + function Trixi.max_abs_speed_naive(u_ll, u_rr, orientation::Integer, + ::NonconservativeLinearAdvectionEquation) + _, advection_velocity_ll = u_ll + _, advection_velocity_rr = u_rr - # We use nonconservative terms - Trixi.have_nonconservative_terms(::NonconservativeLinearAdvectionEquation) = Trixi.True() + return max(abs(advection_velocity_ll), abs(advection_velocity_rr)) + end - function flux_nonconservative(u_mine, u_other, orientation, - equations::NonconservativeLinearAdvectionEquation) - _, advection_velocity = u_mine - scalar, _ = u_other + # We use nonconservative terms + Trixi.have_nonconservative_terms(::NonconservativeLinearAdvectionEquation) = Trixi.True() - return SVector(advection_velocity * scalar, zero(scalar)) - end + function flux_nonconservative(u_mine, u_other, orientation, + equations::NonconservativeLinearAdvectionEquation) + _, advection_velocity = u_mine + scalar, _ = u_other + return SVector(advection_velocity * scalar, zero(scalar)) + end - # Create a simulation setup - using Trixi - using OrdinaryDiffEq + # Create a simulation setup + using Trixi + using OrdinaryDiffEq - equation = NonconservativeLinearAdvectionEquation() + equation = NonconservativeLinearAdvectionEquation() - # You can derive the exact solution for this setup using the method of - # characteristics - function initial_condition_sine(x, t, equation::NonconservativeLinearAdvectionEquation) - x0 = -2 * atan(sqrt(3) * tan(sqrt(3) / 2 * t - atan(tan(x[1] / 2) / sqrt(3)))) - scalar = sin(x0) - advection_velocity = 2 + cos(x[1]) - SVector(scalar, advection_velocity) - end + # You can derive the exact solution for this setup using the method of + # characteristics + function initial_condition_sine(x, t, + equation::NonconservativeLinearAdvectionEquation) + x0 = -2 * atan(sqrt(3) * tan(sqrt(3) / 2 * t - atan(tan(x[1] / 2) / sqrt(3)))) + scalar = sin(x0) + advection_velocity = 2 + cos(x[1]) + SVector(scalar, advection_velocity) + end - # Create a uniform mesh in 1D in the interval [-π, π] with periodic boundaries - mesh = TreeMesh(-Float64(π), Float64(π), # min/max coordinates - initial_refinement_level=4, n_cells_max=10^4) + # Create a uniform mesh in 1D in the interval [-π, π] with periodic boundaries + mesh = TreeMesh(-Float64(π), Float64(π), # min/max coordinates + initial_refinement_level = 4, n_cells_max = 10^4) - # Create a DGSEM solver with polynomials of degree `polydeg` - volume_flux = (flux_central, flux_nonconservative) - surface_flux = (flux_lax_friedrichs, flux_nonconservative) - solver = DGSEM(polydeg=3, surface_flux=surface_flux, - volume_integral=VolumeIntegralFluxDifferencing(volume_flux)) + # Create a DGSEM solver with polynomials of degree `polydeg` + volume_flux = (flux_central, flux_nonconservative) + surface_flux = (flux_lax_friedrichs, flux_nonconservative) + solver = DGSEM(polydeg = 3, surface_flux = surface_flux, + volume_integral = VolumeIntegralFluxDifferencing(volume_flux)) - # Setup the spatial semidiscretization containing all ingredients - semi = SemidiscretizationHyperbolic(mesh, equation, initial_condition_sine, solver) + # Setup the spatial semidiscretization containing all ingredients + semi = SemidiscretizationHyperbolic(mesh, equation, initial_condition_sine, solver) - # Create an ODE problem with given time span - tspan = (0.0, 1.0) - ode = semidiscretize(semi, tspan); + # Create an ODE problem with given time span + tspan = (0.0, 1.0) + ode = semidiscretize(semi, tspan) - summary_callback = SummaryCallback() - analysis_callback = AnalysisCallback(semi, interval=50) - callbacks = CallbackSet(summary_callback, analysis_callback); + summary_callback = SummaryCallback() + analysis_callback = AnalysisCallback(semi, interval = 50) + callbacks = CallbackSet(summary_callback, analysis_callback) - # OrdinaryDiffEq's `solve` method evolves the solution in time and executes - # the passed callbacks - sol = solve(ode, Tsit5(), abstol=1.0e-6, reltol=1.0e-6, - save_everystep=false, callback=callbacks); + # OrdinaryDiffEq's `solve` method evolves the solution in time and executes + # the passed callbacks + sol = solve(ode, Tsit5(), abstol = 1.0e-6, reltol = 1.0e-6, + save_everystep = false, callback = callbacks) - @test analysis_callback(sol).l2 ≈ [0.00029609575838969394, 5.5681704039507985e-6] + @test analysis_callback(sol).l2 ≈ [0.00029609575838969394, 5.5681704039507985e-6] end - # Clean up afterwards: delete Trixi.jl output directory -@test_nowarn rm(outdir, recursive=true) - +@test_nowarn rm(outdir, recursive = true) end # TreeMesh1D end # module diff --git a/test/test_tree_1d_advection.jl b/test/test_tree_1d_advection.jl index 0cf0f2c1170..a580a3b5600 100644 --- a/test/test_tree_1d_advection.jl +++ b/test/test_tree_1d_advection.jl @@ -8,31 +8,79 @@ include("test_trixi.jl") EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_1d_dgsem") @testset "Linear scalar advection" begin - @trixi_testset "elixir_advection_basic.jl" begin +#! format: noindent + +@trixi_testset "elixir_advection_basic.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_basic.jl"), - l2 = [6.0388296447998465e-6], - linf = [3.217887726258972e-5]) - end + l2=[6.0388296447998465e-6], + linf=[3.217887726258972e-5]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_advection_amr.jl" begin +@trixi_testset "elixir_advection_amr.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_amr.jl"), - l2 = [0.3540206249507417], - linf = [0.9999896603382347], - coverage_override = (maxiters=6,)) - end + l2=[0.3540206249507417], + linf=[0.9999896603382347], + coverage_override=(maxiters = 6,)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_advection_amr_nonperiodic.jl" begin +@trixi_testset "elixir_advection_amr_nonperiodic.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_amr_nonperiodic.jl"), - l2 = [4.283508859843524e-6], - linf = [3.235356127918171e-5], - coverage_override = (maxiters=6,)) - end + l2=[4.283508859843524e-6], + linf=[3.235356127918171e-5], + coverage_override=(maxiters = 6,)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_advection_finite_volume.jl" begin +@trixi_testset "elixir_advection_basic.jl (No errors)" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_basic.jl"), + analysis_callback=AnalysisCallback(semi, interval = 42, + analysis_errors = Symbol[])) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_advection_finite_volume.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_finite_volume.jl"), - l2 = [0.011662300515980219], - linf = [0.01647256923710194]) - end + l2=[0.011662300515980219], + linf=[0.01647256923710194]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end end end # module diff --git a/test/test_tree_1d_burgers.jl b/test/test_tree_1d_burgers.jl index 8c4cfaa406d..56e1ee749f7 100644 --- a/test/test_tree_1d_burgers.jl +++ b/test/test_tree_1d_burgers.jl @@ -8,29 +8,63 @@ include("test_trixi.jl") EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_1d_dgsem") @testset "Inviscid Burgers" begin - @trixi_testset "elixir_burgers_basic.jl" begin +#! format: noindent + +@trixi_testset "elixir_burgers_basic.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_burgers_basic.jl"), - l2 = [2.967470209082194e-5], - linf = [0.00016152468882624227]) - end + l2=[2.967470209082194e-5], + linf=[0.00016152468882624227]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_burgers_linear_stability.jl" begin +@trixi_testset "elixir_burgers_linear_stability.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_burgers_linear_stability.jl"), - l2 = [0.5660569881106876], - linf = [1.9352238038313998]) - end + l2=[0.5660569881106876], + linf=[1.9352238038313998]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_burgers_shock.jl" begin +@trixi_testset "elixir_burgers_shock.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_burgers_shock.jl"), - l2 = [0.4422505602587537], - linf = [1.0000000000000009]) - end + l2=[0.4422505602587537], + linf=[1.0000000000000009]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_burgers_rarefaction.jl" begin +@trixi_testset "elixir_burgers_rarefaction.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_burgers_rarefaction.jl"), - l2 = [0.4038224690923722], - linf = [1.0049201454652736]) - end + l2=[0.4038224690923722], + linf=[1.0049201454652736]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end end end # module diff --git a/test/test_tree_1d_euler.jl b/test/test_tree_1d_euler.jl index 5fb74b80bce..39a1f6e30ba 100644 --- a/test/test_tree_1d_euler.jl +++ b/test/test_tree_1d_euler.jl @@ -8,145 +8,464 @@ include("test_trixi.jl") EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_1d_dgsem") @testset "Compressible Euler" begin - @trixi_testset "elixir_euler_source_terms.jl" begin +#! format: noindent + +@trixi_testset "elixir_euler_source_terms.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms.jl"), - l2 = [2.2527950196212703e-8, 1.8187357193835156e-8, 7.705669939973104e-8], - linf = [1.6205433861493646e-7, 1.465427772462391e-7, 5.372255111879554e-7]) - end + l2=[ + 2.2527950196212703e-8, + 1.8187357193835156e-8, + 7.705669939973104e-8, + ], + linf=[ + 1.6205433861493646e-7, + 1.465427772462391e-7, + 5.372255111879554e-7, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_convergence_pure_fv.jl" begin +@trixi_testset "elixir_euler_convergence_pure_fv.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_convergence_pure_fv.jl"), - l2 = [0.019355699748523896, 0.022326984561234497, 0.02523665947241734], - linf = [0.02895961127645519, 0.03293442484199227, 0.04246098278632804]) - end + l2=[ + 0.019355699748523896, + 0.022326984561234497, + 0.02523665947241734, + ], + linf=[ + 0.02895961127645519, + 0.03293442484199227, + 0.04246098278632804, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_density_wave.jl" begin +@trixi_testset "elixir_euler_density_wave.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_density_wave.jl"), - l2 = [0.0011482554820217855, 0.00011482554830323462, 5.741277429325267e-6], - linf = [0.004090978306812376, 0.0004090978313582294, 2.045489210189544e-5]) - end + l2=[ + 0.0011482554820217855, + 0.00011482554830323462, + 5.741277429325267e-6, + ], + linf=[ + 0.004090978306812376, + 0.0004090978313582294, + 2.045489210189544e-5, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_density_wave.jl with initial_condition_constant" begin +@trixi_testset "elixir_euler_density_wave.jl with initial_condition_constant" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_density_wave.jl"), - l2 = [7.71293052584723e-16, 1.9712947511091717e-14, 7.50672833504266e-15], - linf = [3.774758283725532e-15, 6.733502644351574e-14, 2.4868995751603507e-14], - initial_condition = initial_condition_constant) - end - - @trixi_testset "elixir_euler_source_terms_nonperiodic.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms_nonperiodic.jl"), - l2 = [3.8099996914101204e-6, 1.6745575717106341e-6, 7.732189531480852e-6], - linf = [1.2971473393186272e-5, 9.270328934274374e-6, 3.092514399671842e-5]) - end - - @trixi_testset "elixir_euler_ec.jl" begin + l2=[ + 7.71293052584723e-16, + 1.9712947511091717e-14, + 7.50672833504266e-15, + ], + linf=[ + 3.774758283725532e-15, + 6.733502644351574e-14, + 2.4868995751603507e-14, + ], + initial_condition=initial_condition_constant) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_source_terms_nonperiodic.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_source_terms_nonperiodic.jl"), + l2=[ + 3.8099996914101204e-6, + 1.6745575717106341e-6, + 7.732189531480852e-6, + ], + linf=[ + 1.2971473393186272e-5, + 9.270328934274374e-6, + 3.092514399671842e-5, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_ec.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_ec.jl"), - l2 = [0.11821957357197649, 0.15330089521538678, 0.4417674632047301], - linf = [0.24280567569982958, 0.29130548795961936, 0.8847009003152442]) - end + l2=[ + 0.11821957357197649, + 0.15330089521538678, + 0.4417674632047301, + ], + linf=[ + 0.24280567569982958, + 0.29130548795961936, + 0.8847009003152442, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_ec.jl with flux_kennedy_gruber" begin +@trixi_testset "elixir_euler_ec.jl with flux_kennedy_gruber" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_ec.jl"), - l2 = [0.07803455838661963, 0.10032577312032283, 0.29228156303827935], - linf = [0.2549869853794955, 0.3376472164661263, 0.9650477546553962], - maxiters = 10, - surface_flux = flux_kennedy_gruber, - volume_flux = flux_kennedy_gruber) - end - - @trixi_testset "elixir_euler_ec.jl with flux_shima_etal" begin + l2=[ + 0.07803455838661963, + 0.10032577312032283, + 0.29228156303827935, + ], + linf=[ + 0.2549869853794955, + 0.3376472164661263, + 0.9650477546553962, + ], + maxiters=10, + surface_flux=flux_kennedy_gruber, + volume_flux=flux_kennedy_gruber) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_ec.jl with flux_shima_etal" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_ec.jl"), - l2 = [0.07800654460172655, 0.10030365573277883, 0.2921481199111959], - linf = [0.25408579350400395, 0.3388657679031271, 0.9776486386921928], - maxiters = 10, - surface_flux = flux_shima_etal, - volume_flux = flux_shima_etal) - end - - @trixi_testset "elixir_euler_ec.jl with flux_chandrashekar" begin + l2=[ + 0.07800654460172655, + 0.10030365573277883, + 0.2921481199111959, + ], + linf=[ + 0.25408579350400395, + 0.3388657679031271, + 0.9776486386921928, + ], + maxiters=10, + surface_flux=flux_shima_etal, + volume_flux=flux_shima_etal) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_ec.jl with flux_chandrashekar" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_ec.jl"), - l2 = [0.07801923089205756, 0.10039557434912669, 0.2922210399923278], - linf = [0.2576521982607225, 0.3409717926625057, 0.9772961936567048], - maxiters = 10, - surface_flux = flux_chandrashekar, - volume_flux = flux_chandrashekar) - end - - @trixi_testset "elixir_euler_ec.jl with flux_hll" begin + l2=[ + 0.07801923089205756, + 0.10039557434912669, + 0.2922210399923278, + ], + linf=[ + 0.2576521982607225, + 0.3409717926625057, + 0.9772961936567048, + ], + maxiters=10, + surface_flux=flux_chandrashekar, + volume_flux=flux_chandrashekar) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_ec.jl with flux_hll" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_ec.jl"), - l2 = [0.07852272782240548, 0.10209790867523805, 0.293873048809011], - linf = [0.19244768908604093, 0.2515941686151897, 0.7258000837553769], - maxiters = 10, - surface_flux = flux_hll, - volume_flux = flux_ranocha) - end - - @trixi_testset "elixir_euler_shockcapturing.jl" begin + l2=[0.07852272782240548, 0.10209790867523805, 0.293873048809011], + linf=[ + 0.19244768908604093, + 0.2515941686151897, + 0.7258000837553769, + ], + maxiters=10, + surface_flux=flux_hll, + volume_flux=flux_ranocha) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_shockcapturing.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_shockcapturing.jl"), - l2 = [0.11606096465319675, 0.15028768943458806, 0.4328230323046703], - linf = [0.18031710091067965, 0.2351582421501841, 0.6776805692092567]) - end + l2=[ + 0.11606096465319675, + 0.15028768943458806, + 0.4328230323046703, + ], + linf=[ + 0.18031710091067965, + 0.2351582421501841, + 0.6776805692092567, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_sedov_blast_wave.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov_blast_wave.jl"), + l2=[1.250005061244617, 0.06878411345533507, 0.9264328311018613], + linf=[ + 2.9766770877037168, + 0.16838100902295852, + 2.6655773445485798, + ], + coverage_override=(maxiters = 6,)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_sedov_blast_wave.jl" begin +@trixi_testset "elixir_euler_sedov_blast_wave.jl (HLLE)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov_blast_wave.jl"), - l2 = [1.250005061244617, 0.06878411345533507, 0.9264328311018613], - linf = [2.9766770877037168, 0.16838100902295852, 2.6655773445485798], - coverage_override = (maxiters=6,)) - end - - @trixi_testset "elixir_euler_sedov_blast_wave_pure_fv.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov_blast_wave_pure_fv.jl"), - l2 = [1.0735456065491455, 0.07131078703089379, 0.9205739468590453], - linf = [3.4296365168219216, 0.17635583964559245, 2.6574584326179505], - # Let this test run longer to cover some lines in flux_hllc - coverage_override = (maxiters=10^5, tspan=(0.0, 0.1))) - end - - @trixi_testset "elixir_euler_sedov_blast_wave.jl with pressure" begin + l2=[0.6442208390304879, 0.508817280068289, 0.9482809853033687], + linf=[3.007059066482486, 2.4678899558345506, 2.3952311739389787], + tspan=(0.0, 0.5), + surface_flux=flux_hlle) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_sedov_blast_wave_pure_fv.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_sedov_blast_wave_pure_fv.jl"), + l2=[1.0735456065491455, 0.07131078703089379, 0.9205739468590453], + linf=[ + 3.4296365168219216, + 0.17635583964559245, + 2.6574584326179505, + ], + # Let this test run longer to cover some lines in flux_hllc + coverage_override=(maxiters = 10^5, tspan = (0.0, 0.1))) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_sedov_blast_wave.jl with pressure" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov_blast_wave.jl"), - l2 = [1.297525985166995, 0.07964929522694145, 0.9269991156246368], - linf = [3.1773015255764427, 0.21331831536493773, 2.6650170188241047], - shock_indicator_variable = pressure, - cfl = 0.2, - coverage_override = (maxiters=6,)) - end - - @trixi_testset "elixir_euler_sedov_blast_wave.jl with density" begin + l2=[1.297525985166995, 0.07964929522694145, 0.9269991156246368], + linf=[ + 3.1773015255764427, + 0.21331831536493773, + 2.6650170188241047, + ], + shock_indicator_variable=pressure, + cfl=0.2, + coverage_override=(maxiters = 6,)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_sedov_blast_wave.jl with density" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov_blast_wave.jl"), - l2 = [1.2798798835860528, 0.07103461242058921, 0.9273792517187003], - linf = [3.1087017048015824, 0.17734706962928956, 2.666689753470263], - shock_indicator_variable = density, - cfl = 0.2, - coverage_override = (maxiters=6,)) - end - - @trixi_testset "elixir_euler_positivity.jl" begin + l2=[1.2798798835860528, 0.07103461242058921, 0.9273792517187003], + linf=[ + 3.1087017048015824, + 0.17734706962928956, + 2.666689753470263, + ], + shock_indicator_variable=density, + cfl=0.2, + coverage_override=(maxiters = 6,)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_positivity.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_positivity.jl"), - l2 = [1.6493820253458906, 0.19793887460986834, 0.9783506076125921], - linf = [4.71751203912051, 0.5272411022735763, 2.7426163947635844], - coverage_override = (maxiters=3,)) - end - - @trixi_testset "elixir_euler_blast_wave.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave.jl"), - l2 = [0.21934822867340323, 0.28131919126002686, 0.554361702716662], - linf = [1.5180897390290355, 1.3967085956620369, 2.0663825294019595], - maxiters = 30) - end - - @trixi_testset "elixir_euler_blast_wave_neuralnetwork_perssonperaire.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave_neuralnetwork_perssonperaire.jl"), - l2 = [0.21814833203212694, 0.2818328665444332, 0.5528379124720818], - linf = [1.5548653877320868, 1.4474018998129738, 2.071919577393772], - maxiters = 30) - end - - @trixi_testset "elixir_euler_blast_wave_neuralnetwork_rayhesthaven.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave_neuralnetwork_rayhesthaven.jl"), - l2 = [0.22054468879127423, 0.2828269190680846, 0.5542369885642424], - linf = [1.5623359741479623, 1.4290121654488288, 2.1040405133123072], - maxiters = 30) - end + l2=[1.6493820253458906, 0.19793887460986834, 0.9783506076125921], + linf=[4.71751203912051, 0.5272411022735763, 2.7426163947635844], + coverage_override=(maxiters = 3,)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_blast_wave.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave.jl"), + l2=[0.21934822867340323, 0.28131919126002686, 0.554361702716662], + linf=[ + 1.5180897390290355, + 1.3967085956620369, + 2.0663825294019595, + ], + maxiters=30) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_quasi_1d_source_terms.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_quasi_1d_source_terms.jl"), + l2=[ + 3.876288369618363e-7, + 2.2247043122302947e-7, + 2.964004224572679e-7, + 5.2716983399807875e-8, + ], + linf=[ + 2.3925118561862746e-6, + 1.3603693522767912e-6, + 1.821888865105592e-6, + 1.1166012159335992e-7, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_quasi_1d_discontinuous.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_quasi_1d_discontinuous.jl"), + l2=[ + 0.045510421156346015, + 0.036750584788912195, + 0.2468985959132176, + 0.03684494180829024, + ], + linf=[ + 0.3313374853025697, + 0.11621933362158643, + 1.827403013568638, + 0.28045939999015723, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_quasi_1d_ec.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_quasi_1d_ec.jl"), + l2=[ + 0.08889113985713998, + 0.16199235348889673, + 0.40316524365054346, + 2.9602775074723667e-16, + ], + linf=[ + 0.28891355898284043, + 0.3752709888964313, + 0.84477102402413, + 8.881784197001252e-16, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end end end # module diff --git a/test/test_tree_1d_eulergravity.jl b/test/test_tree_1d_eulergravity.jl index 966add0cdf3..9ab5b287d0b 100644 --- a/test/test_tree_1d_eulergravity.jl +++ b/test/test_tree_1d_eulergravity.jl @@ -8,11 +8,29 @@ include("test_trixi.jl") EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_1d_dgsem") @testset "Compressible Euler with self-gravity" begin - @trixi_testset "elixir_eulergravity_convergence.jl" begin +#! format: noindent + +@trixi_testset "elixir_eulergravity_convergence.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulergravity_convergence.jl"), - l2 = [0.0002170799126638106, 0.0002913792848717502, 0.0006112320856262327], - linf = [0.0004977401033188222, 0.0013594223337776157, 0.002041891084400227]) - end + l2=[ + 0.0002170799126638106, + 0.0002913792848717502, + 0.0006112320856262327, + ], + linf=[ + 0.0004977401033188222, + 0.0013594223337776157, + 0.002041891084400227, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end end end # module diff --git a/test/test_tree_1d_eulermulti.jl b/test/test_tree_1d_eulermulti.jl index e880f98e2d0..b6c79ce03d1 100644 --- a/test/test_tree_1d_eulermulti.jl +++ b/test/test_tree_1d_eulermulti.jl @@ -2,62 +2,153 @@ module TestExamples1DEulerMulti using Test using Trixi +using ForwardDiff include("test_trixi.jl") EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_1d_dgsem") @testset "Compressible Euler Multicomponent" begin + @trixi_testset "Testing entropy2cons and cons2entropy" begin + using ForwardDiff + gammas = (1.3272378792562836, 1.5269959187969864, 1.8362285750521512, + 1.0409061360276926, 1.4652015053812224, 1.3626493264184423) + gas_constants = (1.817636851910076, 6.760820475922636, 5.588953939749113, + 6.31574782981543, 3.362932038038397, 3.212779569399733) + equations = CompressibleEulerMulticomponentEquations1D(gammas = SVector{length(gammas)}(gammas...), + gas_constants = SVector{length(gas_constants)}(gas_constants...)) + u = [-1.4632513788889214, 0.9908786980927811, 0.2909066990257628, + 0.6256623915420473, 0.4905882754313441, 0.14481800501749112, + 1.0333532872771651, 0.6805599818745411] + w = cons2entropy(u, equations) + # test that the entropy variables match the gradients of the total entropy + @test w ≈ ForwardDiff.gradient(u -> Trixi.total_entropy(u, equations), u) + # test that `entropy2cons` is the inverse of `cons2entropy` + @test entropy2cons(w, equations) ≈ u + end - @trixi_testset "elixir_eulermulti_ec.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulermulti_ec.jl"), - l2 = [0.15330089521538684, 0.4417674632047301, 0.016888510510282385, 0.03377702102056477, - 0.06755404204112954], - linf = [0.29130548795961864, 0.8847009003152357, 0.034686525099975274, 0.06937305019995055, - 0.1387461003999011]) - end - - @trixi_testset "elixir_eulermulti_es.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulermulti_es.jl"), - l2 = [0.1522380497572071, 0.43830846465313206, 0.03907262116499431, 0.07814524232998862], - linf = [0.24939193075537294, 0.7139395740052739, 0.06324208768391237, 0.12648417536782475]) - end - - @trixi_testset "elixir_eulermulti_convergence_ec.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulermulti_convergence_ec.jl"), - l2 = [8.575236038539227e-5, 0.00016387804318585358, 1.9412699303977585e-5, 3.882539860795517e-5], - linf = [0.00030593277277124464, 0.0006244803933350696, 7.253121435135679e-5, 0.00014506242870271358]) - end - - @trixi_testset "elixir_eulermulti_convergence_es.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulermulti_convergence_es.jl"), - l2 = [1.8983933794407234e-5, 6.207744299844731e-5, 1.5466205761868047e-6, 3.0932411523736094e-6, - 6.186482304747219e-6, 1.2372964609494437e-5], - linf = [0.00012014372605895218, 0.0003313207215800418, 6.50836791016296e-6, 1.301673582032592e-5, - 2.603347164065184e-5, 5.206694328130368e-5]) - end - - @trixi_testset "elixir_eulermulti_convergence_es.jl with flux_chandrashekar" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulermulti_convergence_es.jl"), - l2 = [1.888450477353845e-5, 5.4910600482795386e-5, 9.426737161533622e-7, 1.8853474323067245e-6, - 3.770694864613449e-6, 7.541389729226898e-6], - linf = [0.00011622351152063004, 0.0003079221967086099, 3.2177423254231563e-6, 6.435484650846313e-6, - 1.2870969301692625e-5, 2.574193860338525e-5], - volume_flux = flux_chandrashekar) - end - - @trixi_testset "elixir_eulermulti_two_interacting_blast_waves.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulermulti_two_interacting_blast_waves.jl"), - l2 = [1.288867611915533, 82.71335258388848, 0.00350680272313187, 0.013698784353152794, - 0.019179518517518084], - linf = [29.6413044707026, 1322.5844802186496, 0.09191919374782143, 0.31092970966717925, - 0.4417989757182038], - tspan = (0.0, 0.0001)) - end + @trixi_testset "elixir_eulermulti_ec.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulermulti_ec.jl"), + l2=[0.15330089521538684, 0.4417674632047301, + 0.016888510510282385, 0.03377702102056477, + 0.06755404204112954], + linf=[0.29130548795961864, 0.8847009003152357, + 0.034686525099975274, 0.06937305019995055, + 0.1387461003999011]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end + end + @trixi_testset "elixir_eulermulti_es.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulermulti_es.jl"), + l2=[ + 0.1522380497572071, + 0.43830846465313206, + 0.03907262116499431, + 0.07814524232998862, + ], + linf=[ + 0.24939193075537294, + 0.7139395740052739, + 0.06324208768391237, + 0.12648417536782475, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end + end -end + @trixi_testset "elixir_eulermulti_convergence_ec.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulermulti_convergence_ec.jl"), + l2=[ + 8.575236038539227e-5, + 0.00016387804318585358, + 1.9412699303977585e-5, + 3.882539860795517e-5, + ], + linf=[ + 0.00030593277277124464, + 0.0006244803933350696, + 7.253121435135679e-5, + 0.00014506242870271358, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end + end + + @trixi_testset "elixir_eulermulti_convergence_es.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulermulti_convergence_es.jl"), + l2=[1.8983933794407234e-5, 6.207744299844731e-5, + 1.5466205761868047e-6, 3.0932411523736094e-6, + 6.186482304747219e-6, 1.2372964609494437e-5], + linf=[0.00012014372605895218, 0.0003313207215800418, + 6.50836791016296e-6, 1.301673582032592e-5, + 2.603347164065184e-5, 5.206694328130368e-5]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end + end + @trixi_testset "elixir_eulermulti_convergence_es.jl with flux_chandrashekar" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulermulti_convergence_es.jl"), + l2=[1.888450477353845e-5, 5.4910600482795386e-5, + 9.426737161533622e-7, 1.8853474323067245e-6, + 3.770694864613449e-6, 7.541389729226898e-6], + linf=[0.00011622351152063004, 0.0003079221967086099, + 3.2177423254231563e-6, 6.435484650846313e-6, + 1.2870969301692625e-5, 2.574193860338525e-5], + volume_flux=flux_chandrashekar) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end + end + @trixi_testset "elixir_eulermulti_two_interacting_blast_waves.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_eulermulti_two_interacting_blast_waves.jl"), + l2=[1.288867611915533, 82.71335258388848, 0.00350680272313187, + 0.013698784353152794, + 0.019179518517518084], + linf=[29.6413044707026, 1322.5844802186496, 0.09191919374782143, + 0.31092970966717925, + 0.4417989757182038], + tspan=(0.0, 0.0001)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end + end +end end # module diff --git a/test/test_tree_1d_fdsbp.jl b/test/test_tree_1d_fdsbp.jl index ce0ca660d35..33d67e3366f 100644 --- a/test/test_tree_1d_fdsbp.jl +++ b/test/test_tree_1d_fdsbp.jl @@ -8,112 +8,185 @@ include("test_trixi.jl") EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_1d_fdsbp") @testset "Linear scalar advection" begin - @trixi_testset "elixir_advection_upwind.jl" begin +#! format: noindent + +@trixi_testset "elixir_advection_upwind.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_upwind.jl"), - l2 = [1.7735637157305526e-6], - linf = [1.0418854521951328e-5], - tspan = (0.0, 0.5)) + l2=[1.7735637157305526e-6], + linf=[1.0418854521951328e-5], + tspan=(0.0, 0.5)) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 end - end +end - @trixi_testset "elixir_advection_upwind_periodic.jl" begin +@trixi_testset "elixir_advection_upwind_periodic.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_upwind_periodic.jl"), - l2 = [1.1672962783692568e-5], - linf = [1.650514414558435e-5]) + l2=[1.1672962783692568e-5], + linf=[1.650514414558435e-5]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 end - end +end end @testset "Inviscid Burgers" begin - @trixi_testset "elixir_burgers_basic.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_burgers_basic.jl"), - l2 = [8.316190308678742e-7], - linf = [7.1087263324720595e-6], - tspan = (0.0, 0.5)) + @trixi_testset "elixir_burgers_basic.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_burgers_basic.jl"), + l2=[8.316190308678742e-7], + linf=[7.1087263324720595e-6], + tspan=(0.0, 0.5)) + + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end + end - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + # same tolerances as above since the methods should be identical (up to + # machine precision) + @trixi_testset "elixir_burgers_basic.jl with SurfaceIntegralStrongForm and FluxUpwind" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_burgers_basic.jl"), + l2=[8.316190308678742e-7], + linf=[7.1087263324720595e-6], + tspan=(0.0, 0.5), + solver=DG(D_upw, nothing, + SurfaceIntegralStrongForm(FluxUpwind(flux_splitting)), + VolumeIntegralUpwind(flux_splitting))) + end + + @trixi_testset "elixir_burgers_linear_stability.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_burgers_linear_stability.jl"), + l2=[0.9999995642691271], + linf=[1.824702804788453], + tspan=(0.0, 0.25)) + + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end end - end - - # same tolerances as above since the methods should be identical (up to - # machine precision) - @trixi_testset "elixir_burgers_basic.jl with SurfaceIntegralStrongForm and FluxUpwind" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_burgers_basic.jl"), - l2 = [8.316190308678742e-7], - linf = [7.1087263324720595e-6], - tspan = (0.0, 0.5), - solver = DG(D_upw, nothing, SurfaceIntegralStrongForm(FluxUpwind(flux_splitting)), VolumeIntegralUpwind(flux_splitting))) - end - - @trixi_testset "elixir_burgers_linear_stability.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_burgers_linear_stability.jl"), - l2 = [0.9999995642691271], - linf = [1.824702804788453], - tspan = (0.0, 0.25)) - end end @testset "Compressible Euler" begin - @trixi_testset "elixir_euler_convergence.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_convergence.jl"), - l2 = [4.1370344463620254e-6, 4.297052451817826e-6, 9.857382045003056e-6], - linf = [1.675305070092392e-5, 1.3448113863834266e-5, 3.8185336878271414e-5], - tspan = (0.0, 0.5)) + @trixi_testset "elixir_euler_convergence.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_convergence.jl"), + l2=[ + 4.1370344463620254e-6, + 4.297052451817826e-6, + 9.857382045003056e-6, + ], + linf=[ + 1.675305070092392e-5, + 1.3448113863834266e-5, + 3.8185336878271414e-5, + ], + tspan=(0.0, 0.5)) + + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end + end - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + @trixi_testset "elixir_euler_convergence.jl with splitting_vanleer_haenel" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_convergence.jl"), + l2=[ + 3.413790589105506e-6, + 4.243957977156001e-6, + 8.667369423676437e-6, + ], + linf=[ + 1.4228079689537765e-5, + 1.3249887941046978e-5, + 3.201552933251861e-5, + ], + tspan=(0.0, 0.5), + flux_splitting=splitting_vanleer_haenel) + + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end + end + + @trixi_testset "elixir_euler_convergence.jl with VolumeIntegralStrongForm" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_convergence.jl"), + l2=[ + 8.6126767518378e-6, + 7.670897071480729e-6, + 1.4972772284191368e-5, + ], + linf=[ + 6.707982777909294e-5, + 3.487256699541419e-5, + 0.00010170331350556339, + ], + tspan=(0.0, 0.5), + solver=DG(D_upw.central, nothing, SurfaceIntegralStrongForm(), + VolumeIntegralStrongForm())) + + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end + end + + @trixi_testset "elixir_euler_density_wave.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_density_wave.jl"), + l2=[ + 1.5894925236031034e-5, + 9.428412101106044e-6, + 0.0008986477358789918, + ], + linf=[ + 4.969438024382544e-5, + 2.393091812063694e-5, + 0.003271817388146303, + ], + tspan=(0.0, 0.005), abstol=1.0e-9, reltol=1.0e-9) + + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end end - end - - @trixi_testset "elixir_euler_convergence.jl with splitting_vanleer_haenel" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_convergence.jl"), - l2 = [3.413790589105506e-6, 4.243957977156001e-6, 8.667369423676437e-6], - linf = [1.4228079689537765e-5, 1.3249887941046978e-5, 3.201552933251861e-5], - tspan = (0.0, 0.5), - flux_splitting = splitting_vanleer_haenel) - end - - @trixi_testset "elixir_euler_convergence.jl with VolumeIntegralStrongForm" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_convergence.jl"), - l2 = [8.6126767518378e-6, 7.670897071480729e-6, 1.4972772284191368e-5], - linf = [6.707982777909294e-5, 3.487256699541419e-5, 0.00010170331350556339], - tspan = (0.0, 0.5), - solver = DG(D_upw.central, nothing, SurfaceIntegralStrongForm(), VolumeIntegralStrongForm())) - end - - @trixi_testset "elixir_euler_density_wave.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_density_wave.jl"), - l2 = [1.5894925236031034e-5, 9.428412101106044e-6, 0.0008986477358789918], - linf = [4.969438024382544e-5, 2.393091812063694e-5, 0.003271817388146303], - tspan = (0.0, 0.005), abstol = 1.0e-9, reltol = 1.0e-9) - end end end # module diff --git a/test/test_tree_1d_hypdiff.jl b/test/test_tree_1d_hypdiff.jl index 560f77b2a13..896a3d4c8d6 100644 --- a/test/test_tree_1d_hypdiff.jl +++ b/test/test_tree_1d_hypdiff.jl @@ -8,20 +8,38 @@ include("test_trixi.jl") EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_1d_dgsem") @testset "Hyperbolic diffusion" begin +#! format: noindent - @trixi_testset "elixir_hypdiff_nonperiodic.jl" begin +@trixi_testset "elixir_hypdiff_nonperiodic.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_hypdiff_nonperiodic.jl"), - l2 = [1.3655114954641076e-7, 1.0200345025539218e-6], - linf = [7.173286515893551e-7, 4.507116363683394e-6], - atol = 2.5e-13) - end + l2=[1.3655114954641076e-7, 1.0200345025539218e-6], + linf=[7.173286515893551e-7, 4.507116363683394e-6], + atol=2.5e-13) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_hypdiff_harmonic_nonperiodic.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_hypdiff_harmonic_nonperiodic.jl"), - l2 = [3.0130941075207524e-12, 2.6240829677090014e-12], - linf = [4.054534485931072e-12, 3.8826719617190975e-12], - atol = 2.5e-13) - end +@trixi_testset "elixir_hypdiff_harmonic_nonperiodic.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_hypdiff_harmonic_nonperiodic.jl"), + l2=[3.0130941075207524e-12, 2.6240829677090014e-12], + linf=[4.054534485931072e-12, 3.8826719617190975e-12], + atol=2.5e-13) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 10000 + end +end end end # module diff --git a/test/test_tree_1d_mhd.jl b/test/test_tree_1d_mhd.jl index e3a0cda3250..2150ddfd074 100644 --- a/test/test_tree_1d_mhd.jl +++ b/test/test_tree_1d_mhd.jl @@ -8,73 +8,359 @@ include("test_trixi.jl") EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_1d_dgsem") @testset "MHD" begin +#! format: noindent - @trixi_testset "elixir_mhd_alfven_wave.jl with initial_condition_constant" begin +@trixi_testset "elixir_mhd_alfven_wave.jl with initial_condition_constant" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_alfven_wave.jl"), - l2 = [1.440611823425164e-15, 1.1373567770134494e-14, 3.024482376149653e-15, 2.0553143516814395e-15, 3.9938347410210535e-14, 3.984545392098788e-16, 2.4782402104201577e-15, 1.551737464879987e-15], - linf = [1.9984014443252818e-15, 1.3405943022348765e-14, 3.3584246494910985e-15, 3.164135620181696e-15, 7.815970093361102e-14, 8.881784197001252e-16, 2.886579864025407e-15, 2.942091015256665e-15], - initial_condition = initial_condition_constant, - tspan = (0.0,1.0)) - end + l2=[ + 1.440611823425164e-15, + 1.1373567770134494e-14, + 3.024482376149653e-15, + 2.0553143516814395e-15, + 3.9938347410210535e-14, + 3.984545392098788e-16, + 2.4782402104201577e-15, + 1.551737464879987e-15, + ], + linf=[ + 1.9984014443252818e-15, + 1.3405943022348765e-14, + 3.3584246494910985e-15, + 3.164135620181696e-15, + 7.815970093361102e-14, + 8.881784197001252e-16, + 2.886579864025407e-15, + 2.942091015256665e-15, + ], + initial_condition=initial_condition_constant, + tspan=(0.0, 1.0)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_mhd_alfven_wave.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_alfven_wave.jl"), + l2=[ + 1.0375628983659061e-5, + 6.571144191446236e-7, + 3.5833569836289104e-5, + 3.583356983615859e-5, + 5.084863194951084e-6, + 1.1963224165731992e-16, + 3.598916927583752e-5, + 3.598916927594727e-5, + ], + linf=[ + 2.614095879338585e-5, + 9.577266731216823e-7, + 0.00012406198007461344, + 0.00012406198007509917, + 1.5066209528846741e-5, + 2.220446049250313e-16, + 0.00012658678753942054, + 0.00012658678753908748, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_mhd_alfven_wave.jl" begin +@trixi_testset "elixir_mhd_alfven_wave.jl with flux_derigs_etal" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_alfven_wave.jl"), - l2 = [1.0375628983659061e-5, 6.571144191446236e-7, 3.5833569836289104e-5, 3.583356983615859e-5, 5.084863194951084e-6, 1.1963224165731992e-16, 3.598916927583752e-5, 3.598916927594727e-5], - linf = [2.614095879338585e-5, 9.577266731216823e-7, 0.00012406198007461344, 0.00012406198007509917, 1.5066209528846741e-5, 2.220446049250313e-16, 0.00012658678753942054, 0.00012658678753908748]) - end + l2=[ + 1.4396053943470756e-5, + 1.1211016739165248e-5, + 3.577870687983967e-5, + 3.577870687982181e-5, + 1.967962220860377e-6, + 1.1963224165731992e-16, + 3.583562899483433e-5, + 3.583562899486565e-5, + ], + linf=[ + 5.830577969345718e-5, + 3.280495696370357e-5, + 0.00012279619948236953, + 0.00012279619948227238, + 6.978806516122482e-6, + 2.220446049250313e-16, + 0.00012564003648959932, + 0.00012564003648994626, + ], + volume_flux=flux_derigs_etal) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_mhd_alfven_wave.jl with flux_derigs_etal" begin +@trixi_testset "elixir_mhd_alfven_wave.jl with flux_hllc" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_alfven_wave.jl"), - l2 = [1.4396053943470756e-5, 1.1211016739165248e-5, 3.577870687983967e-5, 3.577870687982181e-5, 1.967962220860377e-6, 1.1963224165731992e-16, 3.583562899483433e-5, 3.583562899486565e-5], - linf = [5.830577969345718e-5, 3.280495696370357e-5, 0.00012279619948236953, 0.00012279619948227238, 6.978806516122482e-6, 2.220446049250313e-16, 0.00012564003648959932, 0.00012564003648994626], - volume_flux = flux_derigs_etal) - end + l2=[ + 1.036850596986597e-5, 1.965192583650368e-6, + 3.5882124656715505e-5, 3.5882124656638764e-5, + 5.270975504780837e-6, 1.1963224165731992e-16, + 3.595811808912869e-5, 3.5958118089159453e-5, + ], + linf=[ + 2.887280521446378e-5, 7.310580790352001e-6, + 0.00012390046377899755, 0.00012390046377787345, + 1.5102711136583125e-5, 2.220446049250313e-16, + 0.0001261935452181312, 0.0001261935452182006, + ], + surface_flux=flux_hllc) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_mhd_ec.jl" begin +@trixi_testset "elixir_mhd_ec.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_ec.jl"), - l2 = [0.05815183849746399, 0.08166807325621023, 0.054659228513541165, 0.054659228513541165, 0.15578125987042743, 4.130462730494e-17, 0.05465258887150046, 0.05465258887150046], - linf = [0.12165312668363826, 0.1901920742264952, 0.10059813883022554, 0.10059813883022554, 0.44079257431070706, 1.1102230246251565e-16, 0.10528911365809579, 0.10528911365809579]) - end + l2=[ + 0.05815183849746399, + 0.08166807325621023, + 0.054659228513541165, + 0.054659228513541165, + 0.15578125987042743, + 4.130462730494e-17, + 0.05465258887150046, + 0.05465258887150046, + ], + linf=[ + 0.12165312668363826, + 0.1901920742264952, + 0.10059813883022554, + 0.10059813883022554, + 0.44079257431070706, + 1.1102230246251565e-16, + 0.10528911365809579, + 0.10528911365809579, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_mhd_briowu_shock_tube.jl" begin +@trixi_testset "elixir_mhd_briowu_shock_tube.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_briowu_shock_tube.jl"), - l2 = [0.17477712356961989, 0.19489623595086944, 0.3596546157640463, 0.0, 0.3723215736814466, 1.2060075775846403e-15, 0.36276754492568164, 0.0], - linf = [0.5797109945880677, 0.4372991899547103, 1.0906536287185835, 0.0, 1.0526758874956808, 5.995204332975845e-15, 1.5122922036932964, 0.0], - coverage_override = (maxiters=6,)) - end + l2=[ + 0.17477712356961989, + 0.19489623595086944, + 0.3596546157640463, + 0.0, + 0.3723215736814466, + 1.2060075775846403e-15, + 0.36276754492568164, + 0.0, + ], + linf=[ + 0.5797109945880677, + 0.4372991899547103, + 1.0906536287185835, + 0.0, + 1.0526758874956808, + 5.995204332975845e-15, + 1.5122922036932964, + 0.0, + ], + coverage_override=(maxiters = 6,)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_mhd_torrilhon_shock_tube.jl" begin +@trixi_testset "elixir_mhd_torrilhon_shock_tube.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_torrilhon_shock_tube.jl"), - l2 = [0.45700904847931145, 0.4792535936512035, 0.340651203521865, 0.4478034694296928, 0.9204708961093411, 1.3216517820475193e-16, 0.28897419402047725, 0.25521206483145126], - linf = [1.2185238171352286, 0.8913202384963431, 0.8488793580488431, 0.973083603686, 1.660723397705417, 2.220446049250313e-16, 0.6874726847741993, 0.65536978110274]) - end + l2=[ + 0.45700904847931145, + 0.4792535936512035, + 0.340651203521865, + 0.4478034694296928, + 0.9204708961093411, + 1.3216517820475193e-16, + 0.28897419402047725, + 0.25521206483145126, + ], + linf=[ + 1.2185238171352286, + 0.8913202384963431, + 0.8488793580488431, + 0.973083603686, + 1.660723397705417, + 2.220446049250313e-16, + 0.6874726847741993, + 0.65536978110274, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_mhd_torrilhon_shock_tube.jl (HLLC)" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_torrilhon_shock_tube.jl"), + surface_flux=flux_hllc, + l2=[ + 0.4573799618744708, 0.4792633358230866, 0.34064852506872795, + 0.4479668434955162, 0.9203891782415092, + 1.3216517820475193e-16, 0.28887826520860815, + 0.255281629265771, + ], + linf=[ + 1.2382842201671505, 0.8929169308132259, 0.871298623806198, + 0.9822415614542821, 1.6726170732132717, + 2.220446049250313e-16, 0.7016155888023747, + 0.6556091522071984, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_mhd_ryujones_shock_tube.jl" begin +@trixi_testset "elixir_mhd_ryujones_shock_tube.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_ryujones_shock_tube.jl"), - l2 = [0.23469781891518154, 0.3916675299696121, 0.08245195301016353, 0.1745346945706147, 0.9606363432904367, 6.608258910237605e-17, 0.21542929107153735, 0.10705457908737925], - linf = [0.6447951791685409, 0.9461857095377463, 0.35074627554617605, 0.8515177411529542, 2.0770652030507053, 1.1102230246251565e-16, 0.49670855513788204, 0.24830199967863564], - tspan = (0.0, 0.1)) - end + l2=[ + 0.23469781891518154, + 0.3916675299696121, + 0.08245195301016353, + 0.1745346945706147, + 0.9606363432904367, + 6.608258910237605e-17, + 0.21542929107153735, + 0.10705457908737925, + ], + linf=[ + 0.6447951791685409, + 0.9461857095377463, + 0.35074627554617605, + 0.8515177411529542, + 2.0770652030507053, + 1.1102230246251565e-16, + 0.49670855513788204, + 0.24830199967863564, + ], + tspan=(0.0, 0.1)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_mhd_shu_osher_shock_tube.jl" begin +@trixi_testset "elixir_mhd_shu_osher_shock_tube.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_shu_osher_shock_tube.jl"), - l2 = [1.01126210e+00, 8.27157902e+00, 1.30882545e+00, 0.00000000e+00, 5.21930435e+01, 6.56538824e-16, 1.01022340e+00, 0.00000000e+00], - linf = [2.87172004e+00, 2.26438057e+01, 4.16672442e+00, 0.00000000e+00, 1.35152372e+02, 3.44169138e-15, 2.83556069e+00, 0.00000000e+00], - tspan = (0.0, 0.2), - coverage_override = (maxiters=6,)) - end + l2=[ + 1.01126210e+00, + 8.27157902e+00, + 1.30882545e+00, + 0.00000000e+00, + 5.21930435e+01, + 6.56538824e-16, + 1.01022340e+00, + 0.00000000e+00, + ], + linf=[ + 2.87172004e+00, + 2.26438057e+01, + 4.16672442e+00, + 0.00000000e+00, + 1.35152372e+02, + 3.44169138e-15, + 2.83556069e+00, + 0.00000000e+00, + ], + tspan=(0.0, 0.2), + coverage_override=(maxiters = 6,)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_mhd_shu_osher_shock_tube.jl with flipped shock direction" begin +@trixi_testset "elixir_mhd_shu_osher_shock_tube.jl with flipped shock direction" begin # Include this elixir to make `initial_condition_shu_osher_shock_tube_flipped` available, which is used below - trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_shu_osher_shock_tube.jl"), tspan=(0.0, 0.0)) + trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_shu_osher_shock_tube.jl"), + tspan = (0.0, 0.0)) @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_shu_osher_shock_tube.jl"), - l2 = [1.01539817e+00, 8.29625810e+00, 1.29548008e+00, 0.00000000e+00, 5.23565514e+01, 3.18641825e-16, 1.00485291e+00, 0.00000000e+00], - linf = [2.92876280e+00, 2.28341581e+01, 4.11643561e+00, 0.00000000e+00, 1.36966213e+02, 1.55431223e-15, 2.80548864e+00, 0.00000000e+00], - initial_condition = initial_condition_shu_osher_shock_tube_flipped, - boundary_conditions=BoundaryConditionDirichlet(initial_condition_shu_osher_shock_tube_flipped), - tspan = (0.0, 0.2), - coverage_override = (maxiters=6,)) - end + l2=[ + 1.01539817e+00, + 8.29625810e+00, + 1.29548008e+00, + 0.00000000e+00, + 5.23565514e+01, + 3.18641825e-16, + 1.00485291e+00, + 0.00000000e+00, + ], + linf=[ + 2.92876280e+00, + 2.28341581e+01, + 4.11643561e+00, + 0.00000000e+00, + 1.36966213e+02, + 1.55431223e-15, + 2.80548864e+00, + 0.00000000e+00, + ], + initial_condition=initial_condition_shu_osher_shock_tube_flipped, + boundary_conditions=BoundaryConditionDirichlet(initial_condition_shu_osher_shock_tube_flipped), + tspan=(0.0, 0.2), + coverage_override=(maxiters = 6,)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end end end # module diff --git a/test/test_tree_1d_mhdmulti.jl b/test/test_tree_1d_mhdmulti.jl index 5214ed26d38..9bf34634886 100644 --- a/test/test_tree_1d_mhdmulti.jl +++ b/test/test_tree_1d_mhdmulti.jl @@ -8,59 +8,119 @@ include("test_trixi.jl") EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_1d_dgsem") @testset "MHD Multicomponent" begin +#! format: noindent - @trixi_testset "elixir_mhdmulti_ec.jl" begin +@trixi_testset "elixir_mhdmulti_ec.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhdmulti_ec.jl"), - l2 = [0.08166807325620999, 0.054659228513541616, 0.054659228513541616, 0.15578125987042812, - 4.130462730494e-17, 0.054652588871500665, 0.054652588871500665, 0.008307405499637766, - 0.01661481099927553, 0.03322962199855106], - linf = [0.19019207422649645, 0.10059813883022888, 0.10059813883022888, 0.4407925743107146, - 1.1102230246251565e-16, 0.10528911365809623, 0.10528911365809623, 0.01737901809766182, - 0.03475803619532364, 0.06951607239064728]) - end + l2=[0.08166807325620999, 0.054659228513541616, + 0.054659228513541616, 0.15578125987042812, + 4.130462730494e-17, 0.054652588871500665, + 0.054652588871500665, 0.008307405499637766, + 0.01661481099927553, 0.03322962199855106], + linf=[0.19019207422649645, 0.10059813883022888, + 0.10059813883022888, 0.4407925743107146, + 1.1102230246251565e-16, 0.10528911365809623, + 0.10528911365809623, 0.01737901809766182, + 0.03475803619532364, 0.06951607239064728]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_mhdmulti_ec.jl with flux_derigs_etal" begin +@trixi_testset "elixir_mhdmulti_ec.jl with flux_derigs_etal" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhdmulti_ec.jl"), - l2 = [0.08151404166186461, 0.054640238302693274, 0.054640238302693274, 0.15536125426328573, - 4.130462730494e-17, 0.054665489963920275, 0.054665489963920275, 0.008308349501359825, - 0.01661669900271965, 0.0332333980054393], - linf = [0.1824424257860952, 0.09734687137001484, 0.09734687137001484, 0.4243089502087325, - 1.1102230246251565e-16, 0.09558639591092555, 0.09558639591092555, 0.017364773041550624, - 0.03472954608310125, 0.0694590921662025], - volume_flux = flux_derigs_etal) - end + l2=[0.08151404166186461, 0.054640238302693274, + 0.054640238302693274, 0.15536125426328573, + 4.130462730494e-17, 0.054665489963920275, + 0.054665489963920275, 0.008308349501359825, + 0.01661669900271965, 0.0332333980054393], + linf=[0.1824424257860952, 0.09734687137001484, + 0.09734687137001484, 0.4243089502087325, + 1.1102230246251565e-16, 0.09558639591092555, + 0.09558639591092555, 0.017364773041550624, + 0.03472954608310125, 0.0694590921662025], + volume_flux=flux_derigs_etal) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_mhdmulti_es.jl" begin +@trixi_testset "elixir_mhdmulti_es.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhdmulti_es.jl"), - l2 = [0.07994082660130175, 0.053940174914031976, 0.053940174914031976, 0.15165513559250643, - 4.130462730494e-17, 0.05363207135290325, 0.05363207135290325, 0.008258265884659555, - 0.01651653176931911, 0.03303306353863822], - linf = [0.14101014428198477, 0.07762441749521025, 0.07762441749521025, 0.3381334453289866, - 1.1102230246251565e-16, 0.07003646400675223, 0.07003646400675223, 0.014962483760600165, - 0.02992496752120033, 0.05984993504240066]) - end + l2=[0.07994082660130175, 0.053940174914031976, + 0.053940174914031976, 0.15165513559250643, + 4.130462730494e-17, 0.05363207135290325, + 0.05363207135290325, 0.008258265884659555, + 0.01651653176931911, 0.03303306353863822], + linf=[0.14101014428198477, 0.07762441749521025, + 0.07762441749521025, 0.3381334453289866, + 1.1102230246251565e-16, 0.07003646400675223, + 0.07003646400675223, 0.014962483760600165, + 0.02992496752120033, 0.05984993504240066]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_mhdmulti_convergence.jl" begin +@trixi_testset "elixir_mhdmulti_convergence.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhdmulti_convergence.jl"), - l2 = [1.7337265267786785e-5, 0.00032976971029271364, 0.0003297697102926479, 6.194071694759044e-5, - 4.130462730494001e-17, 0.00032596825025664136, 0.0003259682502567132, 2.5467510126885455e-5, - 5.093502025377091e-5, 0.00010187004050754182], - linf = [3.877554303711845e-5, 0.0012437848638874956, 0.0012437848638876898, 0.00016431262020277781, - 1.1102230246251565e-16, 0.0012443734922607112, 0.001244373492260704, 5.691007974162332e-5, - 0.00011382015948324664, 0.00022764031896649328]) + l2=[1.7337265267786785e-5, 0.00032976971029271364, + 0.0003297697102926479, 6.194071694759044e-5, + 4.130462730494001e-17, 0.00032596825025664136, + 0.0003259682502567132, 2.5467510126885455e-5, + 5.093502025377091e-5, 0.00010187004050754182], + linf=[3.877554303711845e-5, 0.0012437848638874956, + 0.0012437848638876898, 0.00016431262020277781, + 1.1102230246251565e-16, 0.0012443734922607112, + 0.001244373492260704, 5.691007974162332e-5, + 0.00011382015948324664, 0.00022764031896649328]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 end +end - @trixi_testset "elixir_mhdmulti_briowu_shock_tube.jl" begin +@trixi_testset "elixir_mhdmulti_briowu_shock_tube.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhdmulti_briowu_shock_tube.jl"), - l2 = [0.1877830835572639, 0.3455841730726793, 0.0, 0.35413123388836687, - 8.745556626531982e-16, 0.3629920109231055, 0.0, 0.05329005553971236, - 0.10658011107942472], - linf = [0.4288187627971754, 1.0386547815614993, 0.0, 0.9541678878162702, - 5.773159728050814e-15, 1.4595119339458051, 0.0, 0.18201910908829552, - 0.36403821817659104], - coverage_override = (maxiters=6,)) + l2=[0.1877830835572639, 0.3455841730726793, 0.0, + 0.35413123388836687, + 8.745556626531982e-16, 0.3629920109231055, 0.0, + 0.05329005553971236, + 0.10658011107942472], + linf=[0.4288187627971754, 1.0386547815614993, 0.0, + 0.9541678878162702, + 5.773159728050814e-15, 1.4595119339458051, 0.0, + 0.18201910908829552, + 0.36403821817659104], + coverage_override=(maxiters = 6,)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 end - +end end end # module diff --git a/test/test_tree_1d_shallowwater.jl b/test/test_tree_1d_shallowwater.jl index cafa17edd4c..2269e858928 100644 --- a/test/test_tree_1d_shallowwater.jl +++ b/test/test_tree_1d_shallowwater.jl @@ -10,107 +10,458 @@ include("test_trixi.jl") EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_1d_dgsem") @testset "Shallow Water" begin - @trixi_testset "elixir_shallowwater_ec.jl" begin +#! format: noindent + +@trixi_testset "elixir_shallowwater_ec.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_ec.jl"), - l2 = [0.244729018751225, 0.8583565222389505, 0.07330427577586297], - linf = [2.1635021283528504, 3.8717508164234453, 1.7711213427919539], - tspan = (0.0, 0.25)) - end + l2=[0.244729018751225, 0.8583565222389505, 0.07330427577586297], + linf=[ + 2.1635021283528504, + 3.8717508164234453, + 1.7711213427919539, + ], + tspan=(0.0, 0.25)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_shallowwater_ec.jl with initial_condition_weak_blast_wave" begin +@trixi_testset "elixir_shallowwater_ec.jl with initial_condition_weak_blast_wave" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_ec.jl"), - l2 = [0.39464782107209717, 2.03880864210846, 4.1623084150546725e-10], - linf = [0.778905801278281, 3.2409883402608273, 7.419800190922032e-10], - initial_condition=initial_condition_weak_blast_wave, - tspan = (0.0, 0.25)) - end + l2=[ + 0.39464782107209717, + 2.03880864210846, + 4.1623084150546725e-10, + ], + linf=[ + 0.778905801278281, + 3.2409883402608273, + 7.419800190922032e-10, + ], + initial_condition=initial_condition_weak_blast_wave, + tspan=(0.0, 0.25)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_shallowwater_well_balanced.jl" begin +@trixi_testset "elixir_shallowwater_well_balanced.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_well_balanced.jl"), - l2 = [0.10416666834254829, 1.4352935256803184e-14, 0.10416666834254838], - linf = [1.9999999999999996, 3.248036646353028e-14, 2.0], - tspan = (0.0, 0.25)) - end + l2=[ + 0.10416666834254829, + 1.4352935256803184e-14, + 0.10416666834254838, + ], + linf=[1.9999999999999996, 3.248036646353028e-14, 2.0], + tspan=(0.0, 0.25)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_shallowwater_well_balanced.jl with FluxHydrostaticReconstruction" begin +@trixi_testset "elixir_shallowwater_well_balanced.jl with FluxHydrostaticReconstruction" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_well_balanced.jl"), - l2 = [0.10416666834254835, 1.1891029971551825e-14, 0.10416666834254838], - linf = [2.0000000000000018, 2.4019608337954543e-14, 2.0], - surface_flux=(FluxHydrostaticReconstruction(flux_lax_friedrichs, hydrostatic_reconstruction_audusse_etal), flux_nonconservative_audusse_etal), - tspan = (0.0, 0.25)) - end - - @trixi_testset "elixir_shallowwater_well_balanced_wet_dry.jl with FluxHydrostaticReconstruction" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_well_balanced_wet_dry.jl"), - l2 = [0.00965787167169024, 5.345454081916856e-14, 0.03857583749209928], - linf = [0.4999999999998892, 2.2447689894899726e-13, 1.9999999999999714], - tspan = (0.0, 0.25)) - end - - @trixi_testset "elixir_shallowwater_source_terms.jl" begin + l2=[ + 0.10416666834254835, + 1.1891029971551825e-14, + 0.10416666834254838, + ], + linf=[2.0000000000000018, 2.4019608337954543e-14, 2.0], + surface_flux=(FluxHydrostaticReconstruction(flux_lax_friedrichs, + hydrostatic_reconstruction_audusse_etal), + flux_nonconservative_audusse_etal), + tspan=(0.0, 0.25)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_shallowwater_well_balanced.jl with flux_nonconservative_ersing_etal" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_well_balanced.jl"), + l2=[ + 0.10416666834254838, + 1.6657566141935285e-14, + 0.10416666834254838, + ], + linf=[2.0000000000000004, 3.0610625110157164e-14, 2.0], + surface_flux=(flux_wintermeyer_etal, + flux_nonconservative_ersing_etal), + volume_flux=(flux_wintermeyer_etal, + flux_nonconservative_ersing_etal), + tspan=(0.0, 0.25)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_shallowwater_well_balanced_wet_dry.jl with FluxHydrostaticReconstruction" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_shallowwater_well_balanced_wet_dry.jl"), + l2=[ + 0.00965787167169024, + 5.345454081916856e-14, + 0.03857583749209928, + ], + linf=[ + 0.4999999999998892, + 2.2447689894899726e-13, + 1.9999999999999714, + ], + tspan=(0.0, 0.25), + # Soften the tolerance as test results vary between different CPUs + atol=1000 * eps()) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_shallowwater_source_terms.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_source_terms.jl"), - l2 = [0.0022363707373868713, 0.01576799981934617, 4.436491725585346e-5], - linf = [0.00893601803417754, 0.05939797350246456, 9.098379777405796e-5], - tspan = (0.0, 0.025)) - end + l2=[ + 0.0022363707373868713, + 0.01576799981934617, + 4.436491725585346e-5, + ], + linf=[ + 0.00893601803417754, + 0.05939797350246456, + 9.098379777405796e-5, + ], + tspan=(0.0, 0.025)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_shallowwater_source_terms.jl with flux_hll" begin +@trixi_testset "elixir_shallowwater_source_terms.jl with flux_hll" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_source_terms.jl"), - l2 = [0.0022758146627220154, 0.015864082886204556, 4.436491725585346e-5], - linf = [0.008457195427364006, 0.057201667446161064, 9.098379777405796e-5], - tspan = (0.0, 0.025), surface_flux=(flux_hll, flux_nonconservative_fjordholm_etal)) - end - - @trixi_testset "elixir_shallowwater_source_terms_dirichlet.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_source_terms_dirichlet.jl"), - l2 = [0.0022851099219788917, 0.01560453773635554, 4.43649172558535e-5], - linf = [0.008934615705174398, 0.059403169140869405, 9.098379777405796e-5], - tspan = (0.0, 0.025)) - end - - @trixi_testset "elixir_shallowwater_source_terms_dirichlet.jl with FluxHydrostaticReconstruction" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_source_terms_dirichlet.jl"), - l2 = [0.0022956052733432287, 0.015540053559855601, 4.43649172558535e-5], - linf = [0.008460440313118323, 0.05720939349382359, 9.098379777405796e-5], - surface_flux=(FluxHydrostaticReconstruction(flux_hll, hydrostatic_reconstruction_audusse_etal), flux_nonconservative_audusse_etal), - tspan = (0.0, 0.025)) - end - - @trixi_testset "elixir_shallowwater_well_balanced_nonperiodic.jl with Dirichlet boundary" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_well_balanced_nonperiodic.jl"), - l2 = [1.725964362045055e-8, 5.0427180314307505e-16, 1.7259643530442137e-8], - linf = [3.844551077492042e-8, 3.469453422316143e-15, 3.844551077492042e-8], - tspan = (0.0, 0.25)) - end - - @trixi_testset "elixir_shallowwater_well_balanced_nonperiodic.jl with wall boundary" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_well_balanced_nonperiodic.jl"), - l2 = [1.7259643614361866e-8, 3.5519018243195145e-16, 1.7259643530442137e-8], - linf = [3.844551010878661e-8, 9.846474508971374e-16, 3.844551077492042e-8], - tspan = (0.0, 0.25), - boundary_condition = boundary_condition_slip_wall) - end - - @trixi_testset "elixir_shallowwater_shock_capturing.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_shock_capturing.jl"), - l2 = [0.07424140641160326, 0.2148642632748155, 0.0372579849000542], - linf = [1.1209754279344226, 1.3230788645853582, 0.8646939843534251], - tspan = (0.0, 0.05)) - end - - @trixi_testset "elixir_shallowwater_beach.jl" begin + l2=[ + 0.0022758146627220154, + 0.015864082886204556, + 4.436491725585346e-5, + ], + linf=[ + 0.008457195427364006, + 0.057201667446161064, + 9.098379777405796e-5, + ], + tspan=(0.0, 0.025), + surface_flux=(flux_hll, flux_nonconservative_fjordholm_etal)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_shallowwater_source_terms.jl with flux_nonconservative_ersing_etal" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_source_terms.jl"), + l2=[ + 0.005774284062933275, + 0.017408601639513584, + 4.43649172561843e-5, + ], + linf=[ + 0.01639116193303547, + 0.05102877460799604, + 9.098379777450205e-5, + ], + surface_flux=(flux_wintermeyer_etal, + flux_nonconservative_ersing_etal), + volume_flux=(flux_wintermeyer_etal, + flux_nonconservative_ersing_etal), + tspan=(0.0, 0.025)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_shallowwater_source_terms_dirichlet.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_shallowwater_source_terms_dirichlet.jl"), + l2=[ + 0.0022851099219788917, + 0.01560453773635554, + 4.43649172558535e-5, + ], + linf=[ + 0.008934615705174398, + 0.059403169140869405, + 9.098379777405796e-5, + ], + tspan=(0.0, 0.025)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_shallowwater_source_terms_dirichlet.jl with FluxHydrostaticReconstruction" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_shallowwater_source_terms_dirichlet.jl"), + l2=[ + 0.0022956052733432287, + 0.015540053559855601, + 4.43649172558535e-5, + ], + linf=[ + 0.008460440313118323, + 0.05720939349382359, + 9.098379777405796e-5, + ], + surface_flux=(FluxHydrostaticReconstruction(flux_hll, + hydrostatic_reconstruction_audusse_etal), + flux_nonconservative_audusse_etal), + tspan=(0.0, 0.025)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_shallowwater_well_balanced_nonperiodic.jl with Dirichlet boundary" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_shallowwater_well_balanced_nonperiodic.jl"), + l2=[ + 1.725964362045055e-8, + 5.0427180314307505e-16, + 1.7259643530442137e-8, + ], + linf=[ + 3.844551077492042e-8, + 3.469453422316143e-15, + 3.844551077492042e-8, + ], + tspan=(0.0, 0.25)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_shallowwater_well_balanced_nonperiodic.jl with wall boundary" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_shallowwater_well_balanced_nonperiodic.jl"), + l2=[ + 1.7259643614361866e-8, + 3.5519018243195145e-16, + 1.7259643530442137e-8, + ], + linf=[ + 3.844551010878661e-8, + 9.846474508971374e-16, + 3.844551077492042e-8, + ], + tspan=(0.0, 0.25), + boundary_condition=boundary_condition_slip_wall) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_shallowwater_shock_capturing.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_shallowwater_shock_capturing.jl"), + l2=[0.07424140641160326, 0.2148642632748155, 0.0372579849000542], + linf=[ + 1.1209754279344226, + 1.3230788645853582, + 0.8646939843534251, + ], + tspan=(0.0, 0.05)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_shallowwater_beach.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_beach.jl"), - l2 = [0.17979210479598923, 1.2377495706611434, 6.289818963361573e-8], - linf = [0.845938394800688, 3.3740800777086575, 4.4541473087633676e-7], - tspan = (0.0, 0.05)) - end + l2=[ + 0.17979210479598923, + 1.2377495706611434, + 6.289818963361573e-8, + ], + linf=[ + 0.845938394800688, + 3.3740800777086575, + 4.4541473087633676e-7, + ], + tspan=(0.0, 0.05), + atol=3e-10) # see https://github.com/trixi-framework/Trixi.jl/issues/1617 + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_shallowwater_parabolic_bowl.jl" begin +@trixi_testset "elixir_shallowwater_parabolic_bowl.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_parabolic_bowl.jl"), - l2 = [8.965981683033589e-5, 1.8565707397810857e-5, 4.1043039226164336e-17], - linf = [0.00041080213807871235, 0.00014823261488938177, 2.220446049250313e-16], - tspan = (0.0, 0.05)) - end + l2=[ + 8.965981683033589e-5, + 1.8565707397810857e-5, + 4.1043039226164336e-17, + ], + linf=[ + 0.00041080213807871235, + 0.00014823261488938177, + 2.220446049250313e-16, + ], + tspan=(0.0, 0.05)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_shallow_water_quasi_1d_source_terms.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_shallow_water_quasi_1d_source_terms.jl"), + l2=[ + 6.37048760275098e-5, + 0.0002745658116815704, + 4.436491725647962e-6, + 8.872983451152218e-6, + ], + linf=[ + 0.00026747526881631956, + 0.0012106730729152249, + 9.098379777500165e-6, + 1.8196759554278685e-5, + ], + tspan=(0.0, 0.05)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_shallowwater_quasi_1d_well_balanced.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_shallowwater_quasi_1d_well_balanced.jl"), + l2=[ + 1.4250229186905198e-14, + 2.495109919406496e-12, + 7.408599286788738e-17, + 2.7205812409138776e-16, + ], + linf=[ + 5.284661597215745e-14, + 2.74056233065078e-12, + 2.220446049250313e-16, + 8.881784197001252e-16, + ], + tspan=(0.0, 100.0)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_shallowwater_quasi_1d_discontinuous.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_shallowwater_quasi_1d_discontinuous.jl"), + l2=[ + 0.02843233740533314, + 0.14083324483705398, + 0.0054554472558998, + 0.005455447255899814, + ], + linf=[ + 0.26095842440037487, + 0.45919004549253795, + 0.09999999999999983, + 0.10000000000000009, + ],) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end end end # module diff --git a/test/test_tree_1d_shallowwater_twolayer.jl b/test/test_tree_1d_shallowwater_twolayer.jl index 8372d0d4676..180fb3ec3b3 100644 --- a/test/test_tree_1d_shallowwater_twolayer.jl +++ b/test/test_tree_1d_shallowwater_twolayer.jl @@ -10,43 +10,65 @@ include("test_trixi.jl") EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_1d_dgsem") @testset "Shallow Water Two layer" begin - @trixi_testset "elixir_shallowwater_twolayer_convergence.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_twolayer_convergence.jl"), - l2 = [0.0050681532925156945, 0.002089013899370176, 0.005105544300292713, 0.002526442122643306, - 0.0004744186597732706], - linf = [0.022256679217306008, 0.005421833004652266, 0.02233993939574197, 0.008765261497422516, - 0.0008992474511784199], - tspan = (0.0, 0.25)) - end - - @trixi_testset "elixir_shallowwater_twolayer_convergence.jl with flux_es_fjordholm_etal" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_twolayer_convergence.jl"), - l2 = [0.0027681377074701345, 0.0018007543202559165, 0.0028036917433720576, - 0.0013980358596935737, 0.0004744186597732706], - linf = [0.005699303919826093, 0.006432952918256296, 0.0058507082844360125, 0.002717615543961216, - 0.0008992474511784199], - surface_flux=(flux_es_fjordholm_etal, flux_nonconservative_fjordholm_etal), - tspan = (0.0, 0.25)) - end - - @trixi_testset "elixir_shallowwater_twolayer_well_balanced.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_twolayer_well_balanced.jl"), - l2 = [8.949288784402005e-16, 4.0636427176237915e-17, 0.001002881985401548, - 2.133351105037203e-16, 0.0010028819854016578], - linf = [2.6229018956769323e-15, 1.878451903240623e-16, 0.005119880996670156, - 8.003199803957679e-16, 0.005119880996670666], - tspan = (0.0, 0.25)) - end - - @trixi_testset "elixir_shallowwater_twolayer_dam_break.jl with flux_lax_friedrichs" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_twolayer_dam_break.jl"), - l2 = [0.10010269243463918, 0.5668733957648654, 0.08759617327649398, - 0.4538443183566172, 0.013638618139749523], - linf = [0.5854202777756559, 2.1278930820498934, 0.5193686074348809, 1.8071213168086229, 0.5], - surface_flux = (flux_lax_friedrichs, flux_nonconservative_fjordholm_etal), - tspan = (0.0, 0.25)) - end + @trixi_testset "elixir_shallowwater_twolayer_convergence.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_shallowwater_twolayer_convergence.jl"), + l2=[0.005012009872109003, 0.002091035326731071, + 0.005049271397924551, + 0.0024633066562966574, 0.0004744186597732739], + linf=[0.0213772149343594, 0.005385752427290447, + 0.02175023787351349, + 0.008212004668840978, 0.0008992474511784199], + tspan=(0.0, 0.25)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end + end + @trixi_testset "elixir_shallowwater_twolayer_well_balanced.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_shallowwater_twolayer_well_balanced.jl"), + l2=[8.949288784402005e-16, 4.0636427176237915e-17, + 0.001002881985401548, + 2.133351105037203e-16, 0.0010028819854016578], + linf=[2.6229018956769323e-15, 1.878451903240623e-16, + 0.005119880996670156, + 8.003199803957679e-16, 0.005119880996670666], + tspan=(0.0, 0.25)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end + end + + @trixi_testset "elixir_shallowwater_twolayer_dam_break.jl with flux_lax_friedrichs" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_shallowwater_twolayer_dam_break.jl"), + l2=[0.1000774903431289, 0.5670692949571057, 0.08764242501014498, + 0.45412307886094555, 0.013638618139749523], + linf=[0.586718937495144, 2.1215606128311584, 0.5185911311186155, + 1.820382495072612, 0.5], + surface_flux=(flux_lax_friedrichs, + flux_nonconservative_ersing_etal), + tspan=(0.0, 0.25)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end + end end end # module diff --git a/test/test_tree_2d_acoustics.jl b/test/test_tree_2d_acoustics.jl index b443573e3ac..89bccbf8ca1 100644 --- a/test/test_tree_2d_acoustics.jl +++ b/test/test_tree_2d_acoustics.jl @@ -8,40 +8,137 @@ include("test_trixi.jl") EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") @testset "Acoustic Perturbation" begin - @trixi_testset "elixir_acoustics_convergence.jl" begin +#! format: noindent + +@trixi_testset "elixir_acoustics_convergence.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_acoustics_convergence.jl"), - l2 = [0.0019921138796370834, 0.002090394698052287, 0.0006091925854593805, 0.0, 0.0, 0.0, 0.0], - linf = [0.00769282588065634, 0.008276649669227254, 0.004196479023954813, 0.0, 0.0, 0.0, 0.0]) - end + l2=[ + 0.0019921138796370834, + 0.002090394698052287, + 0.0006091925854593805, + 0.0, + 0.0, + 0.0, + 0.0, + ], + linf=[ + 0.00769282588065634, + 0.008276649669227254, + 0.004196479023954813, + 0.0, + 0.0, + 0.0, + 0.0, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_acoustics_gauss.jl" begin +@trixi_testset "elixir_acoustics_gauss.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_acoustics_gauss.jl"), - l2 = [0.08005276517890283, 0.08005276517890268, 0.4187202920734123, 0.0, 0.0, 0.0, 0.0], - linf = [0.17261097190220992, 0.17261097190220973, 1.13601894068238, 0.0, 0.0, 0.0, 0.0]) - end + l2=[ + 0.08005276517890283, + 0.08005276517890268, + 0.4187202920734123, + 0.0, + 0.0, + 0.0, + 0.0, + ], + linf=[ + 0.17261097190220992, + 0.17261097190220973, + 1.13601894068238, + 0.0, + 0.0, + 0.0, + 0.0, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_acoustics_gaussian_source.jl" begin +@trixi_testset "elixir_acoustics_gaussian_source.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_acoustics_gaussian_source.jl"), - l2 = [0.004296394903650806, 0.004241280404758938, 0.006269684906035964, 0.0, 0.0, 0.0, 0.0], - linf = [0.03970270697049378, 0.04151096349298151, 0.0640019829058819, 0.0, 0.0, 0.0, 0.0]) - end + l2=[ + 0.004296394903650806, + 0.004241280404758938, + 0.006269684906035964, + 0.0, + 0.0, + 0.0, + 0.0, + ], + linf=[ + 0.03970270697049378, + 0.04151096349298151, + 0.0640019829058819, + 0.0, + 0.0, + 0.0, + 0.0, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_acoustics_gauss_wall.jl" begin +@trixi_testset "elixir_acoustics_gauss_wall.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_acoustics_gauss_wall.jl"), - l2 = [0.019419398248465843, 0.019510701017551826, 0.04818246051887614, - 7.382060834820337e-17, 0.0, 1.4764121669640674e-16, 1.4764121669640674e-16], - linf = [0.18193631937316496, 0.1877464607867628, 1.0355388011792845, - 2.220446049250313e-16, 0.0, 4.440892098500626e-16, 4.440892098500626e-16]) - end + l2=[0.019419398248465843, 0.019510701017551826, + 0.04818246051887614, + 7.382060834820337e-17, 0.0, 1.4764121669640674e-16, + 1.4764121669640674e-16], + linf=[0.18193631937316496, 0.1877464607867628, + 1.0355388011792845, + 2.220446049250313e-16, 0.0, 4.440892098500626e-16, + 4.440892098500626e-16]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_acoustics_monopole.jl" begin +@trixi_testset "elixir_acoustics_monopole.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_acoustics_monopole.jl"), - l2 = [0.006816790293009947, 0.0065068948357351625, 0.008724512056168938, - 0.0009894398191644543, 0.0, 7.144325530679576e-17, 7.144325530679576e-17], - linf = [1.000633375007386, 0.5599788929862504, 0.5738432957070382, - 0.015590137026938428, 0.0, 2.220446049250313e-16, 2.220446049250313e-16], - maxiters=50) - end + l2=[0.006816790293009947, 0.0065068948357351625, + 0.008724512056168938, + 0.0009894398191644543, 0.0, 7.144325530679576e-17, + 7.144325530679576e-17], + linf=[1.000633375007386, 0.5599788929862504, 0.5738432957070382, + 0.015590137026938428, 0.0, 2.220446049250313e-16, + 2.220446049250313e-16], + maxiters=50) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end end -end # module \ No newline at end of file +end # module diff --git a/test/test_tree_2d_advection.jl b/test/test_tree_2d_advection.jl index 973d0caf88b..b111651aa6f 100644 --- a/test/test_tree_2d_advection.jl +++ b/test/test_tree_2d_advection.jl @@ -8,198 +8,349 @@ include("test_trixi.jl") EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") @testset "Linear scalar advection" begin - @trixi_testset "elixir_advection_basic.jl" begin +#! format: noindent + +@trixi_testset "elixir_advection_basic.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_basic.jl"), - # Expected errors are exactly the same as in the parallel test! - l2 = [8.311947673061856e-6], - linf = [6.627000273229378e-5], - # Let the small basic test run to the end - coverage_override = (maxiters=10^5,)) - end - - @trixi_testset "elixir_advection_extended.jl with polydeg=1" begin + # Expected errors are exactly the same as in the parallel test! + l2=[8.311947673061856e-6], + linf=[6.627000273229378e-5], + # Let the small basic test run to the end + coverage_override=(maxiters = 10^5,)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_advection_extended.jl with polydeg=1" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_extended.jl"), - l2 = [0.02134571266411136], - linf = [0.04347734797775926], - polydeg=1) - end - - @trixi_testset "elixir_advection_restart.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_restart.jl"), - # Expected errors are exactly the same as in the parallel test! - l2 = [7.81674284320524e-6], - linf = [6.314906965243505e-5]) - end - - @trixi_testset "elixir_advection_mortar.jl" begin + l2=[0.02134571266411136], + linf=[0.04347734797775926], + polydeg=1) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_advection_restart.jl" begin + using OrdinaryDiffEq: SSPRK43 + println("═"^100) + println(joinpath(EXAMPLES_DIR, "elixir_advection_extended.jl")) + trixi_include(@__MODULE__, joinpath(EXAMPLES_DIR, "elixir_advection_extended.jl"), + alg = SSPRK43(), tspan = (0.0, 10.0)) + l2_expected, linf_expected = analysis_callback(sol) + + println("═"^100) + println(joinpath(EXAMPLES_DIR, "elixir_advection_restart.jl")) + # Errors are exactly the same as in the elixir_advection_extended.jl + trixi_include(@__MODULE__, joinpath(EXAMPLES_DIR, "elixir_advection_restart.jl"), + alg = SSPRK43()) + l2_actual, linf_actual = analysis_callback(sol) + + @test l2_actual == l2_expected + @test linf_actual == linf_expected +end + +@trixi_testset "elixir_advection_mortar.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_mortar.jl"), - # Expected errors are exactly the same as in the parallel test! - l2 = [0.0015188466707237375], - linf = [0.008446655719187679]) + # Expected errors are exactly the same as in the parallel test! + l2=[0.0015188466707237375], + linf=[0.008446655719187679]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 end - end +end - @trixi_testset "elixir_advection_amr.jl" begin +@trixi_testset "elixir_advection_amr.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_amr.jl"), - # Expected errors are exactly the same as in the parallel test! - l2 = [4.913300828257469e-5], - linf = [0.00045263895394385967], - # Let this test run to the end to cover some AMR code - coverage_override = (maxiters=10^5,)) - end - - @trixi_testset "elixir_advection_amr_nonperiodic.jl" begin + # Expected errors are exactly the same as in the parallel test! + l2=[4.913300828257469e-5], + linf=[0.00045263895394385967], + # Let this test run to the end to cover some AMR code + coverage_override=(maxiters = 10^5,)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_advection_amr_nonperiodic.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_amr_nonperiodic.jl"), - # Expected errors are exactly the same as in the parallel test! - l2 = [3.2207388565869075e-5], - linf = [0.0007508059772436404], - coverage_override = (maxiters=6,)) - end - - @trixi_testset "elixir_advection_amr_solution_independent.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_amr_solution_independent.jl"), - l2 = [4.949660644033807e-5], - linf = [0.0004867846262313763], - coverage_override = (maxiters=6,)) - end - - @trixi_testset "elixir_advection_amr_visualization.jl" begin + # Expected errors are exactly the same as in the parallel test! + l2=[3.2207388565869075e-5], + linf=[0.0007508059772436404], + coverage_override=(maxiters = 6,)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_advection_amr_solution_independent.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_advection_amr_solution_independent.jl"), + l2=[4.949660644033807e-5], + linf=[0.0004867846262313763], + coverage_override=(maxiters = 6,)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_advection_amr_visualization.jl" begin # To make CI tests work, disable showing a plot window with the GR backend of the Plots package # Xref: https://github.com/jheinen/GR.jl/issues/278 # Xref: https://github.com/JuliaPlots/Plots.jl/blob/8cc6d9d48755ba452a2835f9b89d3880e9945377/test/runtests.jl#L103 if !isinteractive() - restore = get(ENV, "GKSwstype", nothing) - ENV["GKSwstype"] = "100" + restore = get(ENV, "GKSwstype", nothing) + ENV["GKSwstype"] = "100" end @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_amr_visualization.jl"), - l2 = [0.0007225529919720868], - linf = [0.005954447875428925], - coverage_override = (maxiters=6,)) + l2=[0.0007225529919720868], + linf=[0.005954447875428925], + coverage_override=(maxiters = 6,)) # Restore GKSwstype to previous value (if it was set) if !isinteractive() - if isnothing(restore) - delete!(ENV, "GKSwstype") - else - ENV["GKSwstype"] = restore - end + if isnothing(restore) + delete!(ENV, "GKSwstype") + else + ENV["GKSwstype"] = restore + end end - end +end - @trixi_testset "elixir_advection_timeintegration.jl" begin +@trixi_testset "elixir_advection_timeintegration.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_timeintegration.jl"), - l2 = [2.4976030518356626e-5], - linf = [0.0005531580316338533], - # Let this test terminate by time instead of maxiters to cover some lines - # in time_integration/methods_2N.jl - coverage_override = (maxiters=10^5, tspan=(0.0, 0.1))) - end - - @trixi_testset "elixir_advection_timeintegration.jl with carpenter_kennedy_erk43" begin + l2=[2.4976030518356626e-5], + linf=[0.0005531580316338533], + # Let this test terminate by time instead of maxiters to cover some lines + # in time_integration/methods_2N.jl + coverage_override=(maxiters = 10^5, tspan = (0.0, 0.1))) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 + end +end +end + +@trixi_testset "elixir_advection_timeintegration.jl with carpenter_kennedy_erk43" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_timeintegration.jl"), - l2 = [2.5314747030031457e-5], - linf = [0.0005437136621948904], - ode_algorithm=Trixi.CarpenterKennedy2N43(), - cfl = 1.0) - end + l2=[2.5314747030031457e-5], + linf=[0.0005437136621948904], + ode_algorithm=Trixi.CarpenterKennedy2N43(), + cfl=1.0) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 + end +end - @trixi_testset "elixir_advection_timeintegration.jl with carpenter_kennedy_erk43 with maxiters=1" begin +@trixi_testset "elixir_advection_timeintegration.jl with carpenter_kennedy_erk43 with maxiters=1" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_timeintegration.jl"), - l2 = [1.2135350502911197e-5], - linf = [9.999985420537649e-5], - ode_algorithm=Trixi.CarpenterKennedy2N43(), - cfl = 1.0, - maxiters = 1) - end - - @trixi_testset "elixir_advection_timeintegration.jl with parsani_ketcheson_deconinck_erk94" begin + l2=[1.2135350502911197e-5], + linf=[9.999985420537649e-5], + ode_algorithm=Trixi.CarpenterKennedy2N43(), + cfl=1.0, + maxiters=1) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 + end +end + +@trixi_testset "elixir_advection_timeintegration.jl with parsani_ketcheson_deconinck_erk94" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_timeintegration.jl"), - l2 = [2.4976673477385313e-5], - linf = [0.0005534166916640881], - ode_algorithm=Trixi.ParsaniKetchesonDeconinck3Sstar94()) - end + l2=[2.4976673477385313e-5], + linf=[0.0005534166916640881], + ode_algorithm=Trixi.ParsaniKetchesonDeconinck3Sstar94()) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 + end +end - @trixi_testset "elixir_advection_timeintegration.jl with parsani_ketcheson_deconinck_erk32" begin +@trixi_testset "elixir_advection_timeintegration.jl with parsani_ketcheson_deconinck_erk32" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_timeintegration.jl"), - l2 = [3.667894656471403e-5], - linf = [0.0005799465470165757], - ode_algorithm=Trixi.ParsaniKetchesonDeconinck3Sstar32(), - cfl = 1.0) - end + l2=[3.667894656471403e-5], + linf=[0.0005799465470165757], + ode_algorithm=Trixi.ParsaniKetchesonDeconinck3Sstar32(), + cfl=1.0) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 + end +end - @trixi_testset "elixir_advection_timeintegration.jl with parsani_ketcheson_deconinck_erk32 with maxiters=1" begin +@trixi_testset "elixir_advection_timeintegration.jl with parsani_ketcheson_deconinck_erk32 with maxiters=1" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_timeintegration.jl"), - l2 = [1.2198725469737875e-5], - linf = [9.977247740793407e-5], - ode_algorithm=Trixi.ParsaniKetchesonDeconinck3Sstar32(), - cfl = 1.0, - maxiters = 1) - end - - @trixi_testset "elixir_advection_callbacks.jl" begin + l2=[1.2198725469737875e-5], + linf=[9.977247740793407e-5], + ode_algorithm=Trixi.ParsaniKetchesonDeconinck3Sstar32(), + cfl=1.0, + maxiters=1) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 + end +end + +@trixi_testset "elixir_advection_callbacks.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_callbacks.jl"), - l2 = [8.311947673061856e-6], - linf = [6.627000273229378e-5]) - end + l2=[8.311947673061856e-6], + linf=[6.627000273229378e-5]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end end # Coverage test for all initial conditions @testset "Linear scalar advection: Tests for initial conditions" begin - # Linear scalar advection - @trixi_testset "elixir_advection_extended.jl with initial_condition_sin_sin" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_extended.jl"), - l2 = [0.0001420618061089383], - linf = [0.0007140570281718439], - maxiters = 1, - initial_condition = Trixi.initial_condition_sin_sin) - end + # Linear scalar advection + @trixi_testset "elixir_advection_extended.jl with initial_condition_sin_sin" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_extended.jl"), + l2=[0.0001420618061089383], + linf=[0.0007140570281718439], + maxiters=1, + initial_condition=Trixi.initial_condition_sin_sin) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end + end - @trixi_testset "elixir_advection_extended.jl with initial_condition_constant" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_extended.jl"), - l2 = [3.8302867746057483e-16], - linf = [1.3322676295501878e-15], - maxiters = 1, - initial_condition = initial_condition_constant) - end + @trixi_testset "elixir_advection_extended.jl with initial_condition_constant" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_extended.jl"), + l2=[3.8302867746057483e-16], + linf=[1.3322676295501878e-15], + maxiters=1, + initial_condition=initial_condition_constant) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end + end - @trixi_testset "elixir_advection_extended.jl with initial_condition_linear_x_y" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_extended.jl"), - l2 = [2.7276160570381226e-16], - linf = [5.10702591327572e-15], - maxiters = 1, - initial_condition = Trixi.initial_condition_linear_x_y, - boundary_conditions = Trixi.boundary_condition_linear_x_y, - periodicity=false) - end - - @trixi_testset "elixir_advection_extended.jl with initial_condition_linear_x" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_extended.jl"), - l2 = [1.5121648229368207e-16], - linf = [1.3322676295501878e-15], - maxiters = 1, - initial_condition = Trixi.initial_condition_linear_x, - boundary_conditions = Trixi.boundary_condition_linear_x, - periodicity=false) - end - - @trixi_testset "elixir_advection_extended.jl with initial_condition_linear_y" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_extended.jl"), - l2 = [1.714292614252588e-16], - linf = [2.220446049250313e-15], - maxiters = 1, - initial_condition = Trixi.initial_condition_linear_y, - boundary_conditions = Trixi.boundary_condition_linear_y, - periodicity=false) - end + @trixi_testset "elixir_advection_extended.jl with initial_condition_linear_x_y" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_extended.jl"), + l2=[2.7276160570381226e-16], + linf=[5.10702591327572e-15], + maxiters=1, + initial_condition=Trixi.initial_condition_linear_x_y, + boundary_conditions=Trixi.boundary_condition_linear_x_y, + periodicity=false) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end + end + + @trixi_testset "elixir_advection_extended.jl with initial_condition_linear_x" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_extended.jl"), + l2=[1.5121648229368207e-16], + linf=[1.3322676295501878e-15], + maxiters=1, + initial_condition=Trixi.initial_condition_linear_x, + boundary_conditions=Trixi.boundary_condition_linear_x, + periodicity=false) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end + end + + @trixi_testset "elixir_advection_extended.jl with initial_condition_linear_y" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_extended.jl"), + l2=[1.714292614252588e-16], + linf=[2.220446049250313e-15], + maxiters=1, + initial_condition=Trixi.initial_condition_linear_y, + boundary_conditions=Trixi.boundary_condition_linear_y, + periodicity=false) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end + end end end # module diff --git a/test/test_tree_2d_euler.jl b/test/test_tree_2d_euler.jl index e1e3ad32e7d..65899cd5263 100644 --- a/test/test_tree_2d_euler.jl +++ b/test/test_tree_2d_euler.jl @@ -8,288 +8,886 @@ include("test_trixi.jl") EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") @testset "Compressible Euler" begin - @trixi_testset "elixir_euler_source_terms.jl" begin +#! format: noindent + +@trixi_testset "elixir_euler_source_terms.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms.jl"), - l2 = [9.321181253186009e-7, 1.4181210743438511e-6, 1.4181210743487851e-6, 4.824553091276693e-6], - linf = [9.577246529612893e-6, 1.1707525976012434e-5, 1.1707525976456523e-5, 4.8869615580926506e-5]) - end + l2=[ + 9.321181253186009e-7, + 1.4181210743438511e-6, + 1.4181210743487851e-6, + 4.824553091276693e-6, + ], + linf=[ + 9.577246529612893e-6, + 1.1707525976012434e-5, + 1.1707525976456523e-5, + 4.8869615580926506e-5, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_convergence_pure_fv.jl" begin +@trixi_testset "elixir_euler_convergence_pure_fv.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_convergence_pure_fv.jl"), - l2 = [0.026440292358506527, 0.013245905852168414, 0.013245905852168479, 0.03912520302609374], - linf = [0.042130817806361964, 0.022685499230187034, 0.022685499230187922, 0.06999771202145322]) - end + l2=[ + 0.026440292358506527, + 0.013245905852168414, + 0.013245905852168479, + 0.03912520302609374, + ], + linf=[ + 0.042130817806361964, + 0.022685499230187034, + 0.022685499230187922, + 0.06999771202145322, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_density_wave.jl" begin +@trixi_testset "elixir_euler_density_wave.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_density_wave.jl"), - l2 = [0.0010600778457964775, 0.00010600778457634275, 0.00021201556915872665, 2.650194614399671e-5], - linf = [0.006614198043413566, 0.0006614198043973507, 0.001322839608837334, 0.000165354951256802], - tspan = (0.0, 0.5)) - end - - @trixi_testset "elixir_euler_source_terms_nonperiodic.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms_nonperiodic.jl"), - l2 = [2.259440511766445e-6, 2.318888155713922e-6, 2.3188881557894307e-6, 6.3327863238858925e-6], - linf = [1.498738264560373e-5, 1.9182011928187137e-5, 1.918201192685487e-5, 6.0526717141407005e-5]) - end - - @trixi_testset "elixir_euler_ec.jl" begin + l2=[ + 0.0010600778457964775, + 0.00010600778457634275, + 0.00021201556915872665, + 2.650194614399671e-5, + ], + linf=[ + 0.006614198043413566, + 0.0006614198043973507, + 0.001322839608837334, + 0.000165354951256802, + ], + tspan=(0.0, 0.5)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_source_terms_nonperiodic.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_source_terms_nonperiodic.jl"), + l2=[ + 2.259440511766445e-6, + 2.318888155713922e-6, + 2.3188881557894307e-6, + 6.3327863238858925e-6, + ], + linf=[ + 1.498738264560373e-5, + 1.9182011928187137e-5, + 1.918201192685487e-5, + 6.0526717141407005e-5, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_ec.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_ec.jl"), - l2 = [0.061751715597716854, 0.05018223615408711, 0.05018989446443463, 0.225871559730513], - linf = [0.29347582879608825, 0.31081249232844693, 0.3107380389947736, 1.0540358049885143]) - end + l2=[ + 0.061751715597716854, + 0.05018223615408711, + 0.05018989446443463, + 0.225871559730513, + ], + linf=[ + 0.29347582879608825, + 0.31081249232844693, + 0.3107380389947736, + 1.0540358049885143, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_ec.jl with flux_kennedy_gruber" begin +@trixi_testset "elixir_euler_ec.jl with flux_kennedy_gruber" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_ec.jl"), - l2 = [0.03481471610306124, 0.027694280613944234, 0.027697905866996532, 0.12932052501462554], - linf = [0.31052098400669004, 0.3481295959664616, 0.34807152194137336, 1.1044947556170719], - maxiters = 10, - surface_flux = flux_kennedy_gruber, - volume_flux = flux_kennedy_gruber) - end - - @trixi_testset "elixir_euler_ec.jl with flux_chandrashekar" begin + l2=[ + 0.03481471610306124, + 0.027694280613944234, + 0.027697905866996532, + 0.12932052501462554, + ], + linf=[ + 0.31052098400669004, + 0.3481295959664616, + 0.34807152194137336, + 1.1044947556170719, + ], + maxiters=10, + surface_flux=flux_kennedy_gruber, + volume_flux=flux_kennedy_gruber) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_ec.jl with flux_chandrashekar" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_ec.jl"), - l2 = [0.03481122603050542, 0.027662840593087695, 0.027665658732350273, 0.12927455860656786], - linf = [0.3110089578739834, 0.34888111987218107, 0.3488278669826813, 1.1056349046774305], - maxiters = 10, - surface_flux = flux_chandrashekar, - volume_flux = flux_chandrashekar) - end - - @trixi_testset "elixir_euler_shockcapturing.jl" begin + l2=[ + 0.03481122603050542, + 0.027662840593087695, + 0.027665658732350273, + 0.12927455860656786, + ], + linf=[ + 0.3110089578739834, + 0.34888111987218107, + 0.3488278669826813, + 1.1056349046774305, + ], + maxiters=10, + surface_flux=flux_chandrashekar, + volume_flux=flux_chandrashekar) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_shockcapturing.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_shockcapturing.jl"), - l2 = [0.05380629130119074, 0.04696798008325309, 0.04697067787841479, 0.19687382235494968], - linf = [0.18527440131928286, 0.2404798030563736, 0.23269573860381076, 0.6874012187446894]) - end + l2=[ + 0.05380629130119074, + 0.04696798008325309, + 0.04697067787841479, + 0.19687382235494968, + ], + linf=[ + 0.18527440131928286, + 0.2404798030563736, + 0.23269573860381076, + 0.6874012187446894, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_shockcapturing_subcell.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_shockcapturing_subcell.jl"), - l2 = [0.08508147906199143, 0.04510299017724501, 0.045103019801950375, 0.6930704343869766], - linf = [0.31123546471463326, 0.5616274869594462, 0.5619692712224448, 2.88670199345138]) - end +@trixi_testset "elixir_euler_shockcapturing_subcell.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_shockcapturing_subcell.jl"), + l2=[ + 0.08508152653623638, + 0.04510301725066843, + 0.04510304668512745, + 0.6930705064715306, + ], + linf=[ + 0.31136518019691406, + 0.5617651935473419, + 0.5621200790240503, + 2.8866869108596056, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 + end +end - @trixi_testset "elixir_euler_blast_wave.jl" begin +@trixi_testset "elixir_euler_blast_wave.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave.jl"), - l2 = [0.14170569763947993, 0.11647068900798814, 0.11647072556898294, 0.3391989213659599], - linf = [1.6544204510794196, 1.35194638484646, 1.3519463848472744, 1.831228461662809], - maxiters = 30) - end - - @trixi_testset "elixir_euler_blast_wave_neuralnetwork_perssonperaire.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave_neuralnetwork_perssonperaire.jl"), - l2 = [0.4758794741390833, 0.21045415565179362, 0.21045325630191866, 0.7022517958549878], - linf = [1.710832148442441, 0.9711663578827681, 0.9703787873632452, 2.9619758810532653], - initial_refinement_level = 4, - maxiters = 50) - end - - @trixi_testset "elixir_euler_blast_wave_neuralnetwork_rayhesthaven.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave_neuralnetwork_rayhesthaven.jl"), - l2 = [0.472445774440313, 0.2090782039442978, 0.20885558673697927, 0.700569533591275], - linf = [1.7066492792835155, 0.9856122336679919, 0.9784316656930644, 2.9372978989672873], - initial_refinement_level = 4, - maxiters = 50) - end - - @trixi_testset "elixir_euler_blast_wave_neuralnetwork_rayhesthaven.jl with mortars" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave_neuralnetwork_rayhesthaven.jl"), - l2 = [0.016486406327766923, 0.03097329879894433, 0.03101012918167401, 0.15157175775429868], - linf = [0.27688647744873407, 0.5653724536715139, 0.565695523611447, 2.513047611639946], - refinement_patches=( - (type="box", coordinates_min=(-0.25, -0.25), coordinates_max=(0.25, 0.25)), - (type="box", coordinates_min=(-0.125, -0.125), coordinates_max=(0.125, 0.125)),), - initial_refinement_level = 4, - maxiters = 5) - end - - @trixi_testset "elixir_euler_blast_wave_neuralnetwork_cnn.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave_neuralnetwork_cnn.jl"), - l2 = [0.4795795496408325, 0.2125148972465021, 0.21311260934645868, 0.7033388737692883], - linf = [1.8295385992182336, 0.9687795218482794, 0.9616033072376108, 2.9513245978047133], - initial_refinement_level = 4, - maxiters = 50, - rtol = 1.0e-7) - end - - @trixi_testset "elixir_euler_blast_wave_pure_fv.jl" begin + l2=[ + 0.14170569763947993, + 0.11647068900798814, + 0.11647072556898294, + 0.3391989213659599, + ], + linf=[ + 1.6544204510794196, + 1.35194638484646, + 1.3519463848472744, + 1.831228461662809, + ], + maxiters=30) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_blast_wave_pure_fv.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave_pure_fv.jl"), - l2 = [0.39957047631960346, 0.21006912294983154, 0.21006903549932, 0.6280328163981136], - linf = [2.20417889887697, 1.5487238480003327, 1.5486788679247812, 2.4656795949035857], - tspan = (0.0, 0.5), - # Let this test run longer to cover some lines in flux_hllc - coverage_override = (maxiters=10^5, tspan=(0.0, 0.1))) - end - - @trixi_testset "elixir_euler_blast_wave_amr.jl" begin + l2=[ + 0.39957047631960346, + 0.21006912294983154, + 0.21006903549932, + 0.6280328163981136, + ], + linf=[ + 2.20417889887697, + 1.5487238480003327, + 1.5486788679247812, + 2.4656795949035857, + ], + tspan=(0.0, 0.5), + # Let this test run longer to cover some lines in flux_hllc + coverage_override=(maxiters = 10^5, tspan = (0.0, 0.1))) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_blast_wave_amr.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blast_wave_amr.jl"), - l2 = [0.6835576416907511, 0.2839963955262972, 0.28399565983676, 0.7229447806293277], - linf = [3.0969614882801393, 1.7967947300740248, 1.7967508302506658, 3.040149575567518], - tspan = (0.0, 1.0), - coverage_override = (maxiters=6,)) - end + l2=[ + 0.6835576416907511, + 0.2839963955262972, + 0.28399565983676, + 0.7229447806293277, + ], + linf=[ + 3.0969614882801393, + 1.7967947300740248, + 1.7967508302506658, + 3.040149575567518, + ], + tspan=(0.0, 1.0), + coverage_override=(maxiters = 6,)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_blast_wave_sc_subcell_nonperiodic.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_blast_wave_sc_subcell_nonperiodic.jl"), + l2=[ + 0.3517507570120483, + 0.19252291020146015, + 0.19249751956580294, + 0.618717827188004, + ], + linf=[ + 1.6699566795772216, + 1.3608007992899402, + 1.361864507190922, + 2.44022884092527, + ], + tspan=(0.0, 0.5), + initial_refinement_level=4, + coverage_override=(maxiters = 6,)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 + end +end + +@trixi_testset "elixir_euler_sedov_blast_wave.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov_blast_wave.jl"), + l2=[ + 0.4866953770742574, + 0.1673477470091984, + 0.16734774700934, + 0.6184367248923149, + ], + linf=[ + 2.6724832723962053, + 1.2916089288910635, + 1.2916089289001427, + 6.474699399394252, + ], + tspan=(0.0, 1.0), + coverage_override=(maxiters = 6,)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_sedov_blast_wave_sc_subcell.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_sedov_blast_wave_sc_subcell.jl"), + l2=[ + 0.4328635350273501, + 0.15011135840723572, + 0.15011135840723572, + 0.616129927549474, + ], + linf=[ + 1.6145297181778906, + 0.8614006163026988, + 0.8614006163026972, + 6.450225090647602, + ], + tspan=(0.0, 1.0), + initial_refinement_level=4, + coverage_override=(maxiters = 6,)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 + end +end - @trixi_testset "elixir_euler_sedov_blast_wave.jl" begin +@trixi_testset "elixir_euler_sedov_blast_wave.jl (HLLE)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov_blast_wave.jl"), - l2 = [0.4866953770742574, 0.1673477470091984, 0.16734774700934, 0.6184367248923149], - linf = [2.6724832723962053, 1.2916089288910635, 1.2916089289001427, 6.474699399394252], - tspan = (0.0, 1.0), - coverage_override = (maxiters=6,)) - end - - @trixi_testset "elixir_euler_sedov_blast_wave_neuralnetwork_perssonperaire.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov_blast_wave_neuralnetwork_perssonperaire.jl"), - l2 = [0.0845430093623868, 0.09271459184623232, 0.09271459184623232, 0.4377291875101709], - linf = [1.3608553480069898, 1.6822884847136004, 1.6822884847135997, 4.220147414536653], - maxiters = 30, - coverage_override = (maxiters=6,)) - end - - @trixi_testset "elixir_euler_positivity.jl" begin + l2=[ + 0.352405949321075, + 0.17207721487429464, + 0.17207721487433883, + 0.6263024434020885, + ], + linf=[ + 2.760997358628186, + 1.8279186132509326, + 1.8279186132502805, + 6.251573757093399, + ], + tspan=(0.0, 0.5), + callbacks=CallbackSet(summary_callback, + analysis_callback, alive_callback, + stepsize_callback), + surface_flux=flux_hlle), + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_positivity.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_positivity.jl"), - l2 = [0.48862067511841695, 0.16787541578869494, 0.16787541578869422, 0.6184319933114926], - linf = [2.6766520821013002, 1.2910938760258996, 1.2910938760258899, 6.473385481404865], - tspan = (0.0, 1.0), - coverage_override = (maxiters=3,)) - end + l2=[ + 0.48862067511841695, + 0.16787541578869494, + 0.16787541578869422, + 0.6184319933114926, + ], + linf=[ + 2.6766520821013002, + 1.2910938760258996, + 1.2910938760258899, + 6.473385481404865, + ], + tspan=(0.0, 1.0), + coverage_override=(maxiters = 3,)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_blob_mortar.jl" begin +@trixi_testset "elixir_euler_blob_mortar.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blob_mortar.jl"), - l2 = [0.22271619518391986, 0.6284824759323494, 0.24864213447943648, 2.9591811489995474], - linf = [9.15245400430106, 24.96562810334389, 10.388109127032374, 101.20581544156934], - tspan = (0.0, 0.5)) - end + l2=[ + 0.22271619518391986, + 0.6284824759323494, + 0.24864213447943648, + 2.9591811489995474, + ], + linf=[ + 9.15245400430106, + 24.96562810334389, + 10.388109127032374, + 101.20581544156934, + ], + tspan=(0.0, 0.5)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_blob_amr.jl" begin +@trixi_testset "elixir_euler_blob_amr.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blob_amr.jl"), - l2 = [0.2086261501910662, 1.2118352377894666, 0.10255333189606497, 5.296238138639236], - linf = [14.829071984498198, 74.12967742435727, 6.863554388300223, 303.58813147491134], - tspan = (0.0, 0.12), - # Let this test run longer to cover the ControllerThreeLevelCombined lines - coverage_override = (maxiters=10^5,)) - end - - @trixi_testset "elixir_euler_kelvin_helmholtz_instability_fjordholm_etal.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_kelvin_helmholtz_instability_fjordholm_etal.jl"), - l2 = [0.1057230211245312, 0.10621112311257341, 0.07260957505339989, 0.11178239111065721], - linf = [2.998719417992662, 2.1400285015556166, 1.1569648700415078, 1.8922492268110913], - tspan = (0.0, 0.1)) - end - - @trixi_testset "elixir_euler_kelvin_helmholtz_instability.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_kelvin_helmholtz_instability.jl"), - l2 = [0.055691508271624536, 0.032986009333751655, 0.05224390923711999, 0.08009536362771563], - linf = [0.24043622527087494, 0.1660878796929941, 0.12355946691711608, 0.2694290787257758], - tspan = (0.0, 0.2)) - end - - @trixi_testset "elixir_euler_kelvin_helmholtz_instability_amr.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_kelvin_helmholtz_instability_amr.jl"), - l2 = [0.05569452733654995, 0.033107109983417926, 0.05223609622852158, 0.08007777597488817], - linf = [0.2535807803900303, 0.17397028249895308, 0.12321616095649354, 0.269046666668995], - tspan = (0.0, 0.2), - coverage_override = (maxiters=2,)) - end - - @trixi_testset "elixir_euler_kelvin_helmholtz_instability_amr_neuralnetwork_perssonperaire.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_kelvin_helmholtz_instability_amr_neuralnetwork_perssonperaire.jl"), - # This stuff is experimental and annoying to test. In the future, we plan - # to move it to another repository. Thus, we save developer time right now - # and do not run these tests anymore. - # l2 = [0.0009823702998067061, 0.004943231496200673, 0.0048604522073091815, 0.00496983530893294], - # linf = [0.00855717053383187, 0.02087422420794427, 0.017121993783086185, 0.02720703869972585], - maxiters = 30, - coverage_override = (maxiters=2,)) - end - - @trixi_testset "elixir_euler_colliding_flow.jl" begin + l2=[ + 0.2086261501910662, + 1.2118352377894666, + 0.10255333189606497, + 5.296238138639236, + ], + linf=[ + 14.829071984498198, + 74.12967742435727, + 6.863554388300223, + 303.58813147491134, + ], + tspan=(0.0, 0.12), + # Let this test run longer to cover the ControllerThreeLevelCombined lines + coverage_override=(maxiters = 10^5,)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_kelvin_helmholtz_instability_fjordholm_etal.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_kelvin_helmholtz_instability_fjordholm_etal.jl"), + l2=[ + 0.1057230211245312, + 0.10621112311257341, + 0.07260957505339989, + 0.11178239111065721, + ], + linf=[ + 2.998719417992662, + 2.1400285015556166, + 1.1569648700415078, + 1.8922492268110913, + ], + tspan=(0.0, 0.1)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_kelvin_helmholtz_instability.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_kelvin_helmholtz_instability.jl"), + l2=[ + 0.055691508271624536, + 0.032986009333751655, + 0.05224390923711999, + 0.08009536362771563, + ], + linf=[ + 0.24043622527087494, + 0.1660878796929941, + 0.12355946691711608, + 0.2694290787257758, + ], + tspan=(0.0, 0.2)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_kelvin_helmholtz_instability_amr.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_kelvin_helmholtz_instability_amr.jl"), + l2=[ + 0.05569452733654995, + 0.033107109983417926, + 0.05223609622852158, + 0.08007777597488817, + ], + linf=[ + 0.2535807803900303, + 0.17397028249895308, + 0.12321616095649354, + 0.269046666668995, + ], + tspan=(0.0, 0.2), + coverage_override=(maxiters = 2,)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_colliding_flow.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_colliding_flow.jl"), - l2 = [0.007237139090503349, 0.044887582765386916, 1.0453570959003603e-6, 0.6627307840935432], - linf = [0.19437260992446315, 0.5554343646648533, 5.943891455255412e-5, 15.188919846360125], - tspan = (0.0, 0.1)) - end + l2=[ + 0.007237139090503349, + 0.044887582765386916, + 1.0453570959003603e-6, + 0.6627307840935432, + ], + linf=[ + 0.19437260992446315, + 0.5554343646648533, + 5.943891455255412e-5, + 15.188919846360125, + ], + tspan=(0.0, 0.1)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_colliding_flow_amr.jl" begin +@trixi_testset "elixir_euler_colliding_flow_amr.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_colliding_flow_amr.jl"), - l2 = [0.006768801432802192, 0.032184992228603666, 6.923887797276484e-7, 0.6784222932398366], - linf = [0.2508663007713608, 0.4097017076529792, 0.0003528986458217968, 22.435474993016918], - tspan = (0.0, 0.1), - coverage_override = (maxiters=2,)) - end + l2=[ + 0.006768801432802192, + 0.032184992228603666, + 6.923887797276484e-7, + 0.6784222932398366, + ], + linf=[ + 0.2508663007713608, + 0.4097017076529792, + 0.0003528986458217968, + 22.435474993016918, + ], + tspan=(0.0, 0.1), + coverage_override=(maxiters = 2,)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_astro_jet_amr.jl" begin +@trixi_testset "elixir_euler_astro_jet_amr.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_astro_jet_amr.jl"), - l2 = [0.011338365293662804, 10.09743543555765, 0.00392429463200361, 4031.7811487690506], - linf = [3.3178633141984193, 2993.6445033486402, 8.031723414357423, 1.1918867260293828e6], - tspan = (0.0, 1.0e-7), - coverage_override = (maxiters=6,)) - end + l2=[ + 0.011338365293662804, + 10.09743543555765, + 0.00392429463200361, + 4031.7811487690506, + ], + linf=[ + 3.3178633141984193, + 2993.6445033486402, + 8.031723414357423, + 1.1918867260293828e6, + ], + tspan=(0.0, 1.0e-7), + coverage_override=(maxiters = 6,)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_vortex.jl" begin +@trixi_testset "elixir_euler_vortex.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_vortex.jl"), - l2 = [0.00013492249515826863, 0.006615696236378061, 0.006782108219800376, 0.016393831451740604], - linf = [0.0020782600954247776, 0.08150078921935999, 0.08663621974991986, 0.2829930622010579]) - end + l2=[ + 0.00013492249515826863, + 0.006615696236378061, + 0.006782108219800376, + 0.016393831451740604, + ], + linf=[ + 0.0020782600954247776, + 0.08150078921935999, + 0.08663621974991986, + 0.2829930622010579, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_vortex_mortar.jl" begin +@trixi_testset "elixir_euler_vortex_mortar.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_vortex_mortar.jl"), - # Expected errors are exactly the same as in the parallel test! - l2 = [0.0017208369388227673, 0.09628684992237334, 0.09620157717330868, 0.1758809552387432], - linf = [0.021869936355319086, 0.9956698009442038, 1.0002507727219028, 2.223249697515648]) - end + # Expected errors are exactly the same as in the parallel test! + l2=[ + 0.0017208369388227673, + 0.09628684992237334, + 0.09620157717330868, + 0.1758809552387432, + ], + linf=[ + 0.021869936355319086, + 0.9956698009442038, + 1.0002507727219028, + 2.223249697515648, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_vortex_mortar_split.jl" begin +@trixi_testset "elixir_euler_vortex_mortar_split.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_vortex_mortar_split.jl"), - l2 = [0.0017203323613648241, 0.09628962878682261, 0.09621241164155782, 0.17585995600340926], - linf = [0.021740570456931674, 0.9938841665880938, 1.004140123355135, 2.224108857746245]) - end + l2=[ + 0.0017203323613648241, + 0.09628962878682261, + 0.09621241164155782, + 0.17585995600340926, + ], + linf=[ + 0.021740570456931674, + 0.9938841665880938, + 1.004140123355135, + 2.224108857746245, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_vortex_shockcapturing.jl" begin +@trixi_testset "elixir_euler_vortex_shockcapturing.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_vortex_shockcapturing.jl"), - l2 = [0.0017158367642679273, 0.09619888722871434, 0.09616432767924141, 0.17553381166255197], - linf = [0.021853862449723982, 0.9878047229255944, 0.9880191167111795, 2.2154030488035588]) - end + l2=[ + 0.0017158367642679273, + 0.09619888722871434, + 0.09616432767924141, + 0.17553381166255197, + ], + linf=[ + 0.021853862449723982, + 0.9878047229255944, + 0.9880191167111795, + 2.2154030488035588, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_vortex_mortar_shockcapturing.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_vortex_mortar_shockcapturing.jl"), - l2 = [0.0017203324051381415, 0.09628962899999398, 0.0962124115572114, 0.1758599596626405], - linf = [0.021740568112562086, 0.9938841624655501, 1.0041401179009877, 2.2241087041100798]) - end +@trixi_testset "elixir_euler_vortex_mortar_shockcapturing.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_vortex_mortar_shockcapturing.jl"), + l2=[ + 0.0017203324051381415, + 0.09628962899999398, + 0.0962124115572114, + 0.1758599596626405, + ], + linf=[ + 0.021740568112562086, + 0.9938841624655501, + 1.0041401179009877, + 2.2241087041100798, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_vortex_amr.jl" begin +@trixi_testset "elixir_euler_vortex_amr.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_vortex_amr.jl"), - # Expected errors are exactly the same as in the parallel test! - l2 = [5.051719943432265e-5, 0.0022574259317084747, 0.0021755998463189713, 0.004346492398617521], - linf = [0.0012880114865917447, 0.03857193149447702, 0.031090457959835893, 0.12125130332971423], - # Let this test run longer to cover some lines in the AMR indicator - coverage_override = (maxiters=10^5, tspan=(0.0, 10.5))) - end - - @trixi_testset "elixir_euler_ec.jl with boundary_condition_slip_wall" begin + # Expected errors are exactly the same as in the parallel test! + l2=[ + 5.051719943432265e-5, + 0.0022574259317084747, + 0.0021755998463189713, + 0.004346492398617521, + ], + linf=[ + 0.0012880114865917447, + 0.03857193149447702, + 0.031090457959835893, + 0.12125130332971423, + ], + # Let this test run longer to cover some lines in the AMR indicator + coverage_override=(maxiters = 10^5, tspan = (0.0, 10.5))) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_ec.jl with boundary_condition_slip_wall" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_ec.jl"), - l2 = [0.03341239373099515, 0.026673245711492915, 0.026678871434568822, 0.12397486476145089], - linf = [0.3290981764688339, 0.3812055782309788, 0.3812041851225023, 1.168251216556933], - periodicity = false, boundary_conditions = boundary_condition_slip_wall, - cfl = 0.3, tspan = (0.0, 0.1)) # this test is sensitive to the CFL factor - end + l2=[ + 0.03341239373099515, + 0.026673245711492915, + 0.026678871434568822, + 0.12397486476145089, + ], + linf=[ + 0.3290981764688339, + 0.3812055782309788, + 0.3812041851225023, + 1.168251216556933, + ], + periodicity=false, + boundary_conditions=boundary_condition_slip_wall, + cfl=0.3, tspan=(0.0, 0.1)) # this test is sensitive to the CFL factor + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end end # Coverage test for all initial conditions @testset "Compressible Euler: Tests for initial conditions" begin - @trixi_testset "elixir_euler_vortex.jl one step with initial_condition_constant" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_vortex.jl"), - l2 = [1.1790213022362371e-16, 8.580657423476384e-17, 1.3082387431804115e-16, 1.6182739965672862e-15], - linf = [3.3306690738754696e-16, 2.220446049250313e-16, 5.273559366969494e-16, 3.552713678800501e-15], - maxiters = 1, - initial_condition = initial_condition_constant) - end - - @trixi_testset "elixir_euler_sedov_blast_wave.jl one step" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov_blast_wave.jl"), - l2 = [0.0021196114178949396, 0.010703549234544042, 0.01070354923454404, 0.10719124037195142], - linf = [0.11987270645890724, 0.7468615461136827, 0.7468615461136827, 3.910689155287799], - maxiters=1) - end + @trixi_testset "elixir_euler_vortex.jl one step with initial_condition_constant" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_vortex.jl"), + l2=[ + 1.1790213022362371e-16, + 8.580657423476384e-17, + 1.3082387431804115e-16, + 1.6182739965672862e-15, + ], + linf=[ + 3.3306690738754696e-16, + 2.220446049250313e-16, + 5.273559366969494e-16, + 3.552713678800501e-15, + ], + maxiters=1, + initial_condition=initial_condition_constant) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end + end + + @trixi_testset "elixir_euler_sedov_blast_wave.jl one step" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov_blast_wave.jl"), + l2=[ + 0.0021196114178949396, + 0.010703549234544042, + 0.01070354923454404, + 0.10719124037195142, + ], + linf=[ + 0.11987270645890724, + 0.7468615461136827, + 0.7468615461136827, + 3.910689155287799, + ], + maxiters=1) + + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end + end +end end end # module diff --git a/test/test_tree_2d_euleracoustics.jl b/test/test_tree_2d_euleracoustics.jl index 01ac939f8aa..e3a4d65f398 100644 --- a/test/test_tree_2d_euleracoustics.jl +++ b/test/test_tree_2d_euleracoustics.jl @@ -8,14 +8,40 @@ include("test_trixi.jl") EXAMPLES_DIR = joinpath(examples_dir(), "tree_2d_dgsem") @testset "Acoustic perturbation coupled with compressible Euler" begin - @trixi_testset "elixir_euleracoustics_co-rotating_vortex_pair.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euleracoustics_co-rotating_vortex_pair.jl"), +#! format: noindent + +@trixi_testset "elixir_euleracoustics_co-rotating_vortex_pair.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euleracoustics_co-rotating_vortex_pair.jl"), initial_refinement_level=5, tspan1=(0.0, 1.0), tspan_averaging=(0.0, 1.0), tspan=(0.0, 1.0), - l2 = [0.00013268029905807722, 0.0001335062197031223, 0.00021776333678401362, 13.000001753042364, 26.00000080243847, 38.00000884725549, 51.000000003859995], - linf = [0.22312716933051027, 0.1579924424942319, 0.25194831158255576, 13.468872744263273, 26.54666679978679, 38.139032147739684, 51.378134660241294] - ) - end + l2=[ + 0.00013268029905807722, + 0.0001335062197031223, + 0.00021776333678401362, + 13.000001753042364, + 26.00000080243847, + 38.00000884725549, + 51.000000003859995, + ], + linf=[ + 0.22312716933051027, + 0.1579924424942319, + 0.25194831158255576, + 13.468872744263273, + 26.54666679978679, + 38.139032147739684, + 51.378134660241294, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end end -end # module \ No newline at end of file +end # module diff --git a/test/test_tree_2d_eulermulti.jl b/test/test_tree_2d_eulermulti.jl index 606afca1034..7c4a4e722e3 100644 --- a/test/test_tree_2d_eulermulti.jl +++ b/test/test_tree_2d_eulermulti.jl @@ -8,55 +8,253 @@ include("test_trixi.jl") EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") @testset "Compressible Euler Multicomponent" begin - # NOTE: Some of the L2/Linf errors are comparably large. This is due to the fact that some of the - # simulations are set up with dimensional states. For example, the reference pressure in SI - # units is 101325 Pa, i.e., pressure has values of O(10^5) - - @trixi_testset "elixir_eulermulti_shock_bubble.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulermulti_shock_bubble.jl"), - l2 = [73.78467629094177, 0.9174752929795251, 57942.83587826468, 0.1828847253029943, 0.011127037850925347], - linf = [196.81051991521073, 7.8456811648529605, 158891.88930113698, 0.811379581519794, 0.08011973559187913], - tspan = (0.0, 0.001)) - end - - @trixi_testset "elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl"), - l2 = [81.52845664909304, 2.5455678559421346, 63229.190712645846, 0.19929478404550321, 0.011068604228443425], - linf = [249.21708417382013, 40.33299887640794, 174205.0118831558, 0.6881458768113586, 0.11274401158173972], - initial_refinement_level = 3, - tspan = (0.0, 0.001)) - end - - @trixi_testset "elixir_eulermulti_ec.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulermulti_ec.jl"), - l2 = [0.050182236154087095, 0.050189894464434635, 0.2258715597305131, 0.06175171559771687], - linf = [0.3108124923284472, 0.3107380389947733, 1.054035804988521, 0.29347582879608936]) - end - - @trixi_testset "elixir_eulermulti_es.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulermulti_es.jl"), - l2 = [0.0496546258404055, 0.04965550099933263, 0.22425206549856372, 0.004087155041747821, 0.008174310083495642, 0.016348620166991283, 0.032697240333982566], - linf = [0.2488251110766228, 0.24832493304479406, 0.9310354690058298, 0.017452870465607374, 0.03490574093121475, 0.0698114818624295, 0.139622963724859]) - end - - @trixi_testset "elixir_eulermulti_convergence_ec.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulermulti_convergence_ec.jl"), - l2 = [0.00012290225488326508, 0.00012290225488321876, 0.00018867397906337653, 4.8542321753649044e-5, 9.708464350729809e-5], - linf = [0.0006722819239133315, 0.0006722819239128874, 0.0012662292789555885, 0.0002843844182700561, 0.0005687688365401122]) - end - - @trixi_testset "elixir_eulermulti_convergence_es.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulermulti_convergence_es.jl"), - l2 = [2.2661773867001696e-6, 2.266177386666318e-6, 6.593514692980009e-6, 8.836308667348217e-7, 1.7672617334696433e-6], - linf = [1.4713170997993075e-5, 1.4713170997104896e-5, 5.115618808515521e-5, 5.3639516094383666e-6, 1.0727903218876733e-5]) - end - - @trixi_testset "elixir_eulermulti_convergence_es.jl with flux_chandrashekar" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulermulti_convergence_es.jl"), - l2 = [1.8621737639352465e-6, 1.862173764098385e-6, 5.942585713809631e-6, 6.216263279534722e-7, 1.2432526559069443e-6], - linf = [1.6235495582606063e-5, 1.6235495576388814e-5, 5.854523678827661e-5, 5.790274858807898e-6, 1.1580549717615796e-5], - volume_flux = flux_chandrashekar) - end + @trixi_testset "Testing entropy2cons and cons2entropy" begin + using ForwardDiff + gammas = (1.1546412974182538, 1.1171560258914812, 1.097107661471476, + 1.0587601652669245, 1.6209889683979308, 1.6732209755396386, + 1.2954303574165822) + gas_constants = (5.969461071171914, 3.6660802003290183, 6.639008614675539, + 8.116604827140456, 6.190706056680031, 1.6795013743693712, + 2.197737590916966) + equations = CompressibleEulerMulticomponentEquations2D(gammas = SVector{length(gammas)}(gammas...), + gas_constants = SVector{length(gas_constants)}(gas_constants...)) + u = [-1.7433292819144075, 0.8844413258376495, 0.6050737175812364, + 0.8261998359817043, 1.0801186290896465, 0.505654488367698, + 0.6364415555805734, 0.851669392285058, 0.31219606420306223, + 1.0930477805612038] + w = cons2entropy(u, equations) + # test that the entropy variables match the gradients of the total entropy + @test w ≈ ForwardDiff.gradient(u -> Trixi.total_entropy(u, equations), u) + # test that `entropy2cons` is the inverse of `cons2entropy` + @test entropy2cons(w, equations) ≈ u + end + + # NOTE: Some of the L2/Linf errors are comparably large. This is due to the fact that some of the + # simulations are set up with dimensional states. For example, the reference pressure in SI + # units is 101325 Pa, i.e., pressure has values of O(10^5) + + @trixi_testset "elixir_eulermulti_shock_bubble.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulermulti_shock_bubble.jl"), + l2=[ + 73.78467629094177, + 0.9174752929795251, + 57942.83587826468, + 0.1828847253029943, + 0.011127037850925347, + ], + linf=[ + 196.81051991521073, + 7.8456811648529605, + 158891.88930113698, + 0.811379581519794, + 0.08011973559187913, + ], + tspan=(0.0, 0.001)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end + end + + @trixi_testset "elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl" begin + rm("out/deviations.txt", force = true) + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_eulermulti_shock_bubble_shockcapturing_subcell_positivity.jl"), + l2=[ + 81.52845664909304, + 2.5455678559421346, + 63229.190712645846, + 0.19929478404550321, + 0.011068604228443425, + ], + linf=[ + 249.21708417382013, + 40.33299887640794, + 174205.0118831558, + 0.6881458768113586, + 0.11274401158173972, + ], + initial_refinement_level=3, + tspan=(0.0, 0.001), + output_directory="out") + lines = readlines("out/deviations.txt") + @test lines[1] == "# iter, simu_time, rho1_min, rho2_min" + @test startswith(lines[end], "1") + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 + end + end + + @trixi_testset "elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_eulermulti_shock_bubble_shockcapturing_subcell_minmax.jl"), + l2=[ + 73.10832638093902, + 1.4599215762968585, + 57176.014861335476, + 0.17812843581838675, + 0.010123079422717837, + ], + linf=[ + 214.50568817511956, + 25.40392579616452, + 152862.41011222568, + 0.564195553101797, + 0.0956331651771212, + ], + initial_refinement_level=3, + tspan=(0.0, 0.001)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 + end + end + + @trixi_testset "elixir_eulermulti_ec.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulermulti_ec.jl"), + l2=[ + 0.050182236154087095, + 0.050189894464434635, + 0.2258715597305131, + 0.06175171559771687, + ], + linf=[ + 0.3108124923284472, + 0.3107380389947733, + 1.054035804988521, + 0.29347582879608936, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end + end + + @trixi_testset "elixir_eulermulti_es.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulermulti_es.jl"), + l2=[ + 0.0496546258404055, + 0.04965550099933263, + 0.22425206549856372, + 0.004087155041747821, + 0.008174310083495642, + 0.016348620166991283, + 0.032697240333982566, + ], + linf=[ + 0.2488251110766228, + 0.24832493304479406, + 0.9310354690058298, + 0.017452870465607374, + 0.03490574093121475, + 0.0698114818624295, + 0.139622963724859, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end + end + + @trixi_testset "elixir_eulermulti_convergence_ec.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulermulti_convergence_ec.jl"), + l2=[ + 0.00012290225488326508, + 0.00012290225488321876, + 0.00018867397906337653, + 4.8542321753649044e-5, + 9.708464350729809e-5, + ], + linf=[ + 0.0006722819239133315, + 0.0006722819239128874, + 0.0012662292789555885, + 0.0002843844182700561, + 0.0005687688365401122, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end + end + + @trixi_testset "elixir_eulermulti_convergence_es.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulermulti_convergence_es.jl"), + l2=[ + 2.2661773867001696e-6, + 2.266177386666318e-6, + 6.593514692980009e-6, + 8.836308667348217e-7, + 1.7672617334696433e-6, + ], + linf=[ + 1.4713170997993075e-5, + 1.4713170997104896e-5, + 5.115618808515521e-5, + 5.3639516094383666e-6, + 1.0727903218876733e-5, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end + end + + @trixi_testset "elixir_eulermulti_convergence_es.jl with flux_chandrashekar" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulermulti_convergence_es.jl"), + l2=[ + 1.8621737639352465e-6, + 1.862173764098385e-6, + 5.942585713809631e-6, + 6.216263279534722e-7, + 1.2432526559069443e-6, + ], + linf=[ + 1.6235495582606063e-5, + 1.6235495576388814e-5, + 5.854523678827661e-5, + 5.790274858807898e-6, + 1.1580549717615796e-5, + ], + volume_flux=flux_chandrashekar) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end + end end end # module diff --git a/test/test_tree_2d_eulerpolytropic.jl b/test/test_tree_2d_eulerpolytropic.jl new file mode 100644 index 00000000000..545cf7274ff --- /dev/null +++ b/test/test_tree_2d_eulerpolytropic.jl @@ -0,0 +1,35 @@ +module TestExamples2DEulerMulticomponent + +using Test +using Trixi + +include("test_trixi.jl") + +EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") + +@testset "Polytropic Euler" begin +#! format: noindent + +@trixi_testset "elixir_eulerpolytropic_convergence.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_eulerpolytropic_convergence.jl"), + l2=[ + 0.0016689832177626373, 0.0025920263793094526, + 0.003281074494626679, + ], + linf=[ + 0.010994883201896677, 0.013309526619350365, + 0.02008032661117376, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end +end + +end # module diff --git a/test/test_tree_2d_fdsbp.jl b/test/test_tree_2d_fdsbp.jl index e81c82f3f34..c0844ee5dba 100644 --- a/test/test_tree_2d_fdsbp.jl +++ b/test/test_tree_2d_fdsbp.jl @@ -8,78 +8,152 @@ include("test_trixi.jl") EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_fdsbp") @testset "Linear scalar advection" begin - @trixi_testset "elixir_advection_extended.jl" begin +#! format: noindent + +@trixi_testset "elixir_advection_extended.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_extended.jl"), - l2 = [2.898644263922225e-6], - linf = [8.491517930142578e-6], - rtol = 1.0e-7) # These results change a little bit and depend on the CI system + l2=[2.898644263922225e-6], + linf=[8.491517930142578e-6], + rtol=1.0e-7) # These results change a little bit and depend on the CI system # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 end - end +end - @trixi_testset "elixir_advection_extended.jl with periodic operators" begin +@trixi_testset "elixir_advection_extended.jl with periodic operators" begin + global D = SummationByPartsOperators.periodic_derivative_operator(derivative_order = 1, + accuracy_order = 4, + xmin = 0.0, + xmax = 1.0, + N = 40) @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_extended.jl"), - l2 = [1.1239649404463432e-5], - linf = [1.5895264629195438e-5], - D_SBP = SummationByPartsOperators.periodic_derivative_operator( - derivative_order = 1, accuracy_order = 4, xmin = 0.0, xmax = 1.0, N = 40), - initial_refinement_level = 0) + l2=[1.1239649404463432e-5], + linf=[1.5895264629195438e-5], + D_SBP=D, + initial_refinement_level=0) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 end - end +end end @testset "Compressible Euler" begin - @trixi_testset "elixir_euler_convergence.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_convergence.jl"), - l2 = [1.7088389997042244e-6, 1.7437997855125774e-6, 1.7437997855350776e-6, 5.457223460127621e-6], - linf = [9.796504903736292e-6, 9.614745892783105e-6, 9.614745892783105e-6, 4.026107182575345e-5], - tspan = (0.0, 0.1)) + @trixi_testset "elixir_euler_convergence.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_convergence.jl"), + l2=[ + 1.7088389997042244e-6, + 1.7437997855125774e-6, + 1.7437997855350776e-6, + 5.457223460127621e-6, + ], + linf=[ + 9.796504903736292e-6, + 9.614745892783105e-6, + 9.614745892783105e-6, + 4.026107182575345e-5, + ], + tspan=(0.0, 0.1)) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end + end + + @trixi_testset "elixir_euler_convergence.jl with Lax-Friedrichs splitting" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_convergence.jl"), + l2=[ + 2.1149087345799973e-6, + 1.9391438806845798e-6, + 1.9391438806759794e-6, + 5.842833764682604e-6, + ], + linf=[ + 1.3679037540903494e-5, + 1.1770587849069258e-5, + 1.1770587848403125e-5, + 4.68952678644996e-5, + ], + tspan=(0.0, 0.1), flux_splitting=splitting_lax_friedrichs) + + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end + end + + @trixi_testset "elixir_euler_kelvin_helmholtz_instability.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_euler_kelvin_helmholtz_instability.jl"), + l2=[ + 0.02607850081951497, + 0.020357717558016252, + 0.028510191844948945, + 0.02951535039734857, + ], + linf=[ + 0.12185328623662173, + 0.1065055387595834, + 0.06257122956937419, + 0.11992349951978643, + ], + tspan=(0.0, 0.1)) + + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end + end + + @trixi_testset "elixir_euler_vortex.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_vortex.jl"), + l2=[ + 0.0005330228930711585, + 0.028475888529345014, + 0.02847513865894387, + 0.056259951995581196, + ], + linf=[ + 0.007206088611304784, + 0.31690373882847234, + 0.31685665067192326, + 0.7938167296134893, + ], + tspan=(0.0, 0.25)) + + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end end - end - - @trixi_testset "elixir_euler_convergence.jl with Lax-Friedrichs splitting" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_convergence.jl"), - l2 = [2.1149087345799973e-6, 1.9391438806845798e-6, 1.9391438806759794e-6, 5.842833764682604e-6], - linf = [1.3679037540903494e-5, 1.1770587849069258e-5, 1.1770587848403125e-5, 4.68952678644996e-5], - tspan = (0.0, 0.1), flux_splitting = splitting_lax_friedrichs) - end - - @trixi_testset "elixir_euler_kelvin_helmholtz_instability.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_kelvin_helmholtz_instability.jl"), - l2 = [0.02607850081951497, 0.020357717558016252, 0.028510191844948945, 0.02951535039734857], - linf = [0.12185328623662173, 0.1065055387595834, 0.06257122956937419, 0.11992349951978643], - tspan = (0.0, 0.1)) - end - - @trixi_testset "elixir_euler_vortex.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_vortex.jl"), - l2 = [0.0005330228930711585, 0.028475888529345014, 0.02847513865894387, 0.056259951995581196], - linf = [0.007206088611304784, 0.31690373882847234, 0.31685665067192326, 0.7938167296134893], - tspan = (0.0, 0.25)) - end end end # module diff --git a/test/test_tree_2d_hypdiff.jl b/test/test_tree_2d_hypdiff.jl index eb8f8b297b6..8c5973cbf07 100644 --- a/test/test_tree_2d_hypdiff.jl +++ b/test/test_tree_2d_hypdiff.jl @@ -8,30 +8,97 @@ include("test_trixi.jl") EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") @testset "Hyperbolic diffusion" begin - @trixi_testset "elixir_hypdiff_lax_friedrichs.jl" begin +#! format: noindent + +@trixi_testset "elixir_hypdiff_lax_friedrichs.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_hypdiff_lax_friedrichs.jl"), - l2 = [0.00015687751817403066, 0.001025986772216324, 0.0010259867722164071], - linf = [0.001198695637957381, 0.006423873515531753, 0.006423873515533529]) - end + l2=[ + 0.00015687751817403066, + 0.001025986772216324, + 0.0010259867722164071, + ], + linf=[ + 0.001198695637957381, + 0.006423873515531753, + 0.006423873515533529, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 + end +end - @trixi_testset "elixir_hypdiff_harmonic_nonperiodic.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_hypdiff_harmonic_nonperiodic.jl"), - l2 = [8.618132355121019e-8, 5.619399844384306e-7, 5.619399844844044e-7], - linf = [1.1248618588430072e-6, 8.622436487026874e-6, 8.622436487915053e-6]) - end +@trixi_testset "elixir_hypdiff_harmonic_nonperiodic.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_hypdiff_harmonic_nonperiodic.jl"), + l2=[ + 8.618132355121019e-8, + 5.619399844384306e-7, + 5.619399844844044e-7, + ], + linf=[ + 1.1248618588430072e-6, + 8.622436487026874e-6, + 8.622436487915053e-6, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_hypdiff_nonperiodic.jl" begin +@trixi_testset "elixir_hypdiff_nonperiodic.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_hypdiff_nonperiodic.jl"), - l2 = [8.523077653954864e-6, 2.8779323653020624e-5, 5.454942769125663e-5], - linf = [5.522740952468297e-5, 0.00014544895978971679, 0.00032396328684924924]) - end + l2=[ + 8.523077653954864e-6, + 2.8779323653020624e-5, + 5.454942769125663e-5, + ], + linf=[ + 5.522740952468297e-5, + 0.00014544895978971679, + 0.00032396328684924924, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_hypdiff_godunov.jl" begin +@trixi_testset "elixir_hypdiff_godunov.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_hypdiff_godunov.jl"), - l2 = [5.868147556427088e-6, 3.80517927324465e-5, 3.805179273249344e-5], - linf = [3.701965498725812e-5, 0.0002122422943138247, 0.00021224229431116015], - atol = 2.0e-12 #= required for CI on macOS =#) - end + l2=[ + 5.868147556427088e-6, + 3.80517927324465e-5, + 3.805179273249344e-5, + ], + linf=[ + 3.701965498725812e-5, + 0.0002122422943138247, + 0.00021224229431116015, + ], + atol=2.0e-12) #= required for CI on macOS =# + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end end end # module diff --git a/test/test_tree_2d_kpp.jl b/test/test_tree_2d_kpp.jl index 26074ea487f..c9af68c6cc4 100644 --- a/test/test_tree_2d_kpp.jl +++ b/test/test_tree_2d_kpp.jl @@ -8,16 +8,28 @@ include("test_trixi.jl") EXAMPLES_DIR = joinpath(examples_dir(), "tree_2d_dgsem") @testset "KPP" begin - @trixi_testset "elixir_kpp.jl" begin +#! format: noindent + +@trixi_testset "elixir_kpp.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_kpp.jl"), - l2 = [0.36563290910786106], - linf = [9.116732052340398], - max_refinement_level = 6, - tspan = (0.0, 0.01), - atol = 1e-6, - rtol = 1e-6, - skip_coverage = true) - end + l2=[0.36563290910786106], + linf=[9.116732052340398], + max_refinement_level=6, + tspan=(0.0, 0.01), + atol=1e-6, + rtol=1e-6, + skip_coverage=true) + if @isdefined sol # Skipped in coverage run + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end + end +end end end # module diff --git a/test/test_tree_2d_lbm.jl b/test/test_tree_2d_lbm.jl index b516708e6cd..4705c9d0d03 100644 --- a/test/test_tree_2d_lbm.jl +++ b/test/test_tree_2d_lbm.jl @@ -8,71 +8,154 @@ include("test_trixi.jl") EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") @testset "Lattice-Boltzmann" begin - @trixi_testset "elixir_lbm_constant.jl" begin +#! format: noindent + +@trixi_testset "elixir_lbm_constant.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_lbm_constant.jl"), - l2 = [4.888991832247047e-15, 4.8856380534982224e-15, 5.140829677785587e-16, - 7.340293204570167e-16, 2.0559494114924474e-15, 6.125746684189216e-16, - 1.6545443003155128e-16, 6.001333022242579e-16, 9.450994018139234e-15], - linf = [5.551115123125783e-15, 5.662137425588298e-15, 1.2212453270876722e-15, - 1.27675647831893e-15, 2.4980018054066022e-15, 7.494005416219807e-16, - 4.3021142204224816e-16, 8.881784197001252e-16, 1.0436096431476471e-14]) - end + l2=[4.888991832247047e-15, 4.8856380534982224e-15, + 5.140829677785587e-16, + 7.340293204570167e-16, 2.0559494114924474e-15, + 6.125746684189216e-16, + 1.6545443003155128e-16, 6.001333022242579e-16, + 9.450994018139234e-15], + linf=[5.551115123125783e-15, 5.662137425588298e-15, + 1.2212453270876722e-15, + 1.27675647831893e-15, 2.4980018054066022e-15, + 7.494005416219807e-16, + 4.3021142204224816e-16, 8.881784197001252e-16, + 1.0436096431476471e-14]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_lbm_couette.jl" begin +@trixi_testset "elixir_lbm_couette.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_lbm_couette.jl"), - l2 = [0.0007899749117603378, 7.0995283148275575e-6, 0.0007454191223764233, - 1.6482025869100257e-5, 0.00012684365365448903, 0.0001198942846383015, - 0.00028436349827736705, 0.0003005161103138576, 4.496683876631818e-5], - linf = [0.005596384769998769, 4.771160474496827e-5, 0.005270322068908595, - 0.00011747787108790098, 0.00084326349695725, 0.000795551892211168, - 0.001956482118303543, 0.0020739599893902436, 0.00032606270109525326], - tspan = (0.0, 1.0)) - end + l2=[0.0007899749117603378, 7.0995283148275575e-6, + 0.0007454191223764233, + 1.6482025869100257e-5, 0.00012684365365448903, + 0.0001198942846383015, + 0.00028436349827736705, 0.0003005161103138576, + 4.496683876631818e-5], + linf=[0.005596384769998769, 4.771160474496827e-5, + 0.005270322068908595, + 0.00011747787108790098, 0.00084326349695725, + 0.000795551892211168, + 0.001956482118303543, 0.0020739599893902436, + 0.00032606270109525326], + tspan=(0.0, 1.0)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_lbm_lid_driven_cavity.jl" begin +@trixi_testset "elixir_lbm_lid_driven_cavity.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_lbm_lid_driven_cavity.jl"), - l2 = [0.0013628495945172754, 0.00021475256243322154, 0.0012579141312268184, - 0.00036542734715110765, 0.00024127756258120715, 0.00022899415795341014, - 0.0004225564518328741, 0.0004593854895507851, 0.00044244398903669927], - linf = [0.025886626070758242, 0.00573859077176217, 0.027568805277855102, 0.00946724671122974, - 0.004031686575556803, 0.0038728927083346437, 0.020038695575169005, - 0.02061789496737146, 0.05568236920459335], - tspan = (0.0, 1.0)) - end + l2=[0.0013628495945172754, 0.00021475256243322154, + 0.0012579141312268184, + 0.00036542734715110765, 0.00024127756258120715, + 0.00022899415795341014, + 0.0004225564518328741, 0.0004593854895507851, + 0.00044244398903669927], + linf=[0.025886626070758242, 0.00573859077176217, + 0.027568805277855102, 0.00946724671122974, + 0.004031686575556803, 0.0038728927083346437, + 0.020038695575169005, + 0.02061789496737146, 0.05568236920459335], + tspan=(0.0, 1.0)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_lbm_couette.jl with initial_condition_couette_steady" begin +@trixi_testset "elixir_lbm_couette.jl with initial_condition_couette_steady" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_lbm_couette.jl"), - l2 = [9.321369073400123e-16, 1.6498793963435488e-6, 5.211495843124065e-16, - 1.6520893954826173e-6, 1.0406056181388841e-5, 8.801606429417205e-6, - 8.801710065560555e-6, 1.040614383799995e-5, 2.6135657178357052e-15], - linf = [1.4432899320127035e-15, 2.1821189867266e-6, 8.881784197001252e-16, - 2.2481261510165496e-6, 1.0692966335143494e-5, 9.606391697600247e-6, - 9.62138334279633e-6, 1.0725969916147021e-5, 3.3861802251067274e-15], - initial_condition=function initial_condition_couette_steady(x, t, equations::LatticeBoltzmannEquations2D) - # Initial state for a *steady* Couette flow setup. To be used in combination with - # [`boundary_condition_couette`](@ref) and [`boundary_condition_noslip_wall`](@ref). - @unpack L, u0, rho0 = equations + l2=[9.321369073400123e-16, 1.6498793963435488e-6, + 5.211495843124065e-16, + 1.6520893954826173e-6, 1.0406056181388841e-5, + 8.801606429417205e-6, + 8.801710065560555e-6, 1.040614383799995e-5, + 2.6135657178357052e-15], + linf=[1.4432899320127035e-15, 2.1821189867266e-6, + 8.881784197001252e-16, + 2.2481261510165496e-6, 1.0692966335143494e-5, + 9.606391697600247e-6, + 9.62138334279633e-6, 1.0725969916147021e-5, + 3.3861802251067274e-15], + initial_condition=function initial_condition_couette_steady(x, + t, + equations::LatticeBoltzmannEquations2D) + # Initial state for a *steady* Couette flow setup. To be used in combination with + # [`boundary_condition_couette`](@ref) and [`boundary_condition_noslip_wall`](@ref). + @unpack L, u0, rho0 = equations - rho = rho0 - v1 = u0 * x[2] / L - v2 = 0 + rho = rho0 + v1 = u0 * x[2] / L + v2 = 0 - return equilibrium_distribution(rho, v1, v2, equations) - end, - tspan = (0.0, 1.0)) - end + return equilibrium_distribution(rho, v1, v2, equations) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < + 1000 + end + end, + tspan=(0.0, 1.0)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_lbm_lid_driven_cavity.jl with stationary walls" begin +@trixi_testset "elixir_lbm_lid_driven_cavity.jl with stationary walls" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_lbm_lid_driven_cavity.jl"), - l2 = [1.7198203373689985e-16, 1.685644347036533e-16, 2.1604974801394525e-16, - 2.1527076266915764e-16, 4.2170298143732604e-17, 5.160156233016299e-17, - 6.167794865198169e-17, 5.24166554417795e-17, 6.694740573885739e-16], - linf = [5.967448757360216e-16, 6.522560269672795e-16, 6.522560269672795e-16, - 6.245004513516506e-16, 2.1163626406917047e-16, 2.185751579730777e-16, - 2.185751579730777e-16, 2.393918396847994e-16, 1.887379141862766e-15], - boundary_conditions=boundary_condition_noslip_wall, - tspan = (0, 0.1)) - end + l2=[1.7198203373689985e-16, 1.685644347036533e-16, + 2.1604974801394525e-16, + 2.1527076266915764e-16, 4.2170298143732604e-17, + 5.160156233016299e-17, + 6.167794865198169e-17, 5.24166554417795e-17, + 6.694740573885739e-16], + linf=[5.967448757360216e-16, 6.522560269672795e-16, + 6.522560269672795e-16, + 6.245004513516506e-16, 2.1163626406917047e-16, + 2.185751579730777e-16, + 2.185751579730777e-16, 2.393918396847994e-16, + 1.887379141862766e-15], + boundary_conditions=boundary_condition_noslip_wall, + tspan=(0, 0.1)) + + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end end end # module diff --git a/test/test_tree_2d_linearizedeuler.jl b/test/test_tree_2d_linearizedeuler.jl index 2c5f6dc2cd1..7bdb83e328e 100644 --- a/test/test_tree_2d_linearizedeuler.jl +++ b/test/test_tree_2d_linearizedeuler.jl @@ -7,16 +7,54 @@ include("test_trixi.jl") EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") @testset "Linearized Euler Equations 2D" begin - @trixi_testset "elixir_linearizedeuler_convergence.jl" begin +#! format: noindent + +@trixi_testset "elixir_linearizedeuler_convergence.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_linearizedeuler_convergence.jl"), - l2 = [0.00020601485381444888, 0.00013380483421751216, 0.0001338048342174503, 0.00020601485381444888], - linf = [0.0011006084408365924, 0.0005788678074691855, 0.0005788678074701847, 0.0011006084408365924] - ) - end + l2=[ + 0.00020601485381444888, + 0.00013380483421751216, + 0.0001338048342174503, + 0.00020601485381444888, + ], + linf=[ + 0.0011006084408365924, + 0.0005788678074691855, + 0.0005788678074701847, + 0.0011006084408365924, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_linearizedeuler_gauss_wall.jl" begin +@trixi_testset "elixir_linearizedeuler_gauss_wall.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_linearizedeuler_gauss_wall.jl"), - l2 = [0.048185623945503485, 0.01941899333212175, 0.019510224816991825, 0.048185623945503485], - linf = [1.0392165942153189, 0.18188777290819994, 0.1877028372108587, 1.0392165942153189]) - end + l2=[ + 0.048185623945503485, + 0.01941899333212175, + 0.019510224816991825, + 0.048185623945503485, + ], + linf=[ + 1.0392165942153189, + 0.18188777290819994, + 0.1877028372108587, + 1.0392165942153189, + ]) + + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end end diff --git a/test/test_tree_2d_mhd.jl b/test/test_tree_2d_mhd.jl index 3e104da3e91..953c077c0a3 100644 --- a/test/test_tree_2d_mhd.jl +++ b/test/test_tree_2d_mhd.jl @@ -8,71 +8,358 @@ include("test_trixi.jl") EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") @testset "MHD" begin - @trixi_testset "elixir_mhd_alfven_wave.jl" begin +#! format: noindent + +@trixi_testset "elixir_mhd_alfven_wave.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_alfven_wave.jl"), - l2 = [0.00011149543672225127, 5.888242524520296e-6, 5.888242524510072e-6, 8.476931432519067e-6, 1.3160738644036652e-6, 1.2542675002588144e-6, 1.2542675002747718e-6, 1.8705223407238346e-6, 4.651717010670585e-7], - linf = [0.00026806333988971254, 1.6278838272418272e-5, 1.627883827305665e-5, 2.7551183488072617e-5, 5.457878055614707e-6, 8.130129322880819e-6, 8.130129322769797e-6, 1.2406302192291552e-5, 2.373765544951732e-6]) - end + l2=[ + 0.00011149543672225127, + 5.888242524520296e-6, + 5.888242524510072e-6, + 8.476931432519067e-6, + 1.3160738644036652e-6, + 1.2542675002588144e-6, + 1.2542675002747718e-6, + 1.8705223407238346e-6, + 4.651717010670585e-7, + ], + linf=[ + 0.00026806333988971254, + 1.6278838272418272e-5, + 1.627883827305665e-5, + 2.7551183488072617e-5, + 5.457878055614707e-6, + 8.130129322880819e-6, + 8.130129322769797e-6, + 1.2406302192291552e-5, + 2.373765544951732e-6, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_mhd_alfven_wave.jl with flux_derigs_etal" begin +@trixi_testset "elixir_mhd_alfven_wave.jl with flux_derigs_etal" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_alfven_wave.jl"), - l2 = [1.7201098719531215e-6, 8.692057393373005e-7, 8.69205739320643e-7, 1.2726508184718958e-6, 1.040607127595208e-6, 1.07029565814218e-6, 1.0702956581404748e-6, 1.3291748105236525e-6, 4.6172239295786824e-7], - linf = [9.865325754310206e-6, 7.352074675170961e-6, 7.352074674185638e-6, 1.0675656902672803e-5, 5.112498347226158e-6, 7.789533065905019e-6, 7.789533065905019e-6, 1.0933531593274037e-5, 2.340244047768378e-6], - volume_flux = (flux_derigs_etal, flux_nonconservative_powell)) - end + l2=[ + 1.7201098719531215e-6, + 8.692057393373005e-7, + 8.69205739320643e-7, + 1.2726508184718958e-6, + 1.040607127595208e-6, + 1.07029565814218e-6, + 1.0702956581404748e-6, + 1.3291748105236525e-6, + 4.6172239295786824e-7, + ], + linf=[ + 9.865325754310206e-6, + 7.352074675170961e-6, + 7.352074674185638e-6, + 1.0675656902672803e-5, + 5.112498347226158e-6, + 7.789533065905019e-6, + 7.789533065905019e-6, + 1.0933531593274037e-5, + 2.340244047768378e-6, + ], + volume_flux=(flux_derigs_etal, flux_nonconservative_powell)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_mhd_alfven_wave_mortar.jl" begin +@trixi_testset "elixir_mhd_alfven_wave_mortar.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_alfven_wave_mortar.jl"), - l2 = [3.7762324533854616e-6, 1.5534623833573546e-6, 1.4577234868196855e-6, 1.7647724628707057e-6, 1.4831911814574333e-6, 1.456369119716533e-6, 1.4115666913995062e-6, 1.804758237422838e-6, 8.320469738087189e-7], - linf = [3.670661330201774e-5, 1.530289442645827e-5, 1.3592183785327006e-5, 1.5173897443654383e-5, 9.43771379136038e-6, 1.0906323046233624e-5, 1.0603954940346938e-5, 1.5900499596113726e-5, 5.978772247650426e-6], - tspan = (0.0, 1.0)) - end + l2=[ + 3.7762324533854616e-6, + 1.5534623833573546e-6, + 1.4577234868196855e-6, + 1.7647724628707057e-6, + 1.4831911814574333e-6, + 1.456369119716533e-6, + 1.4115666913995062e-6, + 1.804758237422838e-6, + 8.320469738087189e-7, + ], + linf=[ + 3.670661330201774e-5, + 1.530289442645827e-5, + 1.3592183785327006e-5, + 1.5173897443654383e-5, + 9.43771379136038e-6, + 1.0906323046233624e-5, + 1.0603954940346938e-5, + 1.5900499596113726e-5, + 5.978772247650426e-6, + ], + tspan=(0.0, 1.0)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_mhd_ec.jl" begin +@trixi_testset "elixir_mhd_ec.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_ec.jl"), - l2 = [0.03637302248881514, 0.043002991956758996, 0.042987505670836056, 0.02574718055258975, 0.1621856170457943, 0.01745369341302589, 0.017454552320664566, 0.026873190440613117, 5.336243933079389e-16], - linf = [0.23623816236321427, 0.3137152204179957, 0.30378397831730597, 0.21500228807094865, 0.9042495730546518, 0.09398098096581875, 0.09470282020962917, 0.15277253978297378, 4.307694418935709e-15]) - end + l2=[ + 0.03637302248881514, + 0.043002991956758996, + 0.042987505670836056, + 0.02574718055258975, + 0.1621856170457943, + 0.01745369341302589, + 0.017454552320664566, + 0.026873190440613117, + 5.336243933079389e-16, + ], + linf=[ + 0.23623816236321427, + 0.3137152204179957, + 0.30378397831730597, + 0.21500228807094865, + 0.9042495730546518, + 0.09398098096581875, + 0.09470282020962917, + 0.15277253978297378, + 4.307694418935709e-15, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_mhd_orszag_tang.jl" begin +@trixi_testset "elixir_mhd_orszag_tang.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_orszag_tang.jl"), - l2 = [0.21967600768935716, 0.2643126515795721, 0.31488287201980875, 0.0, 0.5160141621186931, 0.23028914748088603, 0.34413527376463915, 0.0, 0.003178793090381426], - linf = [1.2749969218080568, 0.6737013368774057, 0.8604154399895696, 0.0, 2.799342099887639, 0.6473347557712643, 0.9691773375490476, 0.0, 0.05729832038724348], - tspan = (0.0, 0.09)) - end + l2=[ + 0.21967600768935716, + 0.2643126515795721, + 0.31488287201980875, + 0.0, + 0.5160141621186931, + 0.23028914748088603, + 0.34413527376463915, + 0.0, + 0.003178793090381426, + ], + linf=[ + 1.2749969218080568, + 0.6737013368774057, + 0.8604154399895696, + 0.0, + 2.799342099887639, + 0.6473347557712643, + 0.9691773375490476, + 0.0, + 0.05729832038724348, + ], + tspan=(0.0, 0.09)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_mhd_orszag_tang.jl with flux_hll" begin +@trixi_testset "elixir_mhd_orszag_tang.jl with flux_hll" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_orszag_tang.jl"), - l2 = [0.10806619664693064, 0.20199136742199922, 0.22984589847526207, 0.0, 0.29950152196422647, 0.15688413207147794, 0.24293641543490646, 0.0, 0.003246181006326598], - linf = [0.560316034595759, 0.5095520363866776, 0.6536748458764621, 0.0, 0.9627447086204038, 0.3981375420906146, 0.673472146198816, 0.0, 0.04879208429337193], - tspan = (0.0, 0.06), surface_flux = (flux_hll, flux_nonconservative_powell)) - end + l2=[ + 0.10806619664693064, + 0.20199136742199922, + 0.22984589847526207, + 0.0, + 0.29950152196422647, + 0.15688413207147794, + 0.24293641543490646, + 0.0, + 0.003246181006326598, + ], + linf=[ + 0.560316034595759, + 0.5095520363866776, + 0.6536748458764621, + 0.0, + 0.9627447086204038, + 0.3981375420906146, + 0.673472146198816, + 0.0, + 0.04879208429337193, + ], + tspan=(0.0, 0.06), + surface_flux=(flux_hlle, + flux_nonconservative_powell)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_mhd_alfven_wave.jl one step with initial_condition_constant" begin +@trixi_testset "elixir_mhd_alfven_wave.jl one step with initial_condition_constant" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_alfven_wave.jl"), - l2 = [7.144325530681224e-17, 2.123397983547417e-16, 5.061138912500049e-16, 3.6588423152083e-17, 8.449816179702522e-15, 3.9171737639099993e-16, 2.445565690318772e-16, 3.6588423152083e-17, 9.971153407737885e-17], - linf = [2.220446049250313e-16, 8.465450562766819e-16, 1.8318679906315083e-15, 1.1102230246251565e-16, 1.4210854715202004e-14, 8.881784197001252e-16, 4.440892098500626e-16, 1.1102230246251565e-16, 4.779017148551244e-16], - maxiters = 1, - initial_condition = initial_condition_constant, - atol = 2.0e-13) - end + l2=[ + 7.144325530681224e-17, + 2.123397983547417e-16, + 5.061138912500049e-16, + 3.6588423152083e-17, + 8.449816179702522e-15, + 3.9171737639099993e-16, + 2.445565690318772e-16, + 3.6588423152083e-17, + 9.971153407737885e-17, + ], + linf=[ + 2.220446049250313e-16, + 8.465450562766819e-16, + 1.8318679906315083e-15, + 1.1102230246251565e-16, + 1.4210854715202004e-14, + 8.881784197001252e-16, + 4.440892098500626e-16, + 1.1102230246251565e-16, + 4.779017148551244e-16, + ], + maxiters=1, + initial_condition=initial_condition_constant, + atol=2.0e-13) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_mhd_rotor.jl" begin +@trixi_testset "elixir_mhd_rotor.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_rotor.jl"), - l2 = [1.2623319195262743, 1.8273050553090515, 1.7004151198284634, 0.0, 2.2978570581460818, 0.2147235065899803, 0.23558337696054493, 0.0, 0.0032515115395693483], - linf = [11.003677581472843, 14.70614192714736, 15.687648666952708, 0.0, 17.098104835553823, 1.3283750501377847, 1.4365828094434892, 0.0, 0.07886241196068537], - tspan = (0.0, 0.05)) - end + l2=[ + 1.2623319195262743, + 1.8273050553090515, + 1.7004151198284634, + 0.0, + 2.2978570581460818, + 0.2147235065899803, + 0.23558337696054493, + 0.0, + 0.0032515115395693483, + ], + linf=[ + 11.003677581472843, + 14.70614192714736, + 15.687648666952708, + 0.0, + 17.098104835553823, + 1.3283750501377847, + 1.4365828094434892, + 0.0, + 0.07886241196068537, + ], + tspan=(0.0, 0.05)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_mhd_blast_wave.jl" begin +@trixi_testset "elixir_mhd_blast_wave.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_blast_wave.jl"), - l2 = [0.17646728395490927, 3.866230215339417, 2.4867304651291255, 0.0, 355.4562971958441, 2.359493623565687, 1.4030741420730297, 0.0, 0.029613599942667133], - linf = [1.581630420824181, 44.15725488910748, 13.056964982196554, 0.0, 2244.875490238186, 13.07679044647926, 9.14612176426092, 0.0, 0.5154756722488522], - tspan = (0.0, 0.003), - # Calling the AnalysisCallback before iteration 9 causes the interpolation - # of this IC to have negative density/pressure values, crashing the simulation. - coverage_override = (maxiters=9,)) - end + l2=[ + 0.17646728395490927, + 3.866230215339417, + 2.4867304651291255, + 0.0, + 355.4562971958441, + 2.359493623565687, + 1.4030741420730297, + 0.0, + 0.029613599942667133, + ], + linf=[ + 1.581630420824181, + 44.15725488910748, + 13.056964982196554, + 0.0, + 2244.875490238186, + 13.07679044647926, + 9.14612176426092, + 0.0, + 0.5154756722488522, + ], + tspan=(0.0, 0.003), + # Calling the AnalysisCallback before iteration 9 causes the interpolation + # of this IC to have negative density/pressure values, crashing the simulation. + coverage_override=(maxiters = 9,)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_mhd_shockcapturing_subcell.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_shockcapturing_subcell.jl"), + l2=[2.9974425783503109e-02, + 7.2849646345685956e-02, + 7.2488477174662239e-02, + 0.0000000000000000e+00, + 1.2507971380965512e+00, + 1.8929505145499678e-02, + 1.2218606317164420e-02, + 0.0000000000000000e+00, + 3.0154796910479838e-03], + linf=[3.2147382412340830e-01, + 1.3709471664007811e+00, + 1.3465154685288383e+00, + 0.0000000000000000e+00, + 1.6051257523415284e+01, + 3.0564266749926644e-01, + 2.3908016329805595e-01, + 0.0000000000000000e+00, + 1.3711262178549158e-01], + tspan=(0.0, 0.003)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 + end +end end end # module diff --git a/test/test_tree_2d_mhdmulti.jl b/test/test_tree_2d_mhdmulti.jl index 09c26569d46..d36554a6679 100644 --- a/test/test_tree_2d_mhdmulti.jl +++ b/test/test_tree_2d_mhdmulti.jl @@ -8,62 +8,126 @@ include("test_trixi.jl") EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") @testset "MHD Multicomponent" begin +#! format: noindent - @trixi_testset "elixir_mhdmulti_ec.jl" begin +@trixi_testset "elixir_mhdmulti_ec.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhdmulti_ec.jl"), - l2 = [0.04300299195675897, 0.042987505670835945, 0.025747180552589767, 0.1621856170457937, - 0.017453693413025828, 0.0174545523206645, 0.026873190440613162, 1.364647699274761e-15, - 0.012124340829605002, 0.024248681659210004], - linf = [0.31371522041799105, 0.3037839783173047, 0.21500228807094351, 0.904249573054642, - 0.0939809809658183, 0.09470282020962761, 0.1527725397829759, 8.245701827530042e-15, - 0.0787460541210726, 0.1574921082421452]) - end + l2=[0.04300299195675897, 0.042987505670835945, + 0.025747180552589767, 0.1621856170457937, + 0.017453693413025828, 0.0174545523206645, + 0.026873190440613162, 1.364647699274761e-15, + 0.012124340829605002, 0.024248681659210004], + linf=[0.31371522041799105, 0.3037839783173047, + 0.21500228807094351, 0.904249573054642, + 0.0939809809658183, 0.09470282020962761, 0.1527725397829759, + 8.245701827530042e-15, + 0.0787460541210726, 0.1574921082421452]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_mhdmulti_ec.jl with flux_derigs_etal" begin +@trixi_testset "elixir_mhdmulti_ec.jl with flux_derigs_etal" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhdmulti_ec.jl"), - l2 = [0.04301155595653799, 0.04299735787276207, 0.025745530869947714, - 0.16206102676791553, 0.017454384272339165, 0.01745523378100091, - 0.026879482381500154, 0.0002038008756963954, 0.012094208262809778, - 0.024188416525619556], - linf = [0.3156206778985397, 0.30941696929809526, 0.21167563519254176, - 0.9688251298546122, 0.09076254289155083, 0.09160589769498295, - 0.15698032974768705, 0.006131914796912965, 0.07839287555951036, - 0.1567857511190207], - volume_flux = (flux_derigs_etal, flux_nonconservative_powell), - surface_flux = (flux_derigs_etal, flux_nonconservative_powell)) - end + l2=[0.04301155595653799, 0.04299735787276207, + 0.025745530869947714, + 0.16206102676791553, 0.017454384272339165, + 0.01745523378100091, + 0.026879482381500154, 0.0002038008756963954, + 0.012094208262809778, + 0.024188416525619556], + linf=[0.3156206778985397, 0.30941696929809526, + 0.21167563519254176, + 0.9688251298546122, 0.09076254289155083, + 0.09160589769498295, + 0.15698032974768705, 0.006131914796912965, + 0.07839287555951036, + 0.1567857511190207], + volume_flux=(flux_derigs_etal, flux_nonconservative_powell), + surface_flux=(flux_derigs_etal, flux_nonconservative_powell)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_mhdmulti_es.jl" begin +@trixi_testset "elixir_mhdmulti_es.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhdmulti_es.jl"), - l2 = [0.042511527162267, 0.04250603277530184, 0.02385422747993974, 0.11555081362726903, - 0.016366641053738043, 0.01636681584592762, 0.02581748418797907, 0.00023394429554818215, - 0.010834603551662698, 0.021669207103325396], - linf = [0.23454607703107877, 0.23464789247380322, 0.11898832084115452, 0.5331209602648022, - 0.061744814466827336, 0.061767127585091286, 0.09595041452184983, 0.004421037168524759, - 0.06186597801911198, 0.12373195603822396]) - end + l2=[0.042511527162267, 0.04250603277530184, 0.02385422747993974, + 0.11555081362726903, + 0.016366641053738043, 0.01636681584592762, + 0.02581748418797907, 0.00023394429554818215, + 0.010834603551662698, 0.021669207103325396], + linf=[0.23454607703107877, 0.23464789247380322, + 0.11898832084115452, 0.5331209602648022, + 0.061744814466827336, 0.061767127585091286, + 0.09595041452184983, 0.004421037168524759, + 0.06186597801911198, 0.12373195603822396]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_mhdmulti_convergence.jl" begin +@trixi_testset "elixir_mhdmulti_convergence.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhdmulti_convergence.jl"), - l2 = [0.0003808877028249613, 0.0003808877028249593, 0.0005155994511260122, 0.000570394227652563, - 0.000439568811048544, 0.0004395688110485541, 0.0005074093477702055, 0.0003859005258180428, - 7.4611207452221e-5, 0.000149222414904442, 0.000298444829808884], - linf = [0.0013324014301672943, 0.0013324014301669181, 0.002684449324758791, 0.0016236816790307085, - 0.0019172373117153363, 0.0019172373117148922, 0.002664932274107224, 0.0011872396664042962, - 0.0002855492944235094, 0.0005710985888470188, 0.0011421971776940376]) - end + l2=[0.0003808877028249613, 0.0003808877028249593, + 0.0005155994511260122, 0.000570394227652563, + 0.000439568811048544, 0.0004395688110485541, + 0.0005074093477702055, 0.0003859005258180428, + 7.4611207452221e-5, 0.000149222414904442, + 0.000298444829808884], + linf=[0.0013324014301672943, 0.0013324014301669181, + 0.002684449324758791, 0.0016236816790307085, + 0.0019172373117153363, 0.0019172373117148922, + 0.002664932274107224, 0.0011872396664042962, + 0.0002855492944235094, 0.0005710985888470188, + 0.0011421971776940376]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_mhdmulti_rotor.jl" begin +@trixi_testset "elixir_mhdmulti_rotor.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhdmulti_rotor.jl"), - l2 = [0.6574605535168556, 0.6623234319361953, 0.0, 0.689806698245354, - 0.04883686128677976, 0.08382459729494686, 0.0, 0.0021114516459281177, - 0.15909290019096098, 0.07954645009548049], - linf = [9.362339085941425, 9.169838118652539, 0.0, 10.600957847359556, - 0.6628317732399827, 1.4185626901435056, 0.0, 0.06914316292003836, - 3.328770801731456, 1.664385400865728], - tspan = (0.0, 0.01)) + l2=[0.6574605535168556, 0.6623234319361953, 0.0, + 0.689806698245354, + 0.04883686128677976, 0.08382459729494686, 0.0, + 0.0021114516459281177, + 0.15909290019096098, 0.07954645009548049], + linf=[9.362339085941425, 9.169838118652539, 0.0, + 10.600957847359556, + 0.6628317732399827, 1.4185626901435056, 0.0, + 0.06914316292003836, + 3.328770801731456, 1.664385400865728], + tspan=(0.0, 0.01)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end end - end end # module diff --git a/test/test_tree_2d_part1.jl b/test/test_tree_2d_part1.jl index c2076a7e235..2af1f29fcb6 100644 --- a/test/test_tree_2d_part1.jl +++ b/test/test_tree_2d_part1.jl @@ -9,82 +9,94 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") # Start with a clean environment: remove Trixi.jl output directory if it exists outdir = "out" -isdir(outdir) && rm(outdir, recursive=true) +isdir(outdir) && rm(outdir, recursive = true) @testset "TreeMesh2D Part 1" begin +#! format: noindent # Run basic tests @testset "Examples 2D" begin - # Linear advection - include("test_tree_2d_advection.jl") + # Linear advection + include("test_tree_2d_advection.jl") - # Hyperbolic diffusion - include("test_tree_2d_hypdiff.jl") + # Hyperbolic diffusion + include("test_tree_2d_hypdiff.jl") end - @testset "Displaying components 2D" begin - @test_nowarn include(joinpath(EXAMPLES_DIR, "elixir_advection_amr.jl")) - - # test both short and long printing formats - @test_nowarn show(mesh); println() - @test_nowarn println(mesh) - @test_nowarn display(mesh) - - @test_nowarn show(equations); println() - @test_nowarn println(equations) - @test_nowarn display(equations) - - @test_nowarn show(solver); println() - @test_nowarn println(solver) - @test_nowarn display(solver) - - @test_nowarn show(solver.basis); println() - @test_nowarn println(solver.basis) - @test_nowarn display(solver.basis) - - @test_nowarn show(solver.mortar); println() - @test_nowarn println(solver.mortar) - @test_nowarn display(solver.mortar) - - @test_nowarn show(semi); println() - @test_nowarn println(semi) - @test_nowarn display(semi) - - @test_nowarn show(summary_callback); println() - @test_nowarn println(summary_callback) - @test_nowarn display(summary_callback) - - @test_nowarn show(amr_controller); println() - @test_nowarn println(amr_controller) - @test_nowarn display(amr_controller) - - @test_nowarn show(amr_callback); println() - @test_nowarn println(amr_callback) - @test_nowarn display(amr_callback) - - @test_nowarn show(stepsize_callback); println() - @test_nowarn println(stepsize_callback) - @test_nowarn display(stepsize_callback) - - @test_nowarn show(save_solution); println() - @test_nowarn println(save_solution) - @test_nowarn display(save_solution) - - @test_nowarn show(analysis_callback); println() - @test_nowarn println(analysis_callback) - @test_nowarn display(analysis_callback) - - @test_nowarn show(alive_callback); println() - @test_nowarn println(alive_callback) - @test_nowarn display(alive_callback) - - @test_nowarn println(callbacks) + @test_nowarn include(joinpath(EXAMPLES_DIR, "elixir_advection_amr.jl")) + + # test both short and long printing formats + @test_nowarn show(mesh) + println() + @test_nowarn println(mesh) + @test_nowarn display(mesh) + + @test_nowarn show(equations) + println() + @test_nowarn println(equations) + @test_nowarn display(equations) + + @test_nowarn show(solver) + println() + @test_nowarn println(solver) + @test_nowarn display(solver) + + @test_nowarn show(solver.basis) + println() + @test_nowarn println(solver.basis) + @test_nowarn display(solver.basis) + + @test_nowarn show(solver.mortar) + println() + @test_nowarn println(solver.mortar) + @test_nowarn display(solver.mortar) + + @test_nowarn show(semi) + println() + @test_nowarn println(semi) + @test_nowarn display(semi) + + @test_nowarn show(summary_callback) + println() + @test_nowarn println(summary_callback) + @test_nowarn display(summary_callback) + + @test_nowarn show(amr_controller) + println() + @test_nowarn println(amr_controller) + @test_nowarn display(amr_controller) + + @test_nowarn show(amr_callback) + println() + @test_nowarn println(amr_callback) + @test_nowarn display(amr_callback) + + @test_nowarn show(stepsize_callback) + println() + @test_nowarn println(stepsize_callback) + @test_nowarn display(stepsize_callback) + + @test_nowarn show(save_solution) + println() + @test_nowarn println(save_solution) + @test_nowarn display(save_solution) + + @test_nowarn show(analysis_callback) + println() + @test_nowarn println(analysis_callback) + @test_nowarn display(analysis_callback) + + @test_nowarn show(alive_callback) + println() + @test_nowarn println(alive_callback) + @test_nowarn display(alive_callback) + + @test_nowarn println(callbacks) end # Clean up afterwards: delete Trixi.jl output directory -@test_nowarn rm(outdir, recursive=true) - +@test_nowarn rm(outdir, recursive = true) end # TreeMesh2D Part 1 end #module diff --git a/test/test_tree_2d_part2.jl b/test/test_tree_2d_part2.jl index e25b5888c63..622f12109ff 100644 --- a/test/test_tree_2d_part2.jl +++ b/test/test_tree_2d_part2.jl @@ -7,34 +7,37 @@ include("test_trixi.jl") # Start with a clean environment: remove Trixi.jl output directory if it exists outdir = "out" -isdir(outdir) && rm(outdir, recursive=true) +isdir(outdir) && rm(outdir, recursive = true) @testset "TreeMesh2D Part 2" begin +#! format: noindent # Run basic tests @testset "Examples 2D" begin - # Acoustic perturbation - include("test_tree_2d_acoustics.jl") + # Acoustic perturbation + include("test_tree_2d_acoustics.jl") - # Linearized Euler - include("test_tree_2d_linearizedeuler.jl") + # Linearized Euler + include("test_tree_2d_linearizedeuler.jl") - # Compressible Euler - include("test_tree_2d_euler.jl") + # Compressible Euler + include("test_tree_2d_euler.jl") - # Compressible Euler Multicomponent - include("test_tree_2d_eulermulti.jl") + # Compressible Euler Multicomponent + include("test_tree_2d_eulermulti.jl") - # Compressible Euler coupled with acoustic perturbation equations - include("test_tree_2d_euleracoustics.jl") + # Compressible Polytropic Euler + include("test_tree_2d_eulerpolytropic.jl") - # KPP problem - include("test_tree_2d_kpp.jl") + # Compressible Euler coupled with acoustic perturbation equations + include("test_tree_2d_euleracoustics.jl") + + # KPP problem + include("test_tree_2d_kpp.jl") end # Clean up afterwards: delete Trixi.jl output directory -@test_nowarn rm(outdir, recursive=true) - +@test_nowarn rm(outdir, recursive = true) end # TreeMesh2D Part 2 end #module diff --git a/test/test_tree_2d_part3.jl b/test/test_tree_2d_part3.jl index 450dad6eadd..ce9b3bc04f8 100644 --- a/test/test_tree_2d_part3.jl +++ b/test/test_tree_2d_part3.jl @@ -7,34 +7,34 @@ include("test_trixi.jl") # Start with a clean environment: remove Trixi.jl output directory if it exists outdir = "out" -isdir(outdir) && rm(outdir, recursive=true) +isdir(outdir) && rm(outdir, recursive = true) @testset "TreeMesh2D Part 3" begin +#! format: noindent # Run basic tests @testset "Examples 2D" begin - # MHD - include("test_tree_2d_mhd.jl") + # MHD + include("test_tree_2d_mhd.jl") - # MHD Multicomponent - include("test_tree_2d_mhdmulti.jl") + # MHD Multicomponent + include("test_tree_2d_mhdmulti.jl") - # Lattice-Boltzmann - include("test_tree_2d_lbm.jl") + # Lattice-Boltzmann + include("test_tree_2d_lbm.jl") - # Shallow water - include("test_tree_2d_shallowwater.jl") + # Shallow water + include("test_tree_2d_shallowwater.jl") - # Two-Layer Shallow Water - include("test_tree_2d_shallowwater_twolayer.jl") + # Two-Layer Shallow Water + include("test_tree_2d_shallowwater_twolayer.jl") - # FDSBP methods on the TreeMesh - include("test_tree_2d_fdsbp.jl") + # FDSBP methods on the TreeMesh + include("test_tree_2d_fdsbp.jl") end # Clean up afterwards: delete Trixi.jl output directory -@test_nowarn rm(outdir, recursive=true) - +@test_nowarn rm(outdir, recursive = true) end # TreeMesh2D Part 3 end #module diff --git a/test/test_tree_2d_shallowwater.jl b/test/test_tree_2d_shallowwater.jl index 7670d28f43a..58db7c5f35f 100644 --- a/test/test_tree_2d_shallowwater.jl +++ b/test/test_tree_2d_shallowwater.jl @@ -10,77 +10,323 @@ include("test_trixi.jl") EXAMPLES_DIR = joinpath(examples_dir(), "tree_2d_dgsem") @testset "Shallow Water" begin - @trixi_testset "elixir_shallowwater_ec.jl" begin +#! format: noindent + +@trixi_testset "elixir_shallowwater_ec.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_ec.jl"), - l2 = [0.991181203601035, 0.734130029040644, 0.7447696147162621, 0.5875351036989047], - linf = [2.0117744577945413, 2.9962317608172127, 2.6554999727293653, 3.0], - tspan = (0.0, 0.25)) - end + l2=[ + 0.991181203601035, + 0.734130029040644, + 0.7447696147162621, + 0.5875351036989047, + ], + linf=[ + 2.0117744577945413, + 2.9962317608172127, + 2.6554999727293653, + 3.0, + ], + tspan=(0.0, 0.25)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_shallowwater_well_balanced.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_well_balanced.jl"), + l2=[ + 0.9130579602987144, + 1.0602847041965408e-14, + 1.082225645390032e-14, + 0.9130579602987147, + ], + linf=[ + 2.113062037615659, + 4.6613606802974e-14, + 5.4225772771633196e-14, + 2.1130620376156584, + ], + tspan=(0.0, 0.25)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_shallowwater_well_balanced_wall.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_shallowwater_well_balanced_wall.jl"), + l2=[ + 0.9130579602987144, + 1.0602847041965408e-14, + 1.082225645390032e-14, + 0.9130579602987147, + ], + linf=[ + 2.113062037615659, + 4.6613606802974e-14, + 5.4225772771633196e-14, + 2.1130620376156584, + ], + tspan=(0.0, 0.25)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_shallowwater_well_balanced.jl" begin +@trixi_testset "elixir_shallowwater_well_balanced.jl with FluxHydrostaticReconstruction" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_well_balanced.jl"), - l2 = [0.9130579602987144, 1.0602847041965408e-14, 1.082225645390032e-14, 0.9130579602987147], - linf = [2.113062037615659, 4.6613606802974e-14, 5.4225772771633196e-14, 2.1130620376156584], - tspan = (0.0, 0.25)) - end - - @trixi_testset "elixir_shallowwater_well_balanced_wall.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_well_balanced_wall.jl"), - l2 = [0.9130579602987144, 1.0602847041965408e-14, 1.082225645390032e-14, 0.9130579602987147], - linf = [2.113062037615659, 4.6613606802974e-14, 5.4225772771633196e-14, 2.1130620376156584], - tspan = (0.0, 0.25)) - end - - @trixi_testset "elixir_shallowwater_well_balanced.jl with FluxHydrostaticReconstruction" begin + l2=[ + 0.9130579602987147, + 9.68729463970494e-15, + 9.694538537436981e-15, + 0.9130579602987147, + ], + linf=[ + 2.1130620376156584, + 2.3875905654916432e-14, + 2.2492839032269154e-14, + 2.1130620376156584, + ], + surface_flux=(FluxHydrostaticReconstruction(flux_lax_friedrichs, + hydrostatic_reconstruction_audusse_etal), + flux_nonconservative_audusse_etal), + tspan=(0.0, 0.25)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_shallowwater_well_balanced.jl with flux_nonconservative_ersing_etal" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_well_balanced.jl"), - l2 = [0.9130579602987147, 9.68729463970494e-15, 9.694538537436981e-15, 0.9130579602987147], - linf = [2.1130620376156584, 2.3875905654916432e-14, 2.2492839032269154e-14, 2.1130620376156584], - surface_flux=(FluxHydrostaticReconstruction(flux_lax_friedrichs, hydrostatic_reconstruction_audusse_etal), flux_nonconservative_audusse_etal), - tspan = (0.0, 0.25)) - end - - @trixi_testset "elixir_shallowwater_well_balanced_wet_dry.jl with FluxHydrostaticReconstruction" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_well_balanced_wet_dry.jl"), - l2 = [0.030186039395610056, 2.513287752536758e-14, 1.3631397744897607e-16, 0.10911781485920438], - linf = [0.49999999999993505, 5.5278950497971455e-14, 7.462550826772548e-16, 2.0], - tspan = (0.0, 0.25)) - end - - @trixi_testset "elixir_shallowwater_source_terms.jl" begin + l2=[ + 0.9130579602987146, + 1.0323158914614244e-14, + 1.0276096319430528e-14, + 0.9130579602987147, + ], + linf=[ + 2.11306203761566, + 4.063916419044386e-14, + 3.694484044448245e-14, + 2.1130620376156584, + ], + surface_flux=(flux_wintermeyer_etal, + flux_nonconservative_ersing_etal), + volume_flux=(flux_wintermeyer_etal, + flux_nonconservative_ersing_etal), + tspan=(0.0, 0.25)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_shallowwater_well_balanced_wet_dry.jl with FluxHydrostaticReconstruction" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_shallowwater_well_balanced_wet_dry.jl"), + l2=[ + 0.030186039395610056, + 2.513287752536758e-14, + 1.3631397744897607e-16, + 0.10911781485920438, + ], + linf=[ + 0.49999999999993505, + 5.5278950497971455e-14, + 7.462550826772548e-16, + 2.0, + ], + tspan=(0.0, 0.25)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_shallowwater_source_terms.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_source_terms.jl"), - l2 = [0.001868474306068482, 0.01731687445878443, 0.017649083171490863, 6.274146767717023e-5], - linf = [0.016962486402209986, 0.08768628853889782, 0.09038488750767648, 0.0001819675955490041], - tspan = (0.0, 0.025)) - end - - @trixi_testset "elixir_shallowwater_source_terms_dirichlet.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_source_terms_dirichlet.jl"), - l2 = [0.0018746929418489125, 0.017332321628469628, 0.01634953679145536, 6.274146767717023e-5], - linf = [0.016262353691956388, 0.08726160620859424, 0.09043621801418844, 0.0001819675955490041], - tspan = (0.0, 0.025)) - end - - @trixi_testset "elixir_shallowwater_source_terms.jl with flux_hll" begin + l2=[ + 0.001868474306068482, + 0.01731687445878443, + 0.017649083171490863, + 6.274146767717023e-5, + ], + linf=[ + 0.016962486402209986, + 0.08768628853889782, + 0.09038488750767648, + 0.0001819675955490041, + ], + tspan=(0.0, 0.025)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_shallowwater_source_terms_dirichlet.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_shallowwater_source_terms_dirichlet.jl"), + l2=[ + 0.0018746929418489125, + 0.017332321628469628, + 0.01634953679145536, + 6.274146767717023e-5, + ], + linf=[ + 0.016262353691956388, + 0.08726160620859424, + 0.09043621801418844, + 0.0001819675955490041, + ], + tspan=(0.0, 0.025)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_shallowwater_source_terms.jl with flux_hll" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_source_terms.jl"), - l2 = [0.0018957692481057034, 0.016943229710439864, 0.01755623297390675, 6.274146767717414e-5], - linf = [0.015156105797771602, 0.07964811135780492, 0.0839787097210376, 0.0001819675955490041], - tspan = (0.0, 0.025), surface_flux=(flux_hll, flux_nonconservative_fjordholm_etal)) - end + l2=[ + 0.0018957692481057034, + 0.016943229710439864, + 0.01755623297390675, + 6.274146767717414e-5, + ], + linf=[ + 0.015156105797771602, + 0.07964811135780492, + 0.0839787097210376, + 0.0001819675955490041, + ], + tspan=(0.0, 0.025), + surface_flux=(flux_hll, flux_nonconservative_fjordholm_etal)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_shallowwater_conical_island.jl" begin +@trixi_testset "elixir_shallowwater_source_terms.jl with flux_nonconservative_ersing_etal" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_source_terms.jl"), + l2=[ + 0.002471853426064005, + 0.05619168608950033, + 0.11844727575152562, + 6.274146767730281e-5, + ], + linf=[ + 0.014332922987500218, + 0.2141204806174546, + 0.5392313755637872, + 0.0001819675955490041, + ], + surface_flux=(flux_wintermeyer_etal, + flux_nonconservative_ersing_etal), + volume_flux=(flux_wintermeyer_etal, + flux_nonconservative_ersing_etal), + tspan=(0.0, 0.25)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_shallowwater_conical_island.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_conical_island.jl"), - l2 = [0.0459315416430658, 0.1644534881916991, 0.16445348819169914, 0.0011537702354532694], - linf = [0.21100717610846464, 0.9501592344310412, 0.9501592344310417, 0.021790250683516282], - tspan = (0.0, 0.025)) - end + l2=[ + 0.0459315416430658, + 0.1644534881916991, + 0.16445348819169914, + 0.0011537702354532694, + ], + linf=[ + 0.21100717610846464, + 0.9501592344310412, + 0.9501592344310417, + 0.021790250683516282, + ], + tspan=(0.0, 0.025)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_shallowwater_parabolic_bowl.jl" begin +@trixi_testset "elixir_shallowwater_parabolic_bowl.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_parabolic_bowl.jl"), - l2 = [0.00025345501281482687, 4.4525120338817177e-5, 0.00015991819160294247, 7.750412064917294e-15], - linf = [0.004664246019836723, 0.0004972780116736669, 0.0028735707270457628, 6.866729407306593e-14], - tspan = (0.0, 0.025), - basis = LobattoLegendreBasis(3)) - end + l2=[ + 0.00025345501281482687, + 4.4525120338817177e-5, + 0.00015991819160294247, + 7.750412064917294e-15, + ], + linf=[ + 0.004664246019836723, + 0.0004972780116736669, + 0.0028735707270457628, + 6.866729407306593e-14, + ], + tspan=(0.0, 0.025), + basis=LobattoLegendreBasis(3)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end end end # module diff --git a/test/test_tree_2d_shallowwater_twolayer.jl b/test/test_tree_2d_shallowwater_twolayer.jl index 7ad5b0f7316..802bf4e021c 100644 --- a/test/test_tree_2d_shallowwater_twolayer.jl +++ b/test/test_tree_2d_shallowwater_twolayer.jl @@ -10,49 +10,79 @@ include("test_trixi.jl") EXAMPLES_DIR = joinpath(examples_dir(), "tree_2d_dgsem") @testset "Two-Layer Shallow Water" begin - @trixi_testset "elixir_shallowwater_twolayer_convergence.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_twolayer_convergence.jl"), - l2 = [0.0004040147445601598, 0.005466848793475609, 0.006149138398472166, 0.0002908599437447256, - 0.003011817461911792, 0.0026806180089700674, 8.873630921431545e-6], - linf = [0.002822006686981293, 0.014859895905040332, 0.017590546190827894, 0.0016323702636176218, - 0.009361402900653015, 0.008411036357379165, 3.361991620143279e-5], - tspan = (0.0, 0.25)) - end - - @trixi_testset "elixir_shallowwater_twolayer_convergence.jl with flux_es_fjordholm_etal" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_twolayer_convergence.jl"), - l2 = [0.00024709443131137236, 0.0019215286339769443, 0.0023833298173254447, - 0.00021258247976270914, 0.0011299428031136195, 0.0009191313765262401, - 8.873630921431545e-6], - linf = [0.0016099763244645793, 0.007659242165565017, 0.009123320235427057, - 0.0013496983982568267, 0.0035573687287770994, 0.00296823235874899, - 3.361991620143279e-5], - surface_flux = (flux_es_fjordholm_etal, flux_nonconservative_fjordholm_etal), - tspan = (0.0, 0.25)) - end - - @trixi_testset "elixir_shallowwater_twolayer_well_balanced.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_twolayer_well_balanced.jl"), - l2 = [3.2935164267930016e-16, 4.6800825611195103e-17, 4.843057532147818e-17, - 0.0030769233188015013, 1.4809161150389857e-16, 1.509071695038043e-16, - 0.0030769233188014935], - linf = [2.248201624865942e-15, 2.346382070278936e-16, 2.208565017494899e-16, - 0.026474051138910493, 9.237568031609006e-16, 7.520758026187046e-16, - 0.026474051138910267], - tspan = (0.0, 0.25)) - end - - @trixi_testset "elixir_shallowwater_twolayer_well_balanced with flux_lax_friedrichs.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_twolayer_well_balanced.jl"), - l2 = [2.0525741072929735e-16, 6.000589392730905e-17, 6.102759428478984e-17, - 0.0030769233188014905, 1.8421386173122792e-16, 1.8473184927121752e-16, - 0.0030769233188014935], - linf = [7.355227538141662e-16, 2.960836949170518e-16, 4.2726562436938764e-16, - 0.02647405113891016, 1.038795478061861e-15, 1.0401789378532516e-15, - 0.026474051138910267], - surface_flux = (flux_lax_friedrichs, flux_nonconservative_fjordholm_etal), - tspan = (0.0, 0.25)) - end + @trixi_testset "elixir_shallowwater_twolayer_convergence.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_shallowwater_twolayer_convergence.jl"), + l2=[0.0004016779699408397, 0.005466339651545468, + 0.006148841330156112, + 0.0002882339012602492, 0.0030120142442780313, + 0.002680752838455618, + 8.873630921431545e-6], + linf=[0.002788654460984752, 0.01484602033450666, + 0.017572229756493973, + 0.0016010835493927011, 0.009369847995372549, + 0.008407961775489636, + 3.361991620143279e-5], + tspan=(0.0, 0.25)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end + end + + @trixi_testset "elixir_shallowwater_twolayer_well_balanced.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_shallowwater_twolayer_well_balanced.jl"), + l2=[3.2935164267930016e-16, 4.6800825611195103e-17, + 4.843057532147818e-17, + 0.0030769233188015013, 1.4809161150389857e-16, + 1.509071695038043e-16, + 0.0030769233188014935], + linf=[2.248201624865942e-15, 2.346382070278936e-16, + 2.208565017494899e-16, + 0.026474051138910493, 9.237568031609006e-16, + 7.520758026187046e-16, + 0.026474051138910267], + tspan=(0.0, 0.25)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end + end + + @trixi_testset "elixir_shallowwater_twolayer_well_balanced with flux_lax_friedrichs.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_shallowwater_twolayer_well_balanced.jl"), + l2=[2.0525741072929735e-16, 6.000589392730905e-17, + 6.102759428478984e-17, + 0.0030769233188014905, 1.8421386173122792e-16, + 1.8473184927121752e-16, + 0.0030769233188014935], + linf=[7.355227538141662e-16, 2.960836949170518e-16, + 4.2726562436938764e-16, + 0.02647405113891016, 1.038795478061861e-15, + 1.0401789378532516e-15, + 0.026474051138910267], + surface_flux=(flux_lax_friedrichs, + flux_nonconservative_ersing_etal), + tspan=(0.0, 0.25)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end + end end end # module diff --git a/test/test_tree_3d_advection.jl b/test/test_tree_3d_advection.jl index c2e74f8312d..ae53a2df52f 100644 --- a/test/test_tree_3d_advection.jl +++ b/test/test_tree_3d_advection.jl @@ -8,61 +8,117 @@ include("test_trixi.jl") EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_3d_dgsem") @testset "Linear scalar advection" begin - @trixi_testset "elixir_advection_basic.jl" begin +#! format: noindent + +@trixi_testset "elixir_advection_basic.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_basic.jl"), - l2 = [0.00016263963870641478], - linf = [0.0014537194925779984]) - end + l2=[0.00016263963870641478], + linf=[0.0014537194925779984]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_advection_restart.jl" begin +@trixi_testset "elixir_advection_restart.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_restart.jl"), - l2 = [0.00016017848135651983], - linf = [0.0014175368788298393]) - end + l2=[0.00016017848135651983], + linf=[0.0014175368788298393], + # With the default `maxiters = 1` in coverage tests, + # there would be no time steps after the restart. + coverage_override=(maxiters = 100_000,)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_advection_extended.jl with initial_condition_sin" begin +@trixi_testset "elixir_advection_extended.jl with initial_condition_sin" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_extended.jl"), - l2 = [0.002647730309275237], - linf = [0.02114324070353557], - initial_condition=Trixi.initial_condition_sin) - end + l2=[0.002647730309275237], + linf=[0.02114324070353557], + initial_condition=Trixi.initial_condition_sin) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_advection_extended.jl with initial_condition_constant" begin +@trixi_testset "elixir_advection_extended.jl with initial_condition_constant" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_extended.jl"), - l2 = [7.728011630010656e-16], - linf = [3.9968028886505635e-15], - initial_condition=initial_condition_constant) - end + l2=[7.728011630010656e-16], + linf=[3.9968028886505635e-15], + initial_condition=initial_condition_constant) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_advection_extended.jl with initial_condition_linear_z and periodicity=false" begin +@trixi_testset "elixir_advection_extended.jl with initial_condition_linear_z and periodicity=false" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_extended.jl"), - l2 = [3.007995700405795e-16], - linf = [2.886579864025407e-15], - initial_condition=Trixi.initial_condition_linear_z, - boundary_conditions=Trixi.boundary_condition_linear_z, periodicity=false) - end + l2=[3.007995700405795e-16], + linf=[2.886579864025407e-15], + initial_condition=Trixi.initial_condition_linear_z, + boundary_conditions=Trixi.boundary_condition_linear_z, + periodicity=false) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_advection_mortar.jl" begin +@trixi_testset "elixir_advection_mortar.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_mortar.jl"), - l2 = [0.001810141301577316], - linf = [0.017848192256602058]) + l2=[0.001810141301577316], + linf=[0.017848192256602058]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 end - end +end - @trixi_testset "elixir_advection_amr.jl" begin +@trixi_testset "elixir_advection_amr.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_amr.jl"), - l2 = [9.773852895157622e-6], - linf = [0.0005853874124926162], - coverage_override = (maxiters=6, initial_refinement_level=1, base_level=1, med_level=1, max_level=3)) - end + l2=[9.773852895157622e-6], + linf=[0.0005853874124926162], + coverage_override=(maxiters = 6, initial_refinement_level = 1, + base_level = 1, med_level = 1, max_level = 3)) + + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end end end # module diff --git a/test/test_tree_3d_euler.jl b/test/test_tree_3d_euler.jl index 2beb6fc7bed..02e657e001a 100644 --- a/test/test_tree_3d_euler.jl +++ b/test/test_tree_3d_euler.jl @@ -8,126 +8,499 @@ include("test_trixi.jl") EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_3d_dgsem") @testset "Compressible Euler" begin - @trixi_testset "elixir_euler_source_terms.jl" begin +#! format: noindent + +@trixi_testset "elixir_euler_source_terms.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms.jl"), - l2 = [0.010385936842224346, 0.009776048833895767, 0.00977604883389591, 0.009776048833895733, 0.01506687097416608], - linf = [0.03285848350791731, 0.0321792316408982, 0.032179231640894645, 0.032179231640895534, 0.0655408023333299]) - end + l2=[ + 0.010385936842224346, + 0.009776048833895767, + 0.00977604883389591, + 0.009776048833895733, + 0.01506687097416608, + ], + linf=[ + 0.03285848350791731, + 0.0321792316408982, + 0.032179231640894645, + 0.032179231640895534, + 0.0655408023333299, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_convergence_pure_fv.jl" begin +@trixi_testset "elixir_euler_convergence_pure_fv.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_convergence_pure_fv.jl"), - l2 = [0.037182410351406, 0.032062252638283974, 0.032062252638283974, 0.03206225263828395, 0.12228177813586687], - linf = [0.0693648413632646, 0.0622101894740843, 0.06221018947408474, 0.062210189474084965, 0.24196451799555962]) - end + l2=[ + 0.037182410351406, + 0.032062252638283974, + 0.032062252638283974, + 0.03206225263828395, + 0.12228177813586687, + ], + linf=[ + 0.0693648413632646, + 0.0622101894740843, + 0.06221018947408474, + 0.062210189474084965, + 0.24196451799555962, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_source_terms.jl with split_form" begin +@trixi_testset "elixir_euler_source_terms.jl with split_form" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_source_terms.jl"), - l2 = [0.010385936842223388, 0.009776048833894784, 0.009776048833894784, 0.009776048833894765, 0.015066870974164096], - linf = [0.03285848350791687, 0.032179231640897754, 0.0321792316408942, 0.0321792316408982, 0.06554080233333615], - volume_integral=VolumeIntegralFluxDifferencing(flux_central)) - end + l2=[ + 0.010385936842223388, + 0.009776048833894784, + 0.009776048833894784, + 0.009776048833894765, + 0.015066870974164096, + ], + linf=[ + 0.03285848350791687, + 0.032179231640897754, + 0.0321792316408942, + 0.0321792316408982, + 0.06554080233333615, + ], + volume_integral=VolumeIntegralFluxDifferencing(flux_central)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_convergence.jl" begin +@trixi_testset "elixir_euler_convergence.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_convergence.jl"), - l2 = [0.0003637241020254405, 0.0003955570866382718, 0.0003955570866383613, 0.00039555708663834417, 0.0007811613481640202], - linf = [0.0024000660244674066, 0.0029635410025339315, 0.0029635410025292686, 0.002963541002525938, 0.007191437359396424]) - end + l2=[ + 0.0003637241020254405, + 0.0003955570866382718, + 0.0003955570866383613, + 0.00039555708663834417, + 0.0007811613481640202, + ], + linf=[ + 0.0024000660244674066, + 0.0029635410025339315, + 0.0029635410025292686, + 0.002963541002525938, + 0.007191437359396424, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_mortar.jl" begin +@trixi_testset "elixir_euler_mortar.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_mortar.jl"), - l2 = [0.0019428114665068841, 0.0018659907926698422, 0.0018659907926698589, 0.0018659907926698747, 0.0034549095578444056], - linf = [0.011355360771142298, 0.011526889155693887, 0.011526889155689002, 0.011526889155701436, 0.02299726519821288]) - end + l2=[ + 0.0019428114665068841, + 0.0018659907926698422, + 0.0018659907926698589, + 0.0018659907926698747, + 0.0034549095578444056, + ], + linf=[ + 0.011355360771142298, + 0.011526889155693887, + 0.011526889155689002, + 0.011526889155701436, + 0.02299726519821288, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_amr.jl" begin +@trixi_testset "elixir_euler_amr.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_amr.jl"), - l2 = [0.0038281920613404716, 0.003828192061340465, 0.0038281920613404694, 0.0038281920613404672, 0.005742288092010652], - linf = [0.07390396464027349, 0.07390396464027305, 0.07390396464027305, 0.07390396464027305, 0.11085594696041134], - tspan=(0.0, 0.1), - coverage_override = (maxiters=6, initial_refinement_level=0, base_level=0, med_level=0, max_level=1)) - end + l2=[ + 0.0038281920613404716, + 0.003828192061340465, + 0.0038281920613404694, + 0.0038281920613404672, + 0.005742288092010652, + ], + linf=[ + 0.07390396464027349, + 0.07390396464027305, + 0.07390396464027305, + 0.07390396464027305, + 0.11085594696041134, + ], + tspan=(0.0, 0.1), + coverage_override=(maxiters = 6, initial_refinement_level = 0, + base_level = 0, med_level = 0, max_level = 1)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_taylor_green_vortex.jl" begin +@trixi_testset "elixir_euler_taylor_green_vortex.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_taylor_green_vortex.jl"), - l2 = [0.00034949871748737876, 0.03133384111621587, 0.03133384111621582, 0.04378599329988925, 0.015796137903453026], - linf = [0.0013935237751798724, 0.0724080091006194, 0.07240800910061806, 0.12795921224174792, 0.07677156293692633], - tspan = (0.0, 0.5)) - end + l2=[ + 0.00034949871748737876, + 0.03133384111621587, + 0.03133384111621582, + 0.04378599329988925, + 0.015796137903453026, + ], + linf=[ + 0.0013935237751798724, + 0.0724080091006194, + 0.07240800910061806, + 0.12795921224174792, + 0.07677156293692633, + ], + tspan=(0.0, 0.5)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_shockcapturing.jl" begin +@trixi_testset "elixir_euler_shockcapturing.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_shockcapturing.jl"), - l2 = [0.02570137197844877, 0.016179934130642552, 0.01617993413064253, 0.016172648598753545, 0.09261669328795467], - linf = [0.3954458125573179, 0.26876916180359345, 0.26876916180359345, 0.26933123042178553, 1.3724137121660251]) - end + l2=[ + 0.02570137197844877, + 0.016179934130642552, + 0.01617993413064253, + 0.016172648598753545, + 0.09261669328795467, + ], + linf=[ + 0.3954458125573179, + 0.26876916180359345, + 0.26876916180359345, + 0.26933123042178553, + 1.3724137121660251, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_shockcapturing_amr.jl" begin +@trixi_testset "elixir_euler_shockcapturing_amr.jl" begin # OBS! This setup does not make much practical sense. It is only added to exercise the # `sedov_self_gravity` AMR indicator, which in its original configuration is too expensive for # CI testing @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_shockcapturing_amr.jl"), - l2 = [0.02217299067704248, 0.012771561294571411, 0.01277156129457143, 0.012770635779336643, 0.08091898488262424], - linf = [0.4047819603427084, 0.27493532130155474, 0.2749353213015551, 0.2749304638368023, 1.4053942765487641], - maxiters=10, - coverage_override = (maxiters=2,)) - end + l2=[ + 0.02217299067704248, + 0.012771561294571411, + 0.01277156129457143, + 0.012770635779336643, + 0.08091898488262424, + ], + linf=[ + 0.4047819603427084, + 0.27493532130155474, + 0.2749353213015551, + 0.2749304638368023, + 1.4053942765487641, + ], + maxiters=10, + coverage_override=(maxiters = 2,)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_density_pulse.jl" begin +@trixi_testset "elixir_euler_density_pulse.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_density_pulse.jl"), - l2 = [0.057196526814004715, 0.057196526814004715, 0.05719652681400473, 0.057196526814004736, 0.08579479022100575], - linf = [0.27415246703018203, 0.2741524670301829, 0.2741524670301827, 0.27415246703018226, 0.41122870054527816]) - end + l2=[ + 0.057196526814004715, + 0.057196526814004715, + 0.05719652681400473, + 0.057196526814004736, + 0.08579479022100575, + ], + linf=[ + 0.27415246703018203, + 0.2741524670301829, + 0.2741524670301827, + 0.27415246703018226, + 0.41122870054527816, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_ec.jl" begin +@trixi_testset "elixir_euler_ec.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_ec.jl"), - l2 = [0.02526341317987378, 0.016632068583699623, 0.016632068583699623, 0.01662548715216875, 0.0913477018048886], - linf = [0.4372549540810414, 0.28613118232798984, 0.28613118232799006, 0.28796686065271876, 1.5072828647309124]) - end + l2=[ + 0.02526341317987378, + 0.016632068583699623, + 0.016632068583699623, + 0.01662548715216875, + 0.0913477018048886, + ], + linf=[ + 0.4372549540810414, + 0.28613118232798984, + 0.28613118232799006, + 0.28796686065271876, + 1.5072828647309124, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_ec.jl with initial_condition=initial_condition_constant" begin +@trixi_testset "elixir_euler_ec.jl with initial_condition=initial_condition_constant" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_ec.jl"), - l2 = [4.183721551616214e-16, 6.059779958716338e-16, 4.916596221090319e-16, 9.739943366304456e-16, 3.7485908743251566e-15], - linf = [2.4424906541753444e-15, 3.733124920302089e-15, 4.440892098500626e-15, 5.329070518200751e-15, 2.4868995751603507e-14], - initial_condition=initial_condition_constant) - end + l2=[ + 4.183721551616214e-16, + 6.059779958716338e-16, + 4.916596221090319e-16, + 9.739943366304456e-16, + 3.7485908743251566e-15, + ], + linf=[ + 2.4424906541753444e-15, + 3.733124920302089e-15, + 4.440892098500626e-15, + 5.329070518200751e-15, + 2.4868995751603507e-14, + ], + initial_condition=initial_condition_constant) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_ec.jl with flux_chandrashekar" begin +@trixi_testset "elixir_euler_ec.jl with flux_chandrashekar" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_ec.jl"), - l2 = [0.025265721172813106, 0.016649800693500427, 0.01664980069350042, 0.01664379306708522, 0.09137248646784184], - linf = [0.4373399329742198, 0.28434487167605427, 0.28434487167605427, 0.28522678968890774, 1.532471676033761], - surface_flux=flux_chandrashekar, volume_flux=flux_chandrashekar) - end + l2=[ + 0.025265721172813106, + 0.016649800693500427, + 0.01664980069350042, + 0.01664379306708522, + 0.09137248646784184, + ], + linf=[ + 0.4373399329742198, + 0.28434487167605427, + 0.28434487167605427, + 0.28522678968890774, + 1.532471676033761, + ], + surface_flux=flux_chandrashekar, volume_flux=flux_chandrashekar) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_ec.jl with flux_kennedy_gruber" begin +@trixi_testset "elixir_euler_ec.jl with flux_kennedy_gruber" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_ec.jl"), - l2 = [0.025280033869871984, 0.016675487948639846, 0.016675487948639853, 0.016668992714991282, 0.091455613470441], - linf = [0.43348628145015766, 0.28853549062014217, 0.28853549062014217, 0.2903943042772536, 1.5236557526482426], - surface_flux=flux_kennedy_gruber, volume_flux=flux_kennedy_gruber) - end + l2=[ + 0.025280033869871984, + 0.016675487948639846, + 0.016675487948639853, + 0.016668992714991282, + 0.091455613470441, + ], + linf=[ + 0.43348628145015766, + 0.28853549062014217, + 0.28853549062014217, + 0.2903943042772536, + 1.5236557526482426, + ], + surface_flux=flux_kennedy_gruber, + volume_flux=flux_kennedy_gruber) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_ec.jl with flux_shima_etal" begin +@trixi_testset "elixir_euler_ec.jl with flux_shima_etal" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_ec.jl"), - l2 = [0.025261716925811403, 0.016637655557848952, 0.01663765555784895, 0.01663105921013437, 0.09136239054024566], - linf = [0.43692416928732536, 0.28622033209064734, 0.28622033209064746, 0.2881197143457632, 1.506534270303663], - surface_flux=flux_shima_etal, volume_flux=flux_shima_etal) - end + l2=[ + 0.025261716925811403, + 0.016637655557848952, + 0.01663765555784895, + 0.01663105921013437, + 0.09136239054024566, + ], + linf=[ + 0.43692416928732536, + 0.28622033209064734, + 0.28622033209064746, + 0.2881197143457632, + 1.506534270303663, + ], + surface_flux=flux_shima_etal, volume_flux=flux_shima_etal) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_blob_amr.jl" begin +@trixi_testset "elixir_euler_blob_amr.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_blob_amr.jl"), - l2 = [0.04867856452253151, 0.2640486962336911, 0.0354927658652858, 0.03549276586528571, 1.0777274757408568], - linf = [9.558543313792217, 49.4518309553356, 10.319859082570309, 10.319859082570487, 195.1066220797401], - tspan = (0.0, 0.2), - # Let this test run longer to cover some lines in the positivity preserving limiter - # and some AMR lines - coverage_override = (maxiters=10^5,)) - end - - @trixi_testset "elixir_euler_sedov_blast_wave.jl" begin + l2=[ + 0.04867856452253151, + 0.2640486962336911, + 0.0354927658652858, + 0.03549276586528571, + 1.0777274757408568, + ], + linf=[ + 9.558543313792217, + 49.4518309553356, + 10.319859082570309, + 10.319859082570487, + 195.1066220797401, + ], + tspan=(0.0, 0.2), + # Let this test run longer to cover some lines in the positivity preserving limiter + # and some AMR lines + coverage_override=(maxiters = 10^5,)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_sedov_blast_wave.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov_blast_wave.jl"), - l2 = [0.0007127163978031706, 0.0023166296394624025, 0.002316629639462401, 0.0023166296394624038, 0.010200581509653256], - linf = [0.06344190883105805, 0.6292607955969378, 0.6292607955969377, 0.6292607955969377, 2.397746252817731], - maxiters=5, max_level=6, - coverage_override = (maxiters=2, initial_refinement_level=1, base_level=1, max_level=3)) - end + l2=[ + 0.0007127163978031706, + 0.0023166296394624025, + 0.002316629639462401, + 0.0023166296394624038, + 0.010200581509653256, + ], + linf=[ + 0.06344190883105805, + 0.6292607955969378, + 0.6292607955969377, + 0.6292607955969377, + 2.397746252817731, + ], + maxiters=5, max_level=6, + coverage_override=(maxiters = 2, initial_refinement_level = 1, + base_level = 1, max_level = 3)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_euler_sedov_blast_wave.jl (HLLE)" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov_blast_wave.jl"), + l2=[ + 0.0007871241159752619, + 0.0037168004033428146, + 0.0037168004033428094, + 0.0037168004033428514, + 0.011119869089205635, + ], + linf=[ + 0.13982864363612468, + 0.786004687738243, + 0.786004687738243, + 0.7860046877382431, + 1.7082524045150382, + ], + tspan=(0.0, 0.01), + surface_flux=flux_hlle) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end end end # module diff --git a/test/test_tree_3d_eulergravity.jl b/test/test_tree_3d_eulergravity.jl index 635a06a718b..1b5e715f774 100644 --- a/test/test_tree_3d_eulergravity.jl +++ b/test/test_tree_3d_eulergravity.jl @@ -8,12 +8,34 @@ include("test_trixi.jl") EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_3d_dgsem") @testset "Compressible Euler with self-gravity" begin - @trixi_testset "elixir_eulergravity_convergence.jl" begin +#! format: noindent + +@trixi_testset "elixir_eulergravity_convergence.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_eulergravity_convergence.jl"), - l2 = [0.0004276779201667428, 0.00047204222332596204, 0.00047204222332608705, 0.0004720422233259819, 0.0010987026250960728], - linf = [0.003496616916238704, 0.003764418290373106, 0.003764418290377103, 0.0037644182903766588, 0.008370424899251105], - resid_tol = 1.0e-4, tspan = (0.0, 0.2)) - end + l2=[ + 0.0004276779201667428, + 0.00047204222332596204, + 0.00047204222332608705, + 0.0004720422233259819, + 0.0010987026250960728, + ], + linf=[ + 0.003496616916238704, + 0.003764418290373106, + 0.003764418290377103, + 0.0037644182903766588, + 0.008370424899251105, + ], + resid_tol=1.0e-4, tspan=(0.0, 0.2)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end end end # module diff --git a/test/test_tree_3d_fdsbp.jl b/test/test_tree_3d_fdsbp.jl index 106dd007b09..e0e2bfe4b88 100644 --- a/test/test_tree_3d_fdsbp.jl +++ b/test/test_tree_3d_fdsbp.jl @@ -8,72 +8,133 @@ include("test_trixi.jl") EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_3d_fdsbp") @testset "Linear scalar advection" begin - @trixi_testset "elixir_advection_extended.jl" begin +#! format: noindent + +@trixi_testset "elixir_advection_extended.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_extended.jl"), - l2 = [0.005355755365412444], - linf = [0.01856044696350767]) + l2=[0.005355755365412444], + linf=[0.01856044696350767]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 end - end +end - @trixi_testset "elixir_advection_extended.jl with periodic operators" begin +@trixi_testset "elixir_advection_extended.jl with periodic operators" begin + global D = SummationByPartsOperators.periodic_derivative_operator(derivative_order = 1, + accuracy_order = 4, + xmin = 0.0, + xmax = 1.0, + N = 10) @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_extended.jl"), - l2 = [1.3819894522373702e-8], - linf = [3.381866298113323e-8], - D_SBP = SummationByPartsOperators.periodic_derivative_operator( - derivative_order = 1, accuracy_order = 4, xmin = 0.0, xmax = 1.0, N = 10), - initial_refinement_level = 0, - tspan = (0.0, 5.0)) + l2=[5.228248923012878e-9], + linf=[9.24430243465224e-9], + D_SBP=D, + initial_refinement_level=0, + tspan=(0.0, 5.0)) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 end - end +end end @testset "Compressible Euler" begin - @trixi_testset "elixir_euler_convergence.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_convergence.jl"), - l2 = [2.247522803543667e-5, 2.2499169224681058e-5, 2.24991692246826e-5, 2.2499169224684707e-5, 5.814121361417382e-5], - linf = [9.579357410749445e-5, 9.544871933409027e-5, 9.54487193367548e-5, 9.544871933453436e-5, 0.0004192294529472562], - tspan = (0.0, 0.2)) + @trixi_testset "elixir_euler_convergence.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_convergence.jl"), + l2=[ + 2.247522803543667e-5, + 2.2499169224681058e-5, + 2.24991692246826e-5, + 2.2499169224684707e-5, + 5.814121361417382e-5, + ], + linf=[ + 9.579357410749445e-5, + 9.544871933409027e-5, + 9.54487193367548e-5, + 9.544871933453436e-5, + 0.0004192294529472562, + ], + tspan=(0.0, 0.2)) - # Ensure that we do not have excessive memory allocations - # (e.g., from type instabilities) - let - t = sol.t[end] - u_ode = sol.u[end] - du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end end - end - @trixi_testset "elixir_euler_convergence.jl with VolumeIntegralStrongForm" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_convergence.jl"), - l2 = [4.084919840272202e-5, 4.1320630860402814e-5, 4.132063086040211e-5, 4.132063086039092e-5, 8.502518355874354e-5], - linf = [0.0001963934848161486, 0.00020239883896255861, 0.0002023988389729947, 0.00020239883896766564, 0.00052605624510349], - tspan = (0.0, 0.2), - solver = DG(D_upw.central, nothing, SurfaceIntegralStrongForm(), VolumeIntegralStrongForm())) - end + @trixi_testset "elixir_euler_convergence.jl with VolumeIntegralStrongForm" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_convergence.jl"), + l2=[ + 4.084919840272202e-5, + 4.1320630860402814e-5, + 4.132063086040211e-5, + 4.132063086039092e-5, + 8.502518355874354e-5, + ], + linf=[ + 0.0001963934848161486, + 0.00020239883896255861, + 0.0002023988389729947, + 0.00020239883896766564, + 0.00052605624510349, + ], + tspan=(0.0, 0.2), + solver=DG(D_upw.central, nothing, SurfaceIntegralStrongForm(), + VolumeIntegralStrongForm())) + + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end + end - @trixi_testset "elixir_euler_taylor_green_vortex.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_taylor_green_vortex.jl"), - l2 = [3.529693407280806e-6, 0.0004691301922633193, 0.00046913019226332234, 0.0006630180220973541, 0.0015732759680929076], - linf = [3.4253965106145756e-5, 0.0010033197685090707, 0.0010033197685091054, 0.0018655642702542635, 0.008479800046757191], - tspan = (0.0, 0.0075), abstol = 1.0e-9, reltol = 1.0e-9) - end + @trixi_testset "elixir_euler_taylor_green_vortex.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_taylor_green_vortex.jl"), + l2=[ + 3.529693407280806e-6, + 0.0004691301922633193, + 0.00046913019226332234, + 0.0006630180220973541, + 0.0015732759680929076, + ], + linf=[ + 3.4253965106145756e-5, + 0.0010033197685090707, + 0.0010033197685091054, + 0.0018655642702542635, + 0.008479800046757191, + ], + tspan=(0.0, 0.0075), abstol=1.0e-9, reltol=1.0e-9) + + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end + end end end # module diff --git a/test/test_tree_3d_hypdiff.jl b/test/test_tree_3d_hypdiff.jl index 3db0ce93186..5c9dacbd87d 100644 --- a/test/test_tree_3d_hypdiff.jl +++ b/test/test_tree_3d_hypdiff.jl @@ -8,25 +8,81 @@ include("test_trixi.jl") EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_3d_dgsem") @testset "Hyperbolic diffusion" begin - @trixi_testset "elixir_hypdiff_lax_friedrichs.jl" begin +#! format: noindent + +@trixi_testset "elixir_hypdiff_lax_friedrichs.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_hypdiff_lax_friedrichs.jl"), - l2 = [0.001530331609036682, 0.011314177033289238, 0.011314177033289402, 0.011314177033289631], - linf = [0.02263459033909354, 0.10139777904683545, 0.10139777904683545, 0.10139777904683545], - initial_refinement_level=2) - end + l2=[ + 0.001530331609036682, + 0.011314177033289238, + 0.011314177033289402, + 0.011314177033289631, + ], + linf=[ + 0.02263459033909354, + 0.10139777904683545, + 0.10139777904683545, + 0.10139777904683545, + ], + initial_refinement_level=2) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 + end +end - @trixi_testset "elixir_hypdiff_lax_friedrichs.jl with surface_flux=flux_godunov)" begin +@trixi_testset "elixir_hypdiff_lax_friedrichs.jl with surface_flux=flux_godunov)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_hypdiff_lax_friedrichs.jl"), - l2 = [0.0015377731806850128, 0.01137685274151801, 0.011376852741518175, 0.011376852741518494], - linf = [0.022715420630041172, 0.10183745338964201, 0.10183745338964201, 0.1018374533896429], - initial_refinement_level=2, surface_flux=flux_godunov) - end + l2=[ + 0.0015377731806850128, + 0.01137685274151801, + 0.011376852741518175, + 0.011376852741518494, + ], + linf=[ + 0.022715420630041172, + 0.10183745338964201, + 0.10183745338964201, + 0.1018374533896429, + ], + initial_refinement_level=2, surface_flux=flux_godunov) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 + end +end - @trixi_testset "elixir_hypdiff_nonperiodic.jl" begin +@trixi_testset "elixir_hypdiff_nonperiodic.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_hypdiff_nonperiodic.jl"), - l2 = [0.00022868320512754316, 0.0007974309948540525, 0.0015035143230654987, 0.0015035143230655293], - linf = [0.0016405001653623241, 0.0029870057159104594, 0.009410031618285686, 0.009410031618287462]) - end + l2=[ + 0.00022868320512754316, + 0.0007974309948540525, + 0.0015035143230654987, + 0.0015035143230655293, + ], + linf=[ + 0.0016405001653623241, + 0.0029870057159104594, + 0.009410031618285686, + 0.009410031618287462, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 15000 + end +end end end # module diff --git a/test/test_tree_3d_lbm.jl b/test/test_tree_3d_lbm.jl index 0e92c5436af..dc7e770dfa4 100644 --- a/test/test_tree_3d_lbm.jl +++ b/test/test_tree_3d_lbm.jl @@ -8,52 +8,104 @@ include("test_trixi.jl") EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_3d_dgsem") @testset "Lattice-Boltzmann" begin - @trixi_testset "elixir_lbm_constant.jl" begin +#! format: noindent + +@trixi_testset "elixir_lbm_constant.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_lbm_constant.jl"), - l2 = [5.861930511199053e-16, 6.282772442363201e-16, 5.47591540767842e-16, - 6.379244339335046e-16, 5.81421258408584e-16, 6.634626069779352e-16, - 2.9188639102691596e-16, 2.1539168764807097e-16, 3.0131714783573674e-16, - 2.2126555191449657e-16, 2.622901122013102e-16, 2.2115776381362187e-16, - 6.32031843208421e-17, 6.103875364141341e-17, 6.821138567646266e-17, - 6.48022057541854e-17, 5.013642264182462e-17, 7.169498358338181e-17, - 1.3879946832660896e-16, 5.649850447603551e-17, 3.4686869828797276e-17, - 3.8719518141614167e-17, 3.5852179230919525e-17, 4.292415147083455e-17, - 3.608945206319316e-17, 4.187850903422495e-17, 8.254587760492495e-16], - linf = [1.1657341758564144e-15, 1.5543122344752192e-15, 1.1657341758564144e-15, - 1.4710455076283324e-15, 1.0547118733938987e-15, 1.4988010832439613e-15, - 5.273559366969494e-16, 5.065392549852277e-16, 5.967448757360216e-16, - 5.342948306008566e-16, 5.412337245047638e-16, 5.967448757360216e-16, - 3.608224830031759e-16, 3.469446951953614e-16, 2.42861286636753e-16, - 2.498001805406602e-16, 2.2898349882893854e-16, 4.3021142204224816e-16, - 2.1510571102112408e-16, 1.43982048506075e-16, 1.214306433183765e-16, - 1.4224732503009818e-16, 1.214306433183765e-16, 1.3877787807814457e-16, - 8.673617379884035e-17, 9.71445146547012e-17, 2.7755575615628914e-15], - tspan=(0.0, 0.5)) - end + l2=[5.861930511199053e-16, 6.282772442363201e-16, + 5.47591540767842e-16, + 6.379244339335046e-16, 5.81421258408584e-16, + 6.634626069779352e-16, + 2.9188639102691596e-16, 2.1539168764807097e-16, + 3.0131714783573674e-16, + 2.2126555191449657e-16, 2.622901122013102e-16, + 2.2115776381362187e-16, + 6.32031843208421e-17, 6.103875364141341e-17, + 6.821138567646266e-17, + 6.48022057541854e-17, 5.013642264182462e-17, + 7.169498358338181e-17, + 1.3879946832660896e-16, 5.649850447603551e-17, + 3.4686869828797276e-17, + 3.8719518141614167e-17, 3.5852179230919525e-17, + 4.292415147083455e-17, + 3.608945206319316e-17, 4.187850903422495e-17, + 8.254587760492495e-16], + linf=[1.1657341758564144e-15, 1.5543122344752192e-15, + 1.1657341758564144e-15, + 1.4710455076283324e-15, 1.0547118733938987e-15, + 1.4988010832439613e-15, + 5.273559366969494e-16, 5.065392549852277e-16, + 5.967448757360216e-16, + 5.342948306008566e-16, 5.412337245047638e-16, + 5.967448757360216e-16, + 3.608224830031759e-16, 3.469446951953614e-16, + 2.42861286636753e-16, + 2.498001805406602e-16, 2.2898349882893854e-16, + 4.3021142204224816e-16, + 2.1510571102112408e-16, 1.43982048506075e-16, + 1.214306433183765e-16, + 1.4224732503009818e-16, 1.214306433183765e-16, + 1.3877787807814457e-16, + 8.673617379884035e-17, 9.71445146547012e-17, + 2.7755575615628914e-15], + tspan=(0.0, 0.5)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_lbm_taylor_green_vortex.jl" begin +@trixi_testset "elixir_lbm_taylor_green_vortex.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_lbm_taylor_green_vortex.jl"), - l2 = [7.516128821554829e-5, 7.516128821554695e-5, 7.516128821554932e-5, - 7.516128821554856e-5, 7.022624942862394e-6, 7.022624942862171e-6, - 2.961794427142361e-6, 2.961794427142168e-6, 2.6527195181287848e-5, - 2.6527195181287404e-5, 2.652719518128811e-5, 2.6527195181287916e-5, - 2.9617944271423104e-6, 2.961794427142108e-6, 2.652719518128758e-5, - 2.6527195181287513e-5, 2.6527195181287916e-5, 2.6527195181287872e-5, - 6.697526775466e-6, 6.697526775466029e-6, 6.697526775465903e-6, 6.697526775465986e-6, - 6.697526775466051e-6, 6.697526775465938e-6, 6.697526775465983e-6, - 6.697526775466005e-6, 2.8805380887802028e-6], - linf = [0.00021570074723312183, 0.0002157007472331357, 0.00021570074723314958, - 0.00021570074723316346, 1.9675688146578163e-5, 1.967568814660592e-5, - 9.53539471547013e-6, 9.53539471547013e-6, 5.7339968249785905e-5, - 5.7339968249778966e-5, 5.7339968249792844e-5, 5.7339968249778966e-5, - 9.535394715480539e-6, 9.53539471546666e-6, 5.73399682497755e-5, 5.7339968249785905e-5, - 5.7339968249782436e-5, 5.7339968249782436e-5, 1.3570400471223966e-5, - 1.3570400471222231e-5, 1.3570400471220496e-5, 1.3570400471224833e-5, - 1.3570400471223966e-5, 1.3570400471221364e-5, 1.3570400471224833e-5, - 1.3570400471224833e-5, 1.4249297322244114e-5], - tspan=(0.0, 0.1), - initial_refinement_level=3) - end + l2=[7.516128821554829e-5, 7.516128821554695e-5, + 7.516128821554932e-5, + 7.516128821554856e-5, 7.022624942862394e-6, + 7.022624942862171e-6, + 2.961794427142361e-6, 2.961794427142168e-6, + 2.6527195181287848e-5, + 2.6527195181287404e-5, 2.652719518128811e-5, + 2.6527195181287916e-5, + 2.9617944271423104e-6, 2.961794427142108e-6, + 2.652719518128758e-5, + 2.6527195181287513e-5, 2.6527195181287916e-5, + 2.6527195181287872e-5, + 6.697526775466e-6, 6.697526775466029e-6, + 6.697526775465903e-6, 6.697526775465986e-6, + 6.697526775466051e-6, 6.697526775465938e-6, + 6.697526775465983e-6, + 6.697526775466005e-6, 2.8805380887802028e-6], + linf=[0.00021570074723312183, 0.0002157007472331357, + 0.00021570074723314958, + 0.00021570074723316346, 1.9675688146578163e-5, + 1.967568814660592e-5, + 9.53539471547013e-6, 9.53539471547013e-6, + 5.7339968249785905e-5, + 5.7339968249778966e-5, 5.7339968249792844e-5, + 5.7339968249778966e-5, + 9.535394715480539e-6, 9.53539471546666e-6, + 5.73399682497755e-5, 5.7339968249785905e-5, + 5.7339968249782436e-5, 5.7339968249782436e-5, + 1.3570400471223966e-5, + 1.3570400471222231e-5, 1.3570400471220496e-5, + 1.3570400471224833e-5, + 1.3570400471223966e-5, 1.3570400471221364e-5, + 1.3570400471224833e-5, + 1.3570400471224833e-5, 1.4249297322244114e-5], + tspan=(0.0, 0.1), + initial_refinement_level=3) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end end end # module diff --git a/test/test_tree_3d_mhd.jl b/test/test_tree_3d_mhd.jl index a06d721b525..e75685f0b43 100644 --- a/test/test_tree_3d_mhd.jl +++ b/test/test_tree_3d_mhd.jl @@ -8,79 +8,289 @@ include("test_trixi.jl") EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_3d_dgsem") @testset "MHD" begin - @trixi_testset "elixir_mhd_ec.jl" begin +#! format: noindent + +@trixi_testset "elixir_mhd_ec.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_ec.jl"), - l2 = [0.017590099293094203, 0.017695875823827714, 0.017695875823827686, 0.017698038279620777, 0.07495006099352074, 0.010391801950005755, 0.010391801950005759, 0.010393502246627087, 2.524766553484067e-16], - linf = [0.28173002819718196, 0.3297583616136297, 0.32975836161363004, 0.356862935505337, 1.2893514981209626, 0.10950981489747313, 0.10950981489747136, 0.11517234329681891, 2.0816911067714202e-15]) - end + l2=[ + 0.017590099293094203, + 0.017695875823827714, + 0.017695875823827686, + 0.017698038279620777, + 0.07495006099352074, + 0.010391801950005755, + 0.010391801950005759, + 0.010393502246627087, + 2.524766553484067e-16, + ], + linf=[ + 0.28173002819718196, + 0.3297583616136297, + 0.32975836161363004, + 0.356862935505337, + 1.2893514981209626, + 0.10950981489747313, + 0.10950981489747136, + 0.11517234329681891, + 2.0816911067714202e-15, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_mhd_ec.jl with initial_condition=initial_condition_constant" begin +@trixi_testset "elixir_mhd_ec.jl with initial_condition=initial_condition_constant" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_ec.jl"), - l2 = [4.270231310667203e-16, 2.4381208042014784e-15, 5.345107673575357e-15, 3.00313882171883e-15, 1.7772703118758417e-14, 1.0340110783830874e-15, 1.1779095371939702e-15, 9.961878521814573e-16, 8.1201730630719145e-16], - linf = [2.4424906541753444e-15, 2.881028748902281e-14, 2.4646951146678475e-14, 2.3092638912203256e-14, 2.3447910280083306e-13, 1.7763568394002505e-14, 1.0436096431476471e-14, 2.042810365310288e-14, 7.057203733035201e-15], - atol = 1000*eps(), - initial_condition=initial_condition_constant) - end + l2=[ + 4.270231310667203e-16, + 2.4381208042014784e-15, + 5.345107673575357e-15, + 3.00313882171883e-15, + 1.7772703118758417e-14, + 1.0340110783830874e-15, + 1.1779095371939702e-15, + 9.961878521814573e-16, + 8.1201730630719145e-16, + ], + linf=[ + 2.4424906541753444e-15, + 2.881028748902281e-14, + 2.4646951146678475e-14, + 2.3092638912203256e-14, + 2.3447910280083306e-13, + 1.7763568394002505e-14, + 1.0436096431476471e-14, + 2.042810365310288e-14, + 7.057203733035201e-15, + ], + atol=1000 * eps(), + initial_condition=initial_condition_constant) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_mhd_alfven_wave.jl" begin +@trixi_testset "elixir_mhd_alfven_wave.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_alfven_wave.jl"), - l2 = [0.0032217291057246157, 0.009511644936958913, 0.004217358459420256, 0.011591709179125335, 0.009456218722393708, 0.00916500047763897, 0.005069863732625444, 0.011503011541926135, 0.003988175543749985], - linf = [0.01188593784273051, 0.03638015998373141, 0.01568200398945724, 0.04666974730787579, 0.031235294705421968, 0.03316343064943483, 0.011539436992528018, 0.04896687646520839, 0.018714054039927555]) - end + l2=[ + 0.0032217291057246157, + 0.009511644936958913, + 0.004217358459420256, + 0.011591709179125335, + 0.009456218722393708, + 0.00916500047763897, + 0.005069863732625444, + 0.011503011541926135, + 0.003988175543749985, + ], + linf=[ + 0.01188593784273051, + 0.03638015998373141, + 0.01568200398945724, + 0.04666974730787579, + 0.031235294705421968, + 0.03316343064943483, + 0.011539436992528018, + 0.04896687646520839, + 0.018714054039927555, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_mhd_alfven_wave.jl with flux_derigs_etal" begin +@trixi_testset "elixir_mhd_alfven_wave.jl with flux_derigs_etal" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_alfven_wave.jl"), - l2 = [0.003755235939722358, 0.009062519246840721, 0.004096299856228109, 0.011429935838448906, 0.006897420817511043, 0.00900886245212482, 0.004926537542780259, 0.01153285554590683, 0.0037842060148666886], - linf = [0.012982853115883541, 0.0320228076558316, 0.011575276754611022, 0.04425778643430531, 0.02478109022285846, 0.03198699034954189, 0.009761077061886558, 0.04433669321441455, 0.01618905441148782], - volume_flux = (flux_derigs_etal, flux_nonconservative_powell)) - end + l2=[ + 0.003755235939722358, + 0.009062519246840721, + 0.004096299856228109, + 0.011429935838448906, + 0.006897420817511043, + 0.00900886245212482, + 0.004926537542780259, + 0.01153285554590683, + 0.0037842060148666886, + ], + linf=[ + 0.012982853115883541, + 0.0320228076558316, + 0.011575276754611022, + 0.04425778643430531, + 0.02478109022285846, + 0.03198699034954189, + 0.009761077061886558, + 0.04433669321441455, + 0.01618905441148782, + ], + volume_flux=(flux_derigs_etal, flux_nonconservative_powell)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_mhd_alfven_wave_mortar.jl" begin +@trixi_testset "elixir_mhd_alfven_wave_mortar.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_alfven_wave_mortar.jl"), - l2 = [0.001879021634926363, 0.007032724521848316, 0.0032793932234187325, 0.009056594733320348, 0.007514150120617965, 0.007328739509868727, 0.00309794018112387, 0.009026356949274878, 0.0035732583778049776], - linf = [0.013734346970999622, 0.06173467158736011, 0.02183946452704291, 0.06258216169457917, 0.03672304497348122, 0.055120532123884625, 0.018202716205672487, 0.06133688282205586, 0.019888161885935608], - tspan = (0.0, 0.25)) - end + l2=[ + 0.001879021634926363, + 0.007032724521848316, + 0.0032793932234187325, + 0.009056594733320348, + 0.007514150120617965, + 0.007328739509868727, + 0.00309794018112387, + 0.009026356949274878, + 0.0035732583778049776, + ], + linf=[ + 0.013734346970999622, + 0.06173467158736011, + 0.02183946452704291, + 0.06258216169457917, + 0.03672304497348122, + 0.055120532123884625, + 0.018202716205672487, + 0.06133688282205586, + 0.019888161885935608, + ], + tspan=(0.0, 0.25)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_mhd_alfven_wave.jl with Orszag-Tang setup + flux_hll" begin +@trixi_testset "elixir_mhd_alfven_wave.jl with Orszag-Tang setup + flux_hll" begin # OBS! This setup does not make much sense and is only used to exercise all components of the # flux_hll implementation @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_alfven_wave.jl"), - l2 = [0.004391143689111404, 0.04144737547475548, 0.041501307637678286, 0.04150353006408862, 0.03693135855995625, 0.021125605214031118, 0.03295607553556973, 0.03296235755245784, 7.16035229384135e-6], - linf = [0.017894703320895378, 0.08486850681397005, 0.0891044523165206, 0.08492024792056754, 0.10448301878352373, 0.05381260695579509, 0.0884774018719996, 0.07784546966765199, 7.71609149516089e-5], - initial_condition = function initial_condition_orszag_tang(x, t, equations::IdealGlmMhdEquations3D) - # The classical Orszag-Tang vortex test case adapted to 3D. Setup is taken from - # Table 4 of the paper - # - M. Bohm, A. R. Winters, G. J. Gassner, D. Derigs, F. Hindenlang, & J. Saur (2020) - # 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](https://doi.org/10.1016/j.jcp.2018.06.027) - # Domain must be [0, 1]^3 , γ = 5/3 - rho = 25.0 / (36.0 * pi) - v1 = -sin(2.0*pi*x[3]) - v2 = sin(2.0*pi*x[1]) - v3 = sin(2.0*pi*x[2]) - p = 5.0 / (12.0 * pi) - B1 = -sin(2.0*pi*x[3]) / (4.0*pi) - B2 = sin(4.0*pi*x[1]) / (4.0*pi) - B3 = sin(4.0*pi*x[2]) / (4.0*pi) - psi = 0.0 - return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3, psi), equations) - end, - surface_flux = (flux_hll, flux_nonconservative_powell), - volume_flux = (flux_central, flux_nonconservative_powell), - coordinates_min = (0.0, 0.0, 0.0), - coordinates_max = (1.0, 1.0, 1.0), - initial_refinement_level=3, - cfl = 1.1, - tspan = (0.0, 0.06)) - end + l2=[ + 0.004391143689111404, + 0.04144737547475548, + 0.041501307637678286, + 0.04150353006408862, + 0.03693135855995625, + 0.021125605214031118, + 0.03295607553556973, + 0.03296235755245784, + 7.16035229384135e-6, + ], + linf=[ + 0.017894703320895378, + 0.08486850681397005, + 0.0891044523165206, + 0.08492024792056754, + 0.10448301878352373, + 0.05381260695579509, + 0.0884774018719996, + 0.07784546966765199, + 7.71609149516089e-5, + ], + initial_condition=function initial_condition_orszag_tang(x, t, + equations::IdealGlmMhdEquations3D) + # The classical Orszag-Tang vortex test case adapted to 3D. Setup is taken from + # Table 4 of the paper + # - M. Bohm, A. R. Winters, G. J. Gassner, D. Derigs, F. Hindenlang, & J. Saur (2020) + # 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](https://doi.org/10.1016/j.jcp.2018.06.027) + # Domain must be [0, 1]^3 , γ = 5/3 + rho = 25.0 / (36.0 * pi) + v1 = -sin(2.0 * pi * x[3]) + v2 = sin(2.0 * pi * x[1]) + v3 = sin(2.0 * pi * x[2]) + p = 5.0 / (12.0 * pi) + B1 = -sin(2.0 * pi * x[3]) / (4.0 * pi) + B2 = sin(4.0 * pi * x[1]) / (4.0 * pi) + B3 = sin(4.0 * pi * x[2]) / (4.0 * pi) + psi = 0.0 + return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3, + psi), equations) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < + 1000 + end + end, + surface_flux=(flux_hlle, + flux_nonconservative_powell), + volume_flux=(flux_central, flux_nonconservative_powell), + coordinates_min=(0.0, 0.0, 0.0), + coordinates_max=(1.0, 1.0, 1.0), + initial_refinement_level=3, + cfl=1.1, + tspan=(0.0, 0.06)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_mhd_ec_shockcapturing.jl" begin +@trixi_testset "elixir_mhd_ec_shockcapturing.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_ec_shockcapturing.jl"), - l2 = [0.0186712969755079, 0.01620736832264799, 0.01620736832264803, 0.016207474382769683, 0.07306422729650594, 0.007355137041002365, 0.0073551370410023425, 0.00735520932001833, 0.000506140942330923], - linf = [0.28040713666979633, 0.27212885844703694, 0.2721288584470349, 0.2837380205051839, 0.7915852408267114, 0.08770240288089526, 0.08770240288089792, 0.08773409387876674, 0.050221095224119834]) - end + l2=[ + 0.0186712969755079, + 0.01620736832264799, + 0.01620736832264803, + 0.016207474382769683, + 0.07306422729650594, + 0.007355137041002365, + 0.0073551370410023425, + 0.00735520932001833, + 0.000506140942330923, + ], + linf=[ + 0.28040713666979633, + 0.27212885844703694, + 0.2721288584470349, + 0.2837380205051839, + 0.7915852408267114, + 0.08770240288089526, + 0.08770240288089792, + 0.08773409387876674, + 0.050221095224119834, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end end end # module diff --git a/test/test_tree_3d_part1.jl b/test/test_tree_3d_part1.jl index b1bf313d1b6..3fdddc77239 100644 --- a/test/test_tree_3d_part1.jl +++ b/test/test_tree_3d_part1.jl @@ -7,20 +7,19 @@ include("test_trixi.jl") # Start with a clean environment: remove Trixi.jl output directory if it exists outdir = "out" -isdir(outdir) && rm(outdir, recursive=true) +isdir(outdir) && rm(outdir, recursive = true) @testset "TreeMesh3D Part 1" begin +#! format: noindent # Run basic tests @testset "Examples 3D" begin - # Compressible Euler - include("test_tree_3d_euler.jl") + # Compressible Euler + include("test_tree_3d_euler.jl") end - # Clean up afterwards: delete Trixi.jl output directory -@test_nowarn rm(outdir, recursive=true) - +@test_nowarn rm(outdir, recursive = true) end # TreeMesh3D Part 1 end #module diff --git a/test/test_tree_3d_part2.jl b/test/test_tree_3d_part2.jl index 77af51c7481..5c7301654ad 100644 --- a/test/test_tree_3d_part2.jl +++ b/test/test_tree_3d_part2.jl @@ -7,102 +7,113 @@ include("test_trixi.jl") # Start with a clean environment: remove Trixi.jl output directory if it exists outdir = "out" -isdir(outdir) && rm(outdir, recursive=true) +isdir(outdir) && rm(outdir, recursive = true) @testset "TreeMesh3D Part 2" begin +#! format: noindent # Run basic tests @testset "Examples 3D" begin - # Linear scalar advection - include("test_tree_3d_advection.jl") + # Linear scalar advection + include("test_tree_3d_advection.jl") - # Hyperbolic diffusion - include("test_tree_3d_hypdiff.jl") + # Hyperbolic diffusion + include("test_tree_3d_hypdiff.jl") - # Compressible Euler with self-gravity - include("test_tree_3d_eulergravity.jl") + # Compressible Euler with self-gravity + include("test_tree_3d_eulergravity.jl") end - @trixi_testset "Additional tests in 3D" begin - @trixi_testset "compressible Euler" begin - eqn = CompressibleEulerEquations3D(1.4) - - @test isapprox(energy_total([1.0, 2.0, 3.0, 4.0, 20.0], eqn), 20.0) - @test isapprox(energy_kinetic([1.0, 2.0, 3.0, 4.0, 20], eqn), 14.5) - @test isapprox(energy_internal([1.0, 2.0, 3.0, 4.0, 20], eqn), 5.5) - end - - @trixi_testset "hyperbolic diffusion" begin - @test_nowarn HyperbolicDiffusionEquations3D(nu=1.0) - eqn = HyperbolicDiffusionEquations3D(nu=1.0) - end + @trixi_testset "compressible Euler" begin + eqn = CompressibleEulerEquations3D(1.4) + + @test isapprox(energy_total([1.0, 2.0, 3.0, 4.0, 20.0], eqn), 20.0) + @test isapprox(energy_kinetic([1.0, 2.0, 3.0, 4.0, 20], eqn), 14.5) + @test isapprox(energy_internal([1.0, 2.0, 3.0, 4.0, 20], eqn), 5.5) + end + + @trixi_testset "hyperbolic diffusion" begin + @test_nowarn HyperbolicDiffusionEquations3D(nu = 1.0) + eqn = HyperbolicDiffusionEquations3D(nu = 1.0) + end end - @trixi_testset "Displaying components 3D" begin - @test_nowarn include(joinpath(examples_dir(), "tree_3d_dgsem", "elixir_advection_amr.jl")) - - # test both short and long printing formats - @test_nowarn show(mesh); println() - @test_nowarn println(mesh) - @test_nowarn display(mesh) - - @test_nowarn show(equations); println() - @test_nowarn println(equations) - @test_nowarn display(equations) - - @test_nowarn show(solver); println() - @test_nowarn println(solver) - @test_nowarn display(solver) - - @test_nowarn show(solver.basis); println() - @test_nowarn println(solver.basis) - @test_nowarn display(solver.basis) - - @test_nowarn show(solver.mortar); println() - @test_nowarn println(solver.mortar) - @test_nowarn display(solver.mortar) - - @test_nowarn show(semi); println() - @test_nowarn println(semi) - @test_nowarn display(semi) - - @test_nowarn show(summary_callback); println() - @test_nowarn println(summary_callback) - @test_nowarn display(summary_callback) - - @test_nowarn show(amr_controller); println() - @test_nowarn println(amr_controller) - @test_nowarn display(amr_controller) - - @test_nowarn show(amr_callback); println() - @test_nowarn println(amr_callback) - @test_nowarn display(amr_callback) - - @test_nowarn show(stepsize_callback); println() - @test_nowarn println(stepsize_callback) - @test_nowarn display(stepsize_callback) - - @test_nowarn show(save_solution); println() - @test_nowarn println(save_solution) - @test_nowarn display(save_solution) - - @test_nowarn show(analysis_callback); println() - @test_nowarn println(analysis_callback) - @test_nowarn display(analysis_callback) - - @test_nowarn show(alive_callback); println() - @test_nowarn println(alive_callback) - @test_nowarn display(alive_callback) - - @test_nowarn println(callbacks) + @test_nowarn include(joinpath(examples_dir(), "tree_3d_dgsem", + "elixir_advection_amr.jl")) + + # test both short and long printing formats + @test_nowarn show(mesh) + println() + @test_nowarn println(mesh) + @test_nowarn display(mesh) + + @test_nowarn show(equations) + println() + @test_nowarn println(equations) + @test_nowarn display(equations) + + @test_nowarn show(solver) + println() + @test_nowarn println(solver) + @test_nowarn display(solver) + + @test_nowarn show(solver.basis) + println() + @test_nowarn println(solver.basis) + @test_nowarn display(solver.basis) + + @test_nowarn show(solver.mortar) + println() + @test_nowarn println(solver.mortar) + @test_nowarn display(solver.mortar) + + @test_nowarn show(semi) + println() + @test_nowarn println(semi) + @test_nowarn display(semi) + + @test_nowarn show(summary_callback) + println() + @test_nowarn println(summary_callback) + @test_nowarn display(summary_callback) + + @test_nowarn show(amr_controller) + println() + @test_nowarn println(amr_controller) + @test_nowarn display(amr_controller) + + @test_nowarn show(amr_callback) + println() + @test_nowarn println(amr_callback) + @test_nowarn display(amr_callback) + + @test_nowarn show(stepsize_callback) + println() + @test_nowarn println(stepsize_callback) + @test_nowarn display(stepsize_callback) + + @test_nowarn show(save_solution) + println() + @test_nowarn println(save_solution) + @test_nowarn display(save_solution) + + @test_nowarn show(analysis_callback) + println() + @test_nowarn println(analysis_callback) + @test_nowarn display(analysis_callback) + + @test_nowarn show(alive_callback) + println() + @test_nowarn println(alive_callback) + @test_nowarn display(alive_callback) + + @test_nowarn println(callbacks) end - # Clean up afterwards: delete Trixi.jl output directory -@test_nowarn rm(outdir, recursive=true) - +@test_nowarn rm(outdir, recursive = true) end # TreeMesh3D Part 2 end #module diff --git a/test/test_tree_3d_part3.jl b/test/test_tree_3d_part3.jl index 7a77f0e4927..9e1e8bc4dc9 100644 --- a/test/test_tree_3d_part3.jl +++ b/test/test_tree_3d_part3.jl @@ -7,49 +7,47 @@ include("test_trixi.jl") # Start with a clean environment: remove Trixi.jl output directory if it exists outdir = "out" -isdir(outdir) && rm(outdir, recursive=true) +isdir(outdir) && rm(outdir, recursive = true) @testset "TreeMesh3D Part 2" begin +#! format: noindent # Run basic tests @testset "Examples 3D" begin - # MHD - include("test_tree_3d_mhd.jl") + # MHD + include("test_tree_3d_mhd.jl") - # Lattice-Boltzmann - include("test_tree_3d_lbm.jl") + # Lattice-Boltzmann + include("test_tree_3d_lbm.jl") - # FDSBP methods on the TreeMesh - include("test_tree_3d_fdsbp.jl") + # FDSBP methods on the TreeMesh + include("test_tree_3d_fdsbp.jl") end - @trixi_testset "Additional tests in 3D" begin - @testset "ideal GLM MHD" begin - eqn = IdealGlmMhdEquations3D(1.4) - u = [1.0, 2.0, 3.0, 4.0, 20.0, 0.1, 0.2, 0.3, 1.5] + @testset "ideal GLM MHD" begin + eqn = IdealGlmMhdEquations3D(1.4) + u = [1.0, 2.0, 3.0, 4.0, 20.0, 0.1, 0.2, 0.3, 1.5] - @test isapprox(density(u, eqn), 1.0) - @test isapprox(pressure(u, eqn), 1.7219999999999995) - @test isapprox(density_pressure(u, eqn), 1.7219999999999995) + @test isapprox(density(u, eqn), 1.0) + @test isapprox(pressure(u, eqn), 1.7219999999999995) + @test isapprox(density_pressure(u, eqn), 1.7219999999999995) - @test isapprox(Trixi.entropy_thermodynamic(u, eqn), 0.5434864060055388) - @test isapprox(Trixi.entropy_math(u, eqn), -1.3587160150138473) - @test isapprox(Trixi.entropy(u, eqn), -1.3587160150138473) + @test isapprox(Trixi.entropy_thermodynamic(u, eqn), 0.5434864060055388) + @test isapprox(Trixi.entropy_math(u, eqn), -1.3587160150138473) + @test isapprox(Trixi.entropy(u, eqn), -1.3587160150138473) - @test isapprox(energy_total(u, eqn), 20.0) - @test isapprox(energy_kinetic(u, eqn), 14.5) - @test isapprox(energy_magnetic(u, eqn), 0.07) - @test isapprox(energy_internal(u, eqn), 4.305) + @test isapprox(energy_total(u, eqn), 20.0) + @test isapprox(energy_kinetic(u, eqn), 14.5) + @test isapprox(energy_magnetic(u, eqn), 0.07) + @test isapprox(energy_internal(u, eqn), 4.305) - @test isapprox(cross_helicity(u, eqn), 2.0) - end + @test isapprox(cross_helicity(u, eqn), 2.0) + end end - # Clean up afterwards: delete Trixi.jl output directory -@test_nowarn rm(outdir, recursive=true) - +@test_nowarn rm(outdir, recursive = true) end # TreeMesh3D Part 2 end #module diff --git a/test/test_trixi.jl b/test/test_trixi.jl index ddace6b4fbe..cebe2164ae6 100644 --- a/test/test_trixi.jl +++ b/test/test_trixi.jl @@ -5,7 +5,7 @@ import Trixi # inside an elixir. """ @test_trixi_include(elixir; l2=nothing, linf=nothing, - atol=10*eps(), rtol=0.001, + atol=500*eps(), rtol=sqrt(eps()), parameters...) Test Trixi by calling `trixi_include(elixir; parameters...)`. @@ -15,165 +15,162 @@ are compared approximately against these reference values, using `atol, rtol` as absolute/relative tolerance. """ macro test_trixi_include(elixir, args...) - - local l2 = get_kwarg(args, :l2, nothing) - local linf = get_kwarg(args, :linf, nothing) - local atol = get_kwarg(args, :atol, 500*eps()) - local rtol = get_kwarg(args, :rtol, sqrt(eps())) - local skip_coverage = get_kwarg(args, :skip_coverage, false) - local coverage_override = expr_to_named_tuple(get_kwarg(args, :coverage_override, :())) - if !(:maxiters in keys(coverage_override)) - # maxiters in coverage_override defaults to 1 - coverage_override = (; coverage_override..., maxiters=1) - end - - local cmd = string(Base.julia_cmd()) - local coverage = occursin("--code-coverage", cmd) && !occursin("--code-coverage=none", cmd) - - local kwargs = Pair{Symbol, Any}[] - for arg in args - if (arg.head == :(=) && !(arg.args[1] in (:l2, :linf, :atol, :rtol, :coverage_override)) - && !(coverage && arg.args[1] in keys(coverage_override))) - push!(kwargs, Pair(arg.args...)) + local l2 = get_kwarg(args, :l2, nothing) + local linf = get_kwarg(args, :linf, nothing) + local atol = get_kwarg(args, :atol, 500 * eps()) + local rtol = get_kwarg(args, :rtol, sqrt(eps())) + local skip_coverage = get_kwarg(args, :skip_coverage, false) + local coverage_override = expr_to_named_tuple(get_kwarg(args, :coverage_override, :())) + if !(:maxiters in keys(coverage_override)) + # maxiters in coverage_override defaults to 1 + coverage_override = (; coverage_override..., maxiters = 1) end - end - if coverage - for key in keys(coverage_override) - push!(kwargs, Pair(key, coverage_override[key])) - end - end - - if coverage && skip_coverage - return quote - if Trixi.mpi_isroot() - println("═"^100) - println("Skipping coverage test of ", $elixir) - println("═"^100) - println("\n\n") - end - end - end - - quote - Trixi.mpi_isroot() && println("═"^100) - Trixi.mpi_isroot() && println($elixir) - - # if `maxiters` is set in tests, it is usually set to a small number to - # run only a few steps - ignore possible warnings coming from that - if any(==(:maxiters) ∘ first, $kwargs) - additional_ignore_content = [ - r"┌ Warning: Interrupted\. Larger maxiters is needed\..*\n└ @ SciMLBase .+\n", - r"┌ Warning: Interrupted\. Larger maxiters is needed\..*\n└ @ Trixi .+\n"] - else - additional_ignore_content = [] + local cmd = string(Base.julia_cmd()) + local coverage = occursin("--code-coverage", cmd) && + !occursin("--code-coverage=none", cmd) + + local kwargs = Pair{Symbol, Any}[] + for arg in args + if (arg.head == :(=) && + !(arg.args[1] in (:l2, :linf, :atol, :rtol, :coverage_override, :skip_coverage)) + && !(coverage && arg.args[1] in keys(coverage_override))) + push!(kwargs, Pair(arg.args...)) + end end - # evaluate examples in the scope of the module they're called from - @test_nowarn_mod trixi_include(@__MODULE__, $elixir; $kwargs...) additional_ignore_content + if coverage + for key in keys(coverage_override) + push!(kwargs, Pair(key, coverage_override[key])) + end + end - # if present, compare l2 and linf errors against reference values - if !$coverage && (!isnothing($l2) || !isnothing($linf)) - l2_measured, linf_measured = analysis_callback(sol) + if coverage && skip_coverage + return quote + if Trixi.mpi_isroot() + println("═"^100) + println("Skipping coverage test of ", $elixir) + println("═"^100) + println("\n\n") + end + end + end - if Trixi.mpi_isroot() && !isnothing($l2) - @test length($l2) == length(l2_measured) - for (l2_expected, l2_actual) in zip($l2, l2_measured) - @test isapprox(l2_expected, l2_actual, atol=$atol, rtol=$rtol) + quote + Trixi.mpi_isroot() && println("═"^100) + Trixi.mpi_isroot() && println($elixir) + + # if `maxiters` is set in tests, it is usually set to a small number to + # run only a few steps - ignore possible warnings coming from that + if any(==(:maxiters) ∘ first, $kwargs) + additional_ignore_content = [ + r"┌ Warning: Interrupted\. Larger maxiters is needed\..*\n└ @ SciMLBase .+\n", + r"┌ Warning: Interrupted\. Larger maxiters is needed\..*\n└ @ Trixi .+\n"] + else + additional_ignore_content = [] end - end - if Trixi.mpi_isroot() && !isnothing($linf) - @test length($linf) == length(linf_measured) - for (linf_expected, linf_actual) in zip($linf, linf_measured) - @test isapprox(linf_expected, linf_actual, atol=$atol, rtol=$rtol) + # evaluate examples in the scope of the module they're called from + @test_nowarn_mod trixi_include(@__MODULE__, $elixir; $kwargs...) additional_ignore_content + + # if present, compare l2 and linf errors against reference values + if !$coverage && (!isnothing($l2) || !isnothing($linf)) + l2_measured, linf_measured = analysis_callback(sol) + + if Trixi.mpi_isroot() && !isnothing($l2) + @test length($l2) == length(l2_measured) + for (l2_expected, l2_actual) in zip($l2, l2_measured) + @test isapprox(l2_expected, l2_actual, atol = $atol, rtol = $rtol) + end + end + + if Trixi.mpi_isroot() && !isnothing($linf) + @test length($linf) == length(linf_measured) + for (linf_expected, linf_actual) in zip($linf, linf_measured) + @test isapprox(linf_expected, linf_actual, atol = $atol, rtol = $rtol) + end + end end - end - end - Trixi.mpi_isroot() && println("═"^100) - Trixi.mpi_isroot() && println("\n\n") - end + Trixi.mpi_isroot() && println("═"^100) + Trixi.mpi_isroot() && println("\n\n") + end end - # Get the first value assigned to `keyword` in `args` and return `default_value` # if there are no assignments to `keyword` in `args`. function get_kwarg(args, keyword, default_value) - val = default_value - for arg in args - if arg.head == :(=) && arg.args[1] == keyword - val = arg.args[2] - break + val = default_value + for arg in args + if arg.head == :(=) && arg.args[1] == keyword + val = arg.args[2] + break + end end - end - return val + return val end function expr_to_named_tuple(expr) - result = (;) + result = (;) - for arg in expr.args - if arg.head != :(=) - error("Invalid expression") + for arg in expr.args + if arg.head != :(=) + error("Invalid expression") + end + result = (; result..., arg.args[1] => arg.args[2]) end - result = (; result..., arg.args[1] => arg.args[2]) - end - return result + return result end - # Modified version of `@test_nowarn` that prints the content of `stderr` when # it is not empty and ignores module replacements. -macro test_nowarn_mod(expr, additional_ignore_content=String[]) - quote - let fname = tempname() - try - ret = open(fname, "w") do f - redirect_stderr(f) do - $(esc(expr)) - end +macro test_nowarn_mod(expr, additional_ignore_content = String[]) + quote + let fname = tempname() + try + ret = open(fname, "w") do f + redirect_stderr(f) do + $(esc(expr)) + end + end + stderr_content = read(fname, String) + if !isempty(stderr_content) + println("Content of `stderr`:\n", stderr_content) + end + + # Patterns matching the following ones will be ignored. Additional patterns + # passed as arguments can also be regular expressions, so we just use the + # type `Any` for `ignore_content`. + ignore_content = Any[ + # We need to ignore steady state information reported by our callbacks + r"┌ Info: Steady state tolerance reached\n│ steady_state_callback .+\n└ t = .+\n", + # We also ignore our own compilation messages + "[ Info: You just called `trixi_include`. Julia may now compile the code, please be patient.\n", + # TODO: Upstream (PlotUtils). This should be removed again once the + # deprecated stuff is fixed upstream. + "WARNING: importing deprecated binding Colors.RGB1 into Plots.\n", + "WARNING: importing deprecated binding Colors.RGB4 into Plots.\n", + r"┌ Warning: Keyword argument letter not supported with Plots.+\n└ @ Plots.+\n", + r"┌ Warning: `parse\(::Type, ::Coloarant\)` is deprecated.+\n│.+\n│.+\n└ @ Plots.+\n", + # TODO: Silence warning introduced by Flux v0.13.13. Should be properly fixed. + r"┌ Warning: Layer with Float32 parameters got Float64 input.+\n│.+\n│.+\n│.+\n└ @ Flux.+\n"] + append!(ignore_content, $additional_ignore_content) + for pattern in ignore_content + stderr_content = replace(stderr_content, pattern => "") + end + + # We also ignore simple module redefinitions for convenience. Thus, we + # check whether every line of `stderr_content` is of the form of a + # module replacement warning. + @test occursin(r"^(WARNING: replacing module .+\.\n)*$", stderr_content) + ret + finally + rm(fname, force = true) + end end - stderr_content = read(fname, String) - if !isempty(stderr_content) - println("Content of `stderr`:\n", stderr_content) - end - - # Patterns matching the following ones will be ignored. Additional patterns - # passed as arguments can also be regular expressions, so we just use the - # type `Any` for `ignore_content`. - ignore_content = Any[ - # We need to ignore steady state information reported by our callbacks - r"┌ Info: Steady state tolerance reached\n│ steady_state_callback .+\n└ t = .+\n", - # We also ignore our own compilation messages - "[ Info: You just called `trixi_include`. Julia may now compile the code, please be patient.\n", - # TODO: Upstream (PlotUtils). This should be removed again once the - # deprecated stuff is fixed upstream. - "WARNING: importing deprecated binding Colors.RGB1 into Plots.\n", - "WARNING: importing deprecated binding Colors.RGB4 into Plots.\n", - r"┌ Warning: Keyword argument letter not supported with Plots.+\n└ @ Plots.+\n", - r"┌ Warning: `parse\(::Type, ::Coloarant\)` is deprecated.+\n│.+\n│.+\n└ @ Plots.+\n", - # TODO: Silence warning introduced by Flux v0.13.13. Should be properly fixed. - r"┌ Warning: Layer with Float32 parameters got Float64 input.+\n│.+\n│.+\n│.+\n└ @ Flux.+\n", - ] - append!(ignore_content, $additional_ignore_content) - for pattern in ignore_content - stderr_content = replace(stderr_content, pattern => "") - end - - # We also ignore simple module redefinitions for convenience. Thus, we - # check whether every line of `stderr_content` is of the form of a - # module replacement warning. - @test occursin(r"^(WARNING: replacing module .+\.\n)*$", stderr_content) - ret - finally - rm(fname, force=true) - end end - end end - """ @timed_testset "name of the testset" #= code to test #= @@ -181,21 +178,20 @@ Similar to `@testset`, but prints the name of the testset and its runtime after execution. """ macro timed_testset(name, expr) - @assert name isa String - quote - local time_start = time_ns() - @testset $name $expr - local time_stop = time_ns() - if Trixi.mpi_isroot() - flush(stdout) - @info("Testset " * $name * " finished in " - * string(1.0e-9 * (time_stop - time_start)) * " seconds.\n") - flush(stdout) + @assert name isa String + quote + local time_start = time_ns() + @testset $name $expr + local time_stop = time_ns() + if Trixi.mpi_isroot() + flush(stdout) + @info("Testset "*$name*" finished in " + *string(1.0e-9 * (time_stop - time_start))*" seconds.\n") + flush(stdout) + end end - end end - """ @trixi_testset "name of the testset" #= code to test #= @@ -205,38 +201,38 @@ definition of `@test_trixi_include`. Moreover, it records the execution time of the testset similarly to [`timed_testset`](@ref). """ macro trixi_testset(name, expr) - @assert name isa String - # TODO: `@eval` is evil - # We would like to use - # mod = gensym(name) - # ... - # module $mod - # to create new module names for every test set. However, this is not - # compatible with the dirty hack using `@eval` to get the mapping when - # loading structured, curvilinear meshes. Thus, we need to use a plain - # module name here. - quote - local time_start = time_ns() - @eval module TrixiTestModule - using Test - using Trixi - include(@__FILE__) - # We define `EXAMPLES_DIR` in (nearly) all test modules and use it to - # get the path to the elixirs to be tested. However, that's not required - # and we want to fail gracefully if it's not defined. - try - import ..EXAMPLES_DIR - catch + @assert name isa String + # TODO: `@eval` is evil + # We would like to use + # mod = gensym(name) + # ... + # module $mod + # to create new module names for every test set. However, this is not + # compatible with the dirty hack using `@eval` to get the mapping when + # loading structured, curvilinear meshes. Thus, we need to use a plain + # module name here. + quote + local time_start = time_ns() + @eval module TrixiTestModule + using Test + using Trixi + include(@__FILE__) + # We define `EXAMPLES_DIR` in (nearly) all test modules and use it to + # get the path to the elixirs to be tested. However, that's not required + # and we want to fail gracefully if it's not defined. + try + import ..EXAMPLES_DIR + catch + nothing + end + @testset $name $expr + end + local time_stop = time_ns() + if Trixi.mpi_isroot() + flush(stdout) + @info("Testset "*$name*" finished in " + *string(1.0e-9 * (time_stop - time_start))*" seconds.\n") + end nothing - end - @testset $name $expr - end - local time_stop = time_ns() - if Trixi.mpi_isroot() - flush(stdout) - @info("Testset " * $name * " finished in " - * string(1.0e-9 * (time_stop - time_start)) * " seconds.\n") end - nothing - end end diff --git a/test/test_unit.jl b/test/test_unit.jl index 5c5291c2430..b3ed29d38e3 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -7,593 +7,625 @@ include("test_trixi.jl") # Start with a clean environment: remove Trixi.jl output directory if it exists outdir = "out" -isdir(outdir) && rm(outdir, recursive=true) +isdir(outdir) && rm(outdir, recursive = true) # Run various unit (= non-elixir-triggered) tests @testset "Unit tests" begin - @timed_testset "SerialTree" begin +#! format: noindent + +@timed_testset "SerialTree" begin @testset "constructors" begin - @test_nowarn Trixi.SerialTree(Val(1), 10, 0.0, 1.0) + @test_nowarn Trixi.SerialTree(Val(1), 10, 0.0, 1.0) end @testset "helper functions" begin - t = Trixi.SerialTree(Val(1), 10, 0.0, 1.0) - @test_nowarn display(t) - @test Trixi.ndims(t) == 1 - @test Trixi.has_any_neighbor(t, 1, 1) == true - @test Trixi.isperiodic(t, 1) == true - @test Trixi.n_children_per_cell(t) == 2 - @test Trixi.n_directions(t) == 2 + t = Trixi.SerialTree(Val(1), 10, 0.0, 1.0) + @test_nowarn display(t) + @test Trixi.ndims(t) == 1 + @test Trixi.has_any_neighbor(t, 1, 1) == true + @test Trixi.isperiodic(t, 1) == true + @test Trixi.n_children_per_cell(t) == 2 + @test Trixi.n_directions(t) == 2 end @testset "refine!/coarsen!" begin - t = Trixi.SerialTree(Val(1), 10, 0.0, 1.0) - @test Trixi.refine!(t) == [1] - @test Trixi.coarsen!(t) == [1] - @test Trixi.refine!(t) == [1] - @test Trixi.coarsen!(t, 1) == [1] - @test Trixi.coarsen!(t) == Int[] # Coarsen twice to check degenerate case of single-cell tree - @test Trixi.refine!(t) == [1] - @test Trixi.refine!(t) == [2,3] - @test Trixi.coarsen_box!(t, [-0.5], [0.0]) == [2] - @test Trixi.coarsen_box!(t, 0.0, 0.5) == [3] - @test isnothing(Trixi.reset_data_structures!(t)) - end - end - - @timed_testset "ParallelTree" begin + t = Trixi.SerialTree(Val(1), 10, 0.0, 1.0) + @test Trixi.refine!(t) == [1] + @test Trixi.coarsen!(t) == [1] + @test Trixi.refine!(t) == [1] + @test Trixi.coarsen!(t, 1) == [1] + @test Trixi.coarsen!(t) == Int[] # Coarsen twice to check degenerate case of single-cell tree + @test Trixi.refine!(t) == [1] + @test Trixi.refine!(t) == [2, 3] + @test Trixi.coarsen_box!(t, [-0.5], [0.0]) == [2] + @test Trixi.coarsen_box!(t, 0.0, 0.5) == [3] + @test isnothing(Trixi.reset_data_structures!(t)) + end +end + +@timed_testset "ParallelTree" begin @testset "constructors" begin - @test_nowarn Trixi.ParallelTree(Val(1), 10, 0.0, 1.0) + @test_nowarn Trixi.ParallelTree(Val(1), 10, 0.0, 1.0) end @testset "helper functions" begin - t = Trixi.ParallelTree(Val(1), 10, 0.0, 1.0) - @test isnothing(display(t)) - @test isnothing(Trixi.reset_data_structures!(t)) + t = Trixi.ParallelTree(Val(1), 10, 0.0, 1.0) + @test isnothing(display(t)) + @test isnothing(Trixi.reset_data_structures!(t)) end - end +end - @timed_testset "TreeMesh" begin +@timed_testset "TreeMesh" begin @testset "constructors" begin - @test TreeMesh{1, Trixi.SerialTree{1}}(1, 5.0, 2.0) isa TreeMesh + @test TreeMesh{1, Trixi.SerialTree{1}}(1, 5.0, 2.0) isa TreeMesh end - end +end - @timed_testset "ParallelTreeMesh" begin +@timed_testset "ParallelTreeMesh" begin @testset "partition!" begin - @testset "mpi_nranks() = 2" begin - Trixi.mpi_nranks() = 2 - let - @test Trixi.mpi_nranks() == 2 - - mesh = TreeMesh{2, Trixi.ParallelTree{2}}(30, (0.0, 0.0), 1) - # Refine twice - Trixi.refine!(mesh.tree) - Trixi.refine!(mesh.tree) - - # allow_coarsening = true - Trixi.partition!(mesh) - # Use parent for OffsetArray - @test parent(mesh.n_cells_by_rank) == [11, 10] - @test mesh.tree.mpi_ranks[1:21] == - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] - @test parent(mesh.first_cell_by_rank) == [1, 12] - - # allow_coarsening = false - Trixi.partition!(mesh; allow_coarsening=false) - @test parent(mesh.n_cells_by_rank) == [11, 10] - @test mesh.tree.mpi_ranks[1:21] == - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] - @test parent(mesh.first_cell_by_rank) == [1, 12] + @testset "mpi_nranks() = 2" begin + Trixi.mpi_nranks() = 2 + let + @test Trixi.mpi_nranks() == 2 + + mesh = TreeMesh{2, Trixi.ParallelTree{2}}(30, (0.0, 0.0), 1) + # Refine twice + Trixi.refine!(mesh.tree) + Trixi.refine!(mesh.tree) + + # allow_coarsening = true + Trixi.partition!(mesh) + # Use parent for OffsetArray + @test parent(mesh.n_cells_by_rank) == [11, 10] + @test mesh.tree.mpi_ranks[1:21] == + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] + @test parent(mesh.first_cell_by_rank) == [1, 12] + + # allow_coarsening = false + Trixi.partition!(mesh; allow_coarsening = false) + @test parent(mesh.n_cells_by_rank) == [11, 10] + @test mesh.tree.mpi_ranks[1:21] == + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] + @test parent(mesh.first_cell_by_rank) == [1, 12] + end + Trixi.mpi_nranks() = Trixi.MPI_SIZE[] # restore the original behavior end - Trixi.mpi_nranks() = Trixi.MPI_SIZE[] # restore the original behavior - end - - @testset "mpi_nranks() = 3" begin - Trixi.mpi_nranks() = 3 - let - @test Trixi.mpi_nranks() == 3 - - mesh = TreeMesh{2, Trixi.ParallelTree{2}}(100, (0.0, 0.0), 1) - # Refine twice - Trixi.refine!(mesh.tree) - Trixi.refine!(mesh.tree) - - # allow_coarsening = true - Trixi.partition!(mesh) - # Use parent for OffsetArray - @test parent(mesh.n_cells_by_rank) == [11, 5, 5] - @test mesh.tree.mpi_ranks[1:21] == - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2] - @test parent(mesh.first_cell_by_rank) == [1, 12, 17] - - # allow_coarsening = false - Trixi.partition!(mesh; allow_coarsening=false) - @test parent(mesh.n_cells_by_rank) == [9, 6, 6] - @test mesh.tree.mpi_ranks[1:21] == - [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2] - @test parent(mesh.first_cell_by_rank) == [1, 10, 16] + + @testset "mpi_nranks() = 3" begin + Trixi.mpi_nranks() = 3 + let + @test Trixi.mpi_nranks() == 3 + + mesh = TreeMesh{2, Trixi.ParallelTree{2}}(100, (0.0, 0.0), 1) + # Refine twice + Trixi.refine!(mesh.tree) + Trixi.refine!(mesh.tree) + + # allow_coarsening = true + Trixi.partition!(mesh) + # Use parent for OffsetArray + @test parent(mesh.n_cells_by_rank) == [11, 5, 5] + @test mesh.tree.mpi_ranks[1:21] == + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2] + @test parent(mesh.first_cell_by_rank) == [1, 12, 17] + + # allow_coarsening = false + Trixi.partition!(mesh; allow_coarsening = false) + @test parent(mesh.n_cells_by_rank) == [9, 6, 6] + @test mesh.tree.mpi_ranks[1:21] == + [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2] + @test parent(mesh.first_cell_by_rank) == [1, 10, 16] + end + Trixi.mpi_nranks() = Trixi.MPI_SIZE[] # restore the original behavior end - Trixi.mpi_nranks() = Trixi.MPI_SIZE[] # restore the original behavior - end - - @testset "mpi_nranks() = 9" begin - Trixi.mpi_nranks() = 9 - let - @test Trixi.mpi_nranks() == 9 - - mesh = TreeMesh{2, Trixi.ParallelTree{2}}(1000, (0.0, 0.0), 1) - # Refine twice - Trixi.refine!(mesh.tree) - Trixi.refine!(mesh.tree) - Trixi.refine!(mesh.tree) - Trixi.refine!(mesh.tree) - - # allow_coarsening = true - Trixi.partition!(mesh) - # Use parent for OffsetArray - @test parent(mesh.n_cells_by_rank) == [44, 37, 38, 37, 37, 37, 38, 37, 36] - @test parent(mesh.first_cell_by_rank) == [1, 45, 82, 120, 157, 194, 231, 269, 306] + + @testset "mpi_nranks() = 9" begin + Trixi.mpi_nranks() = 9 + let + @test Trixi.mpi_nranks() == 9 + + mesh = TreeMesh{2, Trixi.ParallelTree{2}}(1000, (0.0, 0.0), 1) + # Refine twice + Trixi.refine!(mesh.tree) + Trixi.refine!(mesh.tree) + Trixi.refine!(mesh.tree) + Trixi.refine!(mesh.tree) + + # allow_coarsening = true + Trixi.partition!(mesh) + # Use parent for OffsetArray + @test parent(mesh.n_cells_by_rank) == + [44, 37, 38, 37, 37, 37, 38, 37, 36] + @test parent(mesh.first_cell_by_rank) == + [1, 45, 82, 120, 157, 194, 231, 269, 306] + end + Trixi.mpi_nranks() = Trixi.MPI_SIZE[] # restore the original behavior end - Trixi.mpi_nranks() = Trixi.MPI_SIZE[] # restore the original behavior - end - - @testset "mpi_nranks() = 3 non-uniform" begin - Trixi.mpi_nranks() = 3 - let - @test Trixi.mpi_nranks() == 3 - - mesh = TreeMesh{2, Trixi.ParallelTree{2}}(100, (0.0, 0.0), 1) - # Refine whole tree - Trixi.refine!(mesh.tree) - # Refine left leaf - Trixi.refine!(mesh.tree, [2]) - - # allow_coarsening = true - Trixi.partition!(mesh) - # Use parent for OffsetArray - @test parent(mesh.n_cells_by_rank) == [6, 1, 2] - @test mesh.tree.mpi_ranks[1:9] == [0, 0, 0, 0, 0, 0, 1, 2, 2] - @test parent(mesh.first_cell_by_rank) == [1, 7, 8] - - # allow_coarsening = false - Trixi.partition!(mesh; allow_coarsening=false) - @test parent(mesh.n_cells_by_rank) == [5, 2, 2] - @test mesh.tree.mpi_ranks[1:9] == [0, 0, 0, 0, 0, 1, 1, 2, 2] - @test parent(mesh.first_cell_by_rank) == [1, 6, 8] + + @testset "mpi_nranks() = 3 non-uniform" begin + Trixi.mpi_nranks() = 3 + let + @test Trixi.mpi_nranks() == 3 + + mesh = TreeMesh{2, Trixi.ParallelTree{2}}(100, (0.0, 0.0), 1) + # Refine whole tree + Trixi.refine!(mesh.tree) + # Refine left leaf + Trixi.refine!(mesh.tree, [2]) + + # allow_coarsening = true + Trixi.partition!(mesh) + # Use parent for OffsetArray + @test parent(mesh.n_cells_by_rank) == [6, 1, 2] + @test mesh.tree.mpi_ranks[1:9] == [0, 0, 0, 0, 0, 0, 1, 2, 2] + @test parent(mesh.first_cell_by_rank) == [1, 7, 8] + + # allow_coarsening = false + Trixi.partition!(mesh; allow_coarsening = false) + @test parent(mesh.n_cells_by_rank) == [5, 2, 2] + @test mesh.tree.mpi_ranks[1:9] == [0, 0, 0, 0, 0, 1, 1, 2, 2] + @test parent(mesh.first_cell_by_rank) == [1, 6, 8] + end + Trixi.mpi_nranks() = Trixi.MPI_SIZE[] # restore the original behavior end - Trixi.mpi_nranks() = Trixi.MPI_SIZE[] # restore the original behavior - end - @testset "not enough ranks" begin - Trixi.mpi_nranks() = 3 - let - @test Trixi.mpi_nranks() == 3 + @testset "not enough ranks" begin + Trixi.mpi_nranks() = 3 + let + @test Trixi.mpi_nranks() == 3 - mesh = TreeMesh{2, Trixi.ParallelTree{2}}(100, (0.0, 0.0), 1) + mesh = TreeMesh{2, Trixi.ParallelTree{2}}(100, (0.0, 0.0), 1) - # Only one leaf - @test_throws AssertionError( - "Too many ranks to properly partition the mesh!") Trixi.partition!(mesh) + # Only one leaf + @test_throws AssertionError("Too many ranks to properly partition the mesh!") Trixi.partition!(mesh) - # Refine to 4 leaves - Trixi.refine!(mesh.tree) + # Refine to 4 leaves + Trixi.refine!(mesh.tree) - # All four leaves will need to be on one rank to allow coarsening - @test_throws AssertionError( - "Too many ranks to properly partition the mesh!") Trixi.partition!(mesh) - @test_nowarn Trixi.partition!(mesh; allow_coarsening=false) + # All four leaves will need to be on one rank to allow coarsening + @test_throws AssertionError("Too many ranks to properly partition the mesh!") Trixi.partition!(mesh) + @test_nowarn Trixi.partition!(mesh; allow_coarsening = false) + end + Trixi.mpi_nranks() = Trixi.MPI_SIZE[] # restore the original behavior end - Trixi.mpi_nranks() = Trixi.MPI_SIZE[] # restore the original behavior - end end - end +end - @timed_testset "curved mesh" begin +@timed_testset "curved mesh" begin @testset "calc_jacobian_matrix" begin - @testset "identity map" begin - basis = LobattoLegendreBasis(5) - nodes = Trixi.get_nodes(basis) - jacobian_matrix = Array{Float64, 5}(undef, 2, 2, 6, 6, 1) - - node_coordinates = Array{Float64, 4}(undef, 2, 6, 6, 1) - node_coordinates[1, :, :, 1] .= [nodes[i] for i in 1:6, j in 1:6] - node_coordinates[2, :, :, 1] .= [nodes[j] for i in 1:6, j in 1:6] - expected = zeros(2, 2, 6, 6, 1) - expected[1, 1, :, :, 1] .= 1 - expected[2, 2, :, :, 1] .= 1 - @test Trixi.calc_jacobian_matrix!(jacobian_matrix, 1, node_coordinates, basis) ≈ expected - end - - @testset "maximum exact polydeg" begin - basis = LobattoLegendreBasis(3) - nodes = Trixi.get_nodes(basis) - jacobian_matrix = Array{Float64, 5}(undef, 2, 2, 4, 4, 1) - - # f(x, y) = [x^3, xy^2] - node_coordinates = Array{Float64, 4}(undef, 2, 4, 4, 1) - node_coordinates[1, :, :, 1] .= [nodes[i]^3 for i in 1:4, j in 1:4] - node_coordinates[2, :, :, 1] .= [nodes[i] * nodes[j]^2 for i in 1:4, j in 1:4] - - # Df(x, y) = [3x^2 0; - # y^2 2xy] - expected = zeros(2, 2, 4, 4, 1) - expected[1, 1, :, :, 1] .= [3 * nodes[i]^2 for i in 1:4, j in 1:4] - expected[2, 1, :, :, 1] .= [nodes[j]^2 for i in 1:4, j in 1:4] - expected[2, 2, :, :, 1] .= [2 * nodes[i] * nodes[j] for i in 1:4, j in 1:4] - @test Trixi.calc_jacobian_matrix!(jacobian_matrix, 1, node_coordinates, basis) ≈ expected - end - end - end - - @timed_testset "interpolation" begin + @testset "identity map" begin + basis = LobattoLegendreBasis(5) + nodes = Trixi.get_nodes(basis) + jacobian_matrix = Array{Float64, 5}(undef, 2, 2, 6, 6, 1) + + node_coordinates = Array{Float64, 4}(undef, 2, 6, 6, 1) + node_coordinates[1, :, :, 1] .= [nodes[i] for i in 1:6, j in 1:6] + node_coordinates[2, :, :, 1] .= [nodes[j] for i in 1:6, j in 1:6] + expected = zeros(2, 2, 6, 6, 1) + expected[1, 1, :, :, 1] .= 1 + expected[2, 2, :, :, 1] .= 1 + @test Trixi.calc_jacobian_matrix!(jacobian_matrix, 1, node_coordinates, + basis) ≈ expected + end + + @testset "maximum exact polydeg" begin + basis = LobattoLegendreBasis(3) + nodes = Trixi.get_nodes(basis) + jacobian_matrix = Array{Float64, 5}(undef, 2, 2, 4, 4, 1) + + # f(x, y) = [x^3, xy^2] + node_coordinates = Array{Float64, 4}(undef, 2, 4, 4, 1) + node_coordinates[1, :, :, 1] .= [nodes[i]^3 for i in 1:4, j in 1:4] + node_coordinates[2, :, :, 1] .= [nodes[i] * nodes[j]^2 + for i in 1:4, j in 1:4] + + # Df(x, y) = [3x^2 0; + # y^2 2xy] + expected = zeros(2, 2, 4, 4, 1) + expected[1, 1, :, :, 1] .= [3 * nodes[i]^2 for i in 1:4, j in 1:4] + expected[2, 1, :, :, 1] .= [nodes[j]^2 for i in 1:4, j in 1:4] + expected[2, 2, :, :, 1] .= [2 * nodes[i] * nodes[j] for i in 1:4, j in 1:4] + @test Trixi.calc_jacobian_matrix!(jacobian_matrix, 1, node_coordinates, + basis) ≈ expected + end + end +end + +@timed_testset "interpolation" begin @testset "nodes and weights" begin - @test Trixi.gauss_nodes_weights(1) == ([0.0], [2.0]) + @test Trixi.gauss_nodes_weights(1) == ([0.0], [2.0]) end @testset "multiply_dimensionwise" begin - nodes_in = [0.0, 0.5, 1.0] - nodes_out = [0.0, 1/3, 2/3, 1.0] - matrix = Trixi.polynomial_interpolation_matrix(nodes_in, nodes_out) - data_in = [3.0 4.5 6.0] - @test isapprox(Trixi.multiply_dimensionwise(matrix, data_in), [3.0 4.0 5.0 6.0]) - - n_vars = 3 - size_in = 2 - size_out = 3 - matrix = randn(size_out, size_in) - # 1D - data_in = randn(n_vars, size_in) - data_out = Trixi.multiply_dimensionwise_naive(matrix, data_in) - @test isapprox(data_out, Trixi.multiply_dimensionwise(matrix, data_in)) - # 2D - data_in = randn(n_vars, size_in, size_in) - data_out = Trixi.multiply_dimensionwise_naive(matrix, data_in) - @test isapprox(data_out, Trixi.multiply_dimensionwise(matrix, data_in)) - # 3D - data_in = randn(n_vars, size_in, size_in, size_in) - data_out = Trixi.multiply_dimensionwise_naive(matrix, data_in) - @test isapprox(data_out, Trixi.multiply_dimensionwise(matrix, data_in)) - end - end - - @timed_testset "L2 projection" begin + nodes_in = [0.0, 0.5, 1.0] + nodes_out = [0.0, 1 / 3, 2 / 3, 1.0] + matrix = Trixi.polynomial_interpolation_matrix(nodes_in, nodes_out) + data_in = [3.0 4.5 6.0] + @test isapprox(Trixi.multiply_dimensionwise(matrix, data_in), [3.0 4.0 5.0 6.0]) + + n_vars = 3 + size_in = 2 + size_out = 3 + matrix = randn(size_out, size_in) + # 1D + data_in = randn(n_vars, size_in) + data_out = Trixi.multiply_dimensionwise_naive(matrix, data_in) + @test isapprox(data_out, Trixi.multiply_dimensionwise(matrix, data_in)) + # 2D + data_in = randn(n_vars, size_in, size_in) + data_out = Trixi.multiply_dimensionwise_naive(matrix, data_in) + @test isapprox(data_out, Trixi.multiply_dimensionwise(matrix, data_in)) + # 3D + data_in = randn(n_vars, size_in, size_in, size_in) + data_out = Trixi.multiply_dimensionwise_naive(matrix, data_in) + @test isapprox(data_out, Trixi.multiply_dimensionwise(matrix, data_in)) + end +end + +@timed_testset "L2 projection" begin @testset "calc_reverse_upper for LGL" begin - @test isapprox(Trixi.calc_reverse_upper(2, Val(:gauss_lobatto)), [[0.25, 0.25] [0.0, 0.5]]) + @test isapprox(Trixi.calc_reverse_upper(2, Val(:gauss_lobatto)), + [[0.25, 0.25] [0.0, 0.5]]) end @testset "calc_reverse_lower for LGL" begin - @test isapprox(Trixi.calc_reverse_lower(2, Val(:gauss_lobatto)), [[0.5, 0.0] [0.25, 0.25]]) + @test isapprox(Trixi.calc_reverse_lower(2, Val(:gauss_lobatto)), + [[0.5, 0.0] [0.25, 0.25]]) end - end +end - @testset "containers" begin +@testset "containers" begin # Set up mock container mutable struct MyContainer <: Trixi.AbstractContainer - data::Vector{Int} - capacity::Int - length::Int - dummy::Int + data::Vector{Int} + capacity::Int + length::Int + dummy::Int end function MyContainer(data, capacity) - c = MyContainer(Vector{Int}(undef, capacity+1), capacity, length(data), capacity+1) - c.data[1:length(data)] .= data - return c + c = MyContainer(Vector{Int}(undef, capacity + 1), capacity, length(data), + capacity + 1) + c.data[1:length(data)] .= data + return c end MyContainer(data::AbstractArray) = MyContainer(data, length(data)) Trixi.invalidate!(c::MyContainer, first, last) = (c.data[first:last] .= 0; c) - function Trixi.raw_copy!(target::MyContainer, source::MyContainer, first, last, destination) - Trixi.copy_data!(target.data, source.data, first, last, destination) - return target + function Trixi.raw_copy!(target::MyContainer, source::MyContainer, first, last, + destination) + Trixi.copy_data!(target.data, source.data, first, last, destination) + return target end Trixi.move_connectivity!(c::MyContainer, first, last, destination) = c Trixi.delete_connectivity!(c::MyContainer, first, last) = c - Trixi.reset_data_structures!(c::MyContainer) = (c.data = Vector{Int}(undef, c.capacity+1); c) + function Trixi.reset_data_structures!(c::MyContainer) + (c.data = Vector{Int}(undef, + c.capacity + 1); + c) + end function Base.:(==)(c1::MyContainer, c2::MyContainer) - return (c1.capacity == c2.capacity && - c1.length == c2.length && - c1.dummy == c2.dummy && - c1.data[1:c1.length] == c2.data[1:c2.length]) + return (c1.capacity == c2.capacity && + c1.length == c2.length && + c1.dummy == c2.dummy && + c1.data[1:(c1.length)] == c2.data[1:(c2.length)]) end @testset "size" begin - c = MyContainer([1, 2, 3]) - @test size(c) == (3,) + c = MyContainer([1, 2, 3]) + @test size(c) == (3,) end @testset "resize!" begin - c = MyContainer([1, 2, 3]) - @test length(resize!(c, 2)) == 2 + c = MyContainer([1, 2, 3]) + @test length(resize!(c, 2)) == 2 end @testset "copy!" begin - c1 = MyContainer([1, 2, 3]) - c2 = MyContainer([4, 5]) - @test Trixi.copy!(c1, c2, 2, 1, 2) == MyContainer([1, 2, 3]) # no-op + c1 = MyContainer([1, 2, 3]) + c2 = MyContainer([4, 5]) + @test Trixi.copy!(c1, c2, 2, 1, 2) == MyContainer([1, 2, 3]) # no-op - c1 = MyContainer([1, 2, 3]) - c2 = MyContainer([4, 5]) - @test Trixi.copy!(c1, c2, 1, 2, 2) == MyContainer([1, 4, 5]) + c1 = MyContainer([1, 2, 3]) + c2 = MyContainer([4, 5]) + @test Trixi.copy!(c1, c2, 1, 2, 2) == MyContainer([1, 4, 5]) - c1 = MyContainer([1, 2, 3]) - @test Trixi.copy!(c1, c2, 1, 2) == MyContainer([1, 4, 3]) + c1 = MyContainer([1, 2, 3]) + @test Trixi.copy!(c1, c2, 1, 2) == MyContainer([1, 4, 3]) - c1 = MyContainer([1, 2, 3]) - @test Trixi.copy!(c1, 2, 3, 1) == MyContainer([2, 3, 3]) + c1 = MyContainer([1, 2, 3]) + @test Trixi.copy!(c1, 2, 3, 1) == MyContainer([2, 3, 3]) - c1 = MyContainer([1, 2, 3]) - @test Trixi.copy!(c1, 1, 3) == MyContainer([1, 2, 1]) + c1 = MyContainer([1, 2, 3]) + @test Trixi.copy!(c1, 1, 3) == MyContainer([1, 2, 1]) end @testset "move!" begin - c = MyContainer([1, 2, 3]) - @test Trixi.move!(c, 1, 1) == MyContainer([1, 2, 3]) # no-op + c = MyContainer([1, 2, 3]) + @test Trixi.move!(c, 1, 1) == MyContainer([1, 2, 3]) # no-op - c = MyContainer([1, 2, 3]) - @test Trixi.move!(c, 1, 2) == MyContainer([0, 1, 3]) + c = MyContainer([1, 2, 3]) + @test Trixi.move!(c, 1, 2) == MyContainer([0, 1, 3]) end @testset "swap!" begin - c = MyContainer([1,2]) - @test Trixi.swap!(c, 1, 1) == MyContainer([1, 2]) # no-op + c = MyContainer([1, 2]) + @test Trixi.swap!(c, 1, 1) == MyContainer([1, 2]) # no-op - c = MyContainer([1,2]) - @test Trixi.swap!(c, 1, 2) == MyContainer([2,1]) + c = MyContainer([1, 2]) + @test Trixi.swap!(c, 1, 2) == MyContainer([2, 1]) end @testset "erase!" begin - c = MyContainer([1, 2]) - @test Trixi.erase!(c, 2, 1) == MyContainer([1, 2]) # no-op + c = MyContainer([1, 2]) + @test Trixi.erase!(c, 2, 1) == MyContainer([1, 2]) # no-op - c = MyContainer([1, 2]) - @test Trixi.erase!(c, 1) == MyContainer([0, 2]) + c = MyContainer([1, 2]) + @test Trixi.erase!(c, 1) == MyContainer([0, 2]) end @testset "remove_shift!" begin - c = MyContainer([1, 2, 3, 4]) - @test Trixi.remove_shift!(c, 2, 1) == MyContainer([1, 2, 3, 4]) # no-op + c = MyContainer([1, 2, 3, 4]) + @test Trixi.remove_shift!(c, 2, 1) == MyContainer([1, 2, 3, 4]) # no-op - c = MyContainer([1, 2, 3, 4]) - @test Trixi.remove_shift!(c, 2, 2) == MyContainer([1, 3, 4], 4) + c = MyContainer([1, 2, 3, 4]) + @test Trixi.remove_shift!(c, 2, 2) == MyContainer([1, 3, 4], 4) - c = MyContainer([1, 2, 3, 4]) - @test Trixi.remove_shift!(c, 2) == MyContainer([1, 3, 4], 4) + c = MyContainer([1, 2, 3, 4]) + @test Trixi.remove_shift!(c, 2) == MyContainer([1, 3, 4], 4) end @testset "remove_fill!" begin - c = MyContainer([1, 2, 3, 4]) - @test Trixi.remove_fill!(c, 2, 1) == MyContainer([1, 2, 3, 4]) # no-op + c = MyContainer([1, 2, 3, 4]) + @test Trixi.remove_fill!(c, 2, 1) == MyContainer([1, 2, 3, 4]) # no-op - c = MyContainer([1, 2, 3, 4]) - @test Trixi.remove_fill!(c, 2, 2) == MyContainer([1, 4, 3], 4) + c = MyContainer([1, 2, 3, 4]) + @test Trixi.remove_fill!(c, 2, 2) == MyContainer([1, 4, 3], 4) end @testset "reset!" begin - c = MyContainer([1, 2, 3]) - @test Trixi.reset!(c, 2) == MyContainer(Int[], 2) + c = MyContainer([1, 2, 3]) + @test Trixi.reset!(c, 2) == MyContainer(Int[], 2) end - end +end - @timed_testset "example elixirs" begin +@timed_testset "example elixirs" begin @test basename(examples_dir()) == "examples" @test !isempty(get_examples()) @test endswith(default_example(), "elixir_advection_basic.jl") - end +end - @timed_testset "HLL flux with vanishing wave speed estimates (#502)" begin +@timed_testset "HLL flux with vanishing wave speed estimates (#502)" begin equations = CompressibleEulerEquations1D(1.4) u = SVector(1.0, 0.0, 0.0) @test !any(isnan, flux_hll(u, u, 1, equations)) - end +end - @timed_testset "DG L2 mortar container debug output" begin +@timed_testset "DG L2 mortar container debug output" begin c2d = Trixi.L2MortarContainer2D{Float64}(1, 1, 1) @test isnothing(display(c2d)) c3d = Trixi.L2MortarContainer3D{Float64}(1, 1, 1) @test isnothing(display(c3d)) - end +end - @timed_testset "Printing indicators/controllers" begin +@timed_testset "Printing indicators/controllers" begin # OBS! Constructing indicators/controllers using the parameters below doesn't make sense. It's # just useful to run basic tests of `show` methods. - c = ControllerThreeLevelCombined(1, 2, 3, 10.0, 11.0, 12.0, "primary", "secondary", "cache") + c = ControllerThreeLevelCombined(1, 2, 3, 10.0, 11.0, 12.0, "primary", "secondary", + "cache") @test_nowarn show(stdout, c) indicator_hg = IndicatorHennemannGassner(1.0, 0.0, true, "variable", "cache") @test_nowarn show(stdout, indicator_hg) - limiter_idp = SubcellLimiterIDP(true, [1], 0.1, "cache") + limiter_idp = SubcellLimiterIDP(true, [1], true, [1], 0.1, "cache") @test_nowarn show(stdout, limiter_idp) # TODO: TrixiShallowWater: move unit test - indicator_hg_swe = IndicatorHennemannGassnerShallowWater(1.0, 0.0, true, "variable", "cache") + indicator_hg_swe = IndicatorHennemannGassnerShallowWater(1.0, 0.0, true, "variable", + "cache") @test_nowarn show(stdout, indicator_hg_swe) - indicator_loehner = IndicatorLöhner(1.0, "variable", (; cache=nothing)) + indicator_loehner = IndicatorLöhner(1.0, "variable", (; cache = nothing)) @test_nowarn show(stdout, indicator_loehner) - indicator_max = IndicatorMax("variable", (; cache=nothing)) + indicator_max = IndicatorMax("variable", (; cache = nothing)) @test_nowarn show(stdout, indicator_max) +end - equations = CompressibleEulerEquations2D(1.4) - basis = LobattoLegendreBasis(3) - indicator_neuralnetwork = IndicatorNeuralNetwork( - equations, basis, indicator_type=NeuralNetworkPerssonPeraire(), variable=density, - network=nothing) - @test_nowarn show(stdout, indicator_neuralnetwork) - end - - @timed_testset "LBM 2D constructor" begin +@timed_testset "LBM 2D constructor" begin # Neither Mach number nor velocity set - @test_throws ErrorException LatticeBoltzmannEquations2D(Ma=nothing, Re=1000) + @test_throws ErrorException LatticeBoltzmannEquations2D(Ma = nothing, Re = 1000) # Both Mach number and velocity set - @test_throws ErrorException LatticeBoltzmannEquations2D(Ma=0.1, Re=1000, u0=1) + @test_throws ErrorException LatticeBoltzmannEquations2D(Ma = 0.1, Re = 1000, u0 = 1) # Neither Reynolds number nor viscosity set - @test_throws ErrorException LatticeBoltzmannEquations2D(Ma=0.1, Re=nothing) + @test_throws ErrorException LatticeBoltzmannEquations2D(Ma = 0.1, Re = nothing) # Both Reynolds number and viscosity set - @test_throws ErrorException LatticeBoltzmannEquations2D(Ma=0.1, Re=1000, nu=1) + @test_throws ErrorException LatticeBoltzmannEquations2D(Ma = 0.1, Re = 1000, nu = 1) # No non-dimensional values set - @test LatticeBoltzmannEquations2D(Ma=nothing, Re=nothing, u0=1, nu=1) isa LatticeBoltzmannEquations2D - end + @test LatticeBoltzmannEquations2D(Ma = nothing, Re = nothing, u0 = 1, nu = 1) isa + LatticeBoltzmannEquations2D +end - @timed_testset "LBM 3D constructor" begin +@timed_testset "LBM 3D constructor" begin # Neither Mach number nor velocity set - @test_throws ErrorException LatticeBoltzmannEquations3D(Ma=nothing, Re=1000) + @test_throws ErrorException LatticeBoltzmannEquations3D(Ma = nothing, Re = 1000) # Both Mach number and velocity set - @test_throws ErrorException LatticeBoltzmannEquations3D(Ma=0.1, Re=1000, u0=1) + @test_throws ErrorException LatticeBoltzmannEquations3D(Ma = 0.1, Re = 1000, u0 = 1) # Neither Reynolds number nor viscosity set - @test_throws ErrorException LatticeBoltzmannEquations3D(Ma=0.1, Re=nothing) + @test_throws ErrorException LatticeBoltzmannEquations3D(Ma = 0.1, Re = nothing) # Both Reynolds number and viscosity set - @test_throws ErrorException LatticeBoltzmannEquations3D(Ma=0.1, Re=1000, nu=1) + @test_throws ErrorException LatticeBoltzmannEquations3D(Ma = 0.1, Re = 1000, nu = 1) # No non-dimensional values set - @test LatticeBoltzmannEquations3D(Ma=nothing, Re=nothing, u0=1, nu=1) isa LatticeBoltzmannEquations3D - end + @test LatticeBoltzmannEquations3D(Ma = nothing, Re = nothing, u0 = 1, nu = 1) isa + LatticeBoltzmannEquations3D +end - @timed_testset "LBM 2D functions" begin +@timed_testset "LBM 2D functions" begin # Set up LBM struct and dummy distribution - equation = LatticeBoltzmannEquations2D(Ma=0.1, Re=1000) + equation = LatticeBoltzmannEquations2D(Ma = 0.1, Re = 1000) u = Trixi.equilibrium_distribution(1, 2, 3, equation) # Component-wise velocity @test isapprox(Trixi.velocity(u, 1, equation), 2) @test isapprox(Trixi.velocity(u, 2, equation), 3) - end +end - @timed_testset "LBM 3D functions" begin +@timed_testset "LBM 3D functions" begin # Set up LBM struct and dummy distribution - equation = LatticeBoltzmannEquations3D(Ma=0.1, Re=1000) + equation = LatticeBoltzmannEquations3D(Ma = 0.1, Re = 1000) u = Trixi.equilibrium_distribution(1, 2, 3, 4, equation) # Component-wise velocity @test isapprox(velocity(u, 1, equation), 2) @test isapprox(velocity(u, 2, equation), 3) @test isapprox(velocity(u, 3, equation), 4) - end +end - @timed_testset "LBMCollisionCallback" begin +@timed_testset "LBMCollisionCallback" begin # Printing of LBM collision callback callback = LBMCollisionCallback() @test_nowarn show(stdout, callback) println() @test_nowarn show(stdout, "text/plain", callback) println() - end +end - @timed_testset "Acoustic perturbation 2D varnames" begin +@timed_testset "Acoustic perturbation 2D varnames" begin v_mean_global = (0.0, 0.0) c_mean_global = 1.0 rho_mean_global = 1.0 - equations = AcousticPerturbationEquations2D(v_mean_global, c_mean_global, rho_mean_global) + equations = AcousticPerturbationEquations2D(v_mean_global, c_mean_global, + rho_mean_global) - @test Trixi.varnames(cons2state, equations) == ("v1_prime", "v2_prime", "p_prime_scaled") - @test Trixi.varnames(cons2mean, equations) == ("v1_mean", "v2_mean", "c_mean", "rho_mean") - end + @test Trixi.varnames(cons2state, equations) == + ("v1_prime", "v2_prime", "p_prime_scaled") + @test Trixi.varnames(cons2mean, equations) == + ("v1_mean", "v2_mean", "c_mean", "rho_mean") +end - @timed_testset "Euler conversion between conservative/entropy variables" begin +@timed_testset "Euler conversion between conservative/entropy variables" begin rho, v1, v2, v3, p = 1.0, 0.1, 0.2, 0.3, 2.0 let equations = CompressibleEulerEquations1D(1.4) - cons_vars = prim2cons(SVector(rho, v1, p),equations) - entropy_vars = cons2entropy(cons_vars, equations) - @test cons_vars ≈ entropy2cons(entropy_vars, equations) + cons_vars = prim2cons(SVector(rho, v1, p), equations) + entropy_vars = cons2entropy(cons_vars, equations) + @test cons_vars ≈ entropy2cons(entropy_vars, equations) - # test tuple args - cons_vars = prim2cons((rho, v1, p),equations) - entropy_vars = cons2entropy(cons_vars, equations) - @test cons_vars ≈ entropy2cons(entropy_vars, equations) + # test tuple args + cons_vars = prim2cons((rho, v1, p), equations) + entropy_vars = cons2entropy(cons_vars, equations) + @test cons_vars ≈ entropy2cons(entropy_vars, equations) end let equations = CompressibleEulerEquations2D(1.4) - cons_vars = prim2cons(SVector(rho,v1,v2,p),equations) - entropy_vars = cons2entropy(cons_vars,equations) - @test cons_vars ≈ entropy2cons(entropy_vars,equations) + cons_vars = prim2cons(SVector(rho, v1, v2, p), equations) + entropy_vars = cons2entropy(cons_vars, equations) + @test cons_vars ≈ entropy2cons(entropy_vars, equations) - # test tuple args - cons_vars = prim2cons((rho, v1, v2, p), equations) - entropy_vars = cons2entropy(cons_vars, equations) - @test cons_vars ≈ entropy2cons(entropy_vars, equations) + # test tuple args + cons_vars = prim2cons((rho, v1, v2, p), equations) + entropy_vars = cons2entropy(cons_vars, equations) + @test cons_vars ≈ entropy2cons(entropy_vars, equations) end let equations = CompressibleEulerEquations3D(1.4) - cons_vars = prim2cons(SVector(rho,v1,v2,v3,p),equations) - entropy_vars = cons2entropy(cons_vars,equations) - @test cons_vars ≈ entropy2cons(entropy_vars,equations) + cons_vars = prim2cons(SVector(rho, v1, v2, v3, p), equations) + entropy_vars = cons2entropy(cons_vars, equations) + @test cons_vars ≈ entropy2cons(entropy_vars, equations) - # test tuple args - cons_vars = prim2cons((rho, v1, v2, v3, p), equations) - entropy_vars = cons2entropy(cons_vars, equations) - @test cons_vars ≈ entropy2cons(entropy_vars, equations) + # test tuple args + cons_vars = prim2cons((rho, v1, v2, v3, p), equations) + entropy_vars = cons2entropy(cons_vars, equations) + @test cons_vars ≈ entropy2cons(entropy_vars, equations) end - end +end - @timed_testset "Shallow water conversion between conservative/entropy variables" begin +@timed_testset "Shallow water conversion between conservative/entropy variables" begin H, v1, v2, b = 3.5, 0.25, 0.1, 0.4 - let equations = ShallowWaterEquations1D(gravity_constant=9.8) - cons_vars = prim2cons(SVector(H, v1, b),equations) - entropy_vars = cons2entropy(cons_vars,equations) - @test cons_vars ≈ entropy2cons(entropy_vars,equations) + let equations = ShallowWaterEquations1D(gravity_constant = 9.8) + cons_vars = prim2cons(SVector(H, v1, b), equations) + entropy_vars = cons2entropy(cons_vars, equations) + @test cons_vars ≈ entropy2cons(entropy_vars, equations) - total_energy = energy_total(cons_vars, equations) - @test total_energy ≈ entropy(cons_vars, equations) + total_energy = energy_total(cons_vars, equations) + @test total_energy ≈ entropy(cons_vars, equations) - # test tuple args - cons_vars = prim2cons((H, v1, b), equations) - entropy_vars = cons2entropy(cons_vars, equations) - @test cons_vars ≈ entropy2cons(entropy_vars, equations) + # test tuple args + cons_vars = prim2cons((H, v1, b), equations) + entropy_vars = cons2entropy(cons_vars, equations) + @test cons_vars ≈ entropy2cons(entropy_vars, equations) end - let equations = ShallowWaterEquations2D(gravity_constant=9.8) - cons_vars = prim2cons(SVector(H,v1,v2,b),equations) - entropy_vars = cons2entropy(cons_vars,equations) - @test cons_vars ≈ entropy2cons(entropy_vars,equations) + let equations = ShallowWaterEquations2D(gravity_constant = 9.8) + cons_vars = prim2cons(SVector(H, v1, v2, b), equations) + entropy_vars = cons2entropy(cons_vars, equations) + @test cons_vars ≈ entropy2cons(entropy_vars, equations) - total_energy = energy_total(cons_vars, equations) - @test total_energy ≈ entropy(cons_vars, equations) + total_energy = energy_total(cons_vars, equations) + @test total_energy ≈ entropy(cons_vars, equations) - # test tuple args - cons_vars = prim2cons((H, v1, v2, b), equations) - entropy_vars = cons2entropy(cons_vars, equations) - @test cons_vars ≈ entropy2cons(entropy_vars, equations) + # test tuple args + cons_vars = prim2cons((H, v1, v2, b), equations) + entropy_vars = cons2entropy(cons_vars, equations) + @test cons_vars ≈ entropy2cons(entropy_vars, equations) end - end +end - @timed_testset "boundary_condition_do_nothing" begin +@timed_testset "boundary_condition_do_nothing" begin rho, v1, v2, p = 1.0, 0.1, 0.2, 0.3, 2.0 let equations = CompressibleEulerEquations2D(1.4) - u = prim2cons(SVector(rho, v1, v2, p), equations) - x = SVector(1.0, 2.0) - t = 0.5 - surface_flux = flux_lax_friedrichs - - outward_direction = SVector(0.2, -0.3) - @test flux(u, outward_direction, equations) ≈ boundary_condition_do_nothing(u, outward_direction, x, t, surface_flux, equations) - - orientation = 2 - direction = 4 - @test flux(u, orientation, equations) ≈ boundary_condition_do_nothing(u, orientation, direction, x, t, surface_flux, equations) + u = prim2cons(SVector(rho, v1, v2, p), equations) + x = SVector(1.0, 2.0) + t = 0.5 + surface_flux = flux_lax_friedrichs + + outward_direction = SVector(0.2, -0.3) + @test flux(u, outward_direction, equations) ≈ + boundary_condition_do_nothing(u, outward_direction, x, t, surface_flux, + equations) + + orientation = 2 + direction = 4 + @test flux(u, orientation, equations) ≈ + boundary_condition_do_nothing(u, orientation, direction, x, t, + surface_flux, equations) end - end +end - @timed_testset "TimeSeriesCallback" begin +@timed_testset "TimeSeriesCallback" begin @test_nowarn_mod trixi_include(@__MODULE__, - joinpath(examples_dir(), "tree_2d_dgsem", "elixir_acoustics_gaussian_source.jl"), - tspan=(0, 0.05)) + joinpath(examples_dir(), "tree_2d_dgsem", + "elixir_acoustics_gaussian_source.jl"), + tspan = (0, 0.05)) point_data_1 = time_series.affect!.point_data[1] - @test all(isapprox.(point_data_1[1:7], [-2.4417734981719132e-5, -3.4296207289200194e-5, - 0.0018130846385739788, -0.5, 0.25, 1.0, 1.0])) - @test_throws DimensionMismatch Trixi.get_elements_by_coordinates!([1, 2], rand(2, 4), mesh, + @test all(isapprox.(point_data_1[1:7], + [-2.4417734981719132e-5, -3.4296207289200194e-5, + 0.0018130846385739788, -0.5, 0.25, 1.0, 1.0])) + @test_throws DimensionMismatch Trixi.get_elements_by_coordinates!([1, 2], + rand(2, 4), mesh, solver, nothing) @test_nowarn show(stdout, time_series) - @test_throws ArgumentError TimeSeriesCallback(semi, [(1.0, 1.0)]; interval=-1) + @test_throws ArgumentError TimeSeriesCallback(semi, [(1.0, 1.0)]; interval = -1) @test_throws ArgumentError TimeSeriesCallback(semi, [1.0 1.0 1.0; 2.0 2.0 2.0]) - end +end - @timed_testset "Consistency check for HLL flux (naive): CEE" begin +@timed_testset "Consistency check for single point flux: CEMCE" begin + equations = CompressibleEulerMulticomponentEquations2D(gammas = (1.4, 1.4), + gas_constants = (0.4, 0.4)) + u = SVector(0.1, -0.5, 1.0, 1.0, 2.0) + + orientations = [1, 2] + for orientation in orientations + @test flux(u, orientation, equations) ≈ + flux_ranocha(u, u, orientation, equations) + end +end + +@timed_testset "Consistency check for HLL flux (naive): CEE" begin flux_hll = FluxHLL(min_max_speed_naive) # Set up equations and dummy conservative variables state @@ -602,7 +634,7 @@ isdir(outdir) && rm(outdir, recursive=true) orientations = [1] for orientation in orientations - @test flux_hll(u, u, orientation, equations) ≈ flux(u, orientation, equations) + @test flux_hll(u, u, orientation, equations) ≈ flux(u, orientation, equations) end equations = CompressibleEulerEquations2D(1.4) @@ -610,7 +642,7 @@ isdir(outdir) && rm(outdir, recursive=true) orientations = [1, 2] for orientation in orientations - @test flux_hll(u, u, orientation, equations) ≈ flux(u, orientation, equations) + @test flux_hll(u, u, orientation, equations) ≈ flux(u, orientation, equations) end equations = CompressibleEulerEquations3D(1.4) @@ -618,11 +650,24 @@ isdir(outdir) && rm(outdir, recursive=true) orientations = [1, 2, 3] for orientation in orientations - @test flux_hll(u, u, orientation, equations) ≈ flux(u, orientation, equations) + @test flux_hll(u, u, orientation, equations) ≈ flux(u, orientation, equations) + end +end + +@timed_testset "Consistency check for flux_chan_etal: CEEQ" begin + + # Set up equations and dummy conservative variables state + equations = CompressibleEulerEquationsQuasi1D(1.4) + u = SVector(1.1, 2.34, 5.5, 2.73) + + orientations = [1] + for orientation in orientations + @test flux_chan_etal(u, u, orientation, equations) ≈ + flux(u, orientation, equations) end - end +end - @timed_testset "Consistency check for HLL flux (naive): LEE" begin +@timed_testset "Consistency check for HLL flux (naive): LEE" begin flux_hll = FluxHLL(min_max_speed_naive) equations = LinearizedEulerEquations2D(SVector(1.0, 1.0), 1.0, 1.0) @@ -630,87 +675,91 @@ isdir(outdir) && rm(outdir, recursive=true) orientations = [1, 2] for orientation in orientations - @test flux_hll(u, u, orientation, equations) ≈ flux(u, orientation, equations) + @test flux_hll(u, u, orientation, equations) ≈ flux(u, orientation, equations) end normal_directions = [SVector(1.0, 0.0), - SVector(0.0, 1.0), - SVector(0.5, -0.5), - SVector(-1.2, 0.3)] + SVector(0.0, 1.0), + SVector(0.5, -0.5), + SVector(-1.2, 0.3)] for normal_direction in normal_directions - @test flux_hll(u, u, normal_direction, equations) ≈ flux(u, normal_direction, equations) + @test flux_hll(u, u, normal_direction, equations) ≈ + flux(u, normal_direction, equations) end - end +end - @timed_testset "Consistency check for HLL flux (naive): SWE" begin +@timed_testset "Consistency check for HLL flux (naive): SWE" begin flux_hll = FluxHLL(min_max_speed_naive) - equations = ShallowWaterEquations1D(gravity_constant=9.81) + equations = ShallowWaterEquations1D(gravity_constant = 9.81) u = SVector(1, 0.5, 0.0) @test flux_hll(u, u, 1, equations) ≈ flux(u, 1, equations) - equations = ShallowWaterEquations2D(gravity_constant=9.81) + equations = ShallowWaterEquations2D(gravity_constant = 9.81) normal_directions = [SVector(1.0, 0.0), - SVector(0.0, 1.0), - SVector(0.5, -0.5), - SVector(-1.2, 0.3)] + SVector(0.0, 1.0), + SVector(0.5, -0.5), + SVector(-1.2, 0.3)] u = SVector(1, 0.5, 0.5, 0.0) for normal_direction in normal_directions - @test flux_hll(u, u, normal_direction, equations) ≈ flux(u, normal_direction, equations) + @test flux_hll(u, u, normal_direction, equations) ≈ + flux(u, normal_direction, equations) end - end +end - @timed_testset "Consistency check for HLL flux (naive): MHD" begin +@timed_testset "Consistency check for HLL flux (naive): MHD" begin flux_hll = FluxHLL(min_max_speed_naive) equations = IdealGlmMhdEquations1D(1.4) u_values = [SVector(1.0, 0.4, -0.5, 0.1, 1.0, 0.1, -0.2, 0.1), - SVector(1.5, -0.2, 0.1, 0.2, 5.0, -0.1, 0.1, 0.2),] + SVector(1.5, -0.2, 0.1, 0.2, 5.0, -0.1, 0.1, 0.2)] for u in u_values - @test flux_hll(u, u, 1, equations) ≈ flux(u, 1, equations) + @test flux_hll(u, u, 1, equations) ≈ flux(u, 1, equations) end - equations = IdealGlmMhdEquations2D(1.4, 5.0 #= c_h =#) + equations = IdealGlmMhdEquations2D(1.4, 5.0) #= c_h =# normal_directions = [SVector(1.0, 0.0), - SVector(0.0, 1.0), - SVector(0.5, -0.5), - SVector(-1.2, 0.3)] + SVector(0.0, 1.0), + SVector(0.5, -0.5), + SVector(-1.2, 0.3)] orientations = [1, 2] u_values = [SVector(1.0, 0.4, -0.5, 0.1, 1.0, 0.1, -0.2, 0.1, 0.0), - SVector(1.5, -0.2, 0.1, 0.2, 5.0, -0.1, 0.1, 0.2, 0.2),] + SVector(1.5, -0.2, 0.1, 0.2, 5.0, -0.1, 0.1, 0.2, 0.2)] for u in u_values, orientation in orientations - @test flux_hll(u, u, orientation, equations) ≈ flux(u, orientation, equations) + @test flux_hll(u, u, orientation, equations) ≈ flux(u, orientation, equations) end for u in u_values, normal_direction in normal_directions - @test flux_hll(u, u, normal_direction, equations) ≈ flux(u, normal_direction, equations) + @test flux_hll(u, u, normal_direction, equations) ≈ + flux(u, normal_direction, equations) end - equations = IdealGlmMhdEquations3D(1.4, 5.0 #= c_h =#) + equations = IdealGlmMhdEquations3D(1.4, 5.0) #= c_h =# normal_directions = [SVector(1.0, 0.0, 0.0), - SVector(0.0, 1.0, 0.0), - SVector(0.0, 0.0, 1.0), - SVector(0.5, -0.5, 0.2), - SVector(-1.2, 0.3, 1.4)] + SVector(0.0, 1.0, 0.0), + SVector(0.0, 0.0, 1.0), + SVector(0.5, -0.5, 0.2), + SVector(-1.2, 0.3, 1.4)] orientations = [1, 2, 3] u_values = [SVector(1.0, 0.4, -0.5, 0.1, 1.0, 0.1, -0.2, 0.1, 0.0), - SVector(1.5, -0.2, 0.1, 0.2, 5.0, -0.1, 0.1, 0.2, 0.2),] + SVector(1.5, -0.2, 0.1, 0.2, 5.0, -0.1, 0.1, 0.2, 0.2)] for u in u_values, orientation in orientations - @test flux_hll(u, u, orientation, equations) ≈ flux(u, orientation, equations) + @test flux_hll(u, u, orientation, equations) ≈ flux(u, orientation, equations) end for u in u_values, normal_direction in normal_directions - @test flux_hll(u, u, normal_direction, equations) ≈ flux(u, normal_direction, equations) + @test flux_hll(u, u, normal_direction, equations) ≈ + flux(u, normal_direction, equations) end - end +end - @timed_testset "Consistency check for HLL flux with Davis wave speed estimates: CEE" begin +@timed_testset "Consistency check for HLL flux with Davis wave speed estimates: CEE" begin flux_hll = FluxHLL(min_max_speed_davis) # Set up equations and dummy conservative variables state @@ -719,7 +768,7 @@ isdir(outdir) && rm(outdir, recursive=true) orientations = [1] for orientation in orientations - @test flux_hll(u, u, orientation, equations) ≈ flux(u, orientation, equations) + @test flux_hll(u, u, orientation, equations) ≈ flux(u, orientation, equations) end equations = CompressibleEulerEquations2D(1.4) @@ -727,16 +776,17 @@ isdir(outdir) && rm(outdir, recursive=true) orientations = [1, 2] for orientation in orientations - @test flux_hll(u, u, orientation, equations) ≈ flux(u, orientation, equations) + @test flux_hll(u, u, orientation, equations) ≈ flux(u, orientation, equations) end normal_directions = [SVector(1.0, 0.0), - SVector(0.0, 1.0), - SVector(0.5, -0.5), - SVector(-1.2, 0.3)] + SVector(0.0, 1.0), + SVector(0.5, -0.5), + SVector(-1.2, 0.3)] for normal_direction in normal_directions - @test flux_hll(u, u, normal_direction, equations) ≈ flux(u, normal_direction, equations) + @test flux_hll(u, u, normal_direction, equations) ≈ + flux(u, normal_direction, equations) end equations = CompressibleEulerEquations3D(1.4) @@ -744,21 +794,70 @@ isdir(outdir) && rm(outdir, recursive=true) orientations = [1, 2, 3] for orientation in orientations - @test flux_hll(u, u, orientation, equations) ≈ flux(u, orientation, equations) + @test flux_hll(u, u, orientation, equations) ≈ flux(u, orientation, equations) end normal_directions = [SVector(1.0, 0.0, 0.0), - SVector(0.0, 1.0, 0.0), - SVector(0.0, 0.0, 1.0), - SVector(0.5, -0.5, 0.2), - SVector(-1.2, 0.3, 1.4)] + SVector(0.0, 1.0, 0.0), + SVector(0.0, 0.0, 1.0), + SVector(0.5, -0.5, 0.2), + SVector(-1.2, 0.3, 1.4)] for normal_direction in normal_directions - @test flux_hll(u, u, normal_direction, equations) ≈ flux(u, normal_direction, equations) + @test flux_hll(u, u, normal_direction, equations) ≈ + flux(u, normal_direction, equations) end - end +end - @timed_testset "Consistency check for HLL flux with Davis wave speed estimates: LEE" begin +@timed_testset "Consistency check for HLL flux with Davis wave speed estimates: Polytropic CEE" begin + flux_hll = FluxHLL(min_max_speed_davis) + + gamma = 1.4 + kappa = 0.5 # Scaling factor for the pressure. + equations = PolytropicEulerEquations2D(gamma, kappa) + u = SVector(1.1, -0.5, 2.34) + + orientations = [1, 2] + for orientation in orientations + @test flux_hll(u, u, orientation, equations) ≈ flux(u, orientation, equations) + end + + normal_directions = [SVector(1.0, 0.0), + SVector(0.0, 1.0), + SVector(0.5, -0.5), + SVector(-1.2, 0.3)] + + for normal_direction in normal_directions + @test flux_hll(u, u, normal_direction, equations) ≈ + flux(u, normal_direction, equations) + end +end + +@timed_testset "Consistency check for Winters flux: Polytropic CEE" begin + for gamma in [1.4, 1.0, 5 / 3] + kappa = 0.5 # Scaling factor for the pressure. + equations = PolytropicEulerEquations2D(gamma, kappa) + u = SVector(1.1, -0.5, 2.34) + + orientations = [1, 2] + for orientation in orientations + @test flux_winters_etal(u, u, orientation, equations) ≈ + flux(u, orientation, equations) + end + + normal_directions = [SVector(1.0, 0.0), + SVector(0.0, 1.0), + SVector(0.5, -0.5), + SVector(-1.2, 0.3)] + + for normal_direction in normal_directions + @test flux_winters_etal(u, u, normal_direction, equations) ≈ + flux(u, normal_direction, equations) + end + end +end + +@timed_testset "Consistency check for HLL flux with Davis wave speed estimates: LEE" begin flux_hll = FluxHLL(min_max_speed_davis) equations = LinearizedEulerEquations2D(SVector(1.0, 1.0), 1.0, 1.0) @@ -766,99 +865,103 @@ isdir(outdir) && rm(outdir, recursive=true) orientations = [1, 2] for orientation in orientations - @test flux_hll(u, u, orientation, equations) ≈ flux(u, orientation, equations) + @test flux_hll(u, u, orientation, equations) ≈ flux(u, orientation, equations) end normal_directions = [SVector(1.0, 0.0), - SVector(0.0, 1.0), - SVector(0.5, -0.5), - SVector(-1.2, 0.3)] + SVector(0.0, 1.0), + SVector(0.5, -0.5), + SVector(-1.2, 0.3)] for normal_direction in normal_directions - @test flux_hll(u, u, normal_direction, equations) ≈ flux(u, normal_direction, equations) + @test flux_hll(u, u, normal_direction, equations) ≈ + flux(u, normal_direction, equations) end - end +end - @timed_testset "Consistency check for HLL flux with Davis wave speed estimates: SWE" begin +@timed_testset "Consistency check for HLL flux with Davis wave speed estimates: SWE" begin flux_hll = FluxHLL(min_max_speed_davis) - equations = ShallowWaterEquations1D(gravity_constant=9.81) + equations = ShallowWaterEquations1D(gravity_constant = 9.81) u = SVector(1, 0.5, 0.0) @test flux_hll(u, u, 1, equations) ≈ flux(u, 1, equations) - equations = ShallowWaterEquations2D(gravity_constant=9.81) + equations = ShallowWaterEquations2D(gravity_constant = 9.81) normal_directions = [SVector(1.0, 0.0), - SVector(0.0, 1.0), - SVector(0.5, -0.5), - SVector(-1.2, 0.3)] + SVector(0.0, 1.0), + SVector(0.5, -0.5), + SVector(-1.2, 0.3)] u = SVector(1, 0.5, 0.5, 0.0) for normal_direction in normal_directions - @test flux_hll(u, u, normal_direction, equations) ≈ flux(u, normal_direction, equations) + @test flux_hll(u, u, normal_direction, equations) ≈ + flux(u, normal_direction, equations) end orientations = [1, 2] for orientation in orientations - @test flux_hll(u, u, orientation, equations) ≈ flux(u, orientation, equations) + @test flux_hll(u, u, orientation, equations) ≈ flux(u, orientation, equations) end - end +end - @timed_testset "Consistency check for HLL flux with Davis wave speed estimates: MHD" begin +@timed_testset "Consistency check for HLL flux with Davis wave speed estimates: MHD" begin flux_hll = FluxHLL(min_max_speed_davis) equations = IdealGlmMhdEquations1D(1.4) u_values = [SVector(1.0, 0.4, -0.5, 0.1, 1.0, 0.1, -0.2, 0.1), - SVector(1.5, -0.2, 0.1, 0.2, 5.0, -0.1, 0.1, 0.2),] + SVector(1.5, -0.2, 0.1, 0.2, 5.0, -0.1, 0.1, 0.2)] for u in u_values - @test flux_hll(u, u, 1, equations) ≈ flux(u, 1, equations) + @test flux_hll(u, u, 1, equations) ≈ flux(u, 1, equations) end - equations = IdealGlmMhdEquations2D(1.4, 5.0 #= c_h =#) + equations = IdealGlmMhdEquations2D(1.4, 5.0) #= c_h =# normal_directions = [SVector(1.0, 0.0), - SVector(0.0, 1.0), - SVector(0.5, -0.5), - SVector(-1.2, 0.3)] + SVector(0.0, 1.0), + SVector(0.5, -0.5), + SVector(-1.2, 0.3)] orientations = [1, 2] u_values = [SVector(1.0, 0.4, -0.5, 0.1, 1.0, 0.1, -0.2, 0.1, 0.0), - SVector(1.5, -0.2, 0.1, 0.2, 5.0, -0.1, 0.1, 0.2, 0.2),] + SVector(1.5, -0.2, 0.1, 0.2, 5.0, -0.1, 0.1, 0.2, 0.2)] for u in u_values, orientation in orientations - @test flux_hll(u, u, orientation, equations) ≈ flux(u, orientation, equations) + @test flux_hll(u, u, orientation, equations) ≈ flux(u, orientation, equations) end for u in u_values, normal_direction in normal_directions - @test flux_hll(u, u, normal_direction, equations) ≈ flux(u, normal_direction, equations) + @test flux_hll(u, u, normal_direction, equations) ≈ + flux(u, normal_direction, equations) end - equations = IdealGlmMhdEquations3D(1.4, 5.0 #= c_h =#) + equations = IdealGlmMhdEquations3D(1.4, 5.0) #= c_h =# normal_directions = [SVector(1.0, 0.0, 0.0), - SVector(0.0, 1.0, 0.0), - SVector(0.0, 0.0, 1.0), - SVector(0.5, -0.5, 0.2), - SVector(-1.2, 0.3, 1.4)] + SVector(0.0, 1.0, 0.0), + SVector(0.0, 0.0, 1.0), + SVector(0.5, -0.5, 0.2), + SVector(-1.2, 0.3, 1.4)] orientations = [1, 2, 3] u_values = [SVector(1.0, 0.4, -0.5, 0.1, 1.0, 0.1, -0.2, 0.1, 0.0), - SVector(1.5, -0.2, 0.1, 0.2, 5.0, -0.1, 0.1, 0.2, 0.2),] + SVector(1.5, -0.2, 0.1, 0.2, 5.0, -0.1, 0.1, 0.2, 0.2)] for u in u_values, orientation in orientations - @test flux_hll(u, u, orientation, equations) ≈ flux(u, orientation, equations) + @test flux_hll(u, u, orientation, equations) ≈ flux(u, orientation, equations) end for u in u_values, normal_direction in normal_directions - @test flux_hll(u, u, normal_direction, equations) ≈ flux(u, normal_direction, equations) + @test flux_hll(u, u, normal_direction, equations) ≈ + flux(u, normal_direction, equations) end - end +end - @timed_testset "Consistency check for HLLE flux: CEE" begin +@timed_testset "Consistency check for HLLE flux: CEE" begin # Set up equations and dummy conservative variables state equations = CompressibleEulerEquations1D(1.4) u = SVector(1.1, 2.34, 5.5) orientations = [1] for orientation in orientations - @test flux_hlle(u, u, orientation, equations) ≈ flux(u, orientation, equations) + @test flux_hlle(u, u, orientation, equations) ≈ flux(u, orientation, equations) end equations = CompressibleEulerEquations2D(1.4) @@ -866,16 +969,17 @@ isdir(outdir) && rm(outdir, recursive=true) orientations = [1, 2] for orientation in orientations - @test flux_hlle(u, u, orientation, equations) ≈ flux(u, orientation, equations) + @test flux_hlle(u, u, orientation, equations) ≈ flux(u, orientation, equations) end normal_directions = [SVector(1.0, 0.0), - SVector(0.0, 1.0), - SVector(0.5, -0.5), - SVector(-1.2, 0.3)] + SVector(0.0, 1.0), + SVector(0.5, -0.5), + SVector(-1.2, 0.3)] for normal_direction in normal_directions - @test flux_hll(u, u, normal_direction, equations) ≈ flux(u, normal_direction, equations) + @test flux_hlle(u, u, normal_direction, equations) ≈ + flux(u, normal_direction, equations) end equations = CompressibleEulerEquations3D(1.4) @@ -883,97 +987,96 @@ isdir(outdir) && rm(outdir, recursive=true) orientations = [1, 2, 3] for orientation in orientations - @test flux_hlle(u, u, orientation, equations) ≈ flux(u, orientation, equations) + @test flux_hlle(u, u, orientation, equations) ≈ flux(u, orientation, equations) end normal_directions = [SVector(1.0, 0.0, 0.0), - SVector(0.0, 1.0, 0.0), - SVector(0.0, 0.0, 1.0), - SVector(0.5, -0.5, 0.2), - SVector(-1.2, 0.3, 1.4)] + SVector(0.0, 1.0, 0.0), + SVector(0.0, 0.0, 1.0), + SVector(0.5, -0.5, 0.2), + SVector(-1.2, 0.3, 1.4)] for normal_direction in normal_directions - @test flux_hll(u, u, normal_direction, equations) ≈ flux(u, normal_direction, equations) + @test flux_hlle(u, u, normal_direction, equations) ≈ + flux(u, normal_direction, equations) end - end - - @timed_testset "Consistency check for HLLE flux: SWE" begin - # Test HLL flux with min_max_speed_einfeldt - flux_hll = FluxHLL(min_max_speed_einfeldt) +end - equations = ShallowWaterEquations1D(gravity_constant=9.81) +@timed_testset "Consistency check for HLLE flux: SWE" begin + equations = ShallowWaterEquations1D(gravity_constant = 9.81) u = SVector(1, 0.5, 0.0) - @test flux_hll(u, u, 1, equations) ≈ flux(u, 1, equations) + @test flux_hlle(u, u, 1, equations) ≈ flux(u, 1, equations) - equations = ShallowWaterEquations2D(gravity_constant=9.81) + equations = ShallowWaterEquations2D(gravity_constant = 9.81) normal_directions = [SVector(1.0, 0.0), - SVector(0.0, 1.0), - SVector(0.5, -0.5), - SVector(-1.2, 0.3)] + SVector(0.0, 1.0), + SVector(0.5, -0.5), + SVector(-1.2, 0.3)] orientations = [1, 2] u = SVector(1, 0.5, 0.5, 0.0) for orientation in orientations - @test flux_hll(u, u, orientation, equations) ≈ flux(u, orientation, equations) + @test flux_hlle(u, u, orientation, equations) ≈ flux(u, orientation, equations) end for normal_direction in normal_directions - @test flux_hll(u, u, normal_direction, equations) ≈ flux(u, normal_direction, equations) + @test flux_hlle(u, u, normal_direction, equations) ≈ + flux(u, normal_direction, equations) end - end - - @timed_testset "Consistency check for HLLE flux: MHD" begin - # Test HLL flux with min_max_speed_einfeldt - flux_hll = FluxHLL(min_max_speed_naive) +end +@timed_testset "Consistency check for HLLE flux: MHD" begin equations = IdealGlmMhdEquations1D(1.4) u_values = [SVector(1.0, 0.4, -0.5, 0.1, 1.0, 0.1, -0.2, 0.1), - SVector(1.5, -0.2, 0.1, 0.2, 5.0, -0.1, 0.1, 0.2),] + SVector(1.5, -0.2, 0.1, 0.2, 5.0, -0.1, 0.1, 0.2)] for u in u_values - @test flux_hll(u, u, 1, equations) ≈ flux(u, 1, equations) + @test flux_hlle(u, u, 1, equations) ≈ flux(u, 1, equations) + @test flux_hllc(u, u, 1, equations) ≈ flux(u, 1, equations) end - equations = IdealGlmMhdEquations2D(1.4, 5.0 #= c_h =#) + equations = IdealGlmMhdEquations2D(1.4, 5.0) #= c_h =# normal_directions = [SVector(1.0, 0.0), - SVector(0.0, 1.0), - SVector(0.5, -0.5), - SVector(-1.2, 0.3)] + SVector(0.0, 1.0), + SVector(0.5, -0.5), + SVector(-1.2, 0.3)] orientations = [1, 2] u_values = [SVector(1.0, 0.4, -0.5, 0.1, 1.0, 0.1, -0.2, 0.1, 0.0), - SVector(1.5, -0.2, 0.1, 0.2, 5.0, -0.1, 0.1, 0.2, 0.2),] + SVector(1.5, -0.2, 0.1, 0.2, 5.0, -0.1, 0.1, 0.2, 0.2)] for u in u_values, orientation in orientations - @test flux_hll(u, u, orientation, equations) ≈ flux(u, orientation, equations) + @test flux_hlle(u, u, orientation, equations) ≈ flux(u, orientation, equations) end for u in u_values, normal_direction in normal_directions - @test flux_hll(u, u, normal_direction, equations) ≈ flux(u, normal_direction, equations) + @test flux_hlle(u, u, normal_direction, equations) ≈ + flux(u, normal_direction, equations) end - equations = IdealGlmMhdEquations3D(1.4, 5.0 #= c_h =#) + equations = IdealGlmMhdEquations3D(1.4, 5.0) #= c_h =# normal_directions = [SVector(1.0, 0.0, 0.0), - SVector(0.0, 1.0, 0.0), - SVector(0.0, 0.0, 1.0), - SVector(0.5, -0.5, 0.2), - SVector(-1.2, 0.3, 1.4)] + SVector(0.0, 1.0, 0.0), + SVector(0.0, 0.0, 1.0), + SVector(0.5, -0.5, 0.2), + SVector(-1.2, 0.3, 1.4)] orientations = [1, 2, 3] u_values = [SVector(1.0, 0.4, -0.5, 0.1, 1.0, 0.1, -0.2, 0.1, 0.0), - SVector(1.5, -0.2, 0.1, 0.2, 5.0, -0.1, 0.1, 0.2, 0.2),] + SVector(1.5, -0.2, 0.1, 0.2, 5.0, -0.1, 0.1, 0.2, 0.2)] for u in u_values, orientation in orientations - @test flux_hll(u, u, orientation, equations) ≈ flux(u, orientation, equations) + @test flux_hlle(u, u, orientation, equations) ≈ flux(u, orientation, equations) end for u in u_values, normal_direction in normal_directions - @test flux_hll(u, u, normal_direction, equations) ≈ flux(u, normal_direction, equations) + @test flux_hlle(u, u, normal_direction, equations) ≈ + flux(u, normal_direction, equations) end - end +end - @timed_testset "Consistency check for Godunov flux" begin +@timed_testset "Consistency check for Godunov flux" begin # Set up equations and dummy conservative variables state # Burgers' Equation @@ -982,7 +1085,7 @@ isdir(outdir) && rm(outdir, recursive=true) orientations = [1] for orientation in orientations, u in u_values - @test flux_godunov(u, u, orientation, equation) ≈ flux(u, orientation, equation) + @test flux_godunov(u, u, orientation, equation) ≈ flux(u, orientation, equation) end # Linear Advection 1D @@ -991,7 +1094,7 @@ isdir(outdir) && rm(outdir, recursive=true) orientations = [1] for orientation in orientations - @test flux_godunov(u, u, orientation, equation) ≈ flux(u, orientation, equation) + @test flux_godunov(u, u, orientation, equation) ≈ flux(u, orientation, equation) end # Linear Advection 2D @@ -1000,16 +1103,17 @@ isdir(outdir) && rm(outdir, recursive=true) orientations = [1, 2] for orientation in orientations - @test flux_godunov(u, u, orientation, equation) ≈ flux(u, orientation, equation) + @test flux_godunov(u, u, orientation, equation) ≈ flux(u, orientation, equation) end normal_directions = [SVector(1.0, 0.0), - SVector(0.0, 1.0), - SVector(0.5, -0.5), - SVector(-1.2, 0.3)] + SVector(0.0, 1.0), + SVector(0.5, -0.5), + SVector(-1.2, 0.3)] for normal_direction in normal_directions - @test flux_godunov(u, u, normal_direction, equation) ≈ flux(u, normal_direction, equation) + @test flux_godunov(u, u, normal_direction, equation) ≈ + flux(u, normal_direction, equation) end # Linear Advection 3D @@ -1018,48 +1122,52 @@ isdir(outdir) && rm(outdir, recursive=true) orientations = [1, 2, 3] for orientation in orientations - @test flux_godunov(u, u, orientation, equation) ≈ flux(u, orientation, equation) + @test flux_godunov(u, u, orientation, equation) ≈ flux(u, orientation, equation) end normal_directions = [SVector(1.0, 0.0, 0.0), - SVector(0.0, 1.0, 0.0), - SVector(0.0, 0.0, 1.0), - SVector(0.5, -0.5, 0.2), - SVector(-1.2, 0.3, 1.4)] + SVector(0.0, 1.0, 0.0), + SVector(0.0, 0.0, 1.0), + SVector(0.5, -0.5, 0.2), + SVector(-1.2, 0.3, 1.4)] for normal_direction in normal_directions - @test flux_godunov(u, u, normal_direction, equation) ≈ flux(u, normal_direction, equation) + @test flux_godunov(u, u, normal_direction, equation) ≈ + flux(u, normal_direction, equation) end # Linearized Euler 2D - equation = LinearizedEulerEquations2D(v_mean_global=(0.5, -0.7), c_mean_global=1.1, - rho_mean_global=1.2) + equation = LinearizedEulerEquations2D(v_mean_global = (0.5, -0.7), + c_mean_global = 1.1, + rho_mean_global = 1.2) u_values = [SVector(1.0, 0.5, -0.7, 1.0), - SVector(1.5, -0.2, 0.1, 5.0),] + SVector(1.5, -0.2, 0.1, 5.0)] orientations = [1, 2] for orientation in orientations, u in u_values - @test flux_godunov(u, u, orientation, equation) ≈ flux(u, orientation, equation) + @test flux_godunov(u, u, orientation, equation) ≈ flux(u, orientation, equation) end normal_directions = [SVector(1.0, 0.0), - SVector(0.0, 1.0), - SVector(0.5, -0.5), - SVector(-1.2, 0.3)] + SVector(0.0, 1.0), + SVector(0.5, -0.5), + SVector(-1.2, 0.3)] for normal_direction in normal_directions, u in u_values - @test flux_godunov(u, u, normal_direction, equation) ≈ flux(u, normal_direction, equation) + @test flux_godunov(u, u, normal_direction, equation) ≈ + flux(u, normal_direction, equation) end - end +end - @timed_testset "Consistency check for Engquist-Osher flux" begin +@timed_testset "Consistency check for Engquist-Osher flux" begin # Set up equations and dummy conservative variables state equation = InviscidBurgersEquation1D() u_values = [SVector(42.0), SVector(-42.0)] orientations = [1] for orientation in orientations, u in u_values - @test Trixi.flux_engquist_osher(u, u, orientation, equation) ≈ flux(u, orientation, equation) + @test Trixi.flux_engquist_osher(u, u, orientation, equation) ≈ + flux(u, orientation, equation) end equation = LinearScalarAdvectionEquation1D(-4.2) @@ -1067,11 +1175,12 @@ isdir(outdir) && rm(outdir, recursive=true) orientations = [1] for orientation in orientations - @test Trixi.flux_engquist_osher(u, u, orientation, equation) ≈ flux(u, orientation, equation) + @test Trixi.flux_engquist_osher(u, u, orientation, equation) ≈ + flux(u, orientation, equation) end - end +end - @testset "Equivalent Fluxes" begin +@testset "Equivalent Fluxes" begin # Set up equations and dummy conservative variables state # Burgers' Equation @@ -1080,7 +1189,8 @@ isdir(outdir) && rm(outdir, recursive=true) orientations = [1] for orientation in orientations, u in u_values - @test flux_godunov(0.75*u, u, orientation, equation) ≈ Trixi.flux_engquist_osher(0.75*u, u, orientation, equation) + @test flux_godunov(0.75 * u, u, orientation, equation) ≈ + Trixi.flux_engquist_osher(0.75 * u, u, orientation, equation) end # Linear Advection 1D @@ -1089,8 +1199,10 @@ isdir(outdir) && rm(outdir, recursive=true) orientations = [1] for orientation in orientations - @test flux_godunov(0.5*u, u, orientation, equation) ≈ flux_lax_friedrichs(0.5*u, u, orientation, equation) - @test flux_godunov(2*u, u, orientation, equation) ≈ Trixi.flux_engquist_osher(2*u, u, orientation, equation) + @test flux_godunov(0.5 * u, u, orientation, equation) ≈ + flux_lax_friedrichs(0.5 * u, u, orientation, equation) + @test flux_godunov(2 * u, u, orientation, equation) ≈ + Trixi.flux_engquist_osher(2 * u, u, orientation, equation) end # Linear Advection 2D @@ -1099,16 +1211,18 @@ isdir(outdir) && rm(outdir, recursive=true) orientations = [1, 2] for orientation in orientations - @test flux_godunov(0.25*u, u, orientation, equation) ≈ flux_lax_friedrichs(0.25*u, u, orientation, equation) + @test flux_godunov(0.25 * u, u, orientation, equation) ≈ + flux_lax_friedrichs(0.25 * u, u, orientation, equation) end normal_directions = [SVector(1.0, 0.0), - SVector(0.0, 1.0), - SVector(0.5, -0.5), - SVector(-1.2, 0.3)] + SVector(0.0, 1.0), + SVector(0.5, -0.5), + SVector(-1.2, 0.3)] for normal_direction in normal_directions - @test flux_godunov(3*u, u, normal_direction, equation) ≈ flux_lax_friedrichs(3*u, u, normal_direction, equation) + @test flux_godunov(3 * u, u, normal_direction, equation) ≈ + flux_lax_friedrichs(3 * u, u, normal_direction, equation) end # Linear Advection 3D @@ -1117,113 +1231,160 @@ isdir(outdir) && rm(outdir, recursive=true) orientations = [1, 2, 3] for orientation in orientations - @test flux_godunov(1.5*u, u, orientation, equation) ≈ flux_lax_friedrichs(1.5*u, u, orientation, equation) + @test flux_godunov(1.5 * u, u, orientation, equation) ≈ + flux_lax_friedrichs(1.5 * u, u, orientation, equation) end normal_directions = [SVector(1.0, 0.0, 0.0), - SVector(0.0, 1.0, 0.0), - SVector(0.0, 0.0, 1.0), - SVector(0.5, -0.5, 0.2), - SVector(-1.2, 0.3, 1.4)] + SVector(0.0, 1.0, 0.0), + SVector(0.0, 0.0, 1.0), + SVector(0.5, -0.5, 0.2), + SVector(-1.2, 0.3, 1.4)] for normal_direction in normal_directions - @test flux_godunov(1.3*u, u, normal_direction, equation) ≈ flux_lax_friedrichs(1.3*u, u, normal_direction, equation) + @test flux_godunov(1.3 * u, u, normal_direction, equation) ≈ + flux_lax_friedrichs(1.3 * u, u, normal_direction, equation) end - end +end - @testset "FluxRotated vs. direct implementation" begin - @timed_testset "CompressibleEulerEquations2D" begin - equations = CompressibleEulerEquations2D(1.4) - normal_directions = [SVector(1.0, 0.0), - SVector(0.0, 1.0), - SVector(0.5, -0.5), - SVector(-1.2, 0.3)] - u_values = [SVector(1.0, 0.5, -0.7, 1.0), - SVector(1.5, -0.2, 0.1, 5.0),] - fluxes = [flux_central, flux_ranocha, flux_shima_etal, flux_kennedy_gruber, - flux_hll, FluxHLL(min_max_speed_davis)] - - for f_std in fluxes +@testset "FluxRotated vs. direct implementation" begin + @timed_testset "CompressibleEulerMulticomponentEquations2D" begin + equations = CompressibleEulerMulticomponentEquations2D(gammas = (1.4, 1.4), + gas_constants = (0.4, + 0.4)) + normal_directions = [SVector(1.0, 0.0), + SVector(0.0, 1.0), + SVector(0.5, -0.5), + SVector(-1.2, 0.3)] + u_values = [SVector(0.1, -0.5, 1.0, 1.0, 2.0), + SVector(-0.1, -0.3, 1.2, 1.3, 1.4)] + + f_std = flux f_rot = FluxRotated(f_std) - for u_ll in u_values, u_rr in u_values, normal_direction in normal_directions - @test f_rot(u_ll, u_rr, normal_direction, equations) ≈ f_std(u_ll, u_rr, normal_direction, equations) + println(typeof(f_std)) + println(typeof(f_rot)) + for u in u_values, + normal_direction in normal_directions + + @test f_rot(u, normal_direction, equations) ≈ + f_std(u, normal_direction, equations) + end + end + + @timed_testset "CompressibleEulerEquations2D" begin + equations = CompressibleEulerEquations2D(1.4) + normal_directions = [SVector(1.0, 0.0), + SVector(0.0, 1.0), + SVector(0.5, -0.5), + SVector(-1.2, 0.3)] + u_values = [SVector(1.0, 0.5, -0.7, 1.0), + SVector(1.5, -0.2, 0.1, 5.0)] + fluxes = [flux_central, flux_ranocha, flux_shima_etal, flux_kennedy_gruber, + flux_hll, FluxHLL(min_max_speed_davis), flux_hlle] + + for f_std in fluxes + f_rot = FluxRotated(f_std) + for u_ll in u_values, u_rr in u_values, + normal_direction in normal_directions + + @test f_rot(u_ll, u_rr, normal_direction, equations) ≈ + f_std(u_ll, u_rr, normal_direction, equations) + end end - end end @timed_testset "CompressibleEulerEquations3D" begin - equations = CompressibleEulerEquations3D(1.4) - normal_directions = [SVector(1.0, 0.0, 0.0), - SVector(0.0, 1.0, 0.0), - SVector(0.0, 0.0, 1.0), - SVector(0.5, -0.5, 0.2), - SVector(-1.2, 0.3, 1.4)] - u_values = [SVector(1.0, 0.5, -0.7, 0.1, 1.0), - SVector(1.5, -0.2, 0.1, 0.2, 5.0),] - fluxes = [flux_central, flux_ranocha, flux_shima_etal, flux_kennedy_gruber, FluxLMARS(340), - flux_hll, FluxHLL(min_max_speed_davis)] - - for f_std in fluxes - f_rot = FluxRotated(f_std) - for u_ll in u_values, u_rr in u_values, normal_direction in normal_directions - @test f_rot(u_ll, u_rr, normal_direction, equations) ≈ f_std(u_ll, u_rr, normal_direction, equations) + equations = CompressibleEulerEquations3D(1.4) + normal_directions = [SVector(1.0, 0.0, 0.0), + SVector(0.0, 1.0, 0.0), + SVector(0.0, 0.0, 1.0), + SVector(0.5, -0.5, 0.2), + SVector(-1.2, 0.3, 1.4)] + u_values = [SVector(1.0, 0.5, -0.7, 0.1, 1.0), + SVector(1.5, -0.2, 0.1, 0.2, 5.0)] + fluxes = [flux_central, flux_ranocha, flux_shima_etal, flux_kennedy_gruber, + FluxLMARS(340), + flux_hll, FluxHLL(min_max_speed_davis), flux_hlle] + + for f_std in fluxes + f_rot = FluxRotated(f_std) + for u_ll in u_values, u_rr in u_values, + normal_direction in normal_directions + + @test f_rot(u_ll, u_rr, normal_direction, equations) ≈ + f_std(u_ll, u_rr, normal_direction, equations) + end end - end end @timed_testset "ShallowWaterEquations2D" begin - equations = ShallowWaterEquations2D(gravity_constant=9.81) - normal_directions = [SVector(1.0, 0.0), - SVector(0.0, 1.0), - SVector(0.5, -0.5), - SVector(-1.2, 0.3)] - - u = SVector(1, 0.5, 0.5, 0.0) + equations = ShallowWaterEquations2D(gravity_constant = 9.81) + normal_directions = [SVector(1.0, 0.0), + SVector(0.0, 1.0), + SVector(0.5, -0.5), + SVector(-1.2, 0.3)] - fluxes = [flux_central, flux_fjordholm_etal, flux_wintermeyer_etal, - flux_hll, FluxHLL(min_max_speed_davis), FluxHLL(min_max_speed_einfeldt)] + u = SVector(1, 0.5, 0.5, 0.0) + fluxes = [flux_central, flux_fjordholm_etal, flux_wintermeyer_etal, + flux_hll, FluxHLL(min_max_speed_davis), flux_hlle] end @timed_testset "IdealGlmMhdEquations2D" begin - equations = IdealGlmMhdEquations2D(1.4, 5.0 #= c_h =#) - normal_directions = [SVector(1.0, 0.0), - SVector(0.0, 1.0), - SVector(0.5, -0.5), - SVector(-1.2, 0.3)] - u_values = [SVector(1.0, 0.4, -0.5, 0.1, 1.0, 0.1, -0.2, 0.1, 0.0), - SVector(1.5, -0.2, 0.1, 0.2, 5.0, -0.1, 0.1, 0.2, 0.2),] - fluxes = [flux_central, flux_hindenlang_gassner, flux_hll, FluxHLL(min_max_speed_davis)] - - for f_std in fluxes - f_rot = FluxRotated(f_std) - for u_ll in u_values, u_rr in u_values, normal_direction in normal_directions - @test f_rot(u_ll, u_rr, normal_direction, equations) ≈ f_std(u_ll, u_rr, normal_direction, equations) + equations = IdealGlmMhdEquations2D(1.4, 5.0) #= c_h =# + normal_directions = [SVector(1.0, 0.0), + SVector(0.0, 1.0), + SVector(0.5, -0.5), + SVector(-1.2, 0.3)] + u_values = [SVector(1.0, 0.4, -0.5, 0.1, 1.0, 0.1, -0.2, 0.1, 0.0), + SVector(1.5, -0.2, 0.1, 0.2, 5.0, -0.1, 0.1, 0.2, 0.2)] + fluxes = [ + flux_central, + flux_hindenlang_gassner, + FluxHLL(min_max_speed_davis), + flux_hlle, + ] + + for f_std in fluxes + f_rot = FluxRotated(f_std) + for u_ll in u_values, u_rr in u_values, + normal_direction in normal_directions + + @test f_rot(u_ll, u_rr, normal_direction, equations) ≈ + f_std(u_ll, u_rr, normal_direction, equations) + end end - end end @timed_testset "IdealGlmMhdEquations3D" begin - equations = IdealGlmMhdEquations3D(1.4, 5.0 #= c_h =#) - normal_directions = [SVector(1.0, 0.0, 0.0), - SVector(0.0, 1.0, 0.0), - SVector(0.0, 0.0, 1.0), - SVector(0.5, -0.5, 0.2), - SVector(-1.2, 0.3, 1.4)] - u_values = [SVector(1.0, 0.4, -0.5, 0.1, 1.0, 0.1, -0.2, 0.1, 0.0), - SVector(1.5, -0.2, 0.1, 0.2, 5.0, -0.1, 0.1, 0.2, 0.2),] - fluxes = [flux_central, flux_hindenlang_gassner, flux_hll, FluxHLL(min_max_speed_davis)] - - for f_std in fluxes - f_rot = FluxRotated(f_std) - for u_ll in u_values, u_rr in u_values, normal_direction in normal_directions - @test f_rot(u_ll, u_rr, normal_direction, equations) ≈ f_std(u_ll, u_rr, normal_direction, equations) + equations = IdealGlmMhdEquations3D(1.4, 5.0) #= c_h =# + normal_directions = [SVector(1.0, 0.0, 0.0), + SVector(0.0, 1.0, 0.0), + SVector(0.0, 0.0, 1.0), + SVector(0.5, -0.5, 0.2), + SVector(-1.2, 0.3, 1.4)] + u_values = [SVector(1.0, 0.4, -0.5, 0.1, 1.0, 0.1, -0.2, 0.1, 0.0), + SVector(1.5, -0.2, 0.1, 0.2, 5.0, -0.1, 0.1, 0.2, 0.2)] + fluxes = [ + flux_central, + flux_hindenlang_gassner, + FluxHLL(min_max_speed_davis), + flux_hlle, + ] + + for f_std in fluxes + f_rot = FluxRotated(f_std) + for u_ll in u_values, u_rr in u_values, + normal_direction in normal_directions + + @test f_rot(u_ll, u_rr, normal_direction, equations) ≈ + f_std(u_ll, u_rr, normal_direction, equations) + end end - end end - end +end - @testset "SimpleKronecker" begin +@testset "SimpleKronecker" begin N = 3 NDIMS = 2 @@ -1240,30 +1401,126 @@ isdir(outdir) && rm(outdir, recursive=true) Trixi.mul!(b, V, x) Trixi.mul!(b_kron, V_kron, x) @test b ≈ b_kron - end +end - @testset "SummationByPartsOperators + StartUpDG" begin - dg = DGMulti(polydeg = 3, element_type = Quad(), - approximation_type = derivative_operator( - SummationByPartsOperators.MattssonNordström2004(), - derivative_order=1, accuracy_order=4, - xmin=0.0, xmax=1.0, N=10)) +@testset "SummationByPartsOperators + StartUpDG" begin + global D = derivative_operator(SummationByPartsOperators.MattssonNordström2004(), + derivative_order = 1, + accuracy_order = 4, + xmin = 0.0, xmax = 1.0, + N = 10) + dg = DGMulti(polydeg = 3, element_type = Quad(), approximation_type = D) @test StartUpDG.inverse_trace_constant(dg.basis) ≈ 50.8235294117647 - end +end - @testset "1D non-periodic DGMultiMesh" begin +@testset "1D non-periodic DGMultiMesh" begin # checks whether or not boundary faces are initialized correctly for DGMultiMesh in 1D dg = DGMulti(polydeg = 1, element_type = Line(), approximation_type = Polynomial(), surface_integral = SurfaceIntegralWeakForm(flux_central), volume_integral = VolumeIntegralFluxDifferencing(flux_central)) - mesh = DGMultiMesh(dg, cells_per_dimension=(1,), periodicity=false) + cells_per_dimension = (1,) + mesh = DGMultiMesh(dg, cells_per_dimension, periodicity = false) @test mesh.boundary_faces[:entire_boundary] == [1, 2] - end - end +@testset "trixi_include" begin + @trixi_testset "Basic" begin + example = """ + x = 4 + """ + + filename = tempname() + try + open(filename, "w") do file + write(file, example) + end + + # Use `@trixi_testset`, which wraps code in a temporary module, and call + # `trixi_include` with `@__MODULE__` in order to isolate this test. + @test_warn "You just called" trixi_include(@__MODULE__, filename) + @test @isdefined x + @test x == 4 + + @test_warn "You just called" trixi_include(@__MODULE__, filename, x = 7) + @test x == 7 + + @test_throws "assignment `y` not found in expression" trixi_include(@__MODULE__, + filename, + y = 3) + finally + rm(filename, force = true) + end + end + + @trixi_testset "With `solve` Without `maxiters`" begin + # `trixi_include` assumes this to be the `solve` function of OrdinaryDiffEq, + # and therefore tries to insert the kwarg `maxiters`, which will fail here. + example = """ + solve() = 0 + x = solve() + """ + + filename = tempname() + try + open(filename, "w") do file + write(file, example) + end + + # Use `@trixi_testset`, which wraps code in a temporary module, and call + # `trixi_include` with `@__MODULE__` in order to isolate this test. + @test_throws "no method matching solve(; maxiters::Int64)" trixi_include(@__MODULE__, + filename) + + @test_throws "no method matching solve(; maxiters::Int64)" trixi_include(@__MODULE__, + filename, + maxiters = 3) + finally + rm(filename, force = true) + end + end + @trixi_testset "With `solve` with `maxiters`" begin + # We need another example file that we include with `Base.include` first, in order to + # define the `solve` method without `trixi_include` trying to insert `maxiters` kwargs. + # Then, we can test that `trixi_include` inserts the kwarg in the `solve()` call. + example1 = """ + solve(; maxiters=0) = maxiters + """ + + example2 = """ + x = solve() + """ + + filename1 = tempname() + filename2 = tempname() + try + open(filename1, "w") do file + write(file, example1) + end + open(filename2, "w") do file + write(file, example2) + end + + # Use `@trixi_testset`, which wraps code in a temporary module, and call + # `Base.include` and `trixi_include` with `@__MODULE__` in order to isolate this test. + Base.include(@__MODULE__, filename1) + @test_warn "You just called" trixi_include(@__MODULE__, filename2) + @test @isdefined x + # This is the default `maxiters` inserted by `trixi_include` + @test x == 10^5 + + @test_warn "You just called" trixi_include(@__MODULE__, filename2, + maxiters = 7) + # Test that `maxiters` got overwritten + @test x == 7 + finally + rm(filename1, force = true) + rm(filename2, force = true) + end + end +end +end end #module diff --git a/test/test_unstructured_2d.jl b/test/test_unstructured_2d.jl index fbe88a2a0a3..139b423ead1 100644 --- a/test/test_unstructured_2d.jl +++ b/test/test_unstructured_2d.jl @@ -11,202 +11,723 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "unstructured_2d_dgsem") # Start with a clean environment: remove Trixi.jl output directory if it exists outdir = "out" -isdir(outdir) && rm(outdir, recursive=true) +isdir(outdir) && rm(outdir, recursive = true) @testset "UnstructuredMesh2D" begin - @trixi_testset "elixir_euler_periodic.jl" begin +#! format: noindent + +@trixi_testset "elixir_euler_periodic.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_periodic.jl"), - l2 = [0.00010978828464875207, 0.00013010359527356914, 0.00013010359527326057, 0.0002987656724828824], - linf = [0.00638626102818618, 0.009804042508242183, 0.009804042508253286, 0.02183139311614468]) - end + l2=[ + 0.00010978828464875207, + 0.00013010359527356914, + 0.00013010359527326057, + 0.0002987656724828824, + ], + linf=[ + 0.00638626102818618, + 0.009804042508242183, + 0.009804042508253286, + 0.02183139311614468, + ]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_free_stream.jl" begin +@trixi_testset "elixir_euler_free_stream.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_free_stream.jl"), - l2 = [3.3937971107485363e-14, 2.447586447887882e-13, 1.4585205789296455e-13, 4.716993468962946e-13], - linf = [8.804734719092266e-12, 6.261270668606045e-11, 2.93670088247211e-11, 1.205400224080222e-10], - tspan = (0.0, 0.1), - atol = 3.0e-13) - end + l2=[ + 3.3937971107485363e-14, + 2.447586447887882e-13, + 1.4585205789296455e-13, + 4.716993468962946e-13, + ], + linf=[ + 8.804734719092266e-12, + 6.261270668606045e-11, + 2.93670088247211e-11, + 1.205400224080222e-10, + ], + tspan=(0.0, 0.1), + atol=3.0e-13) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_wall_bc.jl" begin +@trixi_testset "elixir_euler_wall_bc.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_wall_bc.jl"), - l2 = [0.040189107976346644, 0.04256154998030852, 0.03734120743842209, 0.10057425897733507], - linf = [0.24455374304626365, 0.2970686406973577, 0.29339040847600434, 0.5915610037764794], - tspan = (0.0, 0.25)) - end + l2=[ + 0.040189107976346644, + 0.04256154998030852, + 0.03734120743842209, + 0.10057425897733507, + ], + linf=[ + 0.24455374304626365, + 0.2970686406973577, + 0.29339040847600434, + 0.5915610037764794, + ], + tspan=(0.0, 0.25)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_basic.jl" begin +@trixi_testset "elixir_euler_basic.jl" begin @test_trixi_include(default_example_unstructured(), - l2 = [0.0007213418215265047, 0.0006752337675043779, 0.0006437485997536973, 0.0014782883071363362], - linf = [0.004301288971032324, 0.005243995459478956, 0.004685630332338153, 0.01750217718347713], - tspan = (0.0, 1.0)) - end + l2=[ + 0.0007213418215265047, + 0.0006752337675043779, + 0.0006437485997536973, + 0.0014782883071363362, + ], + linf=[ + 0.004301288971032324, + 0.005243995459478956, + 0.004685630332338153, + 0.01750217718347713, + ], + tspan=(0.0, 1.0)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_restart.jl" begin +@trixi_testset "elixir_euler_restart.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_restart.jl"), - l2 = [0.0007213418215265047, 0.0006752337675043779, 0.0006437485997536973, 0.0014782883071363362], - linf = [0.004301288971032324, 0.005243995459478956, 0.004685630332338153, 0.01750217718347713]) - end + l2=[ + 0.0007213418215265047, + 0.0006752337675043779, + 0.0006437485997536973, + 0.0014782883071363362, + ], + linf=[ + 0.004301288971032324, + 0.005243995459478956, + 0.004685630332338153, + 0.01750217718347713, + ], + # With the default `maxiters = 1` in coverage tests, + # there would be no time steps after the restart. + coverage_override=(maxiters = 100_000,)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_ec.jl" begin +@trixi_testset "elixir_euler_ec.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_ec.jl"), - l2 = [0.06594600495903137, 0.10803914821786433, 0.10805946357846291, 0.1738171782368222], - linf = [0.31880214280781305, 0.3468488554333352, 0.34592958184413264, 0.784555926860546], - tspan = (0.0, 1.0)) - end + l2=[ + 0.06594600495903137, + 0.10803914821786433, + 0.10805946357846291, + 0.1738171782368222, + ], + linf=[ + 0.31880214280781305, + 0.3468488554333352, + 0.34592958184413264, + 0.784555926860546, + ], + tspan=(0.0, 1.0)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_advection_basic.jl" begin +@trixi_testset "elixir_advection_basic.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_basic.jl"), - l2 = [0.00018729339078205488], - linf = [0.0018997287705734278]) - end + l2=[0.00018729339078205488], + linf=[0.0018997287705734278]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_euler_sedov.jl" begin +@trixi_testset "elixir_euler_sedov.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov.jl"), - l2 = [2.19945600e-01, 1.71050453e-01, 1.71050453e-01, 1.21719195e+00], - linf = [7.44218635e-01, 7.02887039e-01, 7.02887039e-01, 6.11732719e+00], - tspan = (0.0, 0.3)) - end + l2=[ + 2.19945600e-01, + 1.71050453e-01, + 1.71050453e-01, + 1.21719195e+00, + ], + linf=[ + 7.44218635e-01, + 7.02887039e-01, + 7.02887039e-01, + 6.11732719e+00, + ], + tspan=(0.0, 0.3)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_acoustics_gauss_wall.jl" begin +@trixi_testset "elixir_acoustics_gauss_wall.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_acoustics_gauss_wall.jl"), - l2 = [0.029330394861252995, 0.029345079728907965, 0.03803795043486467, 0.0, - 7.175152371650832e-16, 1.4350304743301665e-15, 1.4350304743301665e-15], - linf = [0.36236334472179443, 0.3690785638275256, 0.8475748723784078, 0.0, - 8.881784197001252e-16, 1.7763568394002505e-15, 1.7763568394002505e-15], - tspan = (0.0, 5.0)) - end - - @trixi_testset "elixir_mhd_ec.jl" begin + l2=[0.029330394861252995, 0.029345079728907965, + 0.03803795043486467, 0.0, + 7.175152371650832e-16, 1.4350304743301665e-15, + 1.4350304743301665e-15], + linf=[0.36236334472179443, 0.3690785638275256, + 0.8475748723784078, 0.0, + 8.881784197001252e-16, 1.7763568394002505e-15, + 1.7763568394002505e-15], + tspan=(0.0, 5.0)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_mhd_ec.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_ec.jl"), - l2 = [0.06418293357851637, 0.12085176618704108, 0.12085099342419513, 0.07743005602933221, - 0.1622218916638482, 0.04044434425257972, 0.04044440614962498, 0.05735896706356321, - 0.0020992340041681734], - linf = [0.1417000509328017, 0.3210578460652491, 0.335041095545175, 0.22500796423572675, - 0.44230628074326406, 0.16743171716317784, 0.16745989278866702, 0.17700588224362557, - 0.02692320090677309], - tspan = (0.0, 0.5)) - end - - @trixi_testset "elixir_mhd_alfven_wave.jl" begin + l2=[0.06418293357851637, 0.12085176618704108, + 0.12085099342419513, 0.07743005602933221, + 0.1622218916638482, 0.04044434425257972, + 0.04044440614962498, 0.05735896706356321, + 0.0020992340041681734], + linf=[0.1417000509328017, 0.3210578460652491, 0.335041095545175, + 0.22500796423572675, + 0.44230628074326406, 0.16743171716317784, + 0.16745989278866702, 0.17700588224362557, + 0.02692320090677309], + tspan=(0.0, 0.5)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_mhd_alfven_wave.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_mhd_alfven_wave.jl"), - l2 = [5.377518922553881e-5, 0.09999999206243514, 0.09999999206243441, 0.1414213538550799, - 8.770450430886394e-6, 0.0999999926130084, 0.0999999926130088, 0.14142135396487032, - 1.1553833987291942e-5], - linf = [0.00039334982566352483, 0.14144904937275282, 0.14144904937277897, 0.20003315928443416, - 6.826863293230012e-5, 0.14146512909995967, 0.14146512909994702, 0.20006706837452526, - 0.00013645610312810813], - tspan = (0.0, 0.5)) - end - - @trixi_testset "elixir_shallowwater_ec.jl" begin + l2=[5.377518922553881e-5, 0.09999999206243514, + 0.09999999206243441, 0.1414213538550799, + 8.770450430886394e-6, 0.0999999926130084, + 0.0999999926130088, 0.14142135396487032, + 1.1553833987291942e-5], + linf=[0.00039334982566352483, 0.14144904937275282, + 0.14144904937277897, 0.20003315928443416, + 6.826863293230012e-5, 0.14146512909995967, + 0.14146512909994702, 0.20006706837452526, + 0.00013645610312810813], + tspan=(0.0, 0.5)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_shallowwater_ec.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_ec.jl"), - l2 = [0.6106939484178353, 0.48586236867426724, 0.48234490854514356, 0.29467422718511727], - linf = [2.775979948281604, 3.1721242154451548, 3.5713448319601393, 2.052861364219655], - tspan = (0.0, 0.25)) - end + l2=[ + 0.6106939484178353, + 0.48586236867426724, + 0.48234490854514356, + 0.29467422718511727, + ], + linf=[ + 2.775979948281604, + 3.1721242154451548, + 3.5713448319601393, + 2.052861364219655, + ], + tspan=(0.0, 0.25)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_shallowwater_well_balanced.jl" begin +@trixi_testset "elixir_shallowwater_well_balanced.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_well_balanced.jl"), - l2 = [1.2164292510839076, 2.6118925543469468e-12, 1.1636046671473883e-12, 1.2164292510839079], - linf = [1.5138512282315846, 4.998482888288039e-11, 2.0246214978154587e-11, 1.513851228231574], - tspan = (0.0, 0.25)) - end + l2=[ + 1.2164292510839076, + 2.6118925543469468e-12, + 1.1636046671473883e-12, + 1.2164292510839079, + ], + linf=[ + 1.5138512282315846, + 4.998482888288039e-11, + 2.0246214978154587e-11, + 1.513851228231574, + ], + tspan=(0.0, 0.25)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_shallowwater_well_balanced.jl with FluxHydrostaticReconstruction" begin +@trixi_testset "elixir_shallowwater_well_balanced.jl with FluxHydrostaticReconstruction" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_well_balanced.jl"), - l2 = [1.2164292510839085, 1.2643106818778908e-12, 7.46884905098358e-13, 1.2164292510839079], - linf = [1.513851228231562, 1.6287765844373185e-11, 6.8766999132716964e-12, 1.513851228231574], - surface_flux=(FluxHydrostaticReconstruction(flux_lax_friedrichs, hydrostatic_reconstruction_audusse_etal), flux_nonconservative_audusse_etal), - tspan = (0.0, 0.2)) - end + l2=[ + 1.2164292510839085, + 1.2643106818778908e-12, + 7.46884905098358e-13, + 1.2164292510839079, + ], + linf=[ + 1.513851228231562, + 1.6287765844373185e-11, + 6.8766999132716964e-12, + 1.513851228231574, + ], + surface_flux=(FluxHydrostaticReconstruction(flux_lax_friedrichs, + hydrostatic_reconstruction_audusse_etal), + flux_nonconservative_audusse_etal), + tspan=(0.0, 0.2)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_shallowwater_well_balanced.jl with flux_nonconservative_ersing_etal" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_well_balanced.jl"), + l2=[ + 1.2164292510839083, + 2.590643638636187e-12, + 1.0945471514840143e-12, + 1.2164292510839079, + ], + linf=[ + 1.5138512282315792, + 5.0276441977281156e-11, + 1.9816934589292803e-11, + 1.513851228231574, + ], + surface_flux=(flux_wintermeyer_etal, + flux_nonconservative_ersing_etal), + volume_flux=(flux_wintermeyer_etal, + flux_nonconservative_ersing_etal), + tspan=(0.0, 0.25)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_shallowwater_source_terms.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_source_terms.jl"), + l2=[ + 0.0011197623982310795, + 0.04456344888447023, + 0.014317376629669337, + 5.089218476758975e-6, + ], + linf=[ + 0.007835284004819698, + 0.3486891284278597, + 0.11242778979399048, + 2.6407324614119432e-5, + ], + tspan=(0.0, 0.025)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_shallowwater_source_terms.jl" begin +@trixi_testset "elixir_shallowwater_source_terms.jl with FluxHydrostaticReconstruction" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_source_terms.jl"), - l2 = [0.0011197623982310795, 0.04456344888447023, 0.014317376629669337, 5.089218476758975e-6], - linf = [0.007835284004819698, 0.3486891284278597, 0.11242778979399048, 2.6407324614119432e-5], - tspan = (0.0, 0.025)) - end + l2=[ + 0.0011197139793938152, + 0.015430259691310781, + 0.017081031802719724, + 5.089218476758271e-6, + ], + linf=[ + 0.014300809338967824, + 0.12783372461225184, + 0.17625472321992852, + 2.6407324614341476e-5, + ], + surface_flux=(FluxHydrostaticReconstruction(flux_hll, + hydrostatic_reconstruction_audusse_etal), + flux_nonconservative_audusse_etal), + tspan=(0.0, 0.025)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_shallowwater_source_terms.jl with FluxHydrostaticReconstruction" begin +@trixi_testset "elixir_shallowwater_source_terms.jl with flux_nonconservative_ersing_etal" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_source_terms.jl"), - l2 = [0.0011197139793938152, 0.015430259691310781, 0.017081031802719724, 5.089218476758271e-6], - linf = [0.014300809338967824, 0.12783372461225184, 0.17625472321992852, 2.6407324614341476e-5], - surface_flux=(FluxHydrostaticReconstruction(flux_hll, hydrostatic_reconstruction_audusse_etal), flux_nonconservative_audusse_etal), - tspan = (0.0, 0.025)) - end + l2=[ + 0.0011196687776346434, + 0.044562672453443995, + 0.014306265289763618, + 5.089218476759981e-6, + ], + linf=[ + 0.007825021762002393, + 0.348550815397918, + 0.1115517935018282, + 2.6407324614341476e-5, + ], + surface_flux=(flux_wintermeyer_etal, + flux_nonconservative_ersing_etal), + volume_flux=(flux_wintermeyer_etal, + flux_nonconservative_ersing_etal), + tspan=(0.0, 0.025)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_shallowwater_source_terms.jl with flux_hll" begin +@trixi_testset "elixir_shallowwater_source_terms.jl with flux_hll" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_source_terms.jl"), - l2 = [0.0011197139793938727, 0.015430259691311309, 0.017081031802719554, 5.089218476759981e-6], - linf = [0.014300809338967824, 0.12783372461224918, 0.17625472321993918, 2.6407324614341476e-5], - surface_flux=(flux_hll, flux_nonconservative_fjordholm_etal), - tspan = (0.0, 0.025)) - end + l2=[ + 0.0011197139793938727, + 0.015430259691311309, + 0.017081031802719554, + 5.089218476759981e-6, + ], + linf=[ + 0.014300809338967824, + 0.12783372461224918, + 0.17625472321993918, + 2.6407324614341476e-5, + ], + surface_flux=(flux_hll, flux_nonconservative_fjordholm_etal), + tspan=(0.0, 0.025)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end - @trixi_testset "elixir_shallowwater_dirichlet.jl" begin +@trixi_testset "elixir_shallowwater_dirichlet.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_dirichlet.jl"), - l2 = [1.1577518608940115e-5, 4.867189932537344e-13, 4.647273240470541e-13, 1.1577518608933468e-5], - linf = [8.394063878602864e-5, 1.1469760027632646e-10, 1.1146619484429974e-10, 8.394063879602065e-5], - tspan = (0.0, 2.0)) - end - - @trixi_testset "elixir_shallowwater_wall_bc_shockcapturing.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_wall_bc_shockcapturing.jl"), - l2 = [0.04444388691670699, 0.1527771788033111, 0.1593763537203512, 6.225080476986749e-8], - linf = [0.6526506870169639, 1.980765893182952, 2.4807635459119757, 3.982097158683473e-7], - tspan = (0.0, 0.05)) - end - - @trixi_testset "elixir_shallowwater_ec_shockcapturing.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_ec_shockcapturing.jl"), - l2 = [0.6124656312639043, 0.504371951785709, 0.49180896200746366, 0.29467422718511727], - linf = [2.7639232436274392, 3.3985508653311767, 3.3330308209196224, 2.052861364219655], - tspan = (0.0, 0.25)) - end - - @trixi_testset "elixir_shallowwater_three_mound_dam_break.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_three_mound_dam_break.jl"), - l2 = [0.0892957892027502, 0.30648836484407915, 2.28712547616214e-15, 0.0008778654298684622], - linf = [0.850329472915091, 2.330631694956507, 5.783660020252348e-14, 0.04326237921249021], - basis = LobattoLegendreBasis(3), - tspan = (0.0, 0.25)) - end - - @trixi_testset "elixir_shallowwater_twolayer_convergence.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_twolayer_convergence.jl"), - l2 = [0.0007953969898161991, 0.00882074628714633, 0.0024322572528892934, - 0.0007597425017400447, 0.004501238950166439, 0.0015784803573661104, - 6.849532064729749e-6], - linf = [0.00592559068081977, 0.08072451118697077, 0.0344854497419107, 0.005892196680485795, - 0.04262651217675306, 0.014006223513881366, 2.5829318284764646e-5], - tspan = (0.0, 0.25)) - end - - @trixi_testset "elixir_shallowwater_twolayer_well_balanced.jl" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_twolayer_well_balanced.jl"), - l2 = [4.706532184998499e-16, 1.1215950712872183e-15, 6.7822712922421565e-16, - 0.002192812926266047, 5.506855295923691e-15, 3.3105180099689275e-15, - 0.0021928129262660085], - linf = [4.468647674116255e-15, 1.3607872120431166e-14, 9.557155049520056e-15, - 0.024280130945632084, 6.68910907640583e-14, 4.7000983997100496e-14, - 0.024280130945632732], - tspan = (0.0, 0.25)) - end - - @trixi_testset "elixir_shallowwater_twolayer_dam_break.jl with flux_lax_friedrichs" begin - @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_shallowwater_twolayer_dam_break.jl"), - l2 = [0.012471300561905669, 0.012363413819726868, 0.0009541478004413331, - 0.09120260327331643, 0.015269590815749993, 0.0012064657396853422, - 0.09991983966647647], - linf = [0.04497814714937959, 0.03286959000796511, 0.010746094385294369, - 0.11138723974511211, 0.03640850605444494, 0.014368386516056392, 0.10000000000000003], - surface_flux = (flux_lax_friedrichs, flux_nonconservative_fjordholm_etal), - tspan = (0.0, 0.25)) - end + l2=[ + 1.1577518608940115e-5, + 4.867189932537344e-13, + 4.647273240470541e-13, + 1.1577518608933468e-5, + ], + linf=[ + 8.394063878602864e-5, + 1.1469760027632646e-10, + 1.1146619484429974e-10, + 8.394063879602065e-5, + ], + tspan=(0.0, 2.0)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_shallowwater_wall_bc_shockcapturing.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_shallowwater_wall_bc_shockcapturing.jl"), + l2=[ + 0.04444388691670699, + 0.1527771788033111, + 0.1593763537203512, + 6.225080476986749e-8, + ], + linf=[ + 0.6526506870169639, + 1.980765893182952, + 2.4807635459119757, + 3.982097158683473e-7, + ], + tspan=(0.0, 0.05)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_shallowwater_ec_shockcapturing.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_shallowwater_ec_shockcapturing.jl"), + l2=[ + 0.6124656312639043, + 0.504371951785709, + 0.49180896200746366, + 0.29467422718511727, + ], + linf=[ + 2.7639232436274392, + 3.3985508653311767, + 3.3330308209196224, + 2.052861364219655, + ], + tspan=(0.0, 0.25)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_shallowwater_three_mound_dam_break.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_shallowwater_three_mound_dam_break.jl"), + l2=[ + 0.0892957892027502, + 0.30648836484407915, + 2.28712547616214e-15, + 0.0008778654298684622, + ], + linf=[ + 0.850329472915091, + 2.330631694956507, + 5.783660020252348e-14, + 0.04326237921249021, + ], + basis=LobattoLegendreBasis(3), + tspan=(0.0, 0.25)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_shallowwater_twolayer_convergence.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_shallowwater_twolayer_convergence.jl"), + l2=[0.0007935561625451243, 0.008825315509943844, + 0.002429969315645897, + 0.0007580145888686304, 0.004495741879625235, + 0.0015758146898767814, + 6.849532064729749e-6], + linf=[0.0059205195991136605, 0.08072126590166251, + 0.03463806075399023, + 0.005884818649227186, 0.042658506561995546, + 0.014125956138838602, 2.5829318284764646e-5], + tspan=(0.0, 0.25)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_shallowwater_twolayer_well_balanced.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_shallowwater_twolayer_well_balanced.jl"), + l2=[4.706532184998499e-16, 1.1215950712872183e-15, + 6.7822712922421565e-16, + 0.002192812926266047, 5.506855295923691e-15, + 3.3105180099689275e-15, + 0.0021928129262660085], + linf=[4.468647674116255e-15, 1.3607872120431166e-14, + 9.557155049520056e-15, + 0.024280130945632084, 6.68910907640583e-14, + 4.7000983997100496e-14, + 0.024280130945632732], + tspan=(0.0, 0.25)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "elixir_shallowwater_twolayer_dam_break.jl with flux_lax_friedrichs" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, + "elixir_shallowwater_twolayer_dam_break.jl"), + l2=[0.012447632879122346, 0.012361250464676683, + 0.0009551519536340908, + 0.09119400061322577, 0.015276216721920347, + 0.0012126995108983853, 0.09991983966647647], + linf=[0.044305765721807444, 0.03279620980615845, + 0.010754320388190101, + 0.111309922939555, 0.03663360204931427, + 0.014332822306649284, + 0.10000000000000003], + surface_flux=(flux_lax_friedrichs, + flux_nonconservative_ersing_etal), + tspan=(0.0, 0.25)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +# TODO: FD; for now put the unstructured tests for the 2D FDSBP here. +@trixi_testset "FDSBP (central): elixir_advection_basic.jl" begin + @test_trixi_include(joinpath(pkgdir(Trixi, "examples", "unstructured_2d_fdsbp"), + "elixir_advection_basic.jl"), + l2=[0.0001105211407319266], + linf=[0.0004199363734466166]) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "FDSBP (central): elixir_euler_source_terms.jl" begin + @test_trixi_include(joinpath(pkgdir(Trixi, "examples", "unstructured_2d_fdsbp"), + "elixir_euler_source_terms.jl"), + l2=[8.155544666380138e-5, + 0.0001477863788446318, + 0.00014778637884460072, + 0.00045584189984542687], + linf=[0.0002670775876922882, + 0.0005683064706873964, + 0.0005683064706762941, + 0.0017770812025146299], + tspan=(0.0, 0.05)) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end + +@trixi_testset "FDSBP (central): elixir_euler_free_stream.jl" begin + @test_trixi_include(joinpath(pkgdir(Trixi, "examples", "unstructured_2d_fdsbp"), + "elixir_euler_free_stream.jl"), + l2=[5.4329175009362306e-14, + 1.0066867437607972e-13, + 6.889210012578449e-14, + 1.568290814572709e-13], + linf=[5.963762816918461e-10, + 5.08869890669672e-11, + 1.1581377523661729e-10, + 4.61017890529547e-11], + tspan=(0.0, 0.1), + atol=1.0e-11) + # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end +end end # Clean up afterwards: delete Trixi.jl output directory -@test_nowarn rm(outdir, recursive=true) +@test_nowarn rm(outdir, recursive = true) end # module diff --git a/test/test_visualization.jl b/test/test_visualization.jl index b700fc71a8f..6444dc91d5d 100644 --- a/test/test_visualization.jl +++ b/test/test_visualization.jl @@ -15,33 +15,40 @@ EXAMPLES_DIR = pkgdir(Trixi, "examples", "tree_2d_dgsem") # Start with a clean environment: remove Trixi.jl output directory if it exists outdir = "out" -isdir(outdir) && rm(outdir, recursive=true) +isdir(outdir) && rm(outdir, recursive = true) # Run various visualization tests @testset "Visualization tests" begin - # Run 2D tests with elixirs for all mesh types - test_examples_2d = Dict( - "TreeMesh" => ("tree_2d_dgsem", "elixir_euler_blast_wave_amr.jl"), - "StructuredMesh" => ("structured_2d_dgsem", "elixir_euler_source_terms_waving_flag.jl"), - "UnstructuredMesh" => ("unstructured_2d_dgsem", "elixir_euler_basic.jl"), - "P4estMesh" => ("p4est_2d_dgsem", "elixir_euler_source_terms_nonconforming_unstructured_flag.jl"), - "DGMulti" => ("dgmulti_2d", "elixir_euler_weakform.jl"), - ) - - @testset "PlotData2D, PlotDataSeries, PlotMesh with $mesh" for mesh in keys(test_examples_2d) +#! format: noindent + +# Run 2D tests with elixirs for all mesh types +test_examples_2d = Dict("TreeMesh" => ("tree_2d_dgsem", + "elixir_euler_blast_wave_amr.jl"), + "StructuredMesh" => ("structured_2d_dgsem", + "elixir_euler_source_terms_waving_flag.jl"), + "UnstructuredMesh" => ("unstructured_2d_dgsem", + "elixir_euler_basic.jl"), + "P4estMesh" => ("p4est_2d_dgsem", + "elixir_euler_source_terms_nonconforming_unstructured_flag.jl"), + "DGMulti" => ("dgmulti_2d", "elixir_euler_weakform.jl")) + +@testset "PlotData2D, PlotDataSeries, PlotMesh with $mesh" for mesh in keys(test_examples_2d) # Run Trixi.jl directory, elixir = test_examples_2d[mesh] - @test_nowarn_mod trixi_include(@__MODULE__, joinpath(examples_dir(), directory, elixir), - tspan=(0,0.1)) + @test_nowarn_mod trixi_include(@__MODULE__, + joinpath(examples_dir(), directory, elixir), + tspan = (0, 0.1)) # Constructor tests if mesh == "TreeMesh" - @test PlotData2D(sol) isa Trixi.PlotData2DCartesian - @test PlotData2D(sol; nvisnodes=0, grid_lines=false, solution_variables=cons2cons) isa Trixi.PlotData2DCartesian - @test Trixi.PlotData2DTriangulated(sol) isa Trixi.PlotData2DTriangulated + @test PlotData2D(sol) isa Trixi.PlotData2DCartesian + @test PlotData2D(sol; nvisnodes = 0, grid_lines = false, + solution_variables = cons2cons) isa Trixi.PlotData2DCartesian + @test Trixi.PlotData2DTriangulated(sol) isa Trixi.PlotData2DTriangulated else - @test PlotData2D(sol) isa Trixi.PlotData2DTriangulated - @test PlotData2D(sol; nvisnodes=0, solution_variables=cons2cons) isa Trixi.PlotData2DTriangulated + @test PlotData2D(sol) isa Trixi.PlotData2DTriangulated + @test PlotData2D(sol; nvisnodes = 0, solution_variables = cons2cons) isa + Trixi.PlotData2DTriangulated end pd = PlotData2D(sol) @@ -64,9 +71,9 @@ isdir(outdir) && rm(outdir, recursive=true) @test keys(pd) == ("rho", "v1", "v2", "p") @test eltype(pd) <: Pair{String, <:Trixi.PlotDataSeries} @test [v for v in pd] == ["rho" => Trixi.PlotDataSeries(pd, 1), - "v1" => Trixi.PlotDataSeries(pd, 2), - "v2" => Trixi.PlotDataSeries(pd, 3), - "p" => Trixi.PlotDataSeries(pd, 4)] + "v1" => Trixi.PlotDataSeries(pd, 2), + "v2" => Trixi.PlotDataSeries(pd, 3), + "p" => Trixi.PlotDataSeries(pd, 4)] # PlotDataSeries pds = pd["p"] @@ -82,48 +89,52 @@ isdir(outdir) && rm(outdir, recursive=true) println(stdout) @testset "2D plot recipes" begin - pd = PlotData2D(sol) - - @test_nowarn_mod Plots.plot(sol) - @test_nowarn_mod Plots.plot(pd) - @test_nowarn_mod Plots.plot(pd["p"]) - @test_nowarn_mod Plots.plot(getmesh(pd)) - - semi = sol.prob.p - if mesh == "DGMulti" - scalar_data = StructArrays.component(sol.u[end], 1) - @test_nowarn_mod Plots.plot(ScalarPlotData2D(scalar_data, semi)) - else - cache = semi.cache - x = view(cache.elements.node_coordinates, 1, :, :, :) - @test_nowarn_mod Plots.plot(ScalarPlotData2D(x, semi)) - end + pd = PlotData2D(sol) + + @test_nowarn_mod Plots.plot(sol) + @test_nowarn_mod Plots.plot(pd) + @test_nowarn_mod Plots.plot(pd["p"]) + @test_nowarn_mod Plots.plot(getmesh(pd)) + + semi = sol.prob.p + if mesh == "DGMulti" + scalar_data = StructArrays.component(sol.u[end], 1) + @test_nowarn_mod Plots.plot(ScalarPlotData2D(scalar_data, semi)) + else + cache = semi.cache + x = view(cache.elements.node_coordinates, 1, :, :, :) + @test_nowarn_mod Plots.plot(ScalarPlotData2D(x, semi)) + end end @testset "1D plot from 2D solution" begin - if mesh != "DGMulti" - @testset "Create 1D plot as slice" begin - @test_nowarn_mod PlotData1D(sol, slice=:y, point=(0.5, 0.0)) isa PlotData1D - @test_nowarn_mod PlotData1D(sol, slice=:x, point=(0.5, 0.0)) isa PlotData1D - pd1D = PlotData1D(sol, slice=:y, point=(0.5, 0.0)) - @test_nowarn_mod Plots.plot(pd1D) - - @testset "Create 1D plot along curve" begin - curve = zeros(2, 10) - curve[1, :] = range(-1, 1,length=10) - @test_nowarn_mod PlotData1D(sol, curve=curve) isa PlotData1D - pd1D = PlotData1D(sol, curve=curve) - @test_nowarn_mod Plots.plot(pd1D) - end + if mesh != "DGMulti" + @testset "Create 1D plot as slice" begin + @test_nowarn_mod PlotData1D(sol, slice = :y, point = (0.5, 0.0)) isa + PlotData1D + @test_nowarn_mod PlotData1D(sol, slice = :x, point = (0.5, 0.0)) isa + PlotData1D + pd1D = PlotData1D(sol, slice = :y, point = (0.5, 0.0)) + @test_nowarn_mod Plots.plot(pd1D) + + @testset "Create 1D plot along curve" begin + curve = zeros(2, 10) + curve[1, :] = range(-1, 1, length = 10) + @test_nowarn_mod PlotData1D(sol, curve = curve) isa PlotData1D + pd1D = PlotData1D(sol, curve = curve) + @test_nowarn_mod Plots.plot(pd1D) + end + end end - end end - end +end - @timed_testset "PlotData1D, PlotDataSeries, PlotMesh" begin +@timed_testset "PlotData1D, PlotDataSeries, PlotMesh" begin # Run Trixi.jl - @test_nowarn_mod trixi_include(@__MODULE__, joinpath(examples_dir(), "tree_1d_dgsem", "elixir_euler_blast_wave.jl"), - tspan=(0,0.1)) + @test_nowarn_mod trixi_include(@__MODULE__, + joinpath(examples_dir(), "tree_1d_dgsem", + "elixir_euler_blast_wave.jl"), + tspan = (0, 0.1)) # Constructor @test PlotData1D(sol) isa PlotData1D @@ -147,8 +158,8 @@ isdir(outdir) && rm(outdir, recursive=true) @test keys(pd) == ("rho", "v1", "p") @test eltype(pd) <: Pair{String, <:Trixi.PlotDataSeries} @test [v for v in pd] == ["rho" => Trixi.PlotDataSeries(pd, 1), - "v1" => Trixi.PlotDataSeries(pd, 2), - "p" => Trixi.PlotDataSeries(pd, 3)] + "v1" => Trixi.PlotDataSeries(pd, 2), + "p" => Trixi.PlotDataSeries(pd, 3)] # PlotDataSeries pds = pd["p"] @@ -165,174 +176,192 @@ isdir(outdir) && rm(outdir, recursive=true) # nvisnodes @test size(pd.data) == (512, 3) - pd0 = PlotData1D(sol, nvisnodes=0) + pd0 = PlotData1D(sol, nvisnodes = 0) @test size(pd0.data) == (256, 3) - pd2 = PlotData1D(sol, nvisnodes=2) + pd2 = PlotData1D(sol, nvisnodes = 2) @test size(pd2.data) == (128, 3) @testset "1D plot recipes" begin - pd = PlotData1D(sol) + pd = PlotData1D(sol) - @test_nowarn_mod Plots.plot(sol) - @test_nowarn_mod Plots.plot(pd) - @test_nowarn_mod Plots.plot(pd["p"]) - @test_nowarn_mod Plots.plot(getmesh(pd)) + @test_nowarn_mod Plots.plot(sol) + @test_nowarn_mod Plots.plot(pd) + @test_nowarn_mod Plots.plot(pd["p"]) + @test_nowarn_mod Plots.plot(getmesh(pd)) end # Fake a PlotDataXD objects to test code for plotting multiple variables on at least two rows # with at least one plot remaining empty @testset "plotting multiple variables" begin - x = collect(0.0:0.1:1.0) - data1d = rand(5, 11) - variable_names = string.('a':'e') - mesh_vertices_x1d = [x[begin], x[end]] - fake1d = PlotData1D(x, data1d, variable_names, mesh_vertices_x1d, 0) - @test_nowarn_mod Plots.plot(fake1d) - - y = x - data2d = [rand(11,11) for _ in 1:5] - mesh_vertices_x2d = [0.0, 1.0, 1.0, 0.0] - mesh_vertices_y2d = [0.0, 0.0, 1.0, 1.0] - fake2d = Trixi.PlotData2DCartesian(x, y, data2d, variable_names, mesh_vertices_x2d, mesh_vertices_y2d, 0, 0) - @test_nowarn_mod Plots.plot(fake2d) + x = collect(0.0:0.1:1.0) + data1d = rand(5, 11) + variable_names = string.('a':'e') + mesh_vertices_x1d = [x[begin], x[end]] + fake1d = PlotData1D(x, data1d, variable_names, mesh_vertices_x1d, 0) + @test_nowarn_mod Plots.plot(fake1d) + + y = x + data2d = [rand(11, 11) for _ in 1:5] + mesh_vertices_x2d = [0.0, 1.0, 1.0, 0.0] + mesh_vertices_y2d = [0.0, 0.0, 1.0, 1.0] + fake2d = Trixi.PlotData2DCartesian(x, y, data2d, variable_names, + mesh_vertices_x2d, mesh_vertices_y2d, 0, 0) + @test_nowarn_mod Plots.plot(fake2d) end - end +end - @timed_testset "PlotData1D (DGMulti)" begin +@timed_testset "PlotData1D (DGMulti)" begin # Test two different approximation types since these use different memory layouts: # - structure of arrays for `Polynomial()` # - array of structures for `SBP()` @test_nowarn_mod trixi_include(@__MODULE__, - joinpath(examples_dir(), "dgmulti_1d", "elixir_euler_flux_diff.jl"), tspan=(0.0 ,0.0), - approximation_type=Polynomial()) + joinpath(examples_dir(), "dgmulti_1d", + "elixir_euler_flux_diff.jl"), + tspan = (0.0, 0.0), + approximation_type = Polynomial()) @test PlotData1D(sol) isa PlotData1D @test_nowarn_mod trixi_include(@__MODULE__, - joinpath(examples_dir(), "dgmulti_1d", "elixir_euler_flux_diff.jl"), tspan=(0.0 ,0.0), - approximation_type=SBP()) + joinpath(examples_dir(), "dgmulti_1d", + "elixir_euler_flux_diff.jl"), + tspan = (0.0, 0.0), + approximation_type = SBP()) @test PlotData1D(sol) isa PlotData1D - end +end - @timed_testset "plot time series" begin +@timed_testset "plot time series" begin @test_nowarn_mod trixi_include(@__MODULE__, - joinpath(examples_dir(), "tree_2d_dgsem", "elixir_acoustics_gaussian_source.jl"), - tspan=(0, 0.05)) + joinpath(examples_dir(), "tree_2d_dgsem", + "elixir_acoustics_gaussian_source.jl"), + tspan = (0, 0.05)) @test_nowarn_mod Plots.plot(time_series, 1) @test PlotData1D(time_series, 1) isa PlotData1D - end +end - @timed_testset "adapt_to_mesh_level" begin - @test_nowarn_mod trixi_include(@__MODULE__, joinpath(examples_dir(), "tree_2d_dgsem", "elixir_advection_basic.jl"), - tspan=(0,0.1), analysis_callback=Trixi.TrivialCallback()) +@timed_testset "adapt_to_mesh_level" begin + @test_nowarn_mod trixi_include(@__MODULE__, + joinpath(examples_dir(), "tree_2d_dgsem", + "elixir_advection_basic.jl"), + analysis_callback = Trixi.TrivialCallback()) @test adapt_to_mesh_level(sol, 5) isa Tuple u_ode_level5, semi_level5 = adapt_to_mesh_level(sol, 5) u_ode_level4, semi_level4 = adapt_to_mesh_level(u_ode_level5, semi_level5, 4) - @test isapprox(sol.u[end], u_ode_level4, atol=1e-13) + @test isapprox(sol.u[end], u_ode_level4, atol = 1e-13) @test adapt_to_mesh_level!(sol, 5) isa Tuple - @test isapprox(sol.u[end], u_ode_level5, atol=1e-13) - end + @test isapprox(sol.u[end], u_ode_level5, atol = 1e-13) +end - @timed_testset "plot 3D" begin - @test_nowarn_mod trixi_include(@__MODULE__, joinpath(examples_dir(), "tree_3d_dgsem", "elixir_advection_basic.jl"), - tspan=(0,0.1), analysis_callback=Trixi.TrivialCallback(), initial_refinement_level=1) +@timed_testset "plot 3D" begin + @test_nowarn_mod trixi_include(@__MODULE__, + joinpath(examples_dir(), "tree_3d_dgsem", + "elixir_advection_basic.jl"), + analysis_callback = Trixi.TrivialCallback(), + initial_refinement_level = 1) @test PlotData2D(sol) isa Trixi.PlotData2DCartesian - @test PlotData2D(sol, slice =:yz) isa Trixi.PlotData2DCartesian - @test PlotData2D(sol, slice =:xz) isa Trixi.PlotData2DCartesian + @test PlotData2D(sol, slice = :yz) isa Trixi.PlotData2DCartesian + @test PlotData2D(sol, slice = :xz) isa Trixi.PlotData2DCartesian @testset "1D plot from 3D solution and Tree-mesh" begin - @testset "Create 1D plot as slice" begin - @test_nowarn_mod PlotData1D(sol) isa PlotData1D - pd1D = PlotData1D(sol) - @test_nowarn_mod Plots.plot(pd1D) - @test_nowarn_mod PlotData1D(sol, slice=:y, point = (0.5, 0.3, 0.1)) isa PlotData1D - @test_nowarn_mod PlotData1D(sol, slice=:z, point = (0.1, 0.3, 0.3)) isa PlotData1D - - end - - @testset "Create 1D plot along curve" begin - curve = zeros(3, 10) - curve[1, :] = range(-1.0, -0.5, length=10) - @test_nowarn_mod PlotData1D(sol, curve=curve) isa PlotData1D - pd1D = PlotData1D(sol, curve=curve) - @test_nowarn_mod Plots.plot(pd1D) - end + @testset "Create 1D plot as slice" begin + @test_nowarn_mod PlotData1D(sol) isa PlotData1D + pd1D = PlotData1D(sol) + @test_nowarn_mod Plots.plot(pd1D) + @test_nowarn_mod PlotData1D(sol, slice = :y, point = (0.5, 0.3, 0.1)) isa + PlotData1D + @test_nowarn_mod PlotData1D(sol, slice = :z, point = (0.1, 0.3, 0.3)) isa + PlotData1D + end + + @testset "Create 1D plot along curve" begin + curve = zeros(3, 10) + curve[1, :] = range(-1.0, -0.5, length = 10) + @test_nowarn_mod PlotData1D(sol, curve = curve) isa PlotData1D + pd1D = PlotData1D(sol, curve = curve) + @test_nowarn_mod Plots.plot(pd1D) + end end - @test_nowarn_mod trixi_include(@__MODULE__, joinpath(examples_dir(), "structured_3d_dgsem", "elixir_advection_basic.jl"), - tspan=(0,0.1)) + @test_nowarn_mod trixi_include(@__MODULE__, + joinpath(examples_dir(), "structured_3d_dgsem", + "elixir_advection_basic.jl")) @testset "1D plot from 3D solution and general mesh" begin - @testset "Create 1D plot as slice" begin - @test_nowarn_mod PlotData1D(sol) isa PlotData1D - pd1D = PlotData1D(sol) - @test_nowarn_mod Plots.plot(pd1D) - @test_nowarn_mod PlotData1D(sol, slice=:y, point = (0.5, 0.3, 0.1)) isa PlotData1D - @test_nowarn_mod PlotData1D(sol, slice=:z, point = (0.1, 0.3, 0.3)) isa PlotData1D - - end - - @testset "Create 1D plot along curve" begin - curve = zeros(3, 10) - curve[1, :] = range(-1.0, 1.0, length=10) - @test_nowarn_mod PlotData1D(sol, curve=curve) isa PlotData1D - pd1D = PlotData1D(sol, curve=curve) - @test_nowarn_mod Plots.plot(pd1D) - end + @testset "Create 1D plot as slice" begin + @test_nowarn_mod PlotData1D(sol) isa PlotData1D + pd1D = PlotData1D(sol) + @test_nowarn_mod Plots.plot(pd1D) + @test_nowarn_mod PlotData1D(sol, slice = :y, point = (0.5, 0.3, 0.1)) isa + PlotData1D + @test_nowarn_mod PlotData1D(sol, slice = :z, point = (0.1, 0.3, 0.3)) isa + PlotData1D + end + + @testset "Create 1D plot along curve" begin + curve = zeros(3, 10) + curve[1, :] = range(-1.0, 1.0, length = 10) + @test_nowarn_mod PlotData1D(sol, curve = curve) isa PlotData1D + pd1D = PlotData1D(sol, curve = curve) + @test_nowarn_mod Plots.plot(pd1D) + end end - end +end - @timed_testset "plotting TimeIntegratorSolution" begin - @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", "elixir_hypdiff_lax_friedrichs.jl"), +@timed_testset "plotting TimeIntegratorSolution" begin + @test_trixi_include(joinpath(examples_dir(), "tree_2d_dgsem", + "elixir_hypdiff_lax_friedrichs.jl"), maxiters=1, analysis_callback=Trixi.TrivialCallback(), initial_refinement_level=1) @test_nowarn_mod Plots.plot(sol) - end +end - @timed_testset "VisualizationCallback" begin +@timed_testset "VisualizationCallback" begin # To make CI tests work, disable showing a plot window with the GR backend of the Plots package # Xref: https://github.com/jheinen/GR.jl/issues/278 # Xref: https://github.com/JuliaPlots/Plots.jl/blob/8cc6d9d48755ba452a2835f9b89d3880e9945377/test/runtests.jl#L103 if !isinteractive() - restore = get(ENV, "GKSwstype", nothing) - ENV["GKSwstype"] = "100" + restore = get(ENV, "GKSwstype", nothing) + ENV["GKSwstype"] = "100" end @test_nowarn_mod trixi_include(@__MODULE__, - joinpath(examples_dir(), "tree_2d_dgsem", "elixir_advection_amr_visualization.jl"), - visualization = VisualizationCallback(interval=20, - clims=(0,1), - plot_creator=Trixi.save_plot), - tspan=(0.0, 3.0)) + joinpath(examples_dir(), "tree_2d_dgsem", + "elixir_advection_amr_visualization.jl"), + visualization = VisualizationCallback(interval = 20, + clims = (0, 1), + plot_creator = Trixi.save_plot), + tspan = (0.0, 3.0)) @testset "elixir_advection_amr_visualization.jl with save_plot" begin - @test isfile(joinpath(outdir, "solution_000000.png")) - @test isfile(joinpath(outdir, "solution_000020.png")) - @test isfile(joinpath(outdir, "solution_000022.png")) + @test isfile(joinpath(outdir, "solution_000000.png")) + @test isfile(joinpath(outdir, "solution_000020.png")) + @test isfile(joinpath(outdir, "solution_000022.png")) end @testset "show" begin - @test_nowarn_mod show(stdout, visualization) - println(stdout) + @test_nowarn_mod show(stdout, visualization) + println(stdout) - @test_nowarn_mod show(stdout, "text/plain", visualization) - println(stdout) + @test_nowarn_mod show(stdout, "text/plain", visualization) + println(stdout) end # Restore GKSwstype to previous value (if it was set) if !isinteractive() - if isnothing(restore) - delete!(ENV, "GKSwstype") - else - ENV["GKSwstype"] = restore - end + if isnothing(restore) + delete!(ENV, "GKSwstype") + else + ENV["GKSwstype"] = restore + end end - end +end - @timed_testset "Makie visualization tests for UnstructuredMesh2D" begin - @test_nowarn_mod trixi_include(@__MODULE__, joinpath(examples_dir(), "unstructured_2d_dgsem", "elixir_euler_wall_bc.jl")) +@timed_testset "Makie visualization tests for UnstructuredMesh2D" begin + @test_nowarn_mod trixi_include(@__MODULE__, + joinpath(examples_dir(), "unstructured_2d_dgsem", + "elixir_euler_wall_bc.jl")) # test interactive surface plot @test_nowarn_mod Trixi.iplot(sol) @@ -343,12 +372,12 @@ isdir(outdir) && rm(outdir, recursive=true) # test interactive ScalarPlotData2D plotting semi = sol.prob.p - x = view(semi.cache.elements.node_coordinates, 1, :, :, :); # extracts the node x coordinates - y = view(semi.cache.elements.node_coordinates, 2, :, :, :); # extracts the node x coordinates - @test_nowarn_mod iplot(ScalarPlotData2D(x.+y, semi), plot_mesh=true) + x = view(semi.cache.elements.node_coordinates, 1, :, :, :) # extracts the node x coordinates + y = view(semi.cache.elements.node_coordinates, 2, :, :, :) # extracts the node x coordinates + @test_nowarn_mod iplot(ScalarPlotData2D(x .+ y, semi), plot_mesh = true) # test heatmap plot - @test_nowarn_mod Makie.plot(sol, plot_mesh=true) + @test_nowarn_mod Makie.plot(sol, plot_mesh = true) # test unpacking/iteration for FigureAndAxes fa = Makie.plot(sol) @@ -360,11 +389,10 @@ isdir(outdir) && rm(outdir, recursive=true) # test plotting of constant solutions with Makie # related issue: https://github.com/MakieOrg/Makie.jl/issues/931 for i in eachindex(sol.u) - fill!(sol.u[i], one(eltype(sol.u[i]))) + fill!(sol.u[i], one(eltype(sol.u[i]))) end @test_nowarn_mod Trixi.iplot(sol) - end end - +end end #module diff --git a/utils/add_alloctest.py b/utils/add_alloctest.py new file mode 100644 index 00000000000..184ad280ea0 --- /dev/null +++ b/utils/add_alloctest.py @@ -0,0 +1,43 @@ +import argparse + +def add_code_after_end(input_file, output_file, code_to_add): + with open(input_file, 'r') as f: + julia_code = f.read() + + # Split the Julia code by "end" keywords + code_lines = julia_code.split("end") + + # Initialize the modified code with the first part of the code + modified_code = code_lines[0] + + # Loop through each "end" and add the code after it, excluding the last "end" + for i in range(1, len(code_lines) - 1): + # Check for consecutive "end" keywords + if code_lines[i].strip() == "": + continue + + modified_code += f"{code_to_add}{code_lines[i]}" + + # Add the last "end" without the code + modified_code += code_lines[-1] + + with open(output_file, 'w') as f: + f.write(modified_code) + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Add code after 'end' keyword in a Julia source file.") + parser.add_argument("input_file", help="Input Julia source file") + + args = parser.parse_args() + + code_to_add = """ # Ensure that we do not have excessive memory allocations + # (e.g., from type instabilities) + let + t = sol.t[end] + u_ode = sol.u[end] + du_ode = similar(u_ode) + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + end + end""" + + add_code_after_end(args.input_file, args.input_file, code_to_add) diff --git a/utils/trixi2txt.jl b/utils/trixi2txt.jl index b386f150da4..12a3d46760e 100644 --- a/utils/trixi2txt.jl +++ b/utils/trixi2txt.jl @@ -70,7 +70,7 @@ function trixi2txt(filename::AbstractString...; center_level_0, length_level_0, leaf_cells, coordinates, levels = read_meshfile(meshfile) # Read data - labels, data, n_elements, n_nodes, element_variables, time = read_datafile(filename) + labels, data, n_elements, n_nodes, element_variables, node_variables, time = read_datafile(filename) # Check if dimensions match if length(leaf_cells) != n_elements @@ -263,7 +263,16 @@ function read_datafile(filename::String) index += 1 end - return labels, data, n_elements, n_nodes, element_variables, time + # Extract node variable arrays + node_variables = Dict{String, Union{Vector{Float64}, Vector{Int}}}() + index = 1 + while haskey(file, "node_variables_$index") + varname = read(attributes(file["node_variables_$index"])["name"]) + node_variables[varname] = read(file["node_variables_$index"]) + index += 1 + end + + return labels, data, n_elements, n_nodes, element_variables, node_variables, time end end