Skip to content
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

PERK4 standalone #2147

Open
wants to merge 80 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
4f95871
PERK4 with imported coefficients
DanielDoehring Nov 5, 2024
3b84504
examples, more constructors
DanielDoehring Nov 6, 2024
749a505
typos
DanielDoehring Nov 6, 2024
8ce7825
comments
DanielDoehring Nov 6, 2024
fe625ca
Merge branch 'main' into PERK4_Standalone
DanielDoehring Nov 6, 2024
072693a
Update src/time_integration/paired_explicit_runge_kutta/methods_PERK2.jl
DanielDoehring Nov 8, 2024
5266a6c
Make `PairedExplicitRK2` constructors consistent
DanielDoehring Dec 1, 2024
ba49773
Make PERK2 constructor consistent
DanielDoehring Dec 1, 2024
c486b8b
changes
DanielDoehring Dec 1, 2024
cd2e868
Update NEWS.md
DanielDoehring Dec 2, 2024
5a30178
Merge branch 'main' into PERK4_Standalone
DanielDoehring Dec 3, 2024
7ba71b0
Merge branch 'PERK4_Standalone' of github.com:DanielDoehring/Trixi.jl…
DanielDoehring Dec 3, 2024
fb21c9e
version
DanielDoehring Dec 3, 2024
fb02916
cosmetics
DanielDoehring Dec 3, 2024
3e23122
remove func
DanielDoehring Dec 3, 2024
4cea3a9
remove unused func
DanielDoehring Dec 3, 2024
69a1e5e
make timestep computable perk4 s=5
DanielDoehring Dec 3, 2024
676ebac
compute dt for no opt vars
DanielDoehring Dec 3, 2024
a1df22d
float
DanielDoehring Dec 3, 2024
42faa7a
Merge branch 'main' into PERK4_Standalone
DanielDoehring Dec 3, 2024
2f8e265
Merge branch 'main' into PERK4_Standalone
DanielDoehring Dec 3, 2024
7b8b166
mention perk4
DanielDoehring Dec 3, 2024
921a3b9
Apply suggestions from code review
DanielDoehring Dec 5, 2024
5c4fce2
prevent readdlm error for S=2
DanielDoehring Dec 10, 2024
880aad2
Merge branch 'PERK2ConstructorConsistence' of github.com:DanielDoehri…
DanielDoehring Dec 10, 2024
6a7e244
Merge branch 'main' into PERK4_Standalone
DanielDoehring Dec 10, 2024
7728de0
Warisa's comments
DanielDoehring Dec 10, 2024
a7cc385
Merge branch 'PERK4_Standalone' of github.com:DanielDoehring/Trixi.jl…
DanielDoehring Dec 10, 2024
2a9d8c4
rename
DanielDoehring Dec 10, 2024
6badb45
PERK2 compute c coeffs
DanielDoehring Dec 10, 2024
b232eec
comment
DanielDoehring Dec 10, 2024
b29c700
bugfix
DanielDoehring Dec 10, 2024
283c385
Update docs/src/time_integration.md
DanielDoehring Dec 10, 2024
c5b48a5
debug
DanielDoehring Dec 10, 2024
44f4ebe
rename
DanielDoehring Dec 10, 2024
2244572
Update src/time_integration/paired_explicit_runge_kutta/methods_PERK4.jl
DanielDoehring Dec 19, 2024
8771f95
Apply suggestions from code review
DanielDoehring Dec 19, 2024
ddf79be
Merge branch 'main' into PERK4_Standalone
DanielDoehring Dec 19, 2024
1001f65
fix
DanielDoehring Dec 19, 2024
e9c988e
Apply suggestions from code review
DanielDoehring Dec 19, 2024
1044bac
view
DanielDoehring Dec 19, 2024
dc76fa7
Update ext/TrixiConvexECOSExt.jl
DanielDoehring Dec 19, 2024
28b6e2f
news
DanielDoehring Dec 20, 2024
438d9d2
comments
DanielDoehring Dec 28, 2024
298a376
Merge branch 'main' into PERK4_Standalone
DanielDoehring Dec 28, 2024
e106776
comment
DanielDoehring Dec 28, 2024
b3611aa
Merge branch 'PERK4_Standalone' of github.com:DanielDoehring/Trixi.jl…
DanielDoehring Dec 28, 2024
cdd6cb8
Update src/time_integration/paired_explicit_runge_kutta/methods_PERK4.jl
DanielDoehring Jan 2, 2025
b9415db
plural
DanielDoehring Jan 2, 2025
47c6ea6
explain `tdir`
DanielDoehring Jan 2, 2025
2ea9487
remove comment
DanielDoehring Jan 3, 2025
dff1ffe
additional if clause
DanielDoehring Jan 3, 2025
3959cb8
use broadcasting for copy operation
DanielDoehring Jan 7, 2025
a2f2ba4
Merge branch 'main' into PERK4_Standalone
DanielDoehring Jan 7, 2025
d5eea18
Update src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl
DanielDoehring Jan 7, 2025
1ad0d61
Update src/time_integration/paired_explicit_runge_kutta/methods_PERK4.jl
DanielDoehring Jan 7, 2025
6da79d6
Merge branch 'main' into PERK4_Standalone
DanielDoehring Jan 8, 2025
d54ef10
Merge branch 'main' into PERK2ConstructorConsistence
DanielDoehring Jan 8, 2025
985dc5f
fix merge errors
DanielDoehring Jan 8, 2025
1c787df
fix errors
DanielDoehring Jan 8, 2025
3437831
Merge branch 'PERK2ConstructorConsistence' into PERK4_Standalone
DanielDoehring Jan 8, 2025
10574df
Merge branch 'PERK4_Standalone' of github.com:DanielDoehring/Trixi.jl…
DanielDoehring Jan 8, 2025
01471d5
typo
DanielDoehring Jan 8, 2025
3bec564
fix errors
DanielDoehring Jan 8, 2025
3167a1b
Merge branch 'main' into PERK4_Standalone
DanielDoehring Jan 8, 2025
62de7f6
Merge branch 'main' into PERK4_Standalone
DanielDoehring Jan 9, 2025
88000ea
completeness
DanielDoehring Jan 9, 2025
411f657
Merge branch 'PERK4_Standalone' of github.com:DanielDoehring/Trixi.jl…
DanielDoehring Jan 9, 2025
22b9a50
Apply suggestions from code review
DanielDoehring Jan 9, 2025
164794c
make t_end function
DanielDoehring Jan 9, 2025
68cec10
avoid globals
DanielDoehring Jan 9, 2025
926a097
Apply suggestions from code review
DanielDoehring Jan 9, 2025
5bba4cd
i.e.,
DanielDoehring Jan 9, 2025
366b84f
shorten opt ext
DanielDoehring Jan 10, 2025
40c4f09
typos
DanielDoehring Jan 10, 2025
4195f72
revert
DanielDoehring Jan 10, 2025
99f754b
shorten
DanielDoehring Jan 10, 2025
c416a81
do not export
DanielDoehring Jan 10, 2025
0ba9120
convert float
DanielDoehring Jan 10, 2025
cb23fe6
remove first blank line
DanielDoehring Jan 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 115 additions & 0 deletions examples/structured_2d_dgsem/elixir_euler_vortex_perk4.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@

using OrdinaryDiffEq # Required for `CallbackSet`
DanielDoehring marked this conversation as resolved.
Show resolved Hide resolved
using Trixi

# Ratio of specific heats
gamma = 1.4
equations = CompressibleEulerEquations2D(gamma)

solver = DGSEM(polydeg = 3, surface_flux = flux_hllc)

"""
initial_condition_isentropic_vortex(x, t, equations::CompressibleEulerEquations2D)

The classical isentropic vortex test case as presented in Section 5.1 of

- Brian Vermeire (2019).
Paired Explicit Runge-Kutta Schemes for Stiff Systems of Equations
[DOI:10.1016/j.jcp.2019.05.014](https://doi.org/10.1016/j.jcp.2019.05.014)
https://spectrum.library.concordia.ca/id/eprint/985444/1/Paired-explicit-Runge-Kutta-schemes-for-stiff-sy_2019_Journal-of-Computation.pdf
"""
function initial_condition_isentropic_vortex(x, t, equations::CompressibleEulerEquations2D)
# Evaluate error after full domain traversion
if t == T_end
t = 0
end

# initial center of the vortex
inicenter = SVector(0.0, 0.0)
# strength of the vortex
S = 13.5
# Radius of vortex
R = 1.5
# Free-stream Mach
M = 0.4
# base flow
v1 = 1.0
v2 = 1.0
vel = SVector(v1, v2)

center = inicenter + vel * t # advection of center
center = x - center # distance to centerpoint
center = SVector(center[2], -center[1])
r2 = center[1]^2 + center[2]^2

f = (1 - r2) / (2 * R^2)

rho = (1 - (S * M / pi)^2 * (gamma - 1) * exp(2 * f) / 8)^(1 / (gamma - 1))

du = S / (2 * π * R) * exp(f) # vel. perturbation
vel = vel + du * center
v1, v2 = vel

p = rho^gamma / (gamma * M^2)
prim = SVector(rho, v1, v2, p)
return prim2cons(prim, equations)
end
initial_condition = initial_condition_isentropic_vortex

EdgeLength = 20

N_passes = 1
T_end = EdgeLength * N_passes
DanielDoehring marked this conversation as resolved.
Show resolved Hide resolved
tspan = (0.0, T_end)

coordinates_min = (-EdgeLength / 2, -EdgeLength / 2)
coordinates_max = (EdgeLength / 2, EdgeLength / 2)
DanielDoehring marked this conversation as resolved.
Show resolved Hide resolved

cells_per_dimension = (32, 32)
mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max)

semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver)

ode = semidiscretize(semi, tspan)

###############################################################################
# Callbacks

summary_callback = SummaryCallback()

analysis_interval = 100
analysis_callback = AnalysisCallback(semi, interval = analysis_interval,
analysis_integrals = (entropy,))

# Note quite large CFL number
stepsize_callback = StepsizeCallback(cfl = 9.1)

callbacks = CallbackSet(summary_callback,
stepsize_callback,
analysis_callback)

###############################################################################
# set up time integration algorithm

num_stages = 19

current_directory = @__DIR__
DanielDoehring marked this conversation as resolved.
Show resolved Hide resolved
coefficient_file = "a_" * string(num_stages) * ".txt"

# Download the optimized PERK4 coefficients
Trixi.download("https://gist.githubusercontent.com/DanielDoehring/84f266ff61f0a69a0127cec64056275e/raw/1a66adbe1b425d33daf502311ecbdd4b191b89cc/a_19.txt",
joinpath(current_directory, coefficient_file))
DanielDoehring marked this conversation as resolved.
Show resolved Hide resolved

ode_algorithm = Trixi.PairedExplicitRK4(num_stages, current_directory)
DanielDoehring marked this conversation as resolved.
Show resolved Hide resolved
DanielDoehring marked this conversation as resolved.
Show resolved Hide resolved

###############################################################################
# run the simulation

sol = Trixi.solve(ode, ode_algorithm,
dt = 42.0, # Not used
DanielDoehring marked this conversation as resolved.
Show resolved Hide resolved
save_everystep = false, callback = callbacks);

# Clean up the downloaded file
rm(joinpath(current_directory, coefficient_file))

summary_callback()
65 changes: 65 additions & 0 deletions examples/tree_1d_dgsem/elixir_hypdiff_nonperiodic_perk4.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@

using OrdinaryDiffEq # Required for `CallbackSet`
DanielDoehring marked this conversation as resolved.
Show resolved Hide resolved
using Trixi

# Convex and ECOS are imported because they are used for finding the optimal time step and optimal
# monomial coefficients in the stability polynomial of P-ERK time integrators.
using Convex, ECOS

###############################################################################
# semidiscretization of the hyperbolic diffusion equations

equations = HyperbolicDiffusionEquations1D()

initial_condition = initial_condition_poisson_nonperiodic

boundary_conditions = boundary_condition_poisson_nonperiodic

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)

semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver,
boundary_conditions = boundary_conditions,
source_terms = source_terms_poisson_nonperiodic)

###############################################################################
# ODE solvers, callbacks etc.

tspan = (0.0, 5.0)
ode = semidiscretize(semi, tspan);

summary_callback = SummaryCallback()

resid_tol = 5.0e-12
steady_state_callback = SteadyStateCallback(abstol = resid_tol, reltol = 0.0)

analysis_interval = 100
analysis_callback = AnalysisCallback(semi, interval = analysis_interval)

alive_callback = AliveCallback(analysis_interval = analysis_interval)

# Construct fourth order paired explicit Runge-Kutta method with 11 stages for given simulation setup.
# Pass `tspan` to calculate maximum time step allowed for the bisection algorithm used
# in calculating the polynomial coefficients in the ODE algorithm.
ode_algorithm = Trixi.PairedExplicitRK4(11, tspan, semi)

cfl_number = Trixi.calculate_cfl(ode_algorithm, ode)
stepsize_callback = StepsizeCallback(cfl = 0.9 * cfl_number)

callbacks = CallbackSet(summary_callback,
analysis_callback, alive_callback,
stepsize_callback)

###############################################################################
# run the simulation

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);
summary_callback() # print the timer summary
138 changes: 134 additions & 4 deletions ext/TrixiConvexECOSExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ end
using LinearAlgebra: eigvals

# Use functions that are to be extended and additional symbols that are not exported
using Trixi: Trixi, undo_normalization!, bisect_stability_polynomial, @muladd
using Trixi: Trixi, undo_normalization!, undo_normalization_PERK4!,
bisect_stability_polynomial, bisect_stability_polynomial_PERK4, @muladd

# By default, Julia/LLVM does not use fused multiply-add operations (FMAs).
# Since these FMAs can increase the performance of many numerical algorithms,
Expand All @@ -28,10 +29,14 @@ using Trixi: Trixi, undo_normalization!, bisect_stability_polynomial, @muladd
# relative to consistency order.
function Trixi.undo_normalization!(gamma_opt, consistency_order, num_stage_evals)
for k in (consistency_order + 1):num_stage_evals
gamma_opt[k - consistency_order] = gamma_opt[k - consistency_order] /
factorial(k)
gamma_opt[k - consistency_order] /= factorial(k)
end
end

function Trixi.undo_normalization_PERK4!(gamma_opt, num_stage_evals)
for k in 1:(num_stage_evals - 5)
gamma_opt[k] /= factorial(k + 4)
DanielDoehring marked this conversation as resolved.
Show resolved Hide resolved
end
return gamma_opt
end

# Compute stability polynomials for paired explicit Runge-Kutta up to specified consistency
Expand Down Expand Up @@ -63,6 +68,44 @@ function stability_polynomials!(pnoms, consistency_order, num_stage_evals,
return maximum(abs(pnoms))
end

# Specialized form of the stability polynomials for fourth-order PERK schemes.
function stability_polynomials_PERK4!(pnoms, num_stage_evals,
normalized_powered_eigvals,
gamma, dt, cS3)
DanielDoehring marked this conversation as resolved.
Show resolved Hide resolved
num_eig_vals = length(pnoms)
DanielDoehring marked this conversation as resolved.
Show resolved Hide resolved
DanielDoehring marked this conversation as resolved.
Show resolved Hide resolved

# Constants arising from the particular form of Butcher tableau chosen for the 4th order PERK methods
k1 = 0.001055026310046423 / cS3
k2 = 0.03726406530405851 / cS3
# Note: `cS3` = c_{S-3} is in principle free, while the other abscissae are fixed to 1.0

# Initialize with zero'th order (z^0) coefficient
for i in 1:num_eig_vals
pnoms[i] = 1.0
end

# First `consistency_order` = 4 terms of the exponential
for k in 1:4
for i in 1:num_eig_vals
pnoms[i] += dt^k * normalized_powered_eigvals[i, k]
end
end

DanielDoehring marked this conversation as resolved.
Show resolved Hide resolved
# "Fixed" term due to choice of the PERK4 Butcher tableau
# Required to un-do the normalization of the eigenvalues here
pnoms += k1 * dt^5 * normalized_powered_eigvals[:, 5] * factorial(5)
DanielDoehring marked this conversation as resolved.
Show resolved Hide resolved

# Contribution from free coefficients
for k in 1:(num_stage_evals - 5)
pnoms += (k2 * dt^(k + 4) * normalized_powered_eigvals[:, k + 4] * gamma[k] +
k1 * dt^(k + 5) * normalized_powered_eigvals[:, k + 5] * gamma[k] *
DanielDoehring marked this conversation as resolved.
Show resolved Hide resolved
(k + 5))
end

# For optimization only the maximum is relevant
return maximum(abs(pnoms))
end

#=
The following structures and methods provide a simplified implementation to
discover optimal stability polynomial for a given set of `eig_vals`
Expand Down Expand Up @@ -158,6 +201,93 @@ function Trixi.bisect_stability_polynomial(consistency_order, num_eig_vals,
gamma_opt = [gamma_opt]
end

undo_normalization!(gamma_opt, consistency_order, num_stage_evals)

return gamma_opt, dt
end

# Specialized routine for PERK4.
# For details, see Section 4 in
# - D. Doehring, L. Christmann, M. Schlottke-Lakemper, G. J. Gassner and M. Torrilhon (2024).
# Fourth-Order Paired-Explicit Runge-Kutta Methods
# [DOI:10.48550/arXiv.2408.05470](https://doi.org/10.48550/arXiv.2408.05470)
function Trixi.bisect_stability_polynomial_PERK4(num_eig_vals,
num_stage_evals,
dtmax, dteps, eig_vals, cS3;
verbose = false)
DanielDoehring marked this conversation as resolved.
Show resolved Hide resolved
dtmin = 0.0
dt = -1.0
abs_p = -1.0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of this is restricted to Float64.

  • Would it make sense to generalize it to also allow Float32?
  • Shall we mention the restriction somewhere in the docs?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, since this is esssentially preprocessing I think it is okay to do this in higher precision. What needs to be revisited, though, is the datatype of the actual butcher arrays, i.e.,

a_matrix::Matrix{Float64}
c::Vector{Float64}


# Construct stability polynomial for each eigenvalue
pnoms = ones(Complex{Float64}, num_eig_vals, 1)

# Init datastructure for monomial coefficients
gamma = Variable(num_stage_evals - 5)
DanielDoehring marked this conversation as resolved.
Show resolved Hide resolved

normalized_powered_eigvals = zeros(Complex{Float64}, num_eig_vals, num_stage_evals)

for j in 1:num_stage_evals
fac_j = factorial(j)
for i in 1:num_eig_vals
normalized_powered_eigvals[i, j] = eig_vals[i]^j / fac_j
end
end
DanielDoehring marked this conversation as resolved.
Show resolved Hide resolved

if verbose
println("Start optimization of stability polynomial \n")
end

# Bisection on timestep
while dtmax - dtmin > dteps
dt = 0.5 * (dtmax + dtmin)

# Use last optimal values for gamma in (potentially) next iteration
problem = minimize(stability_polynomials_PERK4!(pnoms,
num_stage_evals,
normalized_powered_eigvals,
gamma, dt, cS3))

DanielDoehring marked this conversation as resolved.
Show resolved Hide resolved
solve!(problem,
# Parameters taken from default values for EiCOS
MOI.OptimizerWithAttributes(Optimizer, "gamma" => 0.99,
"delta" => 2e-7,
"feastol" => 1e-9,
"abstol" => 1e-9,
"reltol" => 1e-9,
"feastol_inacc" => 1e-4,
"abstol_inacc" => 5e-5,
"reltol_inacc" => 5e-5,
"nitref" => 9,
"maxit" => 100,
"verbose" => 3); silent = true)

abs_p = problem.optval

if abs_p < 1
dtmin = dt
else
dtmax = dt
end
end

if verbose
println("Concluded stability polynomial optimization \n")
end

gamma_opt = []

if num_stage_evals > 5
gamma_opt = evaluate(gamma)

# Catch case S = 6 (only one opt. variable)
if isa(gamma_opt, Number)
gamma_opt = [gamma_opt]
end

undo_normalization_PERK4!(gamma_opt, num_stage_evals)
DanielDoehring marked this conversation as resolved.
Show resolved Hide resolved
end

return gamma_opt, dt
end
end # @muladd
Expand Down
Loading
Loading