Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
trixi-framework
GitHub Repository: trixi-framework/Trixi.jl
Path: blob/main/src/solvers/dgsem_structured/dg.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
# This method is called when a SemidiscretizationHyperbolic is constructed.
9
# It constructs the basic `cache` used throughout the simulation to compute
10
# the RHS etc.
11
function create_cache(mesh::Union{StructuredMesh, StructuredMeshView},
12
equations::AbstractEquations, dg::DG, ::Any,
13
::Type{uEltype}) where {uEltype <: Real}
14
elements = init_elements(mesh, equations, dg.basis, uEltype)
15
16
# Container cache
17
cache = (; elements)
18
19
# Add Volume-Integral cache
20
cache = (; cache...,
21
create_cache(mesh, equations, dg.volume_integral, dg, cache, uEltype)...)
22
23
return cache
24
end
25
26
# Extract contravariant vector Ja^i (i = index) as SVector
27
@inline function get_contravariant_vector(index, contravariant_vectors, indices...)
28
return SVector(ntuple(@inline(dim->contravariant_vectors[dim, index, indices...]),
29
Val(ndims(contravariant_vectors) - 3)))
30
end
31
32
# Dimension agnostic, i.e., valid for all 1D, 2D, and 3D `StructuredMesh`es.
33
function calc_boundary_flux!(cache, t, boundary_condition::BoundaryConditionPeriodic,
34
mesh::StructuredMesh, equations, surface_integral,
35
dg::DG)
36
@assert isperiodic(mesh)
37
38
return nothing
39
end
40
41
function rhs!(du, u, t,
42
mesh::Union{StructuredMesh, StructuredMeshView{2}}, equations,
43
boundary_conditions, source_terms::Source,
44
dg::DG, cache) where {Source}
45
backend = trixi_backend(u)
46
47
# Reset du
48
@trixi_timeit timer() "reset ∂u/∂t" set_zero!(du, dg, cache)
49
50
# Calculate volume integral
51
@trixi_timeit timer() "volume integral" begin
52
calc_volume_integral!(backend, du, u, mesh,
53
have_nonconservative_terms(equations), equations,
54
dg.volume_integral, dg, cache)
55
end
56
57
# Prolong solution to interfaces
58
@trixi_timeit timer() "prolong2interfaces" begin
59
prolong2interfaces!(cache, u, mesh, equations, dg)
60
end
61
62
# Calculate interface fluxes
63
@trixi_timeit timer() "interface flux" begin
64
calc_interface_flux!(cache.elements.surface_flux_values, mesh,
65
have_nonconservative_terms(equations), equations,
66
dg.surface_integral, dg, cache)
67
end
68
69
# `prolong2boundaries!` is not required for `StructuredMesh` since boundary values
70
# are stored in the interface datastructure (`interfaces_u`),
71
# so we can directly calculate the boundary fluxes without prolongation.
72
73
# Calculate boundary fluxes
74
@trixi_timeit timer() "boundary flux" begin
75
calc_boundary_flux!(cache, t, boundary_conditions, mesh, equations,
76
dg.surface_integral, dg)
77
end
78
79
# Calculate surface integrals
80
@trixi_timeit timer() "surface integral" begin
81
calc_surface_integral!(backend, du, u, mesh, equations,
82
dg.surface_integral, dg, cache)
83
end
84
85
# Apply Jacobian from mapping to reference element
86
@trixi_timeit timer() "Jacobian" apply_jacobian!(backend, du, mesh, equations, dg,
87
cache)
88
89
# Calculate source terms
90
@trixi_timeit timer() "source terms" begin
91
calc_sources!(du, u, t, source_terms, equations, dg, cache)
92
end
93
94
return nothing
95
end
96
97
@inline function calc_boundary_flux_by_direction!(surface_flux_values, t,
98
orientation,
99
boundary_condition::BoundaryConditionPeriodic,
100
mesh::Union{StructuredMesh,
101
StructuredMeshView},
102
have_nonconservative_terms::False,
103
equations,
104
surface_integral, dg::DG, cache,
105
direction, node_indices,
106
surface_node_indices, element)
107
@assert isperiodic(mesh, orientation)
108
return nothing
109
end
110
111
@inline function calc_boundary_flux_by_direction!(surface_flux_values, t,
112
orientation,
113
boundary_condition::BoundaryConditionPeriodic,
114
mesh::Union{StructuredMesh,
115
StructuredMeshView},
116
have_nonconservative_terms::True,
117
equations,
118
surface_integral, dg::DG, cache,
119
direction, node_indices,
120
surface_node_indices, element)
121
@assert isperiodic(mesh, orientation)
122
return nothing
123
end
124
125
@inline function calc_boundary_flux_by_direction!(surface_flux_values, t,
126
orientation,
127
boundary_condition,
128
mesh::Union{StructuredMesh,
129
StructuredMeshView},
130
have_nonconservative_terms::False,
131
equations,
132
surface_integral, dg::DG, cache,
133
direction, node_indices,
134
surface_node_indices, element)
135
@unpack node_coordinates, contravariant_vectors, inverse_jacobian, interfaces_u = cache.elements
136
# Boundary values are for `StructuredMesh` stored in the interface datastructure
137
boundaries_u = interfaces_u
138
@unpack surface_flux = surface_integral
139
140
u_inner = get_node_vars(boundaries_u, equations, dg, surface_node_indices...,
141
direction, element)
142
x = get_node_coords(node_coordinates, equations, dg, node_indices..., element)
143
144
# If the mapping is orientation-reversing, the contravariant vectors' orientation
145
# is reversed as well. The normal vector must be oriented in the direction
146
# from `left_element` to `right_element`, or the numerical flux will be computed
147
# incorrectly (downwind direction).
148
sign_jacobian = sign(inverse_jacobian[node_indices..., element])
149
150
# Contravariant vector Ja^i is the normal vector
151
normal = sign_jacobian *
152
get_contravariant_vector(orientation, contravariant_vectors,
153
node_indices..., element)
154
155
# If the mapping is orientation-reversing, the normal vector will be reversed (see above).
156
# However, the flux now has the wrong sign, since we need the physical flux in normal direction.
157
flux = sign_jacobian *
158
boundary_condition(u_inner, normal, direction, x, t, surface_flux, equations)
159
160
# Only flux contribution for boundary element, boundary face is the boundary flux
161
for v in eachvariable(equations)
162
surface_flux_values[v, surface_node_indices..., direction, element] = flux[v]
163
end
164
165
return nothing
166
end
167
168
@inline function calc_boundary_flux_by_direction!(surface_flux_values, t,
169
orientation,
170
boundary_condition,
171
mesh::Union{StructuredMesh,
172
StructuredMeshView},
173
have_nonconservative_terms::True,
174
equations,
175
surface_integral, dg::DG, cache,
176
direction, node_indices,
177
surface_node_indices, element)
178
@unpack node_coordinates, contravariant_vectors, inverse_jacobian, interfaces_u = cache.elements
179
# Boundary values are for `StructuredMesh` stored in the interface datastructure
180
boundaries_u = interfaces_u
181
@unpack surface_flux = surface_integral
182
183
u_inner = get_node_vars(boundaries_u, equations, dg, surface_node_indices...,
184
direction, element)
185
x = get_node_coords(node_coordinates, equations, dg, node_indices..., element)
186
187
# If the mapping is orientation-reversing, the contravariant vectors' orientation
188
# is reversed as well. The normal vector must be oriented in the direction
189
# from `left_element` to `right_element`, or the numerical flux will be computed
190
# incorrectly (downwind direction).
191
sign_jacobian = sign(inverse_jacobian[node_indices..., element])
192
193
# Contravariant vector Ja^i is the normal vector
194
normal = sign_jacobian *
195
get_contravariant_vector(orientation, contravariant_vectors,
196
node_indices..., element)
197
198
# If the mapping is orientation-reversing, the normal vector will be reversed (see above).
199
# However, the flux now has the wrong sign, since we need the physical flux in normal direction.
200
flux, noncons_flux = boundary_condition(u_inner, normal, direction, x, t,
201
surface_flux, equations)
202
203
# Only flux contribution for boundary element, boundary face is the boundary flux
204
for v in eachvariable(equations)
205
surface_flux_values[v, surface_node_indices..., direction, element] = sign_jacobian *
206
(flux[v] +
207
0.5f0 *
208
noncons_flux[v])
209
end
210
211
return nothing
212
end
213
214
@inline function get_inverse_jacobian(inverse_jacobian,
215
mesh::Union{StructuredMesh, StructuredMeshView,
216
UnstructuredMesh2D, P4estMesh,
217
T8codeMesh},
218
indices...)
219
return inverse_jacobian[indices...]
220
end
221
222
include("containers.jl")
223
include("dg_1d.jl")
224
include("dg_2d.jl")
225
include("dg_3d.jl")
226
227
include("indicators_1d.jl")
228
include("indicators_2d.jl")
229
include("indicators_3d.jl")
230
231
include("subcell_limiters_2d.jl")
232
include("dg_2d_subcell_limiters.jl")
233
234
# Specialized implementations used to improve performance
235
include("dg_2d_compressible_euler.jl")
236
include("dg_3d_compressible_euler.jl")
237
end # @muladd
238
239