ASCOT5
Loading...
Searching...
No Matches
B_2DS.c
Go to the documentation of this file.
1
26#include <stdlib.h>
27#include <math.h>
28#include "../math.h"
29#include "../ascot5.h"
30#include "../error.h"
31#include "../print.h"
32#include "B_2DS.h"
33#include "../spline/interp.h"
34
70 real** offload_array) {
71
72 /* Spline initialization */
73 int err = 0;
74 int datasize = offload_data->n_r*offload_data->n_z;
75
76 /* Allocate enough space to store four 2D arrays */
77 real* coeff_array = (real*) malloc(4*NSIZE_COMP2D*datasize*sizeof(real));
78 real* psi = &(coeff_array[0*datasize*NSIZE_COMP2D]);
79 real* B_r = &(coeff_array[1*datasize*NSIZE_COMP2D]);
80 real* B_phi = &(coeff_array[2*datasize*NSIZE_COMP2D]);
81 real* B_z = &(coeff_array[3*datasize*NSIZE_COMP2D]);
82
83 /* Evaluate spline coefficients */
85 psi, *offload_array + 0*datasize,
86 offload_data->n_r, offload_data->n_z,
88 offload_data->r_min, offload_data->r_max,
89 offload_data->z_min, offload_data->z_max);
90
92 B_r, *offload_array + 1*datasize,
93 offload_data->n_r, offload_data->n_z,
95 offload_data->r_min, offload_data->r_max,
96 offload_data->z_min, offload_data->z_max);
97
99 B_phi, *offload_array + 2*datasize,
100 offload_data->n_r, offload_data->n_z,
102 offload_data->r_min, offload_data->r_max,
103 offload_data->z_min, offload_data->z_max);
104
106 B_z, *offload_array + 3*datasize,
107 offload_data->n_r, offload_data->n_z,
109 offload_data->r_min, offload_data->r_max,
110 offload_data->z_min, offload_data->z_max);
111
112 if(err) {
113 print_err("Error: Failed to initialize splines.\n");
114 return err;
115 }
116
117 /* Free offload array and and replace it with the coefficient array */
118 free(*offload_array);
119 *offload_array = coeff_array;
120 offload_data->offload_array_length = 4*NSIZE_COMP2D*datasize;
121
122 /* Initialization complete. Check that the data seem valid. */
123
124 /* Evaluate psi and magnetic field on axis for checks */
125 B_2DS_data Bdata;
126 B_2DS_init(&Bdata, offload_data, *offload_array);
127 real psival[1], Bval[3];
128 err = B_2DS_eval_psi(psival, offload_data->axis_r, 0, offload_data->axis_z,
129 &Bdata);
130 err = B_2DS_eval_B(Bval, offload_data->axis_r, 0, offload_data->axis_z,
131 &Bdata);
132 if(err) {
133 print_err("Error: Initialization failed.\n");
134 return err;
135 }
136
137 /* Print some sanity check on data */
139 "\n2D magnetic field (B_2DS)\n"
140 "Grid: nR = %4.d Rmin = %3.3f Rmax = %3.3f\n"
141 " nz = %4.d zmin = %3.3f zmax = %3.3f\n"
142 "Psi at magnetic axis (%1.3f m, %1.3f m)\n"
143 "%3.3f (evaluated)\n%3.3f (given)\n"
144 "Magnetic field on axis:\n"
145 "B_R = %3.3f B_phi = %3.3f B_z = %3.3f\n",
146 offload_data->n_r,
147 offload_data->r_min, offload_data->r_max,
148 offload_data->n_z,
149 offload_data->z_min, offload_data->z_max,
150 offload_data->axis_r, offload_data->axis_z,
151 psival[0], offload_data->psi0,
152 Bval[0], Bval[1], Bval[2]);
153
154 return err;
155}
156
164 real** offload_array) {
165 free(*offload_array);
166 *offload_array = NULL;
167}
168
176void B_2DS_init(B_2DS_data* Bdata, B_2DS_offload_data* offload_data,
177 real* offload_array) {
178
179 int splinesize = NSIZE_COMP2D * offload_data->n_r * offload_data->n_z;
180
181 /* Initialize target data struct */
182 Bdata->psi0 = offload_data->psi0;
183 Bdata->psi1 = offload_data->psi1;
184 Bdata->axis_r = offload_data->axis_r;
185 Bdata->axis_z = offload_data->axis_z;
186
187 /* Copy parameters and assign pointers to offload array to initialize the
188 spline structs */
189 interp2Dcomp_init_spline(&Bdata->psi, &(offload_array[0*splinesize]),
190 offload_data->n_r,
191 offload_data->n_z,
193 offload_data->r_min,
194 offload_data->r_max,
195 offload_data->z_min,
196 offload_data->z_max);
197
198 interp2Dcomp_init_spline(&Bdata->B_r, &(offload_array[1*splinesize]),
199 offload_data->n_r,
200 offload_data->n_z,
202 offload_data->r_min,
203 offload_data->r_max,
204 offload_data->z_min,
205 offload_data->z_max);
206
207 interp2Dcomp_init_spline(&Bdata->B_phi, &(offload_array[2*splinesize]),
208 offload_data->n_r,
209 offload_data->n_z,
211 offload_data->r_min,
212 offload_data->r_max,
213 offload_data->z_min,
214 offload_data->z_max);
215
216 interp2Dcomp_init_spline(&Bdata->B_z, &(offload_array[3*splinesize]),
217 offload_data->n_r,
218 offload_data->n_z,
220 offload_data->r_min,
221 offload_data->r_max,
222 offload_data->z_min,
223 offload_data->z_max);
224}
225
237a5err B_2DS_eval_psi(real* psi, real r, real phi, real z, B_2DS_data* Bdata) {
238
239 int interperr = 0;
240 interperr += interp2Dcomp_eval_f(&psi[0], &Bdata->psi, r, z);
241
242 a5err err = 0;
243 if(interperr) {
244 err = error_raise( ERR_INPUT_EVALUATION, __LINE__, EF_B_2DS );
245 }
246 return err;
247}
248
261 B_2DS_data* Bdata) {
262
263 int interperr = 0;
264 real psi_dpsi_temp[6];
265
266 interperr += interp2Dcomp_eval_df(psi_dpsi_temp, &Bdata->psi, r, z);
267 psi_dpsi[0] = psi_dpsi_temp[0];
268 psi_dpsi[1] = psi_dpsi_temp[1];
269 psi_dpsi[2] = 0;
270 psi_dpsi[3] = psi_dpsi_temp[2];
271
272 a5err err = 0;
273 if(interperr) {
274 err = error_raise( ERR_INPUT_EVALUATION, __LINE__, EF_B_2DS );
275 }
276
277 return err;
278}
279
292 B_2DS_data* Bdata) {
293 int interperr = 0;
294 real psi_dpsi[6];
295
296 interperr += interp2Dcomp_eval_df(psi_dpsi, &Bdata->psi, r, z);
297
298 a5err err = 0;
299 if(interperr) {
300 err = error_raise( ERR_INPUT_EVALUATION, __LINE__, EF_B_2DS );
301 }
302
303 /* Check that the values seem valid */
304 real delta = Bdata->psi1 - Bdata->psi0;
305 if( !err && (psi_dpsi[0] - Bdata->psi0) / delta < 0 ) {
306 err = error_raise( ERR_INPUT_UNPHYSICAL, __LINE__, EF_B_2DS );
307 }
308
309 /* Normalize psi to get rho */
310 rho_drho[0] = sqrt((psi_dpsi[0] - Bdata->psi0) / delta);
311 rho_drho[1] = psi_dpsi[1] / (2*delta*rho_drho[0]);
312 rho_drho[2] = 0;
313 rho_drho[3] = psi_dpsi[2] / (2*delta*rho_drho[0]);
314
315 return err;
316}
317
329a5err B_2DS_eval_B(real B[3], real r, real phi, real z, B_2DS_data* Bdata) {
330 a5err err = 0;
331 int interperr = 0;
332
333 interperr += interp2Dcomp_eval_f(&B[0], &Bdata->B_r, r, z);
334 interperr += interp2Dcomp_eval_f(&B[1], &Bdata->B_phi, r, z);
335 interperr += interp2Dcomp_eval_f(&B[2], &Bdata->B_z, r, z);
336
337 /* Test for B field interpolation error */
338 if(interperr) {
339 err = error_raise( ERR_INPUT_EVALUATION, __LINE__, EF_B_2DS );
340 }
341
342 if(!err) {
343 real psi_dpsi[6];
344 interperr += interp2Dcomp_eval_df(psi_dpsi, &Bdata->psi, r, z);
345 B[0] = B[0] - psi_dpsi[2]/r;
346 B[2] = B[2] + psi_dpsi[1]/r;
347
348 /* Test for psi interpolation error */
349 if(interperr) {
350 err = error_raise( ERR_INPUT_EVALUATION, __LINE__, EF_B_2DS );
351 }
352 }
353
354 /* Check that magnetic field seems valid */
355 int check = 0;
356 check += ((B[0]*B[0] + B[1]*B[1] + B[2]*B[2]) == 0);
357 if(!err && check) {
358 err = error_raise( ERR_INPUT_UNPHYSICAL, __LINE__, EF_B_2DS );
359 }
360
361 return err;
362}
363
376 B_2DS_data* Bdata) {
377 a5err err = 0;
378 int interperr = 0;
379 real B_dB_temp[6];
380
381 interperr += interp2Dcomp_eval_df(B_dB_temp, &Bdata->B_r, r, z);
382
383 B_dB[0] = B_dB_temp[0];
384 B_dB[1] = B_dB_temp[1];
385 B_dB[2] = 0;
386 B_dB[3] = B_dB_temp[2];
387
388 interperr += interp2Dcomp_eval_df(B_dB_temp, &Bdata->B_phi, r, z);
389
390 B_dB[4] = B_dB_temp[0];
391 B_dB[5] = B_dB_temp[1];
392 B_dB[6] = 0;
393 B_dB[7] = B_dB_temp[2];
394
395 interperr += interp2Dcomp_eval_df(B_dB_temp, &Bdata->B_z, r, z);
396
397 B_dB[8] = B_dB_temp[0];
398 B_dB[9] = B_dB_temp[1];
399 B_dB[10] = 0;
400 B_dB[11] = B_dB_temp[2];
401
402 /* Test for B field interpolation error */
403 if(interperr) {
404 err = error_raise( ERR_INPUT_EVALUATION, __LINE__, EF_B_2DS );
405 }
406
407
408 real psi_dpsi[6];
409
410 if(!err) {
411 interperr += interp2Dcomp_eval_df(psi_dpsi, &Bdata->psi, r, z);
412
413 B_dB[0] = B_dB[0] - psi_dpsi[2]/r;
414 B_dB[1] = B_dB[1] + psi_dpsi[2]/(r*r)-psi_dpsi[5]/r;
415 B_dB[3] = B_dB[3] - psi_dpsi[4]/r;
416 B_dB[8] = B_dB[8] + psi_dpsi[1]/r;
417 B_dB[9] = B_dB[9] - psi_dpsi[1]/(r*r) + psi_dpsi[3]/r;
418 B_dB[11] = B_dB[11] + psi_dpsi[5]/r;
419
420 /* Test for psi interpolation error */
421 if(interperr) {
422 err = error_raise( ERR_INPUT_EVALUATION, __LINE__, EF_B_2DS );
423 }
424 }
425
426 /* Check that magnetic field seems valid */
427 int check = 0;
428 check += ((B_dB[0]*B_dB[0] + B_dB[4]*B_dB[4] + B_dB[8]*B_dB[8]) == 0);
429 if(!err && check) {
430 err = error_raise( ERR_INPUT_UNPHYSICAL, __LINE__, EF_B_2DS );
431 }
432
433 return err;
434}
435
445 a5err err = 0;
446 rz[0] = Bdata->axis_r;
447 rz[1] = Bdata->axis_z;
448 return err;
449}
a5err B_2DS_eval_psi(real *psi, real r, real phi, real z, B_2DS_data *Bdata)
Evaluate poloidal flux psi.
Definition B_2DS.c:237
void B_2DS_free_offload(B_2DS_offload_data *offload_data, real **offload_array)
Free offload array.
Definition B_2DS.c:163
void B_2DS_init(B_2DS_data *Bdata, B_2DS_offload_data *offload_data, real *offload_array)
Initialize magnetic field data struct on target.
Definition B_2DS.c:176
a5err B_2DS_eval_psi_dpsi(real psi_dpsi[4], real r, real phi, real z, B_2DS_data *Bdata)
Evaluate poloidal flux psi and its derivatives.
Definition B_2DS.c:260
a5err B_2DS_eval_rho_drho(real rho_drho[4], real r, real phi, real z, B_2DS_data *Bdata)
Evaluate normalized poloidal flux rho and its derivatives.
Definition B_2DS.c:291
a5err B_2DS_eval_B(real B[3], real r, real phi, real z, B_2DS_data *Bdata)
Evaluate magnetic field.
Definition B_2DS.c:329
a5err B_2DS_get_axis_rz(real rz[2], B_2DS_data *Bdata)
Return magnetic axis R-coordinate.
Definition B_2DS.c:444
a5err B_2DS_eval_B_dB(real B_dB[12], real r, real phi, real z, B_2DS_data *Bdata)
Evaluate magnetic field and its derivatives.
Definition B_2DS.c:375
int B_2DS_init_offload(B_2DS_offload_data *offload_data, real **offload_array)
Initialize magnetic field offload data.
Definition B_2DS.c:69
Header file for B_2DS.c.
Main header file for ASCOT5.
double real
Definition ascot5.h:85
Error module for ASCOT5.
unsigned long int a5err
Simulation error flag.
Definition error.h:17
@ EF_B_2DS
Definition error.h:37
@ ERR_INPUT_EVALUATION
Definition error.h:63
@ ERR_INPUT_UNPHYSICAL
Definition error.h:65
static DECLARE_TARGET_SIMD a5err error_raise(error_type type, int line, error_file file)
Raise a new error.
Definition error.h:86
Spline interpolation library.
@ NATURALBC
Definition interp.h:37
DECLARE_TARGET_END a5err interp2Dcomp_eval_df(real *f_df, interp2D_data *str, real x, real y)
Evaluate interpolated value and 1st and 2nd derivatives of 2D field.
int interp2Dcomp_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.
void interp2Dcomp_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.
DECLARE_TARGET_END a5err interp2Dcomp_eval_f(real *f, interp2D_data *str, real x, real y)
Evaluate interpolated value of a 2D field.
splinesize
Number of coefficients stored for each data point.
Definition interp.h:44
Header file for math.c.
Macros for printing console output.
#define print_out(v,...)
Print to standard output.
Definition print.h:31
@ VERBOSE_IO
Definition print.h:20
#define print_err(...)
Print to standard error.
Definition print.h:42
2D magnetic field parameters on the target
Definition B_2DS.h:34
2D magnetic field parameters that will be offloaded to target
Definition B_2DS.h:17
int offload_array_length
Definition B_2DS.h:28