ASCOT5
Loading...
Searching...
No Matches
mhd_nonstat.c
Go to the documentation of this file.
1
5#include <stdlib.h>
6#include "../ascot5.h"
7#include "../print.h"
8#include "../error.h"
9#include "../boozer.h"
10#include "../spline/interp.h"
11#include "../B_field.h"
12#include "../math.h"
13#include "../mhd.h"
14#include "mhd_nonstat.h"
15
38 real** offload_array) {
39
40 /* Allocate array for storing 2D spline coefficients for two quantities
41 * for each mode */
42 real* coeff_array = (real*)malloc(2 * NSIZE_COMP2D * offload_data->n_modes
43 * offload_data->nrho * offload_data->ntime
44 * sizeof(real));
45
46 /* Go through all modes, and evaluate and store coefficients for each */
47 int err = 0;
48 int datasize = offload_data->nrho * offload_data->ntime;
49 int n_modes = offload_data->n_modes;
50 for(int j=0; j<offload_data->n_modes; j++) {
51
52 /* alpha_nm */
54 &coeff_array[NSIZE_COMP2D * datasize * j],
55 &(*offload_array)[j*datasize],
56 offload_data->nrho, offload_data->ntime,
58 offload_data->rho_min,
59 offload_data->rho_max,
60 offload_data->t_min,
61 offload_data->t_max);
62
63 /* phi_nm */
65 &coeff_array[NSIZE_COMP2D * datasize * (n_modes + j)],
66 &(*offload_array)[(n_modes + j)*datasize],
67 offload_data->nrho,
68 offload_data->ntime,
70 offload_data->rho_min,
71 offload_data->rho_max,
72 offload_data->t_min,
73 offload_data->t_max);
74 }
75
76 free(*offload_array);
77 *offload_array = coeff_array;
78 offload_data->offload_array_length = 2 * NSIZE_COMP2D
79 * offload_data->n_modes * offload_data->nrho * offload_data->ntime;
80
81 /* Print some sanity check on data */
82 print_out(VERBOSE_IO, "\nMHD input (non-stationary)\n");
83 print_out(VERBOSE_IO, "Grid: nrho = %4.d rhomin = %3.3f rhomax = %3.3f\n",
84 offload_data->nrho,
85 offload_data->rho_min, offload_data->rho_max);
86 print_out(VERBOSE_IO, " ntime = %4.d tmin = %3.3f tmax = %3.3f\n",
87 offload_data->ntime,
88 offload_data->t_min, offload_data->t_max);
89
90 print_out(VERBOSE_IO, "\nModes:\n");
91 for(int j=0; j<n_modes; j++) {
93 "(n,m) = (%2.d,%2.d) Amplitude = %3.3g Frequency = %3.3g"
94 " Phase = %3.3g\n",
95 offload_data->nmode[j], offload_data->mmode[j],
96 offload_data->amplitude_nm[j], offload_data->omega_nm[j],
97 offload_data->phase_nm[j]);
98 }
99
100 return err;
101}
102
110 real** offload_array) {
111 free(*offload_array);
112}
113
122 mhd_nonstat_offload_data* offload_data,
123 real* offload_array) {
124
125 mhddata->n_modes = offload_data->n_modes;
126
127 int n_modes = offload_data->n_modes;
128 int datasize = NSIZE_COMP2D * offload_data->nrho * offload_data->ntime;
129
130 for(int j=0; j<mhddata->n_modes; j++) {
131 mhddata->nmode[j] = offload_data->nmode[j];
132 mhddata->mmode[j] = offload_data->mmode[j];
133 mhddata->amplitude_nm[j] = offload_data->amplitude_nm[j];
134 mhddata->omega_nm[j] = offload_data->omega_nm[j];
135 mhddata->phase_nm[j] = offload_data->phase_nm[j];
136
137 interp2Dcomp_init_spline(&(mhddata->alpha_nm[j]),
138 &(offload_array[j*datasize]),
139 offload_data->nrho, offload_data->ntime,
141 offload_data->rho_min, offload_data->rho_max,
142 offload_data->t_min, offload_data->t_max);
143
144 interp2Dcomp_init_spline(&(mhddata->phi_nm[j]),
145 &(offload_array[(n_modes + j)*datasize]),
146 offload_data->nrho, offload_data->ntime,
148 offload_data->rho_min, offload_data->rho_max,
149 offload_data->t_min, offload_data->t_max);
150
151 }
152}
153
184a5err mhd_nonstat_eval(real mhd_dmhd[10], real r, real phi, real z, real t,
185 int includemode, boozer_data* boozerdata,
186 mhd_nonstat_data* mhddata, B_field_data* Bdata) {
187
188 a5err err = 0;
189
190 real ptz[12];
191 int isinside;
192 if(!err) {
193 err = boozer_eval_psithetazeta(ptz, &isinside, r, phi, z, Bdata,
194 boozerdata);
195 }
196 real rho[2];
197 if(!err && isinside) {
198 err = B_field_eval_rho(rho, ptz[0], Bdata);
199 }
200
201 int iterations = mhddata->n_modes;
202
203 /* Initialize values */
204 for(int i=0; i<10; i++) {
205 mhd_dmhd[i] = 0;
206 }
207
208 int interperr = 0;
209 for(int i = 0; i < iterations; i++){
210 if( includemode != MHD_INCLUDE_ALL && includemode != i ) { continue; }
211 /* Get interpolated values */
212 real a_da[6], phi_dphi[6];
213 interperr += interp2Dcomp_eval_df(a_da, &(mhddata->alpha_nm[i]),
214 rho[0], t);
215 interperr += interp2Dcomp_eval_df(phi_dphi, &(mhddata->phi_nm[i]),
216 rho[0], t);
217
218 /* The interpolation returns dx/drho but we require dx/dpsi. Second
219 order derivatives are not needed. */
220 a_da[1] *= rho[1];
221 phi_dphi[1] *= rho[1];
222
223 /* These are used frequently, so store them in separate variables */
224 real mhdarg = mhddata->nmode[i] * ptz[8]
225 - mhddata->mmode[i] * ptz[4]
226 - mhddata->omega_nm[i] * t
227 + mhddata->phase_nm[i];
228 real sinmhd = sin(mhdarg);
229 real cosmhd = cos(mhdarg);
230
231 /* Sum over modes to get alpha, phi */
232 mhd_dmhd[0] += a_da[0] * mhddata->amplitude_nm[i] * cosmhd;
233 mhd_dmhd[5] += phi_dphi[0] * mhddata->amplitude_nm[i] * cosmhd;
234
235 /* Time derivatives */
236 mhd_dmhd[1] += a_da[0] * mhddata->amplitude_nm[i]
237 * mhddata->omega_nm[i] * sinmhd
238 + a_da[2] * mhddata->amplitude_nm[i] * cosmhd;
239 mhd_dmhd[6] += phi_dphi[0] * mhddata->amplitude_nm[i]
240 * mhddata->omega_nm[i] * sinmhd
241 + phi_dphi[2] * mhddata->amplitude_nm[i] * cosmhd;
242
243 /* R component of gradients */
244 mhd_dmhd[2] += mhddata->amplitude_nm[i]
245 * ( a_da[1] * ptz[1] * cosmhd
246 + a_da[0] * mhddata->mmode[i] * ptz[5] * sinmhd
247 - a_da[0] * mhddata->nmode[i] * ptz[9] * sinmhd);
248 mhd_dmhd[7] += mhddata->amplitude_nm[i]
249 * ( phi_dphi[1] * ptz[1] * cosmhd
250 + phi_dphi[0] * mhddata->mmode[i] * ptz[5] * sinmhd
251 - phi_dphi[0] * mhddata->nmode[i] * ptz[9] * sinmhd);
252
253 /* phi component of gradients */
254 mhd_dmhd[3] += (1/r) * mhddata->amplitude_nm[i]
255 * ( a_da[1] * ptz[2] * cosmhd
256 + a_da[0] * mhddata->mmode[i] * ptz[6] * sinmhd
257 - a_da[0] * mhddata->nmode[i] * ptz[10] * sinmhd);
258 mhd_dmhd[8] += (1/r) * mhddata->amplitude_nm[i]
259 * ( phi_dphi[1] * ptz[2] * cosmhd
260 + phi_dphi[0] * mhddata->mmode[i] * ptz[6] * sinmhd
261 - phi_dphi[0] * mhddata->nmode[i] * ptz[10] * sinmhd);
262
263 /* z component of gradients */
264 mhd_dmhd[4] += mhddata->amplitude_nm[i]
265 * ( a_da[1] * ptz[3] * cosmhd
266 + a_da[0] * mhddata->mmode[i] * ptz[7] * sinmhd
267 - a_da[0] * mhddata->nmode[i] * ptz[11] * sinmhd);
268 mhd_dmhd[9] += mhddata->amplitude_nm[i]
269 * ( phi_dphi[1] * ptz[3] * cosmhd
270 + phi_dphi[0] * mhddata->mmode[i] * ptz[7] * sinmhd
271 - phi_dphi[0] * mhddata->nmode[i] * ptz[11] * sinmhd);
272 }
273
274 /* Omit evaluation if point outside the boozer or mhd grid. */
275 if(!isinside || interperr) {
276 for(int i=0; i<10; i++) {
277 mhd_dmhd[i] = 0;
278 }
279 }
280
281 return err;
282}
283
316 real pert_field[7], real r, real phi, real z, real t, int pertonly,
317 int includemode, boozer_data* boozerdata, mhd_nonstat_data* mhddata,
318 B_field_data* Bdata) {
319 a5err err = 0;
320 real mhd_dmhd[10];
321 if(!err) {
322 err = mhd_nonstat_eval(mhd_dmhd, r, phi, z, t, includemode, boozerdata,
323 mhddata, Bdata);
324 }
325 /* see example of curl evaluation in step_gc_rk4.c, ydot_gc*/
326 real B_dB[15];
327 if(!err) {
328 err = B_field_eval_B_dB(B_dB, r, phi, z, t, Bdata);
329 }
330
331 if(!err) {
332 real B[3];
333 B[0] = B_dB[0];
334 B[1] = B_dB[4];
335 B[2] = B_dB[8];
336
337 real curlB[3];
338 curlB[0] = B_dB[10]/r - B_dB[7];
339 curlB[1] = B_dB[3] - B_dB[9];
340 curlB[2] = (B[1] - B_dB[2])/r + B_dB[5];
341
342 real gradalpha[3];
343 gradalpha[0] = mhd_dmhd[2];
344 gradalpha[1] = mhd_dmhd[3];
345 gradalpha[2] = mhd_dmhd[4];
346
347 real gradalphacrossB[3];
348
349 math_cross(gradalpha, B, gradalphacrossB);
350
351 pert_field[0] = mhd_dmhd[0]*curlB[0] + gradalphacrossB[0];
352 pert_field[1] = mhd_dmhd[0]*curlB[1] + gradalphacrossB[1];
353 pert_field[2] = mhd_dmhd[0]*curlB[2] + gradalphacrossB[2];
354
355 pert_field[3] = -mhd_dmhd[7] - B[0]*mhd_dmhd[1];
356 pert_field[4] = -mhd_dmhd[8] - B[1]*mhd_dmhd[1];
357 pert_field[5] = -mhd_dmhd[9] - B[2]*mhd_dmhd[1];
358 pert_field[6] = mhd_dmhd[5];
359
360 if(!pertonly) {
361 pert_field[0] += B[0];
362 pert_field[1] += B[1];
363 pert_field[2] += B[2];
364 }
365 }
366
367 return err;
368}
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_eval_B_dB(real B_dB[15], real r, real phi, real z, real t, B_field_data *Bdata)
Evaluate magnetic field and its derivatives.
Definition B_field.c:547
Header file for B_field.c.
Main header file for ASCOT5.
double real
Definition ascot5.h:85
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.
Error module for ASCOT5.
unsigned long int a5err
Simulation error flag.
Definition error.h:17
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.
Header file for math.c.
#define math_cross(a, b, c)
Calculate cross product for 3D vectors c = a x b.
Definition math.h:31
Header file for mhd.c.
#define MHD_INCLUDE_ALL
includemode parameter to include all modes (default)
Definition mhd.h:19
void mhd_nonstat_init(mhd_nonstat_data *mhddata, mhd_nonstat_offload_data *offload_data, real *offload_array)
Initialize MHD data struct on target.
a5err mhd_nonstat_perturbations(real pert_field[7], real r, real phi, real z, real t, int pertonly, int includemode, boozer_data *boozerdata, mhd_nonstat_data *mhddata, B_field_data *Bdata)
Evaluate mhd perturbed fields Btilde, Etilde and potential Phi for full orbit.
int mhd_nonstat_init_offload(mhd_nonstat_offload_data *offload_data, real **offload_array)
Load MHD data and prepare parameters for offload.
Definition mhd_nonstat.c:37
void mhd_nonstat_free_offload(mhd_nonstat_offload_data *offload_data, real **offload_array)
Free offload array.
a5err mhd_nonstat_eval(real mhd_dmhd[10], real r, real phi, real z, real t, int includemode, boozer_data *boozerdata, mhd_nonstat_data *mhddata, B_field_data *Bdata)
Evaluate the needed quantities from MHD mode for orbit following.
Header file for mhd_nonstat.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
MHD parameters on the target.
Definition mhd_nonstat.h:39
MHD parameters that will be offloaded to target.
Definition mhd_nonstat.h:17
real omega_nm[MHD_MODES_MAX_NUM]
Definition mhd_nonstat.h:29
int nmode[MHD_MODES_MAX_NUM]
Definition mhd_nonstat.h:26
real amplitude_nm[MHD_MODES_MAX_NUM]
Definition mhd_nonstat.h:28
int mmode[MHD_MODES_MAX_NUM]
Definition mhd_nonstat.h:27
real phase_nm[MHD_MODES_MAX_NUM]
Definition mhd_nonstat.h:31