Path: blob/main/test/test_performance_specializations_2d.jl
5582 views
module TestPerformanceSpecializations2D12using Test3using Trixi4using Trixi: @muladd56include("test_trixi.jl")78EXAMPLES_DIR = examples_dir()910# Start with a clean environment: remove Trixi.jl output directory if it exists11outdir = "out"12isdir(outdir) && rm(outdir, recursive = true)1314@testset "Performance specializations 2D" begin15#! format: noindent1617@timed_testset "TreeMesh2D, flux_shima_etal_turbo" begin18trixi_include(@__MODULE__,19joinpath(EXAMPLES_DIR, "tree_2d_dgsem", "elixir_euler_ec.jl"),20initial_refinement_level = 0, tspan = (0.0, 0.0), polydeg = 3,21volume_flux = flux_shima_etal_turbo,22surface_flux = flux_shima_etal_turbo)23u_ode = copy(sol.u[end])24du_ode = zero(u_ode)2526# Preserve original memory since it will be `unsafe_wrap`ped and might27# thus otherwise be garbage collected28GC.@preserve u_ode du_ode begin29u = Trixi.wrap_array(u_ode, semi)30du = Trixi.wrap_array(du_ode, semi)31have_nonconservative_terms = Trixi.have_nonconservative_terms(semi.equations)3233# Call the optimized default version34du .= 035Trixi.flux_differencing_kernel!(du, u, 1, typeof(semi.mesh),36have_nonconservative_terms, semi.equations,37semi.solver.volume_integral.volume_flux,38semi.solver, semi.cache, true)39du_specialized = du[:, :, :, 1]4041# Call the plain version - note the argument type `Function` of42# `semi.solver.volume_integral.volume_flux`43du .= 044invoke(Trixi.flux_differencing_kernel!,45Tuple{typeof(du), typeof(u), Integer, Type{typeof(semi.mesh)},46typeof(have_nonconservative_terms), typeof(semi.equations),47Function, typeof(semi.solver), typeof(semi.cache), Bool},48du, u, 1, typeof(semi.mesh),49have_nonconservative_terms, semi.equations,50semi.solver.volume_integral.volume_flux, semi.solver, semi.cache, true)51du_baseline = du[:, :, :, 1]5253@test du_specialized ≈ du_baseline54end55end5657@timed_testset "TreeMesh2D, flux_ranocha_turbo" begin58trixi_include(@__MODULE__,59joinpath(EXAMPLES_DIR, "tree_2d_dgsem", "elixir_euler_ec.jl"),60initial_refinement_level = 0, tspan = (0.0, 0.0), polydeg = 3,61volume_flux = flux_ranocha_turbo, surface_flux = flux_ranocha_turbo)62u_ode = copy(sol.u[end])63du_ode = zero(u_ode)6465# Preserve original memory since it will be `unsafe_wrap`ped and might66# thus otherwise be garbage collected67GC.@preserve u_ode du_ode begin68u = Trixi.wrap_array(u_ode, semi)69du = Trixi.wrap_array(du_ode, semi)70have_nonconservative_terms = Trixi.have_nonconservative_terms(semi.equations)7172# Call the optimized default version73du .= 074Trixi.flux_differencing_kernel!(du, u, 1, typeof(semi.mesh),75have_nonconservative_terms, semi.equations,76semi.solver.volume_integral.volume_flux,77semi.solver, semi.cache, true)78du_specialized = du[:, :, :, 1]7980# Call the plain version - note the argument type `Function` of81# `semi.solver.volume_integral.volume_flux`82du .= 083invoke(Trixi.flux_differencing_kernel!,84Tuple{typeof(du), typeof(u), Integer, Type{typeof(semi.mesh)},85typeof(have_nonconservative_terms), typeof(semi.equations),86Function, typeof(semi.solver), typeof(semi.cache), Bool},87du, u, 1, typeof(semi.mesh),88have_nonconservative_terms, semi.equations,89semi.solver.volume_integral.volume_flux, semi.solver, semi.cache, true)90du_baseline = du[:, :, :, 1]9192@test du_specialized ≈ du_baseline93end94end9596@timed_testset "StructuredMesh2D, flux_shima_etal_turbo" begin97trixi_include(@__MODULE__,98joinpath(EXAMPLES_DIR, "structured_2d_dgsem", "elixir_euler_ec.jl"),99cells_per_dimension = (1, 1), tspan = (0.0, 0.0), polydeg = 3,100volume_flux = flux_shima_etal_turbo,101surface_flux = flux_shima_etal_turbo)102u_ode = copy(sol.u[end])103du_ode = zero(u_ode)104105# Preserve original memory since it will be `unsafe_wrap`ped and might106# thus otherwise be garbage collected107GC.@preserve u_ode du_ode begin108u = Trixi.wrap_array(u_ode, semi)109du = Trixi.wrap_array(du_ode, semi)110have_nonconservative_terms = Trixi.have_nonconservative_terms(semi.equations)111112# Call the optimized default version113du .= 0114Trixi.flux_differencing_kernel!(du, u, 1, typeof(semi.mesh),115have_nonconservative_terms, semi.equations,116semi.solver.volume_integral.volume_flux,117semi.solver, semi.cache, true)118du_specialized = du[:, :, :, 1]119120# Call the plain version - note the argument type `Function` of121# `semi.solver.volume_integral.volume_flux`122du .= 0123invoke(Trixi.flux_differencing_kernel!,124Tuple{typeof(du), typeof(u), Integer, Type{typeof(semi.mesh)},125typeof(have_nonconservative_terms), typeof(semi.equations),126Function, typeof(semi.solver), typeof(semi.cache), Bool},127du, u, 1, typeof(semi.mesh),128have_nonconservative_terms, semi.equations,129semi.solver.volume_integral.volume_flux, semi.solver, semi.cache, true)130du_baseline = du[:, :, :, 1]131132@test du_specialized ≈ du_baseline133end134end135136@timed_testset "StructuredMesh2D, flux_ranocha_turbo" begin137trixi_include(@__MODULE__,138joinpath(EXAMPLES_DIR, "structured_2d_dgsem", "elixir_euler_ec.jl"),139cells_per_dimension = (1, 1), tspan = (0.0, 0.0), polydeg = 3,140volume_flux = flux_ranocha_turbo, surface_flux = flux_ranocha_turbo)141u_ode = copy(sol.u[end])142du_ode = zero(u_ode)143144# Preserve original memory since it will be `unsafe_wrap`ped and might145# thus otherwise be garbage collected146GC.@preserve u_ode du_ode begin147u = Trixi.wrap_array(u_ode, semi)148du = Trixi.wrap_array(du_ode, semi)149have_nonconservative_terms = Trixi.have_nonconservative_terms(semi.equations)150151# Call the optimized default version152du .= 0153Trixi.flux_differencing_kernel!(du, u, 1, typeof(semi.mesh),154have_nonconservative_terms, semi.equations,155semi.solver.volume_integral.volume_flux,156semi.solver, semi.cache, true)157du_specialized = du[:, :, :, 1]158159# Call the plain version - note the argument type `Function` of160# `semi.solver.volume_integral.volume_flux`161du .= 0162invoke(Trixi.flux_differencing_kernel!,163Tuple{typeof(du), typeof(u), Integer, Type{typeof(semi.mesh)},164typeof(have_nonconservative_terms), typeof(semi.equations),165Function, typeof(semi.solver), typeof(semi.cache), Bool},166du, u, 1, typeof(semi.mesh),167have_nonconservative_terms, semi.equations,168semi.solver.volume_integral.volume_flux, semi.solver, semi.cache, true)169du_baseline = du[:, :, :, 1]170171@test du_specialized ≈ du_baseline172end173end174175@timed_testset "P4estMesh2D, combine_conservative_and_nonconservative_fluxes" begin176trixi_include(@__MODULE__,177joinpath(EXAMPLES_DIR, "p4est_2d_dgsem", "elixir_mhd_rotor.jl"),178volume_integral = VolumeIntegralFluxDifferencing((flux_hindenlang_gassner,179flux_nonconservative_powell)),180amr_callback = nothing, tspan = (0.0, 0.001))181u_ode = copy(sol.u[end])182183@muladd @inline function flux_hindenlang_gassner_nonconservative_powell(u_ll, u_rr,184normal_direction,185equations)186rho_ll, v1_ll, v2_ll, v3_ll, p_ll, B1_ll, B2_ll, B3_ll, psi_ll = cons2prim(u_ll,187equations)188rho_rr, v1_rr, v2_rr, v3_rr, p_rr, B1_rr, B2_rr, B3_rr, psi_rr = cons2prim(u_rr,189equations)190v_dot_n_ll = v1_ll * normal_direction[1] + v2_ll * normal_direction[2]191v_dot_n_rr = v1_rr * normal_direction[1] + v2_rr * normal_direction[2]192B_dot_n_ll = B1_ll * normal_direction[1] + B2_ll * normal_direction[2]193B_dot_n_rr = B1_rr * normal_direction[1] + B2_rr * normal_direction[2]194195# Compute the necessary mean values needed for either direction196rho_mean = Trixi.ln_mean(rho_ll, rho_rr)197# Algebraically equivalent to `inv_ln_mean(rho_ll / p_ll, rho_rr / p_rr)`198# in exact arithmetic since199# log((ϱₗ/pₗ) / (ϱᵣ/pᵣ)) / (ϱₗ/pₗ - ϱᵣ/pᵣ)200# = pₗ pᵣ log((ϱₗ pᵣ) / (ϱᵣ pₗ)) / (ϱₗ pᵣ - ϱᵣ pₗ)201inv_rho_p_mean = p_ll * p_rr * Trixi.inv_ln_mean(rho_ll * p_rr, rho_rr * p_ll)202v1_avg = 0.5f0 * (v1_ll + v1_rr)203v2_avg = 0.5f0 * (v2_ll + v2_rr)204v3_avg = 0.5f0 * (v3_ll + v3_rr)205p_avg = 0.5f0 * (p_ll + p_rr)206psi_avg = 0.5f0 * (psi_ll + psi_rr)207velocity_square_avg = 0.5f0 * (v1_ll * v1_rr + v2_ll * v2_rr + v3_ll * v3_rr)208magnetic_square_avg = 0.5f0 * (B1_ll * B1_rr + B2_ll * B2_rr + B3_ll * B3_rr)209210# Calculate fluxes depending on normal_direction211f1 = rho_mean * 0.5f0 * (v_dot_n_ll + v_dot_n_rr)212f2 = (f1 * v1_avg + (p_avg + magnetic_square_avg) * normal_direction[1]213-2140.5f0 * (B_dot_n_ll * B1_rr + B_dot_n_rr * B1_ll))215f3 = (f1 * v2_avg + (p_avg + magnetic_square_avg) * normal_direction[2]216-2170.5f0 * (B_dot_n_ll * B2_rr + B_dot_n_rr * B2_ll))218f4 = (f1 * v3_avg219-2200.5f0 * (B_dot_n_ll * B3_rr + B_dot_n_rr * B3_ll))221#f5 below222f6 = (equations.c_h * psi_avg * normal_direction[1]223+2240.5f0 * (v_dot_n_ll * B1_ll - v1_ll * B_dot_n_ll +225v_dot_n_rr * B1_rr - v1_rr * B_dot_n_rr))226f7 = (equations.c_h * psi_avg * normal_direction[2]227+2280.5f0 * (v_dot_n_ll * B2_ll - v2_ll * B_dot_n_ll +229v_dot_n_rr * B2_rr - v2_rr * B_dot_n_rr))230f8 = +0.5f0 * (v_dot_n_ll * B3_ll - v3_ll * B_dot_n_ll +231v_dot_n_rr * B3_rr - v3_rr * B_dot_n_rr)232f9 = equations.c_h * 0.5f0 * (B_dot_n_ll + B_dot_n_rr)233# total energy flux is complicated and involves the previous components234f5 = (f1 *235(velocity_square_avg + inv_rho_p_mean * equations.inv_gamma_minus_one)236+2370.5f0 * (+p_ll * v_dot_n_rr + p_rr * v_dot_n_ll238+ (v_dot_n_ll * B1_ll * B1_rr + v_dot_n_rr * B1_rr * B1_ll)239+ (v_dot_n_ll * B2_ll * B2_rr + v_dot_n_rr * B2_rr * B2_ll)240+ (v_dot_n_ll * B3_ll * B3_rr + v_dot_n_rr * B3_rr * B3_ll)241-242(v1_ll * B_dot_n_ll * B1_rr + v1_rr * B_dot_n_rr * B1_ll)243-244(v2_ll * B_dot_n_ll * B2_rr + v2_rr * B_dot_n_rr * B2_ll)245-246(v3_ll * B_dot_n_ll * B3_rr + v3_rr * B_dot_n_rr * B3_ll)247+248equations.c_h * (B_dot_n_ll * psi_rr + B_dot_n_rr * psi_ll)))249250v_dot_B_ll = v1_ll * B1_ll + v2_ll * B2_ll + v3_ll * B3_ll251v_dot_B_rr = v1_rr * B1_rr + v2_rr * B2_rr + v3_rr * B3_rr252253# Powell nonconservative term: (0, B_1, B_2, B_3, v⋅B, v_1, v_2, v_3, 0)254# Galilean nonconservative term: (0, 0, 0, 0, ψ v_{1,2}, 0, 0, 0, v_{1,2})255g_left = SVector(0,256B1_ll * B_dot_n_rr,257B2_ll * B_dot_n_rr,258B3_ll * B_dot_n_rr,259v_dot_B_ll * B_dot_n_rr + v_dot_n_ll * psi_ll * psi_rr,260v1_ll * B_dot_n_rr,261v2_ll * B_dot_n_rr,262v3_ll * B_dot_n_rr,263v_dot_n_ll * psi_rr)264g_right = SVector(0,265B1_rr * B_dot_n_ll,266B2_rr * B_dot_n_ll,267B3_rr * B_dot_n_ll,268v_dot_B_rr * B_dot_n_ll + v_dot_n_rr * psi_rr * psi_ll,269v1_rr * B_dot_n_ll,270v2_rr * B_dot_n_ll,271v3_rr * B_dot_n_ll,272v_dot_n_rr * psi_ll)273274f = SVector(f1, f2, f3, f4, f5, f6, f7, f8, f9)275flux_left = f + g_left * 0.5f0276flux_right = f + g_right * 0.5f0277return flux_left, flux_right278end279280@inline Trixi.combine_conservative_and_nonconservative_fluxes(::typeof(flux_hindenlang_gassner_nonconservative_powell),281equations::IdealGlmMhdEquations2D) = Trixi.True()282283@muladd @inline function flux_lax_friedrichs_nonconservative_powell(u_ll, u_rr,284normal_direction,285equations)286f = FluxLaxFriedrichs(max_abs_speed_naive)(u_ll, u_rr, normal_direction,287equations)288289rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, rho_e_total_ll, B1_ll, B2_ll, B3_ll, psi_ll = u_ll290rho_rr, rho_v1_rr, rho_v2_rr, rho_v3_rr, rho_e_total_rr, B1_rr, B2_rr, B3_rr, psi_rr = u_rr291292inv_rho_ll = 1 / rho_ll293inv_rho_rr = 1 / rho_rr294295v1_ll = rho_v1_ll * inv_rho_ll296v2_ll = rho_v2_ll * inv_rho_ll297v3_ll = rho_v3_ll * inv_rho_ll298v1_rr = rho_v1_rr * inv_rho_rr299v2_rr = rho_v2_rr * inv_rho_rr300v3_rr = rho_v3_rr * inv_rho_rr301v_dot_B_ll = v1_ll * B1_ll + v2_ll * B2_ll + v3_ll * B3_ll302v_dot_B_rr = v1_rr * B1_rr + v2_rr * B2_rr + v3_rr * B3_rr303304v_dot_n_ll = v1_ll * normal_direction[1] + v2_ll * normal_direction[2]305B_dot_n_rr = B1_rr * normal_direction[1] +306B2_rr * normal_direction[2]307308B_dot_n_ll = B1_ll * normal_direction[1] +309B2_ll * normal_direction[2]310v_dot_n_rr = v1_rr * normal_direction[1] + v2_rr * normal_direction[2]311# Powell nonconservative term: (0, B_1, B_2, B_3, v⋅B, v_1, v_2, v_3, 0)312# Galilean nonconservative term: (0, 0, 0, 0, ψ v_{1,2}, 0, 0, 0, v_{1,2})313g_left = SVector(0,314B1_ll * B_dot_n_rr,315B2_ll * B_dot_n_rr,316B3_ll * B_dot_n_rr,317v_dot_B_ll * B_dot_n_rr + v_dot_n_ll * psi_ll * psi_rr,318v1_ll * B_dot_n_rr,319v2_ll * B_dot_n_rr,320v3_ll * B_dot_n_rr,321v_dot_n_ll * psi_rr)322323g_right = SVector(0,324B1_rr * B_dot_n_ll,325B2_rr * B_dot_n_ll,326B3_rr * B_dot_n_ll,327v_dot_B_rr * B_dot_n_ll + v_dot_n_rr * psi_rr * psi_ll,328v1_rr * B_dot_n_ll,329v2_rr * B_dot_n_ll,330v3_rr * B_dot_n_ll,331v_dot_n_rr * psi_ll)332flux_left = f + 0.5f0 * g_left333flux_right = f + 0.5f0 * g_right334return flux_left, flux_right335end336337@inline Trixi.combine_conservative_and_nonconservative_fluxes(::typeof(flux_lax_friedrichs_nonconservative_powell),338equations::IdealGlmMhdEquations2D) = Trixi.True()339340@inline function (boundary_condition::BoundaryConditionDirichlet)(u_inner,341normal_direction::AbstractVector,342x, t,343surface_flux_function::typeof(flux_lax_friedrichs_nonconservative_powell),344equations)345346# get the external value of the solution347u_boundary = boundary_condition.boundary_value_function(x, t, equations)348349# Calculate boundary flux350flux, _ = surface_flux_function(u_inner, u_boundary, normal_direction,351equations)352return flux353end354355trixi_include(@__MODULE__,356joinpath(EXAMPLES_DIR, "p4est_2d_dgsem", "elixir_mhd_rotor.jl"),357surface_flux = flux_lax_friedrichs_nonconservative_powell,358volume_integral = VolumeIntegralFluxDifferencing(flux_hindenlang_gassner_nonconservative_powell),359amr_callback = nothing, tspan = (0.0, 0.001))360361u_ode_specialized = copy(sol.u[end])362@test u_ode_specialized ≈ u_ode363end364end365366# Clean up afterwards: delete Trixi.jl output directory367@test_nowarn rm(outdir, recursive = true)368369end #module370371372