Extension: Geometries
#include "dg/geometries/geometries.h"
fluxfunctions.h
Go to the documentation of this file.
1#pragma once
2#include <functional>
3#include "dg/algorithm.h"
4
5namespace dg
6{
7namespace geo
8{
9
12
24template<class real_type>
26{
34 template<class BinaryFunctor>
35 RealCylindricalFunctor( BinaryFunctor f):
36 m_f(f) {}
38 real_type operator()( real_type R, real_type Z) const{
39 return m_f(R,Z);
40 }
42 real_type operator()( real_type R, real_type Z, real_type phi) const{
43 return m_f(R,Z);
44 }
45 private:
46 std::function<real_type(real_type,real_type)> m_f;
47};
48
51
64template<class Derived>
66{
75 double operator()(double R, double Z) const
76 {
77 const Derived& underlying = static_cast<const Derived&>(*this);
78 return underlying.do_compute(R,Z);
79 }
89 double operator()(double R, double Z, double phi)const
90 {
91 const Derived& underlying = static_cast<const Derived&>(*this);
92 return underlying.do_compute(R,Z);
93 }
94#ifndef __CUDACC__ //nvcc below 10 has problems with the following construct
95 //This trick avoids that classes inherit from the wrong Base:
96 private:
97 friend Derived;
102 aCylindricalFunctor(const aCylindricalFunctor&){}
106 aCylindricalFunctor& operator=(const aCylindricalFunctor&){return *this;}
107#endif //__CUDACC__
108};
109
113struct Constant: public aCylindricalFunctor<Constant>
114{
115 Constant(double c):c_(c){}
116 double do_compute(double R,double Z)const{return c_;}
117 private:
118 double c_;
119};
129struct ZCutter : public aCylindricalFunctor<ZCutter>
130{
131 ZCutter(double ZX, int sign = +1): m_heavi( ZX, sign){}
132 double do_compute(double R, double Z) const {
133 return m_heavi(Z);
134 }
135 private:
136 dg::Heaviside m_heavi;
137};
138
143struct Periodify : public aCylindricalFunctor<Periodify>
144{
151 Periodify( CylindricalFunctor functor, dg::Grid2d g): m_g( g), m_f(functor) {}
163 Periodify( CylindricalFunctor functor, double R0, double R1, double Z0, double Z1, dg::bc bcx, dg::bc bcy): m_g( R0, R1, Z0, Z1, 3, 10, 10, bcx, bcy), m_f(functor) {}
164 double do_compute( double R, double Z) const
165 {
166 bool negative = false;
167 m_g.shift( negative, R, Z);
168 if( negative) return -m_f(R,Z);
169 return m_f( R, Z);
170 }
171 private:
172 dg::Grid2d m_g;
174};
175
182{
193 CylindricalFunctor fy) : p_{{ f, fx, fy}} {
194 }
197 {
198 p_[0] = f;
199 p_[1] = fx;
200 p_[2] = fy;
201 }
203 const CylindricalFunctor& f()const{return p_[0];}
205 const CylindricalFunctor& dfx()const{return p_[1];}
207 const CylindricalFunctor& dfy()const{return p_[2];}
208 private:
209 std::array<CylindricalFunctor,3> p_;
210};
211
212
219{
231 f0(f,fx,fy), f1(fxx,fxy,fyy)
232 { }
237 {
238 f0.reset( f,fx,fy), f1.reset(fxx,fxy,fyy);
239 }
241 operator CylindricalFunctorsLvl1 ()const {return f0;}
243 const CylindricalFunctor& f()const{return f0.f();}
245 const CylindricalFunctor& dfx()const{return f0.dfx();}
247 const CylindricalFunctor& dfy()const{return f0.dfy();}
249 const CylindricalFunctor& dfxx()const{return f1.f();}
251 const CylindricalFunctor& dfxy()const{return f1.dfx();}
253 const CylindricalFunctor& dfyy()const{return f1.dfy();}
254 private:
256};
257
258
275static inline int findCriticalPoint( const CylindricalFunctorsLvl2& psi, double& RC, double& ZC)
276{
277 std::array<double, 2> X{ {0,0} }, XN(X), X_OLD(X);
278 X[0] = RC, X[1] = ZC;
279 double eps = 1e10, eps_old= 2e10;
280 unsigned counter = 0; //safety measure to avoid deadlock
281 double psipRZ = psi.dfxy()(X[0], X[1]);
282 double psipRR = psi.dfxx()(X[0], X[1]), psipZZ = psi.dfyy()(X[0],X[1]);
283 double psipR = psi.dfx()(X[0], X[1]), psipZ = psi.dfy()(X[0], X[1]);
284 double D0 = (psipZZ*psipRR - psipRZ*psipRZ);
285 if(D0 == 0) // try to change initial guess slightly if we are very lucky
286 {
287 X[0] *= 1.0001, X[1]*=1.0001;
288 psipRZ = psi.dfxy()(X[0], X[1]);
289 psipRR = psi.dfxx()(X[0], X[1]), psipZZ = psi.dfyy()(X[0],X[1]);
290 psipR = psi.dfx()(X[0], X[1]), psipZ = psi.dfy()(X[0], X[1]);
291 D0 = (psipZZ*psipRR - psipRZ*psipRZ);
292 }
293 double Dinv = 1./D0;
294 while( (eps < eps_old || eps > 1e-7) && eps > 1e-10 && counter < 100)
295 {
296 //newton iteration
297 XN[0] = X[0] - Dinv*(psipZZ*psipR - psipRZ*psipZ);
298 XN[1] = X[1] - Dinv*(-psipRZ*psipR + psipRR*psipZ);
299 XN.swap(X);
300 eps = sqrt( (X[0]-X_OLD[0])*(X[0]-X_OLD[0]) + (X[1]-X_OLD[1])*(X[1]-X_OLD[1]));
301 X_OLD = X; eps_old= eps;
302 psipRZ = psi.dfxy()(X[0], X[1]);
303 psipRR = psi.dfxx()(X[0], X[1]), psipZZ = psi.dfyy()(X[0],X[1]);
304 psipR = psi.dfx()(X[0], X[1]), psipZ = psi.dfy()(X[0], X[1]);
305 D0 = (psipZZ*psipRR - psipRZ*psipRZ);
306 Dinv = 1./D0;
307 if( D0 == 0) break;
308 counter++;
309 }
310 if ( counter >= 100 || D0 == 0|| std::isnan( Dinv) )
311 return 0;
312 RC = X[0], ZC = X[1];
313 if( Dinv > 0 && psipRR > 0)
314 return 1; //local minimum
315 if( Dinv > 0 && psipRR < 0)
316 return 2; //local maximum
317 //if( Dinv < 0)
318 return 3; //saddle point
319}
320
332static inline int findOpoint( const CylindricalFunctorsLvl2& psi, double& RC, double& ZC)
333{
334 int point = findCriticalPoint( psi, RC, ZC);
335 if( point == 3 || point == 0 )
336 throw dg::Error(dg::Message(_ping_)<<"There is no O-point near "<<RC<<" "<<ZC);
337 return point;
338}
339
350static inline void findXpoint( const CylindricalFunctorsLvl2& psi, double& RC, double& ZC)
351{
352 int point = findCriticalPoint( psi, RC, ZC);
353 if( point != 3)
354 throw dg::Error(dg::Message(_ping_)<<"There is no X-point near "<<RC<<" "<<ZC);
355}
356
357
361{
366 reset( Constant(1), Constant(0), Constant(1), Constant(0), Constant(0));
367 }
380 CylindricalFunctor divChiX, CylindricalFunctor divChiY) :
381 p_{{ chi_xx,chi_xy,chi_yy,divChiX,divChiY}}
382 {
383 }
387 CylindricalFunctor divChiY)
388 {
389 p_[0] = chi_xx;
390 p_[1] = chi_xy;
391 p_[2] = chi_yy;
392 p_[3] = divChiX;
393 p_[4] = divChiY;
394 }
396 const CylindricalFunctor& xx()const{return p_[0];}
398 const CylindricalFunctor& xy()const{return p_[1];}
400 const CylindricalFunctor& yy()const{return p_[2];}
402 const CylindricalFunctor& divX()const{return p_[3];}
404 const CylindricalFunctor& divY()const{return p_[4];}
405 private:
406 std::array<CylindricalFunctor,5> p_;
407};
408
412{
417 CylindricalFunctor v_z): p_{{v_x, v_y, v_z}}{}
421 {
422 p_[0] = v_x;
423 p_[1] = v_y;
424 p_[2] = v_z;
425 }
427 const CylindricalFunctor& x()const{return p_[0];}
429 const CylindricalFunctor& y()const{return p_[1];}
431 const CylindricalFunctor& z()const{return p_[2];}
432 private:
433 std::array<CylindricalFunctor,3> p_;
434};
435
440{
448 CylindricalFunctor divvvz
449 ): f0{v_x, v_y, v_z},
450 m_div(div), m_divvvz(divvvz) {}
456 CylindricalFunctor divvvz
457 )
458 {
459 f0.reset( v_x,v_y,v_z);
460 m_div = div;
461 m_divvvz = divvvz;
462 }
464 operator CylindricalVectorLvl0 ()const {return f0;}
466 const CylindricalFunctor& x()const{return f0.x();}
468 const CylindricalFunctor& y()const{return f0.y();}
470 const CylindricalFunctor& z()const{return f0.z();}
472 const CylindricalFunctor& div()const{return m_div;}
474 const CylindricalFunctor& divvvz()const{return m_divvvz;}
475 private:
477 CylindricalFunctor m_div, m_divvvz;
478};
479
483struct ScalarProduct : public aCylindricalFunctor<ScalarProduct>
484{
486 double do_compute( double R, double Z) const
487 {
488 return m_v.x()(R,Z)*m_w.x()(R,Z)
489 + m_v.y()(R,Z)*m_w.y()(R,Z)
490 + m_v.z()(R,Z)*m_w.z()(R,Z);
491 }
492 private:
493 CylindricalVectorLvl0 m_v, m_w;
494};
495
501struct SquareNorm : public aCylindricalFunctor<SquareNorm>
502{
504 double do_compute( double R, double Z) const
505 {
506 return sqrt(m_s(R,Z));
507 }
508 private:
509 ScalarProduct m_s;
510};
511
512
524template<class Geometry3d>
526 const dg::geo::CylindricalVectorLvl0& bhat, const Geometry3d& g)
527{
528 using host_vector = dg::get_host_vector<Geometry3d>;
530 std::array<host_vector,3> bt;
531 dg::pushForward( bhat.x(), bhat.y(), bhat.z(), bt[0], bt[1], bt[2], g);
532 std::vector<host_vector> chi(6, dg::evaluate( dg::zero,g));
533 dg::blas1::pointwiseDot( bt[0], bt[0], chi[0]);
534 dg::blas1::pointwiseDot( bt[0], bt[1], chi[1]);
535 dg::blas1::pointwiseDot( bt[0], bt[2], chi[2]);
536 dg::blas1::pointwiseDot( bt[1], bt[1], chi[3]);
537 dg::blas1::pointwiseDot( bt[1], bt[2], chi[4]);
538 dg::blas1::pointwiseDot( bt[2], bt[2], chi[5]);
539 t.idx(0,0) = 0, t.idx(0,1) = t.idx(1,0) = 1,
540 t.idx(0,2) = t.idx(2,0) = 2;
541 t.idx(1,1) = 3, t.idx(1,2) = t.idx(2,1) = 4;
542 t.idx(2,2) = 5;
543 t.values() = chi;
544 return t;
545}
557template<class Geometry3d>
559 const dg::geo::CylindricalVectorLvl0& bhat, const Geometry3d& g)
560{
561 using host_vector = dg::get_host_vector<Geometry3d>;
563 dg::SparseTensor<host_vector> m = g.metric();
564 dg::blas1::axpby( 1., m.value(0,0), -1., t.values()[0]);
565 dg::blas1::axpby( 1., m.value(0,1), -1., t.values()[1]);
566 dg::blas1::axpby( 1., m.value(0,2), -1., t.values()[2]);
567 dg::blas1::axpby( 1., m.value(1,1), -1., t.values()[3]);
568 dg::blas1::axpby( 1., m.value(1,2), -1., t.values()[4]);
569 dg::blas1::axpby( 1., m.value(2,2), -1., t.values()[5]);
570 return t;
571}
572
574}//namespace geo
575}//namespace dg
#define _ping_
static DG_DEVICE double zero(double x)
void axpby(get_value_type< ContainerType > alpha, const ContainerType1 &x, get_value_type< ContainerType > beta, ContainerType &y)
void pointwiseDot(get_value_type< ContainerType > alpha, const ContainerType1 &x1, const ContainerType2 &x2, get_value_type< ContainerType > beta, ContainerType &y)
thrust::host_vector< real_type > evaluate(UnaryOp f, const RealGrid1d< real_type > &g)
dg::SparseTensor< dg::get_host_vector< Geometry3d > > createAlignmentTensor(const dg::geo::CylindricalVectorLvl0 &bhat, const Geometry3d &g)
Definition: fluxfunctions.h:525
dg::SparseTensor< dg::get_host_vector< Geometry3d > > createProjectionTensor(const dg::geo::CylindricalVectorLvl0 &bhat, const Geometry3d &g)
Definition: fluxfunctions.h:558
static void findXpoint(const CylindricalFunctorsLvl2 &psi, double &RC, double &ZC)
This function finds X-points of psi.
Definition: fluxfunctions.h:350
static int findCriticalPoint(const CylindricalFunctorsLvl2 &psi, double &RC, double &ZC)
This function finds critical points of psi (any point with vanishing gradient, including the X-point ...
Definition: fluxfunctions.h:275
static int findOpoint(const CylindricalFunctorsLvl2 &psi, double &RC, double &ZC)
This function finds O-points of psi.
Definition: fluxfunctions.h:332
void pushForward(const Functor1 &vR, const Functor2 &vZ, const Functor3 &vPhi, container &vx, container &vy, container &vz, const Geometry &g)
int idx(unsigned i, unsigned j) const
std::vector< container > & values()
const container & value(size_t i, size_t j) const
void shift(bool &negative, real_type &x, real_type &y) const
Definition: fluxfunctions.h:114
double do_compute(double R, double Z) const
Definition: fluxfunctions.h:116
Constant(double c)
Definition: fluxfunctions.h:115
This struct bundles a function and its first derivatives.
Definition: fluxfunctions.h:182
void reset(CylindricalFunctor f, CylindricalFunctor fx, CylindricalFunctor fy)
copy given functors
Definition: fluxfunctions.h:196
CylindricalFunctorsLvl1(CylindricalFunctor f, CylindricalFunctor fx, CylindricalFunctor fy)
Construct with given functors.
Definition: fluxfunctions.h:192
const CylindricalFunctor & dfx() const
Definition: fluxfunctions.h:205
const CylindricalFunctor & f() const
Definition: fluxfunctions.h:203
const CylindricalFunctor & dfy() const
Definition: fluxfunctions.h:207
CylindricalFunctorsLvl1()
the access functions are undefined as long as the class remains empty
Definition: fluxfunctions.h:184
This struct bundles a function and its first and second derivatives.
Definition: fluxfunctions.h:219
const CylindricalFunctor & dfxy() const
Definition: fluxfunctions.h:251
const CylindricalFunctor & dfy() const
Definition: fluxfunctions.h:247
CylindricalFunctorsLvl2(CylindricalFunctor f, CylindricalFunctor fx, CylindricalFunctor fy, CylindricalFunctor fxx, CylindricalFunctor fxy, CylindricalFunctor fyy)
Construct with given functors.
Definition: fluxfunctions.h:228
CylindricalFunctorsLvl2()
the access functions are undefined as long as the class remains empty
Definition: fluxfunctions.h:221
const CylindricalFunctor & dfx() const
Definition: fluxfunctions.h:245
const CylindricalFunctor & dfxx() const
Definition: fluxfunctions.h:249
void reset(CylindricalFunctor f, CylindricalFunctor fx, CylindricalFunctor fy, CylindricalFunctor fxx, CylindricalFunctor fxy, CylindricalFunctor fyy)
Replace with given Functors.
Definition: fluxfunctions.h:234
const CylindricalFunctor & f() const
Definition: fluxfunctions.h:243
const CylindricalFunctor & dfyy() const
Definition: fluxfunctions.h:253
Definition: fluxfunctions.h:361
void reset(CylindricalFunctor chi_xx, CylindricalFunctor chi_xy, CylindricalFunctor chi_yy, CylindricalFunctor divChiX, CylindricalFunctor divChiY)
replace with given functors
Definition: fluxfunctions.h:385
const CylindricalFunctor & yy() const
yy component
Definition: fluxfunctions.h:400
const CylindricalFunctor & divY() const
is the y-component of the divergence of the tensor
Definition: fluxfunctions.h:404
CylindricalSymmTensorLvl1(CylindricalFunctor chi_xx, CylindricalFunctor chi_xy, CylindricalFunctor chi_yy, CylindricalFunctor divChiX, CylindricalFunctor divChiY)
Copy given functors.
Definition: fluxfunctions.h:378
CylindricalSymmTensorLvl1()
Initialize with the identity tensor.
Definition: fluxfunctions.h:365
const CylindricalFunctor & xy() const
xy component
Definition: fluxfunctions.h:398
const CylindricalFunctor & divX() const
is the x-component of the divergence of the tensor
Definition: fluxfunctions.h:402
const CylindricalFunctor & xx() const
xy component
Definition: fluxfunctions.h:396
Definition: fluxfunctions.h:412
const CylindricalFunctor & z() const
z-component of the vector
Definition: fluxfunctions.h:431
CylindricalVectorLvl0(CylindricalFunctor v_x, CylindricalFunctor v_y, CylindricalFunctor v_z)
Copy given Functors.
Definition: fluxfunctions.h:415
const CylindricalFunctor & y() const
y-component of the vector
Definition: fluxfunctions.h:429
void reset(CylindricalFunctor v_x, CylindricalFunctor v_y, CylindricalFunctor v_z)
replace with given functors
Definition: fluxfunctions.h:419
const CylindricalFunctor & x() const
x-component of the vector
Definition: fluxfunctions.h:427
CylindricalVectorLvl0()
Definition: fluxfunctions.h:413
This struct bundles a vector field and its divergence.
Definition: fluxfunctions.h:440
void reset(CylindricalFunctor v_x, CylindricalFunctor v_y, CylindricalFunctor v_z, CylindricalFunctor div, CylindricalFunctor divvvz)
replace with given functors
Definition: fluxfunctions.h:452
const CylindricalFunctor & y() const
y-component of the vector
Definition: fluxfunctions.h:468
const CylindricalFunctor & x() const
x-component of the vector
Definition: fluxfunctions.h:466
const CylindricalFunctor & div() const
Definition: fluxfunctions.h:472
CylindricalVectorLvl1(CylindricalFunctor v_x, CylindricalFunctor v_y, CylindricalFunctor v_z, CylindricalFunctor div, CylindricalFunctor divvvz)
Copy given Functors.
Definition: fluxfunctions.h:444
const CylindricalFunctor & divvvz() const
Definition: fluxfunctions.h:474
const CylindricalFunctor & z() const
z-component of the vector
Definition: fluxfunctions.h:470
CylindricalVectorLvl1()
the access functions are undefined as long as the class remains empty
Definition: fluxfunctions.h:442
This function uses the dg::Grid2d::shift member to extend another function beyond the grid boundaries...
Definition: fluxfunctions.h:144
Periodify(CylindricalFunctor functor, dg::Grid2d g)
Construct from grid.
Definition: fluxfunctions.h:151
Periodify(CylindricalFunctor functor, double R0, double R1, double Z0, double Z1, dg::bc bcx, dg::bc bcy)
provide 2d grid boundaries by hand
Definition: fluxfunctions.h:163
double do_compute(double R, double Z) const
Definition: fluxfunctions.h:164
Inject both 2d and 3d operator() to a 2d functor.
Definition: fluxfunctions.h:26
RealCylindricalFunctor()
Definition: fluxfunctions.h:27
real_type operator()(real_type R, real_type Z, real_type phi) const
Definition: fluxfunctions.h:42
real_type operator()(real_type R, real_type Z) const
Definition: fluxfunctions.h:38
RealCylindricalFunctor(BinaryFunctor f)
Construct from any binary functor.
Definition: fluxfunctions.h:35
Return scalar product of two vector fields .
Definition: fluxfunctions.h:484
double do_compute(double R, double Z) const
Definition: fluxfunctions.h:486
ScalarProduct(CylindricalVectorLvl0 v, CylindricalVectorLvl0 w)
Definition: fluxfunctions.h:485
Return norm of scalar product of two vector fields .
Definition: fluxfunctions.h:502
SquareNorm(CylindricalVectorLvl0 v, CylindricalVectorLvl0 w)
Definition: fluxfunctions.h:503
double do_compute(double R, double Z) const
Definition: fluxfunctions.h:504
Definition: fluxfunctions.h:130
double do_compute(double R, double Z) const
Definition: fluxfunctions.h:132
ZCutter(double ZX, int sign=+1)
Definition: fluxfunctions.h:131
Represent functions written in cylindrical coordinates that are independent of the angle phi serving ...
Definition: fluxfunctions.h:66
double operator()(double R, double Z) const
do_compute(R,Z)
Definition: fluxfunctions.h:75
double operator()(double R, double Z, double phi) const
do_compute(R,Z)
Definition: fluxfunctions.h:89