ASCOT5
Loading...
Searching...
No Matches
interp2Dexpl.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
34 int n_x, int n_y, int bc_x, int bc_y,
35 real x_min, real x_max,
36 real y_min, real y_max) {
37
38 /* Allocate helper quantities */
39 real* f_x = malloc(n_x*sizeof(real));
40 real* f_y = malloc(n_y*sizeof(real));
41 real* c_x = malloc((n_x-1*(bc_x==NATURALBC))*NSIZE_EXPL1D*sizeof(real));
42 real* c_y = malloc((n_y-1*(bc_y==NATURALBC))*NSIZE_EXPL1D*sizeof(real));
43 int i_ct;
44
45 if(f_x == NULL || f_y == NULL || c_x == NULL || c_y == NULL) {
46 return 1;
47 }
48
49 /* Calculate bicubic spline surface coefficients. For each grid cell
50 (i_x, i_y), there are 16 coefficients, one for each variable product
51 dx^p_x*dy^p_y in the evaluation formula, where p_x, p_y = 0, 1, 2, 3. */
52
53 /* Cubic spline along x for each y, using f values to get a total of four
54 coefficients */
55 for(int i_y=0; i_y<n_y; i_y++) {
56 for(int i_x=0; i_x<n_x; i_x++) {
57 f_x[i_x] = f[i_y*n_x+i_x];
58 }
59 splineexpl(f_x, n_x, bc_x, c_x);
60 for(int i_x=0; i_x<n_x-1; i_x++) {
61 for(int i_c=0; i_c<4; i_c++) {
62 c[i_y*n_x*16+i_x*16+i_c] = c_x[i_x*4+i_c];
63 }
64 }
65 }
66
67 /* Four cubic splines along y for each x, using the above calculated four
68 coefficient values to get a total of 16 coefficients */
69 for(int i_x=0; i_x<n_x-1; i_x++) {
70 for(int i_s=0; i_s<4; i_s++) {
71 for(int i_y=0; i_y<n_y; i_y++) {
72 f_y[i_y] = c[i_y*n_x*16+i_x*16+i_s];
73 }
74 splineexpl(f_y, n_y, bc_y, c_y);
75 for(int i_y=0; i_y<n_y-1; i_y++) {
76 i_ct = 0;
77 for(int i_c=i_s; i_c<16; i_c=i_c+4) {
78 c[i_y*n_x*16+i_x*16+i_c] = c_y[i_y*4+i_ct];
79 i_ct++;
80 }
81 }
82 }
83 }
84
85 /* Free allocated memory */
86 free(f_x);
87 free(f_y);
88 free(c_x);
89 free(c_y);
90
91 return 0;
92}
93
109 int n_x, int n_y, int bc_x, int bc_y,
110 real x_min, real x_max,
111 real y_min, real y_max) {
112
113 /* Calculate grid intervals. For periodic boundary condition, grid maximum
114 value and the last data point are not the same. Take this into account
115 in grid intervals. */
116 real x_grid = (x_max - x_min) / ( n_x - 1 * (bc_x == NATURALBC) );
117 real y_grid = (y_max - y_min) / ( n_y - 1 * (bc_y == NATURALBC) );
118
119 /* Initialize the interp2D_data struct */
120 str->n_x = n_x;
121 str->n_y = n_y;
122 str->bc_x = bc_x;
123 str->bc_y = bc_y;
124 str->x_min = x_min;
125 str->x_max = x_max;
126 str->x_grid = x_grid;
127 str->y_min = y_min;
128 str->y_max = y_max;
129 str->y_grid = y_grid;
130 str->c = c;
131}
132
147
148 /* Make sure periodic coordinates are within [min, max] region. */
149 if(str->bc_x == PERIODICBC) {
150 x = fmod(x - str->x_min, str->x_max - str->x_min) + str->x_min;
151 x = x + (x < str->x_min) * (str->x_max - str->x_min);
152 }
153 if(str->bc_y == PERIODICBC) {
154 y = fmod(y - str->y_min, str->y_max - str->y_min) + str->y_min;
155 y = y + (y < str->y_min) * (str->y_max - str->y_min);
156 }
157
158 /* Index for x variable. The -1 needed at exactly grid end. */
159 int i_x = (x-str->x_min)/str->x_grid - 1*(x==str->x_max);
160 /* Normalized x coordinate in current cell */
161 real dx = (x-(str->x_min+i_x*str->x_grid))/str->x_grid;
162 /* Helper variables */
163 real dx2 = dx*dx;
164 real dx3 = dx2*dx;
165
166 /* Index for y variable. The -1 needed at exactly grid end. */
167 int i_y = (y-str->y_min)/str->y_grid - 1*(y==str->y_max);
168 /* Normalized y coordinate in current cell */
169 real dy = (y-(str->y_min+i_y*str->y_grid))/str->y_grid;
170 /* Helper variables */
171 real dy2 = dy*dy;
172 real dy3 = dy2*dy;
173
174 int n = i_y*str->n_x*16+i_x*16; /* Index jump to cell */
175
176 int err = 0;
177
178 /* Check that the coordinate is within the domain. */
179 if( str->bc_x == NATURALBC && !(x >= str->x_min && x <= str->x_max) ) {
180 err = 1;
181 }
182 if( str->bc_y == NATURALBC && !(y >= str->y_min && y <= str->y_max) ) {
183 err = 1;
184 }
185
186 if(!err) {
187 *f =
188 str->c[n+ 0]+dx*str->c[n+ 1]+dx2*str->c[n+ 2]+dx3*str->c[n+ 3]
189 +dy*(
190 str->c[n+ 4]+dx*str->c[n+ 5]+dx2*str->c[n+ 6]+dx3*str->c[n+ 7])
191 +dy2*(
192 str->c[n+ 8]+dx*str->c[n+ 9]+dx2*str->c[n+10]+dx3*str->c[n+11])
193 +dy3*(
194 str->c[n+12]+dx*str->c[n+13]+dx2*str->c[n+14]+dx3*str->c[n+15]);
195 }
196
197 return err;
198}
199
221
222 /* Make sure periodic coordinates are within [min, max] region. */
223 if(str->bc_x == PERIODICBC) {
224 x = fmod(x - str->x_min, str->x_max - str->x_min) + str->x_min;
225 x = x + (x < str->x_min) * (str->x_max - str->x_min);
226 }
227 if(str->bc_y == PERIODICBC) {
228 y = fmod(y - str->y_min, str->y_max - str->y_min) + str->y_min;
229 y = y + (y < str->y_min) * (str->y_max - str->y_min);
230 }
231
232 /* Index for x variable. The -1 needed at exactly grid end. */
233 int i_x = (x-str->x_min)/str->x_grid - 1*(x==str->x_max);
234 /* Normalized x coordinate in current cell */
235 real dx = (x-(str->x_min+i_x*str->x_grid))/str->x_grid;
236 /* Helper variables */
237 real dx2 = dx*dx;
238 real dx3 = dx2*dx;
239 real xgi = 1.0/str->x_grid;
240
241 /* Index for y variable. The -1 needed at exactly grid end. */
242 int i_y = (y-str->y_min)/str->y_grid - 1*(y==str->y_max);
243 /* Normalized y coordinate in current cell */
244 real dy = (y-(str->y_min+i_y*str->y_grid))/str->y_grid;
245 /* Helper variables */
246 real dy2 = dy*dy;
247 real dy3 = dy2*dy;
248 real ygi = 1.0/str->y_grid;
249
250 int n = i_y*str->n_x*16+i_x*16; /* Index jump to cell */
251
252 int err = 0;
253
254 /* Check that the coordinate is within the domain. */
255 if( str->bc_x == NATURALBC && !(x >= str->x_min && x <= str->x_max) ) {
256 err = 1;
257 }
258 if( str->bc_y == NATURALBC && !(y >= str->y_min && y <= str->y_max) ) {
259 err = 1;
260 }
261
262 if(!err) {
263 /* f */
264 f_df[0] =
265 str->c[n+ 0]+dx*str->c[n+ 1]+dx2*str->c[n+ 2]+dx3*str->c[n+ 3]
266 +dy*(
267 str->c[n+ 4]+dx*str->c[n+ 5]+dx2*str->c[n+ 6]+dx3*str->c[n+ 7])
268 +dy2*(
269 str->c[n+ 8]+dx*str->c[n+ 9]+dx2*str->c[n+10]+dx3*str->c[n+11])
270 +dy3*(
271 str->c[n+12]+dx*str->c[n+13]+dx2*str->c[n+14]+dx3*str->c[n+15]);
272
273 /* df/dx */
274 f_df[1] =
275 xgi*(
276 str->c[n+ 1]+2*dx*str->c[n+ 2]+3*dx2*str->c[n+ 3]
277 +dy*(str->c[n+ 5]+2*dx*str->c[n+ 6]+3*dx2*str->c[n+ 7])
278 +dy2*(str->c[n+ 9]+2*dx*str->c[n+10]+3*dx2*str->c[n+11])
279 +dy3*(str->c[n+13]+2*dx*str->c[n+14]+3*dx2*str->c[n+15]));
280
281 /* df/dy */
282 f_df[2] =
283 ygi*(
284 str->c[n+ 4]+dx *str->c[n+ 5]
285 +dx2*str->c[n+ 6]+dx3*str->c[n+ 7]
286 +2*dy*(
287 str->c[n+ 8]+dx *str->c[n+ 9]
288 +dx2*str->c[n+10]+dx3*str->c[n+11])
289 +3*dy2*(
290 str->c[n+12]+dx *str->c[n+13]
291 +dx2*str->c[n+14]+dx3*str->c[n+15]));
292
293 /* d2f/dx2 */
294 f_df[3] =
295 xgi*xgi*(
296 2*str->c[n+ 2]+6*dx*str->c[n+ 3]
297 +dy*(2*str->c[n+ 6]+6*dx*str->c[n+ 7])
298 +dy2*(2*str->c[n+10]+6*dx*str->c[n+11])
299 +dy3*(2*str->c[n+14]+6*dx*str->c[n+15]));
300
301 /* d2f/dy2 */
302 f_df[4] =
303 ygi*ygi*(
304 2*( str->c[n+ 8]+dx *str->c[n+ 9]
305 +dx2*str->c[n+10]+dx3*str->c[n+11])
306 +6*dy*( str->c[n+12]+dx *str->c[n+13]
307 +dx2*str->c[n+14]+dx3*str->c[n+15]));
308
309 /* d2f/dydx */
310 f_df[5] =
311 xgi*ygi*(
312 str->c[n+ 5]+2*dx*str->c[n+ 6]+3*dx2*str->c[n+ 7]
313 +2*dy*(str->c[n+ 9]+2*dx*str->c[n+10]+3*dx2*str->c[n+11])
314 +3*dy2*(str->c[n+13]+2*dx*str->c[n+14]+3*dx2*str->c[n+15]));
315 }
316
317 return err;
318}
Main header file for ASCOT5.
double real
Definition ascot5.h:85
unsigned long int a5err
Simulation error flag.
Definition error.h:17
a5err interp2Dexpl_eval_f(real *f, interp2D_data *str, real x, real y)
Evaluate interpolated value of 2D scalar field.
a5err interp2Dexpl_eval_df(real *f_df, interp2D_data *str, real x, real y)
Evaluate interpolated value and 1st and 2nd derivatives of 2D field.
void interp2Dexpl_init_spline(interp2D_data *str, real *c, int n_x, int n_y, int bc_x, int bc_y, real x_min, real x_max, real y_min, real y_max)
Initialize a bicubic spline.
int interp2Dexpl_init_coeff(real *c, real *f, int n_x, int n_y, int bc_x, int bc_y, real x_min, real x_max, real y_min, real y_max)
Calculate bicubic spline interpolation coefficients for scalar 2D data.
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 splineexpl(real *f, int n, int bc, real *c)
Calculate explicit cubic spline interpolation coefficients in 1D.
Definition splineexpl.c:22
Bicubic interpolation struct.
Definition interp.h:68
real y_min
Definition interp.h:76
real y_grid
Definition interp.h:78
real x_grid
Definition interp.h:75
real x_min
Definition interp.h:73
real y_max
Definition interp.h:77
real x_max
Definition interp.h:74
real * c
Definition interp.h:79