22 FieldRZYT(
const CylindricalFunctorsLvl1& psip,
const CylindricalFunctorsLvl1& ipol,
double R0,
double Z0): R_0_(R0), Z_0_(Z0), psip_(psip), ipol_(ipol){}
23 void operator()(
double t,
const std::array<double,3>& y, std::array<double,3>& yp)
const
25 double psipR = psip_.dfx()(
y[0],
y[1]), psipZ = psip_.dfy()(
y[0],
y[1]);
26 double ipol=ipol_.f()(
y[0],
y[1]);
30 double r2 = (
y[0]-R_0_)*(y[0]-R_0_) + (
y[1]-Z_0_)*(y[1]-Z_0_);
31 double fieldT = psipZ*(
y[1]-Z_0_)/r2 + psipR*(y[0]-R_0_)/r2;
38 CylindricalFunctorsLvl1 psip_, ipol_;
43 FieldRZYZ(
const CylindricalFunctorsLvl1& psip,
const CylindricalFunctorsLvl1& ipol):psip_(psip), ipol_(ipol) {}
44 void operator()(
double t,
const std::array<double,3>& y, std::array<double,3>& yp)
const
46 double psipR = psip_.dfx()(
y[0],
y[1]), psipZ = psip_.dfy()(
y[0],
y[1]);
47 double ipol=ipol_.f()(
y[0],
y[1]);
56 CylindricalFunctorsLvl1 psip_, ipol_;
66 FieldRZY(
const CylindricalFunctorsLvl2& psip,
const CylindricalFunctorsLvl1& ipol): f_(1.), psip_(psip), ipol_(ipol){}
67 void set_f(
double f){ f_ = f;}
68 void operator()(
double t,
const std::array<double,2>& y, std::array<double,2>& yp)
const
70 double psipR = psip_.dfx()(
y[0],
y[1]), psipZ = psip_.dfy()(
y[0],
y[1]);
71 double ipol=ipol_.f()(
y[0],
y[1]);
72 double fnorm =
y[0]/ipol/f_;
73 yp[0] = (psipZ)*fnorm;
74 yp[1] = -(psipR)*fnorm;
78 CylindricalFunctorsLvl1 psip_,ipol_;
94 FieldRZYRYZY(
const CylindricalFunctorsLvl2& psip,
const CylindricalFunctorsLvl1& ipol): f_(1.), f_prime_(1), psip_(psip), ipol_(ipol){}
95 void set_f(
double new_f){ f_ = new_f;}
96 void set_fp(
double new_fp){ f_prime_ = new_fp;}
97 void initialize(
double R0,
double Z0,
double& yR,
double& yZ)
99 double psipR = psip_.dfx()(R0, Z0), psipZ = psip_.dfy()(R0,Z0);
100 double psip2 = (psipR*psipR+ psipZ*psipZ);
101 double fnorm =R0/ipol_.f()(R0,Z0)/f_;
102 yR = -psipZ/psip2/fnorm;
103 yZ = +psipR/psip2/fnorm;
105 void derive(
double R0,
double Z0,
double& xR,
double& xZ)
107 xR = +f_*psip_.dfx()(R0, Z0);
108 xZ = +f_*psip_.dfy()(R0, Z0);
111 void operator()(
double t,
const std::array<double,4>& y, std::array<double,4>& yp)
const
113 double psipR = psip_.dfx()(
y[0],
y[1]), psipZ = psip_.dfy()(
y[0],
y[1]);
114 double psipRR = psip_.dfxx()(
y[0],
y[1]), psipRZ = psip_.dfxy()(
y[0],
y[1]), psipZZ = psip_.dfyy()(
y[0],
y[1]);
115 double ipol=ipol_.f()(
y[0],
y[1]);
116 double ipolR=ipol_.dfx()(
y[0],
y[1]);
117 double ipolZ=ipol_.dfy()(
y[0],
y[1]);
118 double fnorm =
y[0]/ipol/f_;
120 yp[0] = -(psipZ)*fnorm;
121 yp[1] = +(psipR)*fnorm;
122 yp[2] = (+psipRZ*
y[2]- psipRR*
y[3])*fnorm + f_prime_/f_*psipR + ipolR/ipol - 1./y[0];
123 yp[3] = (-psipRZ*
y[3]+ psipZZ*
y[2])*fnorm + f_prime_/f_*psipZ + ipolZ/ipol;
128 CylindricalFunctorsLvl2 psip_;
129 CylindricalFunctorsLvl1 ipol_;
138 FieldRZYT(
const CylindricalFunctorsLvl1& psip,
double R0,
double Z0,
const CylindricalSymmTensorLvl1& chi = CylindricalSymmTensorLvl1() ): R_0_(R0), Z_0_(Z0), psip_(psip), chi_(chi){}
139 void operator()(
double t,
const std::array<double,3>& y, std::array<double,3>& yp)
const
141 double psipR = psip_.dfx()(
y[0],
y[1]), psipZ = psip_.dfy()(
y[0],
y[1]);
142 double psip2 = chi_.xx()(
y[0],
y[1])*psipR*psipR
143 + 2.*chi_.xy()(
y[0],
y[1])*psipR*psipZ
144 + chi_.yy()(
y[0],
y[1])*psipZ*psipZ;
151 double r2 = (
y[0]-R_0_)*(y[0]-R_0_) + (
y[1]-Z_0_)*(y[1]-Z_0_);
152 double fieldT = psipZ*(
y[1]-Z_0_)/r2 + psipR*(y[0]-R_0_)/r2;
159 CylindricalFunctorsLvl1 psip_;
160 CylindricalSymmTensorLvl1 chi_;
165 FieldRZYZ(
const CylindricalFunctorsLvl1& psip,
const CylindricalSymmTensorLvl1& chi = CylindricalSymmTensorLvl1() ): psip_(psip), chi_(chi){}
166 void operator()(
double t,
const std::array<double,3>& y, std::array<double,3>& yp)
const
168 double psipR = psip_.dfx()(
y[0],
y[1]), psipZ = psip_.dfy()(
y[0],
y[1]);
169 double psip2 = chi_.xx()(
y[0],
y[1])*psipR*psipR
170 + 2.*chi_.xy()(
y[0],
y[1])*psipR*psipZ
171 + chi_.yy()(
y[0],
y[1])*psipZ*psipZ;
183 CylindricalFunctorsLvl1 psip_;
184 CylindricalSymmTensorLvl1 chi_;
189 FieldRZY(
const CylindricalFunctorsLvl1& psip,
const CylindricalSymmTensorLvl1& chi = CylindricalSymmTensorLvl1() ): f_(1.), psip_(psip), chi_(chi){}
190 void set_f(
double f){ f_ = f;}
191 void operator()(
double t,
const std::array<double,2>& y, std::array<double,2>& yp)
const
193 double psipR = psip_.dfx()(
y[0],
y[1]), psipZ = psip_.dfy()(
y[0],
y[1]);
194 double psip2 = chi_.xx()(
y[0],
y[1])*psipR*psipR
195 + 2.*chi_.xy()(
y[0],
y[1])*psipR*psipZ
196 + chi_.yy()(
y[0],
y[1])*psipZ*psipZ;
201 yp[0] = -psipZ/psip2/f_;
202 yp[1] = +psipR/psip2/f_;
208 CylindricalFunctorsLvl1 psip_;
209 CylindricalSymmTensorLvl1 chi_;
215 FieldRZYRYZY(
const CylindricalFunctorsLvl2& psip):psip_(psip){ f_ = f_prime_ = 1.;}
216 void set_f(
double new_f){ f_ = new_f;}
217 void set_fp(
double new_fp){ f_prime_ = new_fp;}
218 void initialize(
double R0,
double Z0,
double& yR,
double& yZ)
220 yR = -f_*psip_.dfy()(R0, Z0);
221 yZ = +f_*psip_.dfx()(R0, Z0);
223 void derive(
double R0,
double Z0,
double& xR,
double& xZ)
225 xR = +f_*psip_.dfx()(R0, Z0);
226 xZ = +f_*psip_.dfy()(R0, Z0);
229 void operator()(
double t,
const std::array<double,4>& y, std::array<double,4>& yp)
const
231 double psipR = psip_.dfx()(
y[0],
y[1]), psipZ = psip_.dfy()(
y[0],
y[1]);
232 double psipRR = psip_.dfxx()(
y[0],
y[1]), psipRZ = psip_.dfxy()(
y[0],
y[1]), psipZZ = psip_.dfyy()(
y[0],
y[1]);
233 double psip2 = (psipR*psipR+ psipZ*psipZ);
235 yp[0] = -psipZ/f_/psip2;
236 yp[1] = +psipR/f_/psip2;
237 yp[2] = ( + psipRZ*
y[2] - psipRR*
y[3] )/f_/psip2
238 + f_prime_/f_* psipR + 2.*(psipR*psipRR + psipZ*psipRZ)/psip2 ;
239 yp[3] = (-psipRZ*
y[3] + psipZZ*
y[2])/f_/psip2
240 + f_prime_/f_* psipZ + 2.*(psipR*psipRZ + psipZ*psipZZ)/psip2;
244 CylindricalFunctorsLvl2 psip_;
253 FieldRZYT(
const CylindricalFunctorsLvl1& psip,
double R0,
double Z0,
const CylindricalSymmTensorLvl1& chi = CylindricalSymmTensorLvl1() ): R_0_(R0), Z_0_(Z0), psip_(psip), chi_(chi){}
254 void operator()(
double t,
const std::array<double,3>& y, std::array<double,3>& yp)
const
256 double psipR = psip_.dfx()(
y[0],
y[1]), psipZ = psip_.dfy()(
y[0],
y[1]);
257 double psip2 = chi_.xx()(
y[0],
y[1])*psipR*psipR
258 + 2.*chi_.xy()(
y[0],
y[1])*psipR*psipZ
259 + chi_.yy()(
y[0],
y[1])*psipZ*psipZ;
266 double r2 = (
y[0]-R_0_)*(y[0]-R_0_) + (
y[1]-Z_0_)*(y[1]-Z_0_);
267 double fieldT = psipZ*(
y[1]-Z_0_)/r2 + psipR*(y[0]-R_0_)/r2;
274 CylindricalFunctorsLvl1 psip_;
275 CylindricalSymmTensorLvl1 chi_;
280 FieldRZYZ(
const CylindricalFunctorsLvl1& psip,
const CylindricalSymmTensorLvl1& chi = CylindricalSymmTensorLvl1() ): psip_(psip), chi_(chi){}
281 void operator()(
double t,
const std::array<double,3>& y, std::array<double,3>& yp)
const
283 double psipR = psip_.dfx()(
y[0],
y[1]), psipZ = psip_.dfy()(
y[0],
y[1]);
284 double psip2 = chi_.xx()(
y[0],
y[1])*psipR*psipR
285 + 2.*chi_.xy()(
y[0],
y[1])*psipR*psipZ
286 + chi_.yy()(
y[0],
y[1])*psipZ*psipZ;
298 CylindricalFunctorsLvl1 psip_;
299 CylindricalSymmTensorLvl1 chi_;
304 FieldRZY(
const CylindricalFunctorsLvl1& psip,
const CylindricalSymmTensorLvl1& chi = CylindricalSymmTensorLvl1() ): f_(1.), psip_(psip), chi_(chi){}
305 void set_f(
double f){ f_ = f;}
306 void operator()(
double t,
const std::array<double,2>& y, std::array<double,2>& yp)
const
308 double psipR = psip_.dfx()(
y[0],
y[1]), psipZ = psip_.dfy()(
y[0],
y[1]);
309 double psip2 = chi_.xx()(
y[0],
y[1])*psipR*psipR
310 + 2.*chi_.xy()(
y[0],
y[1])*psipR*psipZ
311 + chi_.yy()(
y[0],
y[1])*psipZ*psipZ;
314 yp[0] = -psipZ/sqrt(psip2)/f_;
315 yp[1] = +psipR/sqrt(psip2)/f_;
323 CylindricalFunctorsLvl1 psip_;
324 CylindricalSymmTensorLvl1 chi_;
330 FieldRZYRYZY(
const CylindricalFunctorsLvl2& psip): psip_(psip){ f_ = f_prime_ = 1.;}
331 void set_f(
double new_f){ f_ = new_f;}
332 void set_fp(
double new_fp){ f_prime_ = new_fp;}
333 void initialize(
double R0,
double Z0,
double& yR,
double& yZ)
335 double psipR = psip_.dfx()(R0, Z0), psipZ = psip_.dfy()(R0,Z0);
336 double psip2 = (psipR*psipR+ psipZ*psipZ);
337 yR = -f_*psipZ/sqrt(psip2);
338 yZ = +f_*psipR/sqrt(psip2);
340 void derive(
double R0,
double Z0,
double& xR,
double& xZ)
342 xR = +f_*psip_.dfx()(R0, Z0);
343 xZ = +f_*psip_.dfy()(R0, Z0);
346 void operator()(
double t,
const std::array<double,4>& y, std::array<double,4>& yp)
const
348 double psipR = psip_.dfx()(
y[0],
y[1]), psipZ = psip_.dfy()(
y[0],
y[1]);
349 double psipRR = psip_.dfxx()(
y[0],
y[1]), psipRZ = psip_.dfxy()(
y[0],
y[1]), psipZZ = psip_.dfyy()(
y[0],
y[1]);
350 double psip2 = (psipR*psipR+ psipZ*psipZ);
352 yp[0] = -psipZ/f_/sqrt(psip2);
353 yp[1] = +psipR/f_/sqrt(psip2);
354 yp[2] = ( +psipRZ*
y[2] - psipRR *
y[3])/f_/sqrt(psip2)
355 + f_prime_/f_* psipR + (psipR*psipRR + psipZ*psipRZ)/psip2 ;
356 yp[3] = ( -psipRZ*
y[3] + psipZZ*
y[2])/f_/sqrt(psip2)
357 + f_prime_/f_* psipZ + (psipR*psipRZ + psipZ*psipZZ)/psip2;
361 CylindricalFunctorsLvl2 psip_;
368 FieldRZtau(
const CylindricalFunctorsLvl1& psip,
const CylindricalSymmTensorLvl1& chi = CylindricalSymmTensorLvl1()): psip_(psip), chi_(chi){}
369 void operator()(
double t,
const std::array<double,2>& y, std::array<double,2>& yp)
const
371 double psipR = psip_.dfx()(
y[0],
y[1]), psipZ = psip_.dfy()(
y[0],
y[1]);
372 double chiRR = chi_.xx()(
y[0],
y[1]),
373 chiRZ = chi_.xy()(
y[0],
y[1]),
374 chiZZ = chi_.yy()(
y[0],
y[1]);
375 double psip2 = chiRR*psipR*psipR + 2.*chiRZ*psipR*psipZ + chiZZ*psipZ*psipZ;
376 yp[0] = (chiRR*psipR + chiRZ*psipZ)/psip2;
377 yp[1] = (chiRZ*psipR + chiZZ*psipZ)/psip2;
380 CylindricalFunctorsLvl1 psip_;
381 CylindricalSymmTensorLvl1 chi_;
386 HessianRZtau(
const CylindricalFunctorsLvl2& psip): norm_(false), quad_(1), psip_(psip){}
388 void set_quadrant(
int quadrant) {quad_ = quadrant;}
389 void set_norm(
bool normed) {norm_ = normed;}
390 void operator()(
double t,
const std::array<double,2>& y, std::array<double,2>& yp)
const
392 double psipRZ = psip_.dfxy()(
y[0],
y[1]);
395 if( quad_ == 0) { yp[0] = 1; yp[1] = 0; }
396 else if( quad_ == 1) { yp[0] = 0; yp[1] = 1; }
397 else if( quad_ == 2) { yp[0] = -1; yp[1] = 0; }
398 else if( quad_ == 3) { yp[0] = 0; yp[1] = -1; }
402 double psipRR = psip_.dfxx()(
y[0],
y[1]), psipZZ = psip_.dfyy()(
y[0],
y[1]);
403 double T = psipRR + psipZZ;
404 double D = psipZZ*psipRR - psipRZ*psipRZ;
405 double L1 = 0.5*T+sqrt( 0.25*T*T-D);
406 double L2 = 0.5*T-sqrt( 0.25*T*T-D);
407 if ( quad_ == 0){ yp[0] = L1 - psipZZ; yp[1] = psipRZ;}
408 else if ( quad_ == 1){ yp[0] = -psipRZ; yp[1] = psipRR - L2;}
409 else if ( quad_ == 2){ yp[0] = psipZZ - L1; yp[1] = -psipRZ;}
410 else if ( quad_ == 3){ yp[0] = +psipRZ; yp[1] = L2 - psipRR;}
414 double vgradpsi = yp[0]*psip_.dfx()(
y[0],
y[1]) + yp[1]*psip_.dfy()(
y[0],
y[1]);
415 yp[0] /= vgradpsi, yp[1] /= vgradpsi;
419 double norm = sqrt(yp[0]*yp[0]+yp[1]*yp[1]);
420 yp[0]/= norm, yp[1]/= norm;
427 CylindricalFunctorsLvl2 psip_;
432 MinimalCurve(
const CylindricalFunctorsLvl1& psip): norm_(false),
434 void set_norm(
bool normed) {norm_ = normed;}
435 void operator()(
double t,
const std::array<double,4>& y, std::array<double,4>& yp)
const
437 double psipR = psip_.dfx()(
y[0],
y[1]), psipZ = psip_.dfy()(
y[0],
y[1]);
445 if( psip_.f()(
y[0],
y[1]) < 0)
458 double vgradpsi =
y[2]*psipR +
y[3]*psipZ;
459 yp[0] /= vgradpsi, yp[1] /= vgradpsi, yp[2] /= vgradpsi, yp[3] /= vgradpsi;
464 CylindricalFunctorsLvl1 psip_;
475template <
class FieldFinv>
476void construct_psi_values( FieldFinv fpsiMinv,
477 const double psi_0,
const double psi_1,
const double x_0,
const thrust::host_vector<double>& x_vec,
const double x_1,
478 thrust::host_vector<double>& psi_x,
479 thrust::host_vector<double>& f_x_,
bool verbose =
false)
481 f_x_.resize( x_vec.size()), psi_x.resize( x_vec.size());
482 double begin(psi_0), end(begin), temp(begin);
484 double eps = 1e10, eps_old=2e10;
485 if(verbose)std::cout <<
"In psi function:\n";
486 double x0=x_0, x1 = psi_1>psi_0? x_vec[0]:-x_vec[0];
488 "Feagin-17-8-10",0.), fpsiMinv);
489 while( (eps < eps_old || eps > 1e-8) && eps > 1e-14)
492 x0 = x_0, x1 = x_vec[0];
493 if( psi_1<psi_0) x1*=-1;
494 odeint.integrate_steps( x0, begin, x1, end, N);
495 psi_x[0] = end; fpsiMinv(0.,end,temp); f_x_[0] = temp;
496 for(
unsigned i=1; i<x_vec.size(); i++)
499 x0 = x_vec[i-1], x1 = x_vec[i];
500 if( psi_1<psi_0) x0*=-1, x1*=-1;
501 odeint.integrate_steps( x0, temp, x1, end, N);
502 psi_x[i] = end; fpsiMinv(0.,end,temp); f_x_[i] = temp;
505 odeint.integrate_steps(x1, temp, psi_1>psi_0?x_1:-x_1, end,N);
506 double psi_1_numerical = end;
507 eps = fabs( psi_1_numerical-psi_1);
508 if(verbose)std::cout <<
"Effective Psi error is "<<eps<<
" with "<<N<<
" steps\n";
516template <
class Fpsi,
class FieldRZYRYZY>
517void compute_rzy(Fpsi fpsi, FieldRZYRYZY fieldRZYRYZY,
518 double psi,
const thrust::host_vector<double>& y_vec,
519 thrust::host_vector<double>& r,
520 thrust::host_vector<double>& z,
521 thrust::host_vector<double>& yr,
522 thrust::host_vector<double>& yz,
523 thrust::host_vector<double>& xr,
524 thrust::host_vector<double>& xz,
525 double& R_0,
double& Z_0,
double& f,
double& fp,
bool verbose =
false )
527 thrust::host_vector<double> r_old(y_vec.size(), 0), r_diff( r_old), yr_old(r_old), xr_old(r_old);
528 thrust::host_vector<double> z_old(y_vec.size(), 0), z_diff( z_old), yz_old(r_old), xz_old(z_old);
529 r.resize( y_vec.size()),
z.resize(y_vec.size()), yr.resize(y_vec.size()),
yz.resize(y_vec.size()), xr.resize(y_vec.size()),
xz.resize(y_vec.size());
532 std::array<double, 4> begin{ {0,0,0,0} }, end(begin), temp(begin);
533 const double f_psi = fpsi.construct_f( psi, begin[0], begin[1]);
534 fieldRZYRYZY.set_f(f_psi);
535 double fprime = fpsi.f_prime( psi);
536 fieldRZYRYZY.set_fp(fprime);
537 fieldRZYRYZY.initialize( begin[0], begin[1], begin[2], begin[3]);
538 R_0 = begin[0], Z_0 = begin[1];
539 if(verbose)std::cout <<f_psi<<
" "<<
" "<< begin[0] <<
" "<<begin[1]<<
"\t";
541 double eps = 1e10, eps_old=2e10;
542 using Vec = std::array<double,4>;
544 begin), fieldRZYRYZY);
545 while( eps < eps_old)
548 eps_old = eps, r_old = r, z_old =
z, yr_old = yr, yz_old =
yz, xr_old = xr, xz_old =
xz;
549 odeint.integrate_steps( 0, begin, y_vec[0], end, steps);
550 r[0] = end[0],
z[0] = end[1], yr[0] = end[2],
yz[0] = end[3];
551 fieldRZYRYZY.derive( r[0], z[0], xr[0], xz[0]);
553 for(
unsigned i=1; i<y_vec.size(); i++)
556 odeint.integrate_steps( y_vec[i-1], temp, y_vec[i], end, steps);
557 r[i] = end[0],
z[i] = end[1], yr[i] = end[2],
yz[i] = end[3];
558 fieldRZYRYZY.derive( r[i], z[i], xr[i], xz[i]);
567 eps = sqrt( er + ez)/sqrt(ar+az);
571 r = r_old,
z = z_old, yr = yr_old,
yz = yz_old, xr = xr_old,
xz = xz_old;
void axpby(get_value_type< ContainerType > alpha, const ContainerType1 &x, get_value_type< ContainerType > beta, ContainerType &y)
get_value_type< ContainerType1 > dot(const ContainerType1 &x, const ContainerType2 &y)