XGC1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
field_aligned_local_fields.hpp
Go to the documentation of this file.
1 #ifndef FIELD_ALIGNED_LOCAL_FIELDS_HPP
2 #define FIELD_ALIGNED_LOCAL_FIELDS_HPP
3 
4 #include "globals.hpp"
5 #include "push_controls.hpp"
6 #include "grid.hpp"
7 #include "gyro_radius.hpp"
8 #include "electric_field.hpp"
9 #include "grid_field_pack.hpp"
10 
11 
12 /* This class manages how to obtain the local grid field data during the push. It either:
13  * - a) performs a gather operation when the method fields_at_point is used, or
14  * - b) performs a gather operation when initialized, stores those values and
15  * returns them when the fields_at_point method is used.
16  * Option b) is used in XGC1 for ions, because the ion location in an intermediate RK step
17  * might not have a valid associated field since it could be outside of the toroidal sector
18  * for which field information is present.
19  * The generic declaration uses Option a) */
20 template<KinType KT, PhiInterpType PIT>
22  // No members
23 
24  public:
25 
26  // Nothing to do in constructor
27  template<class Device>
28  KOKKOS_INLINE_FUNCTION FieldAlignedLocalFields(const Grid<Device> &grid, const PushControls &push_controls, const Species<Device> &species,
30 
31  /* Gather fields if calculating for electrons */
32  template<class Device>
33  KOKKOS_INLINE_FUNCTION void fields_at_point(const GridFieldPack<Device, PIT> fields, const PushControls &push_controls, const Grid<Device> &grid,
34  const SimdVector &B, const SimdVector2D &gradpsi, const SimdGridWeights<Order::One, PIT>& grid_wts,
35  SimdGyroWeights<KT>& rho_wts, LocalFields& fld) const{
36  fields.fields_at_point(push_controls, grid, B,gradpsi,grid_wts,rho_wts, fld);
37  }
38 };
39 
40 /* If using XGC1, then the class specialization on KinType GyroKin stores the field aligned
41  * local field calculated in the constructor, and converts it to cylindrical coordinates in
42  * fields_at_point. */
43 template<>
45  // Simd vectors are hard-coded to (r, z, phi), but here they represent field-aligned coordinates instead
46  // "phi" --> parallel to B-field
48 # ifdef EXPLICIT_EM
51 # endif
52 
53  // Members that don't get adjusted but need to be stored
54 #if defined(DELTAF_CONV) && !defined(EXPLICIT_EM)
57 #endif
58 #ifdef EXPLICIT_EM
62 #endif
63 
64  /* Convert stored electric/magnetic fields to field-aligned coordinates from cylindrical coordinates */
65  KOKKOS_INLINE_FUNCTION void convert_cyl_to_mag(const SimdVector &B, const SimdVector2D &gradpsi, const LocalFields& fld){
66  const auto& fld_E = fld.template get<Label::E>(); // Alias (not a copy)
67 # ifdef EXPLICIT_EM
68  const auto& fld_dAh = fld.template get<Label::dAh>(); // Alias (not a copy)
69  const auto& fld_dAs = fld.template get<Label::dAs>(); // Alias (not a copy)
70 # endif
71  for (int i_simd = 0; i_simd<SIMD_SIZE; i_simd++){
72  double Bmag = B.magnitude(i_simd);
73  double Bp = B.poloidal_magnitude(i_simd);
74  double grad2 = gradpsi.r[i_simd]*gradpsi.r[i_simd] + gradpsi.z[i_simd]*gradpsi.z[i_simd];
75 
76  // get E-field in magnetic field-aligned basis
77  E.r[i_simd] = (fld_E.r[i_simd] *gradpsi.r[i_simd] + fld_E.z[i_simd] *gradpsi.z[i_simd])/grad2;
78  E.z[i_simd] = (fld_E.r[i_simd] *B.r[i_simd] + fld_E.z[i_simd] *B.z[i_simd] )/Bp;
79  E.phi[i_simd] = (E.z[i_simd]*Bp + fld_E.phi[i_simd]*B.phi[i_simd] )/Bmag; // parallel field
80 
81 # ifdef EXPLICIT_EM
82  // grad(A_h)
83  dAh.r[i_simd] = (fld_dAh.r[i_simd]*gradpsi.r[i_simd] + fld_dAh.z[i_simd]*gradpsi.z[i_simd])/grad2;
84  dAh.z[i_simd] = (fld_dAh.r[i_simd]*B.r[i_simd] + fld_dAh.z[i_simd]*B.z[i_simd] )/Bp;
85  dAh.phi[i_simd] = (dAh.z[i_simd] *Bp + fld_dAh.phi[i_simd]*B.phi[i_simd] )/Bmag;
86 
87  // These variables are for the mixed-variables formulation.
88  // Make sure that they are initialized to 0 if Hamiltonian
89  // formulation is used.
90  dAs.r[i_simd] = (fld_dAs.r[i_simd]*gradpsi.r[i_simd] + fld_dAs.z[i_simd]*gradpsi.z[i_simd])/grad2;
91  dAs.z[i_simd] = (fld_dAs.r[i_simd]*B.r[i_simd] + fld_dAs.z[i_simd]*B.z[i_simd] )/Bp;
92  dAs.phi[i_simd] = (dAs.z[i_simd] *Bp + fld_dAs.phi[i_simd]*B.phi[i_simd] )/Bmag;
93 # endif
94  }
95  }
96 
97  /* Convert stored electric/magnetic fields from field-aligned coordinates to cylindrical coordinates */
98  KOKKOS_INLINE_FUNCTION void convert_mag_to_cyl(const SimdVector &B, const SimdVector2D &gradpsi, LocalFields& fld) const{
99  auto& fld_E = fld.template get<Label::E>(); // Alias (not a copy)
100 # ifdef EXPLICIT_EM
101  auto& fld_dAh = fld.template get<Label::dAh>(); // Alias (not a copy)
102  auto& fld_dAs = fld.template get<Label::dAs>(); // Alias (not a copy)
103 # endif
104  for (int i_simd = 0; i_simd<SIMD_SIZE; i_simd++){
105  double Bmag = B.magnitude(i_simd);
106  double Bp = B.poloidal_magnitude(i_simd);
107  double Br_norm = B.r[i_simd] / Bp;
108  double Bz_norm = B.z[i_simd] / Bp;
109 
110  fld_E.r[i_simd] = E.r[i_simd]*gradpsi.r[i_simd]+E.z[i_simd]*Br_norm;
111  fld_E.z[i_simd] = E.r[i_simd]*gradpsi.z[i_simd]+E.z[i_simd]*Bz_norm;
112  fld_E.phi[i_simd] = (E.phi[i_simd]*Bmag - fld_E.r[i_simd]*B.r[i_simd] - fld_E.z[i_simd]*B.z[i_simd])/B.phi[i_simd];
113 
114 # ifdef EXPLICIT_EM
115  fld_dAh.r[i_simd] = dAh.r[i_simd]*gradpsi.r[i_simd]+dAh.z[i_simd]*Br_norm;
116  fld_dAh.z[i_simd] = dAh.r[i_simd]*gradpsi.z[i_simd]+dAh.z[i_simd]*Bz_norm;
117  fld_dAh.phi[i_simd] = (dAh.phi[i_simd]*Bmag - fld_dAh.r[i_simd]*B.r[i_simd] - fld_dAh.z[i_simd]*B.z[i_simd])/B.phi[i_simd];
118 
119  // The following are for the mixed-variable formulation
120  // Make sure that no all variables are initialized
121  fld_dAs.r[i_simd] = dAs.r[i_simd]*gradpsi.r[i_simd]+dAs.z[i_simd]*Br_norm;
122  fld_dAs.z[i_simd] = dAs.r[i_simd]*gradpsi.z[i_simd]+dAs.z[i_simd]*Bz_norm;
123  fld_dAs.phi[i_simd] = (dAs.phi[i_simd]*Bmag - fld_dAs.r[i_simd]*B.r[i_simd] - fld_dAs.z[i_simd]*B.z[i_simd])/B.phi[i_simd];
124 # endif
125  }
126  }
127 
128  public:
129 
130  /* Gather electric/magnetic fields and convert to field-aligned coordinates for storage */
131  template<class Device>
132  KOKKOS_INLINE_FUNCTION FieldAlignedLocalFields(const Grid<Device> &grid, const PushControls &push_controls, const Species<Device> &species,
134  // Declare arrays returned from B-field
135  SimdVector B;
136  SimdVector jacb[3];
137  Simd<double> psi;
138  SimdVector2D gradpsi;
139  SimdVector tdb;
140  Simd<bool> rz_outside;
141 
142  // obtain B-field information
143  magnetic_field.field(part.ph.v(), B, jacb, psi, gradpsi, tdb, rz_outside);
144  part.deactivate(rz_outside);
145 
146  // Get the current field following grid triangle and p weights
147  grid.get_grid_weights(magnetic_field, part.ph.v(), psi, grid_wts);
148 
149  // calculate rho weights
150  SimdGyroWeights<GyroKin> rho_wts(grid, magnetic_field, species, part.ph.v(), part.ct.mu);
151 
152  // get electric field
153  LocalFields fld;
154  gfpack.fields_at_point(push_controls, grid, B,gradpsi,grid_wts,rho_wts, fld);
155 
156  // Convert to field-aligned coordinates and store
157  convert_cyl_to_mag(B, gradpsi, fld);
158 
159  // These get stored without any conversion; Consolidate field_aligned_local_fields with local_fields objects to avoid this copy
160 #if defined(DELTAF_CONV) && !defined(EXPLICIT_EM)
161  E00=fld.template get<Label::E00>(); // Should E00 also be field-aligned?
162  ddpotdt = fld.template get<Label::ddpotdt>();
163 #endif
164 #ifdef EXPLICIT_EM
165  Ah = fld.template get<Label::Ah>();
166  As = fld.template get<Label::As>();
167  Epar_em = fld.template get<Label::Epar_em>();
168 #endif
169  }
170 
171  /* Return the stored field values for XGC1 ions */
172  template<class Device>
173  KOKKOS_INLINE_FUNCTION void fields_at_point(const GridFieldPack<Device, PhiInterpType::Planes> fields, const PushControls &push_controls, const Grid<Device> &grid,
174  const SimdVector &B, const SimdVector2D &gradpsi, const SimdGridWeights<Order::One, PhiInterpType::Planes>& grid_wts,
175  SimdGyroWeights<GyroKin>& rho_wts, LocalFields& fld) const{
176  convert_mag_to_cyl(B, gradpsi, fld);
177 
178  // These get stored without any conversion; Consolidate field_aligned_local_fields with local_fields objects to avoid this copy
179 #if defined(DELTAF_CONV) && !defined(EXPLICIT_EM)
180  fld.template get<Label::E00>()=E00; // Should E00 also be field-aligned?
181  fld.template get<Label::ddpotdt>() = ddpotdt;
182 #endif
183 #ifdef EXPLICIT_EM
184  fld.template get<Label::Ah>() = Ah;
185  fld.template get<Label::As>() = As;
186  fld.template get<Label::Epar_em>() = Epar_em;
187 #endif
188  }
189 };
190 
191 
192 #endif
Simd< double > r
Definition: simd.hpp:150
Definition: simd.hpp:149
Definition: grid_weights.hpp:73
Definition: grid_weights.hpp:47
Definition: push_controls.hpp:9
Definition: magnetic_field.hpp:12
Definition: grid.hpp:21
Definition: grid_field_pack.hpp:21
KOKKOS_INLINE_FUNCTION void field(const SimdVector &v, SimdVector &bvec, SimdVector(&jacb)[3], Simd< double > &psivec, SimdVector2D &gradpsi, SimdVector &tdb, Simd< bool > &rz_outside) const
Definition: magnetic_field.tpp:138
Definition: local_fields.hpp:33
KOKKOS_INLINE_FUNCTION double poloidal_magnitude(const int i_simd) const
Definition: simd.hpp:181
KOKKOS_INLINE_FUNCTION FieldAlignedLocalFields(const Grid< Device > &grid, const PushControls &push_controls, const Species< Device > &species, const MagneticField< Device > &magnetic_field, const GridFieldPack< Device, PIT > &gfpack, SimdParticles &part, SimdGridWeights< Order::One, PIT > &grid_wts)
Definition: field_aligned_local_fields.hpp:28
PhiInterpType
Definition: globals.hpp:95
Definition: gyro_radius.hpp:24
Definition: gyro_radius.hpp:84
KOKKOS_INLINE_FUNCTION SimdVector & v()
Definition: particles.hpp:39
KOKKOS_INLINE_FUNCTION void convert_cyl_to_mag(const SimdVector &B, const SimdVector2D &gradpsi, const LocalFields &fld)
Definition: field_aligned_local_fields.hpp:65
Simd< double > z
Definition: simd.hpp:141
Definition: globals.hpp:90
KOKKOS_INLINE_FUNCTION void fields_at_point(const GridFieldPack< Device, PhiInterpType::Planes > fields, const PushControls &push_controls, const Grid< Device > &grid, const SimdVector &B, const SimdVector2D &gradpsi, const SimdGridWeights< Order::One, PhiInterpType::Planes > &grid_wts, SimdGyroWeights< GyroKin > &rho_wts, LocalFields &fld) const
Definition: field_aligned_local_fields.hpp:173
SimdPhase ph
Definition: particles.hpp:62
Simd< double > phi
Definition: simd.hpp:152
Definition: particles.hpp:61
Simd< double > z
Definition: simd.hpp:151
KOKKOS_INLINE_FUNCTION FieldAlignedLocalFields(const Grid< Device > &grid, const PushControls &push_controls, const Species< Device > &species, const MagneticField< Device > &magnetic_field, const GridFieldPack< Device, PhiInterpType::Planes > &gfpack, SimdParticles &part, SimdGridWeights< Order::One, PhiInterpType::Planes > &grid_wts)
Definition: field_aligned_local_fields.hpp:132
Simd< double > r
Definition: simd.hpp:140
Definition: field_aligned_local_fields.hpp:21
Definition: magnetic_field.F90:1
SimdVector E
Definition: field_aligned_local_fields.hpp:47
Definition: simd.hpp:139
SimdConstants ct
Definition: particles.hpp:63
KOKKOS_INLINE_FUNCTION void convert_mag_to_cyl(const SimdVector &B, const SimdVector2D &gradpsi, LocalFields &fld) const
Definition: field_aligned_local_fields.hpp:98
KOKKOS_INLINE_FUNCTION void fields_at_point(const PushControls &push_controls, const Grid< Device > &grid, const SimdVector &B, const SimdVector2D &gradpsi, const SimdGridWeights< Order::One, PIT_GLOBAL > &grid_wts, const SimdGyroWeights< PT > &rho_wts, LocalFields &fld) const
Definition: grid_field_pack.hpp:201
Definition: species.hpp:75
KOKKOS_INLINE_FUNCTION void get_grid_weights(const MagneticField< Device > &magnetic_field, const SimdVector &v, const Simd< double > &psi, SimdVector2D &xff, SimdGridWeights< Order::One, PIT > &grid_wts) const
Definition: grid.tpp:32
KOKKOS_INLINE_FUNCTION double magnitude(const int i_simd) const
Definition: simd.hpp:176
Simd< double > mu
Definition: particles.hpp:52
KOKKOS_INLINE_FUNCTION void fields_at_point(const GridFieldPack< Device, PIT > fields, const PushControls &push_controls, const Grid< Device > &grid, const SimdVector &B, const SimdVector2D &gradpsi, const SimdGridWeights< Order::One, PIT > &grid_wts, SimdGyroWeights< KT > &rho_wts, LocalFields &fld) const
Definition: field_aligned_local_fields.hpp:33
KOKKOS_INLINE_FUNCTION void deactivate(const Simd< bool > &mask)
Definition: particles.hpp:79