XGCa
electric_field.hpp
Go to the documentation of this file.
1 #ifndef ELECTRIC_FIELD_HPP
2 #define ELECTRIC_FIELD_HPP
3 #include "space_settings.hpp"
4 #include "NamelistReader.hpp"
5 #include "grid.hpp"
6 #include "grid_field_pack.hpp"
7 #include "timer_macro.hpp"
8 #include "smoothing.hpp"
9 #include "get_potential_grad.hpp"
10 #include "plane_field_gatherer.hpp"
12 #ifdef SONIC_GK
13 #include "get_sonic_fields.hpp"
14 #endif
15 #include "perturbed_B_field.hpp"
16 #include "get_dAdt_guess.hpp"
17 
18 template<KinType KT, PhiInterpType PIT, MarkerType MT, MagneticFieldMode MFM>
20 
21 template<KinType KT> struct getGyroVecFldType;
22 template<> struct getGyroVecFldType<KinType::DriftKin>{ using t = EfieldType; };
23 template<> struct getGyroVecFldType<KinType::GyroKin>{ using t = EfieldGyroType; };
24 
25 template<KinType KT> struct getGyroScaFldType;
26 template<> struct getGyroScaFldType<KinType::DriftKin>{ using t = PotType; };
27 template<> struct getGyroScaFldType<KinType::GyroKin>{ using t = PotGyroType; };
28 
29 // XGC1
30 
32 template<KinType KT, MarkerType MT>
34  using t = Pack<Labeled<typename getGyroVecFldType<KT>::t, Label::E>,
40 };
41 
43 template<KinType KT, MarkerType MT>
45  using t = Pack<Labeled<typename getGyroVecFldType<KT>::t, Label::E>>;
46 };
47 
49 template<KinType KT>
51  using t = Pack<Labeled<typename getGyroVecFldType<KT>::t, Label::E>,
54 };
55 
56 // XGCA
57 template<KinType KT, MarkerType MT>
59 # ifdef SONIC_GK
60  using t = Pack<Labeled<Efield2DGyroType, Label::E>,
64 # else
65  using t = Pack<Labeled<Efield2DGyroType, Label::E>>;
66 # endif
67 };
68 
69 
70 // Fortran calls
73 
74 // Electric field class
75 template<class Device>
76 struct ElectricField {
77 
78  // Dimensions
79  int nnode;
80  int nphi;
81 
82  // Gyromatrix info (to be moved soon)
83  int nrho;
84 
85  // Optimization options
87 
88  // Field variables
89  bool turb_efield;
90  bool E00_efield;
92 
93  // Host Views
96 
97  //For EM
109 
112 //#ifdef XGC1
114 //#else
115 //# ifdef SONIC_GK
119 //# endif
120 //#endif
124  View<double***,CLayout, HostType> save_dpot0; // Used for adiabatic response
125  View<double***,CLayout, HostType> save_dpot; // Used for adiabatic response
126  View<double***,CLayout, HostType> dpotsave; // Used for split-weight scheme
127  View<double*,CLayout, HostType> dpot_es; // Used for a diagnostic
128 
129  View<double*,CLayout, HostType> pot0m;
130  View<double*,CLayout, HostType> pot00_1d;
131 
132  // Host View for the adjustable loop voltage current drive
134 
135  // Solver boundaries; These are (shallow) copies so that they aren't needed as arguments to get_potential_grid etc. Should be removed in refactor
138 
139  // Default constructor
141 
142  // Makes sense to use the Grid in the constructor here, but the Grid still copies from fortran so until that changes,
143  // it's simpler to not use it here so that ElectricField can be defined before the restart, which uses psn%As
144  ElectricField(NLReader::NamelistReader& nlr, const Grid<DeviceType>& grid, int nrho_in, bool es_reduced_deltaf_setup=false) : //Grid<HostTypeType>& grid) :
145  nnode(grid.nnode),
146  nphi(grid.nplanes),
147  nrho(nrho_in),
148  // Host Views
149 #ifdef XGC1
150  pot("pot",nphi,nrho,nnode),
151  E("E",nphi,nrho,nnode),
152  save_dpot("save_dpot", 2, 2, nnode), // View. dims: RK2, ff, nnode
153  save_dpot0("save_dpot0", 2, 2, nnode), // View. dims: RK2, ff, nnode
154  dpot_h("dpot_h",4,nnode), // -1:2 in fortran
155  dpot_ff_h("dpot_ff_h",nnode),
156  dpot_n0_h("dpot_n0_h",nnode),
157 #else
158  E("E",nrho, nnode),
159  dpot_h("dpot_h",1,nnode),
160 # ifdef SONIC_GK
161  dEr_B2("dEr_B2",nrho, nnode),
162  dEz_B2("dEz_B2",nrho, nnode),
163  du2_E("du2_E",nrho, nnode),
164 # endif
165  dpot_n0_h("dpot_n0_h",nnode),
166 #endif
167  pot0m("pot0m", nnode),
168  pot00_1d("pot00_1d", grid.psi00.n),
169  pot0_h("pot0_h",nnode),
170  loop_voltage_h("loop_voltage_h",nnode)
171  {
172  if(es_reduced_deltaf_setup){
175  dpotsave = View<double***,CLayout, HostType>("dpotsave", 2, 2, nnode); // View. dims: RK2, ff, nnode
176  }
177 
178  nlr.use_namelist("sml_param");
179  turb_efield = nlr.get<bool>("sml_turb_efield",true); // E-field calculated only with \f$<\phi>\f$ if .false.
180  // psn%dpot will still contain all (n=0,|m|>0) and (|n|>0,m) modes
181  E00_efield = nlr.get<bool>("sml_00_efield",true); // Flux-surface averaged potential not used for calculating the electric field if .false.
182  n0_m_efield = nlr.get<bool>("sml_0m_efield",true); // The axisymmetric potential variation \f$\langle \phi-\langle\phi\rangle\rangle_T\f$ is
183  // set to zero if .false.
184 
185 #ifdef EXPLICIT_EM
186  // Pass these (or sml) as arguments
187  bool em_mixed_variable = nlr.get<bool>("sml_em_mixed_variable",true);
188  bool em_control_variate = nlr.get<bool>("sml_em_control_variate",false);
189  int em_pullback_mode = nlr.get<int>("sml_em_pullback_mode",3);
190  std::string em_pullback_str = nlr.get<std::string>("sml_em_pullback_method","Electrostatic");
191  if(em_pullback_mode==4) em_pullback_str = "IdealMHD";
192  PullbackMethod em_pullback_method = (em_pullback_str=="Electrostatic" ? PullbackMethod::Electrostatic : PullbackMethod::IdealMHD);
193 
194  if (!em_mixed_variable)
195  exit_XGC("\nError: sml_em_mixed_variable is explicitly set to .false. which is incompatible with EXPLICIT_EM\n");
196 
197 
198  dpot_es = View<double*,CLayout, HostType>("dpot_es", nnode);
205 #endif
206 
207  nlr.use_namelist("performance_param", NLReader::NamelistReader::Optional);
208  calculate_phi_ff_on_device = nlr.get<bool>("calculate_phi_ff_on_device", false); // With this option, potential is communicated and the electric field is calculated on every MPI process. This means additional computation, but less communication. This tradeoff is probably beneficial on all current flagship platforms, but this has not been verified.
209 
210 #ifdef EXPLICIT_EM
211  if (em_control_variate){
214  }
215 
216  if (em_mixed_variable){
219  if (em_pullback_method==PullbackMethod::IdealMHD){
221  }
222  }
223 #endif
224 
225  // Set pointers in Fortran to rho arrays
226 #ifndef NO_FORTRAN_MODULES
227 #ifdef XGC1
228  set_rho_ff_pointers(nnode, dpot_h.data(), dpot_ff_h.data());
229 #else
230  set_rho_pointers(nnode, dpot_h.data());
231 #endif
232 #endif
233 
234  // Initialize loop voltage
235  nlr.use_namelist("src_param");
236  const double initial_loop_vol = nlr.get<double>("src_loop_voltage",0.0); // Initial value for loop voltage
237  // Positive loop voltage corresponds to an electron torque opposite to the toroidal
238  // direction (clockwise looking down on the torus, i.e. in negative Z-direction)
239 
240  for (int inode=0; inode<nnode; inode++){
241  loop_voltage_h(inode) = initial_loop_vol;
242  }
243  }
244 
245 
246  /**************************************************/
247  /************ Copy to GridFieldPack *************/
248  /**************************************************/
249  template<MarkerType MT, MagneticFieldMode MFM>
251 
252  // Set push type here for now
254  gfp_push_type gfpack(turb_efield);
255 
256  GPTLstart("GAT_FIELD_INFO");
257  if(pol_decomp.decompose_fields){
258  if(near_field){
259  // Gathering the "near field", defined as the field decomposition region that contains this rank's
260  // global domain decomposition
261  int local_pid = pol_decomp.field_decomp.find_domain_owner(pol_decomp.plane_index, grid.nplanes, pol_decomp.node_offset, grid.nnode);
262  gfpack.phi_offset = pol_decomp.field_decomp.all_first_plane(local_pid);
263  gfpack.node_offset = pol_decomp.field_decomp.all_first_node(local_pid);
264  }else{
265  gfpack.phi_offset = pol_decomp.field_decomp.first_plane;
266  gfpack.node_offset = pol_decomp.field_decomp.first_node;
267  }
268  }
269  PlaneFieldGatherer pfg(pol_decomp, grid, near_field);
270 
272  if(ddpotdt.f.size()>0) pfg.gather_phi_ff_on_device(ddpotdt.f, gfpack.template get<Label::ddpotdt>().f);
273  grid_field_copy(gfpack.template get<Label::E00>(), E00_ff_h); // No gather_phi needed due to axisymmetry
274  }
275 
277  // Allocate temporary views
278  GPTLstart("GET_POT_GRAD_ALLOC_VIEWS");
279  int n_input_field_planes = pot0_h.nphi();
280  bool gradient_requested = true;
281  bool gyroaverage_requested = false;
282  GetPotentialGradTemp<DeviceType, DeviceType> gpg_tmp(sml, grid, pol_decomp, magnetic_field, pbd0, n_input_field_planes, gradient_requested, gyroaverage_requested);
283  GPTLstop("GET_POT_GRAD_ALLOC_VIEWS");
284 
285  // Whether to ignore dpot
286  bool ignore_poloidal_dpot = !(turb_efield);
287  bool use_field00 = E00_efield;
288  bool potential_is_requested = false; // Not used in push
290  pfg.calculate_phi_ff_on_device(sml,grid, gpg_tmp, my_subview(dpot_h.f, 2), pot0_h, gfpack.template get<Label::E>(), unused_pot, potential_is_requested, use_field00, ignore_poloidal_dpot);
291  if constexpr(MFM==MagneticFieldMode::Electromagnetic){
293  pfg.calculate_phi_ff_on_device(sml,grid, gpg_tmp, my_subview(Ah_h.f, 2), pot0_em_h, gfpack.template get<Label::dAh>(), gfpack.template get<Label::Ah>());
294  if(As.f.size()>0) pfg.calculate_phi_ff_on_device(sml,grid, gpg_tmp, my_subview(As_h.f, 2), pot0_em_h, gfpack.template get<Label::dAs>(), gfpack.template get<Label::As>());
295  }
296  }else{
297  pfg.gather_phi_ff_on_device(E.f, gfpack.template get<Label::E>().f);
298  if constexpr(MFM==MagneticFieldMode::Electromagnetic){
299  pfg.gather_phi_ff_on_device(dAh.f, gfpack.template get<Label::dAh>().f);
300  pfg.gather_phi_ff_on_device(Ah.f, gfpack.template get<Label::Ah>().f);
301  if(dAs.f.size()>0) pfg.gather_phi_ff_on_device(dAs.f, gfpack.template get<Label::dAs>().f);
302  if(As.f.size()>0) pfg.gather_phi_ff_on_device(As.f, gfpack.template get<Label::As>().f);
303  }
304  }
305  if constexpr(MFM==MagneticFieldMode::Electromagnetic){
306  if(dAdt_guess.f.size()>0) pfg.gather_phi_ff_on_device(dAdt_guess.f, gfpack.template get<Label::dAdt_guess>().f);
307  }
308  GPTLstop("GAT_FIELD_INFO");
309 
311  // Copy axisymmetric loop voltage to temporary device-view
312  ScalarGridField loop_voltage("loop_voltage",loop_voltage_h.nnode());
313  Kokkos::deep_copy(loop_voltage.f,loop_voltage_h.f);
315  ff.cnvt_grid_real2ff(grid,loop_voltage,gfpack.loop_voltage);
316 
317  return std::make_unique<gfp_push_type>(gfpack);
318  }
319 
320  template<MarkerType MT, MagneticFieldMode MFM>
323  gfp_push_type gfpack(turb_efield);
324 
325  GPTLstart("Copy_rho_ff_fields_to_device");
326  grid_field_copy(gfpack.template get<Label::E>(), E);
327  if constexpr(MFM==MagneticFieldMode::Electromagnetic){
328  grid_field_copy(gfpack.template get<Label::dAs>(), dAs);
329  grid_field_copy(gfpack.template get<Label::dAh>(), dAh);
330  grid_field_copy(gfpack.template get<Label::As>(), As);
331  grid_field_copy(gfpack.template get<Label::Ah>(), Ah);
332  grid_field_copy(gfpack.template get<Label::dAdt_guess>(), dAdt_guess);
333  }
334  GPTLstop("Copy_rho_ff_fields_to_device");
335 
336  // Loop voltage is identical for gyrokinetic and drift-kinetic species,
337  // but different between XGC1 and XGCa
339  // Copy axisymmetric loop voltage to temporary device-view
340  ScalarGridField loop_voltage("loop_voltage",loop_voltage_h.nnode());
341  Kokkos::deep_copy(loop_voltage.f,loop_voltage_h.f);
343  ff.cnvt_grid_real2ff(grid,loop_voltage,gfpack.loop_voltage);
344 
345  return std::make_unique<gfp_push_type>(gfpack);
346  }
347 
348 #ifdef XGC1
349  // Resizes allocations for large arrays that have a phi dimension (i.e used for electron push)
350  GridFieldPackPtr copy_push_fields_to_device(KinType kintype_in, MarkerType markertype_in, const Simulation<DeviceType>& sml, const DomainDecomposition<DeviceType>& pol_decomp, const MagneticField<DeviceType>& magnetic_field, const Grid<DeviceType>& grid, bool near_field=false) const{
351  if(!sml.explicit_electromagnetic){
352  if(markertype_in==MarkerType::ReducedDeltaF){
353  if(kintype_in==DriftKin){
354  return copy_push_fields_to_device_drift_kin_XGC1<MarkerType::ReducedDeltaF, MagneticFieldMode::Electrostatic>(sml, pol_decomp, magnetic_field, grid, near_field);
355  }else{
356  return copy_push_fields_to_device_gyro_kin_XGC1<MarkerType::ReducedDeltaF, MagneticFieldMode::Electrostatic>(sml, pol_decomp, magnetic_field, grid, near_field);
357  }
358  }else{
359  if(kintype_in==DriftKin){
360  return copy_push_fields_to_device_drift_kin_XGC1<MarkerType::TotalF, MagneticFieldMode::Electrostatic>(sml, pol_decomp, magnetic_field, grid, near_field);
361  }else{
362  return copy_push_fields_to_device_gyro_kin_XGC1<MarkerType::TotalF, MagneticFieldMode::Electrostatic>(sml, pol_decomp, magnetic_field, grid, near_field);
363  }
364  }
365  }else{
366  if(markertype_in==MarkerType::ReducedDeltaF){
367  if(kintype_in==DriftKin){
368  return copy_push_fields_to_device_drift_kin_XGC1<MarkerType::ReducedDeltaF, MagneticFieldMode::Electromagnetic>(sml, pol_decomp, magnetic_field, grid, near_field);
369  }else{
370  return copy_push_fields_to_device_gyro_kin_XGC1<MarkerType::ReducedDeltaF, MagneticFieldMode::Electromagnetic>(sml, pol_decomp, magnetic_field, grid, near_field);
371  }
372  }else{
373  if(kintype_in==DriftKin){
374  return copy_push_fields_to_device_drift_kin_XGC1<MarkerType::TotalF, MagneticFieldMode::Electromagnetic>(sml, pol_decomp, magnetic_field, grid, near_field);
375  }else{
376  return copy_push_fields_to_device_gyro_kin_XGC1<MarkerType::TotalF, MagneticFieldMode::Electromagnetic>(sml, pol_decomp, magnetic_field, grid, near_field);
377  }
378  }
379  }
380  }
381 #else
382  // Resizes allocations for large arrays that have a phi dimension (i.e used for electron push)
383  GridFieldPackPtr copy_push_fields_to_device(KinType kintype_in, MarkerType markertype_in, const Simulation<DeviceType>& sml, const DomainDecomposition<DeviceType>& pol_decomp, const MagneticField<DeviceType>& magnetic_field, const Grid<DeviceType>& grid, bool near_field=false) const{
384  // Re-initialize new gridpack - deallocates whatever Views were already allocated
386  gfp_push_type gfpack(turb_efield);
387 
388  grid_field_copy(gfpack.template get<Label::E>(), E);
389 # ifdef SONIC_GK
390  grid_field_copy(gfpack.template get<Label::dEr_B2>, dEr_B2);
391  grid_field_copy(gfpack.template get<Label::dEz_B2>, dEz_B2);
392  grid_field_copy(gfpack.template get<Label::du2_E>, du2_E);
393 # endif
394  // Copy axisymmetric loop voltage to temporary device-view
395  ScalarGridField loop_voltage("loop_voltage",loop_voltage_h.nnode());
396  Kokkos::deep_copy(loop_voltage.f,loop_voltage_h.f);
397  grid_field_copy(gfpack.loop_voltage,loop_voltage);
398 
399  //grid_field_copy(gfpack.loop_voltage,loop_voltage_h);
400  return std::make_unique<gfp_push_type>(gfpack);
401  }
402 #endif
403 
414  GPTLstart("GET_AH_RHO_FF_EXCL_DESTR"); // Timer excludes the destructors which are non-negligible
415 
416  // Allocate temporary views
417  GPTLstart("GET_AH_RHO_FF_ALLOC_VIEWS");
418  int n_input_field_planes = Ah_h.nphi();
419  bool gradient_requested = false;
420  bool gyroaverage_requested = true;
421  species.gyro_avg_matrices.copy_to_device_if_not_resident();
422  GetPotentialGradTemp<DeviceType, HostType> tmp(sml, grid, pol_decomp, magnetic_field, pbd0, n_input_field_planes, gradient_requested, gyroaverage_requested, species.gyro_avg_matrices);
423  GPTLstop("GET_AH_RHO_FF_ALLOC_VIEWS");
424 
425  /****************************************/
426  // Calculation of the Hamiltonian vector potential A_h
427  /****************************************/
429  FieldArgs gpg_field_args(Ah_h.unmanaged());
430  gpg_field_args.request_potential(Ah);
431  get_field_grad(grid, gpg_field_args, tmp);
432 
433  GPTLstop("GET_AH_RHO_FF_EXCL_DESTR");
434 
435  species.gyro_avg_matrices.deallocate_device_matrices_if_not_resident();
436  }
437 
449  GPTLstart("GET_POT_GRAD_EXCL_DESTR"); // Timer excludes the destructors which are non-negligible
450 
451  // Allocate temporary views
452  GPTLstart("GET_POT_GRAD_ALLOC_VIEWS");
453  int n_input_field_planes = dpot_h.nphi();
454  bool gradient_requested = true;
455  bool gyroaverage_requested = true;
456  if(gyroaverage_requested) species.gyro_avg_matrices.copy_to_device_if_not_resident();
457  GetPotentialGradTemp<DeviceType, HostType> tmp(sml, grid, pol_decomp, magnetic_field, pbd0, n_input_field_planes, gradient_requested, gyroaverage_requested, species.gyro_avg_matrices);
458  GPTLstop("GET_POT_GRAD_ALLOC_VIEWS");
459 
460  /****************************************/
461  // Calculation of the electric potential E
462  /****************************************/
463  GPTLstart("GET_POT_GRAD_PHI");
464 
466  FieldArgs gpg_field_args(dpot_h.unmanaged(), !(turb_efield));
467 
468  // Set up E00
469  if(E00_efield){
470  gpg_field_args.field00 = Field00<DeviceType>(pot0_h, sml.grad_psitheta);
471  gpg_field_args.field00.calculate_gradient(grid, tmp.grad_matrices);
472  }
473  // Write results of E00
474  if(sml.reduced_deltaf && sml.electron_on) gpg_field_args.field00.set_field(grid, tmp.ff, E00_ff_h.f);
475 
476  // Request potential and/or gradient outputs
477  // XGC1 algorithm uses potential but XGCa doesnt
478  if(!sml.is_XGCa) gpg_field_args.request_potential(pot);
479  gpg_field_args.request_gradient(E);
480 
482  View<double**,CLayout, DeviceType> para_grad;
483  if(need_para_grad){
484  // dAdt_guess takes parallel gradient as an input, but E is already gyroaveraged and field following
485  // So save the simple parallel gradient here
486  para_grad = View<double**,CLayout, DeviceType>(NoInit("para_grad"), 2, grid.nnode);
487  gpg_field_args.request_para_grad(para_grad);
488  }
489 
490  // Get potentials
491  get_field_grad(grid, gpg_field_args, tmp);
492 
493  GPTLstop("GET_POT_GRAD_PHI");
494 
495  if(sml.explicit_electromagnetic){
496  GPTLstart("GET_EM_PARA");
498  get_dAdt_guess(sml, grid, pol_decomp, magnetic_field, smoothing, perturbed_B_field, tmp, para_grad, AbdH, dAdt_guess);
499  }
500  GPTLstop("GET_EM_PARA");
501 
502 
503  GPTLstart("GET_POT_GRAD_APAR");
504 
505  /****************************************/
506  // Calculation of the Hamiltonian vector potential A_h
507  /****************************************/
508  gpg_field_args = FieldArgs(Ah_h.unmanaged());
509  gpg_field_args.request_potential(Ah);
510  gpg_field_args.request_gradient(dAh);
511  get_field_grad(grid, gpg_field_args, tmp);
512 
513  /****************************************/
514  // Calculation of the symplectic vector potential A_s
515  /****************************************/
516  if (sml.em_mixed_variable){
517  gpg_field_args = FieldArgs(As_h.unmanaged());
518  gpg_field_args.request_potential(As);
519  gpg_field_args.request_gradient(dAs);
520  get_field_grad(grid, gpg_field_args, tmp);
521  }
522 
523  /****************************************/
524  // Calculation of the Hamiltonian vector potential A_h for the control-variate method
525  /****************************************/
526  if (sml.em_control_variate){
527  TIMER("GET_POT_APAR_CV",
528  get_field_Ah_cv_ff(grid, pol_decomp, Ah_cv_h, Ah_cv) );
529  }
530  GPTLstop("GET_POT_GRAD_APAR");
531  }
532 
533 #ifdef SONIC_GK
534  GPTLstart("GET_POT_GRAD_SONIC");
535  View<double*,CLayout,HostType> Er_B2_h("Er_B2_h",grid.nnode);
536  View<double*,CLayout,HostType> Ez_B2_h("Ez_B2_h",grid.nnode);
537  View<double*,CLayout,HostType> u2_E_h("u2_E_h",grid.nnode);
538 
539  TIMER("GET_POT_SONIC",
540  get_sonic_fields(grid, E, Er_B2_h, Ez_B2_h, u2_E_h) );
541 
542  gpg_field_args = FieldArgs(Er_B2_h);
543  gpg_field_args.request_gradient(dEr_B2);
544  get_field_grad(grid, gpg_field_args, tmp);
545 
546  gpg_field_args = FieldArgs(Ez_B2_h);
547  gpg_field_args.request_gradient(dEz_B2);
548  get_field_grad(grid, gpg_field_args, tmp);
549 
550  gpg_field_args = FieldArgs(u2_E_h);
551  gpg_field_args.request_gradient(du2_E);
552  get_field_grad(grid, gpg_field_args, tmp);
553 
554  GPTLstop("GET_POT_GRAD_SONIC");
555 #endif
556 
557  species.gyro_avg_matrices.deallocate_device_matrices_if_not_resident();
558 
559  GPTLstop("GET_POT_GRAD_EXCL_DESTR");
560  }
561 
563  nlr.use_namelist("sml_param");
564  int field_n_rho = nlr.get<int>("sml_grid_nrho", 6);
565 
566 #ifdef EXPLICIT_EM
567  int n_fields = 3 + 1; // E, dAs, dAh, + scalars As,Ah
568 #else
569  int n_fields = 1;
570 #endif
571  double host_field_GB_per_vertex = (53 + 8*grid.nplanes + 11*(field_n_rho + 1))*8*BYTES_TO_GB;
572  double cpu_memory_usage = grid.nnode*host_field_GB_per_vertex;
573 
574  double device_field_GB_per_vertex = std::max(n_fields*8*grid.nplanes, n_fields*8*(field_n_rho+1))*8*BYTES_TO_GB;
575  double gpu_memory_usage = grid.nnode*device_field_GB_per_vertex;
576 
577  MemoryPrediction memory_prediction{"Collisions", cpu_memory_usage, gpu_memory_usage};
578 
579  return memory_prediction;
580  }
581 };
582 
583 #endif
Definition: boundary.hpp:83
bool decompose_fields
Whether to decompose fields.
Definition: domain_decomposition.hpp:87
FieldDecomposition< Device > field_decomp
Definition: domain_decomposition.hpp:88
int plane_index
Offset of local plane.
Definition: domain_decomposition.hpp:84
int node_offset
Offset of first mesh node belonging to this MPI rank.
Definition: domain_decomposition.hpp:91
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 nplanes
Number of planes.
Definition: grid.hpp:175
int nnode
Number of grid nodes.
Definition: grid.hpp:174
Definition: magnetic_field.hpp:12
Definition: NamelistReader.hpp:193
T get(const string &param, const T default_val, int val_ind=0)
Definition: NamelistReader.hpp:386
void use_namelist(const string &namelist, Options required=Required)
Definition: NamelistReader.hpp:360
@ Optional
Definition: NamelistReader.hpp:287
Definition: perturbed_B_field.hpp:12
Definition: plane_field_gatherer.hpp:9
void calculate_phi_ff_on_device(const Simulation< DeviceType > &sml, const Grid< DeviceType > &grid, GetPotentialGradTemp< DeviceType, DeviceType > &tmp, const View< Field< VarType::Scalar, PhiInterpType::None > *, CLayout, HostType > &dpot_h, const GT0 &pot0_h, GT &phi_ff, GT2 &pot_phi_ff, bool potential_is_requested=true, bool use_field00=false, bool ignore_poloidal_dpot=false)
Definition: plane_field_gatherer.hpp:117
void gather_phi_ff_on_device(View< FT **, CLayout, HostType > &tmp, View< FT *, CLayout, HostType > &tmp_full, const T_h &rho_ff_h, View< FT **, CLayout, DeviceType > &phi_ff)
Definition: plane_field_gatherer.hpp:197
Definition: sml.hpp:9
bool reduced_deltaf
True if any species is reduced_deltaf. Will be removed.
Definition: sml.hpp:37
bool grad_psitheta
Definition: sml.hpp:89
static constexpr bool explicit_electromagnetic
Equivalent to the preprocessor flag for now.
Definition: sml.hpp:26
bool em_control_variate
Switch for use of control variate method.
Definition: sml.hpp:67
PullbackMethod em_pullback_method
Electrostatic: mixed-variable pullback with dA_s/dt=0,.
Definition: sml.hpp:68
static constexpr bool is_XGCa
Equivalent to the preprocessor flag for now.
Definition: sml.hpp:18
bool electron_on
Use kinetic electrons.
Definition: sml.hpp:55
bool em_mixed_variable
Switch for use of mixed-variable formulation.
Definition: sml.hpp:66
Definition: species.hpp:75
GyroAverageMatrices< Device > gyro_avg_matrices
Definition: species.hpp:151
constexpr double BYTES_TO_GB
Definition: constants.hpp:13
void set_rho_pointers(int n, Field< VarType::Scalar, PhiInterpType::None > *dpot)
void set_rho_ff_pointers(int n, Field< VarType::Scalar, PhiInterpType::None > *dpot, Field< VarType::Scalar, PhiInterpType::Planes > *dpot_ff)
void get_dAdt_guess(const Simulation< DeviceType > &sml, const Grid< DeviceType > &grid, const DomainDecomposition< DeviceType > &pol_decomp, const MagneticField< DeviceType > &magnetic_field, Smoothing &smoothing, const PerturbedBField< DeviceType > &perturbed_B_field, GetPotentialGradTemp< DeviceType, HostType > &tmp, const View< double **, CLayout, DeviceType > &field_para, const Boundary &filter_bndry, const GridField< HostType, VarType::Scalar, PhiInterpType::Planes, TorType::OnePlane, KinType::GyroKin > &dAdt_guess)
Definition: get_dAdt_guess.cpp:77
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 get_sonic_fields(const Grid< DeviceType > &grid, const GridField< HostType, vec2d_if_axisym< PIT_GLOBAL >(), PIT_GLOBAL, TorType::OnePlane, KinType::GyroKin > &E, View< double *, CLayout, HostType > &Er_B2_h, View< double *, CLayout, HostType > &Ez_B2_h, View< double *, CLayout, HostType > &u2_E_h)
void exit_XGC(std::string msg)
Definition: globals.hpp:37
PullbackMethod
Definition: globals.hpp:198
constexpr PhiInterpType PIT_GLOBAL
Definition: globals.hpp:105
KinType
Definition: globals.hpp:88
@ GyroKin
Definition: globals.hpp:90
@ DriftKin
Definition: globals.hpp:89
MarkerType
Definition: globals.hpp:110
PhiInterpType
Definition: globals.hpp:95
GridField< DeviceType, VarType::Scalar, PIT_GLOBAL, TorType::OnePlane, KinType::GyroKin > PotGyroType
Definition: grid_field.hpp:490
GridField< DeviceType, VarType::Vector, PhiInterpType::Planes, TorType::OnePlane, KinType::GyroKin > EfieldGyroType
Definition: grid_field.hpp:488
GridField< DeviceType, VarType::Scalar, PIT_GLOBAL, TorType::MultiplePlanes, KinType::DriftKin > PotType
Definition: grid_field.hpp:486
void grid_field_copy(T &dest, const T &src)
Definition: grid_field.hpp:496
GridField< DeviceType, VarType::Vector, PhiInterpType::Planes, TorType::MultiplePlanes, KinType::DriftKin > EfieldType
Definition: grid_field.hpp:484
std::unique_ptr< GridFieldPackGeneric > GridFieldPackPtr
Definition: grid_field_pack.hpp:21
@ dAdt_guess
@ loop_voltage
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: magnetic_field.F90:1
Kokkos::ViewAllocateWithoutInitializing NoInit
Definition: space_settings.hpp:69
Definition: electric_field.hpp:76
View< double ***, CLayout, HostType > save_dpot
Definition: electric_field.hpp:125
GridField< HostType, vec2d_if_axisym< PIT_GLOBAL >), PIT_GLOBAL, TorType::OnePlane, KinType::GyroKin > dAh
Definition: electric_field.hpp:100
View< double ***, CLayout, HostType > dpotsave
Definition: electric_field.hpp:126
GridField< HostType, VarType::Scalar, PhiInterpType::Planes, TorType::OnePlane, KinType::GyroKin > dAdt_guess
Definition: electric_field.hpp:108
GridFieldPackPtr copy_push_fields_to_device_drift_kin_XGC1(const Simulation< DeviceType > &sml, const DomainDecomposition< DeviceType > &pol_decomp, const MagneticField< DeviceType > &magnetic_field, const Grid< DeviceType > &grid, bool near_field=false) const
Definition: electric_field.hpp:250
GridField< HostType, VarType::Scalar, PhiInterpType::None, TorType::MultiplePlanes, KinType::DriftKin > dpot_h
Definition: electric_field.hpp:121
View< double *, CLayout, HostType > pot0m
n=0 component of the electrostatic potential before smoothing
Definition: electric_field.hpp:129
void get_potential_grad(const Simulation< DeviceType > &sml, const Grid< DeviceType > &grid, const DomainDecomposition< DeviceType > &pol_decomp, const MagneticField< DeviceType > &magnetic_field, Smoothing &smoothing, const PerturbedBField< DeviceType > &perturbed_B_field, Species< DeviceType > &species)
Definition: electric_field.hpp:448
GridField< HostType, VarType::Vector2D, PIT_GLOBAL, TorType::OnePlane, KinType::DriftKin > E00_ff_h
Radial electric field from in field-following format.
Definition: electric_field.hpp:94
GridField< HostType, vec2d_if_axisym< PIT_GLOBAL >), PIT_GLOBAL, TorType::OnePlane, KinType::GyroKin > dAs
Definition: electric_field.hpp:104
Boundary AbdH
Definition: electric_field.hpp:136
GridField< HostType, VarType::Vector2D, PIT_GLOBAL, TorType::OnePlane, KinType::GyroKin > dEr_B2
Gradient of Er/B^2.
Definition: electric_field.hpp:116
GridField< HostType, VarType::Scalar, PIT_GLOBAL, TorType::OnePlane, KinType::GyroKin > Ah
Definition: electric_field.hpp:101
View< double *, CLayout, HostType > dpot_es
Definition: electric_field.hpp:127
int nnode
Definition: electric_field.hpp:79
GridField< HostType, VarType::Scalar, PhiInterpType::None, TorType::MultiplePlanes, KinType::DriftKin > As_h_backup
Definition: electric_field.hpp:103
GridField< HostType, VarType::Scalar, PIT_GLOBAL, TorType::OnePlane, KinType::GyroKin > As
Definition: electric_field.hpp:105
View< double *, CLayout, HostType > pot00_1d
1D flux-surface averaged potential
Definition: electric_field.hpp:130
ElectricField(NLReader::NamelistReader &nlr, const Grid< DeviceType > &grid, int nrho_in, bool es_reduced_deltaf_setup=false)
Definition: electric_field.hpp:144
GridField< HostType, VarType::Scalar, PhiInterpType::None, TorType::OnePlane, KinType::DriftKin > dpot_n0_h
Definition: electric_field.hpp:123
GridFieldPackPtr copy_push_fields_to_device(KinType kintype_in, MarkerType markertype_in, const Simulation< DeviceType > &sml, const DomainDecomposition< DeviceType > &pol_decomp, const MagneticField< DeviceType > &magnetic_field, const Grid< DeviceType > &grid, bool near_field=false) const
Definition: electric_field.hpp:383
bool turb_efield
E-field calculated only with if .false., psndpot will still contain all (n=0,|m|>0) and (|n|>0,...
Definition: electric_field.hpp:89
GridField< HostType, VarType::Scalar, PhiInterpType::None, TorType::MultiplePlanes, KinType::DriftKin > As_h
Definition: electric_field.hpp:102
GridField< HostType, VarType::Vector2D, PIT_GLOBAL, TorType::OnePlane, KinType::GyroKin > du2_E
Gradient of the square (dot product) of the E x B drift.
Definition: electric_field.hpp:118
bool E00_efield
Flux-surface averaged potential not used for calculating the electric field if .false.
Definition: electric_field.hpp:90
Boundary pbd0
Definition: electric_field.hpp:137
int nrho
Definition: electric_field.hpp:83
GridField< HostType, VarType::Vector2D, PIT_GLOBAL, TorType::OnePlane, KinType::GyroKin > dEz_B2
Gradient of Ez/B^2.
Definition: electric_field.hpp:117
void get_Ah_rho_ff(const Simulation< DeviceType > &sml, const Grid< DeviceType > &grid, const DomainDecomposition< DeviceType > &pol_decomp, const MagneticField< DeviceType > &magnetic_field, Species< DeviceType > &species)
Definition: electric_field.hpp:413
ElectricField()
Definition: electric_field.hpp:140
GridField< HostType, VarType::Scalar, PhiInterpType::None, TorType::MultiplePlanes, KinType::DriftKin > Ah_h
Definition: electric_field.hpp:98
GridField< HostType, VarType::Scalar, PIT_GLOBAL, TorType::OnePlane, KinType::GyroKin > pot
Definition: electric_field.hpp:110
GridField< HostType, VarType::Scalar, PhiInterpType::Planes, TorType::OnePlane, KinType::DriftKin > ddpotdt
Time derivative of - Not field-following?
Definition: electric_field.hpp:95
GridField< HostType, vec2d_if_axisym< PIT_GLOBAL >), PIT_GLOBAL, TorType::OnePlane, KinType::GyroKin > E
Definition: electric_field.hpp:111
GridField< HostType, VarType::Scalar, PhiInterpType::None, TorType::MultiplePlanes, KinType::DriftKin > Ah_cv_h
Definition: electric_field.hpp:106
GridField< HostType, VarType::Scalar, PhiInterpType::Planes, TorType::OnePlane, KinType::DriftKin > Ah_cv
Definition: electric_field.hpp:107
bool calculate_phi_ff_on_device
Definition: electric_field.hpp:86
GridField< HostType, VarType::Scalar, PhiInterpType::None, TorType::OnePlane, KinType::DriftKin > Ah_h_backup
Definition: electric_field.hpp:99
GridField< HostType, VarType::Scalar, PhiInterpType::Planes, TorType::OnePlane, KinType::DriftKin > dpot_ff_h
Definition: electric_field.hpp:113
GridField< HostType, VarType::Scalar, PhiInterpType::None, TorType::OnePlane, KinType::DriftKin > pot0_h
Definition: electric_field.hpp:122
View< double ***, CLayout, HostType > save_dpot0
Definition: electric_field.hpp:124
GridFieldPackPtr copy_push_fields_to_device_gyro_kin_XGC1(const Simulation< DeviceType > &sml, const DomainDecomposition< DeviceType > &pol_decomp, const MagneticField< DeviceType > &magnetic_field, const Grid< DeviceType > &grid, bool near_field=false) const
Definition: electric_field.hpp:321
bool n0_m_efield
Definition: electric_field.hpp:91
int nphi
Definition: electric_field.hpp:80
static MemoryPrediction estimate_memory_usage(NLReader::NamelistReader &nlr, const Grid< DeviceType > &grid)
Definition: electric_field.hpp:562
GridField< HostType, VarType::Scalar, PhiInterpType::None, TorType::OnePlane, KinType::DriftKin > loop_voltage_h
Definition: electric_field.hpp:133
Definition: get_potential_grad.hpp:205
Definition: get_potential_grad.hpp:44
FieldFollowingCoordinates ff
Definition: get_potential_grad.hpp:66
GradientMatrices< DeviceType > grad_matrices
Definition: get_potential_grad.hpp:65
Definition: grid_field_pack.hpp:24
Definition: grid_field.hpp:22
Definition: label.hpp:44
Definition: memory_prediction.hpp:4
Definition: smoothing.hpp:10
Definition: electric_field.hpp:25
Definition: electric_field.hpp:21
Pack< Labeled< Efield2DGyroType, Label::E > > t
Definition: electric_field.hpp:65
Pack< Labeled< typename getGyroVecFldType< KT >::t, Label::E >, Labeled< typename getGyroVecFldType< KT >::t, Label::dAh >, Labeled< typename getGyroVecFldType< KT >::t, Label::dAs >, Labeled< typename getGyroScaFldType< KT >::t, Label::Ah >, Labeled< typename getGyroScaFldType< KT >::t, Label::As >, Labeled< typename getGyroScaFldType< KT >::t, Label::dAdt_guess > > t
Definition: electric_field.hpp:39
Pack< Labeled< typename getGyroVecFldType< KT >::t, Label::E > > t
Definition: electric_field.hpp:45
Pack< Labeled< typename getGyroVecFldType< KT >::t, Label::E >, Labeled< E00Type, Label::E00 >, Labeled< PotType, Label::ddpotdt > > t
Definition: electric_field.hpp:53
Definition: electric_field.hpp:19
#define TIMER(N, F)
Definition: timer_macro.hpp:24
static int GPTLstart(const char *name)
Definition: timer_macro.hpp:9
static int GPTLstop(const char *name)
Definition: timer_macro.hpp:10