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
117
133 p_fo->r[j] = 1;
134 p_fo->phi[j] = 1;
135 p_fo->z[j] = 1;
136 p_fo->p_r[j] = 1;
137 p_fo->p_phi[j] = 1;
138 p_fo->p_z[j] = 1;
139 p_fo->mass[j] = 1;
140 p_fo->charge[j] = 1;
141 p_fo->znum[j] = 1;
142 p_fo->anum[j] = 1;
143 p_fo->bounces[j] = 0;
144 p_fo->weight[j] = 0;
145 p_fo->time[j] = 0;
146 p_fo->id[j] = -1;
147 p_fo->mileage[j] = 0;
148 p_fo->running[j] = 0;
149 p_fo->endcond[j] = 0;
150 p_fo->walltile[j] = 0;
151 p_fo->B_r[j] = 1;
152 p_fo->B_phi[j] = 1;
153 p_fo->B_z[j] = 1;
154 p_fo->index[j] = -1;
155 p_fo->err[j] = 0;
156}
157
173 p_gc->r[j] = 1;
174 p_gc->phi[j] = 1;
175 p_gc->z[j] = 1;
176 p_gc->ppar[j] = 1;
177 p_gc->mu[j] = 1;
178 p_gc->zeta[j] = 1;
179 p_gc->mass[j] = 1;
180 p_gc->charge[j] = 1;
181 p_gc->time[j] = 0;
182 p_gc->bounces[j] = 0;
183 p_gc->weight[j] = 0;
184 p_gc->id[j] = -1;
185 p_gc->mileage[j] = 0;
186 p_gc->B_r[j] = 1;
187 p_gc->B_r_dr[j] = 1;
188 p_gc->B_r_dphi[j] = 1;
189 p_gc->B_r_dz[j] = 1;
190
191 p_gc->B_phi[j] = 1;
192 p_gc->B_phi_dr[j] = 1;
193 p_gc->B_phi_dphi[j] = 1;
194 p_gc->B_phi_dz[j] = 1;
195
196 p_gc->B_z[j] = 1;
197 p_gc->B_z_dr[j] = 1;
198 p_gc->B_z_dphi[j] = 1;
199 p_gc->B_z_dz[j] = 1;
200 p_gc->index[j] = -1;
201 p_gc->err[j] = 0;
202}
203
219 p_ml->r[j] = 1;
220 p_ml->phi[j] = 1;
221 p_ml->z[j] = 1;
222 p_ml->time[j] = 0;
223 p_ml->id[j] = -1;
224 p_ml->mileage[j] = 0;
225 p_ml->B_r[j] = 1;
226 p_ml->B_r_dr[j] = 1;
227 p_ml->B_r_dphi[j] = 1;
228 p_ml->B_r_dz[j] = 1;
229
230 p_ml->B_phi[j] = 1;
231 p_ml->B_phi_dr[j] = 1;
232 p_ml->B_phi_dphi[j] = 1;
233 p_ml->B_phi_dz[j] = 1;
234
235 p_ml->B_z[j] = 1;
236 p_ml->B_z_dr[j] = 1;
237 p_ml->B_z_dphi[j] = 1;
238 p_ml->B_z_dz[j] = 1;
239 p_ml->index[j] = -1;
240 p_ml->err[j] = 0;
241}
242
269 B_field_data* Bdata, int* cycle) {
270
271 /* Loop over markers.
272 * A SIMD loop is not possible as we modify the queue. */
273 for(int i = 0; i < p->n_mrk; i++) {
274
275 /* First check whether we should pick a new marker */
276 int newmarker = 0;
277
278 /* 1. There are markers in queue and this marker is dummy */
279 if(p->id[i] < 0 && q->next < q->n) {
280 newmarker = 1;
281 }
282
283 /* 2. This marker has finished simulation */
284 if(!p->running[i] && p->id[i] >= 0) {
285 /* Convert finished marker to state
286 * and store it back to the queue */
287 particle_fo_to_state(p, i, q->p[p->index[i]], Bdata);
288 newmarker = 1;
289 #pragma omp critical
290 q->finished++;
291 }
292
293 /* Init a new marker if one is needed */
294 cycle[i] = 0;
295 while(newmarker) {
296 /* Get the next unsimulated marker from the queue */
297 int i_prt;
298 #pragma omp critical
299 i_prt = q->next++;
300
301 if(i_prt >= q->n) {
302 /* The queue is empty, place a dummy marker here */
303 p->running[i] = 0;
304 p->id[i] = -1;
305 cycle[i] = -1;
306 newmarker = 0;
307 }
308 else if(q->p[i_prt]->endcond) {
309 /* This marker already has an active end condition. Try next. */
310 #pragma omp critical
311 q->finished++;
312 }
313 else {
314 /* Try to convert marker state to a simulation marker */
316 q->p[i_prt], i_prt, p, i, Bdata);
317 if(err) {
318 /* Failed! Mark the marker candidate as finished
319 * and try with a new marker state*/
320 q->p[i_prt]->err = err;
321 #pragma omp critical
322 q->finished++;
323 }
324 else {
325 /* Success! We are good to go. */
326 cycle[i] = 1;
327 newmarker = 0;
328 }
329 }
330 }
331 }
332
333 int n_running = 0;
334 #pragma omp simd reduction(+:n_running)
335 for(int i = 0; i < p->n_mrk; i++) {
336 n_running += p->running[i];
337 }
338
339 return n_running;
340}
341
368 B_field_data* Bdata, int* cycle) {
369
370 /* Loop over markers.
371 * A SIMD loop is not possible as we modify the queue. */
372 for(int i = 0; i < NSIMD; i++) {
373
374 /* First check whether we should pick a new marker */
375 int newmarker = 0;
376
377 /* 1. There are markers in queue and this marker is dummy */
378 if(p->id[i] < 0 && q->next < q->n) {
379 newmarker = 1;
380 }
381
382 /* 2. This marker has finished simulation */
383 if(!p->running[i] && p->id[i] >= 0) {
384 /* Convert finished marker to state
385 * and store it back to the queue */
386 particle_gc_to_state(p, i, q->p[p->index[i]], Bdata);
387 newmarker = 1;
388 #pragma omp critical
389 q->finished++;
390 }
391
392 /* Init a new marker if one is needed */
393 cycle[i] = 0;
394 while(newmarker) {
395 /* Get the next unsimulated marker from the queue */
396 int i_prt;
397 #pragma omp critical
398 i_prt = q->next++;
399
400 if(i_prt >= q->n) {
401 /* The queue is empty, place a dummy marker here */
402 p->running[i] = 0;
403 p->id[i] = -1;
404 cycle[i] = -1;
405 newmarker = 0;
406 }
407 else {
408 /* Try to convert marker state to a simulation marker */
410 q->p[i_prt], i_prt, p, i, Bdata);
411 if(err) {
412 /* Failed! Mark the marker candidate as finished
413 * and try with a new marker state*/
414 q->p[i_prt]->err = err;
415 #pragma omp critical
416 q->finished++;
417 }
418 else {
419 /* Success! We are good to go. */
420 cycle[i] = 1;
421 newmarker = 0;
422 }
423 }
424 }
425 }
426
427 int n_running = 0;
428 #pragma omp simd reduction(+:n_running)
429 for(int i = 0; i < NSIMD; i++) {
430 n_running += p->running[i];
431 }
432
433 return n_running;
434}
435
462 B_field_data* Bdata, int* cycle) {
463
464 /* Loop over markers.
465 * A SIMD loop is not possible as we modify the queue. */
466 for(int i = 0; i < NSIMD; i++) {
467
468 /* First check whether we should pick a new marker */
469 int newmarker = 0;
470
471 /* 1. There are markers in queue and this marker is dummy */
472 if(p->id[i] < 0 && q->next < q->n) {
473 newmarker = 1;
474 }
475
476 /* 2. This marker has finished simulation */
477 if(!p->running[i] && p->id[i] >= 0) {
478 /* Convert finished marker to state
479 * and store it back to the queue */
480 particle_ml_to_state(p, i, q->p[p->index[i]], Bdata);
481 newmarker = 1;
482 #pragma omp critical
483 q->finished++;
484 }
485
486 /* Init a new marker if one is needed */
487 cycle[i] = 0;
488 while(newmarker) {
489 /* Get the next unsimulated marker from the queue */
490 int i_prt;
491 #pragma omp critical
492 i_prt = q->next++;
493
494 if(i_prt >= q->n) {
495 /* The queue is empty, place a dummy marker here */
496 p->running[i] = 0;
497 p->id[i] = -1;
498 cycle[i] = -1;
499 newmarker = 0;
500 }
501 else {
502 /* Try to convert marker state to a simulation marker */
504 q->p[i_prt], i_prt, p, i, Bdata);
505 if(err) {
506 /* Failed! Mark the marker candidate as finished
507 * and try with a new marker state*/
508 q->p[i_prt]->err = err;
509 #pragma omp critical
510 q->finished++;
511 }
512 else {
513 /* Success! We are good to go. */
514 cycle[i] = 1;
515 newmarker = 0;
516 }
517 }
518 }
519 }
520
521 int n_running = 0;
522 #pragma omp simd reduction(+:n_running)
523 for(int i = 0; i < NSIMD; i++) {
524 n_running += p->running[i];
525 }
526
527 return n_running;
528}
529
551 B_field_data* Bdata) {
552 a5err err = 0;
553 integer id = 0;
554
555 if(p->type == input_particle_type_p) {
556 /* Check that input is valid */
557 if(!err && p->p.r <= 0) {
559 }
560 if(!err && p->p.mass <= 0) {
562 }
563 if(!err && p->p.weight <= 0) {
565 }
566 if(!err && p->p.id <= 0) {
568 }
569
570 /* Particle to state */
572 id = p->p.id;
573 if(!err) {
574 err = particle_input_p_to_state(&p->p, ps, Bdata);
575 }
576 }
577 else if(p->type == input_particle_type_gc) {
578 /* Check that input is valid */
579 if(!err && p->p_gc.r <= 0) {
581 }
582 if(!err && fabs(p->p_gc.pitch) > 1) {
584 }
585 if(!err && p->p_gc.energy <= 0) {
587 }
588 if(!err && p->p_gc.mass <= 0) {
590 }
591 if(!err && p->p_gc.weight <= 0) {
593 }
594 if(!err && p->p_gc.id <= 0) {
596 }
597
598 /* Guiding center to state */
600 id = p->p_gc.id;
601 if(!err) {
602 err = particle_input_gc_to_state(&p->p_gc, ps, Bdata);
603 }
604 }
605 else if(p->type == input_particle_type_ml) {
606 /* Check that input is valid */
607 if(!err && p->p_ml.r <= 0) {
609 }
610 if(!err && p->p_ml.weight <= 0) {
612 }
613 if(!err && p->p_ml.id <= 0) {
615 }
616
617 /* Magnetic field line to state */
619 id = p->p_ml.id;
620 if(!err) {
621 err = particle_input_ml_to_state(&p->p_ml, ps, Bdata);
622 }
623 }
624
625 /* If particle was rejected, ensure that these fields are filled */
626 if(err) {
627 ps->id = id;
628 ps->endcond = 0;
629 ps->err = err;
630 }
631}
632
660 int j, B_field_data* Bdata) {
661 a5err err = p->err;
662
663 if(!err) {
664 p_fo->r[j] = p->rprt;
665 p_fo->phi[j] = p->phiprt;
666 p_fo->z[j] = p->zprt;
667 p_fo->p_r[j] = p->p_r;
668 p_fo->p_phi[j] = p->p_phi;
669 p_fo->p_z[j] = p->p_z;
670
671 p_fo->mass[j] = p->mass;
672 p_fo->charge[j] = p->charge;
673 p_fo->znum[j] = p->znum;
674 p_fo->anum[j] = p->anum;
675 p_fo->bounces[j] = 0;
676 p_fo->weight[j] = p->weight;
677 p_fo->time[j] = p->time;
678 p_fo->theta[j] = p->theta;
679 p_fo->id[j] = p->id;
680 p_fo->endcond[j] = p->endcond;
681 p_fo->walltile[j] = p->walltile;
682 p_fo->mileage[j] = p->mileage;
683 }
684
685 /* Magnetic field stored in state is for the gc position */
686 real B_dB[15], psi[1], rho[2];
687 if(!err) {
688 err = B_field_eval_B_dB(B_dB, p->rprt, p->phiprt, p->zprt, p->time,
689 Bdata);
690 }
691 if(!err) {
692 err = B_field_eval_psi(psi, p->rprt, p->phiprt, p->zprt, p->time,
693 Bdata);
694 }
695 if(!err) {
696 err = B_field_eval_rho(rho, psi[0], Bdata);
697 }
698
699 if(!err) {
700 p_fo->rho[j] = rho[0];
701
702 p_fo->B_r[j] = B_dB[0];
703 p_fo->B_r_dr[j] = B_dB[1];
704 p_fo->B_r_dphi[j] = B_dB[2];
705 p_fo->B_r_dz[j] = B_dB[3];
706
707 p_fo->B_phi[j] = B_dB[4];
708 p_fo->B_phi_dr[j] = B_dB[5];
709 p_fo->B_phi_dphi[j] = B_dB[6];
710 p_fo->B_phi_dz[j] = B_dB[7];
711
712 p_fo->B_z[j] = B_dB[8];
713 p_fo->B_z_dr[j] = B_dB[9];
714 p_fo->B_z_dphi[j] = B_dB[10];
715 p_fo->B_z_dz[j] = B_dB[11];
716
717 p_fo->running[j] = 1;
718 if(p->endcond) {
719 p_fo->running[j] = 0;
720 }
721 p_fo->cputime[j] = p->cputime;
722 p_fo->index[j] = i;
723
724 p_fo->err[j] = 0;
725 }
726
727 return err;
728}
729
745 B_field_data* Bdata) {
746 a5err err = 0;
747
748 p->rprt = p_fo->r[j];
749 p->phiprt = p_fo->phi[j];
750 p->zprt = p_fo->z[j];
751 p->p_r = p_fo->p_r[j];
752 p->p_phi = p_fo->p_phi[j];
753 p->p_z = p_fo->p_z[j];
754
755 p->mass = p_fo->mass[j];
756 p->charge = p_fo->charge[j];
757 p->znum = p_fo->znum[j];
758 p->anum = p_fo->anum[j];
759 p->weight = p_fo->weight[j];
760 p->time = p_fo->time[j];
761 p->theta = p_fo->theta[j];
762 p->id = p_fo->id[j];
763 p->endcond = p_fo->endcond[j];
764 p->walltile = p_fo->walltile[j];
765 p->cputime = p_fo->cputime[j];
766 p->mileage = p_fo->mileage[j];
767
768 /* Particle to guiding center */
769 real B_dB[15], psi[1], rho[2];
770 rho[0] = p_fo->rho[j];
771 B_dB[0] = p_fo->B_r[j];
772 B_dB[1] = p_fo->B_r_dr[j];
773 B_dB[2] = p_fo->B_r_dphi[j];
774 B_dB[3] = p_fo->B_r_dz[j];
775 B_dB[4] = p_fo->B_phi[j];
776 B_dB[5] = p_fo->B_phi_dr[j];
777 B_dB[6] = p_fo->B_phi_dphi[j];
778 B_dB[7] = p_fo->B_phi_dz[j];
779 B_dB[8] = p_fo->B_z[j];
780 B_dB[9] = p_fo->B_z_dr[j];
781 B_dB[10] = p_fo->B_z_dphi[j];
782 B_dB[11] = p_fo->B_z_dz[j];
783
784 /* Guiding center transformation */
785 real ppar;
786 if(!err) {
787 real pr = p->p_r;
788 real pphi = p->p_phi;
789 real pz = p->p_z;
790
792 p->mass, p->charge, B_dB,
793 p->rprt, p->phiprt, p->zprt, pr , pphi, pz,
794 &p->r, &p->phi, &p->z, &ppar, &p->mu, &p->zeta);
795 }
796 if(!err && p->r <= 0) {err = error_raise(ERR_MARKER_UNPHYSICAL, __LINE__, EF_PARTICLE);}
797 if(!err && p->mu < 0) {err = error_raise(ERR_MARKER_UNPHYSICAL, __LINE__, EF_PARTICLE);}
798
799 if(!err) {
800 err = B_field_eval_B_dB(B_dB, p->r, p->phi, p->z, p->time, Bdata);
801 }
802 if(!err) {
803 err = B_field_eval_psi(psi, p->r, p->phi, p->z, p->time, Bdata);
804 }
805 if(!err) {
806 err = B_field_eval_rho(rho, psi[0], Bdata);
807 }
808
809 if(!err) {
810 p->ppar = ppar;
811 }
812 if(!err && p->ppar >= CONST_C) {
814 }
815
816 /* Normally magnetic field data at gc position is stored here
817 * but, if gc transformation fails, field at particle position is
818 * stored instead. */
819 p->rho = rho[0];
820
821 p->B_r = B_dB[0];
822 p->B_r_dr = B_dB[1];
823 p->B_r_dphi = B_dB[2];
824 p->B_r_dz = B_dB[3];
825
826 p->B_phi = B_dB[4];
827 p->B_phi_dr = B_dB[5];
828 p->B_phi_dphi = B_dB[6];
829 p->B_phi_dz = B_dB[7];
830
831 p->B_z = B_dB[8];
832 p->B_z_dr = B_dB[9];
833 p->B_z_dphi = B_dB[10];
834 p->B_z_dz = B_dB[11];
835
836 /* If marker already has error flag, make sure it is not overwritten here */
837 a5err simerr = p_fo->err[j];
838 if(simerr) {
839 p->err = simerr;
840 }
841 else {
842 p->err = err;
843 }
844}
845
872 int j, B_field_data* Bdata) {
873 a5err err = p->err;
874
875 if(!err) {
876 p_gc->r[j] = p->r;
877 p_gc->phi[j] = p->phi;
878 p_gc->z[j] = p->z;
879 p_gc->ppar[j] = p->ppar;
880 p_gc->mu[j] = p->mu;
881 p_gc->zeta[j] = p->zeta;
882
883 p_gc->mass[j] = p->mass;
884 p_gc->charge[j] = p->charge;
885 p_gc->time[j] = p->time;
886 p_gc->bounces[j] = 0;
887 p_gc->weight[j] = p->weight;
888 p_gc->rho[j] = p->rho;
889 p_gc->theta[j] = p->theta;
890 p_gc->id[j] = p->id;
891 p_gc->endcond[j] = p->endcond;
892 p_gc->walltile[j] = p->walltile;
893 p_gc->mileage[j] = p->mileage;
894
895 p_gc->B_r[j] = p->B_r;
896 p_gc->B_r_dr[j] = p->B_r_dr;
897 p_gc->B_r_dphi[j] = p->B_r_dphi;
898 p_gc->B_r_dz[j] = p->B_r_dz;
899
900 p_gc->B_phi[j] = p->B_phi;
901 p_gc->B_phi_dr[j] = p->B_phi_dr;
902 p_gc->B_phi_dphi[j] = p->B_phi_dphi;
903 p_gc->B_phi_dz[j] = p->B_phi_dz;
904
905 p_gc->B_z[j] = p->B_z;
906 p_gc->B_z_dr[j] = p->B_z_dr;
907 p_gc->B_z_dphi[j] = p->B_z_dphi;
908 p_gc->B_z_dz[j] = p->B_z_dz;
909
910 p_gc->running[j] = 1;
911 if(p->endcond) {
912 p_gc->running[j] = 0;
913 }
914 p_gc->cputime[j] = p->cputime;
915 p_gc->index[j] = i;
916 p_gc->err[j] = 0;
917 }
918
919 return err;
920}
921
937 B_field_data* Bdata) {
938 a5err err = 0;
939
940 p->r = p_gc->r[j];
941 p->phi = p_gc->phi[j];
942 p->z = p_gc->z[j];
943 p->ppar = p_gc->ppar[j];
944 p->mu = p_gc->mu[j];
945 p->zeta = p_gc->zeta[j];
946
947 p->mass = p_gc->mass[j];
948 p->charge = p_gc->charge[j];
949 p->time = p_gc->time[j];
950 p->weight = p_gc->weight[j];
951 p->id = p_gc->id[j];
952 p->cputime = p_gc->cputime[j];
953 p->rho = p_gc->rho[j];
954 p->theta = p_gc->theta[j];
955 p->endcond = p_gc->endcond[j];
956 p->walltile = p_gc->walltile[j];
957 p->mileage = p_gc->mileage[j];
958
959 p->B_r = p_gc->B_r[j];
960 p->B_r_dr = p_gc->B_r_dr[j];
961 p->B_r_dphi = p_gc->B_r_dphi[j];
962 p->B_r_dz = p_gc->B_r_dz[j];
963
964 p->B_phi = p_gc->B_phi[j];
965 p->B_phi_dr = p_gc->B_phi_dr[j];
966 p->B_phi_dphi = p_gc->B_phi_dphi[j];
967 p->B_phi_dz = p_gc->B_phi_dz[j];
968
969 p->B_z = p_gc->B_z[j];
970 p->B_z_dr = p_gc->B_z_dr[j];
971 p->B_z_dphi = p_gc->B_z_dphi[j];
972 p->B_z_dz = p_gc->B_z_dz[j];
973
974 /* Guiding center to particle transformation */
975 real B_dB[15];
976 B_dB[0] = p->B_r;
977 B_dB[1] = p->B_r_dr;
978 B_dB[2] = p->B_r_dphi;
979 B_dB[3] = p->B_r_dz;
980 B_dB[4] = p->B_phi;
981 B_dB[5] = p->B_phi_dr;
982 B_dB[6] = p->B_phi_dphi;
983 B_dB[7] = p->B_phi_dz;
984 B_dB[8] = p->B_z;
985 B_dB[9] = p->B_z_dr;
986 B_dB[10] = p->B_z_dphi;
987 B_dB[11] = p->B_z_dz;
988
989 real pr, pphi, pz;
990 if(!err) {
991 real pparprt, muprt, zetaprt;
993 p->mass, p->charge, B_dB,
994 p->r, p->phi, p->z, p->ppar, p->mu, p->zeta,
995 &p->rprt, &p->phiprt, &p->zprt, &pparprt, &muprt, &zetaprt);
996
997 B_field_eval_B_dB(B_dB, p->rprt, p->phiprt, p->zprt, p->time, Bdata);
998
1000 p->mass, p->charge, B_dB,
1001 p->phiprt, pparprt, muprt, zetaprt,
1002 &pr, &pphi, &pz);
1003 }
1004 if(!err && p->rprt <= 0) {err = error_raise(ERR_MARKER_UNPHYSICAL, __LINE__, EF_PARTICLE);}
1005
1006 if(!err) {
1007 p->p_r = pr;
1008 p->p_phi = pphi;
1009 p->p_z = pz;
1010 }
1011
1012 /* If marker already has error flag, make sure it is not overwritten here */
1013 a5err simerr = p_gc->err[j];
1014 if(simerr) {
1015 p->err = simerr;
1016 }
1017 else {
1018 p->err = err;
1019 }
1020}
1021
1053 int j, B_field_data* Bdata) {
1054 a5err err = p->err;
1055
1056 if(!err) {
1057 p_ml->r[j] = p->r;
1058 p_ml->phi[j] = p->phi;
1059 p_ml->z[j] = p->z;
1060
1061 p_ml->pitch[j] = 2*(p->ppar >= 0) - 1.0;
1062 p_ml->time[j] = p->time;
1063 p_ml->weight[j] = p->weight;
1064 p_ml->id[j] = p->id;
1065 p_ml->cputime[j] = p->cputime;
1066 p_ml->rho[j] = p->rho;
1067 p_ml->theta[j] = p->theta;
1068 p_ml->endcond[j] = p->endcond;
1069 p_ml->walltile[j] = p->walltile;
1070 p_ml->mileage[j] = p->mileage;
1071
1072 p_ml->B_r[j] = p->B_r;
1073 p_ml->B_r_dr[j] = p->B_r_dr;
1074 p_ml->B_r_dphi[j] = p->B_r_dphi;
1075 p_ml->B_r_dz[j] = p->B_r_dz;
1076
1077 p_ml->B_phi[j] = p->B_phi;
1078 p_ml->B_phi_dr[j] = p->B_phi_dr;
1079 p_ml->B_phi_dphi[j] = p->B_phi_dphi;
1080 p_ml->B_phi_dz[j] = p->B_phi_dz;
1081
1082 p_ml->B_z[j] = p->B_z;
1083 p_ml->B_z_dr[j] = p->B_z_dr;
1084 p_ml->B_z_dphi[j] = p->B_z_dphi;
1085 p_ml->B_z_dz[j] = p->B_z_dz;
1086
1087 p_ml->running[j] = 1;
1088 if(p->endcond) {
1089 p_ml->running[j] = 0;
1090 }
1091 p_ml->index[j] = i;
1092
1093 p_ml->err[j] = 0;
1094 }
1095
1096 return err;
1097}
1098
1118 B_field_data* Bdata) {
1119 a5err err = 0;
1120
1121 p->rprt = p_ml->r[j];
1122 p->phiprt = p_ml->phi[j];
1123 p->zprt = p_ml->z[j];
1124 p->p_r = 0;
1125 p->p_phi = 0;
1126 p->p_z = 0;
1127
1128 p->r = p_ml->r[j];
1129 p->phi = p_ml->phi[j];
1130 p->z = p_ml->z[j];
1131 p->ppar = p_ml->pitch[j];
1132 p->mu = 0;
1133 p->zeta = 0;
1134 p->mass = 0;
1135 p->charge = 0;
1136 p->time = p_ml->time[j];
1137 p->weight = p_ml->weight[j];
1138 p->id = p_ml->id[j];
1139 p->cputime = p_ml->cputime[j];
1140 p->rho = p_ml->rho[j];
1141 p->theta = p_ml->theta[j];
1142 p->endcond = p_ml->endcond[j];
1143 p->walltile = p_ml->walltile[j];
1144 p->mileage = p_ml->mileage[j];
1145 p->err = p_ml->err[j];
1146
1147 p->B_r = p_ml->B_r[j];
1148 p->B_r_dr = p_ml->B_r_dr[j];
1149 p->B_r_dphi = p_ml->B_r_dphi[j];
1150 p->B_r_dz = p_ml->B_r_dz[j];
1151
1152 p->B_phi = p_ml->B_phi[j];
1153 p->B_phi_dr = p_ml->B_phi_dr[j];
1154 p->B_phi_dphi = p_ml->B_phi_dphi[j];
1155 p->B_phi_dz = p_ml->B_phi_dz[j];
1156
1157 p->B_z = p_ml->B_z[j];
1158 p->B_z_dr = p_ml->B_z_dr[j];
1159 p->B_z_dphi = p_ml->B_z_dphi[j];
1160 p->B_z_dz = p_ml->B_z_dz[j];
1161
1162 /* If marker already has error flag, make sure it is not overwritten here */
1163 a5err simerr = p_ml->err[j];
1164 if(simerr) {
1165 p->err = simerr;
1166 }
1167 else {
1168 p->err = err;
1169 }
1170 if(!simerr && err) {err = err;}
1171 p->err = err;
1172}
1173
1186 B_field_data* Bdata) {
1187 a5err err = p_fo->err[j];
1188 real axisrz[2];
1189 int simerr = 0; /* Error has already occurred */
1190 if(err) {simerr = 1;}
1191 p_gc->id[j] = p_fo->id[j];
1192 p_gc->index[j] = p_fo->index[j];
1193
1194 real r, phi, z, ppar, mu, zeta, B_dB[15];
1195 if(!err) {
1196 real Rprt = p_fo->r[j];
1197 real phiprt = p_fo->phi[j];
1198 real zprt = p_fo->z[j];
1199 real pr = p_fo->p_r[j];
1200 real pphi = p_fo->p_phi[j];
1201 real pz = p_fo->p_z[j];
1202 real mass = p_fo->mass[j];
1203 real charge = p_fo->charge[j];
1204
1205 p_gc->mass[j] = p_fo->mass[j];
1206 p_gc->charge[j] = p_fo->charge[j];
1207 p_gc->weight[j] = p_fo->weight[j];
1208 p_gc->time[j] = p_fo->time[j];
1209 p_gc->mileage[j] = p_fo->mileage[j];
1210 p_gc->endcond[j] = p_fo->endcond[j];
1211 p_gc->running[j] = p_fo->running[j];
1212 p_gc->walltile[j] = p_fo->walltile[j];
1213 p_gc->cputime[j] = p_fo->cputime[j];
1214
1215 B_dB[0] = p_fo->B_r[j];
1216 B_dB[1] = p_fo->B_r_dr[j];
1217 B_dB[2] = p_fo->B_r_dphi[j];
1218 B_dB[3] = p_fo->B_r_dz[j];
1219 B_dB[4] = p_fo->B_phi[j];
1220 B_dB[5] = p_fo->B_phi_dr[j];
1221 B_dB[6] = p_fo->B_phi_dphi[j];
1222 B_dB[7] = p_fo->B_phi_dz[j];
1223 B_dB[8] = p_fo->B_z[j];
1224 B_dB[9] = p_fo->B_z_dr[j];
1225 B_dB[10] = p_fo->B_z_dphi[j];
1226 B_dB[11] = p_fo->B_z_dz[j];
1227
1228 /* Guiding center transformation */
1230 mass, charge, B_dB,
1231 Rprt, phiprt, zprt, pr , pphi, pz,
1232 &r, &phi, &z, &ppar, &mu, &zeta);
1233 }
1234 if(!err && r <= 0) {err = error_raise(ERR_MARKER_UNPHYSICAL, __LINE__, EF_PARTICLE);}
1235 if(!err && mu < 0) {err = error_raise(ERR_MARKER_UNPHYSICAL, __LINE__, EF_PARTICLE);}
1236
1237 real psi[1], rho[2];
1238 if(!err) {
1239 err = B_field_eval_B_dB(
1240 B_dB, r, phi, z, p_fo->time[j], Bdata);
1241 }
1242 if(!err) {
1243 err = B_field_eval_psi(
1244 psi, r, phi, z, p_fo->time[j], Bdata);
1245 }
1246 if(!err) {
1247 err = B_field_eval_rho(rho, psi[0], Bdata);
1248 }
1249 if(!err) {
1250 err = B_field_get_axis_rz(axisrz, Bdata, p_gc->phi[j]);
1251 }
1252
1253 if(!err) {
1254 p_gc->r[j] = r;
1255 p_gc->phi[j] = phi;
1256 p_gc->z[j] = z;
1257 p_gc->mu[j] = mu;
1258 p_gc->zeta[j] = zeta;
1259 p_gc->ppar[j] = ppar;
1260 p_gc->rho[j] = rho[0];
1261
1262 /* Evaluate pol angle so that it is cumulative and at gc position */
1263 p_gc->theta[j] = p_fo->theta[j];
1264 p_gc->theta[j] += atan2( (p_fo->r[j]-axisrz[0]) * (p_gc->z[j]-axisrz[1])
1265 - (p_fo->z[j]-axisrz[1]) * (p_gc->r[j]-axisrz[0]),
1266 (p_fo->r[j]-axisrz[0]) * (p_gc->r[j]-axisrz[0])
1267 + (p_fo->z[j]-axisrz[1]) * (p_gc->z[j]-axisrz[1]) );
1268
1269 p_gc->B_r[j] = B_dB[0];
1270 p_gc->B_r_dr[j] = B_dB[1];
1271 p_gc->B_r_dphi[j] = B_dB[2];
1272 p_gc->B_r_dz[j] = B_dB[3];
1273
1274 p_gc->B_phi[j] = B_dB[4];
1275 p_gc->B_phi_dr[j] = B_dB[5];
1276 p_gc->B_phi_dphi[j] = B_dB[6];
1277 p_gc->B_phi_dz[j] = B_dB[7];
1278
1279 p_gc->B_z[j] = B_dB[8];
1280 p_gc->B_z_dr[j] = B_dB[9];
1281 p_gc->B_z_dphi[j] = B_dB[10];
1282 p_gc->B_z_dz[j] = B_dB[11];
1283 }
1284 if(!simerr) {err = err;}
1285 p_gc->err[j] = err;
1286 if(p_gc->err[j]) {
1287 p_gc->running[j] = 0;
1288 p_gc->endcond[j] = 0;
1289 }
1290
1291 return err > 0;
1292}
1293
1303 p2->r[j] = p1->r[i];
1304 p2->phi[j] = p1->phi[i];
1305 p2->z[j] = p1->z[i];
1306 p2->p_r[j] = p1->p_r[i];
1307 p2->p_phi[j] = p1->p_phi[i];
1308 p2->p_z[j] = p1->p_z[i];
1309
1310 p2->time[j] = p1->time[i];
1311 p2->mileage[j] = p1->mileage[i];
1312 p2->cputime[j] = p1->cputime[i];
1313 p2->rho[j] = p1->rho[i];
1314 p2->weight[j] = p1->weight[i];
1315 p2->cputime[j] = p1->cputime[i];
1316 p2->rho[j] = p1->rho[i];
1317 p2->theta[j] = p1->theta[i];
1318
1319 p2->mass[j] = p1->mass[i];
1320 p2->charge[j] = p1->charge[i];
1321 p2->znum[j] = p1->znum[i];
1322 p2->anum[j] = p1->anum[i];
1323
1324 p2->id[j] = p1->id[i];
1325 p2->bounces[j] = p1->bounces[i];
1326 p2->running[j] = p1->running[i];
1327 p2->endcond[j] = p1->endcond[i];
1328 p2->walltile[j] = p1->walltile[i];
1329
1330 p2->B_r[j] = p1->B_r[i];
1331 p2->B_phi[j] = p1->B_phi[i];
1332 p2->B_z[j] = p1->B_z[i];
1333
1334 p2->B_r_dr[j] = p1->B_r_dr[i];
1335 p2->B_r_dphi[j] = p1->B_r_dphi[i];
1336 p2->B_r_dz[j] = p1->B_r_dz[i];
1337
1338 p2->B_phi_dr[j] = p1->B_phi_dr[i];
1339 p2->B_phi_dphi[j] = p1->B_phi_dphi[i];
1340 p2->B_phi_dz[j] = p1->B_phi_dz[i];
1341
1342 p2->B_z_dr[j] = p1->B_z_dr[i];
1343 p2->B_z_dphi[j] = p1->B_z_dphi[i];
1344 p2->B_z_dz[j] = p1->B_z_dz[i];
1345}
1346
1356 p2->r[j] = p1->r[i];
1357 p2->phi[j] = p1->phi[i];
1358 p2->z[j] = p1->z[i];
1359 p2->ppar[j] = p1->ppar[i];
1360 p2->mu[j] = p1->mu[i];
1361 p2->zeta[j] = p1->zeta[i];
1362
1363 p2->time[j] = p1->time[i];
1364 p2->mileage[j] = p1->mileage[i];
1365 p2->weight[j] = p1->weight[i];
1366 p2->cputime[j] = p1->cputime[i];
1367 p2->rho[j] = p1->rho[i];
1368 p2->theta[j] = p1->theta[i];
1369
1370 p2->mass[j] = p1->mass[i];
1371 p2->charge[j] = p1->charge[i];
1372
1373 p2->id[j] = p1->id[i];
1374 p2->bounces[j] = p1->bounces[i];
1375 p2->running[j] = p1->running[i];
1376 p2->endcond[j] = p1->endcond[i];
1377 p2->walltile[j] = p1->walltile[i];
1378
1379 p2->B_r[j] = p1->B_r[i];
1380 p2->B_phi[j] = p1->B_phi[i];
1381 p2->B_z[j] = p1->B_z[i];
1382
1383 p2->B_r_dr[j] = p1->B_r_dr[i];
1384 p2->B_r_dphi[j] = p1->B_r_dphi[i];
1385 p2->B_r_dz[j] = p1->B_r_dz[i];
1386
1387 p2->B_phi_dr[j] = p1->B_phi_dr[i];
1388 p2->B_phi_dphi[j] = p1->B_phi_dphi[i];
1389 p2->B_phi_dz[j] = p1->B_phi_dz[i];
1390
1391 p2->B_z_dr[j] = p1->B_z_dr[i];
1392 p2->B_z_dphi[j] = p1->B_z_dphi[i];
1393 p2->B_z_dz[j] = p1->B_z_dz[i];
1394}
1395
1405 int j) {
1406 p2->r[j] = p1->r[i];
1407 p2->phi[j] = p1->phi[i];
1408 p2->z[j] = p1->z[i];
1409 p2->pitch[j] = p1->pitch[i];
1410
1411 p2->time[j] = p1->time[i];
1412 p2->mileage[j] = p1->mileage[i];
1413 p2->cputime[j] = p1->cputime[i];
1414 p2->rho[j] = p1->rho[i];
1415 p2->weight[j] = p1->weight[i];
1416 p2->theta[j] = p1->theta[i];
1417
1418 p2->id[j] = p1->id[i];
1419 p2->running[j] = p1->running[i];
1420 p2->endcond[j] = p1->endcond[i];
1421 p2->walltile[j] = p1->walltile[i];
1422
1423 p2->B_r[j] = p1->B_r[i];
1424 p2->B_phi[j] = p1->B_phi[i];
1425 p2->B_z[j] = p1->B_z[i];
1426
1427 p2->B_r_dr[j] = p1->B_r_dr[i];
1428 p2->B_r_dphi[j] = p1->B_r_dphi[i];
1429 p2->B_r_dz[j] = p1->B_r_dz[i];
1430
1431 p2->B_phi_dr[j] = p1->B_phi_dr[i];
1432 p2->B_phi_dphi[j] = p1->B_phi_dphi[i];
1433 p2->B_phi_dz[j] = p1->B_phi_dz[i];
1434
1435 p2->B_z_dr[j] = p1->B_z_dr[i];
1436 p2->B_z_dphi[j] = p1->B_z_dphi[i];
1437 p2->B_z_dz[j] = p1->B_z_dz[i];
1438}
1439
1450 B_field_data* Bdata) {
1451 a5err err = 0;
1452 real axisrz[2];
1453 if(!err) {
1454 err = B_field_get_axis_rz(axisrz, Bdata, p->phi);
1455 }
1456 ps->rprt = p->r;
1457 ps->phiprt = p->phi;
1458 ps->zprt = p->z;
1459 ps->p_r = p->p_r;
1460 ps->p_phi = p->p_phi;
1461 ps->p_z = p->p_z;
1462 ps->mass = p->mass;
1463 ps->charge = p->charge;
1464 ps->anum = p->anum;
1465 ps->znum = p->znum;
1466 ps->weight = p->weight;
1467 ps->time = p->time;
1468 ps->theta = atan2(ps->zprt-axisrz[1], ps->rprt-axisrz[0]);
1469 ps->id = p->id;
1470 ps->mileage = 0;
1471 ps->endcond = 0;
1472 ps->walltile = 0;
1473 ps->cputime = 0;
1474
1475 /* Guiding center transformation */
1476 real B_dB[15], r, phi, z, ppar, mu, zeta, psi[1], rho[2];
1477 err = B_field_eval_B_dB(B_dB, ps->rprt, ps->phiprt, ps->zprt,
1478 ps->time, Bdata);
1479
1480 if(!err) {
1482 ps->mass, ps->charge, B_dB,
1483 ps->rprt, ps->phiprt, ps->zprt, p->p_r, p->p_phi, p->p_z,
1484 &r, &phi, &z, &ppar, &mu, &zeta);
1485 }
1486 if(!err && r <= 0) {
1488 }
1489 if(!err && mu < 0) {
1491 }
1492
1493 /* Update magnetic field at gc position */
1494 if(!err) {
1495 err = B_field_eval_B_dB(B_dB, r, phi, z, ps->time, Bdata);
1496 }
1497 if(!err) {
1498 err = B_field_eval_psi(psi, r, phi, z, ps->time, Bdata);
1499 }
1500 if(!err) {
1501 err = B_field_eval_rho(rho, psi[0], Bdata);
1502 }
1503
1504 if(!err) {
1505 ps->r = r;
1506 ps->phi = phi;
1507 ps->z = z;
1508 ps->ppar = ppar;
1509 ps->mu = mu;
1510 ps->zeta = zeta;
1511
1512 ps->rho = rho[0];
1513 ps->B_r = B_dB[0];
1514 ps->B_phi = B_dB[4];
1515 ps->B_z = B_dB[8];
1516 ps->B_r_dr = B_dB[1];
1517 ps->B_phi_dr = B_dB[5];
1518 ps->B_z_dr = B_dB[9];
1519 ps->B_r_dphi = B_dB[2];
1520 ps->B_phi_dphi = B_dB[6];
1521 ps->B_z_dphi = B_dB[10];
1522 ps->B_r_dz = B_dB[3];
1523 ps->B_phi_dz = B_dB[7];
1524 ps->B_z_dz = B_dB[11];
1525
1526 ps->err = 0;
1527 }
1528 return err;
1529}
1530
1541 B_field_data* Bdata) {
1542 a5err err = 0;
1543 real axisrz[2];
1544 real B_dB[15], psi[1], rho[2];
1545 if(!err) {
1546 err = B_field_eval_B_dB(B_dB, p->r, p->phi, p->z, p->time, Bdata);
1547 }
1548 if(!err) {
1549 err = B_field_eval_psi(psi, p->r, p->phi, p->z, p->time, Bdata);
1550 }
1551 if(!err) {
1552 err = B_field_eval_rho(rho, psi[0], Bdata);
1553 }
1554
1555 if(!err) {
1556 ps->rho = rho[0];
1557 ps->B_r = B_dB[0];
1558 ps->B_phi = B_dB[4];
1559 ps->B_z = B_dB[8];
1560 ps->B_r_dr = B_dB[1];
1561 ps->B_phi_dr = B_dB[5];
1562 ps->B_z_dr = B_dB[9];
1563 ps->B_r_dphi = B_dB[2];
1564 ps->B_phi_dphi = B_dB[6];
1565 ps->B_z_dphi = B_dB[10];
1566 ps->B_r_dz = B_dB[3];
1567 ps->B_phi_dz = B_dB[7];
1568 ps->B_z_dz = B_dB[11];
1569 }
1570
1571 /* Input is in (Ekin,xi) coordinates but state needs (mu,vpar) so we need
1572 * to do that transformation first. */
1573 real gamma, mu, ppar;
1574 if(!err) {
1575 /* From kinetic energy we get Lorentz factor as gamma = 1 + Ekin/mc^2 */
1576 gamma = 1 + p->energy / (p->mass * CONST_C2);
1577
1578 /* And then we can use the formula for Lorentz factor to get total momentum */
1579 real pnorm = sqrt( gamma * gamma - 1 ) * p->mass * CONST_C;
1580
1581 /* Now we can use library functions for transformation */
1582 real Bnorm = math_normc(B_dB[0], B_dB[4], B_dB[8]);
1583 ppar = physlib_gc_ppar(pnorm, p->pitch);
1584 mu = physlib_gc_mu(p->mass, pnorm, p->pitch, Bnorm);
1585 }
1586 if(!err && mu < 0) {
1588 }
1589 if(!err) {
1590 err = B_field_get_axis_rz(axisrz, Bdata, p->phi);
1591 }
1592
1593 if(!err) {
1594 ps->r = p->r;
1595 ps->phi = p->phi;
1596 ps->z = p->z;
1597 ps->mu = mu;
1598 ps->ppar = ppar;
1599 ps->zeta = p->zeta;
1600 ps->mass = p->mass;
1601 ps->charge = p->charge;
1602 ps->anum = p->anum;
1603 ps->znum = p->znum;
1604 ps->weight = p->weight;
1605 ps->time = p->time;
1606 ps->theta = atan2(ps->z-axisrz[1], ps->r-axisrz[0]);
1607 ps->id = p->id;
1608 ps->mileage = 0;
1609 ps->endcond = 0;
1610 ps->walltile = 0;
1611 ps->cputime = 0;
1612 }
1613
1614 /* Guiding center transformation to get particle coordinates */
1615 real rprt, phiprt, zprt, pr, pphi, pz;
1616 if(!err) {
1617 real pparprt, muprt, zetaprt;
1619 ps->mass, ps->charge, B_dB,
1620 ps->r, ps->phi, ps->z, ps->ppar, ps->mu, ps->zeta,
1621 &rprt, &phiprt, &zprt, &pparprt, &muprt, &zetaprt);
1622
1623 B_field_eval_B_dB(B_dB, rprt, phiprt, zprt, ps->time, Bdata);
1624
1626 ps->mass, ps->charge, B_dB,
1627 phiprt, pparprt, muprt, zetaprt,
1628 &pr, &pphi, &pz);
1629 }
1630 if(!err && rprt <= 0) {
1632 }
1633
1634 if(!err) {
1635 ps->rprt = rprt;
1636 ps->phiprt = phiprt;
1637 ps->zprt = zprt;
1638 ps->p_r = pr;
1639 ps->p_phi = pphi;
1640 ps->p_z = pz;
1641
1642 ps->err = 0;
1643 }
1644 return err;
1645}
1646
1657 B_field_data* Bdata) {
1658 a5err err = 0;
1659 real axisrz[2];
1660 real B_dB[15], psi[1], rho[2];
1661 if(!err) {
1662 err = B_field_eval_B_dB(B_dB, p->r, p->phi, p->z, p->time, Bdata);
1663 }
1664 if(!err) {
1665 err = B_field_eval_psi(psi, p->r, p->phi, p->z, p->time, Bdata);
1666 }
1667 if(!err) {
1668 err = B_field_eval_rho(rho, psi[0], Bdata);
1669 }
1670 if(!err) {
1671 err = B_field_get_axis_rz(axisrz, Bdata, p->phi);
1672 }
1673
1674 if(!err) {
1675 ps->rprt = p->r;
1676 ps->phiprt = p->phi;
1677 ps->zprt = p->z;
1678 ps->p_r = 0;
1679 ps->p_phi = 0;
1680 ps->p_z = 0;
1681
1682 ps->mass = 0;
1683 ps->charge = 0;
1684 ps->anum = 0;
1685 ps->znum = 0;
1686 ps->weight = p->weight;
1687 ps->time = p->time;
1688 ps->id = p->id;
1689 ps->theta = atan2(p->z - axisrz[1], p->r - axisrz[0]);
1690 ps->endcond = 0;
1691 ps->walltile = 0;
1692 ps->cputime = 0;
1693 ps->mileage = 0;
1694
1695 ps->r = p->r;
1696 ps->phi = p->phi;
1697 ps->z = p->z;
1698 ps->ppar = p->pitch >= 0;
1699 ps->mu = 0;
1700 ps->zeta = 0;
1701
1702 ps->rho = rho[0];
1703 ps->B_r = B_dB[0];
1704 ps->B_phi = B_dB[4];
1705 ps->B_z = B_dB[8];
1706 ps->B_r_dr = B_dB[1];
1707 ps->B_phi_dr = B_dB[5];
1708 ps->B_z_dr = B_dB[9];
1709 ps->B_r_dphi = B_dB[2];
1710 ps->B_phi_dphi = B_dB[6];
1711 ps->B_z_dphi = B_dB[10];
1712 ps->B_r_dz = B_dB[3];
1713 ps->B_phi_dz = B_dB[7];
1714 ps->B_z_dz = B_dB[11];
1715
1716 ps->err = 0;
1717 }
1718 return err;
1719}
1720
1727 GPU_MAP_TO_DEVICE(
1728 p[0:1],\
1729 p->running [0:p->n_mrk],\
1730 p->r [0:p->n_mrk],\
1731 p->phi [0:p->n_mrk],\
1732 p->p_r [0:p->n_mrk],\
1733 p->p_phi [0:p->n_mrk],\
1734 p->p_z [0:p->n_mrk],\
1735 p->mileage [0:p->n_mrk],\
1736 p->z [0:p->n_mrk],\
1737 p->charge [0:p->n_mrk],\
1738 p->mass [0:p->n_mrk],\
1739 p->B_r [0:p->n_mrk],\
1740 p->B_r_dr [0:p->n_mrk],\
1741 p->B_r_dphi [0:p->n_mrk],\
1742 p->B_r_dz [0:p->n_mrk],\
1743 p->B_phi [0:p->n_mrk],\
1744 p->B_phi_dr [0:p->n_mrk],\
1745 p->B_phi_dphi[0:p->n_mrk],\
1746 p->B_phi_dz [0:p->n_mrk],\
1747 p->B_z [0:p->n_mrk],\
1748 p->B_z_dr [0:p->n_mrk],\
1749 p->B_z_dphi [0:p->n_mrk],\
1750 p->B_z_dz [0:p->n_mrk],\
1751 p->rho [0:p->n_mrk],\
1752 p->theta [0:p->n_mrk],\
1753 p->err [0:p->n_mrk],\
1754 p->time [0:p->n_mrk],\
1755 p->weight [0:p->n_mrk],\
1756 p->cputime [0:p->n_mrk],\
1757 p->id [0:p->n_mrk],\
1758 p->endcond [0:p->n_mrk],\
1759 p->walltile [0:p->n_mrk],\
1760 p->index [0:p->n_mrk],\
1761 p->znum [0:p->n_mrk],\
1762 p->anum [0:p->n_mrk],\
1763 p->bounces [0:p->n_mrk]
1764 )
1765}
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_psi(real *psi, real r, real phi, real z, real t, B_field_data *Bdata)
Evaluate poloidal flux psi.
Definition B_field.c:201
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
a5err B_field_get_axis_rz(real rz[2], B_field_data *Bdata, real phi)
Return magnetic axis Rz-coordinates.
Definition B_field.c:599
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:66
static DECLARE_TARGET_SIMD a5err error_raise(error_type type, int line, error_file file)
Raise a new error.
Definition error.h:86
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:67
void particle_to_ml_dummy(particle_simd_ml *p_ml, int j)
Makes a dummy ML simulation marker.
Definition particle.c:218
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:936
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:1540
void particle_copy_gc(particle_simd_gc *p1, int i, particle_simd_gc *p2, int j)
Copy GC struct.
Definition particle.c:1355
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:871
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:659
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:744
void particle_to_fo_dummy(particle_simd_fo *p_fo, int j)
Makes a dummy FO simulation marker.
Definition particle.c:132
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:1185
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:1656
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:550
void particle_to_gc_dummy(particle_simd_gc *p_gc, int j)
Makes a dummy GC simulation marker.
Definition particle.c:172
void particle_copy_ml(particle_simd_ml *p1, int i, particle_simd_ml *p2, int j)
Copy ML struct.
Definition particle.c:1404
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:1052
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:1449
void particle_offload_fo(particle_simd_fo *p)
Offload particle struct to GPU.
Definition particle.c:1726
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:461
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:1117
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:367
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:268
void particle_copy_fo(particle_simd_fo *p1, int i, particle_simd_fo *p2, int j)
Copy FO struct.
Definition particle.c:1302
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:166
#define physlib_gc_mu(m, p, xi, B)
Evaluate guiding center magnetic moment [J/T] from momentum norm and pitch.
Definition physlib.h:180
Magnetic field simulation data.
Definition B_field.h:63
Wrapper for marker structs.
Definition particle.h:186
particle_ml p_ml
Definition particle.h:191
input_particle_type type
Definition particle.h:187
particle p
Definition particle.h:189
particle_gc p_gc
Definition particle.h:190
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
Struct representing NSIMD field line markers.
Definition particle.h:342
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