LMMC
Lamina Mathematic core
载入中...
搜索中...
未找到
interp_spline_boundary.c
浏览该文件的文档.
2
3#include <string.h>
4
6static 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
22static 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
29static 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
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
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
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}
double lmmc_real_t
Public and internal LMMC real type.
lmmc_spline_bc_t
样条边界条件类型.
@ LMMC_SPLINE_CLAMPED
void interp_spline_standard(interp_spline_workspace_t *work, lmmc_spline_bc_t bc, lmmc_real_t deriv_left, lmmc_real_t deriv_right)
void interp_spline_periodic(interp_spline_workspace_t *work)
void interp_spline_not_a_knot(interp_spline_workspace_t *work)