Skip to content
Open
Show file tree
Hide file tree
Changes from 57 commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
3d24fb8
adapt_structure
benegee Jun 25, 2026
5463667
Merge branch 'main' into bg/adapt-mpicache
benegee Jun 26, 2026
072b754
prolong2mpiinterfaces
benegee Jun 26, 2026
ed8fc47
integrate_via_indices 2D
benegee Sep 2, 2026
69cdbb8
Merge branch 'main' into bg/adapt-mpicache
benegee Sep 8, 2026
78ccbda
move to CPU as in non-parallel case
benegee Sep 14, 2026
cb69596
Merge branch 'main' into bg/adapt-mpicache
benegee Sep 14, 2026
a737166
P4estMeshParallel{2} GPU support
benegee Sep 14, 2026
b935ced
rhs_hyperbolic for parallel GPU
benegee Sep 15, 2026
1f9d981
remove reset du
benegee Sep 15, 2026
7f1ba04
fmt
benegee Sep 15, 2026
a48f151
fix bug
benegee Sep 15, 2026
5fcbd10
use trixi_timeit_ext
benegee Sep 15, 2026
18df67e
avoid kernel launches with zero size
benegee Sep 15, 2026
cc61eba
missed line
benegee Sep 15, 2026
84abfff
removed parallel meshes
benegee Sep 15, 2026
8ea605b
try to set up test with mpi and kernelabstractions
benegee Sep 15, 2026
d317322
add kernelabstractions_mpi to SPECIAL_PROCESS_SUITES
benegee Sep 18, 2026
0d31cc5
backend arguments
benegee Sep 18, 2026
429de3d
typo
benegee Sep 21, 2026
909db1b
Merge branch 'main' into bg/adapt-mpicache
benegee Sep 21, 2026
cbccef7
another backend argument
benegee Sep 21, 2026
daaa898
another one
benegee Sep 21, 2026
36b9235
added NEWS.md
benegee Sep 22, 2026
5200c40
unpack
benegee Sep 23, 2026
439db9f
Merge branch 'bg/adapt-mpicache' of github.com:trixi-framework/Trixi.…
benegee Sep 23, 2026
40c8f43
Merge branch 'main' into bg/adapt-mpicache
benegee Sep 23, 2026
cfeef65
Merge branch 'main' into bg/adapt-mpicache
benegee Oct 2, 2026
596ad55
fmt
benegee Oct 2, 2026
15d9fb5
Merge branch 'main' into bg/adapt-mpicache
benegee Oct 12, 2026
ae83c14
missed in merge
benegee Oct 12, 2026
0a6378b
add inbounds=true to kernels
benegee Oct 12, 2026
35e2c51
to the docs as well
benegee Oct 12, 2026
ada4452
use Base.@propagate_inbounds
benegee Oct 12, 2026
1fbb6e7
fix
benegee Oct 12, 2026
5c67317
fmt
benegee Oct 12, 2026
b43c80e
Merge branch 'main' into bg/multi-gpu-3d
benegee Oct 13, 2026
62796e1
3D
benegee Oct 13, 2026
3d3fb31
missed file
benegee Oct 13, 2026
d2cae2c
Merge branch 'main' into bg/multi-gpu-3d
benegee Oct 17, 2026
3979a79
fix merge
benegee Oct 17, 2026
81aa553
revert to main
benegee Oct 17, 2026
297eabe
docs
benegee Oct 19, 2026
26e6ebd
dimension agnostic start_mpi_send! and finish_mpi_receive!
benegee Oct 19, 2026
dbd634a
fix merge
benegee Oct 19, 2026
9d079c3
tests
benegee Oct 19, 2026
d0c3b7b
revert
benegee Oct 19, 2026
084085e
moved
benegee Oct 19, 2026
cbf6f68
align with 2D
benegee Oct 19, 2026
8b002a9
fmt
benegee Oct 19, 2026
7e4736e
Merge branch 'main' into bg/multi-gpu-3d
benegee Oct 19, 2026
0bed854
adapt reference values
benegee Oct 19, 2026
454a90e
no allocation test
benegee Oct 19, 2026
cbe8177
Merge branch 'main' into bg/multi-gpu-3d
benegee Oct 20, 2026
458232f
Merge branch 'main' into bg/multi-gpu-3d
benegee Nov 4, 2026
e1609c1
address review comments
benegee Nov 4, 2026
94811d8
Merge branch 'main' into bg/multi-gpu-3d
ranocha Nov 5, 2026
4a401cc
Update src/callbacks_step/analysis_dg3d_parallel.jl
benegee Nov 5, 2026
5783cbe
fixup
benegee Nov 5, 2026
61e74e1
dimension agnostic rhs_hyperbolic
benegee Nov 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ for human readability.
Makie, and `trixiheatmap` accepts the attributes of `Makie.mesh`. Plots of slices of
3D `DGMultiMesh` solutions and plots of 1D `DGMultiMesh` solutions now show the
correct axis labels ([#3405]).
- Added multi-GPU support for 2D `P4estMesh`es, i.e., GPU computations with MPI
([#3240]). A local CUDA/ROCm-aware MPI installation is required. For configuration, see
- Added multi-GPU support for 2D and 3D `P4estMesh`es, i.e., GPU computations with MPI
([#3240], [#3364]). A local CUDA/ROCm-aware MPI installation is required.
For configuration, see
[Parallelization](https://trixi-framework.org/TrixiDocumentation/stable/parallelization/#parallel_system_MPI)
in the docs. Currently, only hyperbolic problems (no `SemidiscretizationHyperbolicParabolic`)
on conforming meshes (no mortars, thus also no AMR) are supported.
Expand Down
10 changes: 5 additions & 5 deletions docs/src/heterogeneous.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,12 @@ are supported on conforming (non-adaptive) `P4estMesh{2}`s and `P4estMesh{3}`s a
see, e.g., `examples/p4est_2d_dgsem/elixir_navierstokes_lid_driven_cavity.jl` and
`examples/p4est_3d_dgsem/elixir_navierstokes_convergence.jl`.

Hyperbolic problems on conforming `P4estMesh`es in 2D can also be run on multiple GPUs
with MPI, using one MPI rank per GPU. The setup is the same as above, and the elixir is
started with MPI as described in [Parallelization](@ref parallel_system_MPI).
Hyperbolic problems on conforming `P4estMesh`es in 2D and 3D can also be run on
multiple GPUs with MPI, using one MPI rank per GPU. The setup is the same as above, and
the elixir is started with MPI as described in [Parallelization](@ref parallel_system_MPI).
This requires a local CUDA/ROCm-aware MPI installation, since the MPI buffers are stored
on the GPU and passed directly to MPI. Mixed hyperbolic-parabolic problems, 3D meshes,
and non-conforming meshes (mortars, AMR) are not supported with multiple GPUs yet.
on the GPU and passed directly to MPI. Mixed hyperbolic-parabolic problems and
non-conforming meshes (mortars, AMR) are not supported with multiple GPUs yet.
See the section on
[GPU-aware MPI support](https://juliaparallel.org/MPI.jl/stable/usage/#GPU-aware-MPI-support)
in the MPI.jl documentation for details, including example scripts such as
Expand Down
50 changes: 49 additions & 1 deletion src/callbacks_step/analysis_dg3d_parallel.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ function calc_error_norms(func, u, t, analyzer,
@unpack node_coordinates, inverse_jacobian = cache.elements
@unpack u_local, u_tmp1, u_tmp2, x_local, x_tmp1, x_tmp2, jacobian_local, jacobian_tmp1, jacobian_tmp2 = cache_analysis

# Calculate error norms on the CPU, to ensure the order of summation is the same.
if trixi_backend(u) !== nothing
node_coordinates = Array(node_coordinates)
inverse_jacobian = Array(inverse_jacobian)
u = Array(u)
end

# Set up data structures
l2_error = zero_return_type(func, SVector{nvariables(equations), eltype(u)},
typeof(equations))
Expand Down Expand Up @@ -50,7 +57,7 @@ function calc_error_norms(func, u, t, analyzer,
return reduce_error_norms_mpi(l2_error, linf_error, volume)
end

function integrate_via_indices(func::Func, u,
function integrate_via_indices(func::Func, backend::Nothing, u,
mesh::Union{P4estMeshParallel{3}, T8codeMeshParallel{3}},
equations,
dg::DGSEM, cache, args...; normalize = true) where {Func}
Expand All @@ -74,4 +81,45 @@ function integrate_via_indices(func::Func, u,

return reduce_integral_and_volume_mpi(integral, volume, normalize)
end

function integrate_via_indices(func::Func, backend::Backend, u,
mesh::Union{P4estMeshParallel{3}, T8codeMeshParallel{3}},
equations,
dg::DGSEM, cache, args...; normalize = true) where {Func}
@unpack weights = dg.basis
@unpack inverse_jacobian = cache.elements

function local_plus((integral, total_volume), (integral_element, volume_element))
return (integral + integral_element, total_volume + volume_element)
end

# `func(u, 1,1,1,1, equations, dg, args...)` might access GPU memory
# so we have to rely on the compiler to correctly infer the type of the integral here.
# TODO: Technically we need device_promote_op here that "infers" the function within the context of the GPU.
integral0 = zero(Base.promote_op(func, typeof(u), Int, Int, Int, Int,
typeof(equations), typeof(dg),
map(typeof, args)...))
Comment thread
benegee marked this conversation as resolved.
Resolved
volume0 = zero(eltype(weights)) * zero(eltype(inverse_jacobian))
init = neutral = (integral0, volume0)

# Use quadrature to numerically integrate over entire domain
num_elements = nelements(dg, cache)
integral, volume = AcceleratedKernels.mapreduce(local_plus, 1:num_elements,
backend; init,
neutral) do element
# Initialize integral with zeros of the right shape
local_integral, local_total_volume = neutral

for k in eachnode(dg), j in eachnode(dg), i in eachnode(dg)
volume_jacobian = abs(inv(inverse_jacobian[i, j, k, element]))
local_integral += volume_jacobian * weights[i] * weights[j] * weights[k] *
func(u, i, j, k, element, equations, dg, args...)
local_total_volume += volume_jacobian * weights[i] * weights[j] * weights[k]
end

return (local_integral, local_total_volume)
end

return reduce_integral_and_volume_mpi(integral, volume, normalize)
end
end # @muladd
36 changes: 0 additions & 36 deletions src/solvers/dgsem_p4est/dg_2d_parallel_gpu.jl
Original file line number Diff line number Diff line change
Expand Up @@ -197,42 +197,6 @@ Base.@propagate_inbounds function mpi_buffer_node_offset(mpi_interfaces_buffer_o
return mpi_interfaces_buffer_offsets[interface] + (i - 1) * nvariables(equations)
end

Base.@propagate_inbounds function get_mpi_buffer_node_vars(mpi_buffer, equations,
offset)
# Explicit bounds check, which can be removed by calling this function with `@inbounds`
@boundscheck checkbounds(mpi_buffer, offset .+ eachvariable(equations))
# Assume inbounds access now
return SVector(ntuple(@inline(v->@inbounds mpi_buffer[offset + v]),
Val(nvariables(equations))))
end

# The MPI send buffer is filled in `prolong2mpiinterfaces!`, and the kernels have
# finished when this is called, see `rhs_hyperbolic!`.
function start_mpi_send!(backend::Backend, mpi_cache::P4estMPICache,
mesh::Union{P4estMeshParallel{2}, T8codeMeshParallel{2}},
equations, dg, cache)
# TODO GPU: MPI mortars are not yet implemented
@assert isempty(eachmpimortar(dg, cache)) "MPI mortars are not yet supported on GPU backends"

for (index, rank) in enumerate(mpi_cache.mpi_neighbor_ranks)
send_buffer = mpi_buffer(get_mpi_send_buffer(mpi_cache, index))
mpi_cache.mpi_send_requests[index] = MPI.Isend(send_buffer, rank, mpi_rank(),
mpi_comm())
end

return nothing
end

# The received data is not unpacked but read directly from the MPI receive buffer
# by `calc_mpi_interface_flux!`. Thus, we can wait for all data at once.
function finish_mpi_receive!(backend::Backend, mpi_cache::P4estMPICache,
mesh::Union{P4estMeshParallel{2}, T8codeMeshParallel{2}},
equations, dg, cache)
MPI.Waitall(mpi_cache.mpi_recv_requests)

return nothing
end

# Compute the surface fluxes at all MPI interfaces. In contrast to the CPU version,
# the local data is taken directly from `u` and the remote data directly from the
# MPI receive buffer.
Expand Down
Loading
Loading