7 extern "C" void my_qsort(
int left,
int right,
int* idx,
double* psi_surf2_tmp,
int npsi_surf2);
9 extern "C" void init_guess_xtable_fort(
int* nguess_2,
double* grid_guess_max,
double* grid_guess_min,
double* grid_inv_guess_d,
int* ntriangle,
int* nnodes,
const RZPair* grid_x,
10 Vertex* grid_nd,
int* guess_xtable,
int* guess_count,
int* guess_list_len_in);
13 extern "C" void init_guess_list_fort(
int* nguess_2,
double* grid_guess_max,
double* grid_guess_min,
double* grid_inv_guess_d,
int* ntriangle,
int* nnodes,
const RZPair* grid_x,
14 Vertex* grid_nd,
int* guess_list,
int* guess_xtable,
int* guess_count,
int* guess_list_len_in);
21 void setup_mapping(
const View<Vertex*, CLayout, HostType> nd,
const View<RZPair*, CLayout, HostType> x, View<VertexMap*, CLayout, HostType>& mapping){
22 Kokkos::parallel_for(
"setup_mapping", Kokkos::RangePolicy<HostExSpace>(0,mapping.extent(0)), KOKKOS_LAMBDA(
const int i ){
23 double dx1r=x[nd[i].vertex[0]-1].r - x[nd[i].vertex[2]-1].r;
24 double dx1z=x[nd[i].vertex[0]-1].z - x[nd[i].vertex[2]-1].z;
25 double dx2r=x[nd[i].vertex[1]-1].r - x[nd[i].vertex[2]-1].r;
26 double dx2z=x[nd[i].vertex[1]-1].z - x[nd[i].vertex[2]-1].z;
28 double det = 1.0/( dx1r*dx2z - dx2r*dx1z);
30 mapping[i].vertex[0].r = dx2z*det;
31 mapping[i].vertex[1].r =-dx2r*det;
32 mapping[i].vertex[0].z =-dx1z*det;
33 mapping[i].vertex[1].z = dx1r*det;
36 mapping[i].vertex[2].r = x[nd[i].vertex[2]-1].r;
37 mapping[i].vertex[2].z = x[nd[i].vertex[2]-1].z;
60 template<
class Device,
class Gr
idDevice>
62 const View<double*,CLayout,GridDevice>& psi_h, View<int*, CLayout, GridDevice>& rgn_h){
64 int nnode = gx_h.extent(0);
65 View<RZPair*,CLayout,Device> gx(
"gx",nnode);
66 View<double*,CLayout,Device> psi(
"psi",nnode);
67 View<int*,CLayout,Device> rgn(
"rgn",nnode);
68 Kokkos::deep_copy(gx, gx_h);
69 Kokkos::deep_copy(psi, psi_h);
70 Kokkos::deep_copy(rgn, rgn_h);
72 Kokkos::parallel_for(
"set_rgn", Kokkos::RangePolicy<typename Device::execution_space>(0,rgn.extent(0)), KOKKOS_LAMBDA(
const int i ){
89 Kokkos::deep_copy(gx_h, gx);
90 Kokkos::deep_copy(psi_h, psi);
91 Kokkos::deep_copy(rgn_h, rgn);
95 int get_n_wall_nodes(
const View<int*, HostType>& rgn){
97 for(
int i = 0; i<rgn.size(); i++){
98 if(rgn[i]==Wall) count++;
103 if(
is_rank_zero()) printf(
"\ninit_wall: No wall nodes found!\n");
109 void setup_wall(
const View<int*, CLayout, HostType>& rgn, View<int*, CLayout, HostType>& wall_nodes, View<int*, CLayout, HostType>& node_to_wall){
111 for(
int i = 0; i<rgn.size(); i++){
113 wall_nodes[count]=i + 1;
114 node_to_wall[i]=count + 1;
122 void order_wall(
const View<RZPair*,CLayout,HostType>& gx,
const View<int*, CLayout, HostType>& rgn,
const View<Vertex*, CLayout, HostType>& nodes,
const View<int*,CLayout,DeviceType>& num_t_node_d,
const View<int**,CLayout,DeviceType>& tr_node_d,
const View<int**,CLayout,HostType>& adj,
double z_axis,
const View<int*,CLayout,HostType>& wall_nodes,
const View<int*,CLayout,HostType>& node_to_wall){
124 View<int*,CLayout,HostType> num_t_node(
"num_t_node", num_t_node_d.layout());
125 View<int**,CLayout,HostType> tr_node(
"tr_node", tr_node_d.layout());
126 Kokkos::deep_copy(num_t_node, num_t_node_d);
127 Kokkos::deep_copy(tr_node, tr_node_d);
129 int nwall = wall_nodes.size();
132 View<int*, CLayout, HostType> ordered_wall_nodes(
"ordered_wall_nodes", wall_nodes.layout());
135 int nextnode = wall_nodes(0);
136 for(
int w=0; w<nwall; w++){
137 if (nextnode==lastnode &&
is_rank_zero()) printf(
"WARNING: nextnode and lastnode the same!\n");
138 ordered_wall_nodes(w) = nextnode;
144 for(
int j=0; j<num_t_node(thisnode-1); j++){
145 int itr = tr_node(j,thisnode-1);
148 int iv = nodes(itr).vertex[0]==thisnode ? 0 :
149 nodes(itr).vertex[1]==thisnode ? 1 : 2;
152 for(
int k=0; k<3; k++){
153 int candidate = nodes(itr).vertex[k];
154 if(rgn(candidate-1)==Wall &&
155 candidate!=thisnode &&
157 adj(itr, 3 - (iv + k))==-1 &&
158 candidate!=lastnode){
161 nextnode = candidate;
165 if(nextnode!=-1)
break;
169 if (nextnode != ordered_wall_nodes(0) &&
is_rank_zero()) printf(
"WARNING: wall_nodes ordered doesnt form closed surface\n");
173 int crossing_segment = -1;
174 double min_r_crossing;
176 for(
int w=0; w<nwall; w++){
178 int w2 = (w+1)%nwall;
179 double z1 = gx(ordered_wall_nodes(w)-1).z;
180 double z2 = gx(ordered_wall_nodes(w2)-1).z;
182 bool z_axis_crossed = (z1>=z_axis && z2<z_axis) || (z1<z_axis && z2>=z_axis);
184 double r1 = gx(ordered_wall_nodes(w)-1).r;
185 double r2 = gx(ordered_wall_nodes(w2)-1).r;
188 double r_crossing = r1 + dr*(z_axis-z1)/dz;
191 r_crossing = std::max(std::min(r1, r2), r_crossing);
192 r_crossing = std::min(std::max(r1, r2), r_crossing);
193 if(crossing_segment==-1 || r_crossing<min_r_crossing){
194 crossing_segment = w;
195 min_r_crossing = r_crossing;
204 if(crossing_segment==-1){
205 if(
is_rank_zero()) printf(
"WARNING: Wall does not appear to intersect z-axis.\n");
207 crossing_segment = 0;
208 int p0 = crossing_segment;
209 int p1 = (crossing_segment+1)%nwall;
210 int pm1 = (nwall+crossing_segment-1)%nwall;
211 double r0 = gx(ordered_wall_nodes(p0)-1).r;
212 double r1 = gx(ordered_wall_nodes(p1)-1).r;
213 double rm1 = gx(ordered_wall_nodes(pm1)-1).r;
214 double z0 = gx(ordered_wall_nodes(p0)-1).z;
215 double z1 = gx(ordered_wall_nodes(p1)-1).z;
216 double zm1 = gx(ordered_wall_nodes(pm1)-1).z;
220 double det = (r1-r0)*(zm1-z0)-(rm1-r0)*(z1-z0);
222 clockwise = (det<0.0);
226 clockwise = (r1<rm1);
229 clockwise = (z1<zm1);
234 exit_XGC(
"\nError: Two wall nodes are the same.\n");
243 int first_point = (crossing_segment+1)%nwall;
244 for(
int w=0; w<nwall; w++){
245 wall_nodes(w) = ordered_wall_nodes((first_point+w)%nwall);
249 int first_point = crossing_segment;
250 for(
int w=0; w<nwall; w++){
251 wall_nodes(w) = ordered_wall_nodes((nwall+first_point-w)%nwall);
256 Kokkos::deep_copy(node_to_wall, 0);
257 for(
int i = 0; i<nwall; i++){
258 node_to_wall(wall_nodes(i)-1) = i+1;
263 template<
class Device,
class Gr
idDevice>
265 int nnode = gx_h.extent(0);
266 View<RZPair*,CLayout,Device> gx(
"gx",nnode);
267 Kokkos::deep_copy(gx, gx_h);
270 View<double*,CLayout,Device> psi(
"psi", nnode);
271 Kokkos::parallel_for(
"psi_calc", Kokkos::RangePolicy<typename Device::execution_space>(0, nnode), KOKKOS_LAMBDA(
const int idx ){
272 double psi_local = magnetic_field.
get_psi(gx(idx).r,gx(idx).z, phi);
273 psi(idx) = max(1e-70, psi_local);
279 double psi_zero_eps = 5.0e-3;
280 Kokkos::parallel_for(
"psi_calc_check_first", Kokkos::RangePolicy<typename Device::execution_space>(0, 1), KOKKOS_LAMBDA(
const int idx ){
281 double dr = gx(idx).r - magnetic_field.
equil.
axis.
r;
282 double dz = gx(idx).z - magnetic_field.
equil.
axis.
z;
283 if(sqrt(dr*dr + dz*dz) < psi_zero_eps){
290 View<double*,CLayout,GridDevice> psi_h(
"psi", nnode);
291 Kokkos::deep_copy(psi_h, psi);
297 template<
class Device>
299 const View<double*,CLayout,HostType>& psi_h,
300 const View<int*, CLayout, HostType>& nnodes_on_surface_h,
301 const View<int**,CLayout,HostType>& surf_idx_h,
302 const View<double*,CLayout,HostType>& node_vol_h){
305 View<double*,CLayout,Device> psi(
NoInit(
"psi"), psi_h.layout());
306 View<int*, CLayout,Device> nnodes_on_surface(
NoInit(
"nnodes_on_surface"),nnodes_on_surface_h.layout());
307 View<int**,CLayout,Device> surf_idx(
NoInit(
"surf_idx"),surf_idx_h.layout());
308 View<double*,CLayout,Device> node_vol(
NoInit(
"node_vol"),node_vol_h.layout());
309 Kokkos::deep_copy(psi, psi_h);
310 Kokkos::deep_copy(nnodes_on_surface, nnodes_on_surface_h);
311 Kokkos::deep_copy(node_vol, node_vol_h);
312 Kokkos::deep_copy(surf_idx, surf_idx_h);
315 View<double*,CLayout,Device> psi_surf(
NoInit(
"psi_surf"), nnodes_on_surface.size());
318 Kokkos::parallel_for(
"get_psi_surf", Kokkos::RangePolicy<typename Device::execution_space>(0,psi_surf.size()), KOKKOS_LAMBDA(
const int i ){
319 double surf_vol = 0.0;
320 double psi_sum = 0.0;
321 for(
int j=0; j<nnodes_on_surface(i); j++){
322 int k=surf_idx(i, j)-1;
326 psi_sum += psi(k)*node_vol(k);
327 surf_vol += node_vol(k);
329 psi_surf(i) = psi_sum/surf_vol;
333 View<double*,CLayout,HostType> psi_surf_h(
NoInit(
"psi_surf"), psi_surf.layout());
334 Kokkos::deep_copy(psi_surf_h, psi_surf);
344 template<
class Device>
346 const View<int*, CLayout, HostType>& nnodes_on_surface_h,
347 const View<int**,CLayout, HostType>& surf_idx_h,
348 const View<double*,CLayout,HostType>& psi_surf_h,
349 const View<RZPair*,CLayout,HostType>& gx_h){
350 const double use_surf_thresh=3.0e-2;
351 int nnode = gx_h.extent(0);
352 View<RZPair*,CLayout,Device> gx(
"gx",nnode);
353 View<int*, CLayout, Device> nnodes_on_surface(
NoInit(
"nnodes_on_surface"),nnodes_on_surface_h.layout());
354 View<int**,CLayout, Device> surf_idx(
NoInit(
"surf_idx"),surf_idx_h.layout());
355 Kokkos::deep_copy(nnodes_on_surface, nnodes_on_surface_h);
356 Kokkos::deep_copy(surf_idx, surf_idx_h);
357 Kokkos::deep_copy(gx, gx_h);
359 int nsurfaces = nnodes_on_surface.size();
362 View<bool*,CLayout,Device> use_surf(
"use_surf", nsurfaces);
363 Kokkos::parallel_reduce(
"get_psi_surf2", Kokkos::RangePolicy<typename Device::execution_space>(0,psi_surf_h.size()), KOKKOS_LAMBDA(
const int i,
int& npsi_surf2_l){
365 for(
int j=0; j<nnodes_on_surface(i); j++){
366 int k=surf_idx(i, j)-1;
369 if ( (std::abs(gx(k).z-magnetic_field.
equil.
axis.
z) < zmin) && (gx(k).r-(magnetic_field.
equil.
axis.
r - 5.0e-5) >= 0.0) ){
370 zmin=std::abs(gx(k).z -magnetic_field.
equil.
axis.
z);
374 if (zmin <= use_surf_thresh){
384 View<bool*,CLayout,HostType> use_surf_h(
"use_surf", nsurfaces);
385 Kokkos::deep_copy(use_surf_h, use_surf);
388 View<double*, CLayout, HostType> psi_surf2_h(
NoInit(
"psi_surf2"),npsi_surf2);
390 for(
int i=0; i<nsurfaces; i++){
392 psi_surf2_h(j) = psi_surf_h(i);
398 View<int*, HostType> idx(
NoInit(
"idx"),npsi_surf2);
399 for(
int i=0; i<npsi_surf2; i++) idx(i) = i + 1;
401 int right=npsi_surf2;
402 my_qsort(left,right,idx.data(),psi_surf2_h.data(),npsi_surf2);
403 View<double*, HostType> tmp(
NoInit(
"tmp"),npsi_surf2);
404 for(
int i=0; i<npsi_surf2; i++) tmp(i)=psi_surf2_h(idx(i) - 1);
405 for(
int i=0; i<npsi_surf2; i++) psi_surf2_h(i)=tmp(i);
411 template<
class Device,
class Gr
idDevice>
412 View<double*,CLayout,GridDevice> setup_grid_bfield(
const MagneticField<Device>& magnetic_field,
const View<RZPair*,CLayout,GridDevice>& gx_h){
413 int nnode = gx_h.extent(0);
414 View<RZPair*,CLayout,Device> gx(
"gx",nnode);
415 Kokkos::deep_copy(gx, gx_h);
418 View<double*,CLayout,Device> bfield(
"bfield", nnode);
419 Kokkos::parallel_for(
"node_bfield", Kokkos::RangePolicy<typename Device::execution_space>(0,nnode), KOKKOS_LAMBDA(
const int idx ){
421 magnetic_field.
bvec_interpol(gx(idx).r,gx(idx).z,0.0,br,bz,bphi);
422 bfield(idx) = sqrt(br*br + bz*bz + bphi*bphi);
426 View<double*,CLayout,GridDevice> bfield_h(
"bfield", nnode);
427 Kokkos::deep_copy(bfield_h, bfield);
433 template<
class Device,
class Gr
idDevice>
434 View<double**,CLayout,GridDevice> setup_bfield_vecmag(
const MagneticField<Device>& magnetic_field,
const View<RZPair*,CLayout,GridDevice>& gx_h){
435 int nnode = gx_h.extent(0);
436 View<RZPair*,CLayout,Device> gx(
"gx",nnode);
437 Kokkos::deep_copy(gx, gx_h);
440 View<double**,CLayout,Device> bfield(
"bfield", 4, nnode);
441 Kokkos::parallel_for(
"node_bfield", Kokkos::RangePolicy<typename Device::execution_space>(0,nnode), KOKKOS_LAMBDA(
const int idx ){
443 magnetic_field.
bvec_interpol(gx(idx).r,gx(idx).z,0.0,br,bz,bphi);
446 bfield(2, idx) = bphi;
447 bfield(3, idx) = sqrt(br*br + bz*bz + bphi*bphi);
451 View<double**,CLayout,GridDevice> bfield_h(
"bfield", 4, nnode);
452 Kokkos::deep_copy(bfield_h, bfield);
KOKKOS_INLINE_FUNCTION void bvec_interpol(double r, double z, double phi, double &br, double &bz, double &bphi) const
Definition: magnetic_field.tpp:262
bool is_rank_zero()
Definition: globals.hpp:27
KOKKOS_INLINE_FUNCTION void get_psi(const SimdVector &v, Simd< double > &psi_out) const
Definition: magnetic_field.tpp:46
void init_guess_xtable_fort(int *nguess_2, double *grid_guess_max, double *grid_guess_min, double *grid_inv_guess_d, int *ntriangle, int *nnodes, const RZPair *grid_x, Vertex *grid_nd, int *guess_xtable, int *guess_count, int *guess_list_len_in)
void my_qsort(int left, int right, int *idx, double *psi_surf2_tmp, int npsi_surf2)
Definition: magnetic_field.hpp:12
Equilibrium equil
The object containing information about the magnetic equilibrium.
Definition: magnetic_field.hpp:44
double z
Definition: grid_structs.hpp:30
Definition: grid_structs.hpp:28
FileRegion
Definition: grid_setup.hpp:42
void init_guess_list_fort(int *nguess_2, double *grid_guess_max, double *grid_guess_min, double *grid_inv_guess_d, int *ntriangle, int *nnodes, const RZPair *grid_x, Vertex *grid_nd, int *guess_list, int *guess_xtable, int *guess_count, int *guess_list_len_in)
Definition: grid_structs.hpp:24
double r
Definition: grid_structs.hpp:29
Region
Definition: grid_setup.hpp:48
void exit_XGC(std::string msg)
Definition: globals.hpp:37
Definition: magnetic_field.F90:1
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
KOKKOS_INLINE_FUNCTION bool is_in_region_1_or_2(double r, double z, double psi) const
Definition: magnetic_field.tpp:9
double epsil_psi
Not sure?
Definition: equil.hpp:83
RZPair axis
Definition: equil.hpp:90
Kokkos::ViewAllocateWithoutInitializing NoInit
Definition: space_settings.hpp:68
double xpt_psi
Psi coordinate of 1st X-point.
Definition: equil.hpp:81