ASCOT5
Toggle main menu visibility
Loading...
Searching...
No Matches
spline
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
33
int
interp2Dexpl_init_coeff
(
real
* c,
real
* f,
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
108
void
interp2Dexpl_init_spline
(
interp2D_data
* str,
real
* c,
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
146
a5err
interp2Dexpl_eval_f
(
real
* f,
interp2D_data
* str,
real
x,
real
y) {
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
220
a5err
interp2Dexpl_eval_df
(
real
* f_df,
interp2D_data
* str,
real
x,
real
y) {
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
}
ascot5.h
Main header file for ASCOT5.
real
double real
Definition
ascot5.h:85
a5err
unsigned long int a5err
Simulation error flag.
Definition
error.h:17
interp.h
Spline interpolation library.
NATURALBC
@ NATURALBC
Definition
interp.h:37
PERIODICBC
@ PERIODICBC
Definition
interp.h:38
interp2Dexpl_eval_f
a5err interp2Dexpl_eval_f(real *f, interp2D_data *str, real x, real y)
Evaluate interpolated value of 2D scalar field.
Definition
interp2Dexpl.c:146
interp2Dexpl_eval_df
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.
Definition
interp2Dexpl.c:220
interp2Dexpl_init_spline
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.
Definition
interp2Dexpl.c:108
interp2Dexpl_init_coeff
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.
Definition
interp2Dexpl.c:33
fmod
real fmod(real x, real y)
Compute the modulus of two real numbers.
Definition
math.c:22
math.h
Header file for math.c.
spline.h
Header file for splineexpl.c and splinecomp.c.
splineexpl
void splineexpl(real *f, int n, int bc, real *c)
Calculate explicit cubic spline interpolation coefficients in 1D.
Definition
splineexpl.c:22
interp2D_data
Bicubic interpolation struct.
Definition
interp.h:68
interp2D_data::n_y
int n_y
Definition
interp.h:70
interp2D_data::n_x
int n_x
Definition
interp.h:69
interp2D_data::y_min
real y_min
Definition
interp.h:76
interp2D_data::y_grid
real y_grid
Definition
interp.h:78
interp2D_data::x_grid
real x_grid
Definition
interp.h:75
interp2D_data::bc_y
int bc_y
Definition
interp.h:72
interp2D_data::x_min
real x_min
Definition
interp.h:73
interp2D_data::y_max
real y_max
Definition
interp.h:77
interp2D_data::x_max
real x_max
Definition
interp.h:74
interp2D_data::bc_x
int bc_x
Definition
interp.h:71
interp2D_data::c
real * c
Definition
interp.h:79
Generated on
for ASCOT5 by
1.18.0