ASCOT5
Loading...
Searching...
No Matches
boozer.c
Go to the documentation of this file.
1
5#include <stdlib.h>
6#include <math.h>
7#include "print.h"
8#include "ascot5.h"
9#include "consts.h"
10#include "math.h"
11#include "error.h"
12#include "B_field.h"
13#include "boozer.h"
14#include "spline/interp.h"
15
38 real** offload_array) {
39
40 int err = 0;
41
42 /* Size of 2D grids and 1D data */
43 int nusize = offload_data->npsi * offload_data->ntheta;
44 int thetasize = offload_data->npsi * offload_data->nthetag;
45 int contoursize = offload_data->nrzs;
46
47 /* Grid limits for theta_bzr and theta_geo grids */
48 real THETAMIN = 0;
49 real THETAMAX = CONST_2PI;
50 real padding = (4.0*CONST_2PI)/(offload_data->nthetag-2*4.0 -1);
51
52 /* Allocate array for storing coefficients (which later replaces the
53 offload array) and contour points */
54 real* coeff_array = (real*)malloc( ( ( nusize + thetasize)
55 * NSIZE_COMP2D + 2*contoursize )
56 * sizeof(real) );
57
58 /* Evaluate and store coefficients */
59
60 /* nu */
62 &coeff_array[0],
63 &(*offload_array)[0],
64 offload_data->npsi, offload_data->ntheta,
66 offload_data->psi_min, offload_data->psi_max,
67 THETAMIN, THETAMAX);
68
69 /* theta_bzr */
71 &coeff_array[nusize * NSIZE_COMP2D],
72 &(*offload_array)[nusize],
73 offload_data->npsi, offload_data->nthetag,
75 offload_data->psi_min, offload_data->psi_max,
76 THETAMIN-padding, THETAMAX+padding);
77
78 for(int i = 0; i < contoursize; i++) {
79 coeff_array[(nusize + thetasize)*NSIZE_COMP2D + i] =
80 (*offload_array)[nusize + thetasize + i];
81 coeff_array[(nusize + thetasize)*NSIZE_COMP2D + contoursize + i] =
82 (*offload_array)[nusize + thetasize + contoursize + i];
83 }
84
85 free(*offload_array);
86 *offload_array = coeff_array;
87 offload_data->offload_array_length = (nusize + thetasize)
88 * NSIZE_COMP2D + 2 * contoursize;
89
90 /* Print some sanity check on data */
91 print_out(VERBOSE_IO, "\nBoozer input\n");
92 print_out(VERBOSE_IO, "psi grid: n = %4.d min = %3.3f max = %3.3f\n",
93 offload_data->npsi,
94 offload_data->psi_min, offload_data->psi_max);
95 print_out(VERBOSE_IO, "thetageo grid: n = %4.d\n", offload_data->nthetag);
96 print_out(VERBOSE_IO, "thetabzr grid: n = %4.d\n", offload_data->ntheta);
97
98 return err;
99}
100
108void boozer_init(boozer_data* boozerdata, boozer_offload_data* offload_data,
109 real* offload_array) {
110
111 boozerdata->psi_min = offload_data->psi_min;
112 boozerdata->psi_max = offload_data->psi_max;
113
114 /* Grid limits for theta_bzr and theta_geo grids*/
115 real THETAMIN = 0;
116 real THETAMAX = CONST_2PI;
117 real padding = (4.0*CONST_2PI)/(offload_data->nthetag-2*4.0-1);
118
119 /* Size of 1D and 2D input data arrays */
120 int nusize = offload_data->npsi * offload_data->ntheta * NSIZE_COMP2D;
121 int thetasize = offload_data->npsi * offload_data->nthetag * NSIZE_COMP2D;
122 int contoursize = offload_data->nrzs;
123
124 /* Initialize splines */
126 &(offload_array[0]),
127 offload_data->npsi,
128 offload_data->ntheta,
130 offload_data->psi_min,
131 offload_data->psi_max,
132 THETAMIN, THETAMAX);
133
135 &(offload_array[nusize]),
136 offload_data->npsi,
137 offload_data->nthetag,
139 offload_data->psi_min,
140 offload_data->psi_max,
141 THETAMIN-padding, THETAMAX+padding);
142
143 boozerdata->rs = &(offload_array[nusize + thetasize]);
144 boozerdata->zs = &(offload_array[nusize + thetasize + contoursize]);
145 boozerdata->nrzs = offload_data->nrzs;
146}
147
155 real** offload_array) {
156 free(*offload_array);
157}
158
188a5err boozer_eval_psithetazeta(real psithetazeta[12], int* isinside,
189 real r, real phi, real z, B_field_data* Bdata,
190 boozer_data* boozerdata) {
191 a5err err = 0;
192 int interperr = 0;
193
194 /* Winding number to test whether we are inside the plasma (and not in the
195 private plasma region) */
196 isinside[0]=0;
197 if(math_point_in_polygon(r, z, boozerdata->rs, boozerdata->zs,
198 boozerdata->nrzs)) {
199 /* Get the psi value and check that it is within the psi grid (the grid
200 does not extend all the way to the axis) Use t = 0.0 s */
201 real psi[4], rho[2], r0, z0;
202 err = B_field_eval_psi_dpsi(psi, r, phi, z, 0.0, Bdata);
203 if(!err) {
204 err = B_field_eval_rho(rho, psi[0], Bdata);
205 }
206 if(!err) {
207 real rz[2];
208 err = B_field_get_axis_rz(rz, Bdata, phi);
209 r0 = rz[0];
210 z0 = rz[1];
211 }
212
213 if(!err && psi[0] < boozerdata->psi_max &&
214 psi[0] > boozerdata->psi_min) {
215
216 /* Update the flag, and we are good to go */
217 isinside[0]=1;
218
219 /* Geometrical theta */
220 real thgeo;
221 thgeo = fmod( atan2(z-z0,r-r0) + CONST_2PI,
222 CONST_2PI);
223
224 /* Boozer theta and derivatives */
225 real theta[6];
226 interperr += interp2Dcomp_eval_df(
227 theta, &boozerdata->theta_psithetageom, psi[0], thgeo);
228
229 /* Boozer nu function and derivatives */
230 real nu[6];
231 interperr += interp2Dcomp_eval_df(
232 nu, &boozerdata->nu_psitheta, psi[0], theta[0]);
233
234 /* Set up data for returning the requested values */
235
236 /* Psi and derivatives */
237 psithetazeta[0]=psi[0]; /* psi */
238 psithetazeta[1]=psi[1]; /* dpsi_dr */
239 psithetazeta[2]=0; /* dpsi_dphi */
240 psithetazeta[3]=psi[3]; /* dpsi_dz */
241
242 /* Helpers */
243 real asq;
244 asq = (r - r0) * (r - r0)
245 + (z - z0) * (z - z0);
246 real dthgeo_dr;
247 dthgeo_dr=-(z-z0)/asq;
248 real dthgeo_dz;
249 dthgeo_dz=(r-r0)/asq;
250
251 /* Theta and derivatives */
252 psithetazeta[4]=theta[0]; /* theta */
253 psithetazeta[5]=theta[1]*psi[1]+theta[2]*dthgeo_dr;/* dtheta_dr */
254 psithetazeta[6]=0; /* dtheta_dphi */
255 psithetazeta[7]=theta[1]*psi[3]+theta[2]*dthgeo_dz;/* dtheta_dz */
256
257 /* Zeta and derivatives */
258 psithetazeta[8]=fmod(phi+nu[0], CONST_2PI); /* zeta */
259 psithetazeta[9]=nu[1]*psi[1]+nu[2]*psithetazeta[5]; /* dzeta_dR */
260 psithetazeta[10]=1.0; /* dzeta_dphi*/
261 psithetazeta[11]=nu[1]*psi[3]+nu[2]*psithetazeta[7]; /* dzeta_dz */
262
263 /* Make sure zeta is between [0, 2pi]*/
264 psithetazeta[8]=fmod(psithetazeta[8] + CONST_2PI, CONST_2PI);
265 }
266 }
267
268 if(!err && interperr) {
269 err = error_raise( ERR_INPUT_EVALUATION, __LINE__, EF_BOOZER );
270 }
271
272 return err;
273}
a5err B_field_eval_psi_dpsi(real psi_dpsi[4], real r, real phi, real z, real t, B_field_data *Bdata)
Evaluate poloidal flux psi and its derivatives.
Definition B_field.c:265
a5err B_field_eval_rho(real rho[2], real psi, B_field_data *Bdata)
Evaluate normalized poloidal flux rho and its psi derivative.
Definition B_field.c:327
a5err B_field_get_axis_rz(real rz[2], B_field_data *Bdata, real phi)
Return magnetic axis Rz-coordinates.
Definition B_field.c:599
Header file for B_field.c.
Main header file for ASCOT5.
double real
Definition ascot5.h:85
void boozer_free_offload(boozer_offload_data *offload_data, real **offload_array)
Free offload array.
Definition boozer.c:154
int boozer_init_offload(boozer_offload_data *offload_data, real **offload_array)
Load Boozer data and prepare parameters for offload.
Definition boozer.c:37
void boozer_init(boozer_data *boozerdata, boozer_offload_data *offload_data, real *offload_array)
Initialize boozer data struct on target.
Definition boozer.c:108
a5err boozer_eval_psithetazeta(real psithetazeta[12], int *isinside, real r, real phi, real z, B_field_data *Bdata, boozer_data *boozerdata)
Evaluate Boozer coordinates and partial derivatives.
Definition boozer.c:188
Header file for boozer.c.
Header file containing physical and mathematical constants.
#define CONST_2PI
2*pi
Definition consts.h:14
Error module for ASCOT5.
unsigned long int a5err
Simulation error flag.
Definition error.h:17
@ EF_BOOZER
Definition error.h:48
@ ERR_INPUT_EVALUATION
Definition error.h:63
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
@ PERIODICBC
Definition interp.h:38
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.
int math_point_in_polygon(real r, real z, real *rv, real *zv, int n)
Check if coordinates are within polygon.
Definition math.c:427
real fmod(real x, real y)
Compute the modulus of two real numbers.
Definition math.c:22
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
Magnetic field simulation data.
Definition B_field.h:63
Boozer parameters on the target.
Definition boozer.h:29
int nrzs
Definition boozer.h:36
interp2D_data theta_psithetageom
Definition boozer.h:39
real psi_max
Definition boozer.h:31
interp2D_data nu_psitheta
Definition boozer.h:37
real psi_min
Definition boozer.h:30
real * rs
Definition boozer.h:32
real * zs
Definition boozer.h:34
offload data for maps between boozer and cylindrical coordinates
Definition boozer.h:16
int offload_array_length
Definition boozer.h:23