Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
trixi-framework
GitHub Repository: trixi-framework/Trixi.jl
Path: blob/main/src/meshes/surface_interpolant.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
# CurvedSurface{RealT<:Real}
9
#
10
# Contains the data needed to represent a curve with data points (x,y) as a Lagrange polynomial
11
# interpolant written in barycentric form at a given set of nodes.
12
struct CurvedSurface{RealT <: Real}
13
nodes :: Vector{RealT}
14
barycentric_weights :: Vector{RealT}
15
coordinates :: Array{RealT, 2} #[nnodes, ndims]
16
end
17
18
# evaluate the Gamma curve interpolant at a particular point s and return the (x,y) coordinate
19
function evaluate_at(s, boundary_curve::CurvedSurface)
20
@unpack nodes, barycentric_weights, coordinates = boundary_curve
21
22
x_coordinate_at_s_on_boundary_curve = lagrange_interpolation(s, nodes,
23
view(coordinates, :,
24
1),
25
barycentric_weights)
26
y_coordinate_at_s_on_boundary_curve = lagrange_interpolation(s, nodes,
27
view(coordinates, :,
28
2),
29
barycentric_weights)
30
31
return x_coordinate_at_s_on_boundary_curve, y_coordinate_at_s_on_boundary_curve
32
end
33
34
# evaluate the derivative of a Gamma curve interpolant at a particular point s
35
# and return the (x,y) coordinate
36
function derivative_at(s, boundary_curve::CurvedSurface)
37
@unpack nodes, barycentric_weights, coordinates = boundary_curve
38
39
x_coordinate_at_s_on_boundary_curve_prime = lagrange_interpolation_derivative(s,
40
nodes,
41
view(coordinates,
42
:,
43
1),
44
barycentric_weights)
45
y_coordinate_at_s_on_boundary_curve_prime = lagrange_interpolation_derivative(s,
46
nodes,
47
view(coordinates,
48
:,
49
2),
50
barycentric_weights)
51
return x_coordinate_at_s_on_boundary_curve_prime,
52
y_coordinate_at_s_on_boundary_curve_prime
53
end
54
55
# Chebyshev-Gauss-Lobatto nodes and weights for use with curved boundaries
56
function chebyshev_gauss_lobatto_nodes_weights(n_nodes::Integer)
57
58
# Initialize output
59
nodes = zeros(n_nodes)
60
weights = zeros(n_nodes)
61
62
# Get polynomial degree for convenience
63
N = n_nodes - 1
64
65
for j in 1:n_nodes
66
nodes[j] = -cospi((j - 1) / N)
67
weights[j] = pi / N
68
end
69
weights[1] = 0.5f0 * weights[1]
70
weights[end] = 0.5f0 * weights[end]
71
72
return nodes, weights
73
end
74
75
# Calculate Lagrange interpolating polynomial of a function f(x) at a given point x for a given
76
# node distribution.
77
function lagrange_interpolation(x, nodes, fvals, wbary)
78
# Barycentric two formulation of Lagrange interpolant
79
numerator = zero(eltype(fvals))
80
denominator = zero(eltype(fvals))
81
82
for j in eachindex(nodes)
83
# using eps(nodes[j]) instead of eps(x) allows us to use integer
84
# coordinates for the target location x
85
if isapprox(x, nodes[j], rtol = eps(nodes[j]))
86
return fvals[j]
87
end
88
t = wbary[j] / (x - nodes[j])
89
numerator += t * fvals[j]
90
denominator += t
91
end
92
93
return numerator / denominator
94
end
95
96
# Calculate derivative of a Lagrange interpolating polynomial of a function f(x) at a given
97
# point x for a given node distribution.
98
function lagrange_interpolation_derivative(x, nodes, fvals, wbary)
99
at_node = false
100
numerator = zero(eltype(fvals))
101
i = 0
102
103
for j in eachindex(nodes)
104
if isapprox(x, nodes[j])
105
at_node = true
106
p = fvals[j]
107
denominator = -wbary[j]
108
i = j
109
end
110
end
111
112
if at_node
113
for j in eachindex(nodes)
114
if j != i
115
numerator += wbary[j] * (p - fvals[j]) / (x - nodes[j])
116
end
117
end
118
else
119
denominator = zero(eltype(fvals))
120
p = lagrange_interpolation(x, nodes, fvals, wbary)
121
for j in eachindex(nodes)
122
t = wbary[j] / (x - nodes[j])
123
numerator += t * (p - fvals[j]) / (x - nodes[j])
124
denominator += t
125
end
126
end
127
128
return numerator / denominator # p_prime
129
end
130
end # @muladd
131
132