Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
trixi-framework
GitHub Repository: trixi-framework/Trixi.jl
Path: blob/main/src/solvers/dgsem_unstructured/mappings_geometry_curved_2d.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
# transfinite mapping formula from a point (xi, eta) in reference space [-1,1]^2 to a point
9
# (x,y) in physical coordinate space for a quadrilateral element with general curved sides
10
# Alg. 98 from the blue book of Kopriva
11
function transfinite_quad_map(xi, eta, surface_curves::AbstractVector{<:CurvedSurface})
12
13
# evaluate the gamma curves to get the four corner points of the element
14
x_corner1, y_corner1 = evaluate_at(-1, surface_curves[1])
15
x_corner2, y_corner2 = evaluate_at(1, surface_curves[1])
16
x_corner3, y_corner3 = evaluate_at(1, surface_curves[3])
17
x_corner4, y_corner4 = evaluate_at(-1, surface_curves[3])
18
19
# evaluate along the gamma curves at a particular point (ξ, η) in computational space to get
20
# the value (x,y) in physical space
21
x1, y1 = evaluate_at(xi, surface_curves[1])
22
x2, y2 = evaluate_at(eta, surface_curves[2])
23
x3, y3 = evaluate_at(xi, surface_curves[3])
24
x4, y4 = evaluate_at(eta, surface_curves[4])
25
26
x = (0.5f0 * ((1 - xi) * x4 + (1 + xi) * x2 + (1 - eta) * x1 + (1 + eta) * x3)
27
-
28
0.25f0 * ((1 - xi) * ((1 - eta) * x_corner1 + (1 + eta) * x_corner4) +
29
(1 + xi) * ((1 - eta) * x_corner2 + (1 + eta) * x_corner3)))
30
31
y = (0.5f0 * ((1 - xi) * y4 + (1 + xi) * y2 + (1 - eta) * y1 + (1 + eta) * y3)
32
-
33
0.25f0 * ((1 - xi) * ((1 - eta) * y_corner1 + (1 + eta) * y_corner4) +
34
(1 + xi) * ((1 - eta) * y_corner2 + (1 + eta) * y_corner3)))
35
36
return x, y
37
end
38
39
# Compute the metric terms for the general curved sided quadrilateral transfitie mapping
40
# Alg. 99 from the blue book of Kopriva
41
function transfinite_quad_map_metrics(xi, eta,
42
surface_curves::AbstractVector{<:CurvedSurface})
43
44
# evaluate the gamma curves to get the four corner points of the element
45
x_corner1, y_corner1 = evaluate_at(-1, surface_curves[1])
46
x_corner2, y_corner2 = evaluate_at(1, surface_curves[1])
47
x_corner3, y_corner3 = evaluate_at(1, surface_curves[3])
48
x_corner4, y_corner4 = evaluate_at(-1, surface_curves[3])
49
50
# evaluate along the gamma curves at a particular point (ξ, η) in computational space to get
51
# the value (x,y) in physical space
52
x1, y1 = evaluate_at(xi, surface_curves[1])
53
x2, y2 = evaluate_at(eta, surface_curves[2])
54
x3, y3 = evaluate_at(xi, surface_curves[3])
55
x4, y4 = evaluate_at(eta, surface_curves[4])
56
57
# evaluate along the derivative of the gamma curves at a particular point (ξ, η) in
58
# computational space to get the value (x_prime,y_prime) in physical space
59
x1_prime, y1_prime = derivative_at(xi, surface_curves[1])
60
x2_prime, y2_prime = derivative_at(eta, surface_curves[2])
61
x3_prime, y3_prime = derivative_at(xi, surface_curves[3])
62
x4_prime, y4_prime = derivative_at(eta, surface_curves[4])
63
64
X_xi = (0.5f0 * (x2 - x4 + (1 - eta) * x1_prime + (1 + eta) * x3_prime)
65
-
66
0.25f0 * ((1 - eta) * (x_corner2 - x_corner1) +
67
(1 + eta) * (x_corner3 - x_corner4)))
68
69
X_eta = (0.5f0 * ((1 - xi) * x4_prime + (1 + xi) * x2_prime + x3 - x1)
70
-
71
0.25f0 * ((1 - xi) * (x_corner4 - x_corner1) +
72
(1 + xi) * (x_corner3 - x_corner2)))
73
74
Y_xi = (0.5f0 * (y2 - y4 + (1 - eta) * y1_prime + (1 + eta) * y3_prime)
75
-
76
0.25f0 * ((1 - eta) * (y_corner2 - y_corner1) +
77
(1 + eta) * (y_corner3 - y_corner4)))
78
79
Y_eta = (0.5f0 * ((1 - xi) * y4_prime + (1 + xi) * y2_prime + y3 - y1)
80
-
81
0.25f0 * ((1 - xi) * (y_corner4 - y_corner1) +
82
(1 + xi) * (y_corner3 - y_corner2)))
83
84
return X_xi, X_eta, Y_xi, Y_eta
85
end
86
87
# construct the (x,y) node coordinates in the volume of a curved sided element
88
function calc_node_coordinates!(node_coordinates::AbstractArray{<:Any, 4}, element,
89
nodes,
90
surface_curves::AbstractVector{<:CurvedSurface})
91
for j in eachindex(nodes), i in eachindex(nodes)
92
node_coordinates[:, i, j, element] .= transfinite_quad_map(nodes[i], nodes[j],
93
surface_curves)
94
end
95
96
return node_coordinates
97
end
98
99
# construct the metric terms for a curved sided element
100
function calc_metric_terms!(jacobian_matrix, element, nodes,
101
surface_curves::AbstractVector{<:CurvedSurface})
102
103
# storage format:
104
# jacobian_matrix[1,1,:,:,:] <- X_xi
105
# jacobian_matrix[1,2,:,:,:] <- X_eta
106
# jacobian_matrix[2,1,:,:,:] <- Y_xi
107
# jacobian_matrix[2,2,:,:,:] <- Y_eta
108
for j in eachindex(nodes), i in eachindex(nodes)
109
(jacobian_matrix[1, 1, i, j, element],
110
jacobian_matrix[1, 2, i, j, element],
111
jacobian_matrix[2, 1, i, j, element],
112
jacobian_matrix[2, 2, i, j, element]) = transfinite_quad_map_metrics(nodes[i],
113
nodes[j],
114
surface_curves)
115
end
116
117
return jacobian_matrix
118
end
119
120
# construct the normal direction vectors (but not actually normalized) for a curved sided element
121
# normalization occurs on the fly during the surface flux computation
122
function calc_normal_directions!(normal_directions, element, nodes,
123
surface_curves::AbstractVector{<:CurvedSurface})
124
125
# normal directions on the boundary for the left (local side 4) and right (local side 2)
126
for j in eachindex(nodes)
127
# side 2
128
X_xi, X_eta, Y_xi, Y_eta = transfinite_quad_map_metrics(1, nodes[j],
129
surface_curves)
130
Jtemp = X_xi * Y_eta - X_eta * Y_xi
131
normal_directions[1, j, 2, element] = sign(Jtemp) * (Y_eta)
132
normal_directions[2, j, 2, element] = sign(Jtemp) * (-X_eta)
133
134
# side 4
135
X_xi, X_eta, Y_xi, Y_eta = transfinite_quad_map_metrics(-1, nodes[j],
136
surface_curves)
137
Jtemp = X_xi * Y_eta - X_eta * Y_xi
138
normal_directions[1, j, 4, element] = -sign(Jtemp) * (Y_eta)
139
normal_directions[2, j, 4, element] = -sign(Jtemp) * (-X_eta)
140
end
141
142
# normal directions on the boundary for the top (local side 3) and bottom (local side 1)
143
for i in eachindex(nodes)
144
# side 1
145
X_xi, X_eta, Y_xi, Y_eta = transfinite_quad_map_metrics(nodes[i], -1,
146
surface_curves)
147
Jtemp = X_xi * Y_eta - X_eta * Y_xi
148
normal_directions[1, i, 1, element] = -sign(Jtemp) * (-Y_xi)
149
normal_directions[2, i, 1, element] = -sign(Jtemp) * (X_xi)
150
151
# side 3
152
X_xi, X_eta, Y_xi, Y_eta = transfinite_quad_map_metrics(nodes[i], 1,
153
surface_curves)
154
Jtemp = X_xi * Y_eta - X_eta * Y_xi
155
normal_directions[1, i, 3, element] = sign(Jtemp) * (-Y_xi)
156
normal_directions[2, i, 3, element] = sign(Jtemp) * (X_xi)
157
end
158
159
return normal_directions
160
end
161
end # @muladd
162
163