XGC1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
field_following_coordinates.hpp
Go to the documentation of this file.
1 #ifndef FIELD_FOLLOWING_COORDINATES_HPP
2 #define FIELD_FOLLOWING_COORDINATES_HPP
3 
4 #include "my_subview.hpp"
5 #include "grid.hpp"
6 #include "grid_field.hpp"
7 
8 
10  View<int**,CLayout,DeviceType> tr;
11  View<double***,CLayout,DeviceType> p;
12 
13  // View for temporarily storing result data for in-place conversions
14  View<double**,CLayout,DeviceType> result;
15 
16  public:
17 
19 
21  : tr(NoInit("tr"),projection.tr.layout()),
22  p(NoInit("p"),projection.p.layout()),
23  result(NoInit("result"),tr.layout())
24  {
25  // Copy grid conversion info to device
26  Kokkos::deep_copy(tr, projection.tr);
27  Kokkos::deep_copy(p, projection.p);
28  }
29 
30  /* Conversion from field-following coordinates to toroidal coordinates
31  * @param[in] grid is the Grid object needed here to map elements to nodes
32  * @param[in] input is the array one wants to convert
33  * @param[out] output is the resulting converted array
34  * */
35  void cnvt_grid_ff2real(const Grid<DeviceType>& grid, const View<double**,CLayout,DeviceType>& input, const View<double**,Kokkos::LayoutRight,DeviceType>& output) const{
36  // Check the input and output views are the correct size
37  if(input.extent(0) != 2 || input.extent(1) != grid.nnode ||
38  output.extent(0)!= 2 || output.extent(1)!= grid.nnode ) exit_XGC("\nError in cnvt_grid_ff2real: Unexpected View sizes. \n");
39 
40  // Initialize output to zero
41  Kokkos::deep_copy(output, 0.0);
42 
43  // Initialize vol to zero
44  View<double**,CLayout,DeviceType> vol("vol",input.layout());
45 
46  // Copy grid%node_vol_ff from fortran
47  View<double**,CLayout,DeviceType> node_vol_ff(NoInit("node_vol_ff"),input.layout());
48  Kokkos::deep_copy(node_vol_ff, grid.volumes_and_areas.node_vol_ff_h);
49 
50  // Make a (SHALLOW) copy so the lambda doesn't have to implicitly capture *this
51  FieldFollowingCoordinates ff = *this;
52 
53  // for all node point of ff
54  Kokkos::parallel_for("cnvt_grid_ff2real", Kokkos::RangePolicy<ExSpace>(0,grid.nnode), KOKKOS_LAMBDA( const int i ){
55  for (int dir=0;dir<2;dir++){
56  for (int j=0;j<3;j++){
57  // node and weight
58  int nd=grid.get_node_index(ff.tr(dir,i), j);
59  double wt=ff.p(dir,i,j)*node_vol_ff(dir,nd);
60 
61  // accumulate values
62  Kokkos::atomic_add(&(output(dir,nd)), wt*input(dir,i));
63  Kokkos::atomic_add(&(vol(dir,nd)), wt);
64  }
65  }
66  });
67 
68  // Normalize to vol
69  Kokkos::parallel_for("cnvt_grid_ff2real_norm", Kokkos::RangePolicy<ExSpace>(0,grid.nnode), KOKKOS_LAMBDA( const int i ){
70  for (int dir=0;dir<2;dir++){
71  if(vol(dir, i) == 0.0){
72  output(dir, i) = 0.0;
73  }else{
74  output(dir, i) /= vol(dir, i);
75  }
76  }
77  });
78 
79  // fill empty area --- replace nan values
80  Kokkos::parallel_for("cnvt_grid_ff2real_fillempty", Kokkos::RangePolicy<ExSpace>(0,grid.nnode), KOKKOS_LAMBDA( const int i ){
81  for (int dir=0; dir<2; dir++){
82  if(vol(dir,i)==0.0){
83  int cdir = 1-dir;
84  output(dir,i)=0.0;
85  for (int j=0;j<3;j++){
86  int nd=grid.get_node_index(ff.tr(cdir,i), j);
87  double wt=ff.p(cdir,i,j);
88 
89  // obtain interpolated values
90  output(dir,i) += wt*input(dir,nd);
91  }
92  }
93  }
94  });
95  Kokkos::fence();
96  }
97 
98  /* Conversion from real coordinates to field-following coordinates
99  * @param[in] grid is the Grid object needed here to map elements to nodes
100  * @param[in] input is the array one wants to convert
101  * @param[out] output is the resulting converted array
102  * */
103  void cnvt_grid_real2ff(const Grid<DeviceType>& grid, const View<double**,CLayout,DeviceType>& input, const View<double**,Kokkos::LayoutRight,DeviceType>& output) const{
104  // Check the input and output views are the correct size
105  if(input.extent(0) != 2 || input.extent(1) != grid.nnode ||
106  output.extent(0)!= 2 || output.extent(1)!= grid.nnode ) exit_XGC("\nError in cnvt_grid_real2ff: Unexpected View sizes. \n");
107 
108  // Initialize output to zero
109  Kokkos::deep_copy(output, 0.0);
110 
111 
112  // Make a (SHALLOW) copy so the lambda doesn't have to implicitly capture *this
113  FieldFollowingCoordinates ff = *this;
114 
115  Kokkos::parallel_for("cnvt_grid_real2ff", Kokkos::RangePolicy<ExSpace>(0,grid.nnode), KOKKOS_LAMBDA( const int i ){
116  for (int dir=0;dir<2;dir++){
117  for (int j=0;j<3;j++){
118  int nd=grid.get_node_index(ff.tr(dir,i), j);
119 
120  double wt=ff.p(dir,i,j);
121 
122  // obtain interpolated values
123  output(dir,i) += wt*input(dir,nd);
124  }
125  }
126  });
127  Kokkos::fence();
128  }
129 
130  /* In-place conversion from real coordinates to field-following coordinates, using a buffer array to store the result temporarily
131  * before copying back to the input array
132  * @param[in] grid is the Grid object needed here to map elements to nodes
133  * @param[inout] input is the array one wants to convert, and the resulting converted array
134  * */
135  void cnvt_grid_real2ff(const Grid<DeviceType>& grid, const View<double**,CLayout,DeviceType>& input) const{
136  cnvt_grid_real2ff(grid, input, result);
137 
138  // Copy back to original array
139  Kokkos::deep_copy(input, result);
140  }
141 
142  /* Conversion from real coordinates to field-following coordinates for vectors
143  * @param[in] grid is the Grid object needed here to map elements to nodes
144  * @param[in] input is the array one wants to convert
145  * @param[out] output is the resulting converted array
146  * */
147  void cnvt_grid_real2ff(const Grid<DeviceType>& grid, const View<double***,CLayout,DeviceType>& input, const View<double***,Kokkos::LayoutRight,DeviceType>& output) const{
148  for(int i = 0; i<input.extent(0); i++){
149  auto input_i = my_subview(input, i);
150  auto output_i = my_subview(output, i);
151 
152  cnvt_grid_real2ff(grid, input_i, output_i);
153  }
154  }
155 
156  /* In-place conversion from real coordinates to field-following coordinates for vectors, using a buffer array to store the result temporarily
157  * before copying back to the input array
158  * @param[in] grid is the Grid object needed here to map elements to nodes
159  * @param[inout] input is the array one wants to convert, and the resulting converted array
160  * */
161  void cnvt_grid_real2ff(const Grid<DeviceType>& grid, const View<double***,CLayout,DeviceType>& input)const{
162  for(int i = 0; i<input.extent(0); i++){
163  auto input_i = my_subview(input, i);
164  cnvt_grid_real2ff(grid, input_i);
165  }
166  }
167 
168 
169  /* Conversion from real coordinates to field-following coordinates from a GridField with PhiInterpType::None to a GridField with PhiInterpType::Planes.
170  * This implementation could be improved. It uses the existing algorithm which requires the input to have nphi=2, so there is a lot of superfluous copying etc. */
171  void cnvt_grid_real2ff(const Grid<DeviceType>& grid, const ScalarGridField& field_in,
173 
174  // Field-following algorithm requires argument to be nphi=2, and inode as the contiguous index
175  int nphi = 2;
176  Kokkos::View<double**,Kokkos::LayoutRight,DeviceType> dest_view(NoInit("dest_view"), nphi, field_in.nnode());
177 
178  // Since the input is a ScalarGridField (nphi=1), copy the field into both the iphi=0 and iphi=1 indices
179  field_in.copy_to_double_view(my_subview(dest_view, 0)); // iphi=0;
180  field_in.copy_to_double_view(my_subview(dest_view, 1)); // iphi=1;
181 
182  // Convert to field-following
183  cnvt_grid_real2ff(grid, dest_view, result);
184 
185  // Now transpose and copy into the output argument:
186  field_out.transpose_copy_from_double_view(result);
187  }
188 
189 };
190 
191 #endif
VolumesAndAreas volumes_and_areas
Definition: grid.hpp:286
Definition: field_following_coordinates.hpp:9
void cnvt_grid_ff2real(const Grid< DeviceType > &grid, const View< double **, CLayout, DeviceType > &input, const View< double **, Kokkos::LayoutRight, DeviceType > &output) const
Definition: field_following_coordinates.hpp:35
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:103
FieldFollowingCoordinates(const Projection< HostType > &projection)
Definition: field_following_coordinates.hpp:20
FieldFollowingCoordinates()
Definition: field_following_coordinates.hpp:18
View< int **, CLayout, DeviceType > tr
Definition: field_following_coordinates.hpp:10
Definition: grid_field.hpp:25
View< double ***, CLayout, Device > p
Definition: grid.hpp:54
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:147
void cnvt_grid_real2ff(const Grid< DeviceType > &grid, const View< double ***, CLayout, DeviceType > &input) const
Definition: field_following_coordinates.hpp:161
KOKKOS_INLINE_FUNCTION int get_node_index(int triangle_index, int tri_vertex_index) const
Definition: grid.tpp:792
void cnvt_grid_real2ff(const Grid< DeviceType > &grid, const View< double **, CLayout, DeviceType > &input) const
Definition: field_following_coordinates.hpp:135
void exit_XGC(std::string msg)
Definition: globals.hpp:37
View< double ***, CLayout, DeviceType > p
Definition: field_following_coordinates.hpp:11
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
View< int **, CLayout, Device > tr
Definition: grid.hpp:53
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
View< double **, CLayout, DeviceType > result
Definition: field_following_coordinates.hpp:14
int nnode
Number of grid nodes.
Definition: grid.hpp:246
void cnvt_grid_real2ff(const Grid< DeviceType > &grid, const ScalarGridField &field_in, const GridField< DeviceType, VarType::Scalar, PhiInterpType::Planes, TorType::OnePlane, KinType::DriftKin > &field_out) const
Definition: field_following_coordinates.hpp:171
Kokkos::ViewAllocateWithoutInitializing NoInit
Definition: space_settings.hpp:68
View< double **, CLayout, HostType > node_vol_ff_h
Definition: grid.hpp:22