Path: blob/main/test/test_performance_specializations_3d.jl
5582 views
module TestPerformanceSpecializations3D12using 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 3D" begin15#! format: noindent1617@timed_testset "TreeMesh3D, flux_shima_etal_turbo" begin18trixi_include(@__MODULE__,19joinpath(EXAMPLES_DIR, "tree_3d_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 "TreeMesh3D, flux_ranocha_turbo" begin58trixi_include(@__MODULE__,59joinpath(EXAMPLES_DIR, "tree_3d_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 "StructuredMesh3D, flux_shima_etal_turbo" begin97trixi_include(@__MODULE__,98joinpath(EXAMPLES_DIR, "structured_3d_dgsem", "elixir_euler_ec.jl"),99cells_per_dimension = (1, 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 "StructuredMesh3D, flux_ranocha_turbo" begin137trixi_include(@__MODULE__,138joinpath(EXAMPLES_DIR, "structured_3d_dgsem", "elixir_euler_ec.jl"),139cells_per_dimension = (1, 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 "P4estMesh3D, combine_conservative_and_nonconservative_fluxes" begin176trixi_include(@__MODULE__,177joinpath(EXAMPLES_DIR, "p4est_3d_dgsem",178"elixir_mhd_alfven_wave_nonperiodic.jl"),179volume_integral = VolumeIntegralFluxDifferencing((flux_hindenlang_gassner,180flux_nonconservative_powell)),181tspan = (0.0, 0.1))182u_ode = copy(sol.u[end])183184@muladd @inline function flux_hindenlang_gassner_nonconservative_powell(u_ll, u_rr,185normal_direction::AbstractVector,186equations::IdealGlmMhdEquations3D)187# Unpack left and right states188rho_ll, v1_ll, v2_ll, v3_ll, p_ll, B1_ll, B2_ll, B3_ll, psi_ll = cons2prim(u_ll,189equations)190rho_rr, v1_rr, v2_rr, v3_rr, p_rr, B1_rr, B2_rr, B3_rr, psi_rr = cons2prim(u_rr,191equations)192v_dot_n_ll = v1_ll * normal_direction[1] + v2_ll * normal_direction[2] +193v3_ll * normal_direction[3]194v_dot_n_rr = v1_rr * normal_direction[1] + v2_rr * normal_direction[2] +195v3_rr * normal_direction[3]196B_dot_n_ll = B1_ll * normal_direction[1] + B2_ll * normal_direction[2] +197B3_ll * normal_direction[3]198B_dot_n_rr = B1_rr * normal_direction[1] + B2_rr * normal_direction[2] +199B3_rr * normal_direction[3]200201# Compute the necessary mean values needed for either direction202rho_mean = Trixi.ln_mean(rho_ll, rho_rr)203# Algebraically equivalent to `inv_ln_mean(rho_ll / p_ll, rho_rr / p_rr)`204# in exact arithmetic since205# log((ϱₗ/pₗ) / (ϱᵣ/pᵣ)) / (ϱₗ/pₗ - ϱᵣ/pᵣ)206# = pₗ pᵣ log((ϱₗ pᵣ) / (ϱᵣ pₗ)) / (ϱₗ pᵣ - ϱᵣ pₗ)207inv_rho_p_mean = p_ll * p_rr * Trixi.inv_ln_mean(rho_ll * p_rr, rho_rr * p_ll)208v1_avg = 0.5f0 * (v1_ll + v1_rr)209v2_avg = 0.5f0 * (v2_ll + v2_rr)210v3_avg = 0.5f0 * (v3_ll + v3_rr)211p_avg = 0.5f0 * (p_ll + p_rr)212psi_avg = 0.5f0 * (psi_ll + psi_rr)213velocity_square_avg = 0.5f0 * (v1_ll * v1_rr + v2_ll * v2_rr + v3_ll * v3_rr)214magnetic_square_avg = 0.5f0 * (B1_ll * B1_rr + B2_ll * B2_rr + B3_ll * B3_rr)215216# Calculate fluxes depending on normal_direction217f1 = rho_mean * 0.5f0 * (v_dot_n_ll + v_dot_n_rr)218f2 = (f1 * v1_avg + (p_avg + magnetic_square_avg) * normal_direction[1]219-2200.5f0 * (B_dot_n_ll * B1_rr + B_dot_n_rr * B1_ll))221f3 = (f1 * v2_avg + (p_avg + magnetic_square_avg) * normal_direction[2]222-2230.5f0 * (B_dot_n_ll * B2_rr + B_dot_n_rr * B2_ll))224f4 = (f1 * v3_avg + (p_avg + magnetic_square_avg) * normal_direction[3]225-2260.5f0 * (B_dot_n_ll * B3_rr + B_dot_n_rr * B3_ll))227#f5 below228f6 = (equations.c_h * psi_avg * normal_direction[1]229+2300.5f0 * (v_dot_n_ll * B1_ll - v1_ll * B_dot_n_ll +231v_dot_n_rr * B1_rr - v1_rr * B_dot_n_rr))232f7 = (equations.c_h * psi_avg * normal_direction[2]233+2340.5f0 * (v_dot_n_ll * B2_ll - v2_ll * B_dot_n_ll +235v_dot_n_rr * B2_rr - v2_rr * B_dot_n_rr))236f8 = (equations.c_h * psi_avg * normal_direction[3]237+2380.5f0 * (v_dot_n_ll * B3_ll - v3_ll * B_dot_n_ll +239v_dot_n_rr * B3_rr - v3_rr * B_dot_n_rr))240f9 = equations.c_h * 0.5f0 * (B_dot_n_ll + B_dot_n_rr)241# total energy flux is complicated and involves the previous components242f5 = (f1 *243(velocity_square_avg + inv_rho_p_mean * equations.inv_gamma_minus_one)244+2450.5f0 * (+p_ll * v_dot_n_rr + p_rr * v_dot_n_ll246+ (v_dot_n_ll * B1_ll * B1_rr + v_dot_n_rr * B1_rr * B1_ll)247+ (v_dot_n_ll * B2_ll * B2_rr + v_dot_n_rr * B2_rr * B2_ll)248+ (v_dot_n_ll * B3_ll * B3_rr + v_dot_n_rr * B3_rr * B3_ll)249-250(v1_ll * B_dot_n_ll * B1_rr + v1_rr * B_dot_n_rr * B1_ll)251-252(v2_ll * B_dot_n_ll * B2_rr + v2_rr * B_dot_n_rr * B2_ll)253-254(v3_ll * B_dot_n_ll * B3_rr + v3_rr * B_dot_n_rr * B3_ll)255+256equations.c_h * (B_dot_n_ll * psi_rr + B_dot_n_rr * psi_ll)))257258v_dot_B_ll = v1_ll * B1_ll + v2_ll * B2_ll + v3_ll * B3_ll259260v_dot_B_rr = v1_rr * B1_rr + v2_rr * B2_rr + v3_rr * B3_rr261f = SVector(f1, f2, f3, f4, f5, f6, f7, f8, f9)262# Powell nonconservative term: (0, B_1, B_2, B_3, v⋅B, v_1, v_2, v_3, 0)263# Galilean nonconservative term: (0, 0, 0, 0, ψ v_{1,2,3}, 0, 0, 0, v_{1,2,3})264g_left = SVector(0,265B1_ll * B_dot_n_rr,266B2_ll * B_dot_n_rr,267B3_ll * B_dot_n_rr,268v_dot_B_ll * B_dot_n_rr + v_dot_n_ll * psi_ll * psi_rr,269v1_ll * B_dot_n_rr,270v2_ll * B_dot_n_rr,271v3_ll * B_dot_n_rr,272v_dot_n_ll * psi_rr)273274g_right = SVector(0,275B1_rr * B_dot_n_ll,276B2_rr * B_dot_n_ll,277B3_rr * B_dot_n_ll,278v_dot_B_rr * B_dot_n_ll + v_dot_n_rr * psi_rr * psi_ll,279v1_rr * B_dot_n_ll,280v2_rr * B_dot_n_ll,281v3_rr * B_dot_n_ll,282v_dot_n_rr * psi_ll)283flux_left = f + 0.5f0 * g_left284flux_right = f + 0.5f0 * g_right285return flux_left, flux_right286end287288@inline Trixi.combine_conservative_and_nonconservative_fluxes(::typeof(flux_hindenlang_gassner_nonconservative_powell),289equations::IdealGlmMhdEquations3D) = Trixi.True()290291@muladd @inline function flux_hlle_nonconservative_powell(u_ll, u_rr,292normal_direction::AbstractVector,293equations::IdealGlmMhdEquations3D)294f = flux_hlle(u_ll, u_rr, normal_direction, equations)295296rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, rho_e_total_ll, B1_ll, B2_ll, B3_ll, psi_ll = u_ll297rho_rr, rho_v1_rr, rho_v2_rr, rho_v3_rr, rho_e_total_rr, B1_rr, B2_rr, B3_rr, psi_rr = u_rr298299v1_ll = rho_v1_ll / rho_ll300v2_ll = rho_v2_ll / rho_ll301v3_ll = rho_v3_ll / rho_ll302v1_rr = rho_v1_rr / rho_rr303v2_rr = rho_v2_rr / rho_rr304v3_rr = rho_v3_rr / rho_rr305v_dot_B_ll = v1_ll * B1_ll + v2_ll * B2_ll + v3_ll * B3_ll306v_dot_B_rr = v1_rr * B1_rr + v2_rr * B2_rr + v3_rr * B3_rr307308v_dot_n_ll = v1_ll * normal_direction[1] + v2_ll * normal_direction[2] +309v3_ll * normal_direction[3]310B_dot_n_rr = B1_rr * normal_direction[1] +311B2_rr * normal_direction[2] +312B3_rr * normal_direction[3]313v_dot_n_rr = v1_rr * normal_direction[1] + v2_rr * normal_direction[2] +314v3_rr * normal_direction[3]315B_dot_n_ll = B1_ll * normal_direction[1] +316B2_ll * normal_direction[2] +317B3_ll * normal_direction[3]318319# Powell nonconservative term: (0, B_1, B_2, B_3, v⋅B, v_1, v_2, v_3, 0)320# Galilean nonconservative term: (0, 0, 0, 0, ψ v_{1,2,3}, 0, 0, 0, v_{1,2,3})321g_left = SVector(0,322B1_ll * B_dot_n_rr,323B2_ll * B_dot_n_rr,324B3_ll * B_dot_n_rr,325v_dot_B_ll * B_dot_n_rr + v_dot_n_ll * psi_ll * psi_rr,326v1_ll * B_dot_n_rr,327v2_ll * B_dot_n_rr,328v3_ll * B_dot_n_rr,329v_dot_n_ll * psi_rr)330331g_right = SVector(0,332B1_rr * B_dot_n_ll,333B2_rr * B_dot_n_ll,334B3_rr * B_dot_n_ll,335v_dot_B_rr * B_dot_n_ll + v_dot_n_rr * psi_rr * psi_ll,336v1_rr * B_dot_n_ll,337v2_rr * B_dot_n_ll,338v3_rr * B_dot_n_ll,339v_dot_n_rr * psi_ll)340flux_left = f + 0.5f0 * g_left341flux_right = f + 0.5f0 * g_right342343return flux_left, flux_right344end345346@inline Trixi.combine_conservative_and_nonconservative_fluxes(::typeof(flux_hlle_nonconservative_powell),347equations::IdealGlmMhdEquations3D) = Trixi.True()348349@inline function (boundary_condition::BoundaryConditionDirichlet)(u_inner,350normal_direction::AbstractVector,351x, t,352surface_flux_function::typeof(flux_hlle_nonconservative_powell),353equations)354355# get the external value of the solution356u_boundary = boundary_condition.boundary_value_function(x, t, equations)357358# Calculate boundary flux359flux, _ = surface_flux_function(u_inner, u_boundary, normal_direction,360equations)361return flux362end363364trixi_include(@__MODULE__,365joinpath(EXAMPLES_DIR, "p4est_3d_dgsem",366"elixir_mhd_alfven_wave_nonperiodic.jl"),367surface_flux = flux_hlle_nonconservative_powell,368volume_integral = VolumeIntegralFluxDifferencing(flux_hindenlang_gassner_nonconservative_powell),369tspan = (0.0, 0.1))370371u_ode_specialized = copy(sol.u[end])372@test u_ode_specialized ≈ u_ode373end374end375376# Clean up afterwards: delete Trixi.jl output directory377@test_nowarn rm(outdir, recursive = true)378379end #module380381382