Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
trixi-framework
GitHub Repository: trixi-framework/Trixi.jl
Path: blob/main/src/solvers/dgsem_tree/containers.jl
5591 views
1
# By default, Julia/LLVM does not use fused multiply-add operations (FMAs).
2
# Since these FMAs can increase the performance of many numerical algorithms,
3
# we need to opt-in explicitly.
4
# See https://ranocha.de/blog/Optimizing_EC_Trixi for further details.
5
@muladd begin
6
#! format: noindent
7
8
# Dimension independent code related to containers of the DG solver
9
# with the mesh type TreeMesh
10
11
abstract type AbstractTreeElementContainer <: AbstractElementContainer end
12
13
# Return number of elements
14
@inline nelements(elements::AbstractTreeElementContainer) = length(elements.cell_ids)
15
# Return number of element nodes
16
@inline nnodes(elements::AbstractTreeElementContainer) = size(elements.node_coordinates,
17
2)
18
@inline nvariables(elements::AbstractTreeElementContainer) = size(elements.surface_flux_values,
19
1)
20
# TODO: Taal performance, 1:nelements(elements) vs. Base.OneTo(nelements(elements))
21
"""
22
eachelement(elements::AbstractTreeElementContainer)
23
24
Return an iterator over the indices that specify the location in relevant data structures
25
for the elements in `elements`.
26
In particular, not the elements themselves are returned.
27
"""
28
@inline eachelement(elements::AbstractTreeElementContainer) = Base.OneTo(nelements(elements))
29
30
@inline Base.real(elements::AbstractTreeElementContainer) = eltype(elements.node_coordinates)
31
@inline Base.eltype(elements::AbstractTreeElementContainer) = eltype(elements.surface_flux_values)
32
33
abstract type AbstractTreeInterfaceContainer <: AbstractInterfaceContainer end
34
35
# Return number of interfaces
36
@inline ninterfaces(interfaces::AbstractTreeInterfaceContainer) = length(interfaces.orientations)
37
# Return number of interface nodes for 2D and 3D. For 1D hard-coded to 1 interface node.
38
@inline nnodes(interfaces::AbstractTreeInterfaceContainer) = size(interfaces.u, 3)
39
# Return number of equation variables
40
@inline nvariables(interfaces::AbstractTreeInterfaceContainer) = size(interfaces.u, 2)
41
42
abstract type AbstractTreeMPIInterfaceContainer <: AbstractMPIInterfaceContainer end
43
44
# Return number of interfaces
45
@inline function nmpiinterfaces(mpi_interfaces::AbstractTreeMPIInterfaceContainer)
46
return length(mpi_interfaces.orientations)
47
end
48
# Return number of interface nodes for 2D and 3D. For 1D hard-coded to 1 interface node.
49
@inline nnodes(interfaces::AbstractTreeMPIInterfaceContainer) = size(interfaces.u, 3)
50
# Return number of equation variables
51
@inline nvariables(interfaces::AbstractTreeMPIInterfaceContainer) = size(interfaces.u,
52
2)
53
54
abstract type AbstractTreeBoundaryContainer <: AbstractBoundaryContainer end
55
56
# Return number of boundaries
57
@inline nboundaries(boundaries::AbstractTreeBoundaryContainer) = length(boundaries.orientations)
58
# Return number of boundary nodes for 2D and 3D. For 1D hard-coded to 1 boundary node.
59
@inline nnodes(boundaries::AbstractTreeBoundaryContainer) = size(boundaries.u, 3)
60
# Return number of equation variables
61
@inline nvariables(boundaries::AbstractTreeBoundaryContainer) = size(boundaries.u, 2)
62
63
abstract type AbstractTreeL2MortarContainer <: AbstractMortarContainer end
64
65
# Return number of L2 mortars
66
@inline nmortars(l2mortars::AbstractTreeL2MortarContainer) = length(l2mortars.orientations)
67
68
abstract type AbstractTreeL2MPIMortarContainer <: AbstractMPIMortarContainer end
69
70
# Return number of L2 mortars
71
@inline function nmpimortars(mpi_l2mortars::AbstractTreeL2MPIMortarContainer)
72
return length(mpi_l2mortars.orientations)
73
end
74
75
# Container data structure (structure-of-arrays style) for variables used for IDP limiting
76
mutable struct ContainerSubcellLimiterIDP{NDIMS, uEltype <: Real, NDIMSP1} <:
77
AbstractContainer
78
alpha::Array{uEltype, NDIMSP1} # [i, j, k, element]
79
variable_bounds::Dict{Symbol, Array{uEltype, NDIMSP1}}
80
# internal `resize!`able storage
81
_alpha::Vector{uEltype}
82
_variable_bounds::Dict{Symbol, Vector{uEltype}}
83
end
84
85
function ContainerSubcellLimiterIDP{NDIMS, uEltype}(capacity::Integer, n_nodes,
86
bound_keys) where {NDIMS,
87
uEltype <: Real}
88
nan_uEltype = convert(uEltype, NaN)
89
90
# Initialize fields with defaults
91
_alpha = fill(nan_uEltype, prod(ntuple(_ -> n_nodes, NDIMS)) * capacity)
92
alpha = unsafe_wrap(Array, pointer(_alpha),
93
(ntuple(_ -> n_nodes, NDIMS)..., capacity))
94
95
_variable_bounds = Dict{Symbol, Vector{uEltype}}()
96
variable_bounds = Dict{Symbol, Array{uEltype, NDIMS + 1}}()
97
for key in bound_keys
98
_variable_bounds[key] = fill(nan_uEltype,
99
prod(ntuple(_ -> n_nodes, NDIMS)) * capacity)
100
variable_bounds[key] = unsafe_wrap(Array, pointer(_variable_bounds[key]),
101
(ntuple(_ -> n_nodes, NDIMS)..., capacity))
102
end
103
104
return ContainerSubcellLimiterIDP{NDIMS, uEltype, NDIMS + 1}(alpha,
105
variable_bounds,
106
_alpha,
107
_variable_bounds)
108
end
109
110
@inline nnodes(container::ContainerSubcellLimiterIDP) = size(container.alpha, 1)
111
@inline Base.ndims(::ContainerSubcellLimiterIDP{NDIMS}) where {NDIMS} = NDIMS
112
113
# Only one-dimensional `Array`s are `resize!`able in Julia.
114
# Hence, we use `Vector`s as internal storage and `resize!`
115
# them whenever needed. Then, we reuse the same memory by
116
# `unsafe_wrap`ping multi-dimensional `Array`s around the
117
# internal storage.
118
function Base.resize!(container::ContainerSubcellLimiterIDP, capacity)
119
n_nodes = nnodes(container)
120
n_dims = ndims(container)
121
122
(; _alpha) = container
123
resize!(_alpha, prod(ntuple(_ -> n_nodes, n_dims)) * capacity)
124
container.alpha = unsafe_wrap(Array, pointer(_alpha),
125
(ntuple(_ -> n_nodes, n_dims)..., capacity))
126
container.alpha .= convert(eltype(container.alpha), NaN)
127
128
(; _variable_bounds) = container
129
for (key, _) in _variable_bounds
130
resize!(_variable_bounds[key], prod(ntuple(_ -> n_nodes, n_dims)) * capacity)
131
container.variable_bounds[key] = unsafe_wrap(Array,
132
pointer(_variable_bounds[key]),
133
(ntuple(_ -> n_nodes, n_dims)...,
134
capacity))
135
end
136
137
return nothing
138
end
139
140
abstract type AbstractContainerAntidiffusiveFlux <: AbstractContainer end
141
nvariables(fluxes::AbstractContainerAntidiffusiveFlux) = size(fluxes.antidiffusive_flux1_L,
142
1)
143
nnodes(fluxes::AbstractContainerAntidiffusiveFlux) = size(fluxes.antidiffusive_flux1_L,
144
3)
145
146
# Dimension-specific implementations
147
include("containers_1d.jl")
148
include("containers_2d.jl")
149
include("containers_3d.jl")
150
end # @muladd
151
152