21struct TestFunctionPsi2
23 TestFunctionPsi2(
const TokamakMagneticField& c,
double a):R_0(c.R0()), a(a), c_(c){}
24 double operator()(
double R,
double Z,
double phi)
const {
25 return exp((R-R_0)/a)*exp(Z/a)*cos(phi)*cos(phi);
27 double dR(
double R,
double Z,
double phi)
const{
28 return exp((R-R_0)/a)*exp(Z/a)*cos(phi)*cos(phi)/a;
30 double dRR(
double R,
double Z,
double phi)
const{
31 return exp((R-R_0)/a)*exp(Z/a)*cos(phi)*cos(phi)/a/a;
33 double dRZ(
double R,
double Z,
double phi)
const{
34 return exp((R-R_0)/a)*exp(Z/a)*cos(phi)*cos(phi)/a/a;
36 double dZ(
double R,
double Z,
double phi)
const{
37 return exp((R-R_0)/a)*exp(Z/a)*cos(phi)*cos(phi)/a;
39 double dZZ(
double R,
double Z,
double phi)
const{
40 return exp((R-R_0)/a)*exp(Z/a)*cos(phi)*cos(phi)/a/a;
42 double dP(
double R,
double Z,
double phi)
const{
43 return exp((R-R_0)/a)*exp(Z/a)*(-2.*sin(phi)*cos(phi));
45 double dRP(
double R,
double Z,
double phi)
const{
46 return exp((R-R_0)/a)*exp(Z/a)*(-2.*sin(phi)*cos(phi))/a;
48 double dZP(
double R,
double Z,
double phi)
const{
49 return exp((R-R_0)/a)*exp(Z/a)*(-2.*sin(phi)*cos(phi))/a;
51 double dPP(
double R,
double Z,
double phi)
const{
52 return exp((R-R_0)/a)*exp(Z/a)*(2.*sin(phi)*sin(phi)-2.*cos(phi)*cos(phi));
56 TokamakMagneticField c_;
60struct TestFunctionDirNeu{
61 TestFunctionDirNeu(
const TokamakMagneticField& c){
64 double operator()(
double R,
double Z,
double phi)
const{
65 return (cos(M_PI*(R-R_0))+1.)*(cos(M_PI*Z)+1.)*sin(phi);
67 double dR(
double R,
double Z,
double phi)
const{
68 return -
M_PI*sin(M_PI*(R-R_0))*(cos(M_PI*Z)+1.)*sin(phi);
70 double dZ(
double R,
double Z,
double phi)
const{
71 return -
M_PI*(cos(M_PI*(R-R_0))+1.)*sin(M_PI*Z)*sin(phi);
73 double dP(
double R,
double Z,
double phi)
const{
74 return (cos(M_PI*(R-R_0))+1.)*(cos(M_PI*Z)+1.)*cos(phi);
76 double dRR(
double R,
double Z,
double phi)
const{
77 return -
M_PI*
M_PI*cos(M_PI*(R-R_0))*(cos(M_PI*Z)+1.)*sin(phi);
79 double dZZ(
double R,
double Z,
double phi)
const{
80 return -
M_PI*
M_PI*(cos(M_PI*(R-R_0))+1.)*cos(M_PI*Z)*sin(phi);
82 double dPP(
double R,
double Z,
double phi)
const{
83 return -(cos(M_PI*(R-R_0))+1.)*(cos(M_PI*Z)+1.)*sin(phi);
85 double dRZ(
double R,
double Z,
double phi)
const{
86 return M_PI*
M_PI*sin(M_PI*(R-R_0))*sin(M_PI*Z)*sin(phi);
88 double dRP(
double R,
double Z,
double phi)
const{
89 return -
M_PI*sin(M_PI*(R-R_0))*(cos(M_PI*Z)+1.)*cos(phi);
91 double dZP(
double R,
double Z,
double phi)
const{
92 return -
M_PI*(cos(M_PI*(R-R_0))+1.)*sin(M_PI*Z)*cos(phi);
100template<
class Function>
103 DsFunction(
const TokamakMagneticField& c, Function f): f_(f), c_(c),
104 bhatR_(c), bhatZ_(c), bhatP_(c){}
105 double operator()(
double R,
double Z,
double phi)
const {
106 return bhatR_(R,Z)*f_.dR(R,Z,phi) +
107 bhatZ_(R,Z)*f_.dZ(R,Z,phi) +
108 bhatP_(R,Z)*f_.dP(R,Z,phi);
112 TokamakMagneticField c_;
118template<
class Function>
121 DsDivFunction(
const TokamakMagneticField& c, Function f):
122 f_(f), dsf_(c,f), divb_(c){}
123 double operator()(
double R,
double Z,
double phi)
const {
124 return f_(R,Z,phi)*divb_(R,Z) + dsf_(R,Z,phi);
128 DsFunction<Function> dsf_;
133template<
class Function>
136 DssFunction( TokamakMagneticField c, Function f):f_(f), c_(c),
137 bhatR_(c), bhatZ_(c), bhatP_(c),
138 bhatRR_(c), bhatZR_(c), bhatPR_(c),
139 bhatRZ_(c), bhatZZ_(c), bhatPZ_(c){}
140 double operator()(
double R,
double Z,
double phi)
const {
141 double bhatR = bhatR_(R,Z), bhatZ = bhatZ_(R,Z), bhatP = bhatP_(R,Z);
142 double bhatRR = bhatRR_(R,Z), bhatZR = bhatZR_(R,Z), bhatPR = bhatPR_(R,Z);
143 double bhatRZ = bhatRZ_(R,Z), bhatZZ = bhatZZ_(R,Z), bhatPZ = bhatPZ_(R,Z);
144 double fR = f_.dR(R,Z,phi), fZ = f_.dZ(R,Z,phi), fP = f_.dP(R,Z,phi);
145 double fRR = f_.dRR(R,Z,phi), fRZ = f_.dRZ(R,Z,phi), fZZ = f_.dZZ(R,Z,phi);
146 double fRP = f_.dRP(R,Z,phi), fZP = f_.dZP(R,Z,phi), fPP = f_.dPP(R,Z,phi);
147 double gradbhatR = bhatR*bhatRR+bhatZ*bhatRZ,
148 gradbhatZ = bhatR*bhatZR+bhatZ*bhatZZ,
149 gradbhatP = bhatR*bhatPR+bhatZ*bhatPZ;
150 return bhatR*bhatR*fRR + bhatZ*bhatZ*fZZ + bhatP*bhatP*fPP
151 +2.*(bhatR*bhatZ*fRZ + bhatR*bhatP*fRP + bhatZ*bhatP*fZP)
152 + gradbhatR*fR + gradbhatZ*fZ + gradbhatP*fP;
156 TokamakMagneticField c_;
169template<
class Function>
170struct DsDivDsFunction
172 DsDivDsFunction(
const TokamakMagneticField& c,Function f): dsf_(c,f), dssf_(c,f), divb_(c){}
173 double operator()(
double R,
double Z,
double phi)
const {
174 return divb_(R,Z)*dsf_(R,Z,phi) + dssf_(R,Z,phi);
177 DsFunction<Function> dsf_;
178 DssFunction<Function> dssf_;
183template<
class Function>
186 DPerpFunction(
const TokamakMagneticField& c, Function f): f_(f), dsf_(c,f){}
187 double operator()(
double R,
double Z,
double phi)
const {
188 return f_.dR(R,Z,phi)/R + f_.dRR(R,Z,phi) + f_.dZZ(R,Z,phi) + f_.dPP(R,Z,phi)/R/R - dsf_(R,Z,phi);
192 DsDivDsFunction<Function> dsf_;
195template<
class Function>
196struct OMDsDivDsFunction
198 OMDsDivDsFunction(
const TokamakMagneticField& c,Function f): f_(f), df_(c,f){}
199 double operator()(
double R,
double Z,
double phi)
const {
200 return f_(R,Z,phi)-df_(R,Z,phi);
204 DsDivDsFunction<Function> df_;
207template<
class Function>
210 Variation( Function f): f_(f){}
211 double operator()(
double R,
double Z,
double phi)
const {
212 return sqrt(f_.dR(R,Z,phi)*f_.dR(R,Z,phi) + f_.dZ(R,Z,phi)*f_.dZ(R,Z,phi));
219template<
class DS,
class container>
220void callDS( DS& ds, std::string name,
const container& in, container& out,
221unsigned max_iter = 1e4,
double eps = 1e-6)
223 if( name ==
"forward") ds.ds(
dg::forward, in, out);
224 else if( name ==
"backward") ds.ds(
dg::backward, in, out);
225 else if( name ==
"forward2") ds.forward2( 1., in, 0., out);
226 else if( name ==
"backward2") ds.backward2( 1., in, 0., out);
227 else if( name ==
"centered") ds.ds(
dg::centered, in, out);
228 else if( name ==
"dss") ds.dss( in, out);
229 else if( name ==
"centered_bc_along")
230 ds.centered_bc_along_field( 1., in, 0., out, ds.fieldaligned().bcx(), {0,0});
231 else if( name ==
"dss_bc_along")
232 ds.dss_bc_along_field( 1., in, 0., out, ds.fieldaligned().bcx(), {0,0});
233 else if( name ==
"centered") ds.ds(
dg::centered, in, out);
234 else if( name ==
"dss") ds.dss( in, out);
235 else if( name ==
"divForward") ds.div(
dg::forward, in, out);
236 else if( name ==
"divBackward") ds.div(
dg::backward, in, out);
237 else if( name ==
"divCentered") ds.div(
dg::centered, in, out);
238 else if( name ==
"directLap") {
239 ds.dssd( 1., in, 0., out);
241 else if( name ==
"directLap_bc_along") {
242 ds.dssd_bc_along_field( 1., in, 0., out, ds.fieldaligned().bcx(), {0,0});
244 else if( name ==
"invCenteredLap"){
250 unsigned number =
invert.solve( [&](
const auto& x,
auto& y){
254 }, out, in, precond, ds.weights(), eps);
258 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
262 std::cout <<
"#Number of BICGSTABl iterations: "<<number<<
"\n";
263 std::cout <<
"#Took : "<<t.
diff()<<
"\n";
276 FuncDirPer(
const TokamakMagneticField& c,
double psi_0,
double psi_1,
double k):
277 R_0_(c.R0()), psi0_(psi_0), psi1_(psi_1), k_(k), c_(c) {}
278 double operator()(
double R,
double Z)
const {
279 double psip = c_.psip()(R,Z);
280 double result = (psip-psi0_)*(psip-psi1_)*cos(k_*theta(R,Z));
283 double operator()(
double R,
double Z,
double phi)
const {
284 return operator()(R,Z);
286 double dR(
double R,
double Z)
const
288 double psip = c_.psip()(R,Z), psipR = c_.psipR()(R,Z), theta_ = k_*theta(R,Z);
289 double result = (2.*psip*psipR - (psi0_+psi1_)*psipR)*cos(theta_)
290 - (psip-psi0_)*(psip-psi1_)*sin(theta_)*k_*thetaR(R,Z);
293 double dRR(
double R,
double Z)
const
295 double psip = c_.psip()(R,Z), psipR = c_.psipR()(R,Z), theta_=k_*theta(R,Z), thetaR_=k_*thetaR(R,Z);
296 double psipRR = c_.psipRR()(R,Z);
297 double result = (2.*(psipR*psipR + psip*psipRR) - (psi0_+psi1_)*psipRR)*cos(theta_)
298 - 2.*(2.*psip*psipR-(psi0_+psi1_)*psipR)*sin(theta_)*thetaR_
299 - (psip-psi0_)*(psip-psi1_)*(k_*thetaRR(R,Z)*sin(theta_)+cos(theta_)*thetaR_*thetaR_);
303 double dZ(
double R,
double Z)
const
305 double psip = c_.psip()(R,Z), psipZ = c_.psipZ()(R,Z), theta_=k_*theta(R,Z);
306 double result = (2*psip*psipZ - (psi0_+psi1_)*psipZ)*cos(theta_)
307 - (psip-psi0_)*(psip-psi1_)*sin(theta_)*k_*thetaZ(R,Z);
310 double dZZ(
double R,
double Z)
const
312 double psip = c_.psip()(R,Z), psipZ = c_.psipZ()(R,Z), theta_=k_*theta(R,Z), thetaZ_=k_*thetaZ(R,Z);
313 double psipZZ = c_.psipZZ()(R,Z);
314 double result = (2.*(psipZ*psipZ + psip*psipZZ) - (psi0_+psi1_)*psipZZ)*cos(theta_)
315 - 2.*(2.*psip*psipZ-(psi0_+psi1_)*psipZ)*sin(theta_)*thetaZ_
316 - (psip-psi0_)*(psip-psi1_)*(k_*thetaZZ(R,Z)*sin(theta_) + cos(theta_)*thetaZ_*thetaZ_ );
320 double theta(
double R,
double Z)
const {
323 return acos( dR/sqrt( dR*dR + Z*Z));
325 return 2.*
M_PI-acos( dR/sqrt( dR*dR + Z*Z));
327 double thetaR(
double R,
double Z)
const {
329 return -Z/(dR*dR+Z*Z);
331 double thetaZ(
double R,
double Z)
const {
333 return dR/(dR*dR+Z*Z);
335 double thetaRR(
double R,
double Z)
const {
337 return 2*Z*dR/(dR*dR+Z*Z)/(dR*dR+Z*Z);
339 double thetaZZ(
double R,
double Z)
const {
return -thetaRR(R,Z);}
341 double psi0_, psi1_, k_;
342 const TokamakMagneticField c_;
345struct VariationDirPer
348 double operator()(
double R,
double Z,
double phi)
const {
349 return this->operator()(R,Z);}
351 double operator()(
double R,
double Z)
const {
352 return m_f.dR( R,Z)*m_f.dR(R,Z) + m_f.dZ(R,Z)*m_f.dZ(R,Z);
355 dg::geo::FuncDirPer m_f;
360struct EllipticDirPerM
362 EllipticDirPerM(
const TokamakMagneticField& c,
double psi_0,
double psi_1,
double k): func_(c, psi_0, psi_1, k), bmod_(c), br_(c), bz_(c) {}
363 double operator()(
double R,
double Z,
double phi)
const {
364 return operator()(R,Z);}
365 double operator()(
double R,
double Z)
const {
366 double bmod = bmod_(R,Z), br = br_(R,Z), bz = bz_(R,Z);
367 return -(br*func_.dR(R,Z) + bz*func_.dZ(R,Z) + bmod*(func_.dRR(R,Z) + func_.dZZ(R,Z) ));
380 FuncDirNeu(
const TokamakMagneticField& c,
double psi_0,
double psi_1,
double R_blob,
double Z_blob,
double sigma_blob,
double amp_blob):
381 psi0_(psi_0), psi1_(psi_1),
382 cauchy_(R_blob, Z_blob, sigma_blob, sigma_blob, amp_blob){}
384 double operator()(
double R,
double Z,
double phi)
const {
385 return operator()(R,Z);}
386 double operator()(
double R,
double Z)
const {
392 double dR(
double R,
double Z)
const
394 return cauchy_.dx(R,Z);
399 double dRR(
double R,
double Z)
const
401 return cauchy_.dxx(R,Z);
408 double dZ(
double R,
double Z)
const
410 return cauchy_.dy(R,Z);
415 double dZZ(
double R,
double Z)
const
417 return cauchy_.dyy(R,Z);
432 BmodTheta(
const TokamakMagneticField& c): R_0_(c.R0()), bmod_(c){}
433 double operator()(
double R,
double Z,
double phi)
const{
434 return operator()(R,Z);}
435 double operator()(
double R,
double Z)
const{
436 return bmod_(R,Z)*(1.+0.5*sin(theta(R,Z)));
439 double theta(
double R,
double Z)
const {
442 return acos( dR/sqrt( dR*dR + Z*Z));
444 return 2.*
M_PI-acos( dR/sqrt( dR*dR + Z*Z));
452struct EllipticDirNeuM
454 EllipticDirNeuM(
const TokamakMagneticField& c,
double psi_0,
double psi_1,
double R_blob,
double Z_blob,
double sigma_blob,
double amp_blob): R_0_(c.R0()),
455 func_(c, psi_0, psi_1, R_blob, Z_blob, sigma_blob,amp_blob), bmod_(c), br_(c), bz_(c) {}
456 double operator()(
double R,
double Z)
const {
457 double bmod = bmod_(R,Z), br = br_(R,Z), bz = bz_(R,Z), theta_ = theta(R,Z);
458 double chi = bmod*(1.+0.5*sin(theta_));
459 double chiR = br*(1.+0.5*sin(theta_)) + bmod*0.5*cos(theta_)*thetaR(R,Z);
460 double chiZ = bz*(1.+0.5*sin(theta_)) + bmod*0.5*cos(theta_)*thetaZ(R,Z);
461 return -(chiR*func_.dR(R,Z) + chiZ*func_.dZ(R,Z) + chi*( func_.dRR(R,Z) + func_.dZZ(R,Z) ));
464 double operator()(
double R,
double Z,
double phi)
const {
465 return operator()(R,Z);
468 double theta(
double R,
double Z)
const {
471 return acos( dR/sqrt( dR*dR + Z*Z));
473 return 2.*
M_PI-acos( dR/sqrt( dR*dR + Z*Z));
475 double thetaR(
double R,
double Z)
const {
477 return -Z/(dR*dR+Z*Z);
479 double thetaZ(
double R,
double Z)
const {
481 return dR/(dR*dR+Z*Z);
493 FuncXDirNeu(
const TokamakMagneticField& c,
double psi_0,
double psi_1):
494 c_(c), psi0_(psi_0), psi1_(psi_1){}
496 double operator()(
double R,
double Z,
double phi)
const {
497 return operator()(R,Z);}
498 double operator()(
double R,
double Z)
const {
499 double psip = c_.psip()(R,Z);
500 return (psip-psi0_)*(psip-psi1_);
502 double dR(
double R,
double Z)
const
504 double psip = c_.psip()(R,Z), psipR = c_.psipR()(R,Z);
505 return (2.*psip-psi0_-psi1_)*psipR;
507 double dRR(
double R,
double Z)
const
509 double psip = c_.psip()(R,Z), psipR = c_.psipR()(R,Z);
510 double psipRR = c_.psipRR()(R,Z);
511 return (2.*(psipR*psipR + psip*psipRR) - (psi0_+psi1_)*psipRR);
514 double dZ(
double R,
double Z)
const
516 double psip = c_.psip()(R,Z), psipZ = c_.psipZ()(R,Z);
517 return (2*psip-psi0_-psi1_)*psipZ;
519 double dZZ(
double R,
double Z)
const
521 double psip = c_.psip()(R,Z), psipZ = c_.psipZ()(R,Z);
522 double psipZZ = c_.psipZZ()(R,Z);
523 return (2.*(psipZ*psipZ + psip*psipZZ) - (psi0_+psi1_)*psipZZ);
526 TokamakMagneticField c_;
531struct EllipticXDirNeuM
533 EllipticXDirNeuM(
const TokamakMagneticField& c,
double psi_0,
double psi_1): R_0_(c.R0()),
534 func_(c, psi_0, psi_1), bmod_(c), br_(c), bz_(c) {}
535 double operator()(
double R,
double Z)
const {
536 double bmod = bmod_(R,Z), br = br_(R,Z), bz = bz_(R,Z);
541 return -(chiR*func_.dR(R,Z) + chiZ*func_.dZ(R,Z) + chi*( func_.dRR(R,Z) + func_.dZZ(R,Z) ));
545 double operator()(
double R,
double Z,
double phi)
const {
546 return operator()(R,Z);
557struct EllipticBlobDirNeuM
559 EllipticBlobDirNeuM(
const TokamakMagneticField& c,
double psi_0,
double psi_1,
double R_blob,
double Z_blob,
double sigma_blob,
double amp_blob):
560 func_(c, psi_0, psi_1, R_blob, Z_blob, sigma_blob, amp_blob){}
561 double operator()(
double R,
double Z)
const {
562 return -( func_.dRR(R,Z) + func_.dZZ(R,Z) );
564 double operator()(
double R,
double Z,
double phi)
const {
565 return operator()(R,Z);
572struct EllipticDirSimpleM
574 EllipticDirSimpleM(
const TokamakMagneticField& c,
double psi_0,
double psi_1,
double R_blob,
double Z_blob,
double sigma_blob,
double amp_blob): func_(c, psi_0, psi_1, R_blob, Z_blob, sigma_blob, amp_blob) {}
575 double operator()(
double R,
double Z,
double phi)
const {
576 return -(( 1./R*func_.dR(R,Z) + func_.dRR(R,Z) + func_.dZZ(R,Z) ));
void axpby(get_value_type< ContainerType > alpha, const ContainerType1 &x, get_value_type< ContainerType > beta, ContainerType &y)
void symv(MatrixType &&M, const ContainerType1 &x, ContainerType2 &y)
dg::Operator< T > invert(const dg::Operator< T > &in)
Definition: magnetic_field.h:725
Definition: magnetic_field.h:872
Definition: magnetic_field.h:890
Definition: magnetic_field.h:698
Definition: magnetic_field.h:806
Definition: magnetic_field.h:823
Definition: magnetic_field.h:712
Definition: magnetic_field.h:839
Definition: magnetic_field.h:856
Definition: magnetic_field.h:329
Definition: magnetic_field.h:351
Definition: magnetic_field.h:269
Definition: magnetic_field.h:633
A tokamak field as given by R0, Psi and Ipol plus Meta-data like shape and equilibrium.
Definition: magnetic_field.h:162