ASCOT5
Loading...
Searching...
No Matches
particle.c
Go to the documentation of this file.
1
47#include <stdio.h>
48#include <stdlib.h>
49#include <math.h>
50#include "ascot5.h"
51#include "error.h"
52#include "consts.h"
53#include "math.h"
54#include "physlib.h"
55#include "gctransform.h"
56#include "particle.h"
57#include "B_field.h"
58#include "E_field.h"
59
70 p_fo->r = malloc(nmrk * sizeof(p_fo->r) );
71 p_fo->phi = malloc(nmrk * sizeof(p_fo->phi) );
72 p_fo->z = malloc(nmrk * sizeof(p_fo->z) );
73 p_fo->p_r = malloc(nmrk * sizeof(p_fo->p_r) );
74 p_fo->p_phi = malloc(nmrk * sizeof(p_fo->p_phi) );
75 p_fo->p_z = malloc(nmrk * sizeof(p_fo->p_z) );
76 p_fo->mass = malloc(nmrk * sizeof(p_fo->mass) );
77 p_fo->charge = malloc(nmrk * sizeof(p_fo->charge));
78 p_fo->time = malloc(nmrk * sizeof(p_fo->time) );
79 p_fo->znum = malloc(nmrk * sizeof(p_fo->znum) );
80 p_fo->anum = malloc(nmrk * sizeof(p_fo->anum) );
81
82 /* Magnetic field data */
83 p_fo->B_r = malloc(nmrk * sizeof(p_fo->B_r) );
84 p_fo->B_phi = malloc(nmrk * sizeof(p_fo->B_phi) );
85 p_fo->B_z = malloc(nmrk * sizeof(p_fo->B_z) );
86 p_fo->B_r_dr = malloc(nmrk * sizeof(p_fo->B_r_dr) );
87 p_fo->B_phi_dr = malloc(nmrk * sizeof(p_fo->B_phi_dr) );
88 p_fo->B_z_dr = malloc(nmrk * sizeof(p_fo->B_z_dr) );
89 p_fo->B_r_dphi = malloc(nmrk * sizeof(p_fo->B_r_dphi) );
90 p_fo->B_phi_dphi = malloc(nmrk * sizeof(p_fo->B_phi_dphi));
91 p_fo->B_z_dphi = malloc(nmrk * sizeof(p_fo->B_z_dphi) );
92 p_fo->B_r_dz = malloc(nmrk * sizeof(p_fo->B_r_dz) );
93 p_fo->B_phi_dz = malloc(nmrk * sizeof(p_fo->B_phi_dz) );
94 p_fo->B_z_dz = malloc(nmrk * sizeof(p_fo->B_z_dz) );
95
96 /* Quantities used in diagnostics */
97 p_fo->bounces = malloc(nmrk * sizeof(p_fo->bounces));
98 p_fo->weight = malloc(nmrk * sizeof(p_fo->weight) );
99 p_fo->cputime = malloc(nmrk * sizeof(p_fo->cputime));
100 p_fo->rho = malloc(nmrk * sizeof(p_fo->rho) );
101 p_fo->theta = malloc(nmrk * sizeof(p_fo->theta) );
102
103 p_fo->id = malloc(nmrk * sizeof(p_fo->id) );
104 p_fo->endcond = malloc(nmrk * sizeof(p_fo->endcond) );
105 p_fo->walltile = malloc(nmrk * sizeof(p_fo->walltile));
106
107 /* Meta data */
108 p_fo->mileage = malloc(nmrk * sizeof(p_fo->mileage));
109
110 p_fo->running = malloc(nmrk * sizeof(p_fo->running));
111
112 p_fo->err = malloc(nmrk * sizeof(p_fo->err) );
113 p_fo->index = malloc(nmrk * sizeof(p_fo->index));
114 p_fo->n_mrk = nmrk;
115}
116
127 /* Physical coordinates and parameters */
128 p_gc->r = malloc(nmrk * sizeof(p_gc->r) );
129 p_gc->phi = malloc(nmrk * sizeof(p_gc->phi) );
130 p_gc->z = malloc(nmrk * sizeof(p_gc->z) );
131 p_gc->ppar = malloc(nmrk * sizeof(p_gc->ppar) );
132 p_gc->mu = malloc(nmrk * sizeof(p_gc->mu) );
133 p_gc->zeta = malloc(nmrk * sizeof(p_gc->zeta) );
134 p_gc->mass = malloc(nmrk * sizeof(p_gc->mass) );
135 p_gc->charge = malloc(nmrk * sizeof(p_gc->charge) );
136 p_gc->time = malloc(nmrk * sizeof(p_gc->time) );
137
138 /* Magnetic field data */
139 p_gc->B_r = malloc(nmrk * sizeof(p_gc->B_r) );
140 p_gc->B_phi = malloc(nmrk * sizeof(p_gc->B_phi) );
141 p_gc->B_z = malloc(nmrk * sizeof(p_gc->B_z) );
142 p_gc->B_r_dr = malloc(nmrk * sizeof(p_gc->B_r_dr) );
143 p_gc->B_phi_dr = malloc(nmrk * sizeof(p_gc->B_phi_dr) );
144 p_gc->B_z_dr = malloc(nmrk * sizeof(p_gc->B_z_dr) );
145 p_gc->B_r_dphi = malloc(nmrk * sizeof(p_gc->B_r_dphi) );
146 p_gc->B_phi_dphi = malloc(nmrk * sizeof(p_gc->B_phi_dphi) );
147 p_gc->B_z_dphi = malloc(nmrk * sizeof(p_gc->B_z_dphi) );
148 p_gc->B_r_dz = malloc(nmrk * sizeof(p_gc->B_r_dz) );
149 p_gc->B_phi_dz = malloc(nmrk * sizeof(p_gc->B_phi_dz) );
150 p_gc->B_z_dz = malloc(nmrk * sizeof(p_gc->B_z_dz) );
151
152 /* Quantities used in diagnostics */
153 p_gc->bounces = malloc(nmrk * sizeof(p_gc->bounces));
154 p_gc->weight = malloc(nmrk * sizeof(p_gc->weight) );
155 p_gc->cputime = malloc(nmrk * sizeof(p_gc->cputime) );
156 p_gc->rho = malloc(nmrk * sizeof(p_gc->rho) );
157 p_gc->theta = malloc(nmrk * sizeof(p_gc->theta) );
158 p_gc->id = malloc(nmrk * sizeof(p_gc->id) );
159 p_gc->endcond = malloc(nmrk * sizeof(p_gc->endcond) );
160 p_gc->walltile = malloc(nmrk * sizeof(p_gc->walltile) );
161
162 /* Meta data */
163 p_gc->mileage = malloc(nmrk * sizeof(p_gc->mileage) );
164 p_gc->running = malloc(nmrk * sizeof(p_gc->running) );
165 p_gc->err = malloc(nmrk * sizeof(p_gc->err) );
166 p_gc->index = malloc(nmrk * sizeof(p_gc->index) );
167 p_gc->n_mrk = nmrk;
168}
169
185 p_fo->r[j] = 1;
186 p_fo->phi[j] = 1;
187 p_fo->z[j] = 1;
188 p_fo->p_r[j] = 1;
189 p_fo->p_phi[j] = 1;
190 p_fo->p_z[j] = 1;
191 p_fo->mass[j] = 1;
192 p_fo->charge[j] = 1;
193 p_fo->znum[j] = 1;
194 p_fo->anum[j] = 1;
195 p_fo->bounces[j] = 0;
196 p_fo->weight[j] = 0;
197 p_fo->time[j] = 0;
198 p_fo->id[j] = -1;
199 p_fo->mileage[j] = 0;
200 p_fo->running[j] = 0;
201 p_fo->endcond[j] = 0;
202 p_fo->walltile[j] = 0;
203 p_fo->B_r[j] = 1;
204 p_fo->B_phi[j] = 1;
205 p_fo->B_z[j] = 1;
206 p_fo->index[j] = -1;
207 p_fo->err[j] = 0;
208}
209
225 p_gc->r[j] = 1;
226 p_gc->phi[j] = 1;
227 p_gc->z[j] = 1;
228 p_gc->ppar[j] = 1;
229 p_gc->mu[j] = 1;
230 p_gc->zeta[j] = 1;
231 p_gc->mass[j] = 1;
232 p_gc->charge[j] = 1;
233 p_gc->time[j] = 0;
234 p_gc->bounces[j] = 0;
235 p_gc->weight[j] = 0;
236 p_gc->id[j] = -1;
237 p_gc->mileage[j] = 0;
238 p_gc->B_r[j] = 1;
239 p_gc->B_r_dr[j] = 1;
240 p_gc->B_r_dphi[j] = 1;
241 p_gc->B_r_dz[j] = 1;
242
243 p_gc->B_phi[j] = 1;
244 p_gc->B_phi_dr[j] = 1;
245 p_gc->B_phi_dphi[j] = 1;
246 p_gc->B_phi_dz[j] = 1;
247
248 p_gc->B_z[j] = 1;
249 p_gc->B_z_dr[j] = 1;
250 p_gc->B_z_dphi[j] = 1;
251 p_gc->B_z_dz[j] = 1;
252 p_gc->index[j] = -1;
253 p_gc->err[j] = 0;
254}
255
271 p_ml->r[j] = 1;
272 p_ml->phi[j] = 1;
273 p_ml->z[j] = 1;
274 p_ml->time[j] = 0;
275 p_ml->id[j] = -1;
276 p_ml->mileage[j] = 0;
277 p_ml->B_r[j] = 1;
278 p_ml->B_r_dr[j] = 1;
279 p_ml->B_r_dphi[j] = 1;
280 p_ml->B_r_dz[j] = 1;
281
282 p_ml->B_phi[j] = 1;
283 p_ml->B_phi_dr[j] = 1;
284 p_ml->B_phi_dphi[j] = 1;
285 p_ml->B_phi_dz[j] = 1;
286
287 p_ml->B_z[j] = 1;
288 p_ml->B_z_dr[j] = 1;
289 p_ml->B_z_dphi[j] = 1;
290 p_ml->B_z_dz[j] = 1;
291 p_ml->index[j] = -1;
292 p_ml->err[j] = 0;
293}
294
321 B_field_data* Bdata, int* cycle) {
322
323 /* Loop over markers.
324 * A SIMD loop is not possible as we modify the queue. */
325 for(int i = 0; i < p->n_mrk; i++) {
326
327 /* First check whether we should pick a new marker */
328 int newmarker = 0;
329
330 /* 1. There are markers in queue and this marker is dummy */
331 if(p->id[i] < 0 && q->next < q->n) {
332 newmarker = 1;
333 }
334
335 /* 2. This marker has finished simulation */
336 if(!p->running[i] && p->id[i] >= 0) {
337 /* Convert finished marker to state
338 * and store it back to the queue */
339 particle_fo_to_state(p, i, q->p[p->index[i]], Bdata);
340 newmarker = 1;
341 #pragma omp critical
342 q->finished++;
343 }
344
345 /* Init a new marker if one is needed */
346 cycle[i] = 0;
347 while(newmarker) {
348 /* Get the next unsimulated marker from the queue */
349 int i_prt;
350 #pragma omp critical
351 i_prt = q->next++;
352
353 if(i_prt >= q->n) {
354 /* The queue is empty, place a dummy marker here */
355 p->running[i] = 0;
356 p->id[i] = -1;
357 cycle[i] = -1;
358 newmarker = 0;
359 }
360 else if(q->p[i_prt]->endcond) {
361 /* This marker already has an active end condition. Try next. */
362 #pragma omp critical
363 q->finished++;
364 }
365 else {
366 /* Try to convert marker state to a simulation marker */
368 q->p[i_prt], i_prt, p, i, Bdata);
369 if(err) {
370 /* Failed! Mark the marker candidate as finished
371 * and try with a new marker state*/
372 q->p[i_prt]->err = err;
373 #pragma omp critical
374 q->finished++;
375 }
376 else {
377 /* Success! We are good to go. */
378 cycle[i] = 1;
379 newmarker = 0;
380 }
381 }
382 }
383 }
384
385 int n_running = 0;
386 #pragma omp simd reduction(+:n_running)
387 for(int i = 0; i < p->n_mrk; i++) {
388 n_running += p->running[i];
389 }
390
391 return n_running;
392}
393
420 B_field_data* Bdata, int* cycle) {
421
422 /* Loop over markers.
423 * A SIMD loop is not possible as we modify the queue. */
424 for(int i = 0; i < p->n_mrk; i++) {
425
426 /* First check whether we should pick a new marker */
427 int newmarker = 0;
428
429 /* 1. There are markers in queue and this marker is dummy */
430 if(p->id[i] < 0 && q->next < q->n) {
431 newmarker = 1;
432 }
433
434 /* 2. This marker has finished simulation */
435 if(!p->running[i] && p->id[i] >= 0) {
436 /* Convert finished marker to state
437 * and store it back to the queue */
438 particle_gc_to_state(p, i, q->p[p->index[i]], Bdata);
439 newmarker = 1;
440 #pragma omp critical
441 q->finished++;
442 }
443
444 /* Init a new marker if one is needed */
445 cycle[i] = 0;
446 while(newmarker) {
447 /* Get the next unsimulated marker from the queue */
448 int i_prt;
449 #pragma omp critical
450 i_prt = q->next++;
451
452 if(i_prt >= q->n) {
453 /* The queue is empty, place a dummy marker here */
454 p->running[i] = 0;
455 p->id[i] = -1;
456 cycle[i] = -1;
457 newmarker = 0;
458 }
459 else {
460 /* Try to convert marker state to a simulation marker */
462 q->p[i_prt], i_prt, p, i, Bdata);
463 if(err) {
464 /* Failed! Mark the marker candidate as finished
465 * and try with a new marker state*/
466 q->p[i_prt]->err = err;
467 #pragma omp critical
468 q->finished++;
469 }
470 else {
471 /* Success! We are good to go. */
472 cycle[i] = 1;
473 newmarker = 0;
474 }
475 }
476 }
477 }
478
479 int n_running = 0;
480 #pragma omp simd reduction(+:n_running)
481 for(int i = 0; i < p->n_mrk; i++) {
482 n_running += p->running[i];
483 }
484
485 return n_running;
486}
487
514 B_field_data* Bdata, int* cycle) {
515
516 /* Loop over markers.
517 * A SIMD loop is not possible as we modify the queue. */
518 for(int i = 0; i < NSIMD; i++) {
519
520 /* First check whether we should pick a new marker */
521 int newmarker = 0;
522
523 /* 1. There are markers in queue and this marker is dummy */
524 if(p->id[i] < 0 && q->next < q->n) {
525 newmarker = 1;
526 }
527
528 /* 2. This marker has finished simulation */
529 if(!p->running[i] && p->id[i] >= 0) {
530 /* Convert finished marker to state
531 * and store it back to the queue */
532 particle_ml_to_state(p, i, q->p[p->index[i]], Bdata);
533 newmarker = 1;
534 #pragma omp critical
535 q->finished++;
536 }
537
538 /* Init a new marker if one is needed */
539 cycle[i] = 0;
540 while(newmarker) {
541 /* Get the next unsimulated marker from the queue */
542 int i_prt;
543 #pragma omp critical
544 i_prt = q->next++;
545
546 if(i_prt >= q->n) {
547 /* The queue is empty, place a dummy marker here */
548 p->running[i] = 0;
549 p->id[i] = -1;
550 cycle[i] = -1;
551 newmarker = 0;
552 }
553 else {
554 /* Try to convert marker state to a simulation marker */
556 q->p[i_prt], i_prt, p, i, Bdata);
557 if(err) {
558 /* Failed! Mark the marker candidate as finished
559 * and try with a new marker state*/
560 q->p[i_prt]->err = err;
561 #pragma omp critical
562 q->finished++;
563 }
564 else {
565 /* Success! We are good to go. */
566 cycle[i] = 1;
567 newmarker = 0;
568 }
569 }
570 }
571 }
572
573 int n_running = 0;
574 #pragma omp simd reduction(+:n_running)
575 for(int i = 0; i < NSIMD; i++) {
576 n_running += p->running[i];
577 }
578
579 return n_running;
580}
581
603 B_field_data* Bdata) {
604 a5err err = 0;
605 integer id = 0;
606
607 if(p->type == input_particle_type_p) {
608 /* Check that input is valid */
609 if(!err && p->p.r <= 0) {
610 err = error_raise(ERR_MARKER_UNPHYSICAL, __LINE__, EF_PARTICLE);
611 }
612 if(!err && p->p.mass <= 0) {
613 err = error_raise(ERR_MARKER_UNPHYSICAL, __LINE__, EF_PARTICLE);
614 }
615 if(!err && p->p.weight <= 0) {
616 err = error_raise(ERR_MARKER_UNPHYSICAL, __LINE__, EF_PARTICLE);
617 }
618 if(!err && p->p.id <= 0) {
619 err = error_raise(ERR_MARKER_UNPHYSICAL, __LINE__, EF_PARTICLE);
620 }
621
622 /* Particle to state */
624 id = p->p.id;
625 if(!err) {
626 err = particle_input_p_to_state(&p->p, ps, Bdata);
627 }
628 }
629 else if(p->type == input_particle_type_gc) {
630 /* Check that input is valid */
631 if(!err && p->p_gc.r <= 0) {
632 err = error_raise(ERR_MARKER_UNPHYSICAL, __LINE__, EF_PARTICLE);
633 }
634 if(!err && fabs(p->p_gc.pitch) > 1) {
635 err = error_raise(ERR_MARKER_UNPHYSICAL, __LINE__, EF_PARTICLE);
636 }
637 if(!err && p->p_gc.energy <= 0) {
638 err = error_raise(ERR_MARKER_UNPHYSICAL, __LINE__, EF_PARTICLE);
639 }
640 if(!err && p->p_gc.mass <= 0) {
641 err = error_raise(ERR_MARKER_UNPHYSICAL, __LINE__, EF_PARTICLE);
642 }
643 if(!err && p->p_gc.weight <= 0) {
644 err = error_raise(ERR_MARKER_UNPHYSICAL, __LINE__, EF_PARTICLE);
645 }
646 if(!err && p->p_gc.id <= 0) {
647 err = error_raise(ERR_MARKER_UNPHYSICAL, __LINE__, EF_PARTICLE);
648 }
649
650 /* Guiding center to state */
652 id = p->p_gc.id;
653 if(!err) {
654 err = particle_input_gc_to_state(&p->p_gc, ps, Bdata);
655 }
656 }
657 else if(p->type == input_particle_type_ml) {
658 /* Check that input is valid */
659 if(!err && p->p_ml.r <= 0) {
660 err = error_raise(ERR_MARKER_UNPHYSICAL, __LINE__, EF_PARTICLE);
661 }
662 if(!err && p->p_ml.weight <= 0) {
663 err = error_raise(ERR_MARKER_UNPHYSICAL, __LINE__, EF_PARTICLE);
664 }
665 if(!err && p->p_ml.id <= 0) {
666 err = error_raise(ERR_MARKER_UNPHYSICAL, __LINE__, EF_PARTICLE);
667 }
668
669 /* Magnetic field line to state */
671 id = p->p_ml.id;
672 if(!err) {
673 err = particle_input_ml_to_state(&p->p_ml, ps, Bdata);
674 }
675 }
676
677 /* If particle was rejected, ensure that these fields are filled */
678 if(err) {
679 ps->id = id;
680 ps->endcond = 0;
681 ps->err = err;
682 }
683}
684
712 int j, B_field_data* Bdata) {
713 a5err err = p->err;
714
715 if(!err) {
716 p_fo->r[j] = p->rprt;
717 p_fo->phi[j] = p->phiprt;
718 p_fo->z[j] = p->zprt;
719 p_fo->p_r[j] = p->p_r;
720 p_fo->p_phi[j] = p->p_phi;
721 p_fo->p_z[j] = p->p_z;
722
723 p_fo->mass[j] = p->mass;
724 p_fo->charge[j] = p->charge;
725 p_fo->znum[j] = p->znum;
726 p_fo->anum[j] = p->anum;
727 p_fo->bounces[j] = 0;
728 p_fo->weight[j] = p->weight;
729 p_fo->time[j] = p->time;
730 p_fo->theta[j] = p->theta;
731 p_fo->id[j] = p->id;
732 p_fo->endcond[j] = p->endcond;
733 p_fo->walltile[j] = p->walltile;
734 p_fo->mileage[j] = p->mileage;
735 }
736
737 /* Magnetic field stored in state is for the gc position */
738 real B_dB[15], psi[1], rho[2];
739 if(!err) {
740 err = B_field_eval_B_dB(B_dB, p->rprt, p->phiprt, p->zprt, p->time,
741 Bdata);
742 }
743 if(!err) {
744 err = B_field_eval_psi(psi, p->rprt, p->phiprt, p->zprt, p->time,
745 Bdata);
746 }
747 if(!err) {
748 err = B_field_eval_rho(rho, psi[0], Bdata);
749 }
750
751 if(!err) {
752 p_fo->rho[j] = rho[0];
753
754 p_fo->B_r[j] = B_dB[0];
755 p_fo->B_r_dr[j] = B_dB[1];
756 p_fo->B_r_dphi[j] = B_dB[2];
757 p_fo->B_r_dz[j] = B_dB[3];
758
759 p_fo->B_phi[j] = B_dB[4];
760 p_fo->B_phi_dr[j] = B_dB[5];
761 p_fo->B_phi_dphi[j] = B_dB[6];
762 p_fo->B_phi_dz[j] = B_dB[7];
763
764 p_fo->B_z[j] = B_dB[8];
765 p_fo->B_z_dr[j] = B_dB[9];
766 p_fo->B_z_dphi[j] = B_dB[10];
767 p_fo->B_z_dz[j] = B_dB[11];
768
769 p_fo->running[j] = 1;
770 if(p->endcond) {
771 p_fo->running[j] = 0;
772 }
773 p_fo->cputime[j] = p->cputime;
774 p_fo->index[j] = i;
775
776 p_fo->err[j] = 0;
777 }
778
779 return err;
780}
781
797 B_field_data* Bdata) {
798 a5err err = 0;
799
800 p->rprt = p_fo->r[j];
801 p->phiprt = p_fo->phi[j];
802 p->zprt = p_fo->z[j];
803 p->p_r = p_fo->p_r[j];
804 p->p_phi = p_fo->p_phi[j];
805 p->p_z = p_fo->p_z[j];
806
807 p->mass = p_fo->mass[j];
808 p->charge = p_fo->charge[j];
809 p->znum = p_fo->znum[j];
810 p->anum = p_fo->anum[j];
811 p->weight = p_fo->weight[j];
812 p->time = p_fo->time[j];
813 p->theta = p_fo->theta[j];
814 p->id = p_fo->id[j];
815 p->endcond = p_fo->endcond[j];
816 p->walltile = p_fo->walltile[j];
817 p->cputime = p_fo->cputime[j];
818 p->mileage = p_fo->mileage[j];
819
820 /* Particle to guiding center */
821 real B_dB[15], psi[1], rho[2];
822 rho[0] = p_fo->rho[j];
823 B_dB[0] = p_fo->B_r[j];
824 B_dB[1] = p_fo->B_r_dr[j];
825 B_dB[2] = p_fo->B_r_dphi[j];
826 B_dB[3] = p_fo->B_r_dz[j];
827 B_dB[4] = p_fo->B_phi[j];
828 B_dB[5] = p_fo->B_phi_dr[j];
829 B_dB[6] = p_fo->B_phi_dphi[j];
830 B_dB[7] = p_fo->B_phi_dz[j];
831 B_dB[8] = p_fo->B_z[j];
832 B_dB[9] = p_fo->B_z_dr[j];
833 B_dB[10] = p_fo->B_z_dphi[j];
834 B_dB[11] = p_fo->B_z_dz[j];
835
836 /* Guiding center transformation */
837 real ppar;
838 if(!err) {
839 real pr = p->p_r;
840 real pphi = p->p_phi;
841 real pz = p->p_z;
842
844 p->mass, p->charge, B_dB,
845 p->rprt, p->phiprt, p->zprt, pr , pphi, pz,
846 &p->r, &p->phi, &p->z, &ppar, &p->mu, &p->zeta);
847 }
848 if(!err && p->r <= 0) {err = error_raise(ERR_MARKER_UNPHYSICAL, __LINE__, EF_PARTICLE);}
849 if(!err && p->mu < 0) {err = error_raise(ERR_MARKER_UNPHYSICAL, __LINE__, EF_PARTICLE);}
850
851 if(!err) {
852 err = B_field_eval_B_dB(B_dB, p->r, p->phi, p->z, p->time, Bdata);
853 }
854 if(!err) {
855 err = B_field_eval_psi(psi, p->r, p->phi, p->z, p->time, Bdata);
856 }
857 if(!err) {
858 err = B_field_eval_rho(rho, psi[0], Bdata);
859 }
860
861 if(!err) {
862 p->ppar = ppar;
863 }
864 if(!err && p->ppar >= CONST_C) {
865 err = error_raise(ERR_MARKER_UNPHYSICAL, __LINE__, EF_PARTICLE);
866 }
867
868 /* Normally magnetic field data at gc position is stored here
869 * but, if gc transformation fails, field at particle position is
870 * stored instead. */
871 p->rho = rho[0];
872
873 p->B_r = B_dB[0];
874 p->B_r_dr = B_dB[1];
875 p->B_r_dphi = B_dB[2];
876 p->B_r_dz = B_dB[3];
877
878 p->B_phi = B_dB[4];
879 p->B_phi_dr = B_dB[5];
880 p->B_phi_dphi = B_dB[6];
881 p->B_phi_dz = B_dB[7];
882
883 p->B_z = B_dB[8];
884 p->B_z_dr = B_dB[9];
885 p->B_z_dphi = B_dB[10];
886 p->B_z_dz = B_dB[11];
887
888 /* If marker already has error flag, make sure it is not overwritten here */
889 a5err simerr = p_fo->err[j];
890 if(simerr) {
891 p->err = simerr;
892 }
893 else {
894 p->err = err;
895 }
896}
897
924 int j, B_field_data* Bdata) {
925 a5err err = p->err;
926
927 if(!err) {
928 p_gc->r[j] = p->r;
929 p_gc->phi[j] = p->phi;
930 p_gc->z[j] = p->z;
931 p_gc->ppar[j] = p->ppar;
932 p_gc->mu[j] = p->mu;
933 p_gc->zeta[j] = p->zeta;
934
935 p_gc->mass[j] = p->mass;
936 p_gc->charge[j] = p->charge;
937 p_gc->time[j] = p->time;
938 p_gc->bounces[j] = 0;
939 p_gc->weight[j] = p->weight;
940 p_gc->rho[j] = p->rho;
941 p_gc->theta[j] = p->theta;
942 p_gc->id[j] = p->id;
943 p_gc->endcond[j] = p->endcond;
944 p_gc->walltile[j] = p->walltile;
945 p_gc->mileage[j] = p->mileage;
946
947 p_gc->B_r[j] = p->B_r;
948 p_gc->B_r_dr[j] = p->B_r_dr;
949 p_gc->B_r_dphi[j] = p->B_r_dphi;
950 p_gc->B_r_dz[j] = p->B_r_dz;
951
952 p_gc->B_phi[j] = p->B_phi;
953 p_gc->B_phi_dr[j] = p->B_phi_dr;
954 p_gc->B_phi_dphi[j] = p->B_phi_dphi;
955 p_gc->B_phi_dz[j] = p->B_phi_dz;
956
957 p_gc->B_z[j] = p->B_z;
958 p_gc->B_z_dr[j] = p->B_z_dr;
959 p_gc->B_z_dphi[j] = p->B_z_dphi;
960 p_gc->B_z_dz[j] = p->B_z_dz;
961
962 p_gc->running[j] = 1;
963 if(p->endcond) {
964 p_gc->running[j] = 0;
965 }
966 p_gc->cputime[j] = p->cputime;
967 p_gc->index[j] = i;
968 p_gc->err[j] = 0;
969 }
970
971 return err;
972}
973
989 B_field_data* Bdata) {
990 a5err err = 0;
991
992 p->r = p_gc->r[j];
993 p->phi = p_gc->phi[j];
994 p->z = p_gc->z[j];
995 p->ppar = p_gc->ppar[j];
996 p->mu = p_gc->mu[j];
997 p->zeta = p_gc->zeta[j];
998
999 p->mass = p_gc->mass[j];
1000 p->charge = p_gc->charge[j];
1001 p->time = p_gc->time[j];
1002 p->weight = p_gc->weight[j];
1003 p->id = p_gc->id[j];
1004 p->cputime = p_gc->cputime[j];
1005 p->rho = p_gc->rho[j];
1006 p->theta = p_gc->theta[j];
1007 p->endcond = p_gc->endcond[j];
1008 p->walltile = p_gc->walltile[j];
1009 p->mileage = p_gc->mileage[j];
1010
1011 p->B_r = p_gc->B_r[j];
1012 p->B_r_dr = p_gc->B_r_dr[j];
1013 p->B_r_dphi = p_gc->B_r_dphi[j];
1014 p->B_r_dz = p_gc->B_r_dz[j];
1015
1016 p->B_phi = p_gc->B_phi[j];
1017 p->B_phi_dr = p_gc->B_phi_dr[j];
1018 p->B_phi_dphi = p_gc->B_phi_dphi[j];
1019 p->B_phi_dz = p_gc->B_phi_dz[j];
1020
1021 p->B_z = p_gc->B_z[j];
1022 p->B_z_dr = p_gc->B_z_dr[j];
1023 p->B_z_dphi = p_gc->B_z_dphi[j];
1024 p->B_z_dz = p_gc->B_z_dz[j];
1025
1026 /* Guiding center to particle transformation */
1027 real B_dB[15];
1028 B_dB[0] = p->B_r;
1029 B_dB[1] = p->B_r_dr;
1030 B_dB[2] = p->B_r_dphi;
1031 B_dB[3] = p->B_r_dz;
1032 B_dB[4] = p->B_phi;
1033 B_dB[5] = p->B_phi_dr;
1034 B_dB[6] = p->B_phi_dphi;
1035 B_dB[7] = p->B_phi_dz;
1036 B_dB[8] = p->B_z;
1037 B_dB[9] = p->B_z_dr;
1038 B_dB[10] = p->B_z_dphi;
1039 B_dB[11] = p->B_z_dz;
1040
1041 real pr, pphi, pz;
1042 if(!err) {
1043 real pparprt, muprt, zetaprt;
1045 p->mass, p->charge, B_dB,
1046 p->r, p->phi, p->z, p->ppar, p->mu, p->zeta,
1047 &p->rprt, &p->phiprt, &p->zprt, &pparprt, &muprt, &zetaprt);
1048
1049 B_field_eval_B_dB(B_dB, p->rprt, p->phiprt, p->zprt, p->time, Bdata);
1050
1052 p->mass, p->charge, B_dB,
1053 p->phiprt, pparprt, muprt, zetaprt,
1054 &pr, &pphi, &pz);
1055 }
1056 if(!err && p->rprt <= 0) {err = error_raise(ERR_MARKER_UNPHYSICAL, __LINE__, EF_PARTICLE);}
1057
1058 if(!err) {
1059 p->p_r = pr;
1060 p->p_phi = pphi;
1061 p->p_z = pz;
1062 }
1063
1064 /* If marker already has error flag, make sure it is not overwritten here */
1065 a5err simerr = p_gc->err[j];
1066 if(simerr) {
1067 p->err = simerr;
1068 }
1069 else {
1070 p->err = err;
1071 }
1072}
1073
1105 int j, B_field_data* Bdata) {
1106 a5err err = p->err;
1107
1108 if(!err) {
1109 p_ml->r[j] = p->r;
1110 p_ml->phi[j] = p->phi;
1111 p_ml->z[j] = p->z;
1112
1113 p_ml->pitch[j] = 2*(p->ppar >= 0) - 1.0;
1114 p_ml->time[j] = p->time;
1115 p_ml->weight[j] = p->weight;
1116 p_ml->id[j] = p->id;
1117 p_ml->cputime[j] = p->cputime;
1118 p_ml->rho[j] = p->rho;
1119 p_ml->theta[j] = p->theta;
1120 p_ml->endcond[j] = p->endcond;
1121 p_ml->walltile[j] = p->walltile;
1122 p_ml->mileage[j] = p->mileage;
1123
1124 p_ml->B_r[j] = p->B_r;
1125 p_ml->B_r_dr[j] = p->B_r_dr;
1126 p_ml->B_r_dphi[j] = p->B_r_dphi;
1127 p_ml->B_r_dz[j] = p->B_r_dz;
1128
1129 p_ml->B_phi[j] = p->B_phi;
1130 p_ml->B_phi_dr[j] = p->B_phi_dr;
1131 p_ml->B_phi_dphi[j] = p->B_phi_dphi;
1132 p_ml->B_phi_dz[j] = p->B_phi_dz;
1133
1134 p_ml->B_z[j] = p->B_z;
1135 p_ml->B_z_dr[j] = p->B_z_dr;
1136 p_ml->B_z_dphi[j] = p->B_z_dphi;
1137 p_ml->B_z_dz[j] = p->B_z_dz;
1138
1139 p_ml->running[j] = 1;
1140 if(p->endcond) {
1141 p_ml->running[j] = 0;
1142 }
1143 p_ml->index[j] = i;
1144
1145 p_ml->err[j] = 0;
1146 }
1147
1148 return err;
1149}
1150
1170 B_field_data* Bdata) {
1171 a5err err = 0;
1172
1173 p->rprt = p_ml->r[j];
1174 p->phiprt = p_ml->phi[j];
1175 p->zprt = p_ml->z[j];
1176 p->p_r = 0;
1177 p->p_phi = 0;
1178 p->p_z = 0;
1179
1180 p->r = p_ml->r[j];
1181 p->phi = p_ml->phi[j];
1182 p->z = p_ml->z[j];
1183 p->ppar = p_ml->pitch[j];
1184 p->mu = 0;
1185 p->zeta = 0;
1186 p->mass = 0;
1187 p->charge = 0;
1188 p->time = p_ml->time[j];
1189 p->weight = p_ml->weight[j];
1190 p->id = p_ml->id[j];
1191 p->cputime = p_ml->cputime[j];
1192 p->rho = p_ml->rho[j];
1193 p->theta = p_ml->theta[j];
1194 p->endcond = p_ml->endcond[j];
1195 p->walltile = p_ml->walltile[j];
1196 p->mileage = p_ml->mileage[j];
1197 p->err = p_ml->err[j];
1198
1199 p->B_r = p_ml->B_r[j];
1200 p->B_r_dr = p_ml->B_r_dr[j];
1201 p->B_r_dphi = p_ml->B_r_dphi[j];
1202 p->B_r_dz = p_ml->B_r_dz[j];
1203
1204 p->B_phi = p_ml->B_phi[j];
1205 p->B_phi_dr = p_ml->B_phi_dr[j];
1206 p->B_phi_dphi = p_ml->B_phi_dphi[j];
1207 p->B_phi_dz = p_ml->B_phi_dz[j];
1208
1209 p->B_z = p_ml->B_z[j];
1210 p->B_z_dr = p_ml->B_z_dr[j];
1211 p->B_z_dphi = p_ml->B_z_dphi[j];
1212 p->B_z_dz = p_ml->B_z_dz[j];
1213
1214 /* If marker already has error flag, make sure it is not overwritten here */
1215 a5err simerr = p_ml->err[j];
1216 if(simerr) {
1217 p->err = simerr;
1218 }
1219 else {
1220 p->err = err;
1221 }
1222 if(!simerr && err) {err = err;}
1223 p->err = err;
1224}
1225
1238 B_field_data* Bdata) {
1239 a5err err = p_fo->err[j];
1240 real axisrz[2];
1241 int simerr = 0; /* Error has already occurred */
1242 if(err) {simerr = 1;}
1243 p_gc->id[j] = p_fo->id[j];
1244 p_gc->index[j] = p_fo->index[j];
1245
1246 real r, phi, z, ppar, mu, zeta, B_dB[15];
1247 if(!err) {
1248 real Rprt = p_fo->r[j];
1249 real phiprt = p_fo->phi[j];
1250 real zprt = p_fo->z[j];
1251 real pr = p_fo->p_r[j];
1252 real pphi = p_fo->p_phi[j];
1253 real pz = p_fo->p_z[j];
1254 real mass = p_fo->mass[j];
1255 real charge = p_fo->charge[j];
1256
1257 p_gc->mass[j] = p_fo->mass[j];
1258 p_gc->charge[j] = p_fo->charge[j];
1259 p_gc->weight[j] = p_fo->weight[j];
1260 p_gc->time[j] = p_fo->time[j];
1261 p_gc->mileage[j] = p_fo->mileage[j];
1262 p_gc->endcond[j] = p_fo->endcond[j];
1263 p_gc->running[j] = p_fo->running[j];
1264 p_gc->walltile[j] = p_fo->walltile[j];
1265 p_gc->cputime[j] = p_fo->cputime[j];
1266
1267 B_dB[0] = p_fo->B_r[j];
1268 B_dB[1] = p_fo->B_r_dr[j];
1269 B_dB[2] = p_fo->B_r_dphi[j];
1270 B_dB[3] = p_fo->B_r_dz[j];
1271 B_dB[4] = p_fo->B_phi[j];
1272 B_dB[5] = p_fo->B_phi_dr[j];
1273 B_dB[6] = p_fo->B_phi_dphi[j];
1274 B_dB[7] = p_fo->B_phi_dz[j];
1275 B_dB[8] = p_fo->B_z[j];
1276 B_dB[9] = p_fo->B_z_dr[j];
1277 B_dB[10] = p_fo->B_z_dphi[j];
1278 B_dB[11] = p_fo->B_z_dz[j];
1279
1280 /* Guiding center transformation */
1282 mass, charge, B_dB,
1283 Rprt, phiprt, zprt, pr , pphi, pz,
1284 &r, &phi, &z, &ppar, &mu, &zeta);
1285 }
1286 if(!err && r <= 0) {err = error_raise(ERR_MARKER_UNPHYSICAL, __LINE__, EF_PARTICLE);}
1287 if(!err && mu < 0) {err = error_raise(ERR_MARKER_UNPHYSICAL, __LINE__, EF_PARTICLE);}
1288
1289 real psi[1], rho[2];
1290 if(!err) {
1291 err = B_field_eval_B_dB(
1292 B_dB, r, phi, z, p_fo->time[j], Bdata);
1293 }
1294 if(!err) {
1295 err = B_field_eval_psi(
1296 psi, r, phi, z, p_fo->time[j], Bdata);
1297 }
1298 if(!err) {
1299 err = B_field_eval_rho(rho, psi[0], Bdata);
1300 }
1301 if(!err) {
1302 err = B_field_get_axis_rz(axisrz, Bdata, p_gc->phi[j]);
1303 }
1304
1305 if(!err) {
1306 p_gc->r[j] = r;
1307 p_gc->phi[j] = phi;
1308 p_gc->z[j] = z;
1309 p_gc->mu[j] = mu;
1310 p_gc->zeta[j] = zeta;
1311 p_gc->ppar[j] = ppar;
1312 p_gc->rho[j] = rho[0];
1313
1314 /* Evaluate pol angle so that it is cumulative and at gc position */
1315 p_gc->theta[j] = p_fo->theta[j];
1316 p_gc->theta[j] += atan2( (p_fo->r[j]-axisrz[0]) * (p_gc->z[j]-axisrz[1])
1317 - (p_fo->z[j]-axisrz[1]) * (p_gc->r[j]-axisrz[0]),
1318 (p_fo->r[j]-axisrz[0]) * (p_gc->r[j]-axisrz[0])
1319 + (p_fo->z[j]-axisrz[1]) * (p_gc->z[j]-axisrz[1]) );
1320
1321 p_gc->B_r[j] = B_dB[0];
1322 p_gc->B_r_dr[j] = B_dB[1];
1323 p_gc->B_r_dphi[j] = B_dB[2];
1324 p_gc->B_r_dz[j] = B_dB[3];
1325
1326 p_gc->B_phi[j] = B_dB[4];
1327 p_gc->B_phi_dr[j] = B_dB[5];
1328 p_gc->B_phi_dphi[j] = B_dB[6];
1329 p_gc->B_phi_dz[j] = B_dB[7];
1330
1331 p_gc->B_z[j] = B_dB[8];
1332 p_gc->B_z_dr[j] = B_dB[9];
1333 p_gc->B_z_dphi[j] = B_dB[10];
1334 p_gc->B_z_dz[j] = B_dB[11];
1335 }
1336 if(!simerr) {err = err;}
1337 p_gc->err[j] = err;
1338 if(p_gc->err[j]) {
1339 p_gc->running[j] = 0;
1340 p_gc->endcond[j] = 0;
1341 }
1342
1343 return err > 0;
1344}
1345
1355 p2->r[j] = p1->r[i];
1356 p2->phi[j] = p1->phi[i];
1357 p2->z[j] = p1->z[i];
1358 p2->p_r[j] = p1->p_r[i];
1359 p2->p_phi[j] = p1->p_phi[i];
1360 p2->p_z[j] = p1->p_z[i];
1361
1362 p2->time[j] = p1->time[i];
1363 p2->mileage[j] = p1->mileage[i];
1364 p2->cputime[j] = p1->cputime[i];
1365 p2->rho[j] = p1->rho[i];
1366 p2->weight[j] = p1->weight[i];
1367 p2->cputime[j] = p1->cputime[i];
1368 p2->rho[j] = p1->rho[i];
1369 p2->theta[j] = p1->theta[i];
1370
1371 p2->mass[j] = p1->mass[i];
1372 p2->charge[j] = p1->charge[i];
1373 p2->znum[j] = p1->znum[i];
1374 p2->anum[j] = p1->anum[i];
1375
1376 p2->id[j] = p1->id[i];
1377 p2->bounces[j] = p1->bounces[i];
1378 p2->running[j] = p1->running[i];
1379 p2->endcond[j] = p1->endcond[i];
1380 p2->walltile[j] = p1->walltile[i];
1381
1382 p2->B_r[j] = p1->B_r[i];
1383 p2->B_phi[j] = p1->B_phi[i];
1384 p2->B_z[j] = p1->B_z[i];
1385
1386 p2->B_r_dr[j] = p1->B_r_dr[i];
1387 p2->B_r_dphi[j] = p1->B_r_dphi[i];
1388 p2->B_r_dz[j] = p1->B_r_dz[i];
1389
1390 p2->B_phi_dr[j] = p1->B_phi_dr[i];
1391 p2->B_phi_dphi[j] = p1->B_phi_dphi[i];
1392 p2->B_phi_dz[j] = p1->B_phi_dz[i];
1393
1394 p2->B_z_dr[j] = p1->B_z_dr[i];
1395 p2->B_z_dphi[j] = p1->B_z_dphi[i];
1396 p2->B_z_dz[j] = p1->B_z_dz[i];
1397}
1398
1408 p2->r[j] = p1->r[i];
1409 p2->phi[j] = p1->phi[i];
1410 p2->z[j] = p1->z[i];
1411 p2->ppar[j] = p1->ppar[i];
1412 p2->mu[j] = p1->mu[i];
1413 p2->zeta[j] = p1->zeta[i];
1414
1415 p2->time[j] = p1->time[i];
1416 p2->mileage[j] = p1->mileage[i];
1417 p2->weight[j] = p1->weight[i];
1418 p2->cputime[j] = p1->cputime[i];
1419 p2->rho[j] = p1->rho[i];
1420 p2->theta[j] = p1->theta[i];
1421
1422 p2->mass[j] = p1->mass[i];
1423 p2->charge[j] = p1->charge[i];
1424
1425 p2->id[j] = p1->id[i];
1426 p2->bounces[j] = p1->bounces[i];
1427 p2->running[j] = p1->running[i];
1428 p2->endcond[j] = p1->endcond[i];
1429 p2->walltile[j] = p1->walltile[i];
1430
1431 p2->B_r[j] = p1->B_r[i];
1432 p2->B_phi[j] = p1->B_phi[i];
1433 p2->B_z[j] = p1->B_z[i];
1434
1435 p2->B_r_dr[j] = p1->B_r_dr[i];
1436 p2->B_r_dphi[j] = p1->B_r_dphi[i];
1437 p2->B_r_dz[j] = p1->B_r_dz[i];
1438
1439 p2->B_phi_dr[j] = p1->B_phi_dr[i];
1440 p2->B_phi_dphi[j] = p1->B_phi_dphi[i];
1441 p2->B_phi_dz[j] = p1->B_phi_dz[i];
1442
1443 p2->B_z_dr[j] = p1->B_z_dr[i];
1444 p2->B_z_dphi[j] = p1->B_z_dphi[i];
1445 p2->B_z_dz[j] = p1->B_z_dz[i];
1446}
1447
1457 int j) {
1458 p2->r[j] = p1->r[i];
1459 p2->phi[j] = p1->phi[i];
1460 p2->z[j] = p1->z[i];
1461 p2->pitch[j] = p1->pitch[i];
1462
1463 p2->time[j] = p1->time[i];
1464 p2->mileage[j] = p1->mileage[i];
1465 p2->cputime[j] = p1->cputime[i];
1466 p2->rho[j] = p1->rho[i];
1467 p2->weight[j] = p1->weight[i];
1468 p2->theta[j] = p1->theta[i];
1469
1470 p2->id[j] = p1->id[i];
1471 p2->running[j] = p1->running[i];
1472 p2->endcond[j] = p1->endcond[i];
1473 p2->walltile[j] = p1->walltile[i];
1474
1475 p2->B_r[j] = p1->B_r[i];
1476 p2->B_phi[j] = p1->B_phi[i];
1477 p2->B_z[j] = p1->B_z[i];
1478
1479 p2->B_r_dr[j] = p1->B_r_dr[i];
1480 p2->B_r_dphi[j] = p1->B_r_dphi[i];
1481 p2->B_r_dz[j] = p1->B_r_dz[i];
1482
1483 p2->B_phi_dr[j] = p1->B_phi_dr[i];
1484 p2->B_phi_dphi[j] = p1->B_phi_dphi[i];
1485 p2->B_phi_dz[j] = p1->B_phi_dz[i];
1486
1487 p2->B_z_dr[j] = p1->B_z_dr[i];
1488 p2->B_z_dphi[j] = p1->B_z_dphi[i];
1489 p2->B_z_dz[j] = p1->B_z_dz[i];
1490}
1491
1502 B_field_data* Bdata) {
1503 a5err err = 0;
1504 real axisrz[2];
1505 if(!err) {
1506 err = B_field_get_axis_rz(axisrz, Bdata, p->phi);
1507 }
1508 ps->rprt = p->r;
1509 ps->phiprt = p->phi;
1510 ps->zprt = p->z;
1511 ps->p_r = p->p_r;
1512 ps->p_phi = p->p_phi;
1513 ps->p_z = p->p_z;
1514 ps->mass = p->mass;
1515 ps->charge = p->charge;
1516 ps->anum = p->anum;
1517 ps->znum = p->znum;
1518 ps->weight = p->weight;
1519 ps->time = p->time;
1520 ps->theta = atan2(ps->zprt-axisrz[1], ps->rprt-axisrz[0]);
1521 ps->id = p->id;
1522 ps->mileage = 0;
1523 ps->endcond = 0;
1524 ps->walltile = 0;
1525 ps->cputime = 0;
1526
1527 /* Guiding center transformation */
1528 real B_dB[15], r, phi, z, ppar, mu, zeta, psi[1], rho[2];
1529 err = B_field_eval_B_dB(B_dB, ps->rprt, ps->phiprt, ps->zprt,
1530 ps->time, Bdata);
1531
1532 if(!err) {
1534 ps->mass, ps->charge, B_dB,
1535 ps->rprt, ps->phiprt, ps->zprt, p->p_r, p->p_phi, p->p_z,
1536 &r, &phi, &z, &ppar, &mu, &zeta);
1537 }
1538 if(!err && r <= 0) {
1539 err = error_raise(ERR_MARKER_UNPHYSICAL, __LINE__, EF_PARTICLE);
1540 }
1541 if(!err && mu < 0) {
1542 err = error_raise(ERR_MARKER_UNPHYSICAL, __LINE__, EF_PARTICLE);
1543 }
1544
1545 /* Update magnetic field at gc position */
1546 if(!err) {
1547 err = B_field_eval_B_dB(B_dB, r, phi, z, ps->time, Bdata);
1548 }
1549 if(!err) {
1550 err = B_field_eval_psi(psi, r, phi, z, ps->time, Bdata);
1551 }
1552 if(!err) {
1553 err = B_field_eval_rho(rho, psi[0], Bdata);
1554 }
1555
1556 if(!err) {
1557 ps->r = r;
1558 ps->phi = phi;
1559 ps->z = z;
1560 ps->ppar = ppar;
1561 ps->mu = mu;
1562 ps->zeta = zeta;
1563
1564 ps->rho = rho[0];
1565 ps->B_r = B_dB[0];
1566 ps->B_phi = B_dB[4];
1567 ps->B_z = B_dB[8];
1568 ps->B_r_dr = B_dB[1];
1569 ps->B_phi_dr = B_dB[5];
1570 ps->B_z_dr = B_dB[9];
1571 ps->B_r_dphi = B_dB[2];
1572 ps->B_phi_dphi = B_dB[6];
1573 ps->B_z_dphi = B_dB[10];
1574 ps->B_r_dz = B_dB[3];
1575 ps->B_phi_dz = B_dB[7];
1576 ps->B_z_dz = B_dB[11];
1577
1578 ps->err = 0;
1579 }
1580 return err;
1581}
1582
1593 B_field_data* Bdata) {
1594 a5err err = 0;
1595 real axisrz[2];
1596 real B_dB[15], psi[1], rho[2];
1597 if(!err) {
1598 err = B_field_eval_B_dB(B_dB, p->r, p->phi, p->z, p->time, Bdata);
1599 }
1600 if(!err) {
1601 err = B_field_eval_psi(psi, p->r, p->phi, p->z, p->time, Bdata);
1602 }
1603 if(!err) {
1604 err = B_field_eval_rho(rho, psi[0], Bdata);
1605 }
1606
1607 if(!err) {
1608 ps->rho = rho[0];
1609 ps->B_r = B_dB[0];
1610 ps->B_phi = B_dB[4];
1611 ps->B_z = B_dB[8];
1612 ps->B_r_dr = B_dB[1];
1613 ps->B_phi_dr = B_dB[5];
1614 ps->B_z_dr = B_dB[9];
1615 ps->B_r_dphi = B_dB[2];
1616 ps->B_phi_dphi = B_dB[6];
1617 ps->B_z_dphi = B_dB[10];
1618 ps->B_r_dz = B_dB[3];
1619 ps->B_phi_dz = B_dB[7];
1620 ps->B_z_dz = B_dB[11];
1621 }
1622
1623 /* Input is in (Ekin,xi) coordinates but state needs (mu,vpar) so we need
1624 * to do that transformation first. */
1625 real gamma, mu, ppar;
1626 if(!err) {
1627 /* From kinetic energy we get Lorentz factor as gamma = 1 + Ekin/mc^2 */
1628 gamma = 1 + p->energy / (p->mass * CONST_C2);
1629
1630 /* And then we can use the formula for Lorentz factor to get total momentum */
1631 real pnorm = sqrt( gamma * gamma - 1 ) * p->mass * CONST_C;
1632
1633 /* Now we can use library functions for transformation */
1634 real Bnorm = math_normc(B_dB[0], B_dB[4], B_dB[8]);
1635 ppar = physlib_gc_ppar(pnorm, p->pitch);
1636 mu = physlib_gc_mu(p->mass, pnorm, p->pitch, Bnorm);
1637 }
1638 if(!err && mu < 0) {
1639 err = error_raise(ERR_MARKER_UNPHYSICAL, __LINE__, EF_PARTICLE);
1640 }
1641 if(!err) {
1642 err = B_field_get_axis_rz(axisrz, Bdata, p->phi);
1643 }
1644
1645 if(!err) {
1646 ps->r = p->r;
1647 ps->phi = p->phi;
1648 ps->z = p->z;
1649 ps->mu = mu;
1650 ps->ppar = ppar;
1651 ps->zeta = p->zeta;
1652 ps->mass = p->mass;
1653 ps->charge = p->charge;
1654 ps->anum = p->anum;
1655 ps->znum = p->znum;
1656 ps->weight = p->weight;
1657 ps->time = p->time;
1658 ps->theta = atan2(ps->z-axisrz[1], ps->r-axisrz[0]);
1659 ps->id = p->id;
1660 ps->mileage = 0;
1661 ps->endcond = 0;
1662 ps->walltile = 0;
1663 ps->cputime = 0;
1664 }
1665
1666 /* Guiding center transformation to get particle coordinates */
1667 real rprt, phiprt, zprt, pr, pphi, pz;
1668 if(!err) {
1669 real pparprt, muprt, zetaprt;
1671 ps->mass, ps->charge, B_dB,
1672 ps->r, ps->phi, ps->z, ps->ppar, ps->mu, ps->zeta,
1673 &rprt, &phiprt, &zprt, &pparprt, &muprt, &zetaprt);
1674
1675 B_field_eval_B_dB(B_dB, rprt, phiprt, zprt, ps->time, Bdata);
1676
1678 ps->mass, ps->charge, B_dB,
1679 phiprt, pparprt, muprt, zetaprt,
1680 &pr, &pphi, &pz);
1681 }
1682 if(!err && rprt <= 0) {
1683 err = error_raise(ERR_MARKER_UNPHYSICAL, __LINE__, EF_PARTICLE);
1684 }
1685
1686 if(!err) {
1687 ps->rprt = rprt;
1688 ps->phiprt = phiprt;
1689 ps->zprt = zprt;
1690 ps->p_r = pr;
1691 ps->p_phi = pphi;
1692 ps->p_z = pz;
1693
1694 ps->err = 0;
1695 }
1696 return err;
1697}
1698
1709 B_field_data* Bdata) {
1710 a5err err = 0;
1711 real axisrz[2];
1712 real B_dB[15], psi[1], rho[2];
1713 if(!err) {
1714 err = B_field_eval_B_dB(B_dB, p->r, p->phi, p->z, p->time, Bdata);
1715 }
1716 if(!err) {
1717 err = B_field_eval_psi(psi, p->r, p->phi, p->z, p->time, Bdata);
1718 }
1719 if(!err) {
1720 err = B_field_eval_rho(rho, psi[0], Bdata);
1721 }
1722 if(!err) {
1723 err = B_field_get_axis_rz(axisrz, Bdata, p->phi);
1724 }
1725
1726 if(!err) {
1727 ps->rprt = p->r;
1728 ps->phiprt = p->phi;
1729 ps->zprt = p->z;
1730 ps->p_r = 0;
1731 ps->p_phi = 0;
1732 ps->p_z = 0;
1733
1734 ps->mass = 0;
1735 ps->charge = 0;
1736 ps->anum = 0;
1737 ps->znum = 0;
1738 ps->weight = p->weight;
1739 ps->time = p->time;
1740 ps->id = p->id;
1741 ps->theta = atan2(p->z - axisrz[1], p->r - axisrz[0]);
1742 ps->endcond = 0;
1743 ps->walltile = 0;
1744 ps->cputime = 0;
1745 ps->mileage = 0;
1746
1747 ps->r = p->r;
1748 ps->phi = p->phi;
1749 ps->z = p->z;
1750 ps->ppar = p->pitch >= 0;
1751 ps->mu = 0;
1752 ps->zeta = 0;
1753
1754 ps->rho = rho[0];
1755 ps->B_r = B_dB[0];
1756 ps->B_phi = B_dB[4];
1757 ps->B_z = B_dB[8];
1758 ps->B_r_dr = B_dB[1];
1759 ps->B_phi_dr = B_dB[5];
1760 ps->B_z_dr = B_dB[9];
1761 ps->B_r_dphi = B_dB[2];
1762 ps->B_phi_dphi = B_dB[6];
1763 ps->B_z_dphi = B_dB[10];
1764 ps->B_r_dz = B_dB[3];
1765 ps->B_phi_dz = B_dB[7];
1766 ps->B_z_dz = B_dB[11];
1767
1768 ps->err = 0;
1769 }
1770 return err;
1771}
1772
1779 GPU_MAP_TO_DEVICE(
1780 p[0:1],\
1781 p->running [0:p->n_mrk],\
1782 p->r [0:p->n_mrk],\
1783 p->phi [0:p->n_mrk],\
1784 p->p_r [0:p->n_mrk],\
1785 p->p_phi [0:p->n_mrk],\
1786 p->p_z [0:p->n_mrk],\
1787 p->mileage [0:p->n_mrk],\
1788 p->z [0:p->n_mrk],\
1789 p->charge [0:p->n_mrk],\
1790 p->mass [0:p->n_mrk],\
1791 p->B_r [0:p->n_mrk],\
1792 p->B_r_dr [0:p->n_mrk],\
1793 p->B_r_dphi [0:p->n_mrk],\
1794 p->B_r_dz [0:p->n_mrk],\
1795 p->B_phi [0:p->n_mrk],\
1796 p->B_phi_dr [0:p->n_mrk],\
1797 p->B_phi_dphi[0:p->n_mrk],\
1798 p->B_phi_dz [0:p->n_mrk],\
1799 p->B_z [0:p->n_mrk],\
1800 p->B_z_dr [0:p->n_mrk],\
1801 p->B_z_dphi [0:p->n_mrk],\
1802 p->B_z_dz [0:p->n_mrk],\
1803 p->rho [0:p->n_mrk],\
1804 p->theta [0:p->n_mrk],\
1805 p->err [0:p->n_mrk],\
1806 p->time [0:p->n_mrk],\
1807 p->weight [0:p->n_mrk],\
1808 p->cputime [0:p->n_mrk],\
1809 p->id [0:p->n_mrk],\
1810 p->endcond [0:p->n_mrk],\
1811 p->walltile [0:p->n_mrk],\
1812 p->index [0:p->n_mrk],\
1813 p->znum [0:p->n_mrk],\
1814 p->anum [0:p->n_mrk],\
1815 p->bounces [0:p->n_mrk]
1816 )
1817}
1818
1825 GPU_UPDATE_FROM_DEVICE(
1826 p->running [0:p->n_mrk],\
1827 p->r [0:p->n_mrk],\
1828 p->phi [0:p->n_mrk],\
1829 p->p_r [0:p->n_mrk],\
1830 p->p_phi [0:p->n_mrk],\
1831 p->p_z [0:p->n_mrk],\
1832 p->mileage [0:p->n_mrk],\
1833 p->z [0:p->n_mrk],\
1834 p->charge [0:p->n_mrk],\
1835 p->mass [0:p->n_mrk],\
1836 p->B_r [0:p->n_mrk],\
1837 p->B_r_dr [0:p->n_mrk],\
1838 p->B_r_dphi [0:p->n_mrk],\
1839 p->B_r_dz [0:p->n_mrk],\
1840 p->B_phi [0:p->n_mrk],\
1841 p->B_phi_dr [0:p->n_mrk],\
1842 p->B_phi_dphi[0:p->n_mrk],\
1843 p->B_phi_dz [0:p->n_mrk],\
1844 p->B_z [0:p->n_mrk],\
1845 p->B_z_dr [0:p->n_mrk],\
1846 p->B_z_dphi [0:p->n_mrk],\
1847 p->B_z_dz [0:p->n_mrk],\
1848 p->rho [0:p->n_mrk],\
1849 p->theta [0:p->n_mrk],\
1850 p->err [0:p->n_mrk],\
1851 p->time [0:p->n_mrk],\
1852 p->weight [0:p->n_mrk],\
1853 p->cputime [0:p->n_mrk],\
1854 p->id [0:p->n_mrk],\
1855 p->endcond [0:p->n_mrk],\
1856 p->walltile [0:p->n_mrk],\
1857 p->index [0:p->n_mrk],\
1858 p->znum [0:p->n_mrk],\
1859 p->anum [0:p->n_mrk],\
1860 p->bounces [0:p->n_mrk]
1861 )
1862}
1863
1864
1871 GPU_MAP_TO_DEVICE(
1872 p[0:1],\
1873 p->r [0:p->n_mrk],\
1874 p->phi [0:p->n_mrk],\
1875 p->z [0:p->n_mrk],\
1876 p->ppar [0:p->n_mrk],\
1877 p->mu [0:p->n_mrk],\
1878 p->zeta [0:p->n_mrk],\
1879 p->mass [0:p->n_mrk],\
1880 p->charge [0:p->n_mrk],\
1881 p->time [0:p->n_mrk],\
1882 p->B_r [0:p->n_mrk],\
1883 p->B_phi [0:p->n_mrk],\
1884 p->B_z [0:p->n_mrk],\
1885 p->B_r_dr [0:p->n_mrk],\
1886 p->B_phi_dr [0:p->n_mrk],\
1887 p->B_z_dr [0:p->n_mrk],\
1888 p->B_r_dphi [0:p->n_mrk],\
1889 p->B_phi_dphi [0:p->n_mrk],\
1890 p->B_z_dphi [0:p->n_mrk],\
1891 p->B_r_dz [0:p->n_mrk],\
1892 p->B_phi_dz [0:p->n_mrk],\
1893 p->B_z_dz [0:p->n_mrk],\
1894 p->bounces [0:p->n_mrk],\
1895 p->weight [0:p->n_mrk],\
1896 p->cputime [0:p->n_mrk],\
1897 p->rho [0:p->n_mrk],\
1898 p->theta [0:p->n_mrk],\
1899 p->id [0:p->n_mrk],\
1900 p->endcond [0:p->n_mrk],\
1901 p->walltile [0:p->n_mrk],\
1902 p->mileage [0:p->n_mrk],\
1903 p->running [0:p->n_mrk],\
1904 p->err [0:p->n_mrk],\
1905 p->index [0:p->n_mrk]
1906 )
1907}
1908
1915 GPU_UPDATE_FROM_DEVICE(
1916 p->r [0:p->n_mrk],\
1917 p->phi [0:p->n_mrk],\
1918 p->z [0:p->n_mrk],\
1919 p->ppar [0:p->n_mrk],\
1920 p->mu [0:p->n_mrk],\
1921 p->zeta [0:p->n_mrk],\
1922 p->mass [0:p->n_mrk],\
1923 p->charge [0:p->n_mrk],\
1924 p->time [0:p->n_mrk],\
1925 p->B_r [0:p->n_mrk],\
1926 p->B_phi [0:p->n_mrk],\
1927 p->B_z [0:p->n_mrk],\
1928 p->B_r_dr [0:p->n_mrk],\
1929 p->B_phi_dr [0:p->n_mrk],\
1930 p->B_z_dr [0:p->n_mrk],\
1931 p->B_r_dphi [0:p->n_mrk],\
1932 p->B_phi_dphi [0:p->n_mrk],\
1933 p->B_z_dphi [0:p->n_mrk],\
1934 p->B_r_dz [0:p->n_mrk],\
1935 p->B_phi_dz [0:p->n_mrk],\
1936 p->B_z_dz [0:p->n_mrk],\
1937 p->bounces [0:p->n_mrk],\
1938 p->weight [0:p->n_mrk],\
1939 p->cputime [0:p->n_mrk],\
1940 p->rho [0:p->n_mrk],\
1941 p->theta [0:p->n_mrk],\
1942 p->id [0:p->n_mrk],\
1943 p->endcond [0:p->n_mrk],\
1944 p->walltile [0:p->n_mrk],\
1945 p->mileage [0:p->n_mrk],\
1946 p->running [0:p->n_mrk],\
1947 p->err [0:p->n_mrk],\
1948 p->index [0:p->n_mrk]
1949 )
1950}
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_eval_psi(real *psi, real r, real phi, real z, real t, B_field_data *Bdata)
Evaluate poloidal flux psi.
Definition B_field.c:102
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:449
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.
Header file for E_field.c.
Main header file for ASCOT5.
double real
Definition ascot5.h:85
#define NSIMD
Number of particles simulated simultaneously in a particle group operations.
Definition ascot5.h:91
long integer
Definition ascot5.h:84
Header file containing physical and mathematical constants.
#define CONST_C
Speed of light [m/s].
Definition consts.h:23
#define CONST_C2
Speed of light squared [m^2/s^2].
Definition consts.h:26
Error module for ASCOT5.
unsigned long int a5err
Simulation error flag.
Definition error.h:17
@ EF_PARTICLE
Definition error.h:47
@ ERR_MARKER_UNPHYSICAL
Definition error.h:68
void gctransform_guidingcenter2particle(real mass, real charge, real *B_dB, real R, real Phi, real Z, real ppar, real mu, real zeta, real *r, real *phi, real *z, real *pparprt, real *muprt, real *zetaprt)
Transform guiding center to particle phase space.
void gctransform_pparmuzeta2prpphipz(real mass, real charge, real *B_dB, real phi, real ppar, real mu, real zeta, real *pr, real *pphi, real *pz)
Transform particle ppar, mu, and zeta to momentum vector.
void gctransform_particle2guidingcenter(real mass, real charge, real *B_dB, real r, real phi, real z, real pr, real pphi, real pz, real *R, real *Phi, real *Z, real *ppar, real *mu, real *zeta)
Transform particle to guiding center phase space.
Definition gctransform.c:90
Header file for gctransform.c.
Header file for math.c.
#define math_normc(a1, a2, a3)
Calculate norm of 3D vector from its components a1, a2, a3.
Definition math.h:71
void particle_allocate_gc(particle_simd_gc *p_gc, int nmrk)
Allocates guiding center struct representing particle markers.
Definition particle.c:126
void particle_onload_gc(particle_simd_gc *p)
Onload guiding center particle struct from the GPU.
Definition particle.c:1914
void particle_onload_fo(particle_simd_fo *p)
Onload particle struct from the GPU.
Definition particle.c:1824
void particle_to_ml_dummy(particle_simd_ml *p_ml, int j)
Makes a dummy ML simulation marker.
Definition particle.c:270
void particle_gc_to_state(particle_simd_gc *p_gc, int j, particle_state *p, B_field_data *Bdata)
Convert GC to state.
Definition particle.c:988
a5err particle_input_gc_to_state(particle_gc *p, particle_state *ps, B_field_data *Bdata)
Convert an input guiding center marker to particle state.
Definition particle.c:1592
void particle_copy_gc(particle_simd_gc *p1, int i, particle_simd_gc *p2, int j)
Copy GC struct.
Definition particle.c:1407
a5err particle_state_to_gc(particle_state *p, int i, particle_simd_gc *p_gc, int j, B_field_data *Bdata)
Convert state into a GC SIMD marker.
Definition particle.c:923
a5err particle_state_to_fo(particle_state *p, int i, particle_simd_fo *p_fo, int j, B_field_data *Bdata)
Convert state into a FO SIMD marker.
Definition particle.c:711
void particle_fo_to_state(particle_simd_fo *p_fo, int j, particle_state *p, B_field_data *Bdata)
Convert FO to state.
Definition particle.c:796
void particle_to_fo_dummy(particle_simd_fo *p_fo, int j)
Makes a dummy FO simulation marker.
Definition particle.c:184
void particle_offload_gc(particle_simd_gc *p)
Offload guiding center particle struct to GPU.
Definition particle.c:1870
int particle_fo_to_gc(particle_simd_fo *p_fo, int j, particle_simd_gc *p_gc, B_field_data *Bdata)
Convert FO struct into a GC struct.
Definition particle.c:1237
a5err particle_input_ml_to_state(particle_ml *p, particle_state *ps, B_field_data *Bdata)
Convert an input field line marker to particle state.
Definition particle.c:1708
void particle_input_to_state(input_particle *p, particle_state *ps, B_field_data *Bdata)
Converts input marker to a marker state.
Definition particle.c:602
void particle_to_gc_dummy(particle_simd_gc *p_gc, int j)
Makes a dummy GC simulation marker.
Definition particle.c:224
void particle_copy_ml(particle_simd_ml *p1, int i, particle_simd_ml *p2, int j)
Copy ML struct.
Definition particle.c:1456
void particle_allocate_fo(particle_simd_fo *p_fo, int nmrk)
Allocates struct representing particle markers.
Definition particle.c:69
a5err particle_state_to_ml(particle_state *p, int i, particle_simd_ml *p_ml, int j, B_field_data *Bdata)
Convert state to a ML SIMD marker.
Definition particle.c:1104
a5err particle_input_p_to_state(particle *p, particle_state *ps, B_field_data *Bdata)
Convert an input particle marker to particle state.
Definition particle.c:1501
void particle_offload_fo(particle_simd_fo *p)
Offload particle struct to GPU.
Definition particle.c:1778
int particle_cycle_ml(particle_queue *q, particle_simd_ml *p, B_field_data *Bdata, int *cycle)
Replace finished ML markers with new ones or dummies.
Definition particle.c:513
void particle_ml_to_state(particle_simd_ml *p_ml, int j, particle_state *p, B_field_data *Bdata)
Convert ML to state.
Definition particle.c:1169
int particle_cycle_gc(particle_queue *q, particle_simd_gc *p, B_field_data *Bdata, int *cycle)
Replace finished GC markers with new ones or dummies.
Definition particle.c:419
int particle_cycle_fo(particle_queue *q, particle_simd_fo *p, B_field_data *Bdata, int *cycle)
Replace finished FO markers with new ones or dummies.
Definition particle.c:320
void particle_copy_fo(particle_simd_fo *p1, int i, particle_simd_fo *p2, int j)
Copy FO struct.
Definition particle.c:1354
Header file for particle.c.
@ input_particle_type_gc
Definition particle.h:170
@ input_particle_type_p
Definition particle.h:169
@ input_particle_type_ml
Definition particle.h:171
@ input_particle_type_s
Definition particle.h:172
Methods to evaluate elementary physical quantities.
#define physlib_gc_ppar(p, xi)
Evaluate guiding center parallel momentum [kg m/s] from momentum norm and pitch.
Definition physlib.h:167
#define physlib_gc_mu(m, p, xi, B)
Evaluate guiding center magnetic moment [J/T] from momentum norm and pitch.
Definition physlib.h:182
Magnetic field simulation data.
Definition B_field.h:41
Wrapper for marker structs.
Definition particle.h:186
input_particle_type type
Definition particle.h:187
Guiding center input.
Definition particle.h:110
real weight
Definition particle.h:121
real energy
Definition particle.h:114
integer id
Definition particle.h:123
real charge
Definition particle.h:118
Field line input.
Definition particle.h:132
real weight
Definition particle.h:137
integer id
Definition particle.h:139
Marker queue.
Definition particle.h:154
particle_state ** p
Definition particle.h:156
volatile int next
Definition particle.h:158
volatile int finished
Definition particle.h:159
Struct representing NSIMD particle markers.
Definition particle.h:210
real * B_phi_dphi
Definition particle.h:233
integer * id
Definition particle.h:246
integer * endcond
Definition particle.h:247
integer * index
Definition particle.h:255
integer * walltile
Definition particle.h:248
integer * running
Definition particle.h:252
Struct representing NSIMD guiding center markers.
Definition particle.h:275
integer * walltile
Definition particle.h:314
integer * endcond
Definition particle.h:313
integer * running
Definition particle.h:320
integer * id
Definition particle.h:312
integer * index
Definition particle.h:323
real * B_phi_dphi
Definition particle.h:299
Struct representing NSIMD field line markers.
Definition particle.h:343
General representation of a marker.
Definition particle.h:40
integer id
Definition particle.h:63
integer walltile
Definition particle.h:65
real B_phi_dphi
Definition particle.h:73
integer endcond
Definition particle.h:64
Particle input.
Definition particle.h:88
real charge
Definition particle.h:96
int anum
Definition particle.h:97
real z
Definition particle.h:91
real weight
Definition particle.h:99
real phi
Definition particle.h:90
real p_phi
Definition particle.h:93
real time
Definition particle.h:100
int znum
Definition particle.h:98
real r
Definition particle.h:89
real mass
Definition particle.h:95
real p_z
Definition particle.h:94
integer id
Definition particle.h:101
real p_r
Definition particle.h:92