ASCOT5
Loading...
Searching...
No Matches
interp1Dcomp.c
Go to the documentation of this file.
1
5#include <stdlib.h>
6#include <math.h>
7#include "../ascot5.h"
8#include "../math.h"
9#include "interp.h"
10#include "spline.h"
11
25int interp1Dcomp_init_coeff(real* c, real* f, int n_x, int bc_x,
26 real x_min, real x_max) {
27
28 /* Check boundary condition and calculate grid interval. Grid interval
29 needed because we use normalized grid intervals. For periodic boundary
30 condition, grid maximum value and the last data point are not the same.
31 Take this into account in grid interval. */
32 real x_grid;
33 if(bc_x == PERIODICBC || bc_x == NATURALBC) {
34 x_grid = (x_max - x_min) / ( n_x - 1 * (bc_x == NATURALBC) );
35 }
36 else {
37 return 1;
38 }
39
40 if(c == NULL) {
41 return 1;
42 }
43
44 /* Calculate cubic spline coefficients, i.e. second derivative. For each
45 grid cell i_x, there are two coefficients: [f, fxx]. Note how we account
46 for normalized grid. */
47
48 /* Cubic spline along x, using f values to get fxx */
49 splinecomp(f, n_x, bc_x, c);
50 for(int i_x=0; i_x<n_x; i_x++) {
51 /* Accounting for normalized grid. Affects fxx, but not f. */
52 c[i_x*2 + 1] = c[i_x*2+1] / (x_grid*x_grid);
53 }
54
55 return 0;
56}
57
69 int n_x, int bc_x, real x_min, real x_max) {
70
71 /* Calculate grid interval. For periodic boundary condition, grid maximum
72 value and the last data point are not the same. Take this into account
73 in grid interval. */
74 real x_grid = (x_max - x_min) / ( n_x - 1 * (bc_x == NATURALBC) );
75
76 /* Initialize the interp1D_data struct */
77 str->n_x = n_x;
78 str->bc_x = bc_x;
79 str->x_min = x_min;
80 str->x_max = x_max;
81 str->x_grid = x_grid;
82 str->c = c;
83}
84
100int interp1Dcomp_setup(interp1D_data* str, real* f, int n_x, int bc_x,
101 real x_min, real x_max) {
102 real* c = (real*) malloc(n_x*NSIZE_COMP1D*sizeof(real));
103 int err = interp1Dcomp_init_coeff(c, f, n_x, bc_x, x_min, x_max);
104 if(err) {
105 return err;
106 }
107 interp1Dcomp_init_spline(str, c, n_x, bc_x, x_min, x_max);
108 return 0;
109}
110
124
125 /* Make sure periodic coordinates are within [min, max] region. */
126 if(str->bc_x == PERIODICBC) {
127 x = fmod(x - str->x_min, str->x_max - str->x_min) + str->x_min;
128 x = x + (x < str->x_min) * (str->x_max - str->x_min);
129 }
130
131 /* Index for x variable. The -1 needed at exactly grid end. */
132 int i_x = (x-str->x_min) / str->x_grid - 1*(x==str->x_max);
133 /* Normalized x coordinate in current cell */
134 real dx = ( x - (str->x_min + i_x*str->x_grid) ) / str->x_grid;
135 /* Helper varibles */
136 real dx3 = dx * (dx*dx - 1.0);
137 real dxi = 1.0 - dx;
138 real dxi3 = dxi * (dxi*dxi - 1.0);
139 real xg2 = str->x_grid*str->x_grid;
140
141 int n = i_x*2; /* Index jump to cell */
142 int x1 = 2; /* Index jump one x forward */
143
144 int err = 0;
145
146 /* Enforce periodic BC or check that the coordinate is within the grid. */
147 if( str->bc_x == PERIODICBC && i_x == str->n_x-1 ) {
148 x1 = -(str->n_x-1)*x1;
149 }
150 else if( str->bc_x == NATURALBC && !(x >= str->x_min && x <= str->x_max) ) {
151 err = 1;
152 }
153
154 if(!err) {
155 *f =
156 dxi *str->c[n+0]+dx *str->c[n+x1+0]
157 +(xg2/6)*(dxi3*str->c[n+1]+dx3*str->c[n+x1+1]);
158 }
159
160 return err;
161}
162
182
183 /* Make sure periodic coordinates are within [min, max] region. */
184 if(str->bc_x == PERIODICBC) {
185 x = fmod(x - str->x_min, str->x_max - str->x_min) + str->x_min;
186 x = x + (x < str->x_min) * (str->x_max - str->x_min);
187 }
188
190 int i_x = (x - str->x_min) / str->x_grid - 1*(x==str->x_max);
192 real dx = ( x - (str->x_min + i_x*str->x_grid) ) / str->x_grid;
193 /* Helper varibles */
194 real dx3 = dx * (dx*dx - 1.0);
195 real dx3dx = 3*dx*dx - 1;
196 real dxi = 1.0 - dx;
197 real dxi3 = dxi * (dxi*dxi - 1);
198 real dxi3dx = -3*dxi*dxi + 1;
199 real xg = str->x_grid;
200 real xg2 = xg*xg;
201 real xgi = 1.0 / xg;
202
203 int n = i_x*2; /* Index jump to cell */
204 int x1 = 2; /* Index jump one x forward */
205
206 int err = 0;
207
208 /* Enforce periodic BC or check that the coordinate is within the grid. */
209 if( str->bc_x == PERIODICBC && i_x == str->n_x-1 ) {
210 x1 = -(str->n_x-1)*x1;
211 }
212 else if( str->bc_x == NATURALBC && !(x >= str->x_min && x <= str->x_max) ) {
213 err = 1;
214 }
215
216 if(!err) {
217 /* f */
218 f_df[0] =
219 dxi *str->c[n+0]+dx *str->c[n+x1+0]
220 +(xg2/6)*(dxi3*str->c[n+1]+dx3*str->c[n+x1+1]);
221
222 /* df/dx */
223 f_df[1] =
224 xgi*(str->c[n+x1+0]- str->c[n+0])
225 +(xg/6)*(dx3dx*str->c[n+x1+1]+dxi3dx*str->c[n+1]);
226
227 /* d2f/dx2 */
228 f_df[2] = dxi*str->c[n+1]+dx*str->c[n+x1+1];
229 }
230
231 return err;
232}
Main header file for ASCOT5.
double real
Definition ascot5.h:85
unsigned long int a5err
Simulation error flag.
Definition error.h:17
int interp1Dcomp_init_coeff(real *c, real *f, int n_x, int bc_x, real x_min, real x_max)
Calculate cubic spline interpolation coefficients for scalar 1D data.
a5err interp1Dcomp_eval_f(real *f, interp1D_data *str, real x)
Evaluate interpolated value of 1D scalar field.
int interp1Dcomp_setup(interp1D_data *str, real *f, int n_x, int bc_x, real x_min, real x_max)
Set up splines to interpolate 1D scalar data.
a5err interp1Dcomp_eval_df(real *f_df, interp1D_data *str, real x)
Evaluate interpolated value of 1D and its 1st and 2nd derivatives.
void interp1Dcomp_init_spline(interp1D_data *str, real *c, int n_x, int bc_x, real x_min, real x_max)
Initialize a cubic spline.
Spline interpolation library.
@ NATURALBC
Definition interp.h:37
@ PERIODICBC
Definition interp.h:38
real fmod(real x, real y)
Compute the modulus of two real numbers.
Definition math.c:22
Header file for math.c.
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
Cubic interpolation struct.
Definition interp.h:56
real x_min
Definition interp.h:59
real x_max
Definition interp.h:60
real x_grid
Definition interp.h:61
real * c
Definition interp.h:62