LMMC
Lamina Mathematic core
Toggle main menu visibility
载入中...
搜索中...
未找到
interp_spline_boundary.c
浏览该文件的文档.
1
#include "
internal/interp_internal.h
"
2
3
#include <string.h>
4
6
static
void
interp_tridiag_solve(
size_t
n,
const
lmmc_real_t
* sub,
7
lmmc_real_t
* dia,
const
lmmc_real_t
* sup,
8
lmmc_real_t
* rhs)
9
{
10
size_t
i;
11
for
(i = 1; i < n; ++i) {
12
lmmc_real_t
factor = sub[i] / dia[i - 1];
13
dia[i] -= factor * sup[i - 1];
14
rhs[i] -= factor * rhs[i - 1];
15
}
16
rhs[n - 1] /= dia[n - 1];
17
for
(i = n - 1; i > 0; --i) {
18
rhs[i - 1] = (rhs[i - 1] - sup[i - 1] * rhs[i]) / dia[i - 1];
19
}
20
}
21
22
static
lmmc_real_t
interp_spline_rhs(
const
interp_spline_workspace_t
* w,
23
size_t
i)
24
{
25
return
6.0 * ((w->
ys
[i + 1] - w->
ys
[i]) / w->
h
[i]
26
- (w->
ys
[i] - w->
ys
[i - 1]) / w->
h
[i - 1]);
27
}
28
29
static
void
interp_spline_interior(
interp_spline_workspace_t
* w,
30
size_t
first,
size_t
end,
size_t
offset)
31
{
32
size_t
i;
33
for
(i = first; i < end; ++i) {
34
size_t
row = i - offset;
35
w->
sub
[row] = w->
h
[i - 1];
36
w->
dia
[row] = 2.0 * (w->
h
[i - 1] + w->
h
[i]);
37
w->
sup
[row] = w->
h
[i];
38
w->
rhs
[row] = interp_spline_rhs(w, i);
39
}
40
}
41
42
void
interp_spline_standard
(
interp_spline_workspace_t
* w,
43
lmmc_spline_bc_t
bc,
lmmc_real_t
deriv_left,
44
lmmc_real_t
deriv_right)
45
{
46
size_t
last = w->
n
- 1;
47
const
lmmc_real_t
* h = w->
h
;
48
const
lmmc_real_t
* ys = w->
ys
;
49
interp_spline_interior(w, 1, last, 0);
50
w->
sub
[0] = w->
sup
[0] = w->
rhs
[0] = 0.0;
51
w->
sub
[last] = w->
sup
[last] = w->
rhs
[last] = 0.0;
52
w->
dia
[0] = w->
dia
[last] = 1.0;
53
if
(bc ==
LMMC_SPLINE_CLAMPED
) {
54
w->
dia
[0] = 2.0 * h[0];
55
w->
sup
[0] = h[0];
56
w->
rhs
[0] = 6.0 * ((ys[1] - ys[0]) / h[0] - deriv_left);
57
w->
sub
[last] = h[last - 1];
58
w->
dia
[last] = 2.0 * h[last - 1];
59
w->
rhs
[last] = 6.0 * (deriv_right - (ys[last] - ys[last - 1]) / h[last - 1]);
60
}
61
interp_tridiag_solve(w->
n
, w->
sub
, w->
dia
, w->
sup
, w->
rhs
);
62
memcpy(w->
moments
, w->
rhs
, w->
n
*
sizeof
(
lmmc_real_t
));
63
}
64
65
void
interp_spline_not_a_knot
(
interp_spline_workspace_t
* w)
66
{
67
size_t
n = w->
n
, count = n - 2;
68
const
lmmc_real_t
* h = w->
h
;
69
lmmc_real_t
* moments = w->
moments
;
70
lmmc_real_t
ha, hb;
71
if
(n == 3) {
73
lmmc_real_t
value = interp_spline_rhs(w, 1) / (3.0 * (h[0] + h[1]));
74
moments[0] = moments[1] = moments[2] = value;
75
return
;
76
}
78
interp_spline_interior(w, 1, n - 1, 1);
79
w->
dia
[0] = h[0] * (h[0] + h[1]) / h[1] + 2.0 * (h[0] + h[1]);
80
w->
sup
[0] = h[1] - h[0] * h[0] / h[1];
81
w->
sub
[0] = 0.0;
82
ha = h[n - 3];
83
hb = h[n - 2];
84
w->
sub
[count - 1] = ha - hb * hb / ha;
85
w->
dia
[count - 1] = 2.0 * (ha + hb) + hb * (ha + hb) / ha;
86
w->
sup
[count - 1] = 0.0;
87
interp_tridiag_solve(count, w->
sub
, w->
dia
, w->
sup
, w->
rhs
);
88
memcpy(moments + 1, w->
rhs
, count *
sizeof
(
lmmc_real_t
));
89
moments[0] = ((h[0] + h[1]) * moments[1] - h[0] * moments[2]) / h[1];
90
moments[n - 1] = ((ha + hb) * moments[n - 2] - hb * moments[n - 3]) / ha;
91
}
92
93
void
interp_spline_periodic
(
interp_spline_workspace_t
* w)
94
{
95
size_t
count = w->
n
- 1, i;
96
const
lmmc_real_t
* h = w->
h
;
97
const
lmmc_real_t
* ys = w->
ys
;
98
lmmc_real_t
corner = h[count - 1], gamma, vy, vz;
99
interp_spline_interior(w, 1, count, 0);
100
w->
dia
[0] = 2.0 * (corner + h[0]);
101
w->
sup
[0] = h[0];
102
w->
sub
[0] = 0.0;
103
w->
rhs
[0] = 6.0 * ((ys[1] - ys[0]) / h[0]
104
- (ys[count] - ys[count - 1]) / corner);
105
gamma = -w->
dia
[0];
107
w->
dia
[0] -= gamma;
108
w->
dia
[count - 1] -= corner * corner / gamma;
109
w->
sup
[count - 1] = 0.0;
110
for
(i = 0; i < count; ++i) w->
auxiliary
[i] = 0.0;
111
w->
auxiliary
[0] = gamma;
112
w->
auxiliary
[count - 1] = corner;
113
memcpy(w->
diagonal_copy
, w->
dia
, count *
sizeof
(
lmmc_real_t
));
114
interp_tridiag_solve(count, w->
sub
, w->
dia
, w->
sup
, w->
rhs
);
115
interp_tridiag_solve(count, w->
sub
, w->
diagonal_copy
, w->
sup
, w->
auxiliary
);
116
vy = w->
rhs
[0] + (corner / gamma) * w->
rhs
[count - 1];
117
vz = w->
auxiliary
[0] + (corner / gamma) * w->
auxiliary
[count - 1];
118
for
(i = 0; i < count; ++i) {
119
w->
moments
[i] = w->
rhs
[i] - w->
auxiliary
[i] * vy / (1.0 + vz);
120
}
121
w->
moments
[count] = w->
moments
[0];
122
}
lmmc_real_t
double lmmc_real_t
Public and internal LMMC real type.
定义
config.h:28
lmmc_spline_bc_t
lmmc_spline_bc_t
样条边界条件类型.
定义
interp.h:46
LMMC_SPLINE_CLAMPED
@ LMMC_SPLINE_CLAMPED
定义
interp.h:48
interp_internal.h
interp_spline_workspace_t::dia
lmmc_real_t * dia
定义
interp_internal.h:35
interp_spline_workspace_t::h
lmmc_real_t * h
定义
interp_internal.h:32
interp_spline_workspace_t::n
size_t n
定义
interp_internal.h:30
interp_spline_workspace_t::sub
lmmc_real_t * sub
定义
interp_internal.h:34
interp_spline_standard
void interp_spline_standard(interp_spline_workspace_t *work, lmmc_spline_bc_t bc, lmmc_real_t deriv_left, lmmc_real_t deriv_right)
定义
interp_spline_boundary.c:42
interp_spline_workspace_t::diagonal_copy
lmmc_real_t * diagonal_copy
定义
interp_internal.h:39
interp_spline_workspace_t::rhs
lmmc_real_t * rhs
定义
interp_internal.h:37
interp_spline_workspace_t::auxiliary
lmmc_real_t * auxiliary
定义
interp_internal.h:38
interp_spline_workspace_t::ys
const lmmc_real_t * ys
定义
interp_internal.h:31
interp_spline_periodic
void interp_spline_periodic(interp_spline_workspace_t *work)
定义
interp_spline_boundary.c:93
interp_spline_workspace_t::moments
lmmc_real_t * moments
定义
interp_internal.h:33
interp_spline_not_a_knot
void interp_spline_not_a_knot(interp_spline_workspace_t *work)
定义
interp_spline_boundary.c:65
interp_spline_workspace_t::sup
lmmc_real_t * sup
定义
interp_internal.h:36
interp_spline_workspace_t
定义
interp_internal.h:29
src
interp_spline_boundary.c
生成于
, 为 LMMC使用
1.18.0