XGCa
col_species.hpp
Go to the documentation of this file.
1 #ifndef COL_SPECIES_HPP
2 #define COL_SPECIES_HPP
3 
4 #include <vector>
5 #include <Kokkos_Core.hpp>
6 #include <Kokkos_DualView.hpp>
7 
8 #include "vgrid_distribution.hpp"
9 #include "moments.hpp"
10 
11 struct MomentSet {
12  double n; // Density
13  double w; // Energy
14  double p; // Momentum
15 
16  KOKKOS_INLINE_FUNCTION constexpr MomentSet() : n(0.0), w(0.0), p(0.0) {}
17  //KOKKOS_INLINE_FUNCTION MomentSet(){}
18  KOKKOS_INLINE_FUNCTION MomentSet(double n_in, double w_in, double p_in) : n(n_in), w(w_in), p(p_in) {}
19 
20  // Join operation
21  KOKKOS_INLINE_FUNCTION void operator+=(const MomentSet& other) {
22  n += other.n;
23  w += other.w;
24  p += other.p;
25  }
26 };
27 
28 /*struct Triple {
29  double a;
30  double b;
31  double c;
32 
33  KOKKOS_INLINE_FUNCTION Triple() : a(0.0), b(0.0), c(0.0) {}
34 
35  // Join operation
36  KOKKOS_INLINE_FUNCTION void operator+=(const Triple& other) {
37  a += other.a;
38  b += other.b;
39  c += other.c;
40  }
41 };*/
42 
44  int gid; // Corresponding XGC species
45  bool is_electron; // Whether species is electron
46  double T_avg;
47  double mass;
48  double charge_eu;
50 
51  //> Computes the base collision frequency -- Eq. (6) in Hager et al.
52  KOKKOS_INLINE_FUNCTION double lambda_gamma_pair(const CollisionSpeciesScalars& sp_b ) const {// C(a->b)
53  double lambda;
54  // NRL Plasma Formulary 2011 version, p.34
55  //(c) Mixed ion-ion collisions (here, same species ion-ion collisions)
56  if(is_electron || sp_b.is_electron){
57  //if electron is invovled
58  if(is_electron && sp_b.is_electron){
59  //(a) Thermal electron-electron collisions
60  // Note that pointers for colliding and target are same.
61  lambda = 2.35e1 - log( sqrt(den_lambda_gamma*1e-6)*pow(T_avg,-1.25))
62  - sqrt(std::abs(1e-5 + pow(log(T_avg)-2,2)/16));
63  } else {
64  double ti_ev,massi,densi,chargei,te_ev,masse,dense;
65  if(is_electron){
66  ti_ev = sp_b.T_avg;
67  massi = sp_b.mass;
68  densi = sp_b.den_lambda_gamma;
69  chargei = sp_b.charge_eu;
70  te_ev = T_avg;
71  masse = mass;
72  dense = den_lambda_gamma;
73  } else {
74  te_ev = sp_b.T_avg;
75  masse = sp_b.mass;
76  dense = sp_b.den_lambda_gamma;
77  ti_ev = T_avg;
78  massi = mass;
79  densi = den_lambda_gamma;
80  chargei = charge_eu;
81  }
82  //(b) Electron-ion (and ion-electron) collisions
83  if(ti_ev*masse/massi<te_ev){
84  if(te_ev<1e1*(chargei*chargei)){
85  lambda = 2.3e1 - log(chargei*sqrt(dense*1e-6/(te_ev*te_ev*te_ev)));
86  } else {
87  lambda = 2.4e1 - log(sqrt(dense*1e-6)/te_ev);
88  }
89  } else {
90  lambda = 3e1-log((chargei*chargei)*sqrt(densi*1e-6/(ti_ev*ti_ev*ti_ev))*PROTON_MASS/massi);
91  }
92  }
93  } else {
94  lambda = 2.3e1 - log(charge_eu*sp_b.charge_eu*(mass+sp_b.mass)
95  /(mass*sp_b.T_avg+sp_b.mass*T_avg)
97  +sp_b.den_lambda_gamma*1e-6*(sp_b.charge_eu*sp_b.charge_eu)/sp_b.T_avg));
98  }
99  double tmp = lambda*(charge_eu*charge_eu)*(sp_b.charge_eu*sp_b.charge_eu)*pow(UNIT_CHARGE,4)/(pow(8.8542e-12,2)*8*PI);
100  return tmp/mass; // colliding : a, target : b
101  }
102 };
103 
104 template<class Device>
106  public:
108 
109  Kokkos::DualView<CollisionSpeciesScalars**,Device> s;
110 
111  // Things moved out of CollisionSpeciesScalars
112  View<int*, CLayout, DeviceType> grid_index_d; // Which grid this species is on
113  View<int*, CLayout, HostType> grid_index_h;
114  View<MomentSet**, CLayout, HostType> moments; // Set of moments used internally; note this is a different calculation from den_moment and temp_moment passed in!
115  View<double**, CLayout, HostType> conv_factor;
116 
117  View<int*,CLayout,HostType> moments_index; // Index mapping to moments
118 
119  View<double**, CLayout, HostType> den_moment; // Density moments, shallow copy of moments.den_local
120  View<double**, CLayout, HostType> temp_moment; // Temperature moments, shallow copy of moments.temp_local
121 
122  View<double*,CLayout,DeviceType> inv_mass_d; // Inverse mass of each species
123  std::vector<View<double*,CLayout,HostType>> fg_temp_ev_all; // Vector of views
124 
125  View<double****,CLayout,HostType> pdf_h; // Input distribution (batched)
126  View<double****,CLayout,Device> pdf; // Input distribution (device, batched).
127  View<double****,CLayout,HostType> pdf1_h; // Updated distribution (batched)
128  View<double****,CLayout,Device> pdf1; // Updated distribution (device, batched)
129 
131 
132  CollisionSpecies<Device>(const Moments& moments_in, const VGridDistribution<DeviceType>& f_in, const std::vector<Species<Device>> &all_species, int mb_n_nodes)
133  : f(f_in.n_species(), f_in, VGridDistributionOption::NoViewInit),
134  s("s", f.n_species(), mb_n_nodes),
135  grid_index_d("grid_index_d", f.n_species()),
136  grid_index_h("grid_index_h", f.n_species()),
137  moments(NoInit("moments"), f.n_species(), mb_n_nodes), // note - unrelated to moments_in !!
138  conv_factor(NoInit("conv_factor"), f.n_species(), mb_n_nodes),
139  moments_index("moments_index", f.n_species()),
140  den_moment(moments_in.den_local),
141  temp_moment(moments_in.temp_local),
142  inv_mass_d("inv_mass_d", f.n_species()),
143  pdf("pdf", mb_n_nodes, f.n_species(), f.n_vz(), f.n_vr()),
144  pdf1("pdf1", mb_n_nodes, f.n_species(), f.n_vz(), f.n_vr()) // WARNING: count_negatives assumes this index order!!
145  {
146  // Copy distribution
147  Kokkos::deep_copy(f.f, f_in.f);
148 
149  std::vector<double> inv_mass;
150  int col_species_cnt=0;
151  for (int isp = 0; isp<all_species.size(); isp++){
152  if (!all_species[isp].is_adiabatic){
153  for (int mesh_ind = 0; mesh_ind<mb_n_nodes; mesh_ind++){
154  s.h_view(col_species_cnt, mesh_ind).gid = isp;
155  s.h_view(col_species_cnt, mesh_ind).is_electron = all_species[isp].is_electron;
156  s.h_view(col_species_cnt,mesh_ind).mass = all_species[isp].mass;
157  s.h_view(col_species_cnt,mesh_ind).charge_eu = all_species[isp].charge/UNIT_CHARGE;
158  }
159  grid_index_h(col_species_cnt) = all_species[isp].collision_grid_index;
160  moments_index(col_species_cnt) = all_species[isp].nonadiabatic_idx;
161 
162  // This is a vector of Views, adding the species one at a time
163  inv_mass.push_back(1.0/all_species[isp].mass);
164  fg_temp_ev_all.push_back(all_species[isp].f0.fg_temp_ev_h);
165 
166  col_species_cnt++;
167  }
168  }
169 
170  Kokkos::deep_copy(grid_index_d, grid_index_h);
171  array_deep_copy(inv_mass_d, inv_mass.data());
172 
173 #ifdef USE_GPU
174  pdf_h = View<double****,CLayout,HostType>("pdf_h",pdf.layout());
175  pdf1_h = View<double****,CLayout,HostType>("pdf1_h",pdf1.layout());
176 #else
177  pdf_h = pdf;
178  pdf1_h = pdf1;
179 #endif
180  }
181 
182  // Copy col_spall_in scalar data, but resized to nnode_in
183  CollisionSpecies<Device>(const CollisionSpecies<Device>& col_spall_in, int nnode_in)
184  : f(col_spall_in.f.n_species(), nnode_in, col_spall_in.f, VGridDistributionOption::NoViewInit),
185  s(col_spall_in.s), // SHALLOW COPY
186  grid_index_d(col_spall_in.grid_index_d), // SHALLOW COPY
187  grid_index_h(col_spall_in.grid_index_h), // SHALLOW COPY
188  moments_index(col_spall_in.moments_index), // SHALLOW COPY
189  moments(NoInit("moments"), f.n_species(), col_spall_in.pdf.extent(0)), // note - unrelated to moments_in !!
190  conv_factor(NoInit("conv_factor"), f.n_species(), col_spall_in.pdf.extent(0)),
191  den_moment(NoInit("den_moment"), nnode_in, f.n_species()),
192  temp_moment(NoInit("temp_moment"), nnode_in, f.n_species()),
193  inv_mass_d(col_spall_in.inv_mass_d), // SHALLOW COPY
194  pdf("pdf", col_spall_in.pdf.extent(0), f.n_species(), f.n_vz(), f.n_vr()),
195  pdf1("pdf1", col_spall_in.pdf1.extent(0), f.n_species(), f.n_vz(), f.n_vr())
196  {
197  for(int i=0; i<f.n_species(); i++){
198  // This is a vector of Views, adding the species one at a time
199  fg_temp_ev_all.push_back(View<double*,CLayout,HostType>(NoInit("fg_temp_ev"), nnode_in));
200  }
201 
202 #ifdef USE_GPU
203  pdf_h = View<double****,CLayout,HostType>("pdf_h",pdf.layout());
204  pdf1_h = View<double****,CLayout,HostType>("pdf1_h",pdf1.layout());
205 #else
206  pdf_h = pdf;
207  pdf1_h = pdf1;
208 #endif
209  }
210 
211  //> Convert the distribution function to the units used
212  // internally by the collision operator
213  // The distribution function set up with f0_module is in normalized velocity space
214  // whereas the collision operator uses SI units.
215  void setup_one(int isp, int mesh_ind, int local_node_ind) const{
216 
217  double conv_inv_mass=TWOPI*UNIT_CHARGE/s.h_view(isp,mesh_ind).mass;
218  int moment_isp = moments_index(isp);
219  s.h_view(isp,mesh_ind).den_lambda_gamma = den_moment(local_node_ind, moment_isp);
220  s.h_view(isp,mesh_ind).T_avg = temp_moment(local_node_ind, moment_isp);
221 
222 
223  double conv_fac_temp = fg_temp_ev_all[moment_isp](local_node_ind);
224  conv_factor(isp,mesh_ind) = sqrt(conv_fac_temp*(conv_inv_mass*conv_inv_mass*conv_inv_mass));
225  double inv_conv_factor = 1.0/conv_factor(isp,mesh_ind);
226 
227  // Set up distribution
228  for (int imu = 0; imu < pdf_h.extent(3); imu++){
229  double vnorm_to_SI = inv_conv_factor/f.get_smu_n(imu);
230  for (int ivp = 0; ivp<pdf_h.extent(2); ivp++){
231  double& var = pdf_h(mesh_ind,isp,ivp,imu);
232 
233  // Set to assigned f - involves transpose, hence why this can't just be a copy
234  var = f(moment_isp, imu,local_node_ind,ivp);
235 
236  // Cut off all negative values
237  var = std::max(var,0.0);
238 
239  // Convert to SI
240  var *= vnorm_to_SI;
241  }
242  }
243  }
244 
245  void setup_all(Kokkos::View<int*,HostType>& mesh_nodes, int mb_n_nodes) const{
246  Kokkos::parallel_for("col_sp_setup", Kokkos::RangePolicy<HostExSpace>( 0, mb_n_nodes ), [=] (const int mesh_ind){
247  for (int isp = 0; isp < s.extent(0); isp++){
248  setup_one(isp, mesh_ind, mesh_nodes(mesh_ind));
249  }
250  });
251 
252 #ifdef USE_GPU
253  // Copy dual views to device
254  Kokkos::deep_copy(s.d_view, s.h_view);
255  Kokkos::deep_copy(pdf, pdf_h);
256 #endif
257  }
258 
259  void lambda_gamma_pair(const View<double*,CLayout,HostType>& dt, Kokkos::View<double***,Device>& gammac, int mb_n_nodes) const{
260  // Done on host, so create a mirror
261  //typename Kokkos::View<double***,Device>::HostMirror
262  auto gammac_h = Kokkos::create_mirror_view(gammac);
263 
264  for (int mesh_ind = 0; mesh_ind<mb_n_nodes; mesh_ind++){
265  // gamma
266  for (int isp = 0; isp < s.extent(0); isp++){
267  for (int jsp = 0; jsp < s.extent(0); jsp++){
268  gammac_h(mesh_ind,jsp,isp) = dt(mesh_ind)*s.h_view(isp,mesh_ind).lambda_gamma_pair(s.h_view(jsp,mesh_ind));
269  }
270  }
271  }
272  Kokkos::deep_copy(gammac, gammac_h);
273  }
274 
275  inline int n() const{
276  return f.n_species();
277  }
278 };
279 
280 #endif
void array_deep_copy(T *array, const Kokkos::View< T *, Kokkos::LayoutRight, Device > &view)
Definition: array_deep_copy.hpp:11
Definition: col_species.hpp:105
void setup_one(int isp, int mesh_ind, int local_node_ind) const
Definition: col_species.hpp:215
void lambda_gamma_pair(const View< double *, CLayout, HostType > &dt, Kokkos::View< double ***, Device > &gammac, int mb_n_nodes) const
Definition: col_species.hpp:259
void setup_all(Kokkos::View< int *, HostType > &mesh_nodes, int mb_n_nodes) const
Definition: col_species.hpp:245
View< double **, CLayout, HostType > den_moment
Definition: col_species.hpp:119
View< double ****, CLayout, HostType > pdf_h
Definition: col_species.hpp:125
View< double *, CLayout, DeviceType > inv_mass_d
Definition: col_species.hpp:122
View< int *, CLayout, DeviceType > grid_index_d
Definition: col_species.hpp:112
int n() const
Definition: col_species.hpp:275
View< double ****, CLayout, Device > pdf
Definition: col_species.hpp:126
View< MomentSet **, CLayout, HostType > moments
Definition: col_species.hpp:114
View< double **, CLayout, HostType > conv_factor
Definition: col_species.hpp:115
View< int *, CLayout, HostType > moments_index
Definition: col_species.hpp:117
View< double ****, CLayout, Device > pdf1
Definition: col_species.hpp:128
View< double ****, CLayout, HostType > pdf1_h
Definition: col_species.hpp:127
View< double **, CLayout, HostType > temp_moment
Definition: col_species.hpp:120
View< int *, CLayout, HostType > grid_index_h
Definition: col_species.hpp:113
const VGridDistribution< HostType > f
Definition: col_species.hpp:107
std::vector< View< double *, CLayout, HostType > > fg_temp_ev_all
Definition: col_species.hpp:123
Kokkos::DualView< CollisionSpeciesScalars **, Device > s
Definition: col_species.hpp:109
Definition: species.hpp:75
KOKKOS_INLINE_FUNCTION int n_species() const
Definition: vgrid_distribution.hpp:187
double get_smu_n(int imu) const
Definition: vgrid_distribution.hpp:208
View< double ****, CLayout, Device > f
Definition: vgrid_distribution.hpp:23
constexpr double PI
Definition: constants.hpp:9
constexpr double UNIT_CHARGE
Charge of an electron (C)
Definition: constants.hpp:4
constexpr double TWOPI
Definition: constants.hpp:10
constexpr double PROTON_MASS
Definition: constants.hpp:7
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
real(kind=8), dimension(:,:), pointer den_local
density, local to compute node [Nsp,Nlocalnode]
Definition: mom_module.F90:4
real(kind=8), dimension(:,:), pointer temp_local
temperature, , local to compute node [Nsp,Nlocalnode]
Definition: mom_module.F90:7
Kokkos::ViewAllocateWithoutInitializing NoInit
Definition: space_settings.hpp:69
Definition: col_species.hpp:43
double charge_eu
Definition: col_species.hpp:48
KOKKOS_INLINE_FUNCTION double lambda_gamma_pair(const CollisionSpeciesScalars &sp_b) const
Definition: col_species.hpp:52
double den_lambda_gamma
Definition: col_species.hpp:49
int gid
Definition: col_species.hpp:44
double mass
Definition: col_species.hpp:47
double T_avg
Definition: col_species.hpp:46
bool is_electron
Definition: col_species.hpp:45
Definition: col_species.hpp:11
constexpr KOKKOS_INLINE_FUNCTION MomentSet()
Definition: col_species.hpp:16
double p
Definition: col_species.hpp:14
double w
Definition: col_species.hpp:13
KOKKOS_INLINE_FUNCTION MomentSet(double n_in, double w_in, double p_in)
Definition: col_species.hpp:18
double n
Definition: col_species.hpp:12
KOKKOS_INLINE_FUNCTION void operator+=(const MomentSet &other)
Definition: col_species.hpp:21
Definition: moments.hpp:9
VGridDistributionOption
Definition: vgrid_distribution.hpp:12