ASCOT5
Loading...
Searching...
No Matches
mhd_stat.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_stat.h"
15
38 real** offload_array) {
39
40 /* Allocate array for storing 1D spline coefficients for two quantities
41 * for each mode */
42 real* coeff_array = (real*)malloc(2 * NSIZE_COMP1D * offload_data->n_modes
43 * offload_data->nrho * sizeof(real));
44
45 /* Go through all modes, and evaluate and store coefficients for each */
46 int err = 0;
47 int datasize = offload_data->nrho;
48 int n_modes = offload_data->n_modes;
49 for(int j=0; j<offload_data->n_modes; j++) {
50
51 /* alpha_nm */
53 &coeff_array[NSIZE_COMP1D * datasize * j],
54 &(*offload_array)[j*datasize],
55 offload_data->nrho,
57 offload_data->rho_min,
58 offload_data->rho_max);
59
60 /* phi_nm */
62 &coeff_array[NSIZE_COMP1D * datasize * (n_modes + j)],
63 &(*offload_array)[(n_modes + j)*datasize],
64 offload_data->nrho,
66 offload_data->rho_min,
67 offload_data->rho_max);
68 }
69
70 free(*offload_array);
71 *offload_array = coeff_array;
72 offload_data->offload_array_length = 2 * NSIZE_COMP1D
73 * offload_data->n_modes * offload_data->nrho;
74
75 /* Print some sanity check on data */
76 print_out(VERBOSE_IO, "\nMHD (stationary) input\n");
77 print_out(VERBOSE_IO, "Grid: nrho = %4.d rhomin = %3.3f rhomax = %3.3f\n",
78 offload_data->nrho,
79 offload_data->rho_min, offload_data->rho_max);
80
81 print_out(VERBOSE_IO, "\nModes:\n");
82 for(int j=0; j<n_modes; j++) {
84 "(n,m) = (%2.d,%2.d) Amplitude = %3.3g Frequency = %3.3g"
85 " Phase = %3.3g\n",
86 offload_data->nmode[j], offload_data->mmode[j],
87 offload_data->amplitude_nm[j], offload_data->omega_nm[j],
88 offload_data->phase_nm[j]);
89 }
90
91 return err;
92}
93
101 real** offload_array) {
102 free(*offload_array);
103}
104
113 real* offload_array) {
114
115 mhddata->n_modes = offload_data->n_modes;
116 mhddata->rho_min = offload_data->rho_min;
117 mhddata->rho_max = offload_data->rho_max;
118
119 int n_modes = offload_data->n_modes;
120 int datasize = NSIZE_COMP1D * offload_data->nrho;
121
122 for(int j=0; j<mhddata->n_modes; j++) {
123 mhddata->nmode[j] = offload_data->nmode[j];
124 mhddata->mmode[j] = offload_data->mmode[j];
125 mhddata->amplitude_nm[j] = offload_data->amplitude_nm[j];
126 mhddata->omega_nm[j] = offload_data->omega_nm[j];
127 mhddata->phase_nm[j] = offload_data->phase_nm[j];
128
129 interp1Dcomp_init_spline(&(mhddata->alpha_nm[j]),
130 &(offload_array[j*datasize]),
131 offload_data->nrho,
132 NATURALBC,
133 offload_data->rho_min, offload_data->rho_max);
134
135 interp1Dcomp_init_spline(&(mhddata->phi_nm[j]),
136 &(offload_array[(n_modes + j)*datasize]),
137 offload_data->nrho,
138 NATURALBC,
139 offload_data->rho_min, offload_data->rho_max);
140
141 }
142}
143
174a5err mhd_stat_eval(real mhd_dmhd[10], real r, real phi, real z, real t,
175 int includemode, boozer_data* boozerdata,
176 mhd_stat_data* mhddata, B_field_data* Bdata) {
177
178 a5err err = 0;
179
180 real ptz[12];
181 int isinside;
182 if(!err) {
183 err = boozer_eval_psithetazeta(ptz, &isinside, r, phi, z, Bdata,
184 boozerdata);
185 }
186 real rho[2];
187 if(!err && isinside) {
188 err = B_field_eval_rho(rho, ptz[0], Bdata);
189 }
190
191 /* Initialize values */
192 for(int i=0; i<10; i++) {
193 mhd_dmhd[i] = 0;
194 }
195
196 int interperr = 0;
197 for(int i = 0; i < mhddata->n_modes; i++){
198 if( includemode != MHD_INCLUDE_ALL && includemode != i ) { continue; }
199 /* Get interpolated values */
200 real a_da[3], phi_dphi[3];
201 interperr += interp1Dcomp_eval_df(a_da, &(mhddata->alpha_nm[i]),
202 rho[0]);
203 interperr += interp1Dcomp_eval_df(phi_dphi, &(mhddata->phi_nm[i]),
204 rho[0]);
205
206 /* The interpolation returns dx/drho but we require dx/dpsi.
207 * The second order derivatives are not needed anywhere */
208 a_da[1] *= rho[1];
209 phi_dphi[1] *= rho[1];
210
211 /* These are used frequently, so store them in separate variables */
212 real mhdarg = mhddata->nmode[i] * ptz[8]
213 - mhddata->mmode[i] * ptz[4]
214 - mhddata->omega_nm[i] * t
215 + mhddata->phase_nm[i];
216 real sinmhd = sin(mhdarg);
217 real cosmhd = cos(mhdarg);
218
219 /* Sum over modes to get alpha, phi */
220 mhd_dmhd[0] += a_da[0] * mhddata->amplitude_nm[i] * cosmhd;
221 mhd_dmhd[5] += phi_dphi[0] * mhddata->amplitude_nm[i] * cosmhd;
222
223 /* Time derivatives */
224 mhd_dmhd[1] += a_da[0] * mhddata->amplitude_nm[i]
225 * mhddata->omega_nm[i] * sinmhd;
226 mhd_dmhd[6] += phi_dphi[0] * mhddata->amplitude_nm[i]
227 * mhddata->omega_nm[i] * sinmhd;
228
229 /* R component of gradients */
230 mhd_dmhd[2] += mhddata->amplitude_nm[i]
231 * ( a_da[1] * ptz[1] * cosmhd
232 + a_da[0] * mhddata->mmode[i] * ptz[5] * sinmhd
233 - a_da[0] * mhddata->nmode[i] * ptz[9] * sinmhd);
234 mhd_dmhd[7] += mhddata->amplitude_nm[i]
235 * ( phi_dphi[1] * ptz[1] * cosmhd
236 + phi_dphi[0] * mhddata->mmode[i] * ptz[5] * sinmhd
237 - phi_dphi[0] * mhddata->nmode[i] * ptz[9] * sinmhd);
238
239 /* phi component of gradients */
240 mhd_dmhd[3] += (1/r) * mhddata->amplitude_nm[i]
241 * ( a_da[1] * ptz[2] * cosmhd
242 + a_da[0] * mhddata->mmode[i] * ptz[6] * sinmhd
243 - a_da[0] * mhddata->nmode[i] * ptz[10] * sinmhd);
244 mhd_dmhd[8] += (1/r) * mhddata->amplitude_nm[i]
245 * ( phi_dphi[1] * ptz[2] * cosmhd
246 + phi_dphi[0] * mhddata->mmode[i] * ptz[6] * sinmhd
247 - phi_dphi[0] * mhddata->nmode[i] * ptz[10] * sinmhd);
248
249 /* z component of gradients */
250 mhd_dmhd[4] += mhddata->amplitude_nm[i]
251 * ( a_da[1] * ptz[3] * cosmhd
252 + a_da[0] * mhddata->mmode[i] * ptz[7] * sinmhd
253 - a_da[0] * mhddata->nmode[i] * ptz[11] * sinmhd);
254 mhd_dmhd[9] += mhddata->amplitude_nm[i]
255 * ( phi_dphi[1] * ptz[3] * cosmhd
256 + phi_dphi[0] * mhddata->mmode[i] * ptz[7] * sinmhd
257 - phi_dphi[0] * mhddata->nmode[i] * ptz[11] * sinmhd);
258 }
259
260 /* Omit evaluation if point outside the boozer or mhd grid. */
261 if(!isinside || interperr) {
262 for(int i=0; i<10; i++) {
263 mhd_dmhd[i] = 0;
264 }
265 }
266 return err;
267}
268
300 real t, int pertonly, int includemode,
301 boozer_data* boozerdata, mhd_stat_data* mhddata,
302 B_field_data* Bdata) {
303 a5err err = 0;
304 real mhd_dmhd[10];
305 if(!err) {
306 err = mhd_stat_eval(mhd_dmhd, r, phi, z, t, includemode, boozerdata,
307 mhddata, Bdata);
308 }
309 /* see example of curl evaluation in step_gc_rk4.c, ydot_gc*/
310 real B_dB[15];
311 if(!err) {
312 err = B_field_eval_B_dB(B_dB, r, phi, z, t, Bdata);
313 }
314
315 if(!err) {
316 real B[3];
317 B[0] = B_dB[0];
318 B[1] = B_dB[4];
319 B[2] = B_dB[8];
320
321 real curlB[3];
322 curlB[0] = B_dB[10]/r - B_dB[7];
323 curlB[1] = B_dB[3] - B_dB[9];
324 curlB[2] = (B[1] - B_dB[2])/r + B_dB[5];
325
326 real gradalpha[3];
327 gradalpha[0] = mhd_dmhd[2];
328 gradalpha[1] = mhd_dmhd[3];
329 gradalpha[2] = mhd_dmhd[4];
330
331 real gradalphacrossB[3];
332
333 math_cross(gradalpha, B, gradalphacrossB);
334
335 pert_field[0] = mhd_dmhd[0]*curlB[0] + gradalphacrossB[0];
336 pert_field[1] = mhd_dmhd[0]*curlB[1] + gradalphacrossB[1];
337 pert_field[2] = mhd_dmhd[0]*curlB[2] + gradalphacrossB[2];
338
339 pert_field[3] = -mhd_dmhd[7] - B[0]*mhd_dmhd[1];
340 pert_field[4] = -mhd_dmhd[8] - B[1]*mhd_dmhd[1];
341 pert_field[5] = -mhd_dmhd[9] - B[2]*mhd_dmhd[1];
342 pert_field[6] = mhd_dmhd[5];
343
344 if(!pertonly) {
345 pert_field[0] += B[0];
346 pert_field[1] += B[1];
347 pert_field[2] += B[2];
348 }
349 }
350
351 return err;
352}
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
int interp1Dcomp_init_coeff(real *c, real *f, int n_x, int bc_x, real x_min, real x_max)
Calculate cubic spline interpolation coefficients for scalar 1D data.
a5err interp1Dcomp_eval_df(real *f_df, interp1D_data *str, real x)
Evaluate interpolated value of 1D and its 1st and 2nd derivatives.
void interp1Dcomp_init_spline(interp1D_data *str, real *c, int n_x, int bc_x, real x_min, real x_max)
Initialize a cubic 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_stat_free_offload(mhd_stat_offload_data *offload_data, real **offload_array)
Free offload array.
Definition mhd_stat.c:100
a5err mhd_stat_perturbations(real pert_field[7], real r, real phi, real z, real t, int pertonly, int includemode, boozer_data *boozerdata, mhd_stat_data *mhddata, B_field_data *Bdata)
Evaluate perturbed fields Btilde, Etilde and potential Phi explicitly.
Definition mhd_stat.c:299
a5err mhd_stat_eval(real mhd_dmhd[10], real r, real phi, real z, real t, int includemode, boozer_data *boozerdata, mhd_stat_data *mhddata, B_field_data *Bdata)
Evaluate the needed quantities from MHD mode for orbit following.
Definition mhd_stat.c:174
int mhd_stat_init_offload(mhd_stat_offload_data *offload_data, real **offload_array)
Load MHD data and prepare parameters for offload.
Definition mhd_stat.c:37
void mhd_stat_init(mhd_stat_data *mhddata, mhd_stat_offload_data *offload_data, real *offload_array)
Initialize MHD data struct on target.
Definition mhd_stat.c:112
Header file for mhd_stat.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 stat parameters on the target.
Definition mhd_stat.h:36
MHD stat parameters that will be offloaded to target.
Definition mhd_stat.h:17
int mmode[MHD_MODES_MAX_NUM]
Definition mhd_stat.h:24
real phase_nm[MHD_MODES_MAX_NUM]
Definition mhd_stat.h:28
int nmode[MHD_MODES_MAX_NUM]
Definition mhd_stat.h:23
real amplitude_nm[MHD_MODES_MAX_NUM]
Definition mhd_stat.h:25
real omega_nm[MHD_MODES_MAX_NUM]
Definition mhd_stat.h:26