-
Notifications
You must be signed in to change notification settings - Fork 159
VolumeIntegralAdaptive with IndicatorEntropyChange
#2754
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 144 commits
f355e1b
552d717
3ca63fc
147e896
2eec5d8
8e9949b
d823ff5
7bc660a
fc0347a
724335a
3166699
c0b1f0b
9876f85
dde3c81
6ec9287
a96827b
004adba
7409fdb
0bec762
e7ae7a2
32e4c75
0a38976
1375fa7
64c123a
0dac510
58db43b
5f885d6
224b84d
eaefcc1
e27d62a
ab8cb7f
a755aa6
7535812
7533ad0
624113c
a618ec5
56ac3ef
a5fb02b
26dc558
80d6754
ebb2e21
257480f
2c35e7f
6b324f7
80b91ca
dd741d7
48cad6b
5ebe81f
e3b6e37
da268d3
5df5340
38ab686
b94c156
2f22b19
eae242d
a100e9f
cfd4a39
e55da26
84ababa
68e7ac5
75ca8e0
ca84e57
9011796
e046615
1b6bb01
34e53ab
0c4d712
ecced9c
dd82e11
93e863e
b30f30d
aa29627
59ea821
cb3ba22
22408a3
db543c6
59665f1
a2aafc2
c518f87
1f0a657
f84b246
bf0da64
d3f24e4
92d3e3b
3014939
67f60f5
0dff5da
6311cfa
871b1b0
d2bc478
1390907
2ffe01d
aec137b
7ee24ba
d7a7d71
f8acba2
bc92ae8
67b7cf2
197deed
f63653a
7ab06e9
2f77491
d2b64c4
c6a43bc
7270d74
3d2bcb8
e87e00d
cd82ac1
f6fd807
b704d88
9ca53ac
4b19950
0188262
04cab37
0ec2c60
e103142
f863332
5c07b56
db0f140
5e99fcb
9a53da1
4c4bc81
d3dc47b
f171029
5d60788
5d173a2
ab1e404
a83ac24
c61ceb3
95598b5
22e84d5
fd9e6af
3bbab7d
a16e541
10e42f4
6801e20
dbde5bb
28f3641
dd862b3
17c3d71
8f7ca33
b69e989
ac8a189
181ffc0
45e1441
b8d8182
cb7cee1
66a9882
d93c196
11e059c
9aee330
a5be4a5
f1d6165
4ff6f21
0e1575c
adac3e4
50e6a72
a09c446
01164f7
6a82590
cd36868
89d0784
9ea3cb2
21b9f1f
f777c74
06518b7
ee9b4b1
c0c6e23
2537158
33b3f30
f021569
d01c58b
656e0bc
560df63
4565dbb
4c73871
6d798d1
8f987dc
63f0b34
33b78fb
7809af8
71ade6f
3fdc40b
a6ee470
fab3586
d77d215
3681cdf
d3d8ac0
62b4d29
6d937bf
971402c
76679b9
428f959
6616bfa
61a59ac
d7704b7
85e6cc1
79dd955
e1c0d66
d88ef7b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| using OrdinaryDiffEqLowStorageRK | ||
| using Trixi | ||
|
|
||
| ############################################################################### | ||
| # semidiscretization of the compressible Euler equations | ||
| equations = CompressibleEulerEquations2D(1.4) | ||
|
|
||
| # We repeat test case for stability of EC fluxes from paper | ||
| #- Gregor J. Gassner, Magnus Svärd, Florian J. Hindenlang (2020) | ||
| # Stability issues of entropy-stable and/or split-form high-order schemes | ||
| # [DOI: 10.1007/s10915-021-01720-8](https://doi.org/10.1007/s10915-021-01720-8) | ||
| initial_condition = initial_condition_density_wave | ||
|
|
||
| surface_flux = flux_lax_friedrichs | ||
| volume_flux = flux_chandrashekar | ||
|
|
||
| polydeg = 5 | ||
| basis = LobattoLegendreBasis(polydeg) | ||
|
|
||
| volume_integral_weakform = VolumeIntegralWeakForm() | ||
| volume_integral_fluxdiff = VolumeIntegralFluxDifferencing(volume_flux) | ||
|
|
||
| # This indicator compares the entropy production of the weak form to the | ||
| # entropy-conserving flux-differencing volume integral. | ||
| # If the entropy production of the weak form is lower than that of the | ||
| # flux-differencing form, we use the flux-differencing form to stabilize the solution. | ||
| indicator = IndicatorEntropyDiffusion(equations, basis) | ||
|
|
||
| # Adaptive volume integral using the entropy production comparison indicator to perform the | ||
| # stabilized/EC volume integral when needed and keeping the weak form if it is more diffusive. | ||
| volume_integral = VolumeIntegralAdaptive(volume_integral_default = volume_integral_weakform, | ||
| volume_integral_stabilized = volume_integral_fluxdiff, | ||
| indicator = indicator) | ||
|
|
||
| #volume_integral = volume_integral_weakform # Stable, but unphysical entropy increase! | ||
| #volume_integral = volume_integral_fluxdiff # Crashes! | ||
|
|
||
| solver = DGSEM(polydeg = polydeg, surface_flux = surface_flux, | ||
| volume_integral = volume_integral) | ||
|
|
||
| coordinates_min = (-1.0, -1.0) | ||
| coordinates_max = (1.0, 1.0) | ||
| mesh = TreeMesh(coordinates_min, coordinates_max, | ||
| initial_refinement_level = 2, # 4 x 4 elements | ||
| n_cells_max = 30_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 = 1000 | ||
| analysis_callback = AnalysisCallback(semi, interval = analysis_interval, | ||
| extra_analysis_integrals = (entropy,)) | ||
|
|
||
| alive_callback = AliveCallback(analysis_interval = analysis_interval) | ||
|
|
||
| stepsize_callback = StepsizeCallback(cfl = 0.9) # In paper, CFL = 0.05 is used | ||
|
|
||
| callbacks = CallbackSet(summary_callback, | ||
| analysis_callback, alive_callback, | ||
| stepsize_callback) | ||
|
|
||
| ############################################################################### | ||
| # run the simulation | ||
|
|
||
| sol = solve(ode, CarpenterKennedy2N54(williamson_condition = false); | ||
| dt = 1.0, ode_default_options()..., callback = callbacks); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,93 @@ | ||
| using OrdinaryDiffEqLowStorageRK | ||
| using Trixi | ||
|
|
||
| ############################################################################### | ||
| # 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 | ||
| - Andrés M. Rueda-Ramírez, Gregor J. Gassner (2021) | ||
| A Subcell Finite Volume Positivity-Preserving Limiter for DGSEM Discretizations | ||
| 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 | ||
| RealT = eltype(x) | ||
| slope = 15 | ||
| B = tanh(slope * x[2] + 7.5f0) - tanh(slope * x[2] - 7.5f0) | ||
| rho = 0.5f0 + 0.75f0 * B | ||
| v1 = 0.5f0 * (B - 1) | ||
| v2 = convert(RealT, 0.1) * sinpi(2 * x[1]) | ||
| p = 1 | ||
| return prim2cons(SVector(rho, v1, v2, p), equations) | ||
| end | ||
| initial_condition = initial_condition_kelvin_helmholtz_instability | ||
|
|
||
| surface_flux = flux_hllc | ||
| volume_flux = flux_ranocha | ||
| polydeg = 3 | ||
| basis = LobattoLegendreBasis(polydeg) | ||
|
|
||
| volume_integral_weakform = VolumeIntegralWeakForm() | ||
| volume_integral_fluxdiff = VolumeIntegralFluxDifferencing(volume_flux) | ||
|
|
||
| # This indicator compares the entropy production of the weak form to the | ||
| # entropy-conserving flux-differencing volume integral. | ||
| # If the entropy production of the weak form is lower than that of the | ||
| # flux-differencing form, we use the flux-differencing form to stabilize the solution. | ||
| indicator = IndicatorEntropyDiffusion(equations, basis) | ||
|
|
||
| # Adaptive volume integral using the entropy production comparison indicator to perform the | ||
| # stabilized/EC volume integral when needed and keeping the weak form if it is more diffusive. | ||
| volume_integral = VolumeIntegralAdaptive(volume_integral_default = volume_integral_weakform, | ||
| volume_integral_stabilized = volume_integral_fluxdiff, | ||
| indicator = indicator) | ||
|
|
||
| #volume_integral = volume_integral_weakform # Crashes | ||
| #volume_integral = volume_integral_fluxdiff # Crashes as well! | ||
|
|
||
| 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 = 6, | ||
| n_cells_max = 100_000) | ||
| semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver) | ||
|
|
||
| ############################################################################### | ||
| # ODE solvers, callbacks etc. | ||
|
|
||
| tspan = (0.0, 5.25) | ||
| ode = semidiscretize(semi, tspan) | ||
|
|
||
| summary_callback = SummaryCallback() | ||
|
|
||
| analysis_interval = 1000 | ||
| analysis_callback = AnalysisCallback(semi, interval = analysis_interval, | ||
| analysis_errors = Symbol[], | ||
| extra_analysis_integrals = (entropy,), | ||
| save_analysis = true) | ||
|
|
||
| alive_callback = AliveCallback(alive_interval = 200) | ||
|
|
||
| stepsize_callback = StepsizeCallback(cfl = 1.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 | ||
| ode_default_options()..., callback = callbacks); |
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -280,6 +280,58 @@ function Base.show(io::IO, mime::MIME"text/plain", | |||||||||||||||
| end | ||||||||||||||||
| end | ||||||||||||||||
|
|
||||||||||||||||
| """ | ||||||||||||||||
| VolumeIntegralAdaptive(; | ||||||||||||||||
| volume_integral_default = VolumeIntegralWeakForm(), | ||||||||||||||||
| volume_integral_stabilized = VolumeIntegralFluxDifferencing(flux_central), | ||||||||||||||||
|
DanielDoehring marked this conversation as resolved.
Outdated
|
||||||||||||||||
| indicator = IndicatorEntropyDiffusion()) | ||||||||||||||||
|
|
||||||||||||||||
| !!! warning "Experimental code" | ||||||||||||||||
| This code is experimental and may change in any future release. | ||||||||||||||||
|
|
||||||||||||||||
| Possible combinations: | ||||||||||||||||
| - [`VolumeIntegralWeakForm`](@ref), [`VolumeIntegralFluxDifferencing`](@ref), and [`IndicatorEntropyDiffusion()`](@ref) | ||||||||||||||||
| """ | ||||||||||||||||
| struct VolumeIntegralAdaptive{VolumeIntegralDefault, VolumeIntegralStabilized, | ||||||||||||||||
| Indicator} <: AbstractVolumeIntegral | ||||||||||||||||
| volume_integral_default::VolumeIntegralDefault # Cheap(er) default volume integral to be used in non-critical regions | ||||||||||||||||
| volume_integral_stabilized::VolumeIntegralStabilized # More expensive volume integral with stabilizing effect | ||||||||||||||||
| indicator::Indicator | ||||||||||||||||
| end | ||||||||||||||||
|
Comment on lines
+286
to
+302
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This new version should also work for you @jlchan, right? we would then dispatch
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes! I actually also made the change recently in Lines 309 to 315 in 97504dd
Happy to unify things under
DanielDoehring marked this conversation as resolved.
|
||||||||||||||||
|
|
||||||||||||||||
| function VolumeIntegralAdaptive(; | ||||||||||||||||
| volume_integral_default = VolumeIntegralWeakForm(), | ||||||||||||||||
| volume_integral_stabilized = VolumeIntegralFluxDifferencing(flux_central), | ||||||||||||||||
| indicator = IndicatorEntropyDiffusion()) | ||||||||||||||||
| return VolumeIntegralAdaptive{typeof(volume_integral_default), | ||||||||||||||||
| typeof(volume_integral_stabilized), | ||||||||||||||||
| typeof(indicator)}(volume_integral_default, | ||||||||||||||||
| volume_integral_stabilized, | ||||||||||||||||
| indicator) | ||||||||||||||||
| end | ||||||||||||||||
|
|
||||||||||||||||
| function Base.show(io::IO, mime::MIME"text/plain", | ||||||||||||||||
| integral::VolumeIntegralAdaptive) | ||||||||||||||||
| @nospecialize integral # reduce precompilation time | ||||||||||||||||
|
|
||||||||||||||||
| if get(io, :compact, false) | ||||||||||||||||
| show(io, integral) | ||||||||||||||||
| else | ||||||||||||||||
| summary_header(io, "VolumeIntegralAdaptive") | ||||||||||||||||
| summary_line(io, "volume integral default", | ||||||||||||||||
| integral.volume_integral_default) | ||||||||||||||||
| summary_line(io, "volume integral stabilized", | ||||||||||||||||
| integral.volume_integral_stabilized) | ||||||||||||||||
| if integral.indicator === nothing | ||||||||||||||||
| summary_line(io, "indicator", integral.indicator) | ||||||||||||||||
| else | ||||||||||||||||
| summary_line(io, "indicator", integral.indicator |> typeof |> nameof) | ||||||||||||||||
| show(increment_indent(io), mime, integral.indicator) | ||||||||||||||||
| end | ||||||||||||||||
| summary_footer(io) | ||||||||||||||||
| end | ||||||||||||||||
| end | ||||||||||||||||
|
|
||||||||||||||||
| # Abstract supertype for first-order `VolumeIntegralPureLGLFiniteVolume` and | ||||||||||||||||
| # second-order `VolumeIntegralPureLGLFiniteVolumeO2` subcell-based finite volume | ||||||||||||||||
| # volume integrals. | ||||||||||||||||
|
|
||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,6 +12,17 @@ function create_cache(mesh, equations, | |
| return NamedTuple() | ||
| end | ||
|
|
||
| function create_cache(mesh, equations, | ||
| volume_integral::VolumeIntegralAdaptive, | ||
| dg::DG, cache_containers, uEltype) | ||
| # This assumes that `volume_integral.volume_integral_default` needs no special cache! | ||
| @assert volume_integral.volume_integral_default isa VolumeIntegralWeakForm | ||
|
|
||
| return create_cache(mesh, equations, | ||
| volume_integral.volume_integral_stabilized, | ||
| dg, cache_containers, uEltype) | ||
| end | ||
|
|
||
|
DanielDoehring marked this conversation as resolved.
Outdated
|
||
| # The following `calc_volume_integral!` functions are | ||
| # dimension and meshtype agnostic, i.e., valid for all 1D, 2D, and 3D meshes. | ||
|
|
||
|
|
@@ -123,6 +134,68 @@ function calc_volume_integral!(du, u, mesh, | |
| return nothing | ||
| end | ||
|
|
||
| # Calculate ∫_e (∂S/∂u ⋅ ∂u/∂t) dΩ_e where "e" is an element | ||
| function calc_entropy_change_element(du, u, element, | ||
| mesh::AbstractMesh{2}, equations, dg, cache) | ||
| return integrate_element_ref(u, element, mesh, equations, dg, cache, | ||
| du) do u, i, j, element, equations, dg, du | ||
| u_node = get_node_vars(u, equations, dg, i, j, element) | ||
| du_node = get_node_vars(du, equations, dg, i, j, element) | ||
| # Minus sign because of the flipped sign in the DG RHS. | ||
| # No scaling by inverse Jacobian here, as there is no Jacobian multiplication | ||
| # in `integrate_element_ref`. | ||
| -dot(cons2entropy(u_node, equations), du_node) | ||
| end | ||
| end | ||
|
DanielDoehring marked this conversation as resolved.
Outdated
|
||
|
|
||
| function calc_volume_integral!(du, u, mesh, | ||
| have_nonconservative_terms, equations, | ||
| volume_integral::VolumeIntegralAdaptive{VolumeIntegralWeakForm, | ||
| VolumeIntegralFD, | ||
| Indicator}, | ||
|
DanielDoehring marked this conversation as resolved.
Outdated
|
||
| dg::DGSEM, | ||
| cache) where { | ||
| VolumeIntegralFD <: | ||
| VolumeIntegralFluxDifferencing, | ||
| Indicator <: IndicatorEntropyDiffusion} | ||
| @unpack volume_integral_default, volume_integral_stabilized = volume_integral | ||
| @unpack du_element_threaded = volume_integral.indicator | ||
|
|
||
| @threaded for element in eachelement(dg, cache) | ||
| # Compute weak form volume integral | ||
| weak_form_kernel!(du, u, element, mesh, | ||
| have_nonconservative_terms, equations, | ||
| dg, cache) | ||
|
|
||
| # Compute entropy production of WF volume integral | ||
| entropy_delta_WF = calc_entropy_change_element(du, u, element, | ||
| mesh, equations, dg, cache) | ||
| # Store weak form result | ||
| du_element_WF = du_element_threaded[Threads.threadid()] | ||
| @views du_element_WF .= du[.., element] | ||
|
|
||
| # Reset weak form volume integral | ||
| du[.., element] .= zero(eltype(du)) | ||
|
|
||
| # Recompute using entropy-conservative volume integral | ||
| flux_differencing_kernel!(du, u, element, mesh, | ||
| have_nonconservative_terms, equations, | ||
| volume_integral_stabilized.volume_flux, | ||
| dg, cache) | ||
|
DanielDoehring marked this conversation as resolved.
Outdated
|
||
|
|
||
| # Compute entropy production of FD volume integral | ||
| entropy_delta_FD = calc_entropy_change_element(du, u, element, | ||
| mesh, equations, dg, cache) | ||
|
|
||
| entropy_delta = entropy_delta_WF - entropy_delta_FD | ||
| if entropy_delta < 0 # Use weak form if it is more stable | ||
| @views du[.., element] .= du_element_WF | ||
| end | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is the something I'm a little concerned about - it's a hard switch between two different volume integral evaluations, which I don't think is differentiable with respect to the solution and can lead to a large number of adaptive time-steps.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If there is a way to make this differentiable it might improve adaptive time-stepping performance.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess you could also blend the central (weak form) flux and the EC flux - I fear that this might destroy accuracy though |
||
| end | ||
|
|
||
| return nothing | ||
| end | ||
|
|
||
| function calc_volume_integral!(du, u, mesh, | ||
| have_nonconservative_terms, equations, | ||
| volume_integral::VolumeIntegralPureLGLFiniteVolume, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -133,5 +133,6 @@ end | |
| end | ||
|
|
||
| include("containers.jl") | ||
| include("indicators.jl") | ||
| include("calc_volume_integral.jl") | ||
| end # @muladd | ||
Uh oh!
There was an error while loading. Please reload this page.