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
38int boozer_init(boozer_data* data, int npsi, real psi_min, real psi_max,
39 int ntheta, int nthetag, real* nu, real* theta,
40 int nrzs, real* rs, real* zs) {
41
42 int err = 0;
43 real THETAMIN = 0;
44 real THETAMAX = CONST_2PI;
45 real padding = ( 4.0*CONST_2PI ) / ( nthetag - 2*4.0 - 1 );
46 data->psi_min = psi_min;
47 data->psi_max = psi_max;
48
49 err = interp2Dcomp_setup(&data->nu_psitheta, nu, npsi, ntheta,
50 NATURALBC, PERIODICBC, psi_min, psi_max,
51 THETAMIN, THETAMAX);
52 err = interp2Dcomp_setup(&data->theta_psithetageom, theta, npsi, nthetag,
53 NATURALBC, NATURALBC, psi_min, psi_max,
54 THETAMIN-padding, THETAMAX+padding);
55
56 data->nrzs = nrzs;
57 data->rs = (real*) malloc( nrzs * sizeof(real) );
58 data->zs = (real*) malloc( nrzs * sizeof(real) );
59 for(int i = 0; i < nrzs; i++) {
60 data->rs[i] = rs[i];
61 data->zs[i] = zs[i];
62 }
63
64 /* Print some sanity check on data */
65 print_out(VERBOSE_IO, "\nBoozer input\n");
66 print_out(VERBOSE_IO, "psi grid: n = %4.d min = %3.3f max = %3.3f\n",
67 npsi, psi_min, psi_max);
68 print_out(VERBOSE_IO, "thetageo grid: n = %4.d\n", nthetag);
69 print_out(VERBOSE_IO, "thetabzr grid: n = %4.d\n", ntheta);
70
71 return err;
72}
73
80 free(data->rs);
81 free(data->zs);
82 free(data->nu_psitheta.c);
83 free(data->theta_psithetageom.c);
84}
85
92 // TODO: Implement
93}
94
124a5err boozer_eval_psithetazeta(real psithetazeta[12], int* isinside,
125 real r, real phi, real z, B_field_data* Bdata,
126 boozer_data* boozerdata) {
127 a5err err = 0;
128 int interperr = 0;
129
130 /* Winding number to test whether we are inside the plasma (and not in the
131 private plasma region) */
132 isinside[0]=0;
133 if(math_point_in_polygon(r, z, boozerdata->rs, boozerdata->zs,
134 boozerdata->nrzs)) {
135 /* Get the psi value and check that it is within the psi grid (the grid
136 does not extend all the way to the axis) Use t = 0.0 s */
137 real psi[4], rho[2], r0, z0;
138 err = B_field_eval_psi_dpsi(psi, r, phi, z, 0.0, Bdata);
139 if(!err) {
140 err = B_field_eval_rho(rho, psi[0], Bdata);
141 }
142 if(!err) {
143 real rz[2];
144 err = B_field_get_axis_rz(rz, Bdata, phi);
145 r0 = rz[0];
146 z0 = rz[1];
147 }
148
149 if(!err && psi[0] < boozerdata->psi_max &&
150 psi[0] > boozerdata->psi_min) {
151
152 /* Update the flag, and we are good to go */
153 isinside[0]=1;
154
155 /* Geometrical theta */
156 real thgeo;
157 thgeo = fmod( atan2(z-z0,r-r0) + CONST_2PI,
158 CONST_2PI);
159
160 /* Boozer theta and derivatives */
161 real theta[6];
162 interperr += interp2Dcomp_eval_df(
163 theta, &boozerdata->theta_psithetageom, psi[0], thgeo);
164
165 /* Boozer nu function and derivatives */
166 real nu[6];
167 interperr += interp2Dcomp_eval_df(
168 nu, &boozerdata->nu_psitheta, psi[0], theta[0]);
169
170 /* Set up data for returning the requested values */
171
172 /* Psi and derivatives */
173 psithetazeta[0]=psi[0]; /* psi */
174 psithetazeta[1]=psi[1]; /* dpsi_dr */
175 psithetazeta[2]=0; /* dpsi_dphi */
176 psithetazeta[3]=psi[3]; /* dpsi_dz */
177
178 /* Helpers */
179 real asq;
180 asq = (r - r0) * (r - r0)
181 + (z - z0) * (z - z0);
182 real dthgeo_dr;
183 dthgeo_dr=-(z-z0)/asq;
184 real dthgeo_dz;
185 dthgeo_dz=(r-r0)/asq;
186
187 /* Theta and derivatives */
188 psithetazeta[4]=theta[0]; /* theta */
189 psithetazeta[5]=theta[1]*psi[1]+theta[2]*dthgeo_dr;/* dtheta_dr */
190 psithetazeta[6]=0; /* dtheta_dphi */
191 psithetazeta[7]=theta[1]*psi[3]+theta[2]*dthgeo_dz;/* dtheta_dz */
192
193 /* Zeta and derivatives */
194 psithetazeta[8]=fmod(phi+nu[0], CONST_2PI); /* zeta */
195 psithetazeta[9]=nu[1]*psi[1]+nu[2]*psithetazeta[5]; /* dzeta_dR */
196 psithetazeta[10]=1.0; /* dzeta_dphi*/
197 psithetazeta[11]=nu[1]*psi[3]+nu[2]*psithetazeta[7]; /* dzeta_dz */
198
199 /* Make sure zeta is between [0, 2pi]*/
200 psithetazeta[8]=fmod(psithetazeta[8] + CONST_2PI, CONST_2PI);
201 }
202 }
203
204 if(!err && interperr) {
205 err = error_raise( ERR_INPUT_EVALUATION, __LINE__, EF_BOOZER );
206 }
207
208 return err;
209}
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:166
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:228
a5err B_field_get_axis_rz(real rz[2], B_field_data *Bdata, real phi)
Return magnetic axis Rz-coordinates.
Definition B_field.c:501
Header file for B_field.c.
Main header file for ASCOT5.
double real
Definition ascot5.h:85
void boozer_offload(boozer_data *data)
Offload data to the accelerator.
Definition boozer.c:91
void boozer_free(boozer_data *data)
Free allocated resources.
Definition boozer.c:79
int boozer_init(boozer_data *data, int npsi, real psi_min, real psi_max, int ntheta, int nthetag, real *nu, real *theta, int nrzs, real *rs, real *zs)
Initialize boozer coordinate transformation.
Definition boozer.c:38
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:124
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.
int interp2Dcomp_setup(interp2D_data *str, 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)
Set up splines to interpolate 2D scalar data.
@ 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 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:41
Data for mapping between the cylindrical and Boozer coordinates.
Definition boozer.h:16
int nrzs
Definition boozer.h:23
interp2D_data theta_psithetageom
Definition boozer.h:26
real psi_max
Definition boozer.h:18
interp2D_data nu_psitheta
Definition boozer.h:24
real psi_min
Definition boozer.h:17
real * rs
Definition boozer.h:19
real * zs
Definition boozer.h:21
real * c
Definition interp.h:79