ASCOT5
Loading...
Searching...
No Matches
splinecomp.c
Go to the documentation of this file.
1
5#include <stdlib.h>
6#include "../ascot5.h"
7#include "spline.h"
8#include "interp.h"
9
22void splinecomp(real* f, int n, int bc, real* c) {
23
24 /* Allocate needed variables */
25
26 /* Array for RHS of matrix equation */
27 real* Y = malloc(n*sizeof(real));
28 /* Array superdiagonal values */
29 real* p = malloc((n-1)*sizeof(real));
30 /* Array for 2nd derivative vector to solve */
31 real* D = malloc(n*sizeof(real));
32
33 if(bc == NATURALBC) {
36 /* Initialize RHS of equation */
37 Y[0] = 0.0;
38 for(int i=1; i<n-1; i++) {
39 Y[i] = 6 * (f[i+1] - 2 * f[i] + f[i-1]);
40 }
41 Y[n-1] = 0.0;
42
43 /* Thomas algorithm is used*/
44
45 /* Forward sweep */
46 p[0] = 0.0;
47 Y[0] = Y[0] / 2;
48 for(int i=1; i<n-1; i++) {
49 p[i] = 1 / (4 - p[i-1]);
50 Y[i] = (Y[i] - Y[i-1]) / (4 - p[i-1]);
51 }
52 Y[n-1] = 0.0;
53
54 /* Back substitution */
55 D[n-1] = Y[n-1];
56 for(int i=n-2; i>-1; i--) {
57 D[i] = Y[i] - p[i] * D[i+1];
58 }
59 }
60 else if(bc == PERIODICBC) {
63 /* Initialize some additional helper variables */
64
65 /* Value that starts from lower left corner and moves right */
66 real l = 1.0;
67 /* Last diagonal value */
68 real dlast = 4.0;
69 /* Matrix right column values */
70 real* r = malloc((n-2)*sizeof(real));
71 /* Last subdiagonal value */
72 real blast;
73
74 /* Initialize RHS of equation */
75 Y[0] = 6 * (f[1] - 2 * f[0] + f[n-1]);
76 for(int i=1; i<n-1; i++) {
77 Y[i] = 6 * (f[i+1] - 2 * f[i] + f[i-1]);
78 }
79 Y[n-1] = 6 * (f[0] - 2 * f[n-1] + f[n-2]);
80
81 /* Simplified Gauss elimination is used (own algorithm) */
82
83 /* Forward sweep */
84 p[0] = 1.0 / 4;
85 r[0] = 1.0 / 4;
86 Y[0] = Y[0] / 4;
87 for(int i=1; i<n-2; i++) {
88 dlast = dlast - l * r[i-1];
89 Y[n-1] = Y[n-1] - l * Y[i-1];
90 l = -l * p[i-1];
91 p[i] = 1 / (4 - p[i-1]);
92 r[i] = -r[i-1] / (4 - p[i-1]);
93 Y[i] = (Y[i] - Y[i-1]) / (4 - p[i-1]);
94 }
95 blast = 1.0 - l * p[n-3];
96 dlast = dlast - l * r[n-3];
97 Y[n-1] = Y[n-1] - l * Y[n-3];
98
99 p[n-2] = (1 - r[n-3]) / (4 - p[n-3]);
100 Y[n-2] = (Y[n-2] - Y[n-3]) / (4 - p[n-3]);
101 Y[n-1] = (Y[n-1] - blast * Y[n-2]) / (dlast - blast * p[n-2]);
102
103 /* Back substitution */
104 D[n-1] = Y[n-1];
105 D[n-2] = Y[n-2] - p[n-2] * D[n-1];
106 for(int i=n-3; i>-1; i--) {
107 D[i] = Y[i] - p[i] * D[i+1] - r[i] * D[n-1];
108 }
109
110 /* Free allocated memory */
111 free(r);
112 }
113
114 /* Store the spline coefficients, i.e. the already known function values and
115 the above solved second derivatives. In compact form, we always store
116 coefficients all the way to n, because evaluation requires it. This means
117 that, unlike in the explicit form algorithm, the periodic boundary condition
118 case in this compact form algorithm (above) does not need a separate code
119 segment for storage of period-closing spline coefficients, instead it is
120 done here. */
121 for(int i=0; i<n; i++) {
122 c[i*2] = f[i];
123 c[i*2+1] = D[i];
124 }
125
126 /* Free allocated memory */
127 free(Y);
128 free(p);
129 free(D);
130}
Main header file for ASCOT5.
double real
Definition ascot5.h:85
Spline interpolation library.
@ NATURALBC
Definition interp.h:37
@ PERIODICBC
Definition interp.h:38
Header file for splineexpl.c and splinecomp.c.
void splinecomp(real *f, int n, int bc, real *c)
Calculate compact cubic spline interpolation coefficients in 1D.
Definition splinecomp.c:22