Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
trixi-framework
GitHub Repository: trixi-framework/Trixi.jl
Path: blob/main/src/callbacks_step/time_series_dg_tree.jl
2055 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
# Find element ids containing coordinates given as a matrix [ndims, npoints]
9
function get_elements_by_coordinates!(element_ids, coordinates, mesh::TreeMesh, dg,
10
cache)
11
if length(element_ids) != size(coordinates, 2)
12
throw(DimensionMismatch("storage length for element ids does not match the number of coordinates"))
13
end
14
15
@unpack cell_ids = cache.elements
16
@unpack tree = mesh
17
18
# Reset element ids - 0 indicates "not (yet) found"
19
element_ids .= 0
20
found_elements = 0
21
22
# Iterate over all elements
23
for element in eachelement(dg, cache)
24
# Get cell id
25
cell_id = cell_ids[element]
26
27
# Iterate over coordinates
28
for index in eachindex(element_ids)
29
# Skip coordinates for which an element has already been found
30
if element_ids[index] > 0
31
continue
32
end
33
34
# Construct point
35
x = SVector(ntuple(i -> coordinates[i, index], ndims(mesh)))
36
37
# Skip if point is not in cell
38
if !is_point_in_cell(tree, x, cell_id)
39
continue
40
end
41
42
# Otherwise point is in cell and thus in element
43
element_ids[index] = element
44
found_elements += 1
45
end
46
47
# Exit loop if all elements have already been found
48
if found_elements == length(element_ids)
49
break
50
end
51
end
52
53
return element_ids
54
end
55
56
# Calculate the interpolating polynomials to extract data at the given coordinates
57
# The coordinates are known to be located in the respective element in `element_ids`
58
function calc_interpolating_polynomials!(interpolating_polynomials, coordinates,
59
element_ids,
60
mesh::TreeMesh, dg::DGSEM, cache)
61
@unpack tree = mesh
62
@unpack nodes = dg.basis
63
64
wbary = barycentric_weights(nodes)
65
66
for index in eachindex(element_ids)
67
# Construct point
68
x = SVector(ntuple(i -> coordinates[i, index], ndims(mesh)))
69
70
# Convert to unit coordinates
71
cell_id = cache.elements.cell_ids[element_ids[index]]
72
cell_coordinates_ = cell_coordinates(tree, cell_id)
73
cell_length = length_at_cell(tree, cell_id)
74
unit_coordinates = (x .- cell_coordinates_) * 2 / cell_length
75
76
# Calculate interpolating polynomial for each dimension, making use of tensor product structure
77
for d in 1:ndims(mesh)
78
interpolating_polynomials[:, d, index] .= lagrange_interpolating_polynomials(unit_coordinates[d],
79
nodes,
80
wbary)
81
end
82
end
83
84
return interpolating_polynomials
85
end
86
87
# Record the solution variables at each given point for the 1D case
88
function record_state_at_points!(point_data, u, solution_variables,
89
n_solution_variables,
90
mesh::TreeMesh{1}, equations, dg::DG,
91
time_series_cache)
92
@unpack element_ids, interpolating_polynomials = time_series_cache
93
old_length = length(first(point_data))
94
new_length = old_length + n_solution_variables
95
96
# Loop over all points/elements that should be recorded
97
for index in eachindex(element_ids)
98
# Extract data array and element id
99
data = point_data[index]
100
element_id = element_ids[index]
101
102
# Make room for new data to be recorded
103
resize!(data, new_length)
104
data[(old_length + 1):new_length] .= zero(eltype(data))
105
106
# Loop over all nodes to compute their contribution to the interpolated values
107
for i in eachnode(dg)
108
u_node = solution_variables(get_node_vars(u, equations, dg, i,
109
element_id), equations)
110
111
for v in eachindex(u_node)
112
data[old_length + v] += (u_node[v] *
113
interpolating_polynomials[i, 1, index])
114
end
115
end
116
end
117
118
return nothing
119
end
120
121
# Record the solution variables at each given point for the 2D case
122
function record_state_at_points!(point_data, u, solution_variables,
123
n_solution_variables,
124
mesh::TreeMesh{2},
125
equations, dg::DG, time_series_cache)
126
@unpack element_ids, interpolating_polynomials = time_series_cache
127
old_length = length(first(point_data))
128
new_length = old_length + n_solution_variables
129
130
# Loop over all points/elements that should be recorded
131
for index in eachindex(element_ids)
132
# Extract data array and element id
133
data = point_data[index]
134
element_id = element_ids[index]
135
136
# Make room for new data to be recorded
137
resize!(data, new_length)
138
data[(old_length + 1):new_length] .= zero(eltype(data))
139
140
# Loop over all nodes to compute their contribution to the interpolated values
141
for j in eachnode(dg), i in eachnode(dg)
142
u_node = solution_variables(get_node_vars(u, equations, dg, i, j,
143
element_id), equations)
144
145
for v in eachindex(u_node)
146
data[old_length + v] += (u_node[v]
147
* interpolating_polynomials[i, 1, index]
148
* interpolating_polynomials[j, 2, index])
149
end
150
end
151
end
152
153
return nothing
154
end
155
156
# Record the solution variables at each given point for the 3D case
157
function record_state_at_points!(point_data, u, solution_variables,
158
n_solution_variables,
159
mesh::TreeMesh{3}, equations, dg::DG,
160
time_series_cache)
161
@unpack element_ids, interpolating_polynomials = time_series_cache
162
old_length = length(first(point_data))
163
new_length = old_length + n_solution_variables
164
165
# Loop over all points/elements that should be recorded
166
for index in eachindex(element_ids)
167
# Extract data array and element id
168
data = point_data[index]
169
element_id = element_ids[index]
170
171
# Make room for new data to be recorded
172
resize!(data, new_length)
173
data[(old_length + 1):new_length] .= zero(eltype(data))
174
175
# Loop over all nodes to compute their contribution to the interpolated values
176
for k in eachnode(dg), j in eachnode(dg), i in eachnode(dg)
177
u_node = solution_variables(get_node_vars(u, equations, dg, i, j, k,
178
element_id), equations)
179
180
for v in eachindex(u_node)
181
data[old_length + v] += (u_node[v]
182
* interpolating_polynomials[i, 1, index]
183
* interpolating_polynomials[j, 2, index]
184
* interpolating_polynomials[k, 3, index])
185
end
186
end
187
end
188
189
return nothing
190
end
191
end # @muladd
192
193