Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
trixi-framework
GitHub Repository: trixi-framework/Trixi.jl
Path: blob/main/src/solvers/dgsem_structured/containers_1d.jl
5590 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
# Initialize data structures in element container
9
function init_elements!(elements, mesh::StructuredMesh{1}, basis::AbstractBasisSBP)
10
@unpack node_coordinates, boundary_node_coordinates, left_neighbors,
11
jacobian_matrix, contravariant_vectors, inverse_jacobian = elements
12
13
# Calculate node coordinates, Jacobian matrix, and inverse Jacobian determinant
14
for cell_x in 1:size(mesh, 1)
15
calc_node_coordinates!(node_coordinates, cell_x, mesh.mapping, mesh, basis)
16
17
calc_jacobian_matrix!(jacobian_matrix, cell_x, node_coordinates, basis)
18
19
calc_inverse_jacobian!(inverse_jacobian, cell_x, jacobian_matrix)
20
end
21
22
# Contravariant vectors don't make sense in 1D, they would be identical to inverse_jacobian
23
fill!(contravariant_vectors, NaN)
24
25
initialize_left_neighbor_connectivity!(left_neighbors, mesh)
26
calc_boundary_node_coordinates!(boundary_node_coordinates, node_coordinates,
27
mesh, basis)
28
29
return nothing
30
end
31
32
function calc_boundary_node_coordinates!(boundary_node_coordinates,
33
node_coordinates,
34
mesh::StructuredMesh{1},
35
basis::LobattoLegendreBasis)
36
nelements = size(mesh, 1)
37
38
dim = 1 # spatial dimension
39
boundary_node_coordinates[dim, 1] = node_coordinates[dim, 1, 1]
40
boundary_node_coordinates[dim, 2] = node_coordinates[dim, nnodes(basis), nelements]
41
42
return nothing
43
end
44
45
function calc_boundary_node_coordinates!(boundary_node_coordinates,
46
node_coordinates,
47
mesh::StructuredMesh{1},
48
basis::GaussLegendreBasis)
49
nelements = size(mesh, 1)
50
boundary_matrix = basis.boundary_interpolation
51
52
dim = 1 # spatial dimension
53
# For structured mesh:
54
# Left/right boundaries are really left(-1)/right(+1) [first/second column of boundary matrix]
55
@views boundary_node_coordinates[dim, 1] = dot(boundary_matrix[:, 1],
56
node_coordinates[dim, :, 1])
57
@views boundary_node_coordinates[dim, 2] = dot(boundary_matrix[:, 2],
58
node_coordinates[dim, :, nelements])
59
60
return nothing
61
end
62
63
# Calculate physical coordinates to which every node of the reference element is mapped
64
# `mesh.mapping` is passed as an additional argument for type stability (function barrier)
65
function calc_node_coordinates!(node_coordinates, cell_x, mapping,
66
mesh::StructuredMesh{1},
67
basis::AbstractBasisSBP)
68
@unpack nodes = basis
69
70
# Get cell length in reference mesh
71
dx = 2 / size(mesh, 1)
72
73
# Calculate node coordinates of reference mesh
74
cell_x_offset = -1 + (cell_x - 1) * dx + dx / 2
75
76
for i in eachnode(basis)
77
# node_coordinates are the mapped reference node_coordinates
78
node_coordinates[1, i, cell_x] = mapping(cell_x_offset + dx / 2 * nodes[i])[1]
79
end
80
81
return nothing
82
end
83
84
# Calculate Jacobian matrix of the mapping from the reference element to the element in the physical domain
85
function calc_jacobian_matrix!(jacobian_matrix, element,
86
node_coordinates::AbstractArray{<:Any, 3},
87
basis::AbstractBasisSBP)
88
@views mul!(jacobian_matrix[1, 1, :, element], basis.derivative_matrix,
89
node_coordinates[1, :, element]) # x_ξ
90
91
return jacobian_matrix
92
end
93
94
# Calculate inverse Jacobian (determinant of Jacobian matrix of the mapping) in each node
95
function calc_inverse_jacobian!(inverse_jacobian::AbstractArray{<:Any, 2}, element,
96
jacobian_matrix)
97
@views inverse_jacobian[:, element] .= inv.(jacobian_matrix[1, 1, :, element])
98
99
return inverse_jacobian
100
end
101
102
# Save id of left neighbor of every element
103
function initialize_left_neighbor_connectivity!(left_neighbors, mesh::StructuredMesh{1})
104
# Neighbors in x-direction
105
# Inner elements
106
for cell_x in 2:size(mesh, 1)
107
left_neighbors[1, cell_x] = cell_x - 1
108
end
109
110
if isperiodic(mesh)
111
# Periodic boundary
112
left_neighbors[1, 1] = size(mesh, 1)
113
else
114
# Use boundary conditions
115
left_neighbors[1, 1] = 0
116
end
117
118
return left_neighbors
119
end
120
end # @muladd
121
122