XGC1
get_potential_grad.hpp
Go to the documentation of this file.
1 #ifndef GET_POTENTIAL_GRAD
2 #define GET_POTENTIAL_GRAD
3 
4 #include "sml.hpp"
5 #include "grid.hpp"
7 #include "magnetic_field.hpp"
8 #include "my_mirror_view.hpp"
9 #include "gradparx2.hpp"
11 #include "gradient_matrices.hpp"
12 #include "gyro_avg_mat.hpp"
13 #include "task_group.hpp"
14 #include "grid_field.hpp"
15 #include "grid_deriv.hpp"
16 
17 // Fortran routines
18 
19 extern "C" void ptb_3db_replace_b_grad_phi(double* tmp);
20 
21 template<class Device>
23  View<double**,CLayout,Device> field;
24 
25  public:
26 
27  AlternatingStorage(const std::string& name, int nnode)
28  : field(NoInit(name), 2, nnode)
29  {}
30 
31  // Functions to access the "alternating" Views
32  View<double*,CLayout, Device> left(int i_plane){
33  int i_left_alt = i_plane%2;
34  return my_subview(field,i_left_alt);
35  }
36 
37  View<double*,CLayout, Device> right(int i_plane){
38  int i_right_alt = (i_plane+1)%2;
39  return my_subview(field,i_right_alt);
40  }
41 };
42 
43 template<class Device, class DeviceOut>
45 
46  int nnode;
47  int nrho;
48  int nphi;
49  int ndim;
50 
51  View<double**,CLayout,Device> input_potential;
55  View<double**,CLayout,Device> potential;
56  View<double***,CLayout, Device> gradient;
57  View<double****,CLayout, Device> gradient_rho;
58  View<double***,CLayout, Device> potential_rho;
59 
60  View<double*,CLayout,Device> scratch;
61 
62  // Additional objects that should go elsewhere eventually, but are here
63  // because they are needed for get_pot_grad and can be reused for the different fields
68 
69  GetPotentialGradTemp(const Simulation<DeviceType>& sml, const Grid<DeviceType>& grid, const DomainDecomposition<DeviceType>& pol_decomp, const MagneticField<DeviceType>& magnetic_field, const Boundary& boundary, int n_input_potential_planes, bool gradient_requested, bool gyroavg_requested, const GyroAverageMatrices<DeviceType>& gyro_avg_matrices_in = GyroAverageMatrices<DeviceType>())
70  : nnode(grid.nnode),
71  nrho(gyroavg_requested ? gyro_avg_matrices_in.nrho : 0),
72  nphi((PIT_GLOBAL==PhiInterpType::Planes) ? 2 : 1),
74  potential_alt("potential_alt", nnode),
75  gradient_r_alt("gradient_r_alt", gradient_requested ? nnode : 0),
76  gradient_z_alt("gradient_r_alt", gradient_requested ? nnode : 0),
77  potential(NoInit("potential"), nphi, nnode),
78  gradient(NoInit("gradient"), ndim, nphi, gradient_requested ? nnode : 0),
79  potential_rho(NoInit("potential_rho"), nrho+1, nphi, nnode),
80  gradient_rho(NoInit("gradient_rho"), nrho+1, nphi, gradient_requested ? nnode : 0, ndim),
81  gyro_avg_matrices(gyro_avg_matrices_in) // Send gyromatrices to GPU
82  {
83  // Use scratch for transpose on device if the fields can't be written directly
84  if(!std::is_same<DeviceOut,Device>()){
85  scratch = View<double*,CLayout,Device>(NoInit("scratch"), gradient_requested ? gradient_rho.size() : potential_rho.size() );
86  input_potential = View<double**,CLayout,Device>(NoInit("input_potential"), n_input_potential_planes, nnode);
87  }
88 
89  GPTLstart("GET_POT_GRAD_MAT_SETUP");
90  if(gradient_requested){
91 #ifdef NO_FORTRAN_MODULES
92  grad_matrices = grid.gradient_matrices_h.template mirror<DeviceType>();
93 #else
94  grad_matrices = GradientMatrices<DeviceType>(true); // Copy in fortran data
95 #endif
96  }
97  GPTLstop("GET_POT_GRAD_MAT_SETUP");
98 
99  // This could be set up only once (if it doesnt take up too much device memory)
100  GPTLstart("GET_POT_GRAD_FF_SETUP");
102  GPTLstop("GET_POT_GRAD_FF_SETUP");
103 
104  // Set up for parallel gradient
105  GPTLstart("GET_POT_GRAD_GPTX_SETUP");
106  if(gradient_requested && !sml.is_XGCa){
107  gptx = GradParXTmp(grid, boundary, magnetic_field.bt_sign);
108  }
109  GPTLstop("GET_POT_GRAD_GPTX_SETUP");
110  }
111 };
112 
113 template<class Device>
114 struct Field00{
117 
118  View<Field<VarType::Scalar,PhiInterpType::None>*,CLayout, Device> pot_managed; // Use if device != host
119  View<double*,CLayout, Device, Kokkos::MemoryTraits<Kokkos::Unmanaged>> pot;
120  View<double*,CLayout, Device> r;
121  View<double*,CLayout, Device> z;
122 
124  : is_provided(false)
125  {}
126 
127  template<class DeviceIn>
129  : r(NoInit("r"), field_in.f.extent(0)),
130  z(NoInit("z"), field_in.f.extent(0)),
131  is_provided(true),
132  discard_when_basis_is_one(discard_when_basis_is_one_in)
133  {
134  // Create a mirror if Device is different from the input DeviceIn
135  pot_managed = my_mirror_view(field_in.f, Device());
136  mirror_copy(pot_managed, field_in.f);
137  pot = View<double*,CLayout,Device, Kokkos::MemoryTraits<Kokkos::Unmanaged>>((double*)(pot_managed.data()), pot_managed.layout());
138  }
139 
140  void calculate_gradient(const Grid<DeviceType>& grid, const GradientMatrices<DeviceType>& grad_matrices){
141  grid_deriv(grad_matrices, grid,pot,r,z, discard_when_basis_is_one);
142 
143  auto r_tmp = r; // Use these to avoid using member function in kernel
144  auto z_tmp = z; // Use these to avoid using member function in kernel
145 
146  // rh This is general now --->
147  // We compute the electric field --> flip sign
148  // E=-E
149  Kokkos::parallel_for("get_pot_grad_flip_00", Kokkos::RangePolicy<ExSpace>(0,grid.nnode), KOKKOS_LAMBDA( const int i ){
150  r_tmp(i)=-r_tmp(i);
151  z_tmp(i)=-z_tmp(i);
152  });
153  }
154 
155  template<class DeviceOut, PhiInterpType PIT>
156  void set_field(const Grid<DeviceType>& grid, const FieldFollowingCoordinates& ff, View<Field<VarType::Vector2D,PIT>*,CLayout,DeviceOut>& field00_ff_h){
157  if (is_provided){
158  // Copy to two planes if field following is needed
159  int nphi = (PIT==PhiInterpType::Planes) ? 2 : 1;
160  View<double**,CLayout, Device> r_tmp(NoInit("r_tmp"), nphi, r.size());
161  View<double**,CLayout, Device> z_tmp(NoInit("z_tmp"), nphi, z.size());
162 
163  for(int iphi=0; iphi<nphi; iphi++){
164  Kokkos::deep_copy(my_subview(r_tmp, iphi), r);
165  Kokkos::deep_copy(my_subview(z_tmp, iphi), z);
166  }
167 
168  if(PIT==PhiInterpType::Planes){
169  ff.cnvt_grid_real2ff(grid,r_tmp);
170  ff.cnvt_grid_real2ff(grid,z_tmp);
171  }
172 
173  auto field00_ff = my_mirror_view(field00_ff_h, Device());
174  for(int iphi=0; iphi<nphi; iphi++){
175  Kokkos::parallel_for("set_field", Kokkos::RangePolicy<ExSpace>(0,field00_ff_h.extent(0)), KOKKOS_LAMBDA( const int i ){
176 #ifdef XGC1
177  field00_ff(i).V[iphi][0]=r_tmp(iphi,i);
178  field00_ff(i).V[iphi][1]=z_tmp(iphi,i);
179 #else
180  field00_ff(i).E[0]=r_tmp(iphi,i);
181  field00_ff(i).E[1]=z_tmp(iphi,i);
182 #endif
183  });
184  }
185  Kokkos::fence();
186  // Copy if not a mirror
187  mirror_copy(field00_ff_h, field00_ff);
188  }else{
189  Kokkos::parallel_for("set_field", Kokkos::RangePolicy<typename DeviceOut::execution_space>(0,field00_ff_h.extent(0)), KOKKOS_LAMBDA( const int i ){
190 #ifdef XGC1
191  field00_ff_h(i).V[0][0]=0.0;
192  field00_ff_h(i).V[0][1]=0.0;
193  field00_ff_h(i).V[1][0]=0.0;
194  field00_ff_h(i).V[1][1]=0.0;
195 #else
196  field00_ff_h(i).E[0]=0.0;
197  field00_ff_h(i).E[1]=0.0;
198 #endif
199  });
200  }
201  }
202 };
203 
204 template<class DeviceIn, class DeviceOut, VarType VT, PhiInterpType PIT, TorType TT, KinType KT>
206  View<double**,CLayout,DeviceIn, Kokkos::MemoryTraits<Kokkos::Unmanaged>> input_potential;
209  View<double**,CLayout, DeviceType> para_grad;
215 
216  // Constructor if passed an unmanaged view
217  GetPotGradFieldArgs(const View<double**,CLayout,DeviceIn, Kokkos::MemoryTraits<Kokkos::Unmanaged>>& input_potential_in, bool ignore_poloidal_dpot_in=false)
218  : input_potential(input_potential_in),
219  ignore_poloidal_dpot(ignore_poloidal_dpot_in),
223  {}
224 
225  // Constructor if passed a 1D managed view
226  GetPotGradFieldArgs(const View<double*,CLayout,DeviceIn>& input_potential_in, bool ignore_poloidal_dpot_in=false)
227  : input_potential(View<double**,CLayout,DeviceIn,Kokkos::MemoryTraits<Kokkos::Unmanaged>>((double*)(input_potential_in.data()), 1, input_potential_in.extent(0))),
228  ignore_poloidal_dpot(ignore_poloidal_dpot_in),
232  {}
233 
235  potential = potential_in;
236  potential_is_requested = true;
237  }
238 
240  gradient = gradient_in;
241  gradient_is_requested = true;
242  }
243 
244  void request_para_grad(const View<double**,CLayout, DeviceType>& para_grad_in){
245  para_grad = para_grad_in;
246  para_grad_is_requested = true;
247  }
248 };
249 
251 
252 template<class DeviceIn, class DeviceOut, VarType VT, PhiInterpType PIT, TorType TT, KinType KT>
254 
255 #endif
Definition: get_potential_grad.hpp:22
View< double *, CLayout, Device > left(int i_plane)
Definition: get_potential_grad.hpp:32
View< double *, CLayout, Device > right(int i_plane)
Definition: get_potential_grad.hpp:37
View< double **, CLayout, Device > field
Definition: get_potential_grad.hpp:23
AlternatingStorage(const std::string &name, int nnode)
Definition: get_potential_grad.hpp:27
Definition: boundary.hpp:83
Definition: field_following_coordinates.hpp:9
void cnvt_grid_real2ff(const Grid< DeviceType > &grid, const View< double **, CLayout, DeviceType > &input, const View< double **, Kokkos::LayoutRight, DeviceType > &output) const
Definition: field_following_coordinates.hpp:169
Projection< HostType > half_plane_ff
Definition: grid.hpp:194
int nnode
Number of grid nodes.
Definition: grid.hpp:174
Definition: magnetic_field.hpp:12
Definition: sml.hpp:9
static constexpr bool is_XGCa
Equivalent to the preprocessor flag for now.
Definition: sml.hpp:20
constexpr VarType vec2d_if_axisym()
VarType
Definition: field.hpp:11
void get_field_Ah_cv_ff(const Grid< DeviceType > &grid, const DomainDecomposition< DeviceType > &pol_decomp, const GridField< HostType, VarType::Scalar, PhiInterpType::None, TorType::MultiplePlanes, KinType::DriftKin > &Ah_cv_h, const GridField< HostType, VarType::Scalar, PhiInterpType::Planes, TorType::OnePlane, KinType::DriftKin > &Ah_cv_ff)
Definition: get_potential_grad.cpp:6
void get_field_grad(const Grid< DeviceType > &grid, GetPotGradFieldArgs< DeviceIn, DeviceOut, VT, PIT, TT, KT > &args, GetPotentialGradTemp< DeviceType, DeviceOut > &tmp)
Definition: get_potential_grad.cpp:389
void ptb_3db_replace_b_grad_phi(double *tmp)
constexpr PhiInterpType PIT_GLOBAL
Definition: globals.hpp:103
PhiInterpType
Definition: globals.hpp:95
void grid_deriv(const GradientMatrices< DeviceType > &gm, const Grid< DeviceType > &grid, const Kokkos::View< double *, Kokkos::LayoutRight, DeviceType > &qty, const Kokkos::View< double *, Kokkos::LayoutRight, DeviceType > &qty_deriv_x, const Kokkos::View< double *, Kokkos::LayoutRight, DeviceType > &qty_deriv_y, bool discard_when_basis_is_one)
Definition: grid_deriv.cpp:18
void mirror_copy(T1 &view_dest, const T2 &view_src)
Definition: my_mirror_view.hpp:122
View< T *, CLayout, Device > my_mirror_view(const View< T *, CLayout, Device > &view, Device nd)
Definition: my_mirror_view.hpp:14
Kokkos::View< T *, Kokkos::LayoutRight, Device > my_subview(const Kokkos::View< T ****, Kokkos::LayoutRight, Device > &view, int i, int j, int k)
Definition: my_subview.hpp:8
Definition: col_grid.cpp:127
void parallel_for(const std::string name, int n_ptl, Function func, Option option, HostAoSoA aosoa_h, DeviceAoSoA aosoa_d)
Definition: streamed_parallel_for.hpp:252
Definition: magnetic_field.F90:1
logical false
Definition: module.F90:102
logical true
Definition: module.F90:102
Kokkos::LayoutRight CLayout
Definition: space_settings.hpp:68
Kokkos::ViewAllocateWithoutInitializing NoInit
Definition: space_settings.hpp:69
Definition: get_potential_grad.hpp:114
void calculate_gradient(const Grid< DeviceType > &grid, const GradientMatrices< DeviceType > &grad_matrices)
Definition: get_potential_grad.hpp:140
Field00(const GridField< DeviceIn, VarType::Scalar, PhiInterpType::None, TorType::OnePlane, KinType::DriftKin > &field_in, bool discard_when_basis_is_one_in)
Definition: get_potential_grad.hpp:128
View< double *, CLayout, Device > r
Definition: get_potential_grad.hpp:120
bool discard_when_basis_is_one
Definition: get_potential_grad.hpp:116
void set_field(const Grid< DeviceType > &grid, const FieldFollowingCoordinates &ff, View< Field< VarType::Vector2D, PIT > *, CLayout, DeviceOut > &field00_ff_h)
Definition: get_potential_grad.hpp:156
View< double *, CLayout, Device, Kokkos::MemoryTraits< Kokkos::Unmanaged > > pot
Definition: get_potential_grad.hpp:119
bool is_provided
Definition: get_potential_grad.hpp:115
Field00()
Definition: get_potential_grad.hpp:123
View< double *, CLayout, Device > z
Definition: get_potential_grad.hpp:121
View< Field< VarType::Scalar, PhiInterpType::None > *, CLayout, Device > pot_managed
Definition: get_potential_grad.hpp:118
Definition: field.hpp:45
Definition: get_potential_grad.hpp:205
bool potential_is_requested
Definition: get_potential_grad.hpp:211
bool gradient_is_requested
Definition: get_potential_grad.hpp:212
void request_para_grad(const View< double **, CLayout, DeviceType > &para_grad_in)
Definition: get_potential_grad.hpp:244
void request_gradient(const GridField< DeviceOut, VT, PIT, TT, KT > &gradient_in)
Definition: get_potential_grad.hpp:239
bool ignore_poloidal_dpot
Definition: get_potential_grad.hpp:210
Field00< DeviceType > field00
Definition: get_potential_grad.hpp:214
GridField< DeviceOut, VarType::Scalar, PIT, TT, KT > potential
Definition: get_potential_grad.hpp:208
void request_potential(const GridField< DeviceOut, VarType::Scalar, PIT, TT, KT > &potential_in)
Definition: get_potential_grad.hpp:234
bool para_grad_is_requested
Definition: get_potential_grad.hpp:213
GridField< DeviceOut, VT, PIT, TT, KT > gradient
Definition: get_potential_grad.hpp:207
GetPotGradFieldArgs(const View< double **, CLayout, DeviceIn, Kokkos::MemoryTraits< Kokkos::Unmanaged >> &input_potential_in, bool ignore_poloidal_dpot_in=false)
Definition: get_potential_grad.hpp:217
View< double **, CLayout, DeviceType > para_grad
Definition: get_potential_grad.hpp:209
View< double **, CLayout, DeviceIn, Kokkos::MemoryTraits< Kokkos::Unmanaged > > input_potential
Definition: get_potential_grad.hpp:206
GetPotGradFieldArgs(const View< double *, CLayout, DeviceIn > &input_potential_in, bool ignore_poloidal_dpot_in=false)
Definition: get_potential_grad.hpp:226
Definition: get_potential_grad.hpp:44
int ndim
Definition: get_potential_grad.hpp:49
View< double ****, CLayout, Device > gradient_rho
Definition: get_potential_grad.hpp:57
AlternatingStorage< Device > potential_alt
Definition: get_potential_grad.hpp:52
GyroAverageMatrices< DeviceType > gyro_avg_matrices
Definition: get_potential_grad.hpp:64
int nnode
Definition: get_potential_grad.hpp:46
int nrho
Definition: get_potential_grad.hpp:47
GetPotentialGradTemp(const Simulation< DeviceType > &sml, const Grid< DeviceType > &grid, const DomainDecomposition< DeviceType > &pol_decomp, const MagneticField< DeviceType > &magnetic_field, const Boundary &boundary, int n_input_potential_planes, bool gradient_requested, bool gyroavg_requested, const GyroAverageMatrices< DeviceType > &gyro_avg_matrices_in=GyroAverageMatrices< DeviceType >())
Definition: get_potential_grad.hpp:69
GradParXTmp gptx
Definition: get_potential_grad.hpp:67
View< double **, CLayout, Device > potential
Definition: get_potential_grad.hpp:55
AlternatingStorage< Device > gradient_r_alt
Definition: get_potential_grad.hpp:53
FieldFollowingCoordinates ff
Definition: get_potential_grad.hpp:66
View< double *, CLayout, Device > scratch
Definition: get_potential_grad.hpp:60
View< double ***, CLayout, Device > potential_rho
Definition: get_potential_grad.hpp:58
int nphi
Definition: get_potential_grad.hpp:48
GradientMatrices< DeviceType > grad_matrices
Definition: get_potential_grad.hpp:65
AlternatingStorage< Device > gradient_z_alt
Definition: get_potential_grad.hpp:54
View< double ***, CLayout, Device > gradient
Definition: get_potential_grad.hpp:56
View< double **, CLayout, Device > input_potential
Definition: get_potential_grad.hpp:51
Definition: gradparx2.hpp:8
Definition: grid_field.hpp:22
static int GPTLstart(const char *name)
Definition: timer_macro.hpp:9
static int GPTLstop(const char *name)
Definition: timer_macro.hpp:10