Extension: Geometries
#include "dg/geometries/geometries.h"
Loading...
Searching...
No Matches
testfunctors.h
Go to the documentation of this file.
1#pragma once
2
3#include "dg/functors.h"
4#include "magnetic_field.h"
5
10namespace dg
11{
12namespace geo
13{
15//For testing purposes only
19
20//exp(R-R_0)exp(Z)cos^2 (phi)
21struct TestFunctionPsi2
22{
23 TestFunctionPsi2( const TokamakMagneticField& c, double a, double kphi = 1):R_0(c.R0()), a(a), kphi(kphi), c_(c){}
24 double operator()(double R, double Z, double phi) const {
25 return exp((R-R_0)/a)*exp(Z/a)*cos(kphi*phi)*cos(kphi*phi);
26 }
27 double dR( double R, double Z, double phi) const{
28 return exp((R-R_0)/a)*exp(Z/a)*cos(kphi*phi)*cos(kphi*phi)/a;
29 }
30 double dRR( double R, double Z, double phi) const{
31 return exp((R-R_0)/a)*exp(Z/a)*cos(kphi*phi)*cos(kphi*phi)/a/a;
32 }
33 double dRZ( double R, double Z, double phi) const{
34 return exp((R-R_0)/a)*exp(Z/a)*cos(kphi*phi)*cos(kphi*phi)/a/a;
35 }
36 double dZ( double R, double Z, double phi) const{
37 return exp((R-R_0)/a)*exp(Z/a)*cos(kphi*phi)*cos(kphi*phi)/a;
38 }
39 double dZZ( double R, double Z, double phi) const{
40 return exp((R-R_0)/a)*exp(Z/a)*cos(kphi*phi)*cos(kphi*phi)/a/a;
41 }
42 double dP( double R, double Z, double phi) const{
43 return exp((R-R_0)/a)*exp(Z/a)*(-2.*kphi*sin(kphi*phi)*cos(kphi*phi));
44 }
45 double dRP( double R, double Z, double phi) const{
46 return exp((R-R_0)/a)*exp(Z/a)*(-2.*kphi*sin(kphi*phi)*cos(kphi*phi))/a;
47 }
48 double dZP( double R, double Z, double phi) const{
49 return exp((R-R_0)/a)*exp(Z/a)*(-2.*kphi*sin(kphi*phi)*cos(kphi*phi))/a;
50 }
51 double dPP( double R, double Z, double phi) const{
52 return exp((R-R_0)/a)*exp(Z/a)*kphi*kphi*(2.*sin(kphi*phi)*sin(kphi*phi)-2.*cos(kphi*phi)*cos(kphi*phi));
53 }
54 private:
55 double R_0, a, kphi;
56 TokamakMagneticField c_;
57};
58
59// (cos(M_PI*(R-R_0))+1)*(cos(M_PI*Z/2.)+1)*sin(phi);
60struct TestFunctionDirNeu{
61 TestFunctionDirNeu( const TokamakMagneticField& c){
62 R_0 = c.R0();
63 }
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);
66 }
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);
69 }
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);
72 }
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);
75 }
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);
78 }
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);
81 }
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);
84 }
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);
87 }
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);
90 }
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);
93 }
94 private:
95 double R_0;
96};
97
99// b \nabla f
100template<class Function>
101struct DsFunction
102{
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);
109 }
110 private:
111 Function f_;
112 TokamakMagneticField c_;
113 dg::geo::BHatR bhatR_;
114 dg::geo::BHatZ bhatZ_;
115 dg::geo::BHatP bhatP_;
116};
117//\nabla( b f)
118template<class Function>
119struct DsDivFunction
120{
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);
125 }
126 private:
127 Function f_;
128 DsFunction<Function> dsf_;
129 dg::geo::Divb divb_;
130};
131
132//2nd derivative \nabla_\parallel^2
133template<class Function>
134struct DssFunction
135{
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;
153 }
154 private:
155 Function f_;
156 TokamakMagneticField c_;
157 dg::geo::BHatR bhatR_;
158 dg::geo::BHatZ bhatZ_;
159 dg::geo::BHatP bhatP_;
160 dg::geo::BHatRR bhatRR_;
161 dg::geo::BHatZR bhatZR_;
162 dg::geo::BHatPR bhatPR_;
163 dg::geo::BHatRZ bhatRZ_;
164 dg::geo::BHatZZ bhatZZ_;
165 dg::geo::BHatPZ bhatPZ_;
166};
167
168//positive Laplacian \Delta_\parallel
169template<class Function>
170struct DsDivDsFunction
171{
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);
175 }
176 private:
177 DsFunction<Function> dsf_;
178 DssFunction<Function> dssf_;
179 dg::geo::Divb divb_;
180};
181
182//positive perp Laplacian \Delta_\perp
183template<class Function>
184struct DPerpFunction
185{
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);
189 }
190 private:
191 Function f_;
192 DsDivDsFunction<Function> dsf_;
193};
194
195template<class Function>
196struct OMDsDivDsFunction
197{
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);
201 }
202 private:
203 Function f_;
204 DsDivDsFunction<Function> df_;
205};
206
207template<class Function>
208struct Variation
209{
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));
213 }
214 private:
215 Function f_;
216};
217
219// b \nabla f
220template<class Function>
221struct ToroidalDsFunction
222{
223 ToroidalDsFunction( const TokamakMagneticField& c, Function f): f_(f), c_(c),
224 bhatR_(c), bhatZ_(c), bhatP_(c){}
225 double operator()(double R, double Z, double phi) const {
226 return bhatR_(R,Z)*f_.dR(R,Z,phi) +
227 bhatZ_(R,Z)*f_.dZ(R,Z,phi) +
228 bhatP_(R,Z)*f_.dP(R,Z,phi);
229 }
230 private:
231 Function f_;
232 TokamakMagneticField c_;
236};
237//\nabla( b f)
238template<class Function>
239struct ToroidalDsDivFunction
240{
241 ToroidalDsDivFunction( const TokamakMagneticField& c, Function f):
242 f_(f), dsf_(c,f), divb_(c){}
243 double operator()(double R, double Z, double phi) const {
244 return f_(R,Z,phi)*divb_(R,Z) + dsf_(R,Z,phi);
245 }
246 private:
247 Function f_;
248 ToroidalDsFunction<Function> dsf_;
250};
251
253struct ToroidalBHatRR: public aCylindricalFunctor<ToroidalBHatRR>
254{
255 ToroidalBHatRR( const TokamakMagneticField& mag): m_mag(mag){}
256 double do_compute( double R, double Z) const
257 {
258 double psipZ = m_mag.psipZ()(R,Z);
259 double psipRZ = m_mag.psipRZ()(R,Z);
260 double ipol = m_mag.ipol()(R,Z);
261 double ipolR = m_mag.ipolR()(R,Z);
262 return psipRZ/ipol - psipZ*ipolR/ipol/ipol;
263 }
264 private:
265 TokamakMagneticField m_mag;
266};
268struct ToroidalBHatRZ: public aCylindricalFunctor<ToroidalBHatRZ>
269{
270 ToroidalBHatRZ( const TokamakMagneticField& mag): m_mag(mag){}
271 double do_compute( double R, double Z) const
272 {
273 double psipZ = m_mag.psipZ()(R,Z);
274 double psipZZ = m_mag.psipZZ()(R,Z);
275 double ipol = m_mag.ipol()(R,Z);
276 double ipolZ = m_mag.ipolZ()(R,Z);
277 return psipZZ/ipol - psipZ*ipolZ/ipol/ipol;
278 }
279 private:
280 TokamakMagneticField m_mag;
281};
283struct ToroidalBHatZR: public aCylindricalFunctor<ToroidalBHatZR>
284{
285 ToroidalBHatZR( const TokamakMagneticField& mag): m_mag(mag){}
286 double do_compute( double R, double Z) const
287 {
288 double psipR = m_mag.psipR()(R,Z);
289 double psipRR = m_mag.psipRR()(R,Z);
290 double ipol = m_mag.ipol()(R,Z);
291 double ipolR = m_mag.ipolR()(R,Z);
292 return -psipRR/ipol + psipR*ipolR/ipol/ipol;
293 }
294 private:
295 TokamakMagneticField m_mag;
296};
298struct ToroidalBHatZZ: public aCylindricalFunctor<ToroidalBHatZZ>
299{
300 ToroidalBHatZZ( const TokamakMagneticField& mag): m_mag(mag){}
301 double do_compute( double R, double Z) const
302 {
303 double psipR = m_mag.psipR()(R,Z);
304 double psipRZ = m_mag.psipRZ()(R,Z);
305 double ipol = m_mag.ipol()(R,Z);
306 double ipolZ = m_mag.ipolZ()(R,Z);
307 return -psipRZ/ipol + psipR*ipolZ/ipol/ipol;
308 }
309 private:
310 TokamakMagneticField m_mag;
311};
313struct ToroidalBHatPR: public aCylindricalFunctor<ToroidalBHatPR>
314{
315 ToroidalBHatPR( const TokamakMagneticField& mag): m_mag(mag){ }
316 double do_compute( double R, double ) const
317 {
318 return -1/R/R;
319 }
320 private:
321 TokamakMagneticField m_mag;
322};
324struct ToroidalBHatPZ: public aCylindricalFunctor<ToroidalBHatPZ>
325{
326 ToroidalBHatPZ( const TokamakMagneticField& mag): m_mag(mag){ }
327 double do_compute( double , double ) const
328 {
329 return 0;
330 }
331 private:
332 TokamakMagneticField m_mag;
333};
334
335//2nd derivative \nabla_\parallel^2
336template<class Function>
337struct ToroidalDssFunction
338{
339 ToroidalDssFunction( TokamakMagneticField c, Function f):f_(f), c_(c),
340 bhatR_(c), bhatZ_(c), bhatP_(c),
341 bhatRR_(c), bhatZR_(c), bhatPR_(c),
342 bhatRZ_(c), bhatZZ_(c), bhatPZ_(c){}
343 double operator()(double R, double Z, double phi) const {
344 double bhatR = bhatR_(R,Z), bhatZ = bhatZ_(R,Z), bhatP = bhatP_(R,Z);
345 double bhatRR = bhatRR_(R,Z), bhatZR = bhatZR_(R,Z), bhatPR = bhatPR_(R,Z);
346 double bhatRZ = bhatRZ_(R,Z), bhatZZ = bhatZZ_(R,Z), bhatPZ = bhatPZ_(R,Z);
347 double fR = f_.dR(R,Z,phi), fZ = f_.dZ(R,Z,phi), fP = f_.dP(R,Z,phi);
348 double fRR = f_.dRR(R,Z,phi), fRZ = f_.dRZ(R,Z,phi), fZZ = f_.dZZ(R,Z,phi);
349 double fRP = f_.dRP(R,Z,phi), fZP = f_.dZP(R,Z,phi), fPP = f_.dPP(R,Z,phi);
350 double gradbhatR = bhatR*bhatRR+bhatZ*bhatRZ,
351 gradbhatZ = bhatR*bhatZR+bhatZ*bhatZZ,
352 gradbhatP = bhatR*bhatPR+bhatZ*bhatPZ;
353 return bhatR*bhatR*fRR + bhatZ*bhatZ*fZZ + bhatP*bhatP*fPP
354 +2.*(bhatR*bhatZ*fRZ + bhatR*bhatP*fRP + bhatZ*bhatP*fZP)
355 + gradbhatR*fR + gradbhatZ*fZ + gradbhatP*fP;
356 }
357 private:
358 Function f_;
359 TokamakMagneticField c_;
363 ToroidalBHatRR bhatRR_;
364 ToroidalBHatZR bhatZR_;
365 ToroidalBHatPR bhatPR_;
366 ToroidalBHatRZ bhatRZ_;
367 ToroidalBHatZZ bhatZZ_;
368 ToroidalBHatPZ bhatPZ_;
369};
370
371//positive Laplacian \Delta_\parallel
372template<class Function>
373struct ToroidalDsDivDsFunction
374{
375 ToroidalDsDivDsFunction( const TokamakMagneticField& c,Function f): dsf_(c,f), dssf_(c,f), divb_(c){}
376 double operator()(double R, double Z, double phi) const {
377 return divb_(R,Z)*dsf_(R,Z,phi) + dssf_(R,Z,phi);
378 }
379 private:
380 ToroidalDsFunction<Function> dsf_;
381 ToroidalDssFunction<Function> dssf_;
383};
384
385//positive perp Laplacian \Delta_\perp
386template<class Function>
387struct ToroidalDPerpFunction
388{
389 ToroidalDPerpFunction( const TokamakMagneticField& c, Function f): f_(f), dsf_(c,f){}
390 double operator()(double R, double Z, double phi) const {
391 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);
392 }
393 private:
394 Function f_;
395 ToroidalDsDivDsFunction<Function> dsf_;
396};
397
398template<class Function>
399struct ToroidalOMDsDivDsFunction
400{
401 ToroidalOMDsDivDsFunction( const TokamakMagneticField& c,Function f): f_(f), df_(c,f){}
402 double operator()(double R, double Z, double phi) const {
403 return f_(R,Z,phi)-df_(R,Z,phi);
404 }
405 private:
406 Function f_;
407 ToroidalDsDivDsFunction<Function> df_;
408};
409
411template<class DS, class container>
412void callDS( const DS& ds, std::string name, const container& in, container& out,
413unsigned max_iter = 1e4, double eps = 1e-6)
414{
415 if( name == "forward") ds.ds( dg::forward, in, out);
416 else if( name == "backward") ds.ds( dg::backward, in, out);
417 else if( name == "forward2") ds.forward2( 1., in, 0., out);
418 else if( name == "backward2") ds.backward2( 1., in, 0., out);
419 else if( name == "centered") ds.ds( dg::centered, in, out);
420 else if( name == "dss") ds.dss( in, out);
421 else if( name == "centered_bc_along")
422 ds.centered_bc_along_field( 1., in, 0., out, ds.fieldaligned().bcx(), {0,0});
423 else if( name == "dss_bc_along")
424 ds.dss_bc_along_field( 1., in, 0., out, ds.fieldaligned().bcx(), {0,0});
425 else if( name == "centered") ds.ds( dg::centered, in, out);
426 else if( name == "dss") ds.dss( in, out);
427 else if( name == "divForward") ds.div( dg::forward, in, out);
428 else if( name == "divBackward") ds.div( dg::backward, in, out);
429 else if( name == "divCentered") ds.div( dg::centered, in, out);
430 else if( name == "directLap") {
431 ds.dssd( 1., in, 0., out);
432 }
433 else if( name == "directLap_bc_along") {
434 ds.dssd_bc_along_field( 1., in, 0., out, ds.fieldaligned().bcx(), {0,0});
435 }
436 else if( name == "invCenteredLap"){
437 //dg::LGMRES<container> invert( in, 30,3,10000);
438 dg::BICGSTABl<container> invert( in, max_iter, 3);
439 dg::Timer t;
440 t.tic();
441 double precond = 1.;
442 unsigned number = invert.solve( [&](const auto& x, auto& y){
443 // y = ( 1 - D) x
444 dg::blas2::symv( ds, x, y);
445 dg::blas1::axpby( 1., x, -1., y, y);
446 }, out, in, precond, ds.weights(), eps);
447 t.toc();
448#ifdef MPI_VERSION
449 int rank;
450 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
451 if(rank==0)
452 {
453#endif //MPI
454 std::cout << "#Number of BICGSTABl iterations: "<<number<<"\n";
455 std::cout << "#Took : "<<t.diff()<<"\n";
456#ifdef MPI_VERSION
457 }
458#endif //MPI
459 return;
460 }
461
462}
464
465//psi * cos(theta)
466struct FuncDirPer
467{
468 FuncDirPer( const TokamakMagneticField& c, double psi_0, double psi_1, double k):
469 R_0_(c.R0()), psi0_(psi_0), psi1_(psi_1), k_(k), c_(c) {}
470 double operator()(double R, double Z) const {
471 double psip = c_.psip()(R,Z);
472 double result = (psip-psi0_)*(psip-psi1_)*cos(k_*theta(R,Z));
473 return 0.1*result;
474 }
475 double operator()(double R, double Z, double) const {
476 return operator()(R,Z);
477 }
478 double dR( double R, double Z)const
479 {
480 double psip = c_.psip()(R,Z), psipR = c_.psipR()(R,Z), theta_ = k_*theta(R,Z);
481 double result = (2.*psip*psipR - (psi0_+psi1_)*psipR)*cos(theta_)
482 - (psip-psi0_)*(psip-psi1_)*sin(theta_)*k_*thetaR(R,Z);
483 return 0.1*result;
484 }
485 double dRR( double R, double Z)const
486 {
487 double psip = c_.psip()(R,Z), psipR = c_.psipR()(R,Z), theta_=k_*theta(R,Z), thetaR_=k_*thetaR(R,Z);
488 double psipRR = c_.psipRR()(R,Z);
489 double result = (2.*(psipR*psipR + psip*psipRR) - (psi0_+psi1_)*psipRR)*cos(theta_)
490 - 2.*(2.*psip*psipR-(psi0_+psi1_)*psipR)*sin(theta_)*thetaR_
491 - (psip-psi0_)*(psip-psi1_)*(k_*thetaRR(R,Z)*sin(theta_)+cos(theta_)*thetaR_*thetaR_);
492 return 0.1*result;
493
494 }
495 double dZ( double R, double Z)const
496 {
497 double psip = c_.psip()(R,Z), psipZ = c_.psipZ()(R,Z), theta_=k_*theta(R,Z);
498 double result = (2*psip*psipZ - (psi0_+psi1_)*psipZ)*cos(theta_)
499 - (psip-psi0_)*(psip-psi1_)*sin(theta_)*k_*thetaZ(R,Z);
500 return 0.1*result;
501 }
502 double dZZ( double R, double Z)const
503 {
504 double psip = c_.psip()(R,Z), psipZ = c_.psipZ()(R,Z), theta_=k_*theta(R,Z), thetaZ_=k_*thetaZ(R,Z);
505 double psipZZ = c_.psipZZ()(R,Z);
506 double result = (2.*(psipZ*psipZ + psip*psipZZ) - (psi0_+psi1_)*psipZZ)*cos(theta_)
507 - 2.*(2.*psip*psipZ-(psi0_+psi1_)*psipZ)*sin(theta_)*thetaZ_
508 - (psip-psi0_)*(psip-psi1_)*(k_*thetaZZ(R,Z)*sin(theta_) + cos(theta_)*thetaZ_*thetaZ_ );
509 return 0.1*result;
510 }
511 private:
512 double theta( double R, double Z) const {
513 double dR = R-R_0_;
514 if( Z >= 0)
515 return acos( dR/sqrt( dR*dR + Z*Z));
516 else
517 return 2.*M_PI-acos( dR/sqrt( dR*dR + Z*Z));
518 }
519 double thetaR( double R, double Z) const {
520 double dR = R-R_0_;
521 return -Z/(dR*dR+Z*Z);
522 }
523 double thetaZ( double R, double Z) const {
524 double dR = R-R_0_;
525 return dR/(dR*dR+Z*Z);
526 }
527 double thetaRR( double R, double Z) const {
528 double dR = R-R_0_;
529 return 2*Z*dR/(dR*dR+Z*Z)/(dR*dR+Z*Z);
530 }
531 double thetaZZ( double R, double Z) const { return -thetaRR(R,Z);}
532 double R_0_;
533 double psi0_, psi1_, k_;
534 const TokamakMagneticField c_;
535};
536// Variation of FuncDirPer
537struct VariationDirPer
538{
539 VariationDirPer( dg::geo::TokamakMagneticField mag, double psi_0, double psi_1): m_f(mag, psi_0, psi_1,4. ){}
540 double operator()(double R, double Z, double) const {
541 return this->operator()(R,Z);}
542
543 double operator()(double R, double Z) const {
544 return m_f.dR( R,Z)*m_f.dR(R,Z) + m_f.dZ(R,Z)*m_f.dZ(R,Z);
545 }
546 private:
547 dg::geo::FuncDirPer m_f;
548};
549
550
551//takes the magnetic field as chi
552struct EllipticDirPerM
553{
554 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) {}
555 double operator()(double R, double Z, double) const {
556 return operator()(R,Z);}
557 double operator()(double R, double Z) const {
558 double bmod = bmod_(R,Z), br = br_(R,Z), bz = bz_(R,Z);
559 return -(br*func_.dR(R,Z) + bz*func_.dZ(R,Z) + bmod*(func_.dRR(R,Z) + func_.dZZ(R,Z) ));
560
561 }
562 private:
563 FuncDirPer func_;
564 dg::geo::Bmodule bmod_;
565 dg::geo::BR br_;
566 dg::geo::BZ bz_;
567};
568
569//Blob function
570struct FuncDirNeu
571{
572 FuncDirNeu( const TokamakMagneticField&, [[maybe_unused]] double psi_0, [[maybe_unused]] double psi_1, double R_blob, double Z_blob, double sigma_blob, double amp_blob):
573 //psi0_(psi_0), psi1_(psi_1),
574 cauchy_(R_blob, Z_blob, sigma_blob, sigma_blob, amp_blob){}
575
576 double operator()(double R, double Z, double) const {
577 return operator()(R,Z);}
578 double operator()(double R, double Z) const {
579 return cauchy_(R,Z);
580 //double psip = psip_(R,Z);
581 //return (psip-psi0_)*(psip-psi1_)+cauchy_(R,Z);
582 //return (psip-psi0_)*(psip-psi1_);
583 }
584 double dR( double R, double Z)const
585 {
586 return cauchy_.dx(R,Z);
587 //double psip = psip_(R,Z), psipR = psipR_(R,Z);
588 //return (2.*psip-psi0_-psi1_)*psipR + cauchy_.dx(R,Z);
589 //return (2.*psip-psi0_-psi1_)*psipR;
590 }
591 double dRR( double R, double Z)const
592 {
593 return cauchy_.dxx(R,Z);
594 //double psip = psip_(R,Z), psipR = psipR_(R,Z);
595 //double psipRR = psipRR_(R,Z);
596 //return (2.*(psipR*psipR + psip*psipRR) - (psi0_+psi1_)*psipRR)+cauchy_.dxx(R,Z);
597 //return (2.*(psipR*psipR + psip*psipRR) - (psi0_+psi1_)*psipRR);
598
599 }
600 double dZ( double R, double Z)const
601 {
602 return cauchy_.dy(R,Z);
603 //double psip = psip_(R,Z), psipZ = psipZ_(R,Z);
604 //return (2*psip-psi0_-psi1_)*psipZ+cauchy_.dy(R,Z);
605 //return (2*psip-psi0_-psi1_)*psipZ;
606 }
607 double dZZ( double R, double Z)const
608 {
609 return cauchy_.dyy(R,Z);
610 //double psip = psip_(R,Z), psipZ = psipZ_(R,Z);
611 //double psipZZ = psipZZ_(R,Z);
612 //return (2.*(psipZ*psipZ + psip*psipZZ) - (psi0_+psi1_)*psipZZ)+cauchy_.dyy(R,Z);
613 //return (2.*(psipZ*psipZ + psip*psipZZ) - (psi0_+psi1_)*psipZZ);
614 }
615 private:
616 //double psi0_, psi1_;
617 dg::Cauchy cauchy_;
618};
619
620
621//takes the magnetic field multiplied by (1+0.5sin(theta)) as chi
622struct BmodTheta
623{
624 BmodTheta( const TokamakMagneticField& c): R_0_(c.R0()), bmod_(c){}
625 double operator()(double R,double Z, double) const{
626 return operator()(R,Z);}
627 double operator()(double R,double Z) const{
628 return bmod_(R,Z)*(1.+0.5*sin(theta(R,Z)));
629 }
630 private:
631 double theta( double R, double Z) const {
632 double dR = R-R_0_;
633 if( Z >= 0)
634 return acos( dR/sqrt( dR*dR + Z*Z));
635 else
636 return 2.*M_PI-acos( dR/sqrt( dR*dR + Z*Z));
637 }
638 double R_0_;
639 dg::geo::Bmodule bmod_;
640
641};
642
643//take BmodTheta as chi
644struct EllipticDirNeuM
645{
646 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()),
647 func_(c, psi_0, psi_1, R_blob, Z_blob, sigma_blob,amp_blob), bmod_(c), br_(c), bz_(c) {}
648 double operator()(double R, double Z) const {
649 double bmod = bmod_(R,Z), br = br_(R,Z), bz = bz_(R,Z), theta_ = theta(R,Z);
650 double chi = bmod*(1.+0.5*sin(theta_));
651 double chiR = br*(1.+0.5*sin(theta_)) + bmod*0.5*cos(theta_)*thetaR(R,Z);
652 double chiZ = bz*(1.+0.5*sin(theta_)) + bmod*0.5*cos(theta_)*thetaZ(R,Z);
653 return -(chiR*func_.dR(R,Z) + chiZ*func_.dZ(R,Z) + chi*( func_.dRR(R,Z) + func_.dZZ(R,Z) ));
654
655 }
656 double operator()(double R, double Z, double) const {
657 return operator()(R,Z);
658 }
659 private:
660 double theta( double R, double Z) const {
661 double dR = R-R_0_;
662 if( Z >= 0)
663 return acos( dR/sqrt( dR*dR + Z*Z));
664 else
665 return 2.*M_PI-acos( dR/sqrt( dR*dR + Z*Z));
666 }
667 double thetaR( double R, double Z) const {
668 double dR = R-R_0_;
669 return -Z/(dR*dR+Z*Z);
670 }
671 double thetaZ( double R, double Z) const {
672 double dR = R-R_0_;
673 return dR/(dR*dR+Z*Z);
674 }
675 double R_0_;
676 FuncDirNeu func_;
677 dg::geo::Bmodule bmod_;
678 dg::geo::BR br_;
679 dg::geo::BZ bz_;
680};
681
682//the psi surfaces
683struct FuncXDirNeu
684{
685 FuncXDirNeu( const TokamakMagneticField& c, double psi_0, double psi_1):
686 c_(c), psi0_(psi_0), psi1_(psi_1){}
687
688 double operator()(double R, double Z, double) const {
689 return operator()(R,Z);}
690 double operator()(double R, double Z) const {
691 double psip = c_.psip()(R,Z);
692 return (psip-psi0_)*(psip-psi1_);
693 }
694 double dR( double R, double Z)const
695 {
696 double psip = c_.psip()(R,Z), psipR = c_.psipR()(R,Z);
697 return (2.*psip-psi0_-psi1_)*psipR;
698 }
699 double dRR( double R, double Z)const
700 {
701 double psip = c_.psip()(R,Z), psipR = c_.psipR()(R,Z);
702 double psipRR = c_.psipRR()(R,Z);
703 return (2.*(psipR*psipR + psip*psipRR) - (psi0_+psi1_)*psipRR);
704
705 }
706 double dZ( double R, double Z)const
707 {
708 double psip = c_.psip()(R,Z), psipZ = c_.psipZ()(R,Z);
709 return (2*psip-psi0_-psi1_)*psipZ;
710 }
711 double dZZ( double R, double Z)const
712 {
713 double psip = c_.psip()(R,Z), psipZ = c_.psipZ()(R,Z);
714 double psipZZ = c_.psipZZ()(R,Z);
715 return (2.*(psipZ*psipZ + psip*psipZZ) - (psi0_+psi1_)*psipZZ);
716 }
717 private:
718 TokamakMagneticField c_;
719 double psi0_, psi1_;
720};
721
722//take Bmod as chi
723struct EllipticXDirNeuM
724{
725 EllipticXDirNeuM( const TokamakMagneticField& c, double psi_0, double psi_1): R_0_(c.R0()),
726 func_(c, psi_0, psi_1), bmod_(c), br_(c), bz_(c) {}
727 double operator()(double R, double Z) const {
728 double bmod = bmod_(R,Z), br = br_(R,Z), bz = bz_(R,Z);
729 //double chi = 1e4+bmod; //bmod can be zero for a Taylor state(!)
730 double chi = bmod; //bmod for solovev state
731 double chiR = br;
732 double chiZ = bz;
733 return -(chiR*func_.dR(R,Z) + chiZ*func_.dZ(R,Z) + chi*( func_.dRR(R,Z) + func_.dZZ(R,Z) ));
734 //return -( func_.dRR(R,Z) + func_.dZZ(R,Z) );
735
736 }
737 double operator()(double R, double Z, double) const {
738 return operator()(R,Z);
739 }
740 private:
741 double R_0_;
742 FuncXDirNeu func_;
743 dg::geo::Bmodule bmod_;
744 dg::geo::BR br_;
745 dg::geo::BZ bz_;
746};
747
748//take Blob and chi=1
749struct EllipticBlobDirNeuM
750{
751 EllipticBlobDirNeuM( const TokamakMagneticField& c, double psi_0, double psi_1, double R_blob, double Z_blob, double sigma_blob, double amp_blob):
752 func_(c, psi_0, psi_1, R_blob, Z_blob, sigma_blob, amp_blob){}
753 double operator()(double R, double Z) const {
754 return -( func_.dRR(R,Z) + func_.dZZ(R,Z) );
755 }
756 double operator()(double R, double Z, double) const {
757 return operator()(R,Z);
758 }
759 private:
760 FuncDirNeu func_;
761};
762
763struct EllipticDirSimpleM
764{
765 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) {}
766 double operator()(double R, double Z, double) const {
767 return -(( 1./R*func_.dR(R,Z) + func_.dRR(R,Z) + func_.dZZ(R,Z) ));
768
769 }
770 private:
771 FuncDirNeu func_;
772};
773
776//
777} //namespace functors
778} //namespace dg
#define M_PI
void axpby(value_type alpha, const ContainerType1 &x, value_type1 beta, ContainerType &y)
void symv(MatrixType &&M, const ContainerType1 &x, ContainerType2 &y)
backward
centered
dg::SquareMatrix< T > invert(const dg::SquareMatrix< T > &in)
double diff() const
void toc()
void tic()
Definition magnetic_field.h:911
Definition magnetic_field.h:1095
Definition magnetic_field.h:1113
Definition magnetic_field.h:884
Definition magnetic_field.h:1029
Definition magnetic_field.h:1046
Definition magnetic_field.h:898
Definition magnetic_field.h:1062
Definition magnetic_field.h:1079
Definition magnetic_field.h:368
Definition magnetic_field.h:390
Definition magnetic_field.h:279
Definition magnetic_field.h:786
A tokamak field as given by R0, Psi and Ipol plus Meta-data like shape and equilibrium.
Definition magnetic_field.h:172
Definition magnetic_field.h:949
Definition magnetic_field.h:924
Definition magnetic_field.h:937
Definition magnetic_field.h:819