ASCOT5
Loading...
Searching...
No Matches
B_STS.c
Go to the documentation of this file.
1
28#include <stdlib.h>
29#include <stdio.h>
30#include <math.h>
31#include <string.h>
32#include "../math.h"
33#include "../ascot5.h"
34#include "../error.h"
35#include "../print.h"
36#include "../consts.h"
37#include "B_STS.h"
38#include "../linint/linint.h"
39#include "../spline/interp.h"
40
82 int p_n_r, real p_r_min, real p_r_max,
83 int p_n_phi, real p_phi_min, real p_phi_max,
84 int p_n_z, real p_z_min, real p_z_max,
85 int b_n_r, real b_r_min, real b_r_max,
86 int b_n_phi, real b_phi_min, real b_phi_max,
87 int b_n_z, real b_z_min, real b_z_max,
88 int naxis, real axis_min, real axis_max,
90 real* psi, real* B_r, real* B_phi, real* B_z) {
91
92 /* Spline initialization. */
93 int err = 0;
94 data->psi0 = psi0;
95 data->psi1 = psi1;
96 err = interp3Dcomp_setup(&data->psi, psi, p_n_r, p_n_phi, p_n_z,
98 p_r_min, p_r_max, p_phi_min, p_phi_max,
99 p_z_min, p_z_max);
100 if(err) {
101 print_err("Error: Failed to initialize splines.\n");
102 return 1;
103 }
105 &data->B_r, B_r, b_n_r, b_n_phi, b_n_z,
107 b_r_min, b_r_max, b_phi_min, b_phi_max, b_z_min, b_z_max);
108 if(err) {
109 print_err("Error: Failed to initialize splines.\n");
110 return 1;
111 }
113 &data->B_phi, B_phi, b_n_r, b_n_phi, b_n_z,
115 b_r_min, b_r_max, b_phi_min, b_phi_max, b_z_min, b_z_max);
116 if(err) {
117 print_err("Error: Failed to initialize splines.\n");
118 return 1;
119 }
121 &data->B_z, B_z, b_n_r, b_n_phi, b_n_z,
123 b_r_min, b_r_max, b_phi_min, b_phi_max, b_z_min, b_z_max);
124 if(err) {
125 print_err("Error: Failed to initialize splines.\n");
126 return 1;
127 }
128
129 real* c1 = (real*)malloc(naxis*sizeof(real));
130 real* c2 = (real*)malloc(naxis*sizeof(real));
131 for(int i = 0; i < naxis; i++) {
132 c1[i] = axis_r[i];
133 c2[i] = axis_z[i];
134 }
135 linint1D_init(&data->axis_r, c1, naxis, PERIODICBC, axis_min, axis_max);
136 linint1D_init(&data->axis_z, c2, naxis, PERIODICBC, axis_min, axis_max);
137
138 /* Evaluate psi and magnetic field on axis for checks */
139 real psival[1], Bval[3], axis[2];
140 err += B_STS_get_axis_rz(axis, data, 0);
141 err += B_STS_eval_psi(psival, axis[0], 0, axis[1], data);
142 err += B_STS_eval_B(Bval, axis[0], 0, axis[1], data);
143 if(err) {
144 print_err("Error: Initialization failed.\n");
145 return err;
146 }
147
148 printf("\nStellarator magnetic field (B_STS)\n");
149 print_out(VERBOSE_IO, "Psi-grid: nR = %4.d Rmin = %3.3f m Rmax = %3.3f m\n",
150 p_n_r, p_r_min, p_r_max);
151 print_out(VERBOSE_IO, " nz = %4.d zmin = %3.3f m zmax = %3.3f m\n",
152 p_n_z, p_z_min, p_z_max);
153 print_out(VERBOSE_IO, "nphi = %4.d phimin = %3.3f deg phimax = %3.3f deg\n",
154 p_n_phi, math_rad2deg(p_phi_min), math_rad2deg(p_phi_max));
155 print_out(VERBOSE_IO, "B-grid: nR = %4.d Rmin = %3.3f m Rmax = %3.3f m\n",
156 b_n_r, b_r_min, b_r_max);
157 print_out(VERBOSE_IO, " nz = %4.d zmin = %3.3f m zmax = %3.3f m\n",
158 b_n_z, b_z_min, b_z_max);
159 print_out(VERBOSE_IO, "nphi = %4.d phimin = %3.3f deg phimax = %3.3f deg\n",
160 b_n_phi, math_rad2deg(b_phi_min), math_rad2deg(b_phi_max));
161 print_out(VERBOSE_IO, "Psi at magnetic axis (phi=0) (%1.3f m, %1.3f m)\n",
162 axis[0], axis[1]);
163 print_out(VERBOSE_IO, "%3.3f (evaluated)\n%3.3f (given)\n",
164 psival[0], data->psi0);
165 print_out(VERBOSE_IO, "Magnetic field on axis:\n"
166 "B_R = %3.3f B_phi = %3.3f B_z = %3.3f\n",
167 Bval[0], Bval[1], Bval[2]);
168
169 return 0;
170}
171
178 free(data->psi.c);
179 free(data->B_r.c);
180 free(data->B_phi.c);
181 free(data->B_z.c);
182}
183
190 GPU_MAP_TO_DEVICE(
191 data->axis_r, data->axis_r.c[0:data->axis_r.n_x], \
192 data->axis_z, data->axis_z.c[0:data->axis_z.n_x], \
193 data->psi, data->B_r, data->B_phi, data->B_z, \
194 data->psi.c[0:data->psi.n_x*data->psi.n_y*data->psi.n_z*NSIZE_COMP3D], \
195 data->B_r.c[0:data->B_r.n_x*data->B_r.n_y*data->B_r.n_z*NSIZE_COMP3D],\
196 data->B_phi.c[0:data->B_phi.n_x*data->B_phi.n_y *data->B_phi.n_z*NSIZE_COMP3D], \
197 data->B_z.c[0:data->B_z.n_x*data->B_z.n_y*data->B_z.n_z*NSIZE_COMP3D]
198 )
199}
200
213 B_STS_data* Bdata) {
214 a5err err = 0;
215 int interperr = 0; /* If error happened during interpolation */
216
217 interperr += interp3Dcomp_eval_f(&psi[0], &Bdata->psi, r, phi, z);
218
219#ifdef B_STS_CLAMP_RHO_NONNEGATIVE
220 if ( psi[0] < Bdata->psi0 ){
221 psi[0] = Bdata->psi0;
222 }
223#endif
224
225 /* Test for psi interpolation error */
226 if(interperr) {
227 return error_raise( ERR_INPUT_EVALUATION, __LINE__, EF_B_STS );
228 }
229
230 return err;
231}
232
245 B_STS_data* Bdata) {
246 a5err err = 0;
247 int interperr = 0; /* If error happened during interpolation */
248 real psi_dpsi_temp[10];
249
250 interperr += interp3Dcomp_eval_df(psi_dpsi_temp, &Bdata->psi, r, phi, z);
251
252
253 psi_dpsi[0] = psi_dpsi_temp[0];
254 psi_dpsi[1] = psi_dpsi_temp[1];
255 psi_dpsi[2] = psi_dpsi_temp[2];
256 psi_dpsi[3] = psi_dpsi_temp[3];
257
258#ifdef B_STS_CLAMP_RHO_NONNEGATIVE
259 if ( psi_dpsi_temp[0] < Bdata->psi0 ){
260 psi_dpsi[0] = Bdata->psi0;
261 psi_dpsi[1] = 0.0;
262 psi_dpsi[2] = 0.0;
263 psi_dpsi[3] = 0.0;
264 }
265#endif
266
267
268 if(interperr) {
269 return error_raise( ERR_INPUT_EVALUATION, __LINE__, EF_B_STS );
270 }
271
272 return err;
273}
274
287 B_STS_data* Bdata) {
288 a5err err = 0;
289 real psi_dpsi[4];
290
291 err = B_STS_eval_psi_dpsi(psi_dpsi, r, phi, z, Bdata);
292 if(err){
293 return error_raise( ERR_INPUT_UNPHYSICAL, __LINE__, EF_B_STS );
294 }
295
296 /* Check that the values seem valid */
297 real delta = Bdata->psi1 - Bdata->psi0;
298 if( (psi_dpsi[0] - Bdata->psi0) / delta <= 0 ) {
299#ifdef B_STS_CLAMP_RHO_NONNEGATIVE
300 /* Set rho and the partial derivatives to zero, because otherwise one
301 would need to divide by rho, which is zero. Of course, this problem
302 persists when B_STS_CLAMP_RHO_NONNEGATIVE is not defined and
303 the evaluation happens exactly at rho=0.0 */
304 rho_drho[0] = 0.0;
305 rho_drho[1] = 0.0;
306 rho_drho[2] = 0.0;
307 rho_drho[3] = 0.0;
308 return err;
309#else
310 return error_raise( ERR_INPUT_UNPHYSICAL, __LINE__, EF_B_STS );
311#endif
312 }
313
314 /* Normalize psi to get rho */
315 rho_drho[0] = sqrt( (psi_dpsi[0] - Bdata->psi0) / delta );
316
317 rho_drho[1] = psi_dpsi[1] / (2*delta*rho_drho[0]);
318 rho_drho[2] = psi_dpsi[2] / (2*delta*rho_drho[0]);
319 rho_drho[3] = psi_dpsi[3] / (2*delta*rho_drho[0]);
320
321 return err;
322}
323
335a5err B_STS_eval_B(real B[3], real r, real phi, real z, B_STS_data* Bdata) {
336 a5err err = 0;
337 int interperr = 0; /* If error happened during interpolation */
338
339 interperr += interp3Dcomp_eval_f(&B[0], &Bdata->B_r, r, phi, z);
340 interperr += interp3Dcomp_eval_f(&B[1], &Bdata->B_phi, r, phi, z);
341 interperr += interp3Dcomp_eval_f(&B[2], &Bdata->B_z, r, phi, z);
342
343 /* Test for B field interpolation error */
344 if(interperr) {
345 return error_raise( ERR_INPUT_EVALUATION, __LINE__, EF_B_STS );
346 }
347
348 /* Check that magnetic field seems valid */
349 int check = 0;
350 check += ((B[0]*B[0] + B[1]*B[1] + B[2]*B[2]) == 0);
351 if(!err && check) {
352 return error_raise( ERR_INPUT_UNPHYSICAL, __LINE__, EF_B_STS );
353 }
354
355 return err;
356
357}
358
371 B_STS_data* Bdata) {
372 a5err err = 0;
373 int interperr = 0; /* If error happened during interpolation */
374 real B_dB_temp[10];
375
376 interperr += interp3Dcomp_eval_df(B_dB_temp, &Bdata->B_r, r, phi, z);
377
378 B_dB[0] = B_dB_temp[0];
379 B_dB[1] = B_dB_temp[1];
380 B_dB[2] = B_dB_temp[2];
381 B_dB[3] = B_dB_temp[3];
382
383 interperr += interp3Dcomp_eval_df(B_dB_temp, &Bdata->B_phi, r, phi, z);
384
385 B_dB[4] = B_dB_temp[0];
386 B_dB[5] = B_dB_temp[1];
387 B_dB[6] = B_dB_temp[2];
388 B_dB[7] = B_dB_temp[3];
389
390 interperr += interp3Dcomp_eval_df(B_dB_temp, &Bdata->B_z, r, phi, z);
391
392 B_dB[8] = B_dB_temp[0];
393 B_dB[9] = B_dB_temp[1];
394 B_dB[10] = B_dB_temp[2];
395 B_dB[11] = B_dB_temp[3];
396
397 /* Test for B field interpolation error */
398 if(interperr) {
399 return error_raise( ERR_INPUT_EVALUATION, __LINE__, EF_B_STS );
400 }
401
402 /* Check that magnetic field seems valid */
403 int check = 0;
404 check += ((B_dB[0]*B_dB[0] + B_dB[4]*B_dB[4] + B_dB[8]*B_dB[8]) == 0);
405 if(!err && check) {
406 return error_raise( ERR_INPUT_UNPHYSICAL, __LINE__, EF_B_STS );
407 }
408
409 return 0;
410}
411
422 a5err err = 0;
423
424 int interperr = 0; /* If error happened during interpolation */
425 interperr += linint1D_eval_f(&rz[0], &Bdata->axis_r, phi);
426 interperr += linint1D_eval_f(&rz[1], &Bdata->axis_z, phi);
427 if(interperr) {
428 err = error_raise( ERR_INPUT_EVALUATION, __LINE__, EF_B_STS );
429 }
430 return err;
431}
real axis_r
Definition B_3DS.c:61
real axis_z
Definition B_3DS.c:62
real psi0
Definition B_3DS.c:59
real psi1
Definition B_3DS.c:60
void B_STS_offload(B_STS_data *data)
Offload data to the accelerator.
Definition B_STS.c:189
a5err B_STS_eval_rho_drho(real rho_drho[4], real r, real phi, real z, B_STS_data *Bdata)
Evaluate normalized poloidal flux rho and its derivatives.
Definition B_STS.c:286
int B_STS_init(B_STS_data *data, int p_n_r, real p_r_min, real p_r_max, int p_n_phi, real p_phi_min, real p_phi_max, int p_n_z, real p_z_min, real p_z_max, int b_n_r, real b_r_min, real b_r_max, int b_n_phi, real b_phi_min, real b_phi_max, int b_n_z, real b_z_min, real b_z_max, int naxis, real axis_min, real axis_max, real *axis_r, real *axis_z, real psi0, real psi1, real *psi, real *B_r, real *B_phi, real *B_z)
Initialize magnetic field data.
Definition B_STS.c:81
a5err B_STS_eval_B_dB(real B_dB[12], real r, real phi, real z, B_STS_data *Bdata)
Evaluate magnetic field and its derivatives.
Definition B_STS.c:370
void B_STS_free(B_STS_data *data)
Free allocated resources.
Definition B_STS.c:177
a5err B_STS_eval_psi(real *psi, real r, real phi, real z, B_STS_data *Bdata)
Evaluate poloidal flux psi.
Definition B_STS.c:212
a5err B_STS_eval_psi_dpsi(real psi_dpsi[4], real r, real phi, real z, B_STS_data *Bdata)
Evaluate poloidal flux psi and its derivatives.
Definition B_STS.c:244
a5err B_STS_get_axis_rz(real rz[2], B_STS_data *Bdata, real phi)
Return magnetic axis Rz-coordinates.
Definition B_STS.c:421
a5err B_STS_eval_B(real B[3], real r, real phi, real z, B_STS_data *Bdata)
Evaluate magnetic field.
Definition B_STS.c:335
Header file for B_STS.c.
Main header file for ASCOT5.
double real
Definition ascot5.h:85
Header file containing physical and mathematical constants.
Error module for ASCOT5.
unsigned long int a5err
Simulation error flag.
Definition error.h:17
@ EF_B_STS
Definition error.h:38
@ 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.
DECLARE_TARGET_END a5err interp3Dcomp_eval_f(real *f, interp3D_data *str, real x, real y, real z)
Evaluate interpolated value of 3D scalar field.
int interp3Dcomp_setup(interp3D_data *str, real *f, int n_x, int n_y, int n_z, int bc_x, int bc_y, int bc_z, real x_min, real x_max, real y_min, real y_max, real z_min, real z_max)
Set up splines to interpolate 3D scalar data.
@ NATURALBC
Definition interp.h:37
@ PERIODICBC
Definition interp.h:38
DECLARE_TARGET_END a5err interp3Dcomp_eval_df(real *f_df, interp3D_data *str, real x, real y, real z)
Evaluate interpolated value of 3D field and 1st and 2nd derivatives.
Linear interpolation library.
int linint1D_eval_f(real *f, linint1D_data *str, real x)
Evaluate interpolated value of 1D scalar field.
Definition linint1D.c:47
void linint1D_init(linint1D_data *str, real *c, int n_x, int bc_x, real x_min, real x_max)
Initialize linear interpolation struct for scalar 1D data.
Definition linint1D.c:22
Header file for math.c.
#define math_rad2deg(a)
Convert radians to degrees.
Definition math.h:110
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
stellarator magnetic field parameters on the target
Definition B_STS.h:15
interp3D_data psi
Definition B_STS.h:20
real psi1
Definition B_STS.h:17
real psi0
Definition B_STS.h:16
interp3D_data B_z
Definition B_STS.h:23
interp3D_data B_phi
Definition B_STS.h:22
linint1D_data axis_z
Definition B_STS.h:19
interp3D_data B_r
Definition B_STS.h:21
linint1D_data axis_r
Definition B_STS.h:18
real * c
Definition interp.h:101
real * c
Definition linint.h:27