ASCOT5
Loading...
Searching...
No Matches
B_3DS.c
Go to the documentation of this file.
1
32#include <stdlib.h>
33#include <stdio.h>
34#include <math.h>
35#include "../math.h"
36#include "../ascot5.h"
37#include "../error.h"
38#include "../print.h"
39#include "B_3DS.h"
40#include "../spline/interp.h"
41
107 int p_n_r, real p_r_min, real p_r_max,
108 int p_n_z, real p_z_min, real p_z_max,
109 int b_n_r, real b_r_min, real b_r_max,
110 int b_n_phi, real b_phi_min, real b_phi_max,
111 int b_n_z, real b_z_min, real b_z_max,
113 real* psi, real* B_r, real* B_phi, real* B_z) {
114
115 int err = 0;
116 data->psi0 = psi0;
117 data->psi1 = psi1;
118 data->axis_r = axis_r;
119 data->axis_z = axis_z;
120
121 /* Set up the splines */
122 err = interp2Dcomp_setup(&data->psi, psi, p_n_r, p_n_z,
124 p_r_min, p_r_max, p_z_min, p_z_max);
125 if(err) {
126 print_err("Error: Failed to initialize splines.\n");
127 return 1;
128 }
129 err = interp3Dcomp_setup(&data->B_r, B_r, b_n_r, b_n_phi, b_n_z,
131 b_r_min, b_r_max, b_phi_min, b_phi_max,
132 b_z_min, b_z_max);
133 if(err) {
134 print_err("Error: Failed to initialize splines.\n");
135 return 1;
136 }
137 err = interp3Dcomp_setup(&data->B_phi, B_phi, b_n_r, b_n_phi, b_n_z,
139 b_r_min, b_r_max, b_phi_min, b_phi_max,
140 b_z_min, b_z_max);
141 if(err) {
142 print_err("Error: Failed to initialize splines.\n");
143 return 1;
144 }
145 err = interp3Dcomp_setup(&data->B_z, B_z, b_n_r, b_n_phi, b_n_z,
147 b_r_min, b_r_max, b_phi_min, b_phi_max,
148 b_z_min, b_z_max);
149 if(err) {
150 print_err("Error: Failed to initialize splines.\n");
151 return 1;
152 }
153
154 /* Evaluate psi and magnetic field on axis for checks */
155 real psival[1], Bval[3];
156 err = B_3DS_eval_psi(psival, data->axis_r, 0, data->axis_z, data);
157 err = B_3DS_eval_B(Bval, data->axis_r, 0, data->axis_z, data);
158 if(err) {
159 print_err("Error: Initialization failed.\n");
160 return err;
161 }
162
163 /* Print some sanity check on data */
164 printf("\n3D magnetic field (B_3DS)\n");
165 print_out(VERBOSE_IO, "Psi-grid: nR = %4.d Rmin = %3.3f m Rmax = %3.3f m\n",
166 p_n_r, p_r_min, p_r_max);
167 print_out(VERBOSE_IO, " nz = %4.d zmin = %3.3f m zmax = %3.3f m\n",
168 p_n_z, p_z_min, p_z_max);
169 print_out(VERBOSE_IO, "B-grid: nR = %4.d Rmin = %3.3f m Rmax = %3.3f m\n",
170 b_n_r, b_r_min, b_r_max);
171 print_out(VERBOSE_IO, " nz = %4.d zmin = %3.3f m zmax = %3.3f m\n",
172 b_n_z, b_z_min, b_z_max);
173 print_out(VERBOSE_IO, "nphi = %4.d phimin = %3.3f deg phimax = %3.3f deg\n",
174 b_n_phi, math_rad2deg(b_phi_min), math_rad2deg(b_phi_max));
175 print_out(VERBOSE_IO, "Psi at magnetic axis (%1.3f m, %1.3f m)\n",
176 data->axis_r, data->axis_z);
177 print_out(VERBOSE_IO, "%3.3f (evaluated)\n%3.3f (given)\n",
178 psival[0], data->psi0);
179 print_out(VERBOSE_IO, "Magnetic field on axis:\n"
180 "B_R = %3.3f B_phi = %3.3f B_z = %3.3f\n",
181 Bval[0], Bval[1], Bval[2]);
182
183 return err;
184}
185
192 free(data->psi.c);
193 free(data->B_r.c);
194 free(data->B_phi.c);
195 free(data->B_z.c);
196}
197
204 GPU_MAP_TO_DEVICE(
205 data->psi, data->B_r, data->B_phi, data->B_z, \
206 data->psi.c[0:data->psi.n_x*data->psi.n_y*NSIZE_COMP2D], \
207 data->B_r.c[0:data->B_r.n_x*data->B_r.n_y*data->B_r.n_z*NSIZE_COMP3D], \
208 data->B_phi.c[0:data->B_phi.n_x*data->B_phi.n_y*data->B_phi.n_z*NSIZE_COMP3D], \
209 data->B_z.c[0:data->B_z.n_x*data->B_z.n_y*data->B_z.n_z*NSIZE_COMP3D]
210 )
211}
212
225 B_3DS_data* Bdata) {
226 a5err err = 0;
227 int interperr = 0; /* If error happened during interpolation */
228 interperr += interp2Dcomp_eval_f(&psi[0], &Bdata->psi, r, z);
229
230 if(interperr) {
231 err = error_raise( ERR_INPUT_EVALUATION, __LINE__, EF_B_3DS );
232 }
233
234 return err;
235}
236
249 B_3DS_data* Bdata) {
250 a5err err = 0;
251 int interperr = 0;
252 real psi_dpsi_temp[6];
253
254 interperr += interp2Dcomp_eval_df(psi_dpsi_temp, &Bdata->psi, r, z);
255
256 psi_dpsi[0] = psi_dpsi_temp[0];
257 psi_dpsi[1] = psi_dpsi_temp[1];
258 psi_dpsi[2] = 0;
259 psi_dpsi[3] = psi_dpsi_temp[2];
260
261 if(interperr) {
262 err = error_raise( ERR_INPUT_EVALUATION, __LINE__, EF_B_3DS );
263 }
264
265 return err;
266}
267
280 B_3DS_data* Bdata) {
281 int interperr = 0; /* If error happened during interpolation */
282 real psi_dpsi[6];
283
284 interperr += interp2Dcomp_eval_df(psi_dpsi, &Bdata->psi, r, z);
285
286 if(interperr) {
287 return error_raise( ERR_INPUT_EVALUATION, __LINE__, EF_B_3DS );
288 }
289
290 /* Check that the values seem valid */
291 real delta = Bdata->psi1 - Bdata->psi0;
292 if( (psi_dpsi[0] - Bdata->psi0) / delta < 0 ) {
293 return error_raise( ERR_INPUT_UNPHYSICAL, __LINE__, EF_B_3DS );
294 }
295
296 /* Normalize psi to get rho */
297 rho_drho[0] = sqrt(fabs((psi_dpsi[0] - Bdata->psi0) / delta));
298
299 rho_drho[1] = psi_dpsi[1] / (2*delta*rho_drho[0]);
300 rho_drho[2] = 0;
301 rho_drho[3] = psi_dpsi[2] / (2*delta*rho_drho[0]);
302
303 return 0;
304}
305
317a5err B_3DS_eval_B(real B[3], real r, real phi, real z, B_3DS_data* Bdata) {
318 a5err err = 0;
319 int interperr = 0;
320
321 interperr += interp3Dcomp_eval_f(&B[0], &Bdata->B_r, r, phi, z);
322 interperr += interp3Dcomp_eval_f(&B[1], &Bdata->B_phi, r, phi, z);
323 interperr += interp3Dcomp_eval_f(&B[2], &Bdata->B_z, r, phi, z);
324
325 /* Test for B field interpolation error */
326 if(interperr) {
327 err = error_raise( ERR_INPUT_EVALUATION, __LINE__, EF_B_3DS );
328 }
329
330 if(!err) {
331 real psi_dpsi[6];
332 interperr += interp2Dcomp_eval_df(psi_dpsi, &Bdata->psi, r, z);
333
334 B[0] = B[0] - psi_dpsi[2]/r;
335 B[2] = B[2] + psi_dpsi[1]/r;
336
337 /* Test for psi interpolation error */
338 if(interperr) {
339 err = error_raise( ERR_INPUT_EVALUATION, __LINE__, EF_B_3DS );
340 }
341 }
342
343 /* Check that magnetic field seems valid */
344 int check = 0;
345 check += ((B[0]*B[0] + B[1]*B[1] + B[2]*B[2]) == 0);
346 if(!err && check) {
347 err = error_raise( ERR_INPUT_UNPHYSICAL, __LINE__, EF_B_3DS );
348 }
349
350 return err;
351}
352
365 B_3DS_data* Bdata) {
366 a5err err = 0;
367 int interperr = 0; /* If error happened during interpolation */
368 real B_dB_temp[10];
369
370 interperr += interp3Dcomp_eval_df(B_dB_temp, &Bdata->B_r, r, phi, z);
371 B_dB[0] = B_dB_temp[0];
372 B_dB[1] = B_dB_temp[1];
373 B_dB[2] = B_dB_temp[2];
374 B_dB[3] = B_dB_temp[3];
375
376 interperr += interp3Dcomp_eval_df(B_dB_temp, &Bdata->B_phi, r, phi, z);
377 B_dB[4] = B_dB_temp[0];
378 B_dB[5] = B_dB_temp[1];
379 B_dB[6] = B_dB_temp[2];
380 B_dB[7] = B_dB_temp[3];
381
382 interperr += interp3Dcomp_eval_df(B_dB_temp, &Bdata->B_z, r, phi, z);
383 B_dB[8] = B_dB_temp[0];
384 B_dB[9] = B_dB_temp[1];
385 B_dB[10] = B_dB_temp[2];
386 B_dB[11] = B_dB_temp[3];
387
388 /* Test for B field interpolation error */
389 if(interperr) {
390 err = error_raise( ERR_INPUT_EVALUATION, __LINE__, EF_B_3DS );
391 }
392
393 if(!err) {
394 real psi_dpsi[6];
395 interperr += interp2Dcomp_eval_df(psi_dpsi, &Bdata->psi, r, z);
396
397 B_dB[0] = B_dB[0] - psi_dpsi[2]/r;
398 B_dB[1] = B_dB[1] + psi_dpsi[2]/(r*r)-psi_dpsi[5]/r;
399 B_dB[3] = B_dB[3] - psi_dpsi[4]/r;
400 B_dB[8] = B_dB[8] + psi_dpsi[1]/r;
401 B_dB[9] = B_dB[9] - psi_dpsi[1]/(r*r) + psi_dpsi[3]/r;
402 B_dB[11] = B_dB[11] + psi_dpsi[5]/r;
403
404 /* Test for psi interpolation error */
405 if(interperr) {
406 err = error_raise( ERR_INPUT_EVALUATION, __LINE__, EF_B_3DS );
407 }
408 }
409
410 /* Check that magnetic field seems valid */
411 int check = 0;
412 check += ((B_dB[0]*B_dB[0] + B_dB[4]*B_dB[4] + B_dB[8]*B_dB[8]) == 0);
413 if(!err && check) {
414 err = error_raise( ERR_INPUT_UNPHYSICAL, __LINE__, EF_B_3DS );
415 }
416
417 return err;
418}
419
429 a5err err = 0;
430 rz[0] = Bdata->axis_r;
431 rz[1] = Bdata->axis_z;
432 return err;
433}
real Bgrid_r_min
Definition B_3DS.c:51
real psigrid_z_max
Definition B_3DS.c:47
real Bgrid_z_max
Definition B_3DS.c:54
real axis_r
Definition B_3DS.c:61
real Bgrid_r_max
Definition B_3DS.c:52
real axis_z
Definition B_3DS.c:62
real psigrid_z_min
Definition B_3DS.c:46
a5err B_3DS_eval_rho_drho(real rho_drho[4], real r, real phi, real z, B_3DS_data *Bdata)
Evaluate normalized poloidal flux rho and its derivatives.
Definition B_3DS.c:279
a5err B_3DS_eval_B(real B[3], real r, real phi, real z, B_3DS_data *Bdata)
Evaluate magnetic field.
Definition B_3DS.c:317
real psigrid_r_max
Definition B_3DS.c:45
a5err B_3DS_eval_psi_dpsi(real psi_dpsi[4], real r, real phi, real z, B_3DS_data *Bdata)
Evaluate poloidal flux psi and its derivatives.
Definition B_3DS.c:248
void B_3DS_free(B_3DS_data *data)
Free allocated resources.
Definition B_3DS.c:191
int Bgrid_n_r
Definition B_3DS.c:49
real psi0
Definition B_3DS.c:59
a5err B_3DS_get_axis_rz(real rz[2], B_3DS_data *Bdata)
Return magnetic axis R-coordinate.
Definition B_3DS.c:428
real psigrid_r_min
Definition B_3DS.c:44
int psigrid_n_r
Definition B_3DS.c:42
a5err B_3DS_eval_psi(real *psi, real r, real phi, real z, B_3DS_data *Bdata)
Evaluate poloidal flux psi.
Definition B_3DS.c:224
real Bgrid_phi_max
Definition B_3DS.c:57
int Bgrid_n_phi
Definition B_3DS.c:55
void B_3DS_offload(B_3DS_data *data)
Offload data to the accelerator.
Definition B_3DS.c:203
a5err B_3DS_eval_B_dB(real B_dB[12], real r, real phi, real z, B_3DS_data *Bdata)
Evaluate magnetic field and its derivatives.
Definition B_3DS.c:364
real Bgrid_phi_min
Definition B_3DS.c:56
int Bgrid_n_z
Definition B_3DS.c:50
int psigrid_n_z
Definition B_3DS.c:43
real psi1
Definition B_3DS.c:60
int B_3DS_init(B_3DS_data *data, int p_n_r, real p_r_min, real p_r_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, 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_3DS.c:106
real Bgrid_z_min
Definition B_3DS.c:53
Header file for B_3DS.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_3DS
Definition error.h:36
@ 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.
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.
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.
DECLARE_TARGET_END a5err interp2Dcomp_eval_f(real *f, interp2D_data *str, real x, real y)
Evaluate interpolated value of a 2D field.
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
3D magnetic field parameters
Definition B_3DS.h:15
interp2D_data psi
Definition B_3DS.h:20
interp3D_data B_r
Definition B_3DS.h:21
real axis_z
Definition B_3DS.h:19
real psi0
Definition B_3DS.h:16
real psi1
Definition B_3DS.h:17
real axis_r
Definition B_3DS.h:18
interp3D_data B_phi
Definition B_3DS.h:22
interp3D_data B_z
Definition B_3DS.h:23
real * c
Definition interp.h:79
real * c
Definition interp.h:101