From da330cc1318eca7c55694347c7f873ca24beb36b Mon Sep 17 00:00:00 2001 From: Warisa Date: Sat, 25 May 2024 17:52:44 +0200 Subject: [PATCH 001/120] make NLsolve a weapdep --- Project.toml | 6 +- .../elixir_burgers_perk3.jl | 56 +++ ext/TrixiNLsolveExt.jl | 62 +++ src/Trixi.jl | 6 + .../methods_PERK3.jl | 365 ++++++++++++++++++ .../paired_explicit_runge_kutta.jl | 6 + 6 files changed, 500 insertions(+), 1 deletion(-) create mode 100644 examples/structured_1d_dgsem/elixir_burgers_perk3.jl create mode 100644 ext/TrixiNLsolveExt.jl create mode 100644 src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl diff --git a/Project.toml b/Project.toml index b605cb2c6b..6ae18fb29a 100644 --- a/Project.toml +++ b/Project.toml @@ -53,10 +53,12 @@ UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" Convex = "f65535da-76fb-5f13-bab9-19810c17039a" ECOS = "e2685f51-7e38-5353-a97d-a921fd2c8199" +NLsolve = "2774e3e8-f4cf-5e23-947b-6d7e65073b56" [extensions] TrixiMakieExt = "Makie" TrixiConvexECOSExt = ["Convex", "ECOS"] +TrixiNLsolveExt = "NLsolve" [compat] CodeTracking = "1.0.5" @@ -79,6 +81,7 @@ LoopVectorization = "0.12.151" MPI = "0.20" Makie = "0.19, 0.20" MuladdMacro = "0.2.2" +NLsolve = "4.5.1" Octavian = "0.3.21" OffsetArrays = "1.12" P4est = "0.4.9" @@ -111,4 +114,5 @@ julia = "1.8" [extras] Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" Convex = "f65535da-76fb-5f13-bab9-19810c17039a" -ECOS = "e2685f51-7e38-5353-a97d-a921fd2c8199" \ No newline at end of file +ECOS = "e2685f51-7e38-5353-a97d-a921fd2c8199" +NLsolve = "2774e3e8-f4cf-5e23-947b-6d7e65073b56" \ No newline at end of file diff --git a/examples/structured_1d_dgsem/elixir_burgers_perk3.jl b/examples/structured_1d_dgsem/elixir_burgers_perk3.jl new file mode 100644 index 0000000000..3feb89c6b7 --- /dev/null +++ b/examples/structured_1d_dgsem/elixir_burgers_perk3.jl @@ -0,0 +1,56 @@ +using Convex, ECOS +using NLsolve +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the (inviscid) Burgers' equation + +equations = InviscidBurgersEquation1D() + +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 = 4, surface_flux = flux_lax_friedrichs) + +coordinates_min = (0.0,) # minimum coordinate +coordinates_max = (1.0,) # maximum coordinate +cells_per_dimension = (64,) + +# Create curved mesh with 16 cells +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, 2.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) + +stepsize_callback = StepsizeCallback() + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, + stepsize_callback) + +############################################################################### +# run the simulation + +ode_algorithm = Trixi.PairedExplicitRK3(8, tspan, semi) + +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); + +# Print the timer summary +summary_callback() +analysis_callback(sol) \ No newline at end of file diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl new file mode 100644 index 0000000000..47ea16707c --- /dev/null +++ b/ext/TrixiNLsolveExt.jl @@ -0,0 +1,62 @@ +# Package extension for adding Convex-based features to Trixi.jl +module TrixiNLsolveExt + +# Required for coefficient optimization in P-ERK scheme integrators +if isdefined(Base, :get_extension) + using NLsolve:nlsolve +else + # Until Julia v1.9 is the minimum required version for Trixi.jl, we still support Requires.jl + using ..NLsolve:nlsolve +end + +# Use functions and additional symbols that are not exported +using Trixi: Trixi, @muladd, PairedExplicitRK3_butcher_tableau_objective_function + +# Use functions that are to be extended +using Trixi: Trixi, solve_a_unknown + +# 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 + +# TODO: edit the comment this function +# Define the new function that includes the nlsolve features +function Trixi.solve_a_unknown(num_stages, monomial_coeffs, c_s2, c; verbose) + is_sol_valid = false + a_unknown = zeros(num_stages) + + # Define the objective_function + function objective_function(x) + return Trixi.PairedExplicitRK3_butcher_tableau_objective_function(x, num_stages, num_stages, + monomial_coeffs, c_s2) + end + + while !is_sol_valid + # Initialize initial guess + x0 = 0.1 .* rand(num_stages) + x0[1] = 0.0 + x0[2] = c[2] + + sol = nlsolve(objective_function, x0, method = :trust_region, ftol = 4e-16, + iterations = 10^4, xtol = 1e-13) + + a_unknown = sol.zero + + # Check if the values a[i, i-1] >= 0.0 (which stem from the nonlinear solver) and subsequently c[i] - a[i, i-1] >= 0.0 + is_sol_valid = all(x -> !isnan(x) && x >= 0, a_unknown[3:end]) && + all(x -> !isnan(x) && x >= 0, c[3:end] .- a_unknown[3:end]) + + if verbose && !is_sol_valid + println("Solution invalid. Restart the process of solving non-linear system of equations again.") + end + + end + + return a_unknown +end +end # @muladd + +end # module TrixiNLsolveExt diff --git a/src/Trixi.jl b/src/Trixi.jl index 3a882d0962..0b5f0d0f67 100644 --- a/src/Trixi.jl +++ b/src/Trixi.jl @@ -318,6 +318,12 @@ function __init__() end end + @static if !isdefined(Base, :get_extension) + @require NLsolve="2774e3e8-f4cf-5e23-947b-6d7e65073b56" begin + include("../ext/TrixiNLsolveExt.jl") + end + 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/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl new file mode 100644 index 0000000000..a44e78093a --- /dev/null +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -0,0 +1,365 @@ +# 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. +using DelimitedFiles: readdlm + +@muladd begin +#! format: noindent + +# Initialize Butcher array abscissae c for PairedExplicitRK3 based on SSPRK33 base method +function compute_c_coeff_SSP33(num_stages, c_s2) + c = zeros(num_stages) + + # Last timesteps as for SSPRK33 + c[num_stages] = 0.5 + c[num_stages - 1] = 1 + + # Linear increasing timestep for remainder + for i in 2:(num_stages - 2) + c[i] = c_s2 * (i - 1) / (num_stages - 3) + end + + return c +end + +function PairedExplicitRK3_butcher_tableau_objective_function(a_unknown, num_stages, + num_stage_evals, + monomial_coeffs, c_s2) + c_ts = compute_c_coeff_SSP33(num_stages, c_s2) # ts = timestep + + # Equality Constraint array that ensures that the stability polynomial computed from + # the to-be-constructed Butcher-Tableau matches the monomial coefficients of the + # optimized stability polynomial. + c_eq = zeros(num_stage_evals - 2) # Add equality constraint that c_s2 is equal to 1 + # Both terms should be present + for i in 1:(num_stage_evals - 4) + term1 = a_unknown[num_stage_evals - 1] + term2 = a_unknown[num_stage_evals] + for j in 1:i + term1 *= a_unknown[num_stage_evals - 1 - j] + term2 *= a_unknown[num_stage_evals - j] + end + term1 *= c_ts[num_stages - 2 - i] * 1 / 6 + term2 *= c_ts[num_stages - 1 - i] * 4 / 6 + + c_eq[i] = monomial_coeffs[i] - (term1 + term2) + end + + # Highest coefficient: Only one term present + i = num_stage_evals - 3 + term2 = a_unknown[num_stage_evals] + for j in 1:i + term2 *= a_unknown[num_stage_evals - j] + end + term2 *= c_ts[num_stages - 1 - i] * 4 / 6 + + c_eq[i] = monomial_coeffs[i] - term2 + c_eq[num_stage_evals - 2] = 1.0 - 4 * a_unknown[num_stage_evals] - + a_unknown[num_stage_evals - 1] + + return c_eq +end + +function compute_PairedExplicitRK3_butcher_tableau(num_stages, tspan, eig_vals::Vector{ComplexF64}; + verbose = false, c_s2) + # Initialize array of c + c = compute_c_coeff_SSP33(num_stages, c_s2) + + # Initialize the array of our solution + a_unknown = zeros(num_stages) + + # Special case of e = 3 + if num_stages == 3 + a_unknown = [0, c[2], 0.25] + else + # Calculate coefficients of the stability polynomial in monomial form + consistency_order = 3 + dtmax = tspan[2] - tspan[1] + dteps = 1e-9 + + num_eig_vals, eig_vals = filter_eig_vals(eig_vals; verbose) + + monomial_coeffs, dt_opt = bisect_stability_polynomial(consistency_order, + num_eig_vals, num_stages, + dtmax, + dteps, + eig_vals; verbose) + monomial_coeffs = undo_normalization!(monomial_coeffs, consistency_order, + num_stages) + + # Call function that use the library NLsolve to solve the nonlinear system + a_unknown = solve_a_unknown(num_stages, monomial_coeffs, c_s2, c; verbose) + end + + # For debugging purpose + println("a_unknown") + println(a_unknown[3:end]) + + a_matrix = zeros(num_stages - 2, 2) + a_matrix[:, 1] = c[3:end] + a_matrix[:, 1] -= a_unknown[3:end] + a_matrix[:, 2] = a_unknown[3:end] + + return a_matrix, c, dt_opt +end + +function compute_PairedExplicitRK3_butcher_tableau(num_stages, base_path_monomial_coeffs::AbstractString, + c_s2) + + # Initialize array of c + c = compute_c_coeff_SSP33(num_stages, c_s2) + + # - 2 Since First entry of A is always zero (explicit method) and second is given by c_2 (consistency) + coeffs_max = num_stages - 2 + + a_matrix = zeros(coeffs_max, 2) + a_matrix[:, 1] = c[3:end] + + # TODO: update this to work with CI mktempdir() + path_monomial_coeffs = base_path_monomial_coeffs * "a_" * string(num_stages) * "_" * + string(num_stages) * ".txt" + @assert isfile(path_monomial_coeffs) "Couldn't find file" + A = readdlm(path_monomial_coeffs, Float64) + num_monomial_coeffs = size(A, 1) + + @assert num_monomial_coeffs == coeffs_max + a_matrix[:, 1] -= A + a_matrix[:, 2] = A + + println("A matrix: ") + display(a_matrix) + println() + + return a_matrix, c +end + +""" + PairedExplicitRK3() +The following structures and methods provide a implementation of +the third-order paired explicit Runge-Kutta method +optimized for a certain simulation setup (PDE, IC & BC, Riemann Solver, DG Solver). +The original paper is +- Nasab, Vermeire (2022) +Third-order Paired Explicit Runge-Kutta schemes for stiff systems of equations +[DOI: 10.1016/j.jcp.2022.111470](https://doi.org/10.1016/j.jcp.2022.111470) +While the changes to SSPRK33 base-scheme are described in +- Doehring, Schlottke-Lakemper, Gassner, Torrilhon (2024) +Multirate Time-Integration based on Dynamic ODE Partitioning through Adaptively Refined Meshes for Compressible Fluid Dynamics +[Arxiv: 10.48550/arXiv.2403.05144](https://doi.org/10.48550/arXiv.2403.05144) +""" +mutable struct PairedExplicitRK3 <: AbstractPairedExplicitRKSingle + const num_stages::Int + + a_matrix::Matrix{Float64} + c::Vector{Float64} + dt_opt::Float64 +end # struct PairedExplicitRK3 + + # Constructor for previously computed A Coeffs + function PairedExplicitRK3(num_stages, base_path_monomial_coeffs::AbstractString, dt_opt; + c_s2 = 1.0) + + a_matrix, c = compute_PairedExplicitRK3_butcher_tableau(num_stages, + base_path_monomial_coeffs; + c_s2) + + return PairedExplicitRK3(num_stages, a_matrix, c, dt_opt) +end + +# Constructor that computes Butcher matrix A coefficients from a semidiscretization +function PairedExplicitRK3(num_stages, tspan, semi::AbstractSemidiscretization; + verbose = false, c_s2 = 1.0) + eig_vals = eigvals(jacobian_ad_forward(semi)) + + return PairedExplicitRK3(num_stages, tspan, eig_vals; verbose, c_s2) +end + +# Constructor that calculates the coefficients with polynomial optimizer from a list of eigenvalues +function PairedExplicitRK3(num_stages, tspan, eig_vals::Vector{ComplexF64}; + verbose = false, c_s2 = 1.0) + + a_matrix, c, dt_opt = compute_PairedExplicitRK3_butcher_tableau(num_stages, + tspan, + eig_vals; + verbose, c_s2) + return PairedExplicitRK3(num_stages, a_matrix, c, dt_opt) +end + + + +# This struct is needed to fake https://github.com/SciML/OrdinaryDiffEq.jl/blob/0c2048a502101647ac35faabd80da8a5645beac7/src/integrators/type.jl#L77 +# This implements the interface components described at +# https://diffeq.sciml.ai/v6.8/basics/integrator/#Handing-Integrators-1 +# which are used in Trixi. +mutable struct PairedExplicitRK3Integrator{RealT <: Real, uType, Params, Sol, F, Alg, + PairedExplicitRKOptions} <: AbstractPairedExplicitRKSingleIntegrator + u::uType + du::uType + u_tmp::uType + t::RealT + dt::RealT # current time step + dtcache::RealT # ignored + iter::Int # current number of time steps (iteration) + p::Params # will be the semidiscretization from Trixi + sol::Sol # faked + f::F + alg::Alg # This is our own class written above; Abbreviation for ALGorithm + opts::PairedExplicitRKOptions + finalstep::Bool # added for convenience + # PairedExplicitRK stages: + k1::uType + k_higher::uType + k_s1::uType # Required for custom third order version of PairedExplicitRK3 +end + +# Fakes `solve`: https://diffeq.sciml.ai/v6.8/basics/overview/#Solving-the-Problems-1 +function solve(ode::ODEProblem, alg::PairedExplicitRK3; + dt, callback = nothing, kwargs...) + u0 = copy(ode.u0) + du = zero(u0) + u_tmp = zero(u0) + + # PairedExplicitRK stages + k1 = zero(u0) + k_higher = zero(u0) + k_s1 = zero(u0) + + t0 = first(ode.tspan) + iter = 0 + + integrator = PairedExplicitRK3Integrator(u0, du, u_tmp, t0, dt, zero(dt), iter, ode.p, + (prob = ode,), ode.f, alg, + PairedExplicitRKOptions(callback, ode.tspan; kwargs...), + false, + k1, k_higher, k_s1) + + # initialize callbacks + if callback isa CallbackSet + for cb in callback.continuous_callbacks + error("unsupported") + end + for cb in callback.discrete_callbacks + cb.initialize(cb, integrator.u, integrator.t, integrator) + end + elseif !isnothing(callback) + error("unsupported") + end + + solve!(integrator) +end + +function solve!(integrator::PairedExplicitRK3Integrator) + @unpack prob = integrator.sol + @unpack alg = integrator + t_end = last(prob.tspan) + callbacks = integrator.opts.callback + + integrator.finalstep = false + + #@trixi_timeit timer() "main loop" while !integrator.finalstep + while !integrator.finalstep + if isnan(integrator.dt) + error("time step size `dt` is NaN") + end + + # if the next iteration would push the simulation beyond the end time, set dt accordingly + if integrator.t + integrator.dt > t_end || + isapprox(integrator.t + integrator.dt, t_end) + integrator.dt = t_end - integrator.t + terminate!(integrator) + end + + @trixi_timeit timer() "Paired Explicit Runge-Kutta ODE integration step" begin + # k1 + integrator.f(integrator.du, integrator.u, prob.p, integrator.t) + @threaded for i in eachindex(integrator.du) + integrator.k1[i] = integrator.du[i] * integrator.dt + end + + # Construct current state + @threaded for i in eachindex(integrator.du) + integrator.u_tmp[i] = integrator.u[i] + alg.c[2] * integrator.k1[i] + end + # k2 + integrator.f(integrator.du, integrator.u_tmp, prob.p, + integrator.t + alg.c[2] * integrator.dt) + + @threaded for i in eachindex(integrator.du) + integrator.k_higher[i] = integrator.du[i] * integrator.dt + end + + if alg.num_stages == 3 + @threaded for i in eachindex(integrator.du) + integrator.k_s1[i] = integrator.k_higher[i] + end + end + + # Higher stages + for stage in 3:(alg.num_stages) + # Construct current state + @threaded for i in eachindex(integrator.du) + integrator.u_tmp[i] = integrator.u[i] + + alg.a_matrix[stage - 2, 1] * + integrator.k1[i] + + alg.a_matrix[stage - 2, 2] * + integrator.k_higher[i] + end + + integrator.f(integrator.du, integrator.u_tmp, prob.p, + integrator.t + alg.c[stage] * integrator.dt) + + @threaded for i in eachindex(integrator.du) + integrator.k_higher[i] = integrator.du[i] * integrator.dt + end + + # IDEA: Stop for loop at num_stages -1 to avoid if (maybe more performant?) + if stage == alg.num_stages - 1 + @threaded for i in eachindex(integrator.du) + integrator.k_s1[i] = integrator.k_higher[i] + end + end + end + + @threaded for i in eachindex(integrator.u) + # "Own" PairedExplicitRK based on SSPRK33 + integrator.u[i] += (integrator.k1[i] + integrator.k_s1[i] + + 4.0 * integrator.k_higher[i]) / 6.0 + end + end # PairedExplicitRK step timer + + integrator.iter += 1 + integrator.t += integrator.dt + + # handle callbacks + if callbacks isa CallbackSet + for cb in callbacks.discrete_callbacks + if cb.condition(integrator.u, integrator.t, integrator) + cb.affect!(integrator) + end + end + end + + # respect maximum number of iterations + if integrator.iter >= integrator.opts.maxiters && !integrator.finalstep + @warn "Interrupted. Larger maxiters is needed." + terminate!(integrator) + end + end # "main loop" timer + + return TimeIntegratorSolution((first(prob.tspan), integrator.t), + (prob.u0, integrator.u), + integrator.sol.prob) +end + +# used for AMR (Adaptive Mesh Refinement) +function Base.resize!(integrator::PairedExplicitRK3Integrator, new_size) + resize!(integrator.u, new_size) + resize!(integrator.du, new_size) + resize!(integrator.u_tmp, new_size) + + resize!(integrator.k1, new_size) + resize!(integrator.k_higher, new_size) + resize!(integrator.k_s1, new_size) +end +end # @muladd \ No newline at end of file diff --git a/src/time_integration/paired_explicit_runge_kutta/paired_explicit_runge_kutta.jl b/src/time_integration/paired_explicit_runge_kutta/paired_explicit_runge_kutta.jl index b73ea75831..66fa11e68a 100644 --- a/src/time_integration/paired_explicit_runge_kutta/paired_explicit_runge_kutta.jl +++ b/src/time_integration/paired_explicit_runge_kutta/paired_explicit_runge_kutta.jl @@ -7,6 +7,12 @@ # Basic implementation of the second-order paired explicit Runge-Kutta (PERK) method include("methods_PERK2.jl") +include("methods_PERK3.jl") # Define all of the functions necessary for polynomial optimizations include("polynomial_optimizer.jl") + +# Add definitions of functions related to polynomial optimization by NLsolve here +# such that hey can be exported from Trixi.jl and extended in the TrixiConvexECOSExt package +# extension or by the NLsolve-specific code loaded by Requires.jl +function solve_a_unknown end end # @muladd From a6789b3a0696c61868c3667dc382bef0a4248c81 Mon Sep 17 00:00:00 2001 From: Warisa Date: Sat, 25 May 2024 17:57:39 +0200 Subject: [PATCH 002/120] fmt --- .../elixir_burgers_perk3.jl | 2 +- ext/TrixiNLsolveExt.jl | 17 +++---- .../methods_PERK3.jl | 47 ++++++++++--------- 3 files changed, 35 insertions(+), 31 deletions(-) diff --git a/examples/structured_1d_dgsem/elixir_burgers_perk3.jl b/examples/structured_1d_dgsem/elixir_burgers_perk3.jl index 3feb89c6b7..08c88f0a01 100644 --- a/examples/structured_1d_dgsem/elixir_burgers_perk3.jl +++ b/examples/structured_1d_dgsem/elixir_burgers_perk3.jl @@ -53,4 +53,4 @@ sol = Trixi.solve(ode, ode_algorithm, # Print the timer summary summary_callback() -analysis_callback(sol) \ No newline at end of file + diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index 47ea16707c..0e92e807c5 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -3,10 +3,10 @@ module TrixiNLsolveExt # Required for coefficient optimization in P-ERK scheme integrators if isdefined(Base, :get_extension) - using NLsolve:nlsolve + using NLsolve: nlsolve else # Until Julia v1.9 is the minimum required version for Trixi.jl, we still support Requires.jl - using ..NLsolve:nlsolve + using ..NLsolve: nlsolve end # Use functions and additional symbols that are not exported @@ -30,10 +30,12 @@ function Trixi.solve_a_unknown(num_stages, monomial_coeffs, c_s2, c; verbose) # Define the objective_function function objective_function(x) - return Trixi.PairedExplicitRK3_butcher_tableau_objective_function(x, num_stages, num_stages, - monomial_coeffs, c_s2) + return Trixi.PairedExplicitRK3_butcher_tableau_objective_function(x, num_stages, + num_stages, + monomial_coeffs, + c_s2) end - + while !is_sol_valid # Initialize initial guess x0 = 0.1 .* rand(num_stages) @@ -48,13 +50,12 @@ function Trixi.solve_a_unknown(num_stages, monomial_coeffs, c_s2, c; verbose) # Check if the values a[i, i-1] >= 0.0 (which stem from the nonlinear solver) and subsequently c[i] - a[i, i-1] >= 0.0 is_sol_valid = all(x -> !isnan(x) && x >= 0, a_unknown[3:end]) && all(x -> !isnan(x) && x >= 0, c[3:end] .- a_unknown[3:end]) - + if verbose && !is_sol_valid println("Solution invalid. Restart the process of solving non-linear system of equations again.") end - end - + return a_unknown end end # @muladd diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index a44e78093a..fef3eebc90 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -61,7 +61,8 @@ function PairedExplicitRK3_butcher_tableau_objective_function(a_unknown, num_sta return c_eq end -function compute_PairedExplicitRK3_butcher_tableau(num_stages, tspan, eig_vals::Vector{ComplexF64}; +function compute_PairedExplicitRK3_butcher_tableau(num_stages, tspan, + eig_vals::Vector{ComplexF64}; verbose = false, c_s2) # Initialize array of c c = compute_c_coeff_SSP33(num_stages, c_s2) @@ -104,8 +105,9 @@ function compute_PairedExplicitRK3_butcher_tableau(num_stages, tspan, eig_vals:: return a_matrix, c, dt_opt end -function compute_PairedExplicitRK3_butcher_tableau(num_stages, base_path_monomial_coeffs::AbstractString, - c_s2) +function compute_PairedExplicitRK3_butcher_tableau(num_stages, + base_path_monomial_coeffs::AbstractString, + c_s2) # Initialize array of c c = compute_c_coeff_SSP33(num_stages, c_s2) @@ -118,7 +120,7 @@ function compute_PairedExplicitRK3_butcher_tableau(num_stages, base_path_monomia # TODO: update this to work with CI mktempdir() path_monomial_coeffs = base_path_monomial_coeffs * "a_" * string(num_stages) * "_" * - string(num_stages) * ".txt" + string(num_stages) * ".txt" @assert isfile(path_monomial_coeffs) "Couldn't find file" A = readdlm(path_monomial_coeffs, Float64) num_monomial_coeffs = size(A, 1) @@ -156,20 +158,20 @@ mutable struct PairedExplicitRK3 <: AbstractPairedExplicitRKSingle dt_opt::Float64 end # struct PairedExplicitRK3 - # Constructor for previously computed A Coeffs - function PairedExplicitRK3(num_stages, base_path_monomial_coeffs::AbstractString, dt_opt; - c_s2 = 1.0) - +# Constructor for previously computed A Coeffs +function PairedExplicitRK3(num_stages, base_path_monomial_coeffs::AbstractString, + dt_opt; + c_s2 = 1.0) a_matrix, c = compute_PairedExplicitRK3_butcher_tableau(num_stages, - base_path_monomial_coeffs; - c_s2) + base_path_monomial_coeffs; + c_s2) return PairedExplicitRK3(num_stages, a_matrix, c, dt_opt) end # Constructor that computes Butcher matrix A coefficients from a semidiscretization function PairedExplicitRK3(num_stages, tspan, semi::AbstractSemidiscretization; - verbose = false, c_s2 = 1.0) + verbose = false, c_s2 = 1.0) eig_vals = eigvals(jacobian_ad_forward(semi)) return PairedExplicitRK3(num_stages, tspan, eig_vals; verbose, c_s2) @@ -177,8 +179,7 @@ end # Constructor that calculates the coefficients with polynomial optimizer from a list of eigenvalues function PairedExplicitRK3(num_stages, tspan, eig_vals::Vector{ComplexF64}; - verbose = false, c_s2 = 1.0) - + verbose = false, c_s2 = 1.0) a_matrix, c, dt_opt = compute_PairedExplicitRK3_butcher_tableau(num_stages, tspan, eig_vals; @@ -186,14 +187,13 @@ function PairedExplicitRK3(num_stages, tspan, eig_vals::Vector{ComplexF64}; return PairedExplicitRK3(num_stages, a_matrix, c, dt_opt) end - - # This struct is needed to fake https://github.com/SciML/OrdinaryDiffEq.jl/blob/0c2048a502101647ac35faabd80da8a5645beac7/src/integrators/type.jl#L77 # This implements the interface components described at # https://diffeq.sciml.ai/v6.8/basics/integrator/#Handing-Integrators-1 # which are used in Trixi. mutable struct PairedExplicitRK3Integrator{RealT <: Real, uType, Params, Sol, F, Alg, - PairedExplicitRKOptions} <: AbstractPairedExplicitRKSingleIntegrator + PairedExplicitRKOptions} <: + AbstractPairedExplicitRKSingleIntegrator u::uType du::uType u_tmp::uType @@ -228,11 +228,14 @@ function solve(ode::ODEProblem, alg::PairedExplicitRK3; t0 = first(ode.tspan) iter = 0 - integrator = PairedExplicitRK3Integrator(u0, du, u_tmp, t0, dt, zero(dt), iter, ode.p, - (prob = ode,), ode.f, alg, - PairedExplicitRKOptions(callback, ode.tspan; kwargs...), - false, - k1, k_higher, k_s1) + integrator = PairedExplicitRK3Integrator(u0, du, u_tmp, t0, dt, zero(dt), iter, + ode.p, + (prob = ode,), ode.f, alg, + PairedExplicitRKOptions(callback, + ode.tspan; + kwargs...), + false, + k1, k_higher, k_s1) # initialize callbacks if callback isa CallbackSet @@ -362,4 +365,4 @@ function Base.resize!(integrator::PairedExplicitRK3Integrator, new_size) resize!(integrator.k_higher, new_size) resize!(integrator.k_s1, new_size) end -end # @muladd \ No newline at end of file +end # @muladd From bcd40912eec96b34d5d7e9df924a36576e284b0a Mon Sep 17 00:00:00 2001 From: Warisa Date: Sat, 25 May 2024 18:03:05 +0200 Subject: [PATCH 003/120] add NEWS.md but TBD on the ref pull request --- NEWS.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS.md b/NEWS.md index ecbd70ce47..d27ec29ceb 100644 --- a/NEWS.md +++ b/NEWS.md @@ -15,6 +15,9 @@ for human readability. - New time integrator `PairedExplicitRK2`, implementing the second-order paired explicit Runge-Kutta method with [Convex.jl](https://github.com/jump-dev/Convex.jl) and [ECOS.jl](https://github.com/jump-dev/ECOS.jl) ([#1908]) - Add subcell limiting support for `StructuredMesh` ([#1946]). +- New time integrator `PairedExplicitRK3`, implementing the third-order paired explicit Runge-Kutta + method with [Convex.jl](https://github.com/jump-dev/Convex.jl), [ECOS.jl](https://github.com/jump-dev/ECOS.jl) + , and [NLsolve.jl](https://github.com/JuliaNLSolvers/NLsolve.jl) ([TBD]) ## Changes when updating to v0.7 from v0.6.x From fd3d4ca9fc69e4e3651dfb24f465ad0cc59ce371 Mon Sep 17 00:00:00 2001 From: Warisa Date: Sat, 25 May 2024 23:10:27 +0200 Subject: [PATCH 004/120] add comments and adjustment on solve_a_unknown --- .../elixir_burgers_perk3.jl | 1 - ext/TrixiNLsolveExt.jl | 12 +-- .../methods_PERK3.jl | 83 ++++++++++++------- .../paired_explicit_runge_kutta.jl | 2 +- 4 files changed, 59 insertions(+), 39 deletions(-) diff --git a/examples/structured_1d_dgsem/elixir_burgers_perk3.jl b/examples/structured_1d_dgsem/elixir_burgers_perk3.jl index 08c88f0a01..78d5c00374 100644 --- a/examples/structured_1d_dgsem/elixir_burgers_perk3.jl +++ b/examples/structured_1d_dgsem/elixir_burgers_perk3.jl @@ -53,4 +53,3 @@ sol = Trixi.solve(ode, ode_algorithm, # Print the timer summary summary_callback() - diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index 0e92e807c5..4d2c1108ea 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -10,10 +10,10 @@ else end # Use functions and additional symbols that are not exported -using Trixi: Trixi, @muladd, PairedExplicitRK3_butcher_tableau_objective_function +using Trixi: Trixi, PairedExplicitRK3_butcher_tableau_objective_function, @muladd # Use functions that are to be extended -using Trixi: Trixi, solve_a_unknown +using Trixi: Trixi, solve_a_unknown! # By default, Julia/LLVM does not use fused multiply-add operations (FMAs). # Since these FMAs can increase the performance of many numerical algorithms, @@ -22,11 +22,11 @@ using Trixi: Trixi, solve_a_unknown @muladd begin #! format: noindent -# TODO: edit the comment this function -# Define the new function that includes the nlsolve features -function Trixi.solve_a_unknown(num_stages, monomial_coeffs, c_s2, c; verbose) +# Find the values of a in the Butcher tableau by solving a system of +# non-linear equations +function Trixi.solve_a_unknown!(a_unknown, num_stages, monomial_coeffs, c_s2, c; + verbose) is_sol_valid = false - a_unknown = zeros(num_stages) # Define the objective_function function objective_function(x) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index fef3eebc90..15bad4c2f6 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -8,7 +8,7 @@ using DelimitedFiles: readdlm #! format: noindent # Initialize Butcher array abscissae c for PairedExplicitRK3 based on SSPRK33 base method -function compute_c_coeff_SSP33(num_stages, c_s2) +function compute_c_coeffs_SSP33(num_stages, cS2) c = zeros(num_stages) # Last timesteps as for SSPRK33 @@ -17,21 +17,23 @@ function compute_c_coeff_SSP33(num_stages, c_s2) # Linear increasing timestep for remainder for i in 2:(num_stages - 2) - c[i] = c_s2 * (i - 1) / (num_stages - 3) + c[i] = cS2 * (i - 1) / (num_stages - 3) end return c end +# Compute residuals for nonlinear equations to match a stability polynomial with given coefficients, +# in order to find A matrix in the Butcher-Tableau function PairedExplicitRK3_butcher_tableau_objective_function(a_unknown, num_stages, num_stage_evals, - monomial_coeffs, c_s2) - c_ts = compute_c_coeff_SSP33(num_stages, c_s2) # ts = timestep + monomial_coeffs, cS2) + c_ts = compute_c_coeffs_SSP33(num_stages, cS2) # ts = timestep # Equality Constraint array that ensures that the stability polynomial computed from # the to-be-constructed Butcher-Tableau matches the monomial coefficients of the # optimized stability polynomial. - c_eq = zeros(num_stage_evals - 2) # Add equality constraint that c_s2 is equal to 1 + c_eq = zeros(num_stage_evals - 2) # Add equality constraint that cS2 is equal to 1 # Both terms should be present for i in 1:(num_stage_evals - 4) term1 = a_unknown[num_stage_evals - 1] @@ -61,11 +63,13 @@ function PairedExplicitRK3_butcher_tableau_objective_function(a_unknown, num_sta return c_eq end +# Compute the Butcher tableau for a paired explicit Runge-Kutta method order 3 +# using a list of eigenvalues function compute_PairedExplicitRK3_butcher_tableau(num_stages, tspan, eig_vals::Vector{ComplexF64}; - verbose = false, c_s2) + verbose = false, cS2) # Initialize array of c - c = compute_c_coeff_SSP33(num_stages, c_s2) + c = compute_c_coeffs_SSP33(num_stages, cS2) # Initialize the array of our solution a_unknown = zeros(num_stages) @@ -89,14 +93,12 @@ function compute_PairedExplicitRK3_butcher_tableau(num_stages, tspan, monomial_coeffs = undo_normalization!(monomial_coeffs, consistency_order, num_stages) - # Call function that use the library NLsolve to solve the nonlinear system - a_unknown = solve_a_unknown(num_stages, monomial_coeffs, c_s2, c; verbose) + # Solve the nonlinear system of equations from monomial coefficient and + # Butcher array abscissae c to find Butcher matrix A + a_unknown = solve_a_unknown!(a_unknown, num_stages, monomial_coeffs, cS2, c; + verbose) end - # For debugging purpose - println("a_unknown") - println(a_unknown[3:end]) - a_matrix = zeros(num_stages - 2, 2) a_matrix[:, 1] = c[3:end] a_matrix[:, 1] -= a_unknown[3:end] @@ -105,12 +107,14 @@ function compute_PairedExplicitRK3_butcher_tableau(num_stages, tspan, return a_matrix, c, dt_opt end +# Compute the Butcher tableau for a paired explicit Runge-Kutta method order 3 +# using provided file containing A matrix from Butcher-Tableau function compute_PairedExplicitRK3_butcher_tableau(num_stages, - base_path_monomial_coeffs::AbstractString, - c_s2) + base_path_a_matrix::AbstractString, + cS2) # Initialize array of c - c = compute_c_coeff_SSP33(num_stages, c_s2) + c = compute_c_coeffs_SSP33(num_stages, cS2) # - 2 Since First entry of A is always zero (explicit method) and second is given by c_2 (consistency) coeffs_max = num_stages - 2 @@ -119,7 +123,7 @@ function compute_PairedExplicitRK3_butcher_tableau(num_stages, a_matrix[:, 1] = c[3:end] # TODO: update this to work with CI mktempdir() - path_monomial_coeffs = base_path_monomial_coeffs * "a_" * string(num_stages) * "_" * + path_monomial_coeffs = base_path_a_matrix * "a_" * string(num_stages) * "_" * string(num_stages) * ".txt" @assert isfile(path_monomial_coeffs) "Couldn't find file" A = readdlm(path_monomial_coeffs, Float64) @@ -129,17 +133,34 @@ function compute_PairedExplicitRK3_butcher_tableau(num_stages, a_matrix[:, 1] -= A a_matrix[:, 2] = A - println("A matrix: ") - display(a_matrix) - println() - return a_matrix, c end -""" - PairedExplicitRK3() +@doc raw""" + PairedExplicitRK3(num_stages, base_path_a_matrix::AbstractString, + dt_opt; + cS2 = 1.0) + PairedExplicitRK3(num_stages, tspan, semi::AbstractSemidiscretization; + verbose = false, cS2 = 1.0) + PairedExplicitRK3(num_stages, tspan, semi::AbstractSemidiscretization; + verbose = false, cS2 = 1.0) + + Parameters: + - `num_stages` (`Int`): Number of stages in the PERK method. + - `base_path_a_matrix` (`AbstractString`): Path to a file containing + monomial coefficients of the stability polynomial of PERK method. + The coefficients should be stored in a text file at `joinpath(base_path_a_matrix, "a_$(num_stages).txt")` and separated by line breaks. + - `tspan`: Time span of the simulation. + - `semi` (`AbstractSemidiscretization`): Semidiscretization setup. + - `eig_vals` (`Vector{ComplexF64}`): Eigenvalues of the Jacobian of the right-hand side (rhs) of the ODEProblem after the + equation has been semidiscretized. + - `verbose` (`Bool`, optional): Verbosity flag, default is false. + - `cS2` (`Float64`, optional): Value of c in the Butcher tableau at c_{s-2}, when + s is the number of stages, default is 1.0. + The following structures and methods provide a implementation of the third-order paired explicit Runge-Kutta method + optimized for a certain simulation setup (PDE, IC & BC, Riemann Solver, DG Solver). The original paper is - Nasab, Vermeire (2022) @@ -159,31 +180,31 @@ mutable struct PairedExplicitRK3 <: AbstractPairedExplicitRKSingle end # struct PairedExplicitRK3 # Constructor for previously computed A Coeffs -function PairedExplicitRK3(num_stages, base_path_monomial_coeffs::AbstractString, +function PairedExplicitRK3(num_stages, base_path_a_matrix::AbstractString, dt_opt; - c_s2 = 1.0) + cS2 = 1.0) a_matrix, c = compute_PairedExplicitRK3_butcher_tableau(num_stages, - base_path_monomial_coeffs; - c_s2) + base_path_a_matrix; + cS2) return PairedExplicitRK3(num_stages, a_matrix, c, dt_opt) end # Constructor that computes Butcher matrix A coefficients from a semidiscretization function PairedExplicitRK3(num_stages, tspan, semi::AbstractSemidiscretization; - verbose = false, c_s2 = 1.0) + verbose = false, cS2 = 1.0) eig_vals = eigvals(jacobian_ad_forward(semi)) - return PairedExplicitRK3(num_stages, tspan, eig_vals; verbose, c_s2) + return PairedExplicitRK3(num_stages, tspan, eig_vals; verbose, cS2) end # Constructor that calculates the coefficients with polynomial optimizer from a list of eigenvalues function PairedExplicitRK3(num_stages, tspan, eig_vals::Vector{ComplexF64}; - verbose = false, c_s2 = 1.0) + verbose = false, cS2 = 1.0) a_matrix, c, dt_opt = compute_PairedExplicitRK3_butcher_tableau(num_stages, tspan, eig_vals; - verbose, c_s2) + verbose, cS2) return PairedExplicitRK3(num_stages, a_matrix, c, dt_opt) end diff --git a/src/time_integration/paired_explicit_runge_kutta/paired_explicit_runge_kutta.jl b/src/time_integration/paired_explicit_runge_kutta/paired_explicit_runge_kutta.jl index 66fa11e68a..cc48c3ca45 100644 --- a/src/time_integration/paired_explicit_runge_kutta/paired_explicit_runge_kutta.jl +++ b/src/time_integration/paired_explicit_runge_kutta/paired_explicit_runge_kutta.jl @@ -14,5 +14,5 @@ include("polynomial_optimizer.jl") # Add definitions of functions related to polynomial optimization by NLsolve here # such that hey can be exported from Trixi.jl and extended in the TrixiConvexECOSExt package # extension or by the NLsolve-specific code loaded by Requires.jl -function solve_a_unknown end +function solve_a_unknown! end end # @muladd From c28029278d78c56cf7bc1f3fdcd62f05c1025e63 Mon Sep 17 00:00:00 2001 From: Warisa Date: Sat, 25 May 2024 23:29:41 +0200 Subject: [PATCH 005/120] modular implementation with init, step!, and solve_step! --- .../methods_PERK3.jl | 34 ++++++++++++++----- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index 15bad4c2f6..1ae788e21e 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -234,8 +234,7 @@ mutable struct PairedExplicitRK3Integrator{RealT <: Real, uType, Params, Sol, F, k_s1::uType # Required for custom third order version of PairedExplicitRK3 end -# Fakes `solve`: https://diffeq.sciml.ai/v6.8/basics/overview/#Solving-the-Problems-1 -function solve(ode::ODEProblem, alg::PairedExplicitRK3; +function init(ode::ODEProblem, alg::PairedExplicitRK3; dt, callback = nothing, kwargs...) u0 = copy(ode.u0) du = zero(u0) @@ -270,10 +269,33 @@ function solve(ode::ODEProblem, alg::PairedExplicitRK3; error("unsupported") end - solve!(integrator) + return integrator +end + +# Fakes `solve`: https://diffeq.sciml.ai/v6.8/basics/overview/#Solving-the-Problems-1 +function solve(ode::ODEProblem, alg::PairedExplicitRK3; + dt, callback = nothing, kwargs...) + integrator = init(ode, alg, dt = dt, callback = callback; kwargs...) + + # Start actual solve + solve_steps!(integrator) +end + +function solve_steps!(integrator::PairedExplicitRK3Integrator) + @unpack prob = integrator.sol + + integrator.finalstep = false + + @trixi_timeit timer() "main loop" while !integrator.finalstep + step!(integrator) + end # "main loop" timer + + return TimeIntegratorSolution((first(prob.tspan), integrator.t), + (prob.u0, integrator.u), + integrator.sol.prob) end -function solve!(integrator::PairedExplicitRK3Integrator) +function step!(integrator::PairedExplicitRK3Integrator) @unpack prob = integrator.sol @unpack alg = integrator t_end = last(prob.tspan) @@ -370,10 +392,6 @@ function solve!(integrator::PairedExplicitRK3Integrator) terminate!(integrator) end end # "main loop" timer - - return TimeIntegratorSolution((first(prob.tspan), integrator.t), - (prob.u0, integrator.u), - integrator.sol.prob) end # used for AMR (Adaptive Mesh Refinement) From 3ddf5c4b14b8901307de7d7f693443b744208357 Mon Sep 17 00:00:00 2001 From: Warisa Date: Sat, 25 May 2024 23:31:38 +0200 Subject: [PATCH 006/120] fmt --- .../paired_explicit_runge_kutta/methods_PERK3.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index 1ae788e21e..b656328a86 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -235,7 +235,7 @@ mutable struct PairedExplicitRK3Integrator{RealT <: Real, uType, Params, Sol, F, end function init(ode::ODEProblem, alg::PairedExplicitRK3; - dt, callback = nothing, kwargs...) + dt, callback = nothing, kwargs...) u0 = copy(ode.u0) du = zero(u0) u_tmp = zero(u0) @@ -274,7 +274,7 @@ end # Fakes `solve`: https://diffeq.sciml.ai/v6.8/basics/overview/#Solving-the-Problems-1 function solve(ode::ODEProblem, alg::PairedExplicitRK3; - dt, callback = nothing, kwargs...) + dt, callback = nothing, kwargs...) integrator = init(ode, alg, dt = dt, callback = callback; kwargs...) # Start actual solve @@ -287,7 +287,7 @@ function solve_steps!(integrator::PairedExplicitRK3Integrator) integrator.finalstep = false @trixi_timeit timer() "main loop" while !integrator.finalstep - step!(integrator) + step!(integrator) end # "main loop" timer return TimeIntegratorSolution((first(prob.tspan), integrator.t), From b9b4243e0b2b249f9c9327c9cb2fbba6d6c0ee20 Mon Sep 17 00:00:00 2001 From: Warisa Date: Sun, 26 May 2024 20:58:43 +0200 Subject: [PATCH 007/120] add test --- test/test_structured_1d.jl | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/test_structured_1d.jl b/test/test_structured_1d.jl index f97696d089..3401b314ce 100644 --- a/test/test_structured_1d.jl +++ b/test/test_structured_1d.jl @@ -58,6 +58,21 @@ end end end + +@trixi_testset "elixir_burgers_perk3.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_burgers_perk3.jl"), + l2=[8.120426329330083e-8], + linf=[4.906376900315479e-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_sedov.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov.jl"), l2=[3.67478226e-01, 3.49491179e-01, 8.08910759e-01], From a727a871fef3525d3f0c9bfbf5c5ea39357dacfc Mon Sep 17 00:00:00 2001 From: Warisa Date: Tue, 28 May 2024 23:39:51 +0200 Subject: [PATCH 008/120] adda body of p3 constructor test --- test/test_unit.jl | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/test/test_unit.jl b/test/test_unit.jl index de13d41e93..c94193201e 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -10,6 +10,10 @@ using DelimitedFiles: readdlm using Convex: Convex using ECOS: Optimizer +# Use NLsolve to load the extension that extends functions for testing +# PERK Single p3 Constructors +using NLsolve: nlsolve + include("test_trixi.jl") # Start with a clean environment: remove Trixi.jl output directory if it exists @@ -1674,6 +1678,40 @@ end 0.13942836392940833 0.3605716360705917], atol = 1e-13) end +@testset "PERK Single p3 Constructors" begin + #TODO: make this a p3 Constructors + path_coeff_file = mktempdir() + Trixi.download("https://gist.githubusercontent.com/DanielDoehring/8db0808b6f80e59420c8632c0d8e2901/raw/39aacf3c737cd642636dd78592dbdfe4cb9499af/MonCoeffsS6p2.txt", + joinpath(path_coeff_file, "gamma_6.txt")) + + ode_algorithm = Trixi.PairedExplicitRK2(6, path_coeff_file) + + @test isapprox(ode_algorithm.a_matrix, + [0.12405417889682908 0.07594582110317093 + 0.16178873711001726 0.13821126288998273 + 0.16692313960864164 0.2330768603913584 + 0.12281292901258256 0.37718707098741744], atol = 1e-13) + + Trixi.download("https://gist.githubusercontent.com/DanielDoehring/c7a89eaaa857e87dde055f78eae9b94a/raw/2937f8872ffdc08e0dcf444ee35f9ebfe18735b0/Spectrum_2D_IsentropicVortex_CEE.txt", + joinpath(path_coeff_file, "spectrum_2d.txt")) + + eig_vals = readdlm(joinpath(path_coeff_file, "spectrum_2d.txt"), ComplexF64) + tspan = (0.0, 1.0) + ode_algorithm = Trixi.PairedExplicitRK2(12, tspan, vec(eig_vals)) + + @test isapprox(ode_algorithm.a_matrix, + [0.06453812656705388 0.02637096434203703 + 0.09470601372266194 0.04165762264097442 + 0.12332877820057538 0.05848940361760645 + 0.1498701503275483 0.07740257694517898 + 0.173421149536068 0.09930612319120471 + 0.19261978147927503 0.12556203670254315 + 0.2052334022622969 0.15840296137406676 + 0.2073489042901963 0.2017420048007128 + 0.19135142349998963 0.2631940310454649 + 0.13942836392940833 0.3605716360705917], atol = 1e-13) +end + @testset "Sutherlands Law" begin function mu(u, equations) T_ref = 291.15 From cb98a3fe8f3c9aad32a978ff06a325316b4457e5 Mon Sep 17 00:00:00 2001 From: Warisa Date: Wed, 29 May 2024 15:07:13 +0200 Subject: [PATCH 009/120] changes according to test and correct variable names --- .../methods_PERK3.jl | 16 ++++++++-------- test/test_unit.jl | 19 +++++++++++-------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index b656328a86..3cfa3d70a2 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -108,9 +108,9 @@ function compute_PairedExplicitRK3_butcher_tableau(num_stages, tspan, end # Compute the Butcher tableau for a paired explicit Runge-Kutta method order 3 -# using provided file containing A matrix from Butcher-Tableau +# using provided monomial coefficients file function compute_PairedExplicitRK3_butcher_tableau(num_stages, - base_path_a_matrix::AbstractString, + base_path_monomial_coeffs::AbstractString, cS2) # Initialize array of c @@ -122,9 +122,9 @@ function compute_PairedExplicitRK3_butcher_tableau(num_stages, a_matrix = zeros(coeffs_max, 2) a_matrix[:, 1] = c[3:end] - # TODO: update this to work with CI mktempdir() - path_monomial_coeffs = base_path_a_matrix * "a_" * string(num_stages) * "_" * - string(num_stages) * ".txt" + path_monomial_coeffs = joinpath(base_path_monomial_coeffs, + "gamma_" * string(num_stages) * ".txt") + @assert isfile(path_monomial_coeffs) "Couldn't find file" A = readdlm(path_monomial_coeffs, Float64) num_monomial_coeffs = size(A, 1) @@ -137,7 +137,7 @@ function compute_PairedExplicitRK3_butcher_tableau(num_stages, end @doc raw""" - PairedExplicitRK3(num_stages, base_path_a_matrix::AbstractString, + PairedExplicitRK3(num_stages, base_path_monomial_coeffs::AbstractString, dt_opt; cS2 = 1.0) PairedExplicitRK3(num_stages, tspan, semi::AbstractSemidiscretization; @@ -147,9 +147,9 @@ end Parameters: - `num_stages` (`Int`): Number of stages in the PERK method. - - `base_path_a_matrix` (`AbstractString`): Path to a file containing + - `base_path_monomial_coeffs` (`AbstractString`): Path to a file containing monomial coefficients of the stability polynomial of PERK method. - The coefficients should be stored in a text file at `joinpath(base_path_a_matrix, "a_$(num_stages).txt")` and separated by line breaks. + The coefficients should be stored in a text file at `joinpath(base_path_monomial_coeffs, "gamma_$(num_stages).txt")` and separated by line breaks. - `tspan`: Time span of the simulation. - `semi` (`AbstractSemidiscretization`): Semidiscretization setup. - `eig_vals` (`Vector{ComplexF64}`): Eigenvalues of the Jacobian of the right-hand side (rhs) of the ODEProblem after the diff --git a/test/test_unit.jl b/test/test_unit.jl index c94193201e..05bc216e97 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -1679,19 +1679,22 @@ end end @testset "PERK Single p3 Constructors" begin - #TODO: make this a p3 Constructors path_coeff_file = mktempdir() - Trixi.download("https://gist.githubusercontent.com/DanielDoehring/8db0808b6f80e59420c8632c0d8e2901/raw/39aacf3c737cd642636dd78592dbdfe4cb9499af/MonCoeffsS6p2.txt", - joinpath(path_coeff_file, "gamma_6.txt")) + Trixi.download("https://gist.githubusercontent.com/warisa-r/0796db36abcd5abe735ac7eebf41b973/raw/d55cb5bc1837d40febcf47ff620deb1f23185e15/monomial_coeff_s8_p3.txt", + joinpath(path_coeff_file, "gamma_8.txt")) - ode_algorithm = Trixi.PairedExplicitRK2(6, path_coeff_file) + ode_algorithm = Trixi.PairedExplicitRK2(8, path_coeff_file) + #TODO: adjust this value according to the result in the test pipeline @test isapprox(ode_algorithm.a_matrix, - [0.12405417889682908 0.07594582110317093 - 0.16178873711001726 0.13821126288998273 - 0.16692313960864164 0.2330768603913584 - 0.12281292901258256 0.37718707098741744], atol = 1e-13) + [0.335517 0.0644832 + 0.496535 0.103465 + 0.649689 0.150311 + 0.789172 0.210828 + 0.752297 0.247703 + 0.311926 0.188074], atol = 1e-13) + #TODO: make this a p3 Constructors Trixi.download("https://gist.githubusercontent.com/DanielDoehring/c7a89eaaa857e87dde055f78eae9b94a/raw/2937f8872ffdc08e0dcf444ee35f9ebfe18735b0/Spectrum_2D_IsentropicVortex_CEE.txt", joinpath(path_coeff_file, "spectrum_2d.txt")) From d84daedc4e55e5813686ead6eade7b3448212b97 Mon Sep 17 00:00:00 2001 From: Warisa Date: Fri, 31 May 2024 15:39:03 +0200 Subject: [PATCH 010/120] only check the values of a_matrix from second row to end --- test/test_unit.jl | 41 +++++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/test/test_unit.jl b/test/test_unit.jl index 05bc216e97..0dbac65225 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -1683,7 +1683,7 @@ end Trixi.download("https://gist.githubusercontent.com/warisa-r/0796db36abcd5abe735ac7eebf41b973/raw/d55cb5bc1837d40febcf47ff620deb1f23185e15/monomial_coeff_s8_p3.txt", joinpath(path_coeff_file, "gamma_8.txt")) - ode_algorithm = Trixi.PairedExplicitRK2(8, path_coeff_file) + ode_algorithm = Trixi.PairedExplicitRK3(8, path_coeff_file) #TODO: adjust this value according to the result in the test pipeline @test isapprox(ode_algorithm.a_matrix, @@ -1695,24 +1695,33 @@ end 0.311926 0.188074], atol = 1e-13) #TODO: make this a p3 Constructors - Trixi.download("https://gist.githubusercontent.com/DanielDoehring/c7a89eaaa857e87dde055f78eae9b94a/raw/2937f8872ffdc08e0dcf444ee35f9ebfe18735b0/Spectrum_2D_IsentropicVortex_CEE.txt", - joinpath(path_coeff_file, "spectrum_2d.txt")) + Trixi.download("https://gist.githubusercontent.com/warisa-r/8d93f6a3ae0635e13b9f51ee32ab7fff/raw/54dc5b14be9288e186b745facb5bbcb04d1476f8/EigenvalueList_Refined2.txt", + joinpath(path_coeff_file, "spectrum.txt")) - eig_vals = readdlm(joinpath(path_coeff_file, "spectrum_2d.txt"), ComplexF64) + eig_vals = readdlm(joinpath(path_coeff_file, "spectrum.txt"), ComplexF64) tspan = (0.0, 1.0) - ode_algorithm = Trixi.PairedExplicitRK2(12, tspan, vec(eig_vals)) + ode_algorithm = Trixi.PairedExplicitRK3(10, tspan, vec(eig_vals)) - @test isapprox(ode_algorithm.a_matrix, - [0.06453812656705388 0.02637096434203703 - 0.09470601372266194 0.04165762264097442 - 0.12332877820057538 0.05848940361760645 - 0.1498701503275483 0.07740257694517898 - 0.173421149536068 0.09930612319120471 - 0.19261978147927503 0.12556203670254315 - 0.2052334022622969 0.15840296137406676 - 0.2073489042901963 0.2017420048007128 - 0.19135142349998963 0.2631940310454649 - 0.13942836392940833 0.3605716360705917], atol = 1e-13) + #TODO: adjust this value according to the result in the test pipeline + display(ode_algorithm.a_matrix) # Value in CI differs slightly from what I get locally + + # We are only testing from the second row to the end of `ode_algorithm.a_matrix` due to the nature of the system of equations + # used to find the `a_matrix` in the Butcher tableau. This system can have multiple valid solutions, which can cause slight + # variations in the results of the tests. These variations don't affect the validity of the solutions, but they can cause + # the tests to fail due to small differences in the expected and actual values. + + # The first row of `ode_algorithm.a_matrix` is particularly susceptible to these variations, while the rest of the rows + # remain consistent across different runs. Therefore, to make the tests more robust and less prone to false negatives, + # we are excluding the first row from the test. This approach allows us to verify the correctness of the majority of the + # `a_matrix` while avoiding the issue of test instability caused by the multiple valid solutions of the system of equations. + @test isapprox(ode_algorithm.a_matrix[2:end, :], + [0.406023 0.0225489 + 0.534288 0.0371408 + 0.654943 0.0593431 + 0.76216 0.0949827 + 0.844659 0.155341 + 0.771998 0.228002 + 0.307001 0.192999], atol = 1e-13) end @testset "Sutherlands Law" begin From 1332c289dcd0d79c9440c56c1ab8b070ca2f16f0 Mon Sep 17 00:00:00 2001 From: Warisa Date: Fri, 31 May 2024 16:50:50 +0200 Subject: [PATCH 011/120] adjust the the constructor of path coefficient and its test --- .../methods_PERK3.jl | 22 +++++----- test/test_unit.jl | 41 ++++++++++--------- 2 files changed, 33 insertions(+), 30 deletions(-) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index 3cfa3d70a2..6c6057f4bc 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -107,10 +107,11 @@ function compute_PairedExplicitRK3_butcher_tableau(num_stages, tspan, return a_matrix, c, dt_opt end +#TODO: Correct this and make it actually import A matrix # Compute the Butcher tableau for a paired explicit Runge-Kutta method order 3 # using provided monomial coefficients file function compute_PairedExplicitRK3_butcher_tableau(num_stages, - base_path_monomial_coeffs::AbstractString, + base_path_a_coeffs::AbstractString; cS2) # Initialize array of c @@ -122,22 +123,23 @@ function compute_PairedExplicitRK3_butcher_tableau(num_stages, a_matrix = zeros(coeffs_max, 2) a_matrix[:, 1] = c[3:end] - path_monomial_coeffs = joinpath(base_path_monomial_coeffs, - "gamma_" * string(num_stages) * ".txt") + path_a_coeffs = joinpath(base_path_a_coeffs, + "a_" * string(num_stages) * "_" * string(num_stages) * ".txt") - @assert isfile(path_monomial_coeffs) "Couldn't find file" - A = readdlm(path_monomial_coeffs, Float64) - num_monomial_coeffs = size(A, 1) + @assert isfile(path_a_coeffs) "Couldn't find file" + A = readdlm(path_a_coeffs, Float64) + num_a_coeffs = size(A, 1) - @assert num_monomial_coeffs == coeffs_max + @assert num_a_coeffs == coeffs_max a_matrix[:, 1] -= A a_matrix[:, 2] = A return a_matrix, c end +#TODO: explain dt_opt and also explain base_path_a_coeffs in the first constructor @doc raw""" - PairedExplicitRK3(num_stages, base_path_monomial_coeffs::AbstractString, + PairedExplicitRK3(num_stages, base_path_a_coeffs::AbstractString, dt_opt; cS2 = 1.0) PairedExplicitRK3(num_stages, tspan, semi::AbstractSemidiscretization; @@ -180,11 +182,11 @@ mutable struct PairedExplicitRK3 <: AbstractPairedExplicitRKSingle end # struct PairedExplicitRK3 # Constructor for previously computed A Coeffs -function PairedExplicitRK3(num_stages, base_path_a_matrix::AbstractString, +function PairedExplicitRK3(num_stages, base_path_a_coeffs::AbstractString, dt_opt; cS2 = 1.0) a_matrix, c = compute_PairedExplicitRK3_butcher_tableau(num_stages, - base_path_a_matrix; + base_path_a_coeffs; cS2) return PairedExplicitRK3(num_stages, a_matrix, c, dt_opt) diff --git a/test/test_unit.jl b/test/test_unit.jl index 0dbac65225..eecbe315bc 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -1679,20 +1679,31 @@ end end @testset "PERK Single p3 Constructors" begin + # We are only testing from the second row to the end of `ode_algorithm.a_matrix` due to the nature of the system of equations + # used to find the `a_matrix` in the Butcher tableau. This system can have multiple valid solutions, which can cause slight + # variations in the results of the tests. These variations don't affect the validity of the solutions, but they can cause + # the tests to fail due to small differences in the expected and actual values. + + # The first row of `ode_algorithm.a_matrix` is particularly susceptible to these variations, while the rest of the rows + # remain consistent across different runs. Therefore, to make the tests more robust and less prone to false negatives, + # we are excluding the first row from the test. This approach allows us to verify the correctness of the majority of the + # `a_matrix` while avoiding the issue of test instability caused by the multiple valid solutions of the system of equations. path_coeff_file = mktempdir() - Trixi.download("https://gist.githubusercontent.com/warisa-r/0796db36abcd5abe735ac7eebf41b973/raw/d55cb5bc1837d40febcf47ff620deb1f23185e15/monomial_coeff_s8_p3.txt", - joinpath(path_coeff_file, "gamma_8.txt")) + Trixi.download("https://gist.githubusercontent.com/warisa-r/0796db36abcd5abe735ac7eebf41b973/raw/32889062fd5dcf7f450748f4f5f0797c8155a18d/a_8_8.txt", + joinpath(path_coeff_file, "a_8_8.txt")) - ode_algorithm = Trixi.PairedExplicitRK3(8, path_coeff_file) + # Value of dt_opt obtained from running the simulation in elixir_burgers_perk3 + # The value plays no role in the result but added so that the constructor can be called + dt_opt = 0.004485771991312504 + ode_algorithm = Trixi.PairedExplicitRK3(8, path_coeff_file, dt_opt) #TODO: adjust this value according to the result in the test pipeline - @test isapprox(ode_algorithm.a_matrix, - [0.335517 0.0644832 - 0.496535 0.103465 - 0.649689 0.150311 - 0.789172 0.210828 - 0.752297 0.247703 - 0.311926 0.188074], atol = 1e-13) + @test isapprox(ode_algorithm.a_matrix[2:end, :], + [0.496535 0.103465 + 0.649689 0.150311 + 0.789172 0.210828 + 0.752297 0.247703 + 0.311926 0.188074], atol = 1e-13) #TODO: make this a p3 Constructors Trixi.download("https://gist.githubusercontent.com/warisa-r/8d93f6a3ae0635e13b9f51ee32ab7fff/raw/54dc5b14be9288e186b745facb5bbcb04d1476f8/EigenvalueList_Refined2.txt", @@ -1704,16 +1715,6 @@ end #TODO: adjust this value according to the result in the test pipeline display(ode_algorithm.a_matrix) # Value in CI differs slightly from what I get locally - - # We are only testing from the second row to the end of `ode_algorithm.a_matrix` due to the nature of the system of equations - # used to find the `a_matrix` in the Butcher tableau. This system can have multiple valid solutions, which can cause slight - # variations in the results of the tests. These variations don't affect the validity of the solutions, but they can cause - # the tests to fail due to small differences in the expected and actual values. - - # The first row of `ode_algorithm.a_matrix` is particularly susceptible to these variations, while the rest of the rows - # remain consistent across different runs. Therefore, to make the tests more robust and less prone to false negatives, - # we are excluding the first row from the test. This approach allows us to verify the correctness of the majority of the - # `a_matrix` while avoiding the issue of test instability caused by the multiple valid solutions of the system of equations. @test isapprox(ode_algorithm.a_matrix[2:end, :], [0.406023 0.0225489 0.534288 0.0371408 From 7bf717ad12157a0ea853696dba714c1c838e28ed Mon Sep 17 00:00:00 2001 From: Warisa Date: Tue, 4 Jun 2024 20:44:23 +0200 Subject: [PATCH 012/120] adjust the test and add a seed to the randomized initial guess for reproducibility --- Project.toml | 9 ++-- ext/TrixiNLsolveExt.jl | 11 ++++- .../methods_PERK3.jl | 30 ++++++------ test/test_structured_1d.jl | 8 +-- test/test_unit.jl | 49 ++++++++----------- 5 files changed, 55 insertions(+), 52 deletions(-) diff --git a/Project.toml b/Project.toml index 6ae18fb29a..9abf4d36b5 100644 --- a/Project.toml +++ b/Project.toml @@ -28,6 +28,7 @@ Polyester = "f517fe37-dbe3-4b94-8317-1923a5111588" PrecompileTools = "aea7be01-6a6a-4083-8856-8a6e6704d82a" Preferences = "21216c6a-2e73-6563-6e65-726566657250" Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" +Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" Reexport = "189a3867-3050-52da-a836-e630ba90ab69" Requires = "ae029012-a4dd-5104-9daa-d747884805df" @@ -50,14 +51,14 @@ TrixiBase = "9a0f1c46-06d5-4909-a5a3-ce25d3fa3284" UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" [weakdeps] -Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" Convex = "f65535da-76fb-5f13-bab9-19810c17039a" ECOS = "e2685f51-7e38-5353-a97d-a921fd2c8199" +Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" NLsolve = "2774e3e8-f4cf-5e23-947b-6d7e65073b56" [extensions] -TrixiMakieExt = "Makie" TrixiConvexECOSExt = ["Convex", "ECOS"] +TrixiMakieExt = "Makie" TrixiNLsolveExt = "NLsolve" [compat] @@ -112,7 +113,7 @@ UUIDs = "1.6" julia = "1.8" [extras] -Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" Convex = "f65535da-76fb-5f13-bab9-19810c17039a" ECOS = "e2685f51-7e38-5353-a97d-a921fd2c8199" -NLsolve = "2774e3e8-f4cf-5e23-947b-6d7e65073b56" \ No newline at end of file +Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" +NLsolve = "2774e3e8-f4cf-5e23-947b-6d7e65073b56" diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index 4d2c1108ea..cbe022b1f3 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -9,6 +9,9 @@ else using ..NLsolve: nlsolve end +# Use other necessary libraries +using Random: seed! + # Use functions and additional symbols that are not exported using Trixi: Trixi, PairedExplicitRK3_butcher_tableau_objective_function, @muladd @@ -36,8 +39,13 @@ function Trixi.solve_a_unknown!(a_unknown, num_stages, monomial_coeffs, c_s2, c; c_s2) end + # Set the seed for reproducibility of the initial guess of a_unknown + seed!(5555) + while !is_sol_valid + # Initialize initial guess + # The nonlinear system may have multiple valid solutions, so a reproducible initial guess is important x0 = 0.1 .* rand(num_stages) x0[1] = 0.0 x0[2] = c[2] @@ -47,7 +55,8 @@ function Trixi.solve_a_unknown!(a_unknown, num_stages, monomial_coeffs, c_s2, c; a_unknown = sol.zero - # Check if the values a[i, i-1] >= 0.0 (which stem from the nonlinear solver) and subsequently c[i] - a[i, i-1] >= 0.0 + # Check if the values a[i, i-1] >= 0.0 (which stem from the nonlinear solver) + # and subsequently c[i] - a[i, i-1] >= 0.0 is_sol_valid = all(x -> !isnan(x) && x >= 0, a_unknown[3:end]) && all(x -> !isnan(x) && x >= 0, c[3:end] .- a_unknown[3:end]) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index 6c6057f4bc..ae2042872a 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -94,7 +94,8 @@ function compute_PairedExplicitRK3_butcher_tableau(num_stages, tspan, num_stages) # Solve the nonlinear system of equations from monomial coefficient and - # Butcher array abscissae c to find Butcher matrix A + # Butcher array abscissae c to find Butcher matrix A + # This function is extended in TrixiNLsolveExt.jl a_unknown = solve_a_unknown!(a_unknown, num_stages, monomial_coeffs, cS2, c; verbose) end @@ -107,9 +108,8 @@ function compute_PairedExplicitRK3_butcher_tableau(num_stages, tspan, return a_matrix, c, dt_opt end -#TODO: Correct this and make it actually import A matrix # Compute the Butcher tableau for a paired explicit Runge-Kutta method order 3 -# using provided monomial coefficients file +# using provided values of coefficients a in a matrix of Butcher tableau function compute_PairedExplicitRK3_butcher_tableau(num_stages, base_path_a_coeffs::AbstractString; cS2) @@ -118,26 +118,26 @@ function compute_PairedExplicitRK3_butcher_tableau(num_stages, c = compute_c_coeffs_SSP33(num_stages, cS2) # - 2 Since First entry of A is always zero (explicit method) and second is given by c_2 (consistency) - coeffs_max = num_stages - 2 + a_coeffs_max = num_stages - 2 - a_matrix = zeros(coeffs_max, 2) + a_matrix = zeros(a_coeffs_max, 2) a_matrix[:, 1] = c[3:end] path_a_coeffs = joinpath(base_path_a_coeffs, - "a_" * string(num_stages) * "_" * string(num_stages) * ".txt") + "a_" * string(num_stages) * "_" * string(num_stages) * + ".txt") @assert isfile(path_a_coeffs) "Couldn't find file" - A = readdlm(path_a_coeffs, Float64) - num_a_coeffs = size(A, 1) + a_coeffs = readdlm(path_a_coeffs, Float64) + num_a_coeffs = size(a_coeffs, 1) - @assert num_a_coeffs == coeffs_max - a_matrix[:, 1] -= A - a_matrix[:, 2] = A + @assert num_a_coeffs == a_coeffs_max + a_matrix[:, 1] -= a_coeffs + a_matrix[:, 2] = a_coeffs return a_matrix, c end -#TODO: explain dt_opt and also explain base_path_a_coeffs in the first constructor @doc raw""" PairedExplicitRK3(num_stages, base_path_a_coeffs::AbstractString, dt_opt; @@ -149,9 +149,9 @@ end Parameters: - `num_stages` (`Int`): Number of stages in the PERK method. - - `base_path_monomial_coeffs` (`AbstractString`): Path to a file containing - monomial coefficients of the stability polynomial of PERK method. - The coefficients should be stored in a text file at `joinpath(base_path_monomial_coeffs, "gamma_$(num_stages).txt")` and separated by line breaks. + - `base_path_a_coeffs` (`AbstractString`): Path to a file containing some coefficients in the matrix A in + the Butcher tableau of the Runge Kutta method. + The matrix should be stored in a text file at `joinpath(base_path_a_coeffs, "a_$(num_stages)_.$(num_stages)txt")` and separated by line breaks. - `tspan`: Time span of the simulation. - `semi` (`AbstractSemidiscretization`): Semidiscretization setup. - `eig_vals` (`Vector{ComplexF64}`): Eigenvalues of the Jacobian of the right-hand side (rhs) of the ODEProblem after the diff --git a/test/test_structured_1d.jl b/test/test_structured_1d.jl index 3401b314ce..7b1c28aa1d 100644 --- a/test/test_structured_1d.jl +++ b/test/test_structured_1d.jl @@ -47,7 +47,7 @@ end @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_shockcapturing.jl"), l2=[0.08015029105233593], linf=[0.610709468736576], - atol=1.0e-5) + atol=1.0e-12) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let @@ -58,11 +58,11 @@ end end end - @trixi_testset "elixir_burgers_perk3.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_burgers_perk3.jl"), - l2=[8.120426329330083e-8], - linf=[4.906376900315479e-7]) + l2=[8.120426320528704e-8], + linf=[4.906376875890572e-7], + atol=1.0e-5) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let diff --git a/test/test_unit.jl b/test/test_unit.jl index eecbe315bc..62a04496c0 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -1679,18 +1679,9 @@ end end @testset "PERK Single p3 Constructors" begin - # We are only testing from the second row to the end of `ode_algorithm.a_matrix` due to the nature of the system of equations - # used to find the `a_matrix` in the Butcher tableau. This system can have multiple valid solutions, which can cause slight - # variations in the results of the tests. These variations don't affect the validity of the solutions, but they can cause - # the tests to fail due to small differences in the expected and actual values. - - # The first row of `ode_algorithm.a_matrix` is particularly susceptible to these variations, while the rest of the rows - # remain consistent across different runs. Therefore, to make the tests more robust and less prone to false negatives, - # we are excluding the first row from the test. This approach allows us to verify the correctness of the majority of the - # `a_matrix` while avoiding the issue of test instability caused by the multiple valid solutions of the system of equations. path_coeff_file = mktempdir() Trixi.download("https://gist.githubusercontent.com/warisa-r/0796db36abcd5abe735ac7eebf41b973/raw/32889062fd5dcf7f450748f4f5f0797c8155a18d/a_8_8.txt", - joinpath(path_coeff_file, "a_8_8.txt")) + joinpath(path_coeff_file, "a_8_8.txt")) # Value of dt_opt obtained from running the simulation in elixir_burgers_perk3 # The value plays no role in the result but added so that the constructor can be called @@ -1698,31 +1689,33 @@ end ode_algorithm = Trixi.PairedExplicitRK3(8, path_coeff_file, dt_opt) #TODO: adjust this value according to the result in the test pipeline - @test isapprox(ode_algorithm.a_matrix[2:end, :], - [0.496535 0.103465 - 0.649689 0.150311 - 0.789172 0.210828 - 0.752297 0.247703 - 0.311926 0.188074], atol = 1e-13) - - #TODO: make this a p3 Constructors + println(ode_algorithm.a_matrix) # Value in CI differs slightly from what I get locally + @test isapprox(ode_algorithm.a_matrix, + [0.3355167784195604 0.06448322158043965 + 0.4965349205803965 0.10346507941960345 + 0.6496890792935297 0.15031092070647037 + 0.789172498521197 0.21082750147880308 + 0.7522972036571336 0.2477027963428664 + 0.31192569908571666 0.18807430091428337], atol = 1e-13) + Trixi.download("https://gist.githubusercontent.com/warisa-r/8d93f6a3ae0635e13b9f51ee32ab7fff/raw/54dc5b14be9288e186b745facb5bbcb04d1476f8/EigenvalueList_Refined2.txt", joinpath(path_coeff_file, "spectrum.txt")) eig_vals = readdlm(joinpath(path_coeff_file, "spectrum.txt"), ComplexF64) tspan = (0.0, 1.0) - ode_algorithm = Trixi.PairedExplicitRK3(10, tspan, vec(eig_vals)) + ode_algorithm = Trixi.PairedExplicitRK3(13, tspan, vec(eig_vals)) #TODO: adjust this value according to the result in the test pipeline - display(ode_algorithm.a_matrix) # Value in CI differs slightly from what I get locally - @test isapprox(ode_algorithm.a_matrix[2:end, :], - [0.406023 0.0225489 - 0.534288 0.0371408 - 0.654943 0.0593431 - 0.76216 0.0949827 - 0.844659 0.155341 - 0.771998 0.228002 - 0.307001 0.192999], atol = 1e-13) + println(ode_algorithm.a_matrix) # Value in CI differs slightly from what I get locally + @test isapprox(ode_algorithm.a_matrix, + [0.27321088155198703 0.01250340416229867 + 0.4060225225166573 0.022548906054771216 + 0.534287756076577 0.03714081535199439 + 0.6549425779583463 0.05934313632736803 + 0.7621601562844809 0.09498270085837623 + 0.8446587253087918 0.1553412746912082 + 0.7719976108598626 0.22800238914013735 + 0.30700059728503437 0.1929994027149656], atol = 1e-13) end @testset "Sutherlands Law" begin From 43cf02d08d7bff63467e6b6cb80c1696e0a03846 Mon Sep 17 00:00:00 2001 From: Warisa Date: Tue, 4 Jun 2024 20:49:09 +0200 Subject: [PATCH 013/120] add NLsolve as a dependency for testing --- Project.toml | 1 + test/Project.toml | 2 ++ 2 files changed, 3 insertions(+) diff --git a/Project.toml b/Project.toml index 901e947784..5f55809031 100644 --- a/Project.toml +++ b/Project.toml @@ -90,6 +90,7 @@ Polyester = "0.7.10" PrecompileTools = "1.1" Preferences = "1.3" Printf = "1" +Random = "1" RecipesBase = "1.1" Reexport = "1.0" Requires = "1.1" diff --git a/test/Project.toml b/test/Project.toml index c8ae33a40a..84d35d6ca2 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -10,6 +10,7 @@ FFMPEG = "c87230d0-a227-11e9-1b43-d7ebe4e7570a" ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" MPI = "da04e1cc-30fd-572f-bb4f-1f8673147195" +NLsolve = "2774e3e8-f4cf-5e23-947b-6d7e65073b56" OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed" Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" @@ -28,6 +29,7 @@ FFMPEG = "0.4" ForwardDiff = "0.10.24" LinearAlgebra = "1" MPI = "0.20" +NLsolve = "4.5.1" OrdinaryDiffEq = "6.49.1" Plots = "1.19" Printf = "1" From 9ed5e2b22e59baa6e226625eb8435a22f84704d0 Mon Sep 17 00:00:00 2001 From: Warisa Roongaraya <81345089+warisa-r@users.noreply.github.com> Date: Thu, 6 Jun 2024 19:20:36 +0200 Subject: [PATCH 014/120] Update ext/TrixiNLsolveExt.jl Co-authored-by: Daniel Doehring --- ext/TrixiNLsolveExt.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index cbe022b1f3..f86309f54a 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -25,7 +25,7 @@ using Trixi: Trixi, solve_a_unknown! @muladd begin #! format: noindent -# Find the values of a in the Butcher tableau by solving a system of +# Find the values of the a_{i, i-1} in the Butcher tableau matrix A by solving a system of # non-linear equations function Trixi.solve_a_unknown!(a_unknown, num_stages, monomial_coeffs, c_s2, c; verbose) From a7393507e770da92f26570f4346793d413503500 Mon Sep 17 00:00:00 2001 From: Warisa Roongaraya <81345089+warisa-r@users.noreply.github.com> Date: Thu, 6 Jun 2024 19:20:43 +0200 Subject: [PATCH 015/120] Update ext/TrixiNLsolveExt.jl Co-authored-by: Daniel Doehring --- ext/TrixiNLsolveExt.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index f86309f54a..d894198127 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -45,7 +45,8 @@ function Trixi.solve_a_unknown!(a_unknown, num_stages, monomial_coeffs, c_s2, c; while !is_sol_valid # Initialize initial guess - # The nonlinear system may have multiple valid solutions, so a reproducible initial guess is important + # The nonlinear system may have multiple valid solutions. + # For the sake of reproducibility, we use a seeded random initial guess x0 = 0.1 .* rand(num_stages) x0[1] = 0.0 x0[2] = c[2] From cf7178422a8bcd5cb3288a9dffa2db5b838f91f5 Mon Sep 17 00:00:00 2001 From: Warisa Roongaraya <81345089+warisa-r@users.noreply.github.com> Date: Thu, 6 Jun 2024 19:20:57 +0200 Subject: [PATCH 016/120] Update ext/TrixiNLsolveExt.jl Co-authored-by: Daniel Doehring --- ext/TrixiNLsolveExt.jl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index d894198127..6181011515 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -26,7 +26,9 @@ using Trixi: Trixi, solve_a_unknown! #! format: noindent # Find the values of the a_{i, i-1} in the Butcher tableau matrix A by solving a system of -# non-linear equations +# non-linear equations that arise from the relation of the stability polynomial to the Butcher tableau. +# For details, see Proposition 3.2, Equation (3.3) from +# Hairer, Wanner: Solving Ordinary Differential Equations 2 function Trixi.solve_a_unknown!(a_unknown, num_stages, monomial_coeffs, c_s2, c; verbose) is_sol_valid = false From 01a43433222727f32291c9705cdcf8502e7f5486 Mon Sep 17 00:00:00 2001 From: Warisa Roongaraya <81345089+warisa-r@users.noreply.github.com> Date: Thu, 6 Jun 2024 19:21:02 +0200 Subject: [PATCH 017/120] Update ext/TrixiNLsolveExt.jl Co-authored-by: Daniel Doehring --- ext/TrixiNLsolveExt.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index 6181011515..27438b6985 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -50,6 +50,7 @@ function Trixi.solve_a_unknown!(a_unknown, num_stages, monomial_coeffs, c_s2, c; # The nonlinear system may have multiple valid solutions. # For the sake of reproducibility, we use a seeded random initial guess x0 = 0.1 .* rand(num_stages) + # For explicit methods, a_{1,1} = 0 and a_{2,1} = c_2 (Butcher's condition) x0[1] = 0.0 x0[2] = c[2] From 0deb7bce70b105db5c5bd556d1df30e28ed6e0f3 Mon Sep 17 00:00:00 2001 From: Warisa Roongaraya <81345089+warisa-r@users.noreply.github.com> Date: Thu, 6 Jun 2024 19:21:09 +0200 Subject: [PATCH 018/120] Update ext/TrixiNLsolveExt.jl Co-authored-by: Daniel Doehring --- ext/TrixiNLsolveExt.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index 27438b6985..01919914d6 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -54,7 +54,8 @@ function Trixi.solve_a_unknown!(a_unknown, num_stages, monomial_coeffs, c_s2, c; x0[1] = 0.0 x0[2] = c[2] - sol = nlsolve(objective_function, x0, method = :trust_region, ftol = 4e-16, + sol = nlsolve(objective_function, x0, method = :trust_region, + ftol = 4e-16, # Enforce objective up to machine precision iterations = 10^4, xtol = 1e-13) a_unknown = sol.zero From 0708bc4b697b7620ba7a770bb09072af4ef0af16 Mon Sep 17 00:00:00 2001 From: Warisa Roongaraya <81345089+warisa-r@users.noreply.github.com> Date: Thu, 6 Jun 2024 19:21:27 +0200 Subject: [PATCH 019/120] Update src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl Co-authored-by: Daniel Doehring --- .../paired_explicit_runge_kutta/methods_PERK3.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index ae2042872a..fe3f30dd01 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -12,8 +12,8 @@ function compute_c_coeffs_SSP33(num_stages, cS2) c = zeros(num_stages) # Last timesteps as for SSPRK33 - c[num_stages] = 0.5 c[num_stages - 1] = 1 + c[num_stages] = 0.5 # Linear increasing timestep for remainder for i in 2:(num_stages - 2) From 0a5ad480653814c70e07080be2fbac509d526f8f Mon Sep 17 00:00:00 2001 From: Warisa Roongaraya <81345089+warisa-r@users.noreply.github.com> Date: Thu, 6 Jun 2024 19:21:32 +0200 Subject: [PATCH 020/120] Update src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl Co-authored-by: Daniel Doehring --- .../paired_explicit_runge_kutta/methods_PERK3.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index fe3f30dd01..13435fe5c5 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -132,6 +132,7 @@ function compute_PairedExplicitRK3_butcher_tableau(num_stages, num_a_coeffs = size(a_coeffs, 1) @assert num_a_coeffs == a_coeffs_max + # Fill A-matrix in P-ERK style a_matrix[:, 1] -= a_coeffs a_matrix[:, 2] = a_coeffs From 0a3ab554c1ddb9f94fa6ee919cf19147f34ae9bb Mon Sep 17 00:00:00 2001 From: Warisa Roongaraya <81345089+warisa-r@users.noreply.github.com> Date: Thu, 6 Jun 2024 19:21:36 +0200 Subject: [PATCH 021/120] Update src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl Co-authored-by: Daniel Doehring --- .../paired_explicit_runge_kutta/methods_PERK3.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index 13435fe5c5..a571859eb2 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -163,7 +163,6 @@ end The following structures and methods provide a implementation of the third-order paired explicit Runge-Kutta method - optimized for a certain simulation setup (PDE, IC & BC, Riemann Solver, DG Solver). The original paper is - Nasab, Vermeire (2022) From 8c978e2cb48222da7ce6bc74a2377ddbefe0d252 Mon Sep 17 00:00:00 2001 From: Warisa Roongaraya <81345089+warisa-r@users.noreply.github.com> Date: Thu, 6 Jun 2024 19:21:44 +0200 Subject: [PATCH 022/120] Update src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl Co-authored-by: Daniel Doehring --- .../paired_explicit_runge_kutta/methods_PERK3.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index a571859eb2..28d2bc153c 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -99,7 +99,7 @@ function compute_PairedExplicitRK3_butcher_tableau(num_stages, tspan, a_unknown = solve_a_unknown!(a_unknown, num_stages, monomial_coeffs, cS2, c; verbose) end - + # Fill A-matrix in P-ERK style a_matrix = zeros(num_stages - 2, 2) a_matrix[:, 1] = c[3:end] a_matrix[:, 1] -= a_unknown[3:end] From 45324a26d5ead88f7c96948dab358fb17bbcf80a Mon Sep 17 00:00:00 2001 From: Warisa Date: Mon, 10 Jun 2024 14:44:33 +0200 Subject: [PATCH 023/120] optimize the loop for step! by moving the condition outside --- ext/TrixiConvexECOSExt.jl | 2 +- .../paired_explicit_runge_kutta/methods_PERK3.jl | 12 +++++------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/ext/TrixiConvexECOSExt.jl b/ext/TrixiConvexECOSExt.jl index 948dbf103c..fac127699c 100644 --- a/ext/TrixiConvexECOSExt.jl +++ b/ext/TrixiConvexECOSExt.jl @@ -136,7 +136,7 @@ function Trixi.bisect_stability_polynomial(consistency_order, num_eig_vals, "reltol_inacc" => 5e-5, "nitref" => 9, "maxit" => 100, - "verbose" => 3); silent = true) + "verbose" => 3); silent_solver = true) abs_p = problem.optval diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index 28d2bc153c..cc4cad7ba7 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -344,7 +344,7 @@ function step!(integrator::PairedExplicitRK3Integrator) end # Higher stages - for stage in 3:(alg.num_stages) + for stage in 3:(alg.num_stages-1) # Construct current state @threaded for i in eachindex(integrator.du) integrator.u_tmp[i] = integrator.u[i] + @@ -360,13 +360,11 @@ function step!(integrator::PairedExplicitRK3Integrator) @threaded for i in eachindex(integrator.du) integrator.k_higher[i] = integrator.du[i] * integrator.dt end + end - # IDEA: Stop for loop at num_stages -1 to avoid if (maybe more performant?) - if stage == alg.num_stages - 1 - @threaded for i in eachindex(integrator.du) - integrator.k_s1[i] = integrator.k_higher[i] - end - end + # IDEA: Stop for loop at num_stages -1 to avoid if (maybe more performant?) + @threaded for i in eachindex(integrator.du) + integrator.k_s1[i] = integrator.k_higher[i] end @threaded for i in eachindex(integrator.u) From ca5951ae41ff615a9ea27cfbba2f1916fc15249d Mon Sep 17 00:00:00 2001 From: Warisa Date: Mon, 10 Jun 2024 14:53:55 +0200 Subject: [PATCH 024/120] fmt --- ext/TrixiNLsolveExt.jl | 2 +- .../paired_explicit_runge_kutta/methods_PERK3.jl | 11 +++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index 01919914d6..0d6eae1ba7 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -54,7 +54,7 @@ function Trixi.solve_a_unknown!(a_unknown, num_stages, monomial_coeffs, c_s2, c; x0[1] = 0.0 x0[2] = c[2] - sol = nlsolve(objective_function, x0, method = :trust_region, + sol = nlsolve(objective_function, x0, method = :trust_region, ftol = 4e-16, # Enforce objective up to machine precision iterations = 10^4, xtol = 1e-13) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index cc4cad7ba7..89a8978897 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -24,7 +24,7 @@ function compute_c_coeffs_SSP33(num_stages, cS2) end # Compute residuals for nonlinear equations to match a stability polynomial with given coefficients, -# in order to find A matrix in the Butcher-Tableau +# in order to find A-matrix in the Butcher-Tableau function PairedExplicitRK3_butcher_tableau_objective_function(a_unknown, num_stages, num_stage_evals, monomial_coeffs, cS2) @@ -99,7 +99,7 @@ function compute_PairedExplicitRK3_butcher_tableau(num_stages, tspan, a_unknown = solve_a_unknown!(a_unknown, num_stages, monomial_coeffs, cS2, c; verbose) end - # Fill A-matrix in P-ERK style + # Fill A-matrix in P-ERK style a_matrix = zeros(num_stages - 2, 2) a_matrix[:, 1] = c[3:end] a_matrix[:, 1] -= a_unknown[3:end] @@ -109,7 +109,7 @@ function compute_PairedExplicitRK3_butcher_tableau(num_stages, tspan, end # Compute the Butcher tableau for a paired explicit Runge-Kutta method order 3 -# using provided values of coefficients a in a matrix of Butcher tableau +# using provided values of coefficients a in A-matrix of Butcher tableau function compute_PairedExplicitRK3_butcher_tableau(num_stages, base_path_a_coeffs::AbstractString; cS2) @@ -150,7 +150,7 @@ end Parameters: - `num_stages` (`Int`): Number of stages in the PERK method. - - `base_path_a_coeffs` (`AbstractString`): Path to a file containing some coefficients in the matrix A in + - `base_path_a_coeffs` (`AbstractString`): Path to a file containing some coefficients in the A-matrix in the Butcher tableau of the Runge Kutta method. The matrix should be stored in a text file at `joinpath(base_path_a_coeffs, "a_$(num_stages)_.$(num_stages)txt")` and separated by line breaks. - `tspan`: Time span of the simulation. @@ -344,7 +344,7 @@ function step!(integrator::PairedExplicitRK3Integrator) end # Higher stages - for stage in 3:(alg.num_stages-1) + for stage in 3:(alg.num_stages - 1) # Construct current state @threaded for i in eachindex(integrator.du) integrator.u_tmp[i] = integrator.u[i] + @@ -362,7 +362,6 @@ function step!(integrator::PairedExplicitRK3Integrator) end end - # IDEA: Stop for loop at num_stages -1 to avoid if (maybe more performant?) @threaded for i in eachindex(integrator.du) integrator.k_s1[i] = integrator.k_higher[i] end From 76a7a6bf8f52cb5ef5fb7a59345740cda7181650 Mon Sep 17 00:00:00 2001 From: Warisa Date: Mon, 10 Jun 2024 15:03:28 +0200 Subject: [PATCH 025/120] more type generic --- ext/TrixiNLsolveExt.jl | 4 ++-- .../paired_explicit_runge_kutta/methods_PERK3.jl | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index 0d6eae1ba7..5830d23fae 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -51,7 +51,7 @@ function Trixi.solve_a_unknown!(a_unknown, num_stages, monomial_coeffs, c_s2, c; # For the sake of reproducibility, we use a seeded random initial guess x0 = 0.1 .* rand(num_stages) # For explicit methods, a_{1,1} = 0 and a_{2,1} = c_2 (Butcher's condition) - x0[1] = 0.0 + x0[1] = 0 x0[2] = c[2] sol = nlsolve(objective_function, x0, method = :trust_region, @@ -61,7 +61,7 @@ function Trixi.solve_a_unknown!(a_unknown, num_stages, monomial_coeffs, c_s2, c; a_unknown = sol.zero # Check if the values a[i, i-1] >= 0.0 (which stem from the nonlinear solver) - # and subsequently c[i] - a[i, i-1] >= 0.0 + # and subsequently c[i] - a[i, i-1] >= 0.0 since all coefficients are non-negative is_sol_valid = all(x -> !isnan(x) && x >= 0, a_unknown[3:end]) && all(x -> !isnan(x) && x >= 0, c[3:end] .- a_unknown[3:end]) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index 89a8978897..1972ca89d8 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -57,7 +57,7 @@ function PairedExplicitRK3_butcher_tableau_objective_function(a_unknown, num_sta term2 *= c_ts[num_stages - 1 - i] * 4 / 6 c_eq[i] = monomial_coeffs[i] - term2 - c_eq[num_stage_evals - 2] = 1.0 - 4 * a_unknown[num_stage_evals] - + c_eq[num_stage_evals - 2] = 1 - 4 * a_unknown[num_stage_evals] - a_unknown[num_stage_evals - 1] return c_eq @@ -194,7 +194,7 @@ end # Constructor that computes Butcher matrix A coefficients from a semidiscretization function PairedExplicitRK3(num_stages, tspan, semi::AbstractSemidiscretization; - verbose = false, cS2 = 1.0) + verbose = false, cS2 = 1) eig_vals = eigvals(jacobian_ad_forward(semi)) return PairedExplicitRK3(num_stages, tspan, eig_vals; verbose, cS2) @@ -202,7 +202,7 @@ end # Constructor that calculates the coefficients with polynomial optimizer from a list of eigenvalues function PairedExplicitRK3(num_stages, tspan, eig_vals::Vector{ComplexF64}; - verbose = false, cS2 = 1.0) + verbose = false, cS2 = 1) a_matrix, c, dt_opt = compute_PairedExplicitRK3_butcher_tableau(num_stages, tspan, eig_vals; From 03fad1bf8bcf76cd4f7794a374b36cb9c3ae2612 Mon Sep 17 00:00:00 2001 From: Warisa Date: Mon, 10 Jun 2024 15:05:00 +0200 Subject: [PATCH 026/120] change some names --- .../paired_explicit_runge_kutta/methods_PERK3.jl | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index 1972ca89d8..201bfffeb5 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -233,7 +233,7 @@ mutable struct PairedExplicitRK3Integrator{RealT <: Real, uType, Params, Sol, F, # PairedExplicitRK stages: k1::uType k_higher::uType - k_s1::uType # Required for custom third order version of PairedExplicitRK3 + k_S1::uType # Required for custom third order version of PairedExplicitRK3 end function init(ode::ODEProblem, alg::PairedExplicitRK3; @@ -245,7 +245,7 @@ function init(ode::ODEProblem, alg::PairedExplicitRK3; # PairedExplicitRK stages k1 = zero(u0) k_higher = zero(u0) - k_s1 = zero(u0) + k_S1 = zero(u0) t0 = first(ode.tspan) iter = 0 @@ -257,7 +257,7 @@ function init(ode::ODEProblem, alg::PairedExplicitRK3; ode.tspan; kwargs...), false, - k1, k_higher, k_s1) + k1, k_higher, k_S1) # initialize callbacks if callback isa CallbackSet @@ -339,7 +339,7 @@ function step!(integrator::PairedExplicitRK3Integrator) if alg.num_stages == 3 @threaded for i in eachindex(integrator.du) - integrator.k_s1[i] = integrator.k_higher[i] + integrator.k_S1[i] = integrator.k_higher[i] end end @@ -363,12 +363,12 @@ function step!(integrator::PairedExplicitRK3Integrator) end @threaded for i in eachindex(integrator.du) - integrator.k_s1[i] = integrator.k_higher[i] + integrator.k_S1[i] = integrator.k_higher[i] end @threaded for i in eachindex(integrator.u) # "Own" PairedExplicitRK based on SSPRK33 - integrator.u[i] += (integrator.k1[i] + integrator.k_s1[i] + + integrator.u[i] += (integrator.k1[i] + integrator.k_S1[i] + 4.0 * integrator.k_higher[i]) / 6.0 end end # PairedExplicitRK step timer @@ -401,6 +401,6 @@ function Base.resize!(integrator::PairedExplicitRK3Integrator, new_size) resize!(integrator.k1, new_size) resize!(integrator.k_higher, new_size) - resize!(integrator.k_s1, new_size) + resize!(integrator.k_S1, new_size) end end # @muladd From 78ae8da84b8104e750d8350966e55c97bd018eac Mon Sep 17 00:00:00 2001 From: Warisa Date: Mon, 10 Jun 2024 15:08:26 +0200 Subject: [PATCH 027/120] update test --- test/test_structured_1d.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/test_structured_1d.jl b/test/test_structured_1d.jl index 7b1c28aa1d..513d7e710a 100644 --- a/test/test_structured_1d.jl +++ b/test/test_structured_1d.jl @@ -60,9 +60,9 @@ end @trixi_testset "elixir_burgers_perk3.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_burgers_perk3.jl"), - l2=[8.120426320528704e-8], - linf=[4.906376875890572e-7], - atol=1.0e-5) + l2=[NaN], + linf=[0.0], + atol=1.0e-12) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let From c5c455f8df8db8fd4a82405b4969a4fb82b09212 Mon Sep 17 00:00:00 2001 From: Warisa Date: Mon, 10 Jun 2024 21:28:10 +0200 Subject: [PATCH 028/120] Correcting steps! --- .../paired_explicit_runge_kutta/methods_PERK3.jl | 15 +++++++++++++++ test/test_structured_1d.jl | 6 +++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index 201bfffeb5..4938d37d5e 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -366,6 +366,21 @@ function step!(integrator::PairedExplicitRK3Integrator) integrator.k_S1[i] = integrator.k_higher[i] end + # Last stage + @threaded for i in eachindex(integrator.du) + integrator.u_tmp[i] = integrator.u[i] + + alg.a_matrix[alg.num_stages - 2, 1] * + integrator.k1[i] + + alg.a_matrix[alg.num_stages - 2, 2] * + integrator.k_higher[i] + end + + integrator.f(integrator.du, integrator.u_tmp, prob.p, + integrator.t + alg.c[alg.num_stages] * integrator.dt) + @threaded for i in eachindex(integrator.du) + integrator.k_higher[i] = integrator.du[i] * integrator.dt + end + @threaded for i in eachindex(integrator.u) # "Own" PairedExplicitRK based on SSPRK33 integrator.u[i] += (integrator.k1[i] + integrator.k_S1[i] + diff --git a/test/test_structured_1d.jl b/test/test_structured_1d.jl index 513d7e710a..279febbd5b 100644 --- a/test/test_structured_1d.jl +++ b/test/test_structured_1d.jl @@ -60,9 +60,9 @@ end @trixi_testset "elixir_burgers_perk3.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_burgers_perk3.jl"), - l2=[NaN], - linf=[0.0], - atol=1.0e-12) + l2=[8.120426320528704e-8], + linf=[4.906376875890572e-7], + atol=1.0e-6) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let From 1bfb576c9fb105d4990cbd8a0700ed3901cced80 Mon Sep 17 00:00:00 2001 From: Warisa Roongaraya <81345089+warisa-r@users.noreply.github.com> Date: Mon, 10 Jun 2024 21:31:33 +0200 Subject: [PATCH 029/120] Apply suggestions from code review Co-authored-by: Daniel Doehring --- .../paired_explicit_runge_kutta/methods_PERK3.jl | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index 4938d37d5e..33980d85ad 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -11,7 +11,9 @@ using DelimitedFiles: readdlm function compute_c_coeffs_SSP33(num_stages, cS2) c = zeros(num_stages) - # Last timesteps as for SSPRK33 + # Last timesteps as for SSPRK33, see motivation in + # https://doi.org/10.48550/arXiv.2403.05144 + c[num_stages - 1] = 1 c[num_stages] = 0.5 @@ -33,8 +35,10 @@ function PairedExplicitRK3_butcher_tableau_objective_function(a_unknown, num_sta # Equality Constraint array that ensures that the stability polynomial computed from # the to-be-constructed Butcher-Tableau matches the monomial coefficients of the # optimized stability polynomial. + # For details, see Chapter4.3, Proposition 3.2, Equation (3.3) from + # Hairer, Wanner: Solving Ordinary Differential Equations 2 c_eq = zeros(num_stage_evals - 2) # Add equality constraint that cS2 is equal to 1 - # Both terms should be present + # Lower-order terms: Two summands present for i in 1:(num_stage_evals - 4) term1 = a_unknown[num_stage_evals - 1] term2 = a_unknown[num_stage_evals] @@ -42,8 +46,8 @@ function PairedExplicitRK3_butcher_tableau_objective_function(a_unknown, num_sta term1 *= a_unknown[num_stage_evals - 1 - j] term2 *= a_unknown[num_stage_evals - j] end - term1 *= c_ts[num_stages - 2 - i] * 1 / 6 - term2 *= c_ts[num_stages - 1 - i] * 4 / 6 + term1 *= c_ts[num_stages - 2 - i] * 1 / 6 # 1/ 6 = b_{S-1} + term2 *= c_ts[num_stages - 1 - i] * 2 / 3 # 2 / 3 = b_S c_eq[i] = monomial_coeffs[i] - (term1 + term2) end @@ -54,7 +58,7 @@ function PairedExplicitRK3_butcher_tableau_objective_function(a_unknown, num_sta for j in 1:i term2 *= a_unknown[num_stage_evals - j] end - term2 *= c_ts[num_stages - 1 - i] * 4 / 6 + term2 *= c_ts[num_stages - 1 - i] * 2 / 3 # 2 / 3 = b_S c_eq[i] = monomial_coeffs[i] - term2 c_eq[num_stage_evals - 2] = 1 - 4 * a_unknown[num_stage_evals] - From 86a4daade36710989e773e1eb3605dd125de65ba Mon Sep 17 00:00:00 2001 From: Warisa Roongaraya <81345089+warisa-r@users.noreply.github.com> Date: Mon, 10 Jun 2024 21:31:56 +0200 Subject: [PATCH 030/120] Update examples/structured_1d_dgsem/elixir_burgers_perk3.jl Co-authored-by: Daniel Doehring --- examples/structured_1d_dgsem/elixir_burgers_perk3.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/structured_1d_dgsem/elixir_burgers_perk3.jl b/examples/structured_1d_dgsem/elixir_burgers_perk3.jl index 78d5c00374..1c54731c2d 100644 --- a/examples/structured_1d_dgsem/elixir_burgers_perk3.jl +++ b/examples/structured_1d_dgsem/elixir_burgers_perk3.jl @@ -10,7 +10,7 @@ equations = InviscidBurgersEquation1D() initial_condition = initial_condition_convergence_test -# Create DG solver with polynomial degree = 3 and (local) Lax-Friedrichs/Rusanov flux as surface flux +# 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) coordinates_min = (0.0,) # minimum coordinate From 786de996e447bb994a7f2b00738a355d0ccde243 Mon Sep 17 00:00:00 2001 From: Warisa Roongaraya <81345089+warisa-r@users.noreply.github.com> Date: Mon, 10 Jun 2024 21:32:09 +0200 Subject: [PATCH 031/120] Update examples/structured_1d_dgsem/elixir_burgers_perk3.jl Co-authored-by: Daniel Doehring --- examples/structured_1d_dgsem/elixir_burgers_perk3.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/structured_1d_dgsem/elixir_burgers_perk3.jl b/examples/structured_1d_dgsem/elixir_burgers_perk3.jl index 1c54731c2d..d93d3d0fbb 100644 --- a/examples/structured_1d_dgsem/elixir_burgers_perk3.jl +++ b/examples/structured_1d_dgsem/elixir_burgers_perk3.jl @@ -17,7 +17,6 @@ coordinates_min = (0.0,) # minimum coordinate coordinates_max = (1.0,) # maximum coordinate cells_per_dimension = (64,) -# Create curved mesh with 16 cells mesh = StructuredMesh(cells_per_dimension, coordinates_min, coordinates_max) semi = SemidiscretizationHyperbolic(mesh, equations, initial_condition, solver, From a3d6df5a8c5a8e1b84a889470daba98f21c46100 Mon Sep 17 00:00:00 2001 From: Warisa Date: Mon, 10 Jun 2024 22:46:24 +0200 Subject: [PATCH 032/120] add docstring about dt_opt --- .../paired_explicit_runge_kutta/methods_PERK3.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index 33980d85ad..e645ee37fc 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -157,6 +157,8 @@ end - `base_path_a_coeffs` (`AbstractString`): Path to a file containing some coefficients in the A-matrix in the Butcher tableau of the Runge Kutta method. The matrix should be stored in a text file at `joinpath(base_path_a_coeffs, "a_$(num_stages)_.$(num_stages)txt")` and separated by line breaks. + - `dt_opt` (`Float64`): The optimal time step size that must be supplied when using the first constructor with A-matrix coefficients, + unlike the second or third constructors which calculate it automatically. - `tspan`: Time span of the simulation. - `semi` (`AbstractSemidiscretization`): Semidiscretization setup. - `eig_vals` (`Vector{ComplexF64}`): Eigenvalues of the Jacobian of the right-hand side (rhs) of the ODEProblem after the From 4e35589736c74961dbe0a4aed1f882b1a185d135 Mon Sep 17 00:00:00 2001 From: Warisa Roongaraya <81345089+warisa-r@users.noreply.github.com> Date: Tue, 11 Jun 2024 17:30:05 +0200 Subject: [PATCH 033/120] Update src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl Co-authored-by: Daniel Doehring --- .../paired_explicit_runge_kutta/methods_PERK3.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index e645ee37fc..32f0a152c4 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -368,6 +368,7 @@ function step!(integrator::PairedExplicitRK3Integrator) end end + # Store K_{S-1} @threaded for i in eachindex(integrator.du) integrator.k_S1[i] = integrator.k_higher[i] end From a4b3df6d893f8f4ea9da9154047d5f0e5af25d22 Mon Sep 17 00:00:00 2001 From: Warisa Date: Wed, 12 Jun 2024 09:41:10 +0200 Subject: [PATCH 034/120] merge k_higher in the last stage to a bigger loop --- .../paired_explicit_runge_kutta/methods_PERK3.jl | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index 32f0a152c4..08a107a536 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -384,14 +384,11 @@ function step!(integrator::PairedExplicitRK3Integrator) integrator.f(integrator.du, integrator.u_tmp, prob.p, integrator.t + alg.c[alg.num_stages] * integrator.dt) - @threaded for i in eachindex(integrator.du) - integrator.k_higher[i] = integrator.du[i] * integrator.dt - end @threaded for i in eachindex(integrator.u) # "Own" PairedExplicitRK based on SSPRK33 integrator.u[i] += (integrator.k1[i] + integrator.k_S1[i] + - 4.0 * integrator.k_higher[i]) / 6.0 + 4.0 * integrator.du[i] * integrator.dt) / 6.0 end end # PairedExplicitRK step timer From 6a03a3ae1a25f331d46e61ae4dfcf7f1bb3eba9f Mon Sep 17 00:00:00 2001 From: Warisa Roongaraya <81345089+warisa-r@users.noreply.github.com> Date: Wed, 12 Jun 2024 09:44:54 +0200 Subject: [PATCH 035/120] Update src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl Co-authored-by: Daniel Doehring --- .../paired_explicit_runge_kutta/methods_PERK3.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index 08a107a536..78523b3366 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -61,6 +61,7 @@ function PairedExplicitRK3_butcher_tableau_objective_function(a_unknown, num_sta term2 *= c_ts[num_stages - 1 - i] * 2 / 3 # 2 / 3 = b_S c_eq[i] = monomial_coeffs[i] - term2 + # Third-order consistency condition (Cf. eq. (27) from https://doi.org/10.1016/j.jcp.2022.111470 c_eq[num_stage_evals - 2] = 1 - 4 * a_unknown[num_stage_evals] - a_unknown[num_stage_evals - 1] From b5f227aefa9f846c3d0f0fa3d99cdb357917cdad Mon Sep 17 00:00:00 2001 From: Warisa Date: Fri, 14 Jun 2024 11:50:47 +0200 Subject: [PATCH 036/120] change solve_step! to solve! --- .../paired_explicit_runge_kutta/methods_PERK3.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index 78523b3366..f2565dea68 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -287,10 +287,10 @@ function solve(ode::ODEProblem, alg::PairedExplicitRK3; integrator = init(ode, alg, dt = dt, callback = callback; kwargs...) # Start actual solve - solve_steps!(integrator) + solve!(integrator) end -function solve_steps!(integrator::PairedExplicitRK3Integrator) +function solve!(integrator::PairedExplicitRK3Integrator) @unpack prob = integrator.sol integrator.finalstep = false From d029c218a201c614b47db0051272e010bde4c9b9 Mon Sep 17 00:00:00 2001 From: Warisa Date: Mon, 17 Jun 2024 14:53:29 +0200 Subject: [PATCH 037/120] Correct the logic of step! --- .../methods_PERK2.jl | 4 +- .../methods_PERK3.jl | 148 +++++++++--------- 2 files changed, 74 insertions(+), 78 deletions(-) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK2.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK2.jl index b3b917dc18..1d9680153e 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK2.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK2.jl @@ -273,10 +273,10 @@ function solve(ode::ODEProblem, alg::PairedExplicitRK2; integrator = init(ode, alg, dt = dt, callback = callback; kwargs...) # Start actual solve - solve_steps!(integrator) + solve!(integrator) end -function solve_steps!(integrator::PairedExplicitRK2Integrator) +function solve!(integrator::PairedExplicitRK2Integrator) @unpack prob = integrator.sol integrator.finalstep = false diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index f2565dea68..839b5629e8 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -310,107 +310,103 @@ function step!(integrator::PairedExplicitRK3Integrator) t_end = last(prob.tspan) callbacks = integrator.opts.callback - integrator.finalstep = false + @assert !integrator.finalstep + if isnan(integrator.dt) + error("time step size `dt` is NaN") + end - #@trixi_timeit timer() "main loop" while !integrator.finalstep - while !integrator.finalstep - if isnan(integrator.dt) - error("time step size `dt` is NaN") + # if the next iteration would push the simulation beyond the end time, set dt accordingly + if integrator.t + integrator.dt > t_end || + isapprox(integrator.t + integrator.dt, t_end) + integrator.dt = t_end - integrator.t + terminate!(integrator) + end + + @trixi_timeit timer() "Paired Explicit Runge-Kutta ODE integration step" begin + # k1 + integrator.f(integrator.du, integrator.u, prob.p, integrator.t) + @threaded for i in eachindex(integrator.du) + integrator.k1[i] = integrator.du[i] * integrator.dt end - # if the next iteration would push the simulation beyond the end time, set dt accordingly - if integrator.t + integrator.dt > t_end || - isapprox(integrator.t + integrator.dt, t_end) - integrator.dt = t_end - integrator.t - terminate!(integrator) + # Construct current state + @threaded for i in eachindex(integrator.du) + integrator.u_tmp[i] = integrator.u[i] + alg.c[2] * integrator.k1[i] end + # k2 + integrator.f(integrator.du, integrator.u_tmp, prob.p, + integrator.t + alg.c[2] * integrator.dt) - @trixi_timeit timer() "Paired Explicit Runge-Kutta ODE integration step" begin - # k1 - integrator.f(integrator.du, integrator.u, prob.p, integrator.t) + @threaded for i in eachindex(integrator.du) + integrator.k_higher[i] = integrator.du[i] * integrator.dt + end + + if alg.num_stages == 3 @threaded for i in eachindex(integrator.du) - integrator.k1[i] = integrator.du[i] * integrator.dt + integrator.k_S1[i] = integrator.k_higher[i] end + end + # Higher stages + for stage in 3:(alg.num_stages - 1) # Construct current state @threaded for i in eachindex(integrator.du) - integrator.u_tmp[i] = integrator.u[i] + alg.c[2] * integrator.k1[i] + integrator.u_tmp[i] = integrator.u[i] + + alg.a_matrix[stage - 2, 1] * + integrator.k1[i] + + alg.a_matrix[stage - 2, 2] * + integrator.k_higher[i] end - # k2 + integrator.f(integrator.du, integrator.u_tmp, prob.p, - integrator.t + alg.c[2] * integrator.dt) + integrator.t + alg.c[stage] * integrator.dt) @threaded for i in eachindex(integrator.du) integrator.k_higher[i] = integrator.du[i] * integrator.dt end + end - if alg.num_stages == 3 - @threaded for i in eachindex(integrator.du) - integrator.k_S1[i] = integrator.k_higher[i] - end - end - - # Higher stages - for stage in 3:(alg.num_stages - 1) - # Construct current state - @threaded for i in eachindex(integrator.du) - integrator.u_tmp[i] = integrator.u[i] + - alg.a_matrix[stage - 2, 1] * - integrator.k1[i] + - alg.a_matrix[stage - 2, 2] * - integrator.k_higher[i] - end - - integrator.f(integrator.du, integrator.u_tmp, prob.p, - integrator.t + alg.c[stage] * integrator.dt) - - @threaded for i in eachindex(integrator.du) - integrator.k_higher[i] = integrator.du[i] * integrator.dt - end - end - - # Store K_{S-1} - @threaded for i in eachindex(integrator.du) - integrator.k_S1[i] = integrator.k_higher[i] - end + # Store K_{S-1} + @threaded for i in eachindex(integrator.du) + integrator.k_S1[i] = integrator.k_higher[i] + end - # Last stage - @threaded for i in eachindex(integrator.du) - integrator.u_tmp[i] = integrator.u[i] + - alg.a_matrix[alg.num_stages - 2, 1] * - integrator.k1[i] + - alg.a_matrix[alg.num_stages - 2, 2] * - integrator.k_higher[i] - end + # Last stage + @threaded for i in eachindex(integrator.du) + integrator.u_tmp[i] = integrator.u[i] + + alg.a_matrix[alg.num_stages - 2, 1] * + integrator.k1[i] + + alg.a_matrix[alg.num_stages - 2, 2] * + integrator.k_higher[i] + end - integrator.f(integrator.du, integrator.u_tmp, prob.p, - integrator.t + alg.c[alg.num_stages] * integrator.dt) + integrator.f(integrator.du, integrator.u_tmp, prob.p, + integrator.t + alg.c[alg.num_stages] * integrator.dt) - @threaded for i in eachindex(integrator.u) - # "Own" PairedExplicitRK based on SSPRK33 - integrator.u[i] += (integrator.k1[i] + integrator.k_S1[i] + - 4.0 * integrator.du[i] * integrator.dt) / 6.0 - end - end # PairedExplicitRK step timer + @threaded for i in eachindex(integrator.u) + # "Own" PairedExplicitRK based on SSPRK33 + integrator.u[i] += (integrator.k1[i] + integrator.k_S1[i] + + 4.0 * integrator.du[i] * integrator.dt) / 6.0 + end + end # PairedExplicitRK step timer - integrator.iter += 1 - integrator.t += integrator.dt + integrator.iter += 1 + integrator.t += integrator.dt - # handle callbacks - if callbacks isa CallbackSet - for cb in callbacks.discrete_callbacks - if cb.condition(integrator.u, integrator.t, integrator) - cb.affect!(integrator) - end + # handle callbacks + if callbacks isa CallbackSet + for cb in callbacks.discrete_callbacks + if cb.condition(integrator.u, integrator.t, integrator) + cb.affect!(integrator) end end + end - # respect maximum number of iterations - if integrator.iter >= integrator.opts.maxiters && !integrator.finalstep - @warn "Interrupted. Larger maxiters is needed." - terminate!(integrator) - end - end # "main loop" timer + # respect maximum number of iterations + if integrator.iter >= integrator.opts.maxiters && !integrator.finalstep + @warn "Interrupted. Larger maxiters is needed." + terminate!(integrator) + end end # used for AMR (Adaptive Mesh Refinement) From ff5c590ef3831f8f2c8203c9602ed278c211099c Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Tue, 18 Jun 2024 14:52:43 +0200 Subject: [PATCH 038/120] deprecation --- ext/TrixiConvexECOSExt.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/TrixiConvexECOSExt.jl b/ext/TrixiConvexECOSExt.jl index fac127699c..948dbf103c 100644 --- a/ext/TrixiConvexECOSExt.jl +++ b/ext/TrixiConvexECOSExt.jl @@ -136,7 +136,7 @@ function Trixi.bisect_stability_polynomial(consistency_order, num_eig_vals, "reltol_inacc" => 5e-5, "nitref" => 9, "maxit" => 100, - "verbose" => 3); silent_solver = true) + "verbose" => 3); silent = true) abs_p = problem.optval From df7ec64a719604210b15c0aac8be118755158702 Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Tue, 18 Jun 2024 15:20:43 +0200 Subject: [PATCH 039/120] Optimize K_S1 away --- .../methods_PERK3.jl | 23 +++++-------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index 839b5629e8..235576d805 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -82,6 +82,7 @@ function compute_PairedExplicitRK3_butcher_tableau(num_stages, tspan, # Special case of e = 3 if num_stages == 3 a_unknown = [0, c[2], 0.25] + dt_opt = 42.0 # TODO! This is a placeholder value else # Calculate coefficients of the stability polynomial in monomial form consistency_order = 3 @@ -240,7 +241,6 @@ mutable struct PairedExplicitRK3Integrator{RealT <: Real, uType, Params, Sol, F, # PairedExplicitRK stages: k1::uType k_higher::uType - k_S1::uType # Required for custom third order version of PairedExplicitRK3 end function init(ode::ODEProblem, alg::PairedExplicitRK3; @@ -252,7 +252,6 @@ function init(ode::ODEProblem, alg::PairedExplicitRK3; # PairedExplicitRK stages k1 = zero(u0) k_higher = zero(u0) - k_S1 = zero(u0) t0 = first(ode.tspan) iter = 0 @@ -264,7 +263,7 @@ function init(ode::ODEProblem, alg::PairedExplicitRK3; ode.tspan; kwargs...), false, - k1, k_higher, k_S1) + k1, k_higher) # initialize callbacks if callback isa CallbackSet @@ -341,12 +340,6 @@ function step!(integrator::PairedExplicitRK3Integrator) integrator.k_higher[i] = integrator.du[i] * integrator.dt end - if alg.num_stages == 3 - @threaded for i in eachindex(integrator.du) - integrator.k_S1[i] = integrator.k_higher[i] - end - end - # Higher stages for stage in 3:(alg.num_stages - 1) # Construct current state @@ -366,11 +359,6 @@ function step!(integrator::PairedExplicitRK3Integrator) end end - # Store K_{S-1} - @threaded for i in eachindex(integrator.du) - integrator.k_S1[i] = integrator.k_higher[i] - end - # Last stage @threaded for i in eachindex(integrator.du) integrator.u_tmp[i] = integrator.u[i] + @@ -384,8 +372,10 @@ function step!(integrator::PairedExplicitRK3Integrator) integrator.t + alg.c[alg.num_stages] * integrator.dt) @threaded for i in eachindex(integrator.u) - # "Own" PairedExplicitRK based on SSPRK33 - integrator.u[i] += (integrator.k1[i] + integrator.k_S1[i] + + # "Own" PairedExplicitRK based on SSPRK33. + # Note that 'k_higher' carries the values of K_{S-1} + # and that we construct 'K_S' "in-place" from 'integrator.du' + integrator.u[i] += (integrator.k1[i] + integrator.k_higher[i] + 4.0 * integrator.du[i] * integrator.dt) / 6.0 end end # PairedExplicitRK step timer @@ -417,6 +407,5 @@ function Base.resize!(integrator::PairedExplicitRK3Integrator, new_size) resize!(integrator.k1, new_size) resize!(integrator.k_higher, new_size) - resize!(integrator.k_S1, new_size) end end # @muladd From b9977c0a946a4e75d3f86a185b380d8cf661911d Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Tue, 18 Jun 2024 15:22:47 +0200 Subject: [PATCH 040/120] fmt --- .../paired_explicit_runge_kutta/methods_PERK3.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index 235576d805..fa71fcefc6 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -371,7 +371,7 @@ function step!(integrator::PairedExplicitRK3Integrator) integrator.f(integrator.du, integrator.u_tmp, prob.p, integrator.t + alg.c[alg.num_stages] * integrator.dt) - @threaded for i in eachindex(integrator.u) + @threaded for i in eachindex(integrator.u) # "Own" PairedExplicitRK based on SSPRK33. # Note that 'k_higher' carries the values of K_{S-1} # and that we construct 'K_S' "in-place" from 'integrator.du' From 34d0eb58d8d601de77218a5d850c4aa345446c64 Mon Sep 17 00:00:00 2001 From: Warisa Date: Thu, 20 Jun 2024 18:25:21 +0200 Subject: [PATCH 041/120] remove dt_opt as an attribute of PERK3 --- .../methods_PERK3.jl | 17 ++++++----------- test/test_unit.jl | 5 +---- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index fa71fcefc6..f38a77f82a 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -111,7 +111,7 @@ function compute_PairedExplicitRK3_butcher_tableau(num_stages, tspan, a_matrix[:, 1] -= a_unknown[3:end] a_matrix[:, 2] = a_unknown[3:end] - return a_matrix, c, dt_opt + return a_matrix, c end # Compute the Butcher tableau for a paired explicit Runge-Kutta method order 3 @@ -146,8 +146,7 @@ function compute_PairedExplicitRK3_butcher_tableau(num_stages, end @doc raw""" - PairedExplicitRK3(num_stages, base_path_a_coeffs::AbstractString, - dt_opt; + PairedExplicitRK3(num_stages, base_path_a_coeffs::AbstractString; cS2 = 1.0) PairedExplicitRK3(num_stages, tspan, semi::AbstractSemidiscretization; verbose = false, cS2 = 1.0) @@ -159,8 +158,6 @@ end - `base_path_a_coeffs` (`AbstractString`): Path to a file containing some coefficients in the A-matrix in the Butcher tableau of the Runge Kutta method. The matrix should be stored in a text file at `joinpath(base_path_a_coeffs, "a_$(num_stages)_.$(num_stages)txt")` and separated by line breaks. - - `dt_opt` (`Float64`): The optimal time step size that must be supplied when using the first constructor with A-matrix coefficients, - unlike the second or third constructors which calculate it automatically. - `tspan`: Time span of the simulation. - `semi` (`AbstractSemidiscretization`): Semidiscretization setup. - `eig_vals` (`Vector{ComplexF64}`): Eigenvalues of the Jacobian of the right-hand side (rhs) of the ODEProblem after the @@ -186,18 +183,16 @@ mutable struct PairedExplicitRK3 <: AbstractPairedExplicitRKSingle a_matrix::Matrix{Float64} c::Vector{Float64} - dt_opt::Float64 end # struct PairedExplicitRK3 # Constructor for previously computed A Coeffs -function PairedExplicitRK3(num_stages, base_path_a_coeffs::AbstractString, - dt_opt; +function PairedExplicitRK3(num_stages, base_path_a_coeffs::AbstractString; cS2 = 1.0) a_matrix, c = compute_PairedExplicitRK3_butcher_tableau(num_stages, base_path_a_coeffs; cS2) - return PairedExplicitRK3(num_stages, a_matrix, c, dt_opt) + return PairedExplicitRK3(num_stages, a_matrix, c) end # Constructor that computes Butcher matrix A coefficients from a semidiscretization @@ -211,11 +206,11 @@ end # Constructor that calculates the coefficients with polynomial optimizer from a list of eigenvalues function PairedExplicitRK3(num_stages, tspan, eig_vals::Vector{ComplexF64}; verbose = false, cS2 = 1) - a_matrix, c, dt_opt = compute_PairedExplicitRK3_butcher_tableau(num_stages, + a_matrix, c = compute_PairedExplicitRK3_butcher_tableau(num_stages, tspan, eig_vals; verbose, cS2) - return PairedExplicitRK3(num_stages, a_matrix, c, dt_opt) + return PairedExplicitRK3(num_stages, a_matrix, c,) end # This struct is needed to fake https://github.com/SciML/OrdinaryDiffEq.jl/blob/0c2048a502101647ac35faabd80da8a5645beac7/src/integrators/type.jl#L77 diff --git a/test/test_unit.jl b/test/test_unit.jl index 4157f26dc6..ecc96a8b21 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -1683,10 +1683,7 @@ end Trixi.download("https://gist.githubusercontent.com/warisa-r/0796db36abcd5abe735ac7eebf41b973/raw/32889062fd5dcf7f450748f4f5f0797c8155a18d/a_8_8.txt", joinpath(path_coeff_file, "a_8_8.txt")) - # Value of dt_opt obtained from running the simulation in elixir_burgers_perk3 - # The value plays no role in the result but added so that the constructor can be called - dt_opt = 0.004485771991312504 - ode_algorithm = Trixi.PairedExplicitRK3(8, path_coeff_file, dt_opt) + ode_algorithm = Trixi.PairedExplicitRK3(8, path_coeff_file) #TODO: adjust this value according to the result in the test pipeline println(ode_algorithm.a_matrix) # Value in CI differs slightly from what I get locally From 13ac6dc60310db30857037df0223833fb95ef706 Mon Sep 17 00:00:00 2001 From: Warisa Date: Mon, 24 Jun 2024 14:30:17 +0200 Subject: [PATCH 042/120] change the objective function to match the number of equations --- ext/TrixiConvexECOSExt.jl | 2 +- ext/TrixiNLsolveExt.jl | 13 ++++----- .../methods_PERK3.jl | 29 ++++++++++--------- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/ext/TrixiConvexECOSExt.jl b/ext/TrixiConvexECOSExt.jl index 948dbf103c..fac127699c 100644 --- a/ext/TrixiConvexECOSExt.jl +++ b/ext/TrixiConvexECOSExt.jl @@ -136,7 +136,7 @@ function Trixi.bisect_stability_polynomial(consistency_order, num_eig_vals, "reltol_inacc" => 5e-5, "nitref" => 9, "maxit" => 100, - "verbose" => 3); silent = true) + "verbose" => 3); silent_solver = true) abs_p = problem.optval diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index 5830d23fae..ea418cf837 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -11,6 +11,7 @@ end # Use other necessary libraries using Random: seed! +using LinearAlgebra: norm # Use functions and additional symbols that are not exported using Trixi: Trixi, PairedExplicitRK3_butcher_tableau_objective_function, @muladd @@ -42,17 +43,13 @@ function Trixi.solve_a_unknown!(a_unknown, num_stages, monomial_coeffs, c_s2, c; end # Set the seed for reproducibility of the initial guess of a_unknown - seed!(5555) + #seed!(5555) while !is_sol_valid - # Initialize initial guess # The nonlinear system may have multiple valid solutions. # For the sake of reproducibility, we use a seeded random initial guess - x0 = 0.1 .* rand(num_stages) - # For explicit methods, a_{1,1} = 0 and a_{2,1} = c_2 (Butcher's condition) - x0[1] = 0 - x0[2] = c[2] + x0 = 0.1 .* rand(num_stages-2) sol = nlsolve(objective_function, x0, method = :trust_region, ftol = 4e-16, # Enforce objective up to machine precision @@ -62,8 +59,8 @@ function Trixi.solve_a_unknown!(a_unknown, num_stages, monomial_coeffs, c_s2, c; # Check if the values a[i, i-1] >= 0.0 (which stem from the nonlinear solver) # and subsequently c[i] - a[i, i-1] >= 0.0 since all coefficients are non-negative - is_sol_valid = all(x -> !isnan(x) && x >= 0, a_unknown[3:end]) && - all(x -> !isnan(x) && x >= 0, c[3:end] .- a_unknown[3:end]) + is_sol_valid = all(x -> !isnan(x) && x >= 0, a_unknown) && + all(x -> !isnan(x) && x >= 0, c[3:end] .- a_unknown) if verbose && !is_sol_valid println("Solution invalid. Restart the process of solving non-linear system of equations again.") diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index f38a77f82a..e623d4f7d0 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -31,7 +31,8 @@ function PairedExplicitRK3_butcher_tableau_objective_function(a_unknown, num_sta num_stage_evals, monomial_coeffs, cS2) c_ts = compute_c_coeffs_SSP33(num_stages, cS2) # ts = timestep - + # For explicit methods, a_{1,1} = 0 and a_{2,1} = c_2 (Butcher's condition) + a_coeff = [0.0, c_ts[2], a_unknown...] # Equality Constraint array that ensures that the stability polynomial computed from # the to-be-constructed Butcher-Tableau matches the monomial coefficients of the # optimized stability polynomial. @@ -40,11 +41,11 @@ function PairedExplicitRK3_butcher_tableau_objective_function(a_unknown, num_sta c_eq = zeros(num_stage_evals - 2) # Add equality constraint that cS2 is equal to 1 # Lower-order terms: Two summands present for i in 1:(num_stage_evals - 4) - term1 = a_unknown[num_stage_evals - 1] - term2 = a_unknown[num_stage_evals] + term1 = a_coeff[num_stage_evals - 1] + term2 = a_coeff[num_stage_evals] for j in 1:i - term1 *= a_unknown[num_stage_evals - 1 - j] - term2 *= a_unknown[num_stage_evals - j] + term1 *= a_coeff[num_stage_evals - 1 - j] + term2 *= a_coeff[num_stage_evals - j] end term1 *= c_ts[num_stages - 2 - i] * 1 / 6 # 1/ 6 = b_{S-1} term2 *= c_ts[num_stages - 1 - i] * 2 / 3 # 2 / 3 = b_S @@ -54,16 +55,16 @@ function PairedExplicitRK3_butcher_tableau_objective_function(a_unknown, num_sta # Highest coefficient: Only one term present i = num_stage_evals - 3 - term2 = a_unknown[num_stage_evals] + term2 = a_coeff[num_stage_evals] for j in 1:i - term2 *= a_unknown[num_stage_evals - j] + term2 *= a_coeff[num_stage_evals - j] end term2 *= c_ts[num_stages - 1 - i] * 2 / 3 # 2 / 3 = b_S c_eq[i] = monomial_coeffs[i] - term2 # Third-order consistency condition (Cf. eq. (27) from https://doi.org/10.1016/j.jcp.2022.111470 - c_eq[num_stage_evals - 2] = 1 - 4 * a_unknown[num_stage_evals] - - a_unknown[num_stage_evals - 1] + c_eq[num_stage_evals - 2] = 1 - 4 * a_coeff[num_stage_evals] - + a_coeff[num_stage_evals - 1] return c_eq end @@ -77,10 +78,12 @@ function compute_PairedExplicitRK3_butcher_tableau(num_stages, tspan, c = compute_c_coeffs_SSP33(num_stages, cS2) # Initialize the array of our solution - a_unknown = zeros(num_stages) + a_unknown = zeros(num_stages-2) # Special case of e = 3 if num_stages == 3 + #TODO: with this new defining of what we are solving from nlsolve, this array shouldn't be called a_unknown anymore + # or maybe it should be called a_unknown but only with one member a_unknown = [0, c[2], 0.25] dt_opt = 42.0 # TODO! This is a placeholder value else @@ -108,9 +111,9 @@ function compute_PairedExplicitRK3_butcher_tableau(num_stages, tspan, # Fill A-matrix in P-ERK style a_matrix = zeros(num_stages - 2, 2) a_matrix[:, 1] = c[3:end] - a_matrix[:, 1] -= a_unknown[3:end] - a_matrix[:, 2] = a_unknown[3:end] - + a_matrix[:, 1] -= a_unknown + a_matrix[:, 2] = a_unknown + return a_matrix, c end From 516e95f779a0215bbffee37e31e038a71aef2633 Mon Sep 17 00:00:00 2001 From: Warisa Date: Mon, 24 Jun 2024 14:50:50 +0200 Subject: [PATCH 043/120] fmt --- ext/TrixiNLsolveExt.jl | 2 +- .../paired_explicit_runge_kutta/methods_PERK3.jl | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index ea418cf837..c552f9b584 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -49,7 +49,7 @@ function Trixi.solve_a_unknown!(a_unknown, num_stages, monomial_coeffs, c_s2, c; # Initialize initial guess # The nonlinear system may have multiple valid solutions. # For the sake of reproducibility, we use a seeded random initial guess - x0 = 0.1 .* rand(num_stages-2) + x0 = 0.1 .* rand(num_stages - 2) sol = nlsolve(objective_function, x0, method = :trust_region, ftol = 4e-16, # Enforce objective up to machine precision diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index e623d4f7d0..7fcc6a93d9 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -78,7 +78,7 @@ function compute_PairedExplicitRK3_butcher_tableau(num_stages, tspan, c = compute_c_coeffs_SSP33(num_stages, cS2) # Initialize the array of our solution - a_unknown = zeros(num_stages-2) + a_unknown = zeros(num_stages - 2) # Special case of e = 3 if num_stages == 3 @@ -113,7 +113,7 @@ function compute_PairedExplicitRK3_butcher_tableau(num_stages, tspan, a_matrix[:, 1] = c[3:end] a_matrix[:, 1] -= a_unknown a_matrix[:, 2] = a_unknown - + return a_matrix, c end @@ -210,10 +210,10 @@ end function PairedExplicitRK3(num_stages, tspan, eig_vals::Vector{ComplexF64}; verbose = false, cS2 = 1) a_matrix, c = compute_PairedExplicitRK3_butcher_tableau(num_stages, - tspan, - eig_vals; - verbose, cS2) - return PairedExplicitRK3(num_stages, a_matrix, c,) + tspan, + eig_vals; + verbose, cS2) + return PairedExplicitRK3(num_stages, a_matrix, c) end # This struct is needed to fake https://github.com/SciML/OrdinaryDiffEq.jl/blob/0c2048a502101647ac35faabd80da8a5645beac7/src/integrators/type.jl#L77 From fdba17d4edc6d8e435bb617d6fe4dd789554d7da Mon Sep 17 00:00:00 2001 From: Warisa Date: Mon, 24 Jun 2024 19:54:37 +0200 Subject: [PATCH 044/120] minor comment fix --- ext/TrixiNLsolveExt.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index c552f9b584..b677f2920a 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -58,7 +58,7 @@ function Trixi.solve_a_unknown!(a_unknown, num_stages, monomial_coeffs, c_s2, c; a_unknown = sol.zero # Check if the values a[i, i-1] >= 0.0 (which stem from the nonlinear solver) - # and subsequently c[i] - a[i, i-1] >= 0.0 since all coefficients are non-negative + # and also c[i] - a[i, i-1] >= 0.0 since all coefficients are non-negative is_sol_valid = all(x -> !isnan(x) && x >= 0, a_unknown) && all(x -> !isnan(x) && x >= 0, c[3:end] .- a_unknown) From b78f39a00c1f4d58b3117536ef04c6648a0f1337 Mon Sep 17 00:00:00 2001 From: Warisa Date: Mon, 24 Jun 2024 21:20:42 +0200 Subject: [PATCH 045/120] delete some stuff left from random --- ext/TrixiNLsolveExt.jl | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index b677f2920a..e1a8c9b72c 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -10,7 +10,6 @@ else end # Use other necessary libraries -using Random: seed! using LinearAlgebra: norm # Use functions and additional symbols that are not exported @@ -42,9 +41,6 @@ function Trixi.solve_a_unknown!(a_unknown, num_stages, monomial_coeffs, c_s2, c; c_s2) end - # Set the seed for reproducibility of the initial guess of a_unknown - #seed!(5555) - while !is_sol_valid # Initialize initial guess # The nonlinear system may have multiple valid solutions. From 000f117a9d33447a342eeeb9c001222433904e00 Mon Sep 17 00:00:00 2001 From: Warisa Roongaraya <81345089+warisa-r@users.noreply.github.com> Date: Tue, 25 Jun 2024 10:48:02 +0200 Subject: [PATCH 046/120] Update src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl Co-authored-by: Daniel Doehring --- .../paired_explicit_runge_kutta/methods_PERK3.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index 7fcc6a93d9..2bab82f9da 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -182,7 +182,7 @@ Multirate Time-Integration based on Dynamic ODE Partitioning through Adaptively [Arxiv: 10.48550/arXiv.2403.05144](https://doi.org/10.48550/arXiv.2403.05144) """ mutable struct PairedExplicitRK3 <: AbstractPairedExplicitRKSingle - const num_stages::Int + const num_stages::Int # S a_matrix::Matrix{Float64} c::Vector{Float64} From 3289fafeeb0773ab7748fe1373f35dbe5d21b7fb Mon Sep 17 00:00:00 2001 From: Warisa Date: Tue, 25 Jun 2024 14:41:44 +0200 Subject: [PATCH 047/120] minor adjustments --- ext/TrixiNLsolveExt.jl | 4 +--- .../paired_explicit_runge_kutta/methods_PERK3.jl | 12 +++++------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index e1a8c9b72c..583ddf6c42 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -42,9 +42,7 @@ function Trixi.solve_a_unknown!(a_unknown, num_stages, monomial_coeffs, c_s2, c; end while !is_sol_valid - # Initialize initial guess - # The nonlinear system may have multiple valid solutions. - # For the sake of reproducibility, we use a seeded random initial guess + # Initialize an initial guess x0 = 0.1 .* rand(num_stages - 2) sol = nlsolve(objective_function, x0, method = :trust_region, diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index 2bab82f9da..2799cea512 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -8,7 +8,7 @@ using DelimitedFiles: readdlm #! format: noindent # Initialize Butcher array abscissae c for PairedExplicitRK3 based on SSPRK33 base method -function compute_c_coeffs_SSP33(num_stages, cS2) +function compute_c_coeffs(num_stages, cS2) c = zeros(num_stages) # Last timesteps as for SSPRK33, see motivation in @@ -30,7 +30,7 @@ end function PairedExplicitRK3_butcher_tableau_objective_function(a_unknown, num_stages, num_stage_evals, monomial_coeffs, cS2) - c_ts = compute_c_coeffs_SSP33(num_stages, cS2) # ts = timestep + c_ts = compute_c_coeffs(num_stages, cS2) # ts = timestep # For explicit methods, a_{1,1} = 0 and a_{2,1} = c_2 (Butcher's condition) a_coeff = [0.0, c_ts[2], a_unknown...] # Equality Constraint array that ensures that the stability polynomial computed from @@ -75,16 +75,14 @@ function compute_PairedExplicitRK3_butcher_tableau(num_stages, tspan, eig_vals::Vector{ComplexF64}; verbose = false, cS2) # Initialize array of c - c = compute_c_coeffs_SSP33(num_stages, cS2) + c = compute_c_coeffs(num_stages, cS2) # Initialize the array of our solution a_unknown = zeros(num_stages - 2) # Special case of e = 3 if num_stages == 3 - #TODO: with this new defining of what we are solving from nlsolve, this array shouldn't be called a_unknown anymore - # or maybe it should be called a_unknown but only with one member - a_unknown = [0, c[2], 0.25] + a_unknown = [0.25] dt_opt = 42.0 # TODO! This is a placeholder value else # Calculate coefficients of the stability polynomial in monomial form @@ -124,7 +122,7 @@ function compute_PairedExplicitRK3_butcher_tableau(num_stages, cS2) # Initialize array of c - c = compute_c_coeffs_SSP33(num_stages, cS2) + c = compute_c_coeffs(num_stages, cS2) # - 2 Since First entry of A is always zero (explicit method) and second is given by c_2 (consistency) a_coeffs_max = num_stages - 2 From d73c377309b05655c088f0f6fa5b42c783e1fa08 Mon Sep 17 00:00:00 2001 From: Warisa Date: Tue, 25 Jun 2024 14:43:01 +0200 Subject: [PATCH 048/120] minor change to the comment --- ext/TrixiNLsolveExt.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index 583ddf6c42..1f27239fd6 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -52,7 +52,7 @@ function Trixi.solve_a_unknown!(a_unknown, num_stages, monomial_coeffs, c_s2, c; a_unknown = sol.zero # Check if the values a[i, i-1] >= 0.0 (which stem from the nonlinear solver) - # and also c[i] - a[i, i-1] >= 0.0 since all coefficients are non-negative + # and also c[i] - a[i, i-1] >= 0.0 since all coefficients should be non-negative is_sol_valid = all(x -> !isnan(x) && x >= 0, a_unknown) && all(x -> !isnan(x) && x >= 0, c[3:end] .- a_unknown) From b22476e8e0ffe1cf4e4c6455f5b38b4c8273536d Mon Sep 17 00:00:00 2001 From: Warisa Date: Tue, 25 Jun 2024 15:10:07 +0200 Subject: [PATCH 049/120] add proper comment and bring seed back --- ext/TrixiNLsolveExt.jl | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index 1f27239fd6..0e0cfba338 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -12,6 +12,8 @@ end # Use other necessary libraries using LinearAlgebra: norm +using Random: seed! + # Use functions and additional symbols that are not exported using Trixi: Trixi, PairedExplicitRK3_butcher_tableau_objective_function, @muladd @@ -41,8 +43,13 @@ function Trixi.solve_a_unknown!(a_unknown, num_stages, monomial_coeffs, c_s2, c; c_s2) end + seed!(5555) + while !is_sol_valid - # Initialize an initial guess + # Due to the nature of the nonlinear solver, different initial guesses can lead to + # small numerical differences in the solution. + # To ensure consistency and reproducibility of results across runs, we use + # a seeded random initial guess. x0 = 0.1 .* rand(num_stages - 2) sol = nlsolve(objective_function, x0, method = :trust_region, From 2ec41faeb62530e10e4d941d37df14d3b0c59af4 Mon Sep 17 00:00:00 2001 From: Warisa Date: Tue, 25 Jun 2024 15:21:01 +0200 Subject: [PATCH 050/120] update test values --- test/test_unit.jl | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/test/test_unit.jl b/test/test_unit.jl index ecc96a8b21..607631d253 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -1705,14 +1705,17 @@ end #TODO: adjust this value according to the result in the test pipeline println(ode_algorithm.a_matrix) # Value in CI differs slightly from what I get locally @test isapprox(ode_algorithm.a_matrix, - [0.27321088155198703 0.01250340416229867 - 0.4060225225166573 0.022548906054771216 - 0.534287756076577 0.03714081535199439 - 0.6549425779583463 0.05934313632736803 - 0.7621601562844809 0.09498270085837623 - 0.8446587253087918 0.1553412746912082 - 0.7719976108598626 0.22800238914013735 - 0.30700059728503437 0.1929994027149656], atol = 1e-13) + [0.19258805209433105 0.007411947905668948 + 0.28723273300165075 0.012767266998349255 + 0.38017685928843065 0.0198231407115694 + 0.4706744386325171 0.029325561367482902 + 0.5575742010881195 0.04242579891188053 + 0.6390910444606461 0.060908955539353826 + 0.7124869884931394 0.08751301150686068 + 0.7736366314117405 0.12636336858825947 + 0.8161317899892583 0.18386821001074174 + 0.7532715707531655 0.2467284292468345 + 0.31168210731170864 0.18831789268829138], atol = 1e-13) end @testset "Sutherlands Law" begin From 03fb32f4576a649e61039d2ce7ce7a42f5a12e1c Mon Sep 17 00:00:00 2001 From: Warisa Date: Tue, 25 Jun 2024 15:35:57 +0200 Subject: [PATCH 051/120] fmt --- .../methods_PERK3.jl | 2 +- test/test_unit.jl | 20 +++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index 2799cea512..4562d0fc8b 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -82,7 +82,7 @@ function compute_PairedExplicitRK3_butcher_tableau(num_stages, tspan, # Special case of e = 3 if num_stages == 3 - a_unknown = [0.25] + a_unknown = [0.25] dt_opt = 42.0 # TODO! This is a placeholder value else # Calculate coefficients of the stability polynomial in monomial form diff --git a/test/test_unit.jl b/test/test_unit.jl index 607631d253..92ed2f2379 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -1706,16 +1706,16 @@ end println(ode_algorithm.a_matrix) # Value in CI differs slightly from what I get locally @test isapprox(ode_algorithm.a_matrix, [0.19258805209433105 0.007411947905668948 - 0.28723273300165075 0.012767266998349255 - 0.38017685928843065 0.0198231407115694 - 0.4706744386325171 0.029325561367482902 - 0.5575742010881195 0.04242579891188053 - 0.6390910444606461 0.060908955539353826 - 0.7124869884931394 0.08751301150686068 - 0.7736366314117405 0.12636336858825947 - 0.8161317899892583 0.18386821001074174 - 0.7532715707531655 0.2467284292468345 - 0.31168210731170864 0.18831789268829138], atol = 1e-13) + 0.28723273300165075 0.012767266998349255 + 0.38017685928843065 0.0198231407115694 + 0.4706744386325171 0.029325561367482902 + 0.5575742010881195 0.04242579891188053 + 0.6390910444606461 0.060908955539353826 + 0.7124869884931394 0.08751301150686068 + 0.7736366314117405 0.12636336858825947 + 0.8161317899892583 0.18386821001074174 + 0.7532715707531655 0.2467284292468345 + 0.31168210731170864 0.18831789268829138], atol = 1e-13) end @testset "Sutherlands Law" begin From cda3c840fbcfb30d2a6a3dafa404a012c2f1e595 Mon Sep 17 00:00:00 2001 From: Warisa Date: Tue, 25 Jun 2024 18:01:18 +0200 Subject: [PATCH 052/120] change the keyword according to the error in the test pipeline and edit some values to match the test pipeline --- ext/TrixiConvexECOSExt.jl | 2 +- test/test_structured_1d.jl | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/TrixiConvexECOSExt.jl b/ext/TrixiConvexECOSExt.jl index fac127699c..948dbf103c 100644 --- a/ext/TrixiConvexECOSExt.jl +++ b/ext/TrixiConvexECOSExt.jl @@ -136,7 +136,7 @@ function Trixi.bisect_stability_polynomial(consistency_order, num_eig_vals, "reltol_inacc" => 5e-5, "nitref" => 9, "maxit" => 100, - "verbose" => 3); silent_solver = true) + "verbose" => 3); silent = true) abs_p = problem.optval diff --git a/test/test_structured_1d.jl b/test/test_structured_1d.jl index 279febbd5b..283ab40ed7 100644 --- a/test/test_structured_1d.jl +++ b/test/test_structured_1d.jl @@ -60,8 +60,8 @@ end @trixi_testset "elixir_burgers_perk3.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_burgers_perk3.jl"), - l2=[8.120426320528704e-8], - linf=[4.906376875890572e-7], + l2=[8.12194103e-08], + linf=[4.90725569e-07], atol=1.0e-6) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) From 84f6a6d78f30a1a0866a1ea143a16c836b8c0288 Mon Sep 17 00:00:00 2001 From: Warisa Date: Tue, 25 Jun 2024 18:10:35 +0200 Subject: [PATCH 053/120] remove unused import --- ext/TrixiNLsolveExt.jl | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index 0e0cfba338..ba15bb913c 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -9,16 +9,11 @@ else using ..NLsolve: nlsolve end -# Use other necessary libraries -using LinearAlgebra: norm - using Random: seed! -# Use functions and additional symbols that are not exported -using Trixi: Trixi, PairedExplicitRK3_butcher_tableau_objective_function, @muladd - -# Use functions that are to be extended -using Trixi: Trixi, solve_a_unknown! +# Use functions that are to be extended and additional symbols that are not exported +using Trixi: Trixi, solve_a_unknown!, PairedExplicitRK3_butcher_tableau_objective_function, + @muladd # By default, Julia/LLVM does not use fused multiply-add operations (FMAs). # Since these FMAs can increase the performance of many numerical algorithms, From 144bfa1d712f6586cf62d677da1f23f0572c9173 Mon Sep 17 00:00:00 2001 From: Warisa Date: Tue, 25 Jun 2024 18:14:49 +0200 Subject: [PATCH 054/120] fix test values in misc --- test/test_unit.jl | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/test/test_unit.jl b/test/test_unit.jl index 92ed2f2379..1c61fa6ce7 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -1705,17 +1705,17 @@ end #TODO: adjust this value according to the result in the test pipeline println(ode_algorithm.a_matrix) # Value in CI differs slightly from what I get locally @test isapprox(ode_algorithm.a_matrix, - [0.19258805209433105 0.007411947905668948 - 0.28723273300165075 0.012767266998349255 - 0.38017685928843065 0.0198231407115694 - 0.4706744386325171 0.029325561367482902 - 0.5575742010881195 0.04242579891188053 - 0.6390910444606461 0.060908955539353826 - 0.7124869884931394 0.08751301150686068 - 0.7736366314117405 0.12636336858825947 - 0.8161317899892583 0.18386821001074174 - 0.7532715707531655 0.2467284292468345 - 0.31168210731170864 0.18831789268829138], atol = 1e-13) + [0.19258815209175084 0.007411847908249183 + 0.287232921421498 0.012767078578501994 + 0.38017716660879974 0.019822833391200292 + 0.4706748922245802 0.029325107775419784 + 0.5575748091858802 0.042425190814119815 + 0.6390917624593604 0.06090823754063958 + 0.712487669254592 0.08751233074540807 + 0.7736370088751211 0.1263629911248789 + 0.816131548721476 0.18386845127852405 + 0.7532704353232954 0.24672956467670462 + 0.3116823911691762 0.18831760883082385], atol = 1e-13) end @testset "Sutherlands Law" begin From 6e53ad216c16deb123b38b42ae6f478d8f2bb62b Mon Sep 17 00:00:00 2001 From: Warisa Date: Wed, 26 Jun 2024 18:33:32 +0200 Subject: [PATCH 055/120] add max iteration --- ext/TrixiNLsolveExt.jl | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index ba15bb913c..79084e30a0 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -27,7 +27,7 @@ using Trixi: Trixi, solve_a_unknown!, PairedExplicitRK3_butcher_tableau_objectiv # For details, see Proposition 3.2, Equation (3.3) from # Hairer, Wanner: Solving Ordinary Differential Equations 2 function Trixi.solve_a_unknown!(a_unknown, num_stages, monomial_coeffs, c_s2, c; - verbose) + verbose, max_iter = 100000) is_sol_valid = false # Define the objective_function @@ -40,7 +40,7 @@ function Trixi.solve_a_unknown!(a_unknown, num_stages, monomial_coeffs, c_s2, c; seed!(5555) - while !is_sol_valid + for _ in 1:max_iter # Due to the nature of the nonlinear solver, different initial guesses can lead to # small numerical differences in the solution. # To ensure consistency and reproducibility of results across runs, we use @@ -58,12 +58,16 @@ function Trixi.solve_a_unknown!(a_unknown, num_stages, monomial_coeffs, c_s2, c; is_sol_valid = all(x -> !isnan(x) && x >= 0, a_unknown) && all(x -> !isnan(x) && x >= 0, c[3:end] .- a_unknown) - if verbose && !is_sol_valid - println("Solution invalid. Restart the process of solving non-linear system of equations again.") + if is_sol_valid + return a_unknown + else + if verbose + println("Solution invalid. Restart the process of solving non-linear system of equations again.") + end end end - return a_unknown + error("Maximum number of iterations ($max_iter) reached. Cannot find valid sets of coefficients.") end end # @muladd From a34d412fa48ce96941996f29eda1a661c41f0ac0 Mon Sep 17 00:00:00 2001 From: Warisa Roongaraya <81345089+warisa-r@users.noreply.github.com> Date: Wed, 26 Jun 2024 19:04:11 +0200 Subject: [PATCH 056/120] Update ext/TrixiNLsolveExt.jl Co-authored-by: Daniel Doehring --- ext/TrixiNLsolveExt.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index 79084e30a0..b5707f8f6a 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -9,6 +9,8 @@ else using ..NLsolve: nlsolve end +# We use a random initialization of the nonlinear solver. +# To make the tests reproducible, we need to seed the RNG using Random: seed! # Use functions that are to be extended and additional symbols that are not exported From a65cdb8d48327b3eedec3f1573d1b2ffa2ae196c Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Fri, 5 Jul 2024 12:04:45 +0200 Subject: [PATCH 057/120] Apply suggestions from code review --- examples/structured_1d_dgsem/elixir_burgers_perk3.jl | 2 +- .../paired_explicit_runge_kutta/methods_PERK3.jl | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/examples/structured_1d_dgsem/elixir_burgers_perk3.jl b/examples/structured_1d_dgsem/elixir_burgers_perk3.jl index d93d3d0fbb..ec2c8169ca 100644 --- a/examples/structured_1d_dgsem/elixir_burgers_perk3.jl +++ b/examples/structured_1d_dgsem/elixir_burgers_perk3.jl @@ -4,7 +4,7 @@ using OrdinaryDiffEq using Trixi ############################################################################### -# semidiscretization of the (inviscid) Burgers' equation +# semidiscretization of the (inviscid) Burgers equation equations = InviscidBurgersEquation1D() diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index 4562d0fc8b..7693b7f9de 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -13,7 +13,6 @@ function compute_c_coeffs(num_stages, cS2) # Last timesteps as for SSPRK33, see motivation in # https://doi.org/10.48550/arXiv.2403.05144 - c[num_stages - 1] = 1 c[num_stages] = 0.5 @@ -33,7 +32,7 @@ function PairedExplicitRK3_butcher_tableau_objective_function(a_unknown, num_sta c_ts = compute_c_coeffs(num_stages, cS2) # ts = timestep # For explicit methods, a_{1,1} = 0 and a_{2,1} = c_2 (Butcher's condition) a_coeff = [0.0, c_ts[2], a_unknown...] - # Equality Constraint array that ensures that the stability polynomial computed from + # Equality constraint array that ensures that the stability polynomial computed from # the to-be-constructed Butcher-Tableau matches the monomial coefficients of the # optimized stability polynomial. # For details, see Chapter4.3, Proposition 3.2, Equation (3.3) from @@ -167,8 +166,8 @@ end - `cS2` (`Float64`, optional): Value of c in the Butcher tableau at c_{s-2}, when s is the number of stages, default is 1.0. -The following structures and methods provide a implementation of -the third-order paired explicit Runge-Kutta method +The following structures and methods provide an implementation of +the third-order paired explicit Runge-Kutta (P-ERK) method optimized for a certain simulation setup (PDE, IC & BC, Riemann Solver, DG Solver). The original paper is - Nasab, Vermeire (2022) From 6d2fc6db2f6211c45fd65822c5a3613c2f17027c Mon Sep 17 00:00:00 2001 From: Warisa Date: Fri, 5 Jul 2024 15:17:21 +0200 Subject: [PATCH 058/120] remove the allocating part of is_sol_valid --- ext/TrixiNLsolveExt.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index b5707f8f6a..571eb1377e 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -58,7 +58,8 @@ function Trixi.solve_a_unknown!(a_unknown, num_stages, monomial_coeffs, c_s2, c; # Check if the values a[i, i-1] >= 0.0 (which stem from the nonlinear solver) # and also c[i] - a[i, i-1] >= 0.0 since all coefficients should be non-negative is_sol_valid = all(x -> !isnan(x) && x >= 0, a_unknown) && - all(x -> !isnan(x) && x >= 0, c[3:end] .- a_unknown) + all(!isnan(c[i] - a_unknown[i - 2]) && + c[i] - a_unknown[i - 2] >= 0 for i in eachindex(c) if i > 2) if is_sol_valid return a_unknown From e95fe976f35c78704b01f9ae3855df6d2aa20996 Mon Sep 17 00:00:00 2001 From: Warisa Date: Fri, 5 Jul 2024 15:38:38 +0200 Subject: [PATCH 059/120] removing dt_opt and update test values --- .../paired_explicit_runge_kutta/methods_PERK3.jl | 11 +++++------ test/test_structured_1d.jl | 4 ++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index 7693b7f9de..d42713e409 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -82,7 +82,6 @@ function compute_PairedExplicitRK3_butcher_tableau(num_stages, tspan, # Special case of e = 3 if num_stages == 3 a_unknown = [0.25] - dt_opt = 42.0 # TODO! This is a placeholder value else # Calculate coefficients of the stability polynomial in monomial form consistency_order = 3 @@ -91,11 +90,11 @@ function compute_PairedExplicitRK3_butcher_tableau(num_stages, tspan, num_eig_vals, eig_vals = filter_eig_vals(eig_vals; verbose) - monomial_coeffs, dt_opt = bisect_stability_polynomial(consistency_order, - num_eig_vals, num_stages, - dtmax, - dteps, - eig_vals; verbose) + monomial_coeffs, _ = bisect_stability_polynomial(consistency_order, + num_eig_vals, num_stages, + dtmax, + dteps, + eig_vals; verbose) monomial_coeffs = undo_normalization!(monomial_coeffs, consistency_order, num_stages) diff --git a/test/test_structured_1d.jl b/test/test_structured_1d.jl index 283ab40ed7..53b4c75444 100644 --- a/test/test_structured_1d.jl +++ b/test/test_structured_1d.jl @@ -60,8 +60,8 @@ end @trixi_testset "elixir_burgers_perk3.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_burgers_perk3.jl"), - l2=[8.12194103e-08], - linf=[4.90725569e-07], + l2=[8.120426534092787e-8], + linf=[4.906376900315479e-7], atol=1.0e-6) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) From c61187c7fb744203bb6eb4b736db1b11b579239e Mon Sep 17 00:00:00 2001 From: Warisa Roongaraya <81345089+warisa-r@users.noreply.github.com> Date: Fri, 5 Jul 2024 16:32:20 +0200 Subject: [PATCH 060/120] Update NEWS.md Co-authored-by: Daniel Doehring --- NEWS.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NEWS.md b/NEWS.md index d27ec29ceb..b13f756c1b 100644 --- a/NEWS.md +++ b/NEWS.md @@ -16,8 +16,8 @@ for human readability. method with [Convex.jl](https://github.com/jump-dev/Convex.jl) and [ECOS.jl](https://github.com/jump-dev/ECOS.jl) ([#1908]) - Add subcell limiting support for `StructuredMesh` ([#1946]). - New time integrator `PairedExplicitRK3`, implementing the third-order paired explicit Runge-Kutta - method with [Convex.jl](https://github.com/jump-dev/Convex.jl), [ECOS.jl](https://github.com/jump-dev/ECOS.jl) - , and [NLsolve.jl](https://github.com/JuliaNLSolvers/NLsolve.jl) ([TBD]) + method with [Convex.jl](https://github.com/jump-dev/Convex.jl), [ECOS.jl](https://github.com/jump-dev/ECOS.jl), + and [NLsolve.jl](https://github.com/JuliaNLSolvers/NLsolve.jl) ([TBD]) ## Changes when updating to v0.7 from v0.6.x From 2fc30857d254ef66a020135dcbb9117f84c597c7 Mon Sep 17 00:00:00 2001 From: Warisa Date: Fri, 5 Jul 2024 16:48:32 +0200 Subject: [PATCH 061/120] update cfl number for the simulation --- examples/structured_1d_dgsem/elixir_burgers_perk3.jl | 2 +- test/test_structured_1d.jl | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/structured_1d_dgsem/elixir_burgers_perk3.jl b/examples/structured_1d_dgsem/elixir_burgers_perk3.jl index ec2c8169ca..59f49921e2 100644 --- a/examples/structured_1d_dgsem/elixir_burgers_perk3.jl +++ b/examples/structured_1d_dgsem/elixir_burgers_perk3.jl @@ -35,7 +35,7 @@ analysis_callback = AnalysisCallback(semi, interval = analysis_interval) alive_callback = AliveCallback(analysis_interval = analysis_interval) -stepsize_callback = StepsizeCallback() +stepsize_callback = StepsizeCallback(cfl = 3.713) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, diff --git a/test/test_structured_1d.jl b/test/test_structured_1d.jl index 53b4c75444..883f1b12fa 100644 --- a/test/test_structured_1d.jl +++ b/test/test_structured_1d.jl @@ -60,8 +60,8 @@ end @trixi_testset "elixir_burgers_perk3.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_burgers_perk3.jl"), - l2=[8.120426534092787e-8], - linf=[4.906376900315479e-7], + l2=[6.4744366559817754e-6], + linf=[4.357450084224723e-5], atol=1.0e-6) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) From bd55f1d478c3e9c1dc917c94c0e23e42f6a727a5 Mon Sep 17 00:00:00 2001 From: Warisa Roongaraya <81345089+warisa-r@users.noreply.github.com> Date: Fri, 5 Jul 2024 16:53:35 +0200 Subject: [PATCH 062/120] Update examples/structured_1d_dgsem/elixir_burgers_perk3.jl Co-authored-by: Daniel Doehring --- examples/structured_1d_dgsem/elixir_burgers_perk3.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/structured_1d_dgsem/elixir_burgers_perk3.jl b/examples/structured_1d_dgsem/elixir_burgers_perk3.jl index 59f49921e2..6f74bb1d98 100644 --- a/examples/structured_1d_dgsem/elixir_burgers_perk3.jl +++ b/examples/structured_1d_dgsem/elixir_burgers_perk3.jl @@ -35,7 +35,7 @@ analysis_callback = AnalysisCallback(semi, interval = analysis_interval) alive_callback = AliveCallback(analysis_interval = analysis_interval) -stepsize_callback = StepsizeCallback(cfl = 3.713) +stepsize_callback = StepsizeCallback(cfl = 3.7) callbacks = CallbackSet(summary_callback, analysis_callback, alive_callback, From 8d08b87d63a3bf2d55553e960d3601c5af85d236 Mon Sep 17 00:00:00 2001 From: Warisa Roongaraya <81345089+warisa-r@users.noreply.github.com> Date: Fri, 5 Jul 2024 16:54:27 +0200 Subject: [PATCH 063/120] Update src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl Co-authored-by: Daniel Doehring --- .../paired_explicit_runge_kutta/methods_PERK3.jl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index d42713e409..d50f8f1bf0 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -92,8 +92,7 @@ function compute_PairedExplicitRK3_butcher_tableau(num_stages, tspan, monomial_coeffs, _ = bisect_stability_polynomial(consistency_order, num_eig_vals, num_stages, - dtmax, - dteps, + dtmax, dteps, eig_vals; verbose) monomial_coeffs = undo_normalization!(monomial_coeffs, consistency_order, num_stages) From c5c00bceb2991bfc459b357f7da0125e822f770d Mon Sep 17 00:00:00 2001 From: Warisa Roongaraya <81345089+warisa-r@users.noreply.github.com> Date: Fri, 5 Jul 2024 16:54:34 +0200 Subject: [PATCH 064/120] Update src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl Co-authored-by: Daniel Doehring --- .../paired_explicit_runge_kutta/methods_PERK3.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index d50f8f1bf0..a04d5ce199 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -46,7 +46,7 @@ function PairedExplicitRK3_butcher_tableau_objective_function(a_unknown, num_sta term1 *= a_coeff[num_stage_evals - 1 - j] term2 *= a_coeff[num_stage_evals - j] end - term1 *= c_ts[num_stages - 2 - i] * 1 / 6 # 1/ 6 = b_{S-1} + term1 *= c_ts[num_stages - 2 - i] * 1 / 6 # 1 / 6 = b_{S-1} term2 *= c_ts[num_stages - 1 - i] * 2 / 3 # 2 / 3 = b_S c_eq[i] = monomial_coeffs[i] - (term1 + term2) From 6fa86477c29a252171270c17c859f13351ebe087 Mon Sep 17 00:00:00 2001 From: Warisa Date: Fri, 5 Jul 2024 17:02:39 +0200 Subject: [PATCH 065/120] change from a_stages_stages.txt to a_stages.txt --- .../paired_explicit_runge_kutta/methods_PERK3.jl | 5 ++--- test/test_unit.jl | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index d42713e409..111a2902d2 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -129,8 +129,7 @@ function compute_PairedExplicitRK3_butcher_tableau(num_stages, a_matrix[:, 1] = c[3:end] path_a_coeffs = joinpath(base_path_a_coeffs, - "a_" * string(num_stages) * "_" * string(num_stages) * - ".txt") + "a_" * string(num_stages) * ".txt") @assert isfile(path_a_coeffs) "Couldn't find file" a_coeffs = readdlm(path_a_coeffs, Float64) @@ -156,7 +155,7 @@ end - `num_stages` (`Int`): Number of stages in the PERK method. - `base_path_a_coeffs` (`AbstractString`): Path to a file containing some coefficients in the A-matrix in the Butcher tableau of the Runge Kutta method. - The matrix should be stored in a text file at `joinpath(base_path_a_coeffs, "a_$(num_stages)_.$(num_stages)txt")` and separated by line breaks. + The matrix should be stored in a text file at `joinpath(base_path_a_coeffs, "a_$(num_stages).txt")` and separated by line breaks. - `tspan`: Time span of the simulation. - `semi` (`AbstractSemidiscretization`): Semidiscretization setup. - `eig_vals` (`Vector{ComplexF64}`): Eigenvalues of the Jacobian of the right-hand side (rhs) of the ODEProblem after the diff --git a/test/test_unit.jl b/test/test_unit.jl index 1c61fa6ce7..65b2bde4f5 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -1681,7 +1681,7 @@ end @testset "PERK Single p3 Constructors" begin path_coeff_file = mktempdir() Trixi.download("https://gist.githubusercontent.com/warisa-r/0796db36abcd5abe735ac7eebf41b973/raw/32889062fd5dcf7f450748f4f5f0797c8155a18d/a_8_8.txt", - joinpath(path_coeff_file, "a_8_8.txt")) + joinpath(path_coeff_file, "a_8.txt")) ode_algorithm = Trixi.PairedExplicitRK3(8, path_coeff_file) From 88c92e210771fa9b7b9331558f4c08b3426800bb Mon Sep 17 00:00:00 2001 From: Warisa Date: Mon, 8 Jul 2024 17:49:04 +0200 Subject: [PATCH 066/120] fixed step size should work with save solution now --- .../paired_explicit_runge_kutta/methods_PERK3.jl | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index 1c36f5e370..ca549e744a 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -221,8 +221,9 @@ mutable struct PairedExplicitRK3Integrator{RealT <: Real, uType, Params, Sol, F, du::uType u_tmp::uType t::RealT + tdir::RealT dt::RealT # current time step - dtcache::RealT # ignored + dtcache::RealT # manually set time step iter::Int # current number of time steps (iteration) p::Params # will be the semidiscretization from Trixi sol::Sol # faked @@ -230,6 +231,8 @@ mutable struct PairedExplicitRK3Integrator{RealT <: Real, uType, Params, Sol, F, alg::Alg # This is our own class written above; Abbreviation for ALGorithm opts::PairedExplicitRKOptions finalstep::Bool # added for convenience + dtchangeable::Bool + force_stepfail::Bool # PairedExplicitRK stages: k1::uType k_higher::uType @@ -246,15 +249,16 @@ function init(ode::ODEProblem, alg::PairedExplicitRK3; k_higher = zero(u0) t0 = first(ode.tspan) + tdir = sign(ode.tspan[end] - ode.tspan[1]) iter = 0 - integrator = PairedExplicitRK3Integrator(u0, du, u_tmp, t0, dt, zero(dt), iter, + integrator = PairedExplicitRK3Integrator(u0, du, u_tmp, t0, tdir, dt, dt, iter, ode.p, (prob = ode,), ode.f, alg, PairedExplicitRKOptions(callback, ode.tspan; kwargs...), - false, + false, true, false, k1, k_higher) # initialize callbacks @@ -306,6 +310,8 @@ function step!(integrator::PairedExplicitRK3Integrator) error("time step size `dt` is NaN") end + modify_dt_for_tstops!(integrator) + # if the next iteration would push the simulation beyond the end time, set dt accordingly if integrator.t + integrator.dt > t_end || isapprox(integrator.t + integrator.dt, t_end) From 71f2841a1abb0c2078f74b32380e2015fafa23e1 Mon Sep 17 00:00:00 2001 From: Warisa Roongaraya <81345089+warisa-r@users.noreply.github.com> Date: Tue, 9 Jul 2024 19:34:35 +0200 Subject: [PATCH 067/120] Update examples/structured_1d_dgsem/elixir_burgers_perk3.jl Co-authored-by: Daniel Doehring --- examples/structured_1d_dgsem/elixir_burgers_perk3.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/structured_1d_dgsem/elixir_burgers_perk3.jl b/examples/structured_1d_dgsem/elixir_burgers_perk3.jl index 6f74bb1d98..cc3ee92d53 100644 --- a/examples/structured_1d_dgsem/elixir_burgers_perk3.jl +++ b/examples/structured_1d_dgsem/elixir_burgers_perk3.jl @@ -44,6 +44,7 @@ callbacks = CallbackSet(summary_callback, ############################################################################### # run the simulation +# Optimize 8-stage, third order P-ERK scheme for this semidiscretization ode_algorithm = Trixi.PairedExplicitRK3(8, tspan, semi) sol = Trixi.solve(ode, ode_algorithm, From 739b54b430599a5738b6b62b51a9a712d6555fba Mon Sep 17 00:00:00 2001 From: Warisa Date: Tue, 9 Jul 2024 19:39:08 +0200 Subject: [PATCH 068/120] add save solution to the example --- examples/structured_1d_dgsem/elixir_burgers_perk3.jl | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/examples/structured_1d_dgsem/elixir_burgers_perk3.jl b/examples/structured_1d_dgsem/elixir_burgers_perk3.jl index cc3ee92d53..832968acab 100644 --- a/examples/structured_1d_dgsem/elixir_burgers_perk3.jl +++ b/examples/structured_1d_dgsem/elixir_burgers_perk3.jl @@ -35,10 +35,15 @@ analysis_callback = AnalysisCallback(semi, interval = analysis_interval) alive_callback = AliveCallback(analysis_interval = analysis_interval) +save_solution = SaveSolutionCallback(dt = 0.1, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) + stepsize_callback = StepsizeCallback(cfl = 3.7) callbacks = CallbackSet(summary_callback, - analysis_callback, alive_callback, + analysis_callback, alive_callback, save_solution, stepsize_callback) ############################################################################### From 995107b2db330522da75a0af516244665de45f2a Mon Sep 17 00:00:00 2001 From: Warisa Date: Tue, 9 Jul 2024 19:56:58 +0200 Subject: [PATCH 069/120] update test to be compatible with save_solution --- test/test_structured_1d.jl | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/test/test_structured_1d.jl b/test/test_structured_1d.jl index 883f1b12fa..034604f778 100644 --- a/test/test_structured_1d.jl +++ b/test/test_structured_1d.jl @@ -60,8 +60,8 @@ end @trixi_testset "elixir_burgers_perk3.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_burgers_perk3.jl"), - l2=[6.4744366559817754e-6], - linf=[4.357450084224723e-5], + l2=[4.12066275835687e-6], + linf=[2.538190787615413e-5], atol=1.0e-6) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) @@ -73,6 +73,25 @@ end end end +# Testing the third-order paired explicit Runge-Kutta (PERK) method without stepsize callback +@trixi_testset "elixir_burgers_perk3.jl(fixed time step)" begin + @test_trixi_include( dt=2.0e-3, + tspan=(0.0, 2.0), + save_solution=SaveSolutionCallback(dt = 0.1 + 1.0e-8), + callbacks=CallbackSet(summary_callback, save_solution, + analysis_callback, alive_callback), + l2=[5.725141913990915e-7], + linf=[3.4298598041715422e-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.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_euler_sedov.jl"), l2=[3.67478226e-01, 3.49491179e-01, 8.08910759e-01], From 640c7f642ccd859d9c801f6d85d17f37906b58ae Mon Sep 17 00:00:00 2001 From: Warisa Date: Tue, 9 Jul 2024 20:02:04 +0200 Subject: [PATCH 070/120] move comment regarding seed upwards --- ext/TrixiNLsolveExt.jl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index 571eb1377e..74f3e442da 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -40,13 +40,14 @@ function Trixi.solve_a_unknown!(a_unknown, num_stages, monomial_coeffs, c_s2, c; c_s2) end + # To ensure consistency and reproducibility of results across runs, we use + # a seeded random initial guess. seed!(5555) for _ in 1:max_iter # Due to the nature of the nonlinear solver, different initial guesses can lead to # small numerical differences in the solution. - # To ensure consistency and reproducibility of results across runs, we use - # a seeded random initial guess. + x0 = 0.1 .* rand(num_stages - 2) sol = nlsolve(objective_function, x0, method = :trust_region, From e92330557c3dc0898dbef5ed398cdb90e65a868e Mon Sep 17 00:00:00 2001 From: Warisa Date: Tue, 9 Jul 2024 20:10:43 +0200 Subject: [PATCH 071/120] Revert "Correct the logic of step!" only the part that meddles with methods_PERK2 --- .../methods_PERK2.jl | 4 +- .../methods_PERK3.jl | 109 +++++++++--------- 2 files changed, 57 insertions(+), 56 deletions(-) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK2.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK2.jl index 1d9680153e..b3b917dc18 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK2.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK2.jl @@ -273,10 +273,10 @@ function solve(ode::ODEProblem, alg::PairedExplicitRK2; integrator = init(ode, alg, dt = dt, callback = callback; kwargs...) # Start actual solve - solve!(integrator) + solve_steps!(integrator) end -function solve!(integrator::PairedExplicitRK2Integrator) +function solve_steps!(integrator::PairedExplicitRK2Integrator) @unpack prob = integrator.sol integrator.finalstep = false diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index ca549e744a..cc1acc617b 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -312,62 +312,62 @@ function step!(integrator::PairedExplicitRK3Integrator) modify_dt_for_tstops!(integrator) - # if the next iteration would push the simulation beyond the end time, set dt accordingly - if integrator.t + integrator.dt > t_end || - isapprox(integrator.t + integrator.dt, t_end) - integrator.dt = t_end - integrator.t - terminate!(integrator) - end - - @trixi_timeit timer() "Paired Explicit Runge-Kutta ODE integration step" begin - # k1 - integrator.f(integrator.du, integrator.u, prob.p, integrator.t) - @threaded for i in eachindex(integrator.du) - integrator.k1[i] = integrator.du[i] * integrator.dt + # if the next iteration would push the simulation beyond the end time, set dt accordingly + if integrator.t + integrator.dt > t_end || + isapprox(integrator.t + integrator.dt, t_end) + integrator.dt = t_end - integrator.t + terminate!(integrator) end - # Construct current state - @threaded for i in eachindex(integrator.du) - integrator.u_tmp[i] = integrator.u[i] + alg.c[2] * integrator.k1[i] - end - # k2 - integrator.f(integrator.du, integrator.u_tmp, prob.p, - integrator.t + alg.c[2] * integrator.dt) + @trixi_timeit timer() "Paired Explicit Runge-Kutta ODE integration step" begin + # k1 + integrator.f(integrator.du, integrator.u, prob.p, integrator.t) + @threaded for i in eachindex(integrator.du) + integrator.k1[i] = integrator.du[i] * integrator.dt + end + + # Construct current state + @threaded for i in eachindex(integrator.du) + integrator.u_tmp[i] = integrator.u[i] + alg.c[2] * integrator.k1[i] + end + # k2 + integrator.f(integrator.du, integrator.u_tmp, prob.p, + integrator.t + alg.c[2] * integrator.dt) @threaded for i in eachindex(integrator.du) integrator.k_higher[i] = integrator.du[i] * integrator.dt end - # Higher stages - for stage in 3:(alg.num_stages - 1) - # Construct current state - @threaded for i in eachindex(integrator.du) - integrator.u_tmp[i] = integrator.u[i] + - alg.a_matrix[stage - 2, 1] * - integrator.k1[i] + - alg.a_matrix[stage - 2, 2] * - integrator.k_higher[i] - end + # Higher stages + for stage in 3:(alg.num_stages - 1) + # Construct current state + @threaded for i in eachindex(integrator.du) + integrator.u_tmp[i] = integrator.u[i] + + alg.a_matrix[stage - 2, 1] * + integrator.k1[i] + + alg.a_matrix[stage - 2, 2] * + integrator.k_higher[i] + end - integrator.f(integrator.du, integrator.u_tmp, prob.p, - integrator.t + alg.c[stage] * integrator.dt) + integrator.f(integrator.du, integrator.u_tmp, prob.p, + integrator.t + alg.c[stage] * integrator.dt) @threaded for i in eachindex(integrator.du) integrator.k_higher[i] = integrator.du[i] * integrator.dt end end - # Last stage - @threaded for i in eachindex(integrator.du) - integrator.u_tmp[i] = integrator.u[i] + - alg.a_matrix[alg.num_stages - 2, 1] * - integrator.k1[i] + - alg.a_matrix[alg.num_stages - 2, 2] * - integrator.k_higher[i] - end + # Last stage + @threaded for i in eachindex(integrator.du) + integrator.u_tmp[i] = integrator.u[i] + + alg.a_matrix[alg.num_stages - 2, 1] * + integrator.k1[i] + + alg.a_matrix[alg.num_stages - 2, 2] * + integrator.k_higher[i] + end - integrator.f(integrator.du, integrator.u_tmp, prob.p, - integrator.t + alg.c[alg.num_stages] * integrator.dt) + integrator.f(integrator.du, integrator.u_tmp, prob.p, + integrator.t + alg.c[alg.num_stages] * integrator.dt) @threaded for i in eachindex(integrator.u) # "Own" PairedExplicitRK based on SSPRK33. @@ -378,23 +378,24 @@ function step!(integrator::PairedExplicitRK3Integrator) end end # PairedExplicitRK step timer - integrator.iter += 1 - integrator.t += integrator.dt + integrator.iter += 1 + integrator.t += integrator.dt - # handle callbacks - if callbacks isa CallbackSet - for cb in callbacks.discrete_callbacks - if cb.condition(integrator.u, integrator.t, integrator) - cb.affect!(integrator) + # handle callbacks + if callbacks isa CallbackSet + for cb in callbacks.discrete_callbacks + if cb.condition(integrator.u, integrator.t, integrator) + cb.affect!(integrator) + end end end - end - # respect maximum number of iterations - if integrator.iter >= integrator.opts.maxiters && !integrator.finalstep - @warn "Interrupted. Larger maxiters is needed." - terminate!(integrator) - end + # respect maximum number of iterations + if integrator.iter >= integrator.opts.maxiters && !integrator.finalstep + @warn "Interrupted. Larger maxiters is needed." + terminate!(integrator) + end + end # "main loop" timer end # used for AMR (Adaptive Mesh Refinement) From f3f4e254085378271a4d47fcd2d9883ea7cbc396 Mon Sep 17 00:00:00 2001 From: Warisa Date: Tue, 9 Jul 2024 20:12:48 +0200 Subject: [PATCH 072/120] correct methods_PERK3 --- .../methods_PERK3.jl | 109 +++++++++--------- 1 file changed, 54 insertions(+), 55 deletions(-) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index cc1acc617b..ca549e744a 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -312,62 +312,62 @@ function step!(integrator::PairedExplicitRK3Integrator) modify_dt_for_tstops!(integrator) - # if the next iteration would push the simulation beyond the end time, set dt accordingly - if integrator.t + integrator.dt > t_end || - isapprox(integrator.t + integrator.dt, t_end) - integrator.dt = t_end - integrator.t - terminate!(integrator) - end + # if the next iteration would push the simulation beyond the end time, set dt accordingly + if integrator.t + integrator.dt > t_end || + isapprox(integrator.t + integrator.dt, t_end) + integrator.dt = t_end - integrator.t + terminate!(integrator) + end - @trixi_timeit timer() "Paired Explicit Runge-Kutta ODE integration step" begin - # k1 - integrator.f(integrator.du, integrator.u, prob.p, integrator.t) - @threaded for i in eachindex(integrator.du) - integrator.k1[i] = integrator.du[i] * integrator.dt - end + @trixi_timeit timer() "Paired Explicit Runge-Kutta ODE integration step" begin + # k1 + integrator.f(integrator.du, integrator.u, prob.p, integrator.t) + @threaded for i in eachindex(integrator.du) + integrator.k1[i] = integrator.du[i] * integrator.dt + end - # Construct current state - @threaded for i in eachindex(integrator.du) - integrator.u_tmp[i] = integrator.u[i] + alg.c[2] * integrator.k1[i] - end - # k2 - integrator.f(integrator.du, integrator.u_tmp, prob.p, - integrator.t + alg.c[2] * integrator.dt) + # Construct current state + @threaded for i in eachindex(integrator.du) + integrator.u_tmp[i] = integrator.u[i] + alg.c[2] * integrator.k1[i] + end + # k2 + integrator.f(integrator.du, integrator.u_tmp, prob.p, + integrator.t + alg.c[2] * integrator.dt) @threaded for i in eachindex(integrator.du) integrator.k_higher[i] = integrator.du[i] * integrator.dt end - # Higher stages - for stage in 3:(alg.num_stages - 1) - # Construct current state - @threaded for i in eachindex(integrator.du) - integrator.u_tmp[i] = integrator.u[i] + - alg.a_matrix[stage - 2, 1] * - integrator.k1[i] + - alg.a_matrix[stage - 2, 2] * - integrator.k_higher[i] - end + # Higher stages + for stage in 3:(alg.num_stages - 1) + # Construct current state + @threaded for i in eachindex(integrator.du) + integrator.u_tmp[i] = integrator.u[i] + + alg.a_matrix[stage - 2, 1] * + integrator.k1[i] + + alg.a_matrix[stage - 2, 2] * + integrator.k_higher[i] + end - integrator.f(integrator.du, integrator.u_tmp, prob.p, - integrator.t + alg.c[stage] * integrator.dt) + integrator.f(integrator.du, integrator.u_tmp, prob.p, + integrator.t + alg.c[stage] * integrator.dt) @threaded for i in eachindex(integrator.du) integrator.k_higher[i] = integrator.du[i] * integrator.dt end end - # Last stage - @threaded for i in eachindex(integrator.du) - integrator.u_tmp[i] = integrator.u[i] + - alg.a_matrix[alg.num_stages - 2, 1] * - integrator.k1[i] + - alg.a_matrix[alg.num_stages - 2, 2] * - integrator.k_higher[i] - end + # Last stage + @threaded for i in eachindex(integrator.du) + integrator.u_tmp[i] = integrator.u[i] + + alg.a_matrix[alg.num_stages - 2, 1] * + integrator.k1[i] + + alg.a_matrix[alg.num_stages - 2, 2] * + integrator.k_higher[i] + end - integrator.f(integrator.du, integrator.u_tmp, prob.p, - integrator.t + alg.c[alg.num_stages] * integrator.dt) + integrator.f(integrator.du, integrator.u_tmp, prob.p, + integrator.t + alg.c[alg.num_stages] * integrator.dt) @threaded for i in eachindex(integrator.u) # "Own" PairedExplicitRK based on SSPRK33. @@ -378,24 +378,23 @@ function step!(integrator::PairedExplicitRK3Integrator) end end # PairedExplicitRK step timer - integrator.iter += 1 - integrator.t += integrator.dt + integrator.iter += 1 + integrator.t += integrator.dt - # handle callbacks - if callbacks isa CallbackSet - for cb in callbacks.discrete_callbacks - if cb.condition(integrator.u, integrator.t, integrator) - cb.affect!(integrator) - end + # handle callbacks + if callbacks isa CallbackSet + for cb in callbacks.discrete_callbacks + if cb.condition(integrator.u, integrator.t, integrator) + cb.affect!(integrator) end end + end - # respect maximum number of iterations - if integrator.iter >= integrator.opts.maxiters && !integrator.finalstep - @warn "Interrupted. Larger maxiters is needed." - terminate!(integrator) - end - end # "main loop" timer + # respect maximum number of iterations + if integrator.iter >= integrator.opts.maxiters && !integrator.finalstep + @warn "Interrupted. Larger maxiters is needed." + terminate!(integrator) + end end # used for AMR (Adaptive Mesh Refinement) From a6addd71a5095dfeeafa4511b5d63f3863bdd99d Mon Sep 17 00:00:00 2001 From: Warisa Date: Tue, 9 Jul 2024 20:16:03 +0200 Subject: [PATCH 073/120] move is_sol_valid closer to the for loop --- ext/TrixiNLsolveExt.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index 74f3e442da..731d31da18 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -30,7 +30,6 @@ using Trixi: Trixi, solve_a_unknown!, PairedExplicitRK3_butcher_tableau_objectiv # Hairer, Wanner: Solving Ordinary Differential Equations 2 function Trixi.solve_a_unknown!(a_unknown, num_stages, monomial_coeffs, c_s2, c; verbose, max_iter = 100000) - is_sol_valid = false # Define the objective_function function objective_function(x) @@ -44,6 +43,8 @@ function Trixi.solve_a_unknown!(a_unknown, num_stages, monomial_coeffs, c_s2, c; # a seeded random initial guess. seed!(5555) + is_sol_valid = false + for _ in 1:max_iter # Due to the nature of the nonlinear solver, different initial guesses can lead to # small numerical differences in the solution. From 87c6cae97e30f898b0cbb8bc46579902a0d6ef05 Mon Sep 17 00:00:00 2001 From: Warisa Date: Tue, 9 Jul 2024 20:17:52 +0200 Subject: [PATCH 074/120] fmt --- ext/TrixiNLsolveExt.jl | 2 +- test/test_structured_1d.jl | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index 731d31da18..27e7a714ca 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -48,7 +48,7 @@ function Trixi.solve_a_unknown!(a_unknown, num_stages, monomial_coeffs, c_s2, c; for _ in 1:max_iter # Due to the nature of the nonlinear solver, different initial guesses can lead to # small numerical differences in the solution. - + x0 = 0.1 .* rand(num_stages - 2) sol = nlsolve(objective_function, x0, method = :trust_region, diff --git a/test/test_structured_1d.jl b/test/test_structured_1d.jl index 034604f778..3f6a3a2e55 100644 --- a/test/test_structured_1d.jl +++ b/test/test_structured_1d.jl @@ -75,13 +75,13 @@ end # Testing the third-order paired explicit Runge-Kutta (PERK) method without stepsize callback @trixi_testset "elixir_burgers_perk3.jl(fixed time step)" begin - @test_trixi_include( dt=2.0e-3, - tspan=(0.0, 2.0), - save_solution=SaveSolutionCallback(dt = 0.1 + 1.0e-8), - callbacks=CallbackSet(summary_callback, save_solution, - analysis_callback, alive_callback), - l2=[5.725141913990915e-7], - linf=[3.4298598041715422e-6]) + @test_trixi_include(dt=2.0e-3, + tspan=(0.0, 2.0), + save_solution=SaveSolutionCallback(dt = 0.1 + 1.0e-8), + callbacks=CallbackSet(summary_callback, save_solution, + analysis_callback, alive_callback), + l2=[5.725141913990915e-7], + linf=[3.4298598041715422e-6]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let From 0d642fb33f4b19a0be360af7279848701eb599e2 Mon Sep 17 00:00:00 2001 From: Warisa Date: Tue, 9 Jul 2024 20:35:11 +0200 Subject: [PATCH 075/120] Revert some random changes in other test unit --- test/test_structured_1d.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_structured_1d.jl b/test/test_structured_1d.jl index 3f6a3a2e55..35d402ed73 100644 --- a/test/test_structured_1d.jl +++ b/test/test_structured_1d.jl @@ -47,7 +47,7 @@ end @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_advection_shockcapturing.jl"), l2=[0.08015029105233593], linf=[0.610709468736576], - atol=1.0e-12) + atol=1.0e-5) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let From d602a959cf420fbd2d4cf573834a300161bec682 Mon Sep 17 00:00:00 2001 From: Warisa Date: Tue, 9 Jul 2024 20:36:18 +0200 Subject: [PATCH 076/120] add tolerance to the test --- test/test_structured_1d.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/test_structured_1d.jl b/test/test_structured_1d.jl index 35d402ed73..6acbc3ccb0 100644 --- a/test/test_structured_1d.jl +++ b/test/test_structured_1d.jl @@ -81,7 +81,8 @@ end callbacks=CallbackSet(summary_callback, save_solution, analysis_callback, alive_callback), l2=[5.725141913990915e-7], - linf=[3.4298598041715422e-6]) + linf=[3.4298598041715422e-6], + atol=1.0e-6) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let From bc358e455f5baf24734374bc9884096a808c9e94 Mon Sep 17 00:00:00 2001 From: Warisa Date: Tue, 9 Jul 2024 20:45:04 +0200 Subject: [PATCH 077/120] modify functions so that they are also compatible with PERK3 --- .../paired_explicit_runge_kutta/methods_PERK2.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK2.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK2.jl index ddcc1b365b..6abf1cbaa9 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK2.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK2.jl @@ -233,11 +233,11 @@ mutable struct PairedExplicitRK2Integrator{RealT <: Real, uType, Params, Sol, F, end """ - add_tstop!(integrator::PairedExplicitRK2Integrator, t) + add_tstop!(integrator::AbstractPairedExplicitRKSingleIntegrator, 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::PairedExplicitRK2Integrator, t) +function add_tstop!(integrator::AbstractPairedExplicitRKSingleIntegrator, 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. @@ -248,8 +248,8 @@ function add_tstop!(integrator::PairedExplicitRK2Integrator, t) push!(integrator.opts.tstops, integrator.tdir * t) end -has_tstop(integrator::PairedExplicitRK2Integrator) = !isempty(integrator.opts.tstops) -first_tstop(integrator::PairedExplicitRK2Integrator) = first(integrator.opts.tstops) +has_tstop(integrator::AbstractPairedExplicitRKSingleIntegrator) = !isempty(integrator.opts.tstops) +first_tstop(integrator::AbstractPairedExplicitRKSingleIntegrator) = first(integrator.opts.tstops) # Forward integrator.stats.naccept to integrator.iter (see GitHub PR#771) function Base.getproperty(integrator::PairedExplicitRK, field::Symbol) From 10d712697dafe26720888ac8de91fc0b5dc9632c Mon Sep 17 00:00:00 2001 From: Warisa Date: Tue, 9 Jul 2024 21:02:06 +0200 Subject: [PATCH 078/120] change function's name to be more descriptive --- ext/TrixiConvexECOSExt.jl | 2 +- ext/TrixiNLsolveExt.jl | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/TrixiConvexECOSExt.jl b/ext/TrixiConvexECOSExt.jl index 8251fe3eed..0a5b4c44c5 100644 --- a/ext/TrixiConvexECOSExt.jl +++ b/ext/TrixiConvexECOSExt.jl @@ -136,7 +136,7 @@ function Trixi.bisect_stability_polynomial(consistency_order, num_eig_vals, "reltol_inacc" => 5e-5, "nitref" => 9, "maxit" => 100, - "verbose" => 3); silent = true) + "verbose" => 3); silent_solver = true) abs_p = problem.optval diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index 27e7a714ca..4b4a5a2dc5 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -14,7 +14,7 @@ end using Random: seed! # Use functions that are to be extended and additional symbols that are not exported -using Trixi: Trixi, solve_a_unknown!, PairedExplicitRK3_butcher_tableau_objective_function, +using Trixi: Trixi, solve_a_butcher_coeffs_unknown!, PairedExplicitRK3_butcher_tableau_objective_function, @muladd # By default, Julia/LLVM does not use fused multiply-add operations (FMAs). @@ -28,7 +28,7 @@ using Trixi: Trixi, solve_a_unknown!, PairedExplicitRK3_butcher_tableau_objectiv # non-linear equations that arise from the relation of the stability polynomial to the Butcher tableau. # For details, see Proposition 3.2, Equation (3.3) from # Hairer, Wanner: Solving Ordinary Differential Equations 2 -function Trixi.solve_a_unknown!(a_unknown, num_stages, monomial_coeffs, c_s2, c; +function Trixi.solve_a_butcher_coeffs_unknown!(a_unknown, num_stages, monomial_coeffs, c_s2, c; verbose, max_iter = 100000) # Define the objective_function From 75de0888ec61a39e6bf4dde15e4879153d0f28ad Mon Sep 17 00:00:00 2001 From: Warisa Date: Tue, 9 Jul 2024 21:02:49 +0200 Subject: [PATCH 079/120] change function's name to be more descriptive in all files --- .../paired_explicit_runge_kutta/methods_PERK3.jl | 2 +- .../paired_explicit_runge_kutta/paired_explicit_runge_kutta.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index ca549e744a..0cc472ba33 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -100,7 +100,7 @@ function compute_PairedExplicitRK3_butcher_tableau(num_stages, tspan, # Solve the nonlinear system of equations from monomial coefficient and # Butcher array abscissae c to find Butcher matrix A # This function is extended in TrixiNLsolveExt.jl - a_unknown = solve_a_unknown!(a_unknown, num_stages, monomial_coeffs, cS2, c; + a_unknown = solve_a_butcher_coeffs_unknown!(a_unknown, num_stages, monomial_coeffs, cS2, c; verbose) end # Fill A-matrix in P-ERK style diff --git a/src/time_integration/paired_explicit_runge_kutta/paired_explicit_runge_kutta.jl b/src/time_integration/paired_explicit_runge_kutta/paired_explicit_runge_kutta.jl index cc48c3ca45..8f8cacadd7 100644 --- a/src/time_integration/paired_explicit_runge_kutta/paired_explicit_runge_kutta.jl +++ b/src/time_integration/paired_explicit_runge_kutta/paired_explicit_runge_kutta.jl @@ -14,5 +14,5 @@ include("polynomial_optimizer.jl") # Add definitions of functions related to polynomial optimization by NLsolve here # such that hey can be exported from Trixi.jl and extended in the TrixiConvexECOSExt package # extension or by the NLsolve-specific code loaded by Requires.jl -function solve_a_unknown! end +function solve_a_butcher_coeffs_unknown! end end # @muladd From 58fabb79e1f6dada4cf645f975e13d8596ef1071 Mon Sep 17 00:00:00 2001 From: Warisa Date: Tue, 9 Jul 2024 21:03:40 +0200 Subject: [PATCH 080/120] Revert irrelevent change in TrixiConvexECOSExt.jl --- ext/TrixiConvexECOSExt.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/TrixiConvexECOSExt.jl b/ext/TrixiConvexECOSExt.jl index 0a5b4c44c5..8251fe3eed 100644 --- a/ext/TrixiConvexECOSExt.jl +++ b/ext/TrixiConvexECOSExt.jl @@ -136,7 +136,7 @@ function Trixi.bisect_stability_polynomial(consistency_order, num_eig_vals, "reltol_inacc" => 5e-5, "nitref" => 9, "maxit" => 100, - "verbose" => 3); silent_solver = true) + "verbose" => 3); silent = true) abs_p = problem.optval From 40dd61029713968bb00cba3a3f9ae66df4a783bd Mon Sep 17 00:00:00 2001 From: Warisa Date: Tue, 9 Jul 2024 21:05:52 +0200 Subject: [PATCH 081/120] add PR number to NEWS.md --- NEWS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index b089b71650..fdc234ab88 100644 --- a/NEWS.md +++ b/NEWS.md @@ -31,7 +31,7 @@ for human readability. - Add subcell limiting support for `StructuredMesh` ([#1946]). - New time integrator `PairedExplicitRK3`, implementing the third-order paired explicit Runge-Kutta method with [Convex.jl](https://github.com/jump-dev/Convex.jl), [ECOS.jl](https://github.com/jump-dev/ECOS.jl), - and [NLsolve.jl](https://github.com/JuliaNLSolvers/NLsolve.jl) ([TBD]) + and [NLsolve.jl](https://github.com/JuliaNLSolvers/NLsolve.jl) ([#2008]) ## Changes when updating to v0.7 from v0.6.x From c104ff2efaf585b80904cf4baff99fa7287961c9 Mon Sep 17 00:00:00 2001 From: Warisa Date: Tue, 9 Jul 2024 21:09:20 +0200 Subject: [PATCH 082/120] fmt --- ext/TrixiNLsolveExt.jl | 8 +++++--- .../paired_explicit_runge_kutta/methods_PERK3.jl | 5 +++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index 4b4a5a2dc5..0766f8ed5e 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -14,7 +14,8 @@ end using Random: seed! # Use functions that are to be extended and additional symbols that are not exported -using Trixi: Trixi, solve_a_butcher_coeffs_unknown!, PairedExplicitRK3_butcher_tableau_objective_function, +using Trixi: Trixi, solve_a_butcher_coeffs_unknown!, + PairedExplicitRK3_butcher_tableau_objective_function, @muladd # By default, Julia/LLVM does not use fused multiply-add operations (FMAs). @@ -28,8 +29,9 @@ using Trixi: Trixi, solve_a_butcher_coeffs_unknown!, PairedExplicitRK3_butcher_t # non-linear equations that arise from the relation of the stability polynomial to the Butcher tableau. # For details, see Proposition 3.2, Equation (3.3) from # Hairer, Wanner: Solving Ordinary Differential Equations 2 -function Trixi.solve_a_butcher_coeffs_unknown!(a_unknown, num_stages, monomial_coeffs, c_s2, c; - verbose, max_iter = 100000) +function Trixi.solve_a_butcher_coeffs_unknown!(a_unknown, num_stages, monomial_coeffs, + c_s2, c; + verbose, max_iter = 100000) # Define the objective_function function objective_function(x) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index 0cc472ba33..4e1a3b54ef 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -100,8 +100,9 @@ function compute_PairedExplicitRK3_butcher_tableau(num_stages, tspan, # Solve the nonlinear system of equations from monomial coefficient and # Butcher array abscissae c to find Butcher matrix A # This function is extended in TrixiNLsolveExt.jl - a_unknown = solve_a_butcher_coeffs_unknown!(a_unknown, num_stages, monomial_coeffs, cS2, c; - verbose) + a_unknown = solve_a_butcher_coeffs_unknown!(a_unknown, num_stages, + monomial_coeffs, cS2, c; + verbose) end # Fill A-matrix in P-ERK style a_matrix = zeros(num_stages - 2, 2) From 76487b5d7f4a3153559a8f4cc4625a2cd9592624 Mon Sep 17 00:00:00 2001 From: Warisa Date: Tue, 9 Jul 2024 21:31:05 +0200 Subject: [PATCH 083/120] change from using Random to StableRNGs --- Project.toml | 4 ++-- ext/TrixiNLsolveExt.jl | 6 +++--- test/Project.toml | 2 ++ 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Project.toml b/Project.toml index 1d39733570..d931fc8b82 100644 --- a/Project.toml +++ b/Project.toml @@ -28,13 +28,13 @@ Polyester = "f517fe37-dbe3-4b94-8317-1923a5111588" PrecompileTools = "aea7be01-6a6a-4083-8856-8a6e6704d82a" Preferences = "21216c6a-2e73-6563-6e65-726566657250" Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" -Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" Reexport = "189a3867-3050-52da-a836-e630ba90ab69" Requires = "ae029012-a4dd-5104-9daa-d747884805df" SciMLBase = "0bca4576-84f4-4d90-8ffe-ffa030f20462" SimpleUnPack = "ce78b400-467f-4804-87d8-8f486da07d0a" SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" +StableRNGs = "860ef19b-820b-49d6-a774-d7a799459cd3" StartUpDG = "472ebc20-7c99-4d4b-9470-8fde4e9faa0f" Static = "aedffcd0-7271-4cad-89d0-dc628f76c6d3" StaticArrayInterface = "0d7ed370-da01-4f52-bd93-41d350b8b718" @@ -90,13 +90,13 @@ Polyester = "0.7.10" PrecompileTools = "1.1" Preferences = "1.3" Printf = "1" -Random = "1" RecipesBase = "1.1" Reexport = "1.0" Requires = "1.1" SciMLBase = "1.90, 2" SimpleUnPack = "1.1" SparseArrays = "1" +StableRNGs = "1.0.2" StartUpDG = "0.17.7" Static = "0.8.7" StaticArrayInterface = "1.4" diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index 0766f8ed5e..60f0094115 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -11,7 +11,7 @@ end # We use a random initialization of the nonlinear solver. # To make the tests reproducible, we need to seed the RNG -using Random: seed! +using StableRNGs: StableRNG, rand # Use functions that are to be extended and additional symbols that are not exported using Trixi: Trixi, solve_a_butcher_coeffs_unknown!, @@ -43,7 +43,7 @@ function Trixi.solve_a_butcher_coeffs_unknown!(a_unknown, num_stages, monomial_c # To ensure consistency and reproducibility of results across runs, we use # a seeded random initial guess. - seed!(5555) + rng = StableRNG(555) is_sol_valid = false @@ -51,7 +51,7 @@ function Trixi.solve_a_butcher_coeffs_unknown!(a_unknown, num_stages, monomial_c # Due to the nature of the nonlinear solver, different initial guesses can lead to # small numerical differences in the solution. - x0 = 0.1 .* rand(num_stages - 2) + x0 = 0.1 .* rand(rng, num_stages - 2) sol = nlsolve(objective_function, x0, method = :trust_region, ftol = 4e-16, # Enforce objective up to machine precision diff --git a/test/Project.toml b/test/Project.toml index 84d35d6ca2..f8bcff947c 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -15,6 +15,7 @@ OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed" Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +StableRNGs = "860ef19b-820b-49d6-a774-d7a799459cd3" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [compat] @@ -34,6 +35,7 @@ OrdinaryDiffEq = "6.49.1" Plots = "1.19" Printf = "1" Random = "1" +StableRNGs = "1.0.2" Test = "1" [preferences.OrdinaryDiffEq] From ecbb0ffc95d08daf19eb85762ac1432014d52b69 Mon Sep 17 00:00:00 2001 From: Warisa Date: Tue, 9 Jul 2024 22:40:00 +0200 Subject: [PATCH 084/120] fix the value in unit test --- test/test_unit.jl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/test_unit.jl b/test/test_unit.jl index b71c0130cb..06580e322d 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -1724,16 +1724,16 @@ end #TODO: adjust this value according to the result in the test pipeline println(ode_algorithm.a_matrix) # Value in CI differs slightly from what I get locally @test isapprox(ode_algorithm.a_matrix, - [0.19258815209175084 0.007411847908249183 - 0.287232921421498 0.012767078578501994 - 0.38017716660879974 0.019822833391200292 - 0.4706748922245802 0.029325107775419784 - 0.5575748091858802 0.042425190814119815 - 0.6390917624593604 0.06090823754063958 + [0.19156094079581354 0.008439059204186486 + 0.2872329213106948 0.01276707868930521 + 0.3801771666087999 0.019822833391200098 + 0.4706748922245802 0.02932510777541978 + 0.5575748091858802 0.04242519081411982 + 0.6390917624593604 0.06090823754063957 0.712487669254592 0.08751233074540807 0.7736370088751211 0.1263629911248789 - 0.816131548721476 0.18386845127852405 - 0.7532704353232954 0.24672956467670462 + 0.8161315487214759 0.1838684512785241 + 0.7532704353232954 0.24672956467670457 0.3116823911691762 0.18831760883082385], atol = 1e-13) end From bcadd5a5087bd3924891787f68779a52afe99279 Mon Sep 17 00:00:00 2001 From: Warisa Date: Tue, 9 Jul 2024 22:40:40 +0200 Subject: [PATCH 085/120] remove prints --- test/test_unit.jl | 4 ---- 1 file changed, 4 deletions(-) diff --git a/test/test_unit.jl b/test/test_unit.jl index 06580e322d..07e8cc836d 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -1704,8 +1704,6 @@ end ode_algorithm = Trixi.PairedExplicitRK3(8, path_coeff_file) - #TODO: adjust this value according to the result in the test pipeline - println(ode_algorithm.a_matrix) # Value in CI differs slightly from what I get locally @test isapprox(ode_algorithm.a_matrix, [0.3355167784195604 0.06448322158043965 0.4965349205803965 0.10346507941960345 @@ -1721,8 +1719,6 @@ end tspan = (0.0, 1.0) ode_algorithm = Trixi.PairedExplicitRK3(13, tspan, vec(eig_vals)) - #TODO: adjust this value according to the result in the test pipeline - println(ode_algorithm.a_matrix) # Value in CI differs slightly from what I get locally @test isapprox(ode_algorithm.a_matrix, [0.19156094079581354 0.008439059204186486 0.2872329213106948 0.01276707868930521 From 47e52d0985c35359981035cf3ac1e41b39825d11 Mon Sep 17 00:00:00 2001 From: Warisa Date: Wed, 10 Jul 2024 11:57:13 +0200 Subject: [PATCH 086/120] minor comment correction --- ext/TrixiNLsolveExt.jl | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index 60f0094115..4f0ad2a3fd 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -1,4 +1,4 @@ -# Package extension for adding Convex-based features to Trixi.jl +# Package extension for adding NLsolve-based features to Trixi.jl module TrixiNLsolveExt # Required for coefficient optimization in P-ERK scheme integrators @@ -14,9 +14,8 @@ end using StableRNGs: StableRNG, rand # Use functions that are to be extended and additional symbols that are not exported -using Trixi: Trixi, solve_a_butcher_coeffs_unknown!, - PairedExplicitRK3_butcher_tableau_objective_function, - @muladd +using Trixi: Trixi, PairedExplicitRK3_butcher_tableau_objective_function, + solve_a_butcher_coeffs_unknown!, @muladd # By default, Julia/LLVM does not use fused multiply-add operations (FMAs). # Since these FMAs can increase the performance of many numerical algorithms, From 98264575195ecabacb926c8750e0f01fc30a5ea2 Mon Sep 17 00:00:00 2001 From: Warisa Date: Wed, 10 Jul 2024 12:04:15 +0200 Subject: [PATCH 087/120] attempt to fix the error at fixed time step --- test/test_structured_1d.jl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/test_structured_1d.jl b/test/test_structured_1d.jl index 6acbc3ccb0..35d402ed73 100644 --- a/test/test_structured_1d.jl +++ b/test/test_structured_1d.jl @@ -81,8 +81,7 @@ end callbacks=CallbackSet(summary_callback, save_solution, analysis_callback, alive_callback), l2=[5.725141913990915e-7], - linf=[3.4298598041715422e-6], - atol=1.0e-6) + linf=[3.4298598041715422e-6]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let From d66b241bcdacb83b814d3549ba1ea061adc41e27 Mon Sep 17 00:00:00 2001 From: Warisa Date: Wed, 10 Jul 2024 20:19:59 +0200 Subject: [PATCH 088/120] add the missing clause to test set --- test/test_structured_1d.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/test_structured_1d.jl b/test/test_structured_1d.jl index 35d402ed73..5ad71f7b5b 100644 --- a/test/test_structured_1d.jl +++ b/test/test_structured_1d.jl @@ -75,7 +75,8 @@ end # Testing the third-order paired explicit Runge-Kutta (PERK) method without stepsize callback @trixi_testset "elixir_burgers_perk3.jl(fixed time step)" begin - @test_trixi_include(dt=2.0e-3, + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_burgers_perk3.jl"), + dt=2.0e-3, tspan=(0.0, 2.0), save_solution=SaveSolutionCallback(dt = 0.1 + 1.0e-8), callbacks=CallbackSet(summary_callback, save_solution, From d405551c28ffe0ebc1ef9ca6eddfcef2d7a4736f Mon Sep 17 00:00:00 2001 From: Warisa Date: Wed, 10 Jul 2024 20:30:49 +0200 Subject: [PATCH 089/120] adjust allocation values in test of perk3 --- test/test_structured_1d.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_structured_1d.jl b/test/test_structured_1d.jl index 5ad71f7b5b..8745116e3c 100644 --- a/test/test_structured_1d.jl +++ b/test/test_structured_1d.jl @@ -69,7 +69,7 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 8000 end end @@ -89,7 +89,7 @@ end t = sol.t[end] u_ode = sol.u[end] du_ode = similar(u_ode) - @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 1000 + @test (@allocated Trixi.rhs!(du_ode, u_ode, semi, t)) < 8000 end end From f07066859f754f62e46a70b41df0c2cb28102d4e Mon Sep 17 00:00:00 2001 From: Warisa Date: Wed, 10 Jul 2024 21:15:15 +0200 Subject: [PATCH 090/120] update test value --- test/test_structured_1d.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_structured_1d.jl b/test/test_structured_1d.jl index 8745116e3c..ff682f3ea5 100644 --- a/test/test_structured_1d.jl +++ b/test/test_structured_1d.jl @@ -81,8 +81,8 @@ end save_solution=SaveSolutionCallback(dt = 0.1 + 1.0e-8), callbacks=CallbackSet(summary_callback, save_solution, analysis_callback, alive_callback), - l2=[5.725141913990915e-7], - linf=[3.4298598041715422e-6]) + l2=[5.726144786001842e-7], + linf=[3.430730019182704e-6]) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities) let From 5746b5f8c9edc0d2b23bf2b436f06aeb07d43842 Mon Sep 17 00:00:00 2001 From: Warisa Date: Thu, 11 Jul 2024 19:37:17 +0200 Subject: [PATCH 091/120] move objective function to the extension --- ext/TrixiNLsolveExt.jl | 58 ++++++++++++++++--- .../methods_PERK3.jl | 44 -------------- 2 files changed, 51 insertions(+), 51 deletions(-) diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index 4f0ad2a3fd..c64e0ceed8 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -1,7 +1,8 @@ # Package extension for adding NLsolve-based features to Trixi.jl module TrixiNLsolveExt -# Required for coefficient optimization in P-ERK scheme integrators +# Required for finding coefficients in Butcher tableau in the third order of +# P-ERK scheme integrators if isdefined(Base, :get_extension) using NLsolve: nlsolve else @@ -14,8 +15,7 @@ end using StableRNGs: StableRNG, rand # Use functions that are to be extended and additional symbols that are not exported -using Trixi: Trixi, PairedExplicitRK3_butcher_tableau_objective_function, - solve_a_butcher_coeffs_unknown!, @muladd +using Trixi: Trixi, solve_a_butcher_coeffs_unknown!, compute_c_coeffs, @muladd # By default, Julia/LLVM does not use fused multiply-add operations (FMAs). # Since these FMAs can increase the performance of many numerical algorithms, @@ -24,6 +24,50 @@ using Trixi: Trixi, PairedExplicitRK3_butcher_tableau_objective_function, @muladd begin #! format: noindent +# Compute residuals for nonlinear equations to match a stability polynomial with given coefficients, +# in order to find A-matrix in the Butcher-Tableau +function PairedExplicitRK3_butcher_tableau_objective_function(a_unknown, num_stages, + num_stage_evals, + monomial_coeffs, cS2) + c_ts = Trixi.compute_c_coeffs(num_stages, cS2) # ts = timestep + # For explicit methods, a_{1,1} = 0 and a_{2,1} = c_2 (Butcher's condition) + a_coeff = [0.0, c_ts[2], a_unknown...] + # Equality constraint array that ensures that the stability polynomial computed from + # the to-be-constructed Butcher-Tableau matches the monomial coefficients of the + # optimized stability polynomial. + # For details, see Chapter4.3, Proposition 3.2, Equation (3.3) from + # Hairer, Wanner: Solving Ordinary Differential Equations 2 + c_eq = zeros(num_stage_evals - 2) # Add equality constraint that cS2 is equal to 1 + # Lower-order terms: Two summands present + for i in 1:(num_stage_evals - 4) + term1 = a_coeff[num_stage_evals - 1] + term2 = a_coeff[num_stage_evals] + for j in 1:i + term1 *= a_coeff[num_stage_evals - 1 - j] + term2 *= a_coeff[num_stage_evals - j] + end + term1 *= c_ts[num_stages - 2 - i] * 1 / 6 # 1 / 6 = b_{S-1} + term2 *= c_ts[num_stages - 1 - i] * 2 / 3 # 2 / 3 = b_S + + c_eq[i] = monomial_coeffs[i] - (term1 + term2) + end + + # Highest coefficient: Only one term present + i = num_stage_evals - 3 + term2 = a_coeff[num_stage_evals] + for j in 1:i + term2 *= a_coeff[num_stage_evals - j] + end + term2 *= c_ts[num_stages - 1 - i] * 2 / 3 # 2 / 3 = b_S + + c_eq[i] = monomial_coeffs[i] - term2 + # Third-order consistency condition (Cf. eq. (27) from https://doi.org/10.1016/j.jcp.2022.111470 + c_eq[num_stage_evals - 2] = 1 - 4 * a_coeff[num_stage_evals] - + a_coeff[num_stage_evals - 1] + + return c_eq +end + # Find the values of the a_{i, i-1} in the Butcher tableau matrix A by solving a system of # non-linear equations that arise from the relation of the stability polynomial to the Butcher tableau. # For details, see Proposition 3.2, Equation (3.3) from @@ -34,10 +78,10 @@ function Trixi.solve_a_butcher_coeffs_unknown!(a_unknown, num_stages, monomial_c # Define the objective_function function objective_function(x) - return Trixi.PairedExplicitRK3_butcher_tableau_objective_function(x, num_stages, - num_stages, - monomial_coeffs, - c_s2) + return PairedExplicitRK3_butcher_tableau_objective_function(x, num_stages, + num_stages, + monomial_coeffs, + c_s2) end # To ensure consistency and reproducibility of results across runs, we use diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index 4e1a3b54ef..cedcd06a9b 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -24,50 +24,6 @@ function compute_c_coeffs(num_stages, cS2) return c end -# Compute residuals for nonlinear equations to match a stability polynomial with given coefficients, -# in order to find A-matrix in the Butcher-Tableau -function PairedExplicitRK3_butcher_tableau_objective_function(a_unknown, num_stages, - num_stage_evals, - monomial_coeffs, cS2) - c_ts = compute_c_coeffs(num_stages, cS2) # ts = timestep - # For explicit methods, a_{1,1} = 0 and a_{2,1} = c_2 (Butcher's condition) - a_coeff = [0.0, c_ts[2], a_unknown...] - # Equality constraint array that ensures that the stability polynomial computed from - # the to-be-constructed Butcher-Tableau matches the monomial coefficients of the - # optimized stability polynomial. - # For details, see Chapter4.3, Proposition 3.2, Equation (3.3) from - # Hairer, Wanner: Solving Ordinary Differential Equations 2 - c_eq = zeros(num_stage_evals - 2) # Add equality constraint that cS2 is equal to 1 - # Lower-order terms: Two summands present - for i in 1:(num_stage_evals - 4) - term1 = a_coeff[num_stage_evals - 1] - term2 = a_coeff[num_stage_evals] - for j in 1:i - term1 *= a_coeff[num_stage_evals - 1 - j] - term2 *= a_coeff[num_stage_evals - j] - end - term1 *= c_ts[num_stages - 2 - i] * 1 / 6 # 1 / 6 = b_{S-1} - term2 *= c_ts[num_stages - 1 - i] * 2 / 3 # 2 / 3 = b_S - - c_eq[i] = monomial_coeffs[i] - (term1 + term2) - end - - # Highest coefficient: Only one term present - i = num_stage_evals - 3 - term2 = a_coeff[num_stage_evals] - for j in 1:i - term2 *= a_coeff[num_stage_evals - j] - end - term2 *= c_ts[num_stages - 1 - i] * 2 / 3 # 2 / 3 = b_S - - c_eq[i] = monomial_coeffs[i] - term2 - # Third-order consistency condition (Cf. eq. (27) from https://doi.org/10.1016/j.jcp.2022.111470 - c_eq[num_stage_evals - 2] = 1 - 4 * a_coeff[num_stage_evals] - - a_coeff[num_stage_evals - 1] - - return c_eq -end - # Compute the Butcher tableau for a paired explicit Runge-Kutta method order 3 # using a list of eigenvalues function compute_PairedExplicitRK3_butcher_tableau(num_stages, tspan, From b87592ec25559ffdb892050b7f2401dfa1c068eb Mon Sep 17 00:00:00 2001 From: Warisa Date: Fri, 12 Jul 2024 11:53:10 +0200 Subject: [PATCH 092/120] minor fix with compute_c_coeffs --- ext/TrixiNLsolveExt.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index c64e0ceed8..e172074edb 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -29,7 +29,7 @@ using Trixi: Trixi, solve_a_butcher_coeffs_unknown!, compute_c_coeffs, @muladd function PairedExplicitRK3_butcher_tableau_objective_function(a_unknown, num_stages, num_stage_evals, monomial_coeffs, cS2) - c_ts = Trixi.compute_c_coeffs(num_stages, cS2) # ts = timestep + c_ts = compute_c_coeffs(num_stages, cS2) # ts = timestep # For explicit methods, a_{1,1} = 0 and a_{2,1} = c_2 (Butcher's condition) a_coeff = [0.0, c_ts[2], a_unknown...] # Equality constraint array that ensures that the stability polynomial computed from From 24cbde6b84065a0b2fd1d0606e709ee905a86230 Mon Sep 17 00:00:00 2001 From: Warisa Date: Fri, 12 Jul 2024 14:26:21 +0200 Subject: [PATCH 093/120] remove explicit import of solve_a_unknown from line 18 --- ext/TrixiNLsolveExt.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index e172074edb..0241d5e67f 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -15,7 +15,7 @@ end using StableRNGs: StableRNG, rand # Use functions that are to be extended and additional symbols that are not exported -using Trixi: Trixi, solve_a_butcher_coeffs_unknown!, compute_c_coeffs, @muladd +using Trixi: Trixi, compute_c_coeffs, @muladd # By default, Julia/LLVM does not use fused multiply-add operations (FMAs). # Since these FMAs can increase the performance of many numerical algorithms, From a083ac013ac6843cec594ddae4a4c52abf11956e Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Mon, 15 Jul 2024 12:10:52 +0200 Subject: [PATCH 094/120] Apply suggestions from code review --- ext/TrixiNLsolveExt.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index 0241d5e67f..d2c8ac03b5 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -88,6 +88,7 @@ function Trixi.solve_a_butcher_coeffs_unknown!(a_unknown, num_stages, monomial_c # a seeded random initial guess. rng = StableRNG(555) + # Flag for criteria going beyond satisfaction of non-linear equations is_sol_valid = false for _ in 1:max_iter @@ -100,7 +101,7 @@ function Trixi.solve_a_butcher_coeffs_unknown!(a_unknown, num_stages, monomial_c ftol = 4e-16, # Enforce objective up to machine precision iterations = 10^4, xtol = 1e-13) - a_unknown = sol.zero + a_unknown = sol.zero # Retrieve solution (root = zero) # Check if the values a[i, i-1] >= 0.0 (which stem from the nonlinear solver) # and also c[i] - a[i, i-1] >= 0.0 since all coefficients should be non-negative From fe26ef182d98e852baa2db9eb44d2266c0981b8c Mon Sep 17 00:00:00 2001 From: Warisa Date: Mon, 15 Jul 2024 14:39:31 +0200 Subject: [PATCH 095/120] document why additional packages are loaded --- examples/structured_1d_dgsem/elixir_burgers_perk3.jl | 6 ++++++ examples/tree_1d_dgsem/elixir_advection_perk2.jl | 3 +++ 2 files changed, 9 insertions(+) diff --git a/examples/structured_1d_dgsem/elixir_burgers_perk3.jl b/examples/structured_1d_dgsem/elixir_burgers_perk3.jl index 832968acab..4d031db7ae 100644 --- a/examples/structured_1d_dgsem/elixir_burgers_perk3.jl +++ b/examples/structured_1d_dgsem/elixir_burgers_perk3.jl @@ -1,5 +1,11 @@ +# 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 + +# NLsolve is imported to solve the system of nonlinear equations to find a coefficients +# in the Butcher tableau in the third order P-ERK time integrator. using NLsolve + using OrdinaryDiffEq using Trixi diff --git a/examples/tree_1d_dgsem/elixir_advection_perk2.jl b/examples/tree_1d_dgsem/elixir_advection_perk2.jl index 7db461a079..68befbcfe8 100644 --- a/examples/tree_1d_dgsem/elixir_advection_perk2.jl +++ b/examples/tree_1d_dgsem/elixir_advection_perk2.jl @@ -1,5 +1,8 @@ +# 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 + using OrdinaryDiffEq using Trixi From 339eae2c4b9eb5b98cb4cf7bfd50a3f325bd44c7 Mon Sep 17 00:00:00 2001 From: Warisa Date: Tue, 16 Jul 2024 09:29:55 +0200 Subject: [PATCH 096/120] correct docstring --- .../paired_explicit_runge_kutta/methods_PERK3.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index cedcd06a9b..f17fd3f8b9 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -104,7 +104,7 @@ end cS2 = 1.0) PairedExplicitRK3(num_stages, tspan, semi::AbstractSemidiscretization; verbose = false, cS2 = 1.0) - PairedExplicitRK3(num_stages, tspan, semi::AbstractSemidiscretization; + PairedExplicitRK3(num_stages, tspan, eig_vals::Vector{ComplexF64}; verbose = false, cS2 = 1.0) Parameters: @@ -151,7 +151,7 @@ end # Constructor that computes Butcher matrix A coefficients from a semidiscretization function PairedExplicitRK3(num_stages, tspan, semi::AbstractSemidiscretization; - verbose = false, cS2 = 1) + verbose = false, cS2 = 1.0) eig_vals = eigvals(jacobian_ad_forward(semi)) return PairedExplicitRK3(num_stages, tspan, eig_vals; verbose, cS2) @@ -159,7 +159,7 @@ end # Constructor that calculates the coefficients with polynomial optimizer from a list of eigenvalues function PairedExplicitRK3(num_stages, tspan, eig_vals::Vector{ComplexF64}; - verbose = false, cS2 = 1) + verbose = false, cS2 = 1.0) a_matrix, c = compute_PairedExplicitRK3_butcher_tableau(num_stages, tspan, eig_vals; From 1a0bf58ab278247516e40db5391d3c601d8b3084 Mon Sep 17 00:00:00 2001 From: Warisa Date: Tue, 16 Jul 2024 17:06:13 +0200 Subject: [PATCH 097/120] use Float32 --- ext/TrixiNLsolveExt.jl | 10 ++++----- .../methods_PERK3.jl | 22 +++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index d2c8ac03b5..aea077e589 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -31,7 +31,7 @@ function PairedExplicitRK3_butcher_tableau_objective_function(a_unknown, num_sta monomial_coeffs, cS2) c_ts = compute_c_coeffs(num_stages, cS2) # ts = timestep # For explicit methods, a_{1,1} = 0 and a_{2,1} = c_2 (Butcher's condition) - a_coeff = [0.0, c_ts[2], a_unknown...] + a_coeff = [0.0f0, c_ts[2], a_unknown...] # Equality constraint array that ensures that the stability polynomial computed from # the to-be-constructed Butcher-Tableau matches the monomial coefficients of the # optimized stability polynomial. @@ -62,7 +62,7 @@ function PairedExplicitRK3_butcher_tableau_objective_function(a_unknown, num_sta c_eq[i] = monomial_coeffs[i] - term2 # Third-order consistency condition (Cf. eq. (27) from https://doi.org/10.1016/j.jcp.2022.111470 - c_eq[num_stage_evals - 2] = 1 - 4 * a_coeff[num_stage_evals] - + c_eq[num_stage_evals - 2] = 1.0f0 - 4.0f0 * a_coeff[num_stage_evals] - a_coeff[num_stage_evals - 1] return c_eq @@ -95,11 +95,11 @@ function Trixi.solve_a_butcher_coeffs_unknown!(a_unknown, num_stages, monomial_c # Due to the nature of the nonlinear solver, different initial guesses can lead to # small numerical differences in the solution. - x0 = 0.1 .* rand(rng, num_stages - 2) + x0 = 0.1f0 .* rand(rng, num_stages - 2) sol = nlsolve(objective_function, x0, method = :trust_region, - ftol = 4e-16, # Enforce objective up to machine precision - iterations = 10^4, xtol = 1e-13) + ftol = 4.0f-16, # Enforce objective up to machine precision + iterations = 10^4, xtol = 1.0f-13) a_unknown = sol.zero # Retrieve solution (root = zero) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index f17fd3f8b9..89e5c4cfa3 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -13,8 +13,8 @@ function compute_c_coeffs(num_stages, cS2) # Last timesteps as for SSPRK33, see motivation in # https://doi.org/10.48550/arXiv.2403.05144 - c[num_stages - 1] = 1 - c[num_stages] = 0.5 + c[num_stages - 1] = 1.0f0 + c[num_stages] = 0.5f0 # Linear increasing timestep for remainder for i in 2:(num_stages - 2) @@ -37,12 +37,12 @@ function compute_PairedExplicitRK3_butcher_tableau(num_stages, tspan, # Special case of e = 3 if num_stages == 3 - a_unknown = [0.25] + a_unknown = [0.25f0] else # Calculate coefficients of the stability polynomial in monomial form consistency_order = 3 dtmax = tspan[2] - tspan[1] - dteps = 1e-9 + dteps = 1.0f-9 num_eig_vals, eig_vals = filter_eig_vals(eig_vals; verbose) @@ -101,11 +101,11 @@ end @doc raw""" PairedExplicitRK3(num_stages, base_path_a_coeffs::AbstractString; - cS2 = 1.0) + cS2 = 1.0f0) PairedExplicitRK3(num_stages, tspan, semi::AbstractSemidiscretization; - verbose = false, cS2 = 1.0) + verbose = false, cS2 = 1.0f0) PairedExplicitRK3(num_stages, tspan, eig_vals::Vector{ComplexF64}; - verbose = false, cS2 = 1.0) + verbose = false, cS2 = 1.0f0) Parameters: - `num_stages` (`Int`): Number of stages in the PERK method. @@ -118,7 +118,7 @@ end equation has been semidiscretized. - `verbose` (`Bool`, optional): Verbosity flag, default is false. - `cS2` (`Float64`, optional): Value of c in the Butcher tableau at c_{s-2}, when - s is the number of stages, default is 1.0. + s is the number of stages, default is 1.0f0. The following structures and methods provide an implementation of the third-order paired explicit Runge-Kutta (P-ERK) method @@ -141,7 +141,7 @@ end # struct PairedExplicitRK3 # Constructor for previously computed A Coeffs function PairedExplicitRK3(num_stages, base_path_a_coeffs::AbstractString; - cS2 = 1.0) + cS2 = 1.0f0) a_matrix, c = compute_PairedExplicitRK3_butcher_tableau(num_stages, base_path_a_coeffs; cS2) @@ -151,7 +151,7 @@ end # Constructor that computes Butcher matrix A coefficients from a semidiscretization function PairedExplicitRK3(num_stages, tspan, semi::AbstractSemidiscretization; - verbose = false, cS2 = 1.0) + verbose = false, cS2 = 1.0f0) eig_vals = eigvals(jacobian_ad_forward(semi)) return PairedExplicitRK3(num_stages, tspan, eig_vals; verbose, cS2) @@ -159,7 +159,7 @@ end # Constructor that calculates the coefficients with polynomial optimizer from a list of eigenvalues function PairedExplicitRK3(num_stages, tspan, eig_vals::Vector{ComplexF64}; - verbose = false, cS2 = 1.0) + verbose = false, cS2 = 1.0f0) a_matrix, c = compute_PairedExplicitRK3_butcher_tableau(num_stages, tspan, eig_vals; From 6d95ec6af375660104ec470fd6668f22e1662f20 Mon Sep 17 00:00:00 2001 From: Warisa Roongaraya <81345089+warisa-r@users.noreply.github.com> Date: Wed, 17 Jul 2024 08:39:27 +0200 Subject: [PATCH 098/120] Update ext/TrixiNLsolveExt.jl Co-authored-by: Hendrik Ranocha --- ext/TrixiNLsolveExt.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index aea077e589..ac6759f984 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -62,7 +62,7 @@ function PairedExplicitRK3_butcher_tableau_objective_function(a_unknown, num_sta c_eq[i] = monomial_coeffs[i] - term2 # Third-order consistency condition (Cf. eq. (27) from https://doi.org/10.1016/j.jcp.2022.111470 - c_eq[num_stage_evals - 2] = 1.0f0 - 4.0f0 * a_coeff[num_stage_evals] - + c_eq[num_stage_evals - 2] = 1 - 4 * a_coeff[num_stage_evals] - a_coeff[num_stage_evals - 1] return c_eq From 485a2a70082d70c10be49551b09d4e3dfc77abd1 Mon Sep 17 00:00:00 2001 From: Warisa Roongaraya <81345089+warisa-r@users.noreply.github.com> Date: Wed, 17 Jul 2024 08:39:35 +0200 Subject: [PATCH 099/120] Update ext/TrixiNLsolveExt.jl Co-authored-by: Hendrik Ranocha --- ext/TrixiNLsolveExt.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index ac6759f984..2ac419d427 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -95,7 +95,7 @@ function Trixi.solve_a_butcher_coeffs_unknown!(a_unknown, num_stages, monomial_c # Due to the nature of the nonlinear solver, different initial guesses can lead to # small numerical differences in the solution. - x0 = 0.1f0 .* rand(rng, num_stages - 2) + x0 = convert(RealT, 0.1) .* rand(rng, RealT, num_stages - 2) sol = nlsolve(objective_function, x0, method = :trust_region, ftol = 4.0f-16, # Enforce objective up to machine precision From f8731c17be11233810b689dcfaf86ae00984476c Mon Sep 17 00:00:00 2001 From: Warisa Roongaraya <81345089+warisa-r@users.noreply.github.com> Date: Wed, 17 Jul 2024 08:39:42 +0200 Subject: [PATCH 100/120] Update ext/TrixiNLsolveExt.jl Co-authored-by: Hendrik Ranocha --- ext/TrixiNLsolveExt.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index 2ac419d427..e9fc555aeb 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -31,7 +31,7 @@ function PairedExplicitRK3_butcher_tableau_objective_function(a_unknown, num_sta monomial_coeffs, cS2) c_ts = compute_c_coeffs(num_stages, cS2) # ts = timestep # For explicit methods, a_{1,1} = 0 and a_{2,1} = c_2 (Butcher's condition) - a_coeff = [0.0f0, c_ts[2], a_unknown...] + a_coeff = [0, c_ts[2], a_unknown...] # Equality constraint array that ensures that the stability polynomial computed from # the to-be-constructed Butcher-Tableau matches the monomial coefficients of the # optimized stability polynomial. From 3faf2cc1a562b74873e0c2e406b6110b8f1a0219 Mon Sep 17 00:00:00 2001 From: Warisa Date: Wed, 17 Jul 2024 16:06:33 +0200 Subject: [PATCH 101/120] change some Flot32 back to the way they originally were --- ext/TrixiNLsolveExt.jl | 4 ++-- .../paired_explicit_runge_kutta/methods_PERK3.jl | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index e9fc555aeb..7a8df05831 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -98,8 +98,8 @@ function Trixi.solve_a_butcher_coeffs_unknown!(a_unknown, num_stages, monomial_c x0 = convert(RealT, 0.1) .* rand(rng, RealT, num_stages - 2) sol = nlsolve(objective_function, x0, method = :trust_region, - ftol = 4.0f-16, # Enforce objective up to machine precision - iterations = 10^4, xtol = 1.0f-13) + ftol = 4.0e-16, # Enforce objective up to machine precision + iterations = 10^4, xtol = 1.0e-13) a_unknown = sol.zero # Retrieve solution (root = zero) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index 89e5c4cfa3..c93e95819e 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -37,7 +37,7 @@ function compute_PairedExplicitRK3_butcher_tableau(num_stages, tspan, # Special case of e = 3 if num_stages == 3 - a_unknown = [0.25f0] + a_unknown = [0.25] else # Calculate coefficients of the stability polynomial in monomial form consistency_order = 3 From 339f43eefae4818a8afa83ebacb34f297a013fd3 Mon Sep 17 00:00:00 2001 From: Warisa Date: Wed, 17 Jul 2024 20:14:46 +0200 Subject: [PATCH 102/120] add line that get the type that a_unknown should be --- ext/TrixiNLsolveExt.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index 7a8df05831..435e2f87d3 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -84,6 +84,9 @@ function Trixi.solve_a_butcher_coeffs_unknown!(a_unknown, num_stages, monomial_c c_s2) end + # RealT is determined as the type of the first element in monomial_coeffs to ensure type consistency + RealT = typeof(monomial_coeffs[1]) + # To ensure consistency and reproducibility of results across runs, we use # a seeded random initial guess. rng = StableRNG(555) From ad47a2fda0bda1c99738e89e0306819d2c1807b4 Mon Sep 17 00:00:00 2001 From: Warisa Date: Wed, 17 Jul 2024 21:44:10 +0200 Subject: [PATCH 103/120] due to some the change of type, print out some values of a_matrix that changes slighly from the original value (error value in other tests still remain the same) --- test/test_unit.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/test_unit.jl b/test/test_unit.jl index 90341dbc7f..116f32a062 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -1710,6 +1710,7 @@ end ode_algorithm = Trixi.PairedExplicitRK3(8, path_coeff_file) + println(ode_algorithm.a_matrix) @test isapprox(ode_algorithm.a_matrix, [0.3355167784195604 0.06448322158043965 0.4965349205803965 0.10346507941960345 @@ -1725,6 +1726,7 @@ end tspan = (0.0, 1.0) ode_algorithm = Trixi.PairedExplicitRK3(13, tspan, vec(eig_vals)) + println(ode_algorithm.a_matrix) @test isapprox(ode_algorithm.a_matrix, [0.19156094079581354 0.008439059204186486 0.2872329213106948 0.01276707868930521 From 29743017252a6dfb732a3be8a344ed6a24b4d518 Mon Sep 17 00:00:00 2001 From: Warisa Date: Wed, 17 Jul 2024 23:17:41 +0200 Subject: [PATCH 104/120] update test values --- test/test_unit.jl | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/test/test_unit.jl b/test/test_unit.jl index 116f32a062..befad58aa7 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -1710,11 +1710,10 @@ end ode_algorithm = Trixi.PairedExplicitRK3(8, path_coeff_file) - println(ode_algorithm.a_matrix) @test isapprox(ode_algorithm.a_matrix, - [0.3355167784195604 0.06448322158043965 - 0.4965349205803965 0.10346507941960345 - 0.6496890792935297 0.15031092070647037 + [0.33551678438002486 0.06448322158043965 + 0.49653494442225443 0.10346507941960345 + 0.6496890912144586 0.15031092070647037 0.789172498521197 0.21082750147880308 0.7522972036571336 0.2477027963428664 0.31192569908571666 0.18807430091428337], atol = 1e-13) @@ -1726,18 +1725,17 @@ end tspan = (0.0, 1.0) ode_algorithm = Trixi.PairedExplicitRK3(13, tspan, vec(eig_vals)) - println(ode_algorithm.a_matrix) @test isapprox(ode_algorithm.a_matrix, - [0.19156094079581354 0.008439059204186486 - 0.2872329213106948 0.01276707868930521 - 0.3801771666087999 0.019822833391200098 - 0.4706748922245802 0.02932510777541978 - 0.5575748091858802 0.04242519081411982 - 0.6390917624593604 0.06090823754063957 - 0.712487669254592 0.08751233074540807 - 0.7736370088751211 0.1263629911248789 - 0.8161315487214759 0.1838684512785241 - 0.7532704353232954 0.24672956467670457 + [0.19258815508201277 0.00741184789821947 + 0.2872329330253629 0.01276707889556606 + 0.3801771730615694 0.01982283289889509 + 0.4706748926615584 0.02932510733844162 + 0.5575748313419124 0.04242519249994544 + 0.6390917539959684 0.06090823408310269 + 0.7124876783811593 0.08751233353976957 + 0.7736369902636945 0.12636298589444758 + 0.8161315438506253 0.18386845614937472 + 0.7532704353232954 0.24672956467670462 0.3116823911691762 0.18831760883082385], atol = 1e-13) end From 3023dc2c07c46a8d0fb6d003eca0293b660a1927 Mon Sep 17 00:00:00 2001 From: Warisa Roongaraya <81345089+warisa-r@users.noreply.github.com> Date: Sat, 27 Jul 2024 11:13:25 +0200 Subject: [PATCH 105/120] Update src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> --- .../paired_explicit_runge_kutta/methods_PERK3.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index c93e95819e..fcd0762c01 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -108,7 +108,7 @@ end verbose = false, cS2 = 1.0f0) Parameters: - - `num_stages` (`Int`): Number of stages in the PERK method. + - `num_stages` (`Int`): Number of stages in the paired explicit Runge-Kutta (P-ERK) method. - `base_path_a_coeffs` (`AbstractString`): Path to a file containing some coefficients in the A-matrix in the Butcher tableau of the Runge Kutta method. The matrix should be stored in a text file at `joinpath(base_path_a_coeffs, "a_$(num_stages).txt")` and separated by line breaks. From 3071c4824cc0ce0738cb48b2242c8db4211fc0df Mon Sep 17 00:00:00 2001 From: Warisa Roongaraya <81345089+warisa-r@users.noreply.github.com> Date: Sat, 27 Jul 2024 11:16:27 +0200 Subject: [PATCH 106/120] Update src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> --- .../paired_explicit_runge_kutta/methods_PERK3.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index fcd0762c01..6a54959aab 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -170,7 +170,7 @@ end # This struct is needed to fake https://github.com/SciML/OrdinaryDiffEq.jl/blob/0c2048a502101647ac35faabd80da8a5645beac7/src/integrators/type.jl#L77 # This implements the interface components described at # https://diffeq.sciml.ai/v6.8/basics/integrator/#Handing-Integrators-1 -# which are used in Trixi. +# which are used in Trixi.jl. mutable struct PairedExplicitRK3Integrator{RealT <: Real, uType, Params, Sol, F, Alg, PairedExplicitRKOptions} <: AbstractPairedExplicitRKSingleIntegrator From 6454c469f4a17bdc706700dbec3df3e5c97eb831 Mon Sep 17 00:00:00 2001 From: Warisa Roongaraya <81345089+warisa-r@users.noreply.github.com> Date: Sat, 27 Jul 2024 15:17:28 +0200 Subject: [PATCH 107/120] Apply suggestions from code review Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> --- .../paired_explicit_runge_kutta/methods_PERK3.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index 6a54959aab..b06f22f5e7 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -87,7 +87,7 @@ function compute_PairedExplicitRK3_butcher_tableau(num_stages, path_a_coeffs = joinpath(base_path_a_coeffs, "a_" * string(num_stages) * ".txt") - @assert isfile(path_a_coeffs) "Couldn't find file" + @assert isfile(path_a_coeffs) "Couldn't find file $path_a_coeffs" a_coeffs = readdlm(path_a_coeffs, Float64) num_a_coeffs = size(a_coeffs, 1) From f325f991628a253964fe45cd12c598ba9f2face1 Mon Sep 17 00:00:00 2001 From: Warisa Roongaraya <81345089+warisa-r@users.noreply.github.com> Date: Sat, 27 Jul 2024 15:28:55 +0200 Subject: [PATCH 108/120] Update src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> --- .../paired_explicit_runge_kutta/methods_PERK3.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index b06f22f5e7..da582bb595 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -221,7 +221,7 @@ function init(ode::ODEProblem, alg::PairedExplicitRK3; # initialize callbacks if callback isa CallbackSet for cb in callback.continuous_callbacks - error("unsupported") + error("Continuous callbacks are unsupported with paired explicit Runge-Kutta methods.") end for cb in callback.discrete_callbacks cb.initialize(cb, integrator.u, integrator.t, integrator) From 8334c75b5512c01daeb33671a32e43bc16881d77 Mon Sep 17 00:00:00 2001 From: Warisa Date: Sat, 27 Jul 2024 16:00:05 +0200 Subject: [PATCH 109/120] allocate c_eq once per solve_a_unknown is called --- ext/TrixiNLsolveExt.jl | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index 435e2f87d3..745348f151 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -28,7 +28,8 @@ using Trixi: Trixi, compute_c_coeffs, @muladd # in order to find A-matrix in the Butcher-Tableau function PairedExplicitRK3_butcher_tableau_objective_function(a_unknown, num_stages, num_stage_evals, - monomial_coeffs, cS2) + monomial_coeffs, c_eq, + cS2) c_ts = compute_c_coeffs(num_stages, cS2) # ts = timestep # For explicit methods, a_{1,1} = 0 and a_{2,1} = c_2 (Butcher's condition) a_coeff = [0, c_ts[2], a_unknown...] @@ -37,7 +38,7 @@ function PairedExplicitRK3_butcher_tableau_objective_function(a_unknown, num_sta # optimized stability polynomial. # For details, see Chapter4.3, Proposition 3.2, Equation (3.3) from # Hairer, Wanner: Solving Ordinary Differential Equations 2 - c_eq = zeros(num_stage_evals - 2) # Add equality constraint that cS2 is equal to 1 + # Lower-order terms: Two summands present for i in 1:(num_stage_evals - 4) term1 = a_coeff[num_stage_evals - 1] @@ -76,11 +77,17 @@ function Trixi.solve_a_butcher_coeffs_unknown!(a_unknown, num_stages, monomial_c c_s2, c; verbose, max_iter = 100000) + # c_eq is a vector initialized with zeros with length num_stages - 2. + # It is used to store the coefficients of the non-linear equations arise from the relation of + # the coefficients of the stability polynomial and the coefficients of the Butcher tableau. + c_eq = zeros(num_stages - 2) + # Define the objective_function function objective_function(x) return PairedExplicitRK3_butcher_tableau_objective_function(x, num_stages, num_stages, monomial_coeffs, + c_eq, c_s2) end From b309ca5b6ca0eb1cc4d8b9cb471af7c9b2e7b72a Mon Sep 17 00:00:00 2001 From: Warisa Roongaraya <81345089+warisa-r@users.noreply.github.com> Date: Sat, 27 Jul 2024 21:44:32 +0200 Subject: [PATCH 110/120] Update ext/TrixiNLsolveExt.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> --- ext/TrixiNLsolveExt.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index 745348f151..61121badc0 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -26,9 +26,9 @@ using Trixi: Trixi, compute_c_coeffs, @muladd # Compute residuals for nonlinear equations to match a stability polynomial with given coefficients, # in order to find A-matrix in the Butcher-Tableau -function PairedExplicitRK3_butcher_tableau_objective_function(a_unknown, num_stages, +function PairedExplicitRK3_butcher_tableau_objective_function!(c_eq, a_unknown, num_stages, num_stage_evals, - monomial_coeffs, c_eq, + monomial_coeffs, cS2) c_ts = compute_c_coeffs(num_stages, cS2) # ts = timestep # For explicit methods, a_{1,1} = 0 and a_{2,1} = c_2 (Butcher's condition) From 08733ba5f1be6e1b3b433ed50f0c06a83e64b483 Mon Sep 17 00:00:00 2001 From: Warisa Roongaraya <81345089+warisa-r@users.noreply.github.com> Date: Sat, 27 Jul 2024 21:44:39 +0200 Subject: [PATCH 111/120] Update ext/TrixiNLsolveExt.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> --- ext/TrixiNLsolveExt.jl | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index 61121badc0..c4576b5798 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -83,11 +83,10 @@ function Trixi.solve_a_butcher_coeffs_unknown!(a_unknown, num_stages, monomial_c c_eq = zeros(num_stages - 2) # Define the objective_function - function objective_function(x) - return PairedExplicitRK3_butcher_tableau_objective_function(x, num_stages, + function objective_function!(c_eq, x) + return PairedExplicitRK3_butcher_tableau_objective_function!(c_eq, x, num_stages, num_stages, monomial_coeffs, - c_eq, c_s2) end From 01bc7574a60a83a85e30aab5590cf0a76fd3066c Mon Sep 17 00:00:00 2001 From: Warisa Roongaraya <81345089+warisa-r@users.noreply.github.com> Date: Sat, 27 Jul 2024 21:44:48 +0200 Subject: [PATCH 112/120] Update ext/TrixiNLsolveExt.jl Co-authored-by: Joshua Lampert <51029046+JoshuaLampert@users.noreply.github.com> --- ext/TrixiNLsolveExt.jl | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index c4576b5798..08c5ed7b5b 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -77,10 +77,6 @@ function Trixi.solve_a_butcher_coeffs_unknown!(a_unknown, num_stages, monomial_c c_s2, c; verbose, max_iter = 100000) - # c_eq is a vector initialized with zeros with length num_stages - 2. - # It is used to store the coefficients of the non-linear equations arise from the relation of - # the coefficients of the stability polynomial and the coefficients of the Butcher tableau. - c_eq = zeros(num_stages - 2) # Define the objective_function function objective_function!(c_eq, x) From 33bdcb8e8ff56f40748740953a3ecb795fd6cacf Mon Sep 17 00:00:00 2001 From: Warisa Date: Sat, 27 Jul 2024 21:48:54 +0200 Subject: [PATCH 113/120] minor fix regarding recent changes witjh c_eq --- ext/TrixiNLsolveExt.jl | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index 08c5ed7b5b..66933b7e5d 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -26,10 +26,11 @@ using Trixi: Trixi, compute_c_coeffs, @muladd # Compute residuals for nonlinear equations to match a stability polynomial with given coefficients, # in order to find A-matrix in the Butcher-Tableau -function PairedExplicitRK3_butcher_tableau_objective_function!(c_eq, a_unknown, num_stages, - num_stage_evals, - monomial_coeffs, - cS2) +function PairedExplicitRK3_butcher_tableau_objective_function!(c_eq, a_unknown, + num_stages, + num_stage_evals, + monomial_coeffs, + cS2) c_ts = compute_c_coeffs(num_stages, cS2) # ts = timestep # For explicit methods, a_{1,1} = 0 and a_{2,1} = c_2 (Butcher's condition) a_coeff = [0, c_ts[2], a_unknown...] @@ -65,8 +66,6 @@ function PairedExplicitRK3_butcher_tableau_objective_function!(c_eq, a_unknown, # Third-order consistency condition (Cf. eq. (27) from https://doi.org/10.1016/j.jcp.2022.111470 c_eq[num_stage_evals - 2] = 1 - 4 * a_coeff[num_stage_evals] - a_coeff[num_stage_evals - 1] - - return c_eq end # Find the values of the a_{i, i-1} in the Butcher tableau matrix A by solving a system of @@ -77,13 +76,13 @@ function Trixi.solve_a_butcher_coeffs_unknown!(a_unknown, num_stages, monomial_c c_s2, c; verbose, max_iter = 100000) - # Define the objective_function function objective_function!(c_eq, x) - return PairedExplicitRK3_butcher_tableau_objective_function!(c_eq, x, num_stages, - num_stages, - monomial_coeffs, - c_s2) + return PairedExplicitRK3_butcher_tableau_objective_function!(c_eq, x, + num_stages, + num_stages, + monomial_coeffs, + c_s2) end # RealT is determined as the type of the first element in monomial_coeffs to ensure type consistency @@ -102,7 +101,7 @@ function Trixi.solve_a_butcher_coeffs_unknown!(a_unknown, num_stages, monomial_c x0 = convert(RealT, 0.1) .* rand(rng, RealT, num_stages - 2) - sol = nlsolve(objective_function, x0, method = :trust_region, + sol = nlsolve(objective_function!, x0, method = :trust_region, ftol = 4.0e-16, # Enforce objective up to machine precision iterations = 10^4, xtol = 1.0e-13) From ff7ec1a1d82277d24a2a4d052ddf7a8f1b831f50 Mon Sep 17 00:00:00 2001 From: Warisa Date: Sat, 27 Jul 2024 22:31:47 +0200 Subject: [PATCH 114/120] adjust a constructor to get num stages from reading the files directly --- .../methods_PERK3.jl | 38 ++++++++----------- test/test_unit.jl | 13 ++++--- 2 files changed, 23 insertions(+), 28 deletions(-) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index da582bb595..a6c395966d 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -71,36 +71,30 @@ end # Compute the Butcher tableau for a paired explicit Runge-Kutta method order 3 # using provided values of coefficients a in A-matrix of Butcher tableau -function compute_PairedExplicitRK3_butcher_tableau(num_stages, - base_path_a_coeffs::AbstractString; +function compute_PairedExplicitRK3_butcher_tableau(path_a_coeffs::AbstractString; cS2) + @assert isfile(path_a_coeffs) "Couldn't find file $path_a_coeffs" + a_coeffs = readdlm(path_a_coeffs, Float64) + num_a_coeffs = size(a_coeffs, 1) + + # + 2 Since the first entry of A is always zero (explicit method) and the second is given by c_2 (consistency) + num_stages = num_a_coeffs + 2 # Initialize array of c c = compute_c_coeffs(num_stages, cS2) - # - 2 Since First entry of A is always zero (explicit method) and second is given by c_2 (consistency) - a_coeffs_max = num_stages - 2 - - a_matrix = zeros(a_coeffs_max, 2) + a_matrix = zeros(num_a_coeffs, 2) a_matrix[:, 1] = c[3:end] - path_a_coeffs = joinpath(base_path_a_coeffs, - "a_" * string(num_stages) * ".txt") - - @assert isfile(path_a_coeffs) "Couldn't find file $path_a_coeffs" - a_coeffs = readdlm(path_a_coeffs, Float64) - num_a_coeffs = size(a_coeffs, 1) - - @assert num_a_coeffs == a_coeffs_max # Fill A-matrix in P-ERK style a_matrix[:, 1] -= a_coeffs a_matrix[:, 2] = a_coeffs - return a_matrix, c + return num_stages, a_matrix, c end @doc raw""" - PairedExplicitRK3(num_stages, base_path_a_coeffs::AbstractString; + PairedExplicitRK3(path_a_coeffs::AbstractString; cS2 = 1.0f0) PairedExplicitRK3(num_stages, tspan, semi::AbstractSemidiscretization; verbose = false, cS2 = 1.0f0) @@ -108,10 +102,9 @@ end verbose = false, cS2 = 1.0f0) Parameters: - - `num_stages` (`Int`): Number of stages in the paired explicit Runge-Kutta (P-ERK) method. - - `base_path_a_coeffs` (`AbstractString`): Path to a file containing some coefficients in the A-matrix in + - `path_a_coeffs` (`AbstractString`): Path to a file containing some coefficients in the A-matrix in the Butcher tableau of the Runge Kutta method. - The matrix should be stored in a text file at `joinpath(base_path_a_coeffs, "a_$(num_stages).txt")` and separated by line breaks. + - `num_stages` (`Int`): Number of stages in the paired explicit Runge-Kutta (P-ERK) method. - `tspan`: Time span of the simulation. - `semi` (`AbstractSemidiscretization`): Semidiscretization setup. - `eig_vals` (`Vector{ComplexF64}`): Eigenvalues of the Jacobian of the right-hand side (rhs) of the ODEProblem after the @@ -140,11 +133,10 @@ mutable struct PairedExplicitRK3 <: AbstractPairedExplicitRKSingle end # struct PairedExplicitRK3 # Constructor for previously computed A Coeffs -function PairedExplicitRK3(num_stages, base_path_a_coeffs::AbstractString; +function PairedExplicitRK3(path_a_coeffs::AbstractString; cS2 = 1.0f0) - a_matrix, c = compute_PairedExplicitRK3_butcher_tableau(num_stages, - base_path_a_coeffs; - cS2) + num_stages, a_matrix, c = compute_PairedExplicitRK3_butcher_tableau(path_a_coeffs; + cS2) return PairedExplicitRK3(num_stages, a_matrix, c) end diff --git a/test/test_unit.jl b/test/test_unit.jl index befad58aa7..84ffed77f9 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -1704,11 +1704,13 @@ end end @testset "PERK Single p3 Constructors" begin - path_coeff_file = mktempdir() + base_path_coeff_file = mktempdir() + + path_a_coeffs = joinpath(base_path_coeff_file, "a_8.txt") Trixi.download("https://gist.githubusercontent.com/warisa-r/0796db36abcd5abe735ac7eebf41b973/raw/32889062fd5dcf7f450748f4f5f0797c8155a18d/a_8_8.txt", - joinpath(path_coeff_file, "a_8.txt")) + path_a_coeffs) - ode_algorithm = Trixi.PairedExplicitRK3(8, path_coeff_file) + ode_algorithm = Trixi.PairedExplicitRK3(path_a_coeffs) @test isapprox(ode_algorithm.a_matrix, [0.33551678438002486 0.06448322158043965 @@ -1718,10 +1720,11 @@ end 0.7522972036571336 0.2477027963428664 0.31192569908571666 0.18807430091428337], atol = 1e-13) + path_spectrum = joinpath(base_path_coeff_file, "spectrum.txt") Trixi.download("https://gist.githubusercontent.com/warisa-r/8d93f6a3ae0635e13b9f51ee32ab7fff/raw/54dc5b14be9288e186b745facb5bbcb04d1476f8/EigenvalueList_Refined2.txt", - joinpath(path_coeff_file, "spectrum.txt")) + path_spectrum) - eig_vals = readdlm(joinpath(path_coeff_file, "spectrum.txt"), ComplexF64) + eig_vals = readdlm(path_spectrum, ComplexF64) tspan = (0.0, 1.0) ode_algorithm = Trixi.PairedExplicitRK3(13, tspan, vec(eig_vals)) From fd05aff653bba7629241d5f396b609b71f4d8d3e Mon Sep 17 00:00:00 2001 From: Warisa Date: Mon, 29 Jul 2024 09:03:45 +0200 Subject: [PATCH 115/120] Revert "adjust a constructor to get num stages from reading the files directly" since it is breaking --- .../methods_PERK3.jl | 38 +++++++++++-------- test/test_unit.jl | 13 +++---- 2 files changed, 28 insertions(+), 23 deletions(-) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index a6c395966d..da582bb595 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -71,30 +71,36 @@ end # Compute the Butcher tableau for a paired explicit Runge-Kutta method order 3 # using provided values of coefficients a in A-matrix of Butcher tableau -function compute_PairedExplicitRK3_butcher_tableau(path_a_coeffs::AbstractString; +function compute_PairedExplicitRK3_butcher_tableau(num_stages, + base_path_a_coeffs::AbstractString; cS2) - @assert isfile(path_a_coeffs) "Couldn't find file $path_a_coeffs" - a_coeffs = readdlm(path_a_coeffs, Float64) - num_a_coeffs = size(a_coeffs, 1) - - # + 2 Since the first entry of A is always zero (explicit method) and the second is given by c_2 (consistency) - num_stages = num_a_coeffs + 2 # Initialize array of c c = compute_c_coeffs(num_stages, cS2) - a_matrix = zeros(num_a_coeffs, 2) + # - 2 Since First entry of A is always zero (explicit method) and second is given by c_2 (consistency) + a_coeffs_max = num_stages - 2 + + a_matrix = zeros(a_coeffs_max, 2) a_matrix[:, 1] = c[3:end] + path_a_coeffs = joinpath(base_path_a_coeffs, + "a_" * string(num_stages) * ".txt") + + @assert isfile(path_a_coeffs) "Couldn't find file $path_a_coeffs" + a_coeffs = readdlm(path_a_coeffs, Float64) + num_a_coeffs = size(a_coeffs, 1) + + @assert num_a_coeffs == a_coeffs_max # Fill A-matrix in P-ERK style a_matrix[:, 1] -= a_coeffs a_matrix[:, 2] = a_coeffs - return num_stages, a_matrix, c + return a_matrix, c end @doc raw""" - PairedExplicitRK3(path_a_coeffs::AbstractString; + PairedExplicitRK3(num_stages, base_path_a_coeffs::AbstractString; cS2 = 1.0f0) PairedExplicitRK3(num_stages, tspan, semi::AbstractSemidiscretization; verbose = false, cS2 = 1.0f0) @@ -102,9 +108,10 @@ end verbose = false, cS2 = 1.0f0) Parameters: - - `path_a_coeffs` (`AbstractString`): Path to a file containing some coefficients in the A-matrix in - the Butcher tableau of the Runge Kutta method. - `num_stages` (`Int`): Number of stages in the paired explicit Runge-Kutta (P-ERK) method. + - `base_path_a_coeffs` (`AbstractString`): Path to a file containing some coefficients in the A-matrix in + the Butcher tableau of the Runge Kutta method. + The matrix should be stored in a text file at `joinpath(base_path_a_coeffs, "a_$(num_stages).txt")` and separated by line breaks. - `tspan`: Time span of the simulation. - `semi` (`AbstractSemidiscretization`): Semidiscretization setup. - `eig_vals` (`Vector{ComplexF64}`): Eigenvalues of the Jacobian of the right-hand side (rhs) of the ODEProblem after the @@ -133,10 +140,11 @@ mutable struct PairedExplicitRK3 <: AbstractPairedExplicitRKSingle end # struct PairedExplicitRK3 # Constructor for previously computed A Coeffs -function PairedExplicitRK3(path_a_coeffs::AbstractString; +function PairedExplicitRK3(num_stages, base_path_a_coeffs::AbstractString; cS2 = 1.0f0) - num_stages, a_matrix, c = compute_PairedExplicitRK3_butcher_tableau(path_a_coeffs; - cS2) + a_matrix, c = compute_PairedExplicitRK3_butcher_tableau(num_stages, + base_path_a_coeffs; + cS2) return PairedExplicitRK3(num_stages, a_matrix, c) end diff --git a/test/test_unit.jl b/test/test_unit.jl index 84ffed77f9..befad58aa7 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -1704,13 +1704,11 @@ end end @testset "PERK Single p3 Constructors" begin - base_path_coeff_file = mktempdir() - - path_a_coeffs = joinpath(base_path_coeff_file, "a_8.txt") + path_coeff_file = mktempdir() Trixi.download("https://gist.githubusercontent.com/warisa-r/0796db36abcd5abe735ac7eebf41b973/raw/32889062fd5dcf7f450748f4f5f0797c8155a18d/a_8_8.txt", - path_a_coeffs) + joinpath(path_coeff_file, "a_8.txt")) - ode_algorithm = Trixi.PairedExplicitRK3(path_a_coeffs) + ode_algorithm = Trixi.PairedExplicitRK3(8, path_coeff_file) @test isapprox(ode_algorithm.a_matrix, [0.33551678438002486 0.06448322158043965 @@ -1720,11 +1718,10 @@ end 0.7522972036571336 0.2477027963428664 0.31192569908571666 0.18807430091428337], atol = 1e-13) - path_spectrum = joinpath(base_path_coeff_file, "spectrum.txt") Trixi.download("https://gist.githubusercontent.com/warisa-r/8d93f6a3ae0635e13b9f51ee32ab7fff/raw/54dc5b14be9288e186b745facb5bbcb04d1476f8/EigenvalueList_Refined2.txt", - path_spectrum) + joinpath(path_coeff_file, "spectrum.txt")) - eig_vals = readdlm(path_spectrum, ComplexF64) + eig_vals = readdlm(joinpath(path_coeff_file, "spectrum.txt"), ComplexF64) tspan = (0.0, 1.0) ode_algorithm = Trixi.PairedExplicitRK3(13, tspan, vec(eig_vals)) From 582dd870d22deca7a8c156abc7723a5987e8b1fd Mon Sep 17 00:00:00 2001 From: Warisa Date: Mon, 29 Jul 2024 09:50:20 +0200 Subject: [PATCH 116/120] Update TrixiNLsolveExt.jl to use forward autodiff in solve_a_butcher_coeffs_unknown! function --- ext/TrixiNLsolveExt.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/TrixiNLsolveExt.jl b/ext/TrixiNLsolveExt.jl index 66933b7e5d..4de8feb25a 100644 --- a/ext/TrixiNLsolveExt.jl +++ b/ext/TrixiNLsolveExt.jl @@ -103,7 +103,7 @@ function Trixi.solve_a_butcher_coeffs_unknown!(a_unknown, num_stages, monomial_c sol = nlsolve(objective_function!, x0, method = :trust_region, ftol = 4.0e-16, # Enforce objective up to machine precision - iterations = 10^4, xtol = 1.0e-13) + iterations = 10^4, xtol = 1.0e-13, autodiff = :forward) a_unknown = sol.zero # Retrieve solution (root = zero) From 859bf371a679112a9400f61db083fd9ec7c3bfba Mon Sep 17 00:00:00 2001 From: Daniel Doehring Date: Tue, 13 Aug 2024 17:59:07 +0200 Subject: [PATCH 117/120] Apply suggestions from code review --- .../paired_explicit_runge_kutta/methods_PERK3.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index da582bb595..f069ec8100 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -11,8 +11,8 @@ using DelimitedFiles: readdlm function compute_c_coeffs(num_stages, cS2) c = zeros(num_stages) - # Last timesteps as for SSPRK33, see motivation in - # https://doi.org/10.48550/arXiv.2403.05144 + # Last timesteps as for SSPRK33, see motivation in Section 3.3 of + # https://doi.org/10.1016/j.jcp.2024.113223 c[num_stages - 1] = 1.0f0 c[num_stages] = 0.5f0 @@ -130,7 +130,7 @@ Third-order Paired Explicit Runge-Kutta schemes for stiff systems of equations While the changes to SSPRK33 base-scheme are described in - Doehring, Schlottke-Lakemper, Gassner, Torrilhon (2024) Multirate Time-Integration based on Dynamic ODE Partitioning through Adaptively Refined Meshes for Compressible Fluid Dynamics -[Arxiv: 10.48550/arXiv.2403.05144](https://doi.org/10.48550/arXiv.2403.05144) +[DOI: 10.1016/j.jcp.2024.113223](https://doi.org/10.1016/j.jcp.2024.113223) """ mutable struct PairedExplicitRK3 <: AbstractPairedExplicitRKSingle const num_stages::Int # S From 55418447f7101eea724fb6bfca7286021f1437d7 Mon Sep 17 00:00:00 2001 From: Daniel_Doehring Date: Wed, 14 Aug 2024 10:25:31 +0200 Subject: [PATCH 118/120] Slight modifications a values --- test/test_unit.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/test_unit.jl b/test/test_unit.jl index befad58aa7..bc149dc715 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -1726,15 +1726,15 @@ end ode_algorithm = Trixi.PairedExplicitRK3(13, tspan, vec(eig_vals)) @test isapprox(ode_algorithm.a_matrix, - [0.19258815508201277 0.00741184789821947 - 0.2872329330253629 0.01276707889556606 - 0.3801771730615694 0.01982283289889509 + [0.19258815508348048 0.007411847896751755 + 0.28723293302534425 0.012767078895584727 + 0.38017717306156973 0.01982283289889476 0.4706748926615584 0.02932510733844162 0.5575748313419124 0.04242519249994544 0.6390917539959684 0.06090823408310269 0.7124876783811593 0.08751233353976957 0.7736369902636945 0.12636298589444758 - 0.8161315438506253 0.18386845614937472 + 0.8161315438506253 0.18386845614937475 0.7532704353232954 0.24672956467670462 0.3116823911691762 0.18831760883082385], atol = 1e-13) end From a50a4e07519149cd6d28c71eb4eabe690d68ba9f Mon Sep 17 00:00:00 2001 From: Warisa Date: Thu, 10 Oct 2024 19:50:19 +0200 Subject: [PATCH 119/120] add cfl number calculation for PERK3 --- .../elixir_burgers_perk3_optimal_cfl.jl | 69 +++++++++++++++++++ .../methods_PERK3.jl | 28 ++++---- test/test_structured_1d.jl | 16 +++++ test/test_unit.jl | 2 +- 4 files changed, 101 insertions(+), 14 deletions(-) create mode 100644 examples/structured_1d_dgsem/elixir_burgers_perk3_optimal_cfl.jl diff --git a/examples/structured_1d_dgsem/elixir_burgers_perk3_optimal_cfl.jl b/examples/structured_1d_dgsem/elixir_burgers_perk3_optimal_cfl.jl new file mode 100644 index 0000000000..b59543fbfd --- /dev/null +++ b/examples/structured_1d_dgsem/elixir_burgers_perk3_optimal_cfl.jl @@ -0,0 +1,69 @@ +# 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 + +# NLsolve is imported to solve the system of nonlinear equations to find a coefficients +# in the Butcher tableau in the third order P-ERK time integrator. +using NLsolve + +using OrdinaryDiffEq +using Trixi + +############################################################################### +# semidiscretization of the (inviscid) Burgers equation + +equations = InviscidBurgersEquation1D() + +initial_condition = initial_condition_convergence_test + +# 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) + +coordinates_min = (0.0,) # minimum coordinate +coordinates_max = (1.0,) # maximum coordinate +cells_per_dimension = (64,) + +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, 2.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(dt = 0.1, + save_initial_solution = true, + save_final_solution = true, + solution_variables = cons2prim) + +# Construct second order paired explicit Runge-Kutta method with 8 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.PairedExplicitRK3(8, tspan, semi) + +cfl_number = Trixi.calculate_cfl(ode_algorithm, ode) +# For non-linear problems, the CFL number should be reduced by a safety factor +stepsize_callback = StepsizeCallback(cfl = 0.85 * cfl_number) + +callbacks = CallbackSet(summary_callback, + analysis_callback, alive_callback, save_solution, + 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); + +# Print the timer summary +summary_callback() diff --git a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl index f069ec8100..6f0a9a9629 100644 --- a/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl +++ b/src/time_integration/paired_explicit_runge_kutta/methods_PERK3.jl @@ -46,10 +46,10 @@ function compute_PairedExplicitRK3_butcher_tableau(num_stages, tspan, num_eig_vals, eig_vals = filter_eig_vals(eig_vals; verbose) - monomial_coeffs, _ = bisect_stability_polynomial(consistency_order, - num_eig_vals, num_stages, - dtmax, dteps, - eig_vals; verbose) + monomial_coeffs, dt_opt = bisect_stability_polynomial(consistency_order, + num_eig_vals, num_stages, + dtmax, dteps, + eig_vals; verbose) monomial_coeffs = undo_normalization!(monomial_coeffs, consistency_order, num_stages) @@ -66,7 +66,7 @@ function compute_PairedExplicitRK3_butcher_tableau(num_stages, tspan, a_matrix[:, 1] -= a_unknown a_matrix[:, 2] = a_unknown - return a_matrix, c + return a_matrix, c, dt_opt end # Compute the Butcher tableau for a paired explicit Runge-Kutta method order 3 @@ -100,7 +100,7 @@ function compute_PairedExplicitRK3_butcher_tableau(num_stages, end @doc raw""" - PairedExplicitRK3(num_stages, base_path_a_coeffs::AbstractString; + PairedExplicitRK3(num_stages, base_path_a_coeffs::AbstractString, dt_opt; cS2 = 1.0f0) PairedExplicitRK3(num_stages, tspan, semi::AbstractSemidiscretization; verbose = false, cS2 = 1.0f0) @@ -112,6 +112,7 @@ end - `base_path_a_coeffs` (`AbstractString`): Path to a file containing some coefficients in the A-matrix in the Butcher tableau of the Runge Kutta method. The matrix should be stored in a text file at `joinpath(base_path_a_coeffs, "a_$(num_stages).txt")` and separated by line breaks. + - `dt_opt` (`Float64`): Optimal time step size for the simulation setup. - `tspan`: Time span of the simulation. - `semi` (`AbstractSemidiscretization`): Semidiscretization setup. - `eig_vals` (`Vector{ComplexF64}`): Eigenvalues of the Jacobian of the right-hand side (rhs) of the ODEProblem after the @@ -137,16 +138,17 @@ mutable struct PairedExplicitRK3 <: AbstractPairedExplicitRKSingle a_matrix::Matrix{Float64} c::Vector{Float64} + dt_opt::Float64 end # struct PairedExplicitRK3 # Constructor for previously computed A Coeffs -function PairedExplicitRK3(num_stages, base_path_a_coeffs::AbstractString; +function PairedExplicitRK3(num_stages, base_path_a_coeffs::AbstractString, dt_opt; cS2 = 1.0f0) a_matrix, c = compute_PairedExplicitRK3_butcher_tableau(num_stages, base_path_a_coeffs; cS2) - return PairedExplicitRK3(num_stages, a_matrix, c) + return PairedExplicitRK3(num_stages, a_matrix, c, dt_opt) end # Constructor that computes Butcher matrix A coefficients from a semidiscretization @@ -160,11 +162,11 @@ end # Constructor that calculates the coefficients with polynomial optimizer from a list of eigenvalues function PairedExplicitRK3(num_stages, tspan, eig_vals::Vector{ComplexF64}; verbose = false, cS2 = 1.0f0) - a_matrix, c = compute_PairedExplicitRK3_butcher_tableau(num_stages, - tspan, - eig_vals; - verbose, cS2) - return PairedExplicitRK3(num_stages, a_matrix, c) + a_matrix, c, dt_opt = compute_PairedExplicitRK3_butcher_tableau(num_stages, + tspan, + eig_vals; + verbose, cS2) + return PairedExplicitRK3(num_stages, a_matrix, c, dt_opt) end # This struct is needed to fake https://github.com/SciML/OrdinaryDiffEq.jl/blob/0c2048a502101647ac35faabd80da8a5645beac7/src/integrators/type.jl#L77 diff --git a/test/test_structured_1d.jl b/test/test_structured_1d.jl index 8943762d23..094f1c4f69 100644 --- a/test/test_structured_1d.jl +++ b/test/test_structured_1d.jl @@ -73,6 +73,22 @@ end end end +# Testing the third-order paired explicit Runge-Kutta (PERK) method with its optimal CFL number +@trixi_testset "elixir_burgers_perk3_optimal_cfl.jl" begin + @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_burgers_perk3_optimal_cfl.jl"), + l2=[4.12066275835687e-6], #TODO: fix this values to match the ones in CI + linf=[2.538190787615413e-5], + atol=1.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)) < 8000 + end +end + # Testing the third-order paired explicit Runge-Kutta (PERK) method without stepsize callback @trixi_testset "elixir_burgers_perk3.jl(fixed time step)" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_burgers_perk3.jl"), diff --git a/test/test_unit.jl b/test/test_unit.jl index eefb412cc9..e4d2ff24d9 100644 --- a/test/test_unit.jl +++ b/test/test_unit.jl @@ -1708,7 +1708,7 @@ end Trixi.download("https://gist.githubusercontent.com/warisa-r/0796db36abcd5abe735ac7eebf41b973/raw/32889062fd5dcf7f450748f4f5f0797c8155a18d/a_8_8.txt", joinpath(path_coeff_file, "a_8.txt")) - ode_algorithm = Trixi.PairedExplicitRK3(8, path_coeff_file) + ode_algorithm = Trixi.PairedExplicitRK3(8, path_coeff_file, 42) # dummy optimal time step (dt_opt plays no role in determining `a_matrix`) @test isapprox(ode_algorithm.a_matrix, [0.33551678438002486 0.06448322158043965 From 0d9e66445c22e048d0547f7209a0000a96423f6f Mon Sep 17 00:00:00 2001 From: Warisa Date: Thu, 10 Oct 2024 20:28:40 +0200 Subject: [PATCH 120/120] update CI values --- test/test_structured_1d.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_structured_1d.jl b/test/test_structured_1d.jl index 094f1c4f69..6bc4b9ccab 100644 --- a/test/test_structured_1d.jl +++ b/test/test_structured_1d.jl @@ -76,8 +76,8 @@ end # Testing the third-order paired explicit Runge-Kutta (PERK) method with its optimal CFL number @trixi_testset "elixir_burgers_perk3_optimal_cfl.jl" begin @test_trixi_include(joinpath(EXAMPLES_DIR, "elixir_burgers_perk3_optimal_cfl.jl"), - l2=[4.12066275835687e-6], #TODO: fix this values to match the ones in CI - linf=[2.538190787615413e-5], + l2=[3.8156922097242205e-6], + linf=[2.1962957979626552e-5], atol=1.0e-6) # Ensure that we do not have excessive memory allocations # (e.g., from type instabilities)