Extension: Geometries
#include "dg/geometries/geometries.h"
hector.h
Go to the documentation of this file.
1#pragma once
2
3#include <vector>
4#include "dg/algorithm.h"
5#include "fluxfunctions.h"
6#include "curvilinear.h"
7#include "flux.h"
8#include "adaption.h"
9
10
11
12namespace dg
13{
14namespace geo
15{
16
18namespace detail
19{
20
21//interpolate the two components of a vector field
22template<class real_type>
23struct Interpolate
24{
25 Interpolate( const thrust::host_vector<real_type>& fZeta,
26 const thrust::host_vector<real_type>& fEta,
27 const dg::aTopology2d& g2d ):
28 iter0_( dg::forward_transform( fZeta, g2d) ),
29 iter1_( dg::forward_transform( fEta, g2d) ),
30 g_(g2d), zeta1_(g2d.x1()), eta1_(g2d.y1()){}
31 void operator()(real_type t, const std::array<real_type,2>& zeta, std::array<real_type,2>& fZeta)
32 {
33 fZeta[0] = interpolate( dg::lspace, iter0_, fmod( zeta[0]+zeta1_, zeta1_), fmod( zeta[1]+eta1_, eta1_), g_);
34 fZeta[1] = interpolate( dg::lspace, iter1_, fmod( zeta[0]+zeta1_, zeta1_), fmod( zeta[1]+eta1_, eta1_), g_);
35 //fZeta[0] = interpolate( zeta[0], zeta[1], iter0_, g_);
36 //fZeta[1] = interpolate( zeta[0], zeta[1], iter1_, g_);
37 }
38 void operator()(real_type t, const std::array<thrust::host_vector<real_type>,2 >& zeta, std::array< thrust::host_vector<real_type>,2 >& fZeta)
39 {
40 for( unsigned i=0; i<zeta[0].size(); i++)
41 {
42 fZeta[0][i] = interpolate( dg::lspace, iter0_, fmod( zeta[0][i]+zeta1_, zeta1_), fmod( zeta[1][i]+eta1_, eta1_), g_);
43 fZeta[1][i] = interpolate( dg::lspace, iter1_, fmod( zeta[0][i]+zeta1_, zeta1_), fmod( zeta[1][i]+eta1_, eta1_), g_);
44 }
45 }
46 private:
47 thrust::host_vector<real_type> iter0_;
48 thrust::host_vector<real_type> iter1_;
50 real_type zeta1_, eta1_;
51};
52
53//compute c_0
54template<class real_type>
55real_type construct_c0( const thrust::host_vector<real_type>& etaVinv, const dg::aRealTopology2d<real_type>& g2d)
56{
57 //this is a normal integration:
58 thrust::host_vector<real_type> etaVinvL( dg::forward_transform( etaVinv, g2d) );
59 dg::Grid1d g1d( 0., 2.*M_PI, g2d.ny(), g2d.Ny());
61 dg::HVec w1d = dg::create::weights( g1d);
62 dg::HVec int_etaVinv(eta);
63 for( unsigned i=0; i<eta.size(); i++)
64 int_etaVinv[i] = interpolate( dg::lspace, etaVinvL, 0., eta[i], g2d);
65 real_type c0 = 2.*M_PI/dg::blas1::dot( w1d, int_etaVinv );
66 return c0;
67
68 //the following is too naiv (gives a slightly wrong result):
69 //the right way to do it is to integrate de/de=1, dv/de = f(e) because in only dv/de = f(e) our integrator assumes dv/de=f(v)
70 //Interpolate inter( thrust::host_vector<real_type>( etaVinv.size(), 0), etaVinv, g2d);
71 //thrust::host_vector<real_type> begin( 2, 0), end(begin), end_old(begin);
72 //begin[0] = 0, begin[1] = 0;
73 //real_type eps = 1e10, eps_old = 2e10;
74 //unsigned N = 5;
75 //while( (eps < eps_old || eps > 1e-7)&& eps > 1e-12)
76 //{
77 // eps_old = eps, end_old = end;
78 // N*=2; dg::stepperRK( "ARK-4-2-3 (explicit)", inter, 0., begin, 2*M_PI, end, N);
79 // eps = fabs( end[1]-end_old[1]);
80 // std::cout << "\t error eps "<<eps<<" with "<<N<<" steps: " << 2*M_PI/end[1]<<"\n";
81 // std::cout << "\t error c0 "<<fabs(c0-2.*M_PI/end[1])<<" with "<<N<<" steps: " << 2*M_PI/end[1]<<"\n";
82 //}
84 //real_type f_psi = 2.*M_PI/end_old[1];
85
86 //return f_psi;
87}
88
89
90//compute the vector of zeta and eta - values that form first v surface
91template<class real_type>
92void compute_zev(
93 const thrust::host_vector<real_type>& etaV,
94 const thrust::host_vector<real_type>& v_vec,
95 thrust::host_vector<real_type>& eta,
97 )
98{
99 Interpolate<real_type> iter( thrust::host_vector<real_type>( etaV.size(),
100 0), etaV, g2d);
101 eta.resize( v_vec.size());
102 thrust::host_vector<real_type> eta_old(v_vec.size(), 0), eta_diff( eta_old);
103 std::array<real_type,2> begin{ 0, 0}, end(begin), temp(begin);
104 begin[0] = 0., begin[1] = 0.;
105 unsigned steps = 1;
106 real_type eps = 1e10, eps_old=2e10;
107 using Vec = std::array<double,2>;
108 dg::SinglestepTimeloop<Vec> odeint( dg::RungeKutta<Vec>( "Feagin-17-8-10",
109 begin), iter);
110 while( (eps < eps_old||eps > 1e-7) && eps > 1e-12)
111 {
112 //begin is left const
113 eps_old = eps, eta_old = eta;
114 odeint.integrate_steps( 0, begin, v_vec[0], end, steps);
115 eta[0] = end[1];
116 for( unsigned i=1; i<v_vec.size(); i++)
117 {
118 temp = end;
119 odeint.integrate_steps( v_vec[i-1], temp, v_vec[i], end, steps);
120 eta[i] = end[1];
121 }
122 temp = end;
123 odeint.integrate_steps( v_vec[v_vec.size()-1], begin, 2.*M_PI, end, steps);
124 dg::blas1::axpby( 1., eta, -1., eta_old, eta_diff);
125 eps = dg::fast_l2norm( eta_diff)/dg::fast_l2norm( eta);
126 //std::cout << "rel. error is "<<eps<<" with "<<steps<<" steps\n";
127 //std::cout << "abs. error is "<<( 2.*M_PI-end[1])<<"\n";
128 steps*=2;
129 }
130}
131
132template<class real_type>
133void construct_grid(
134 const thrust::host_vector<real_type>& zetaU, //2d Zeta component
135 const thrust::host_vector<real_type>& etaU, //2d Eta component
136 const thrust::host_vector<real_type>& u_vec, //1d u values
137 const thrust::host_vector<real_type>& zeta_init, //1d intial values
138 const thrust::host_vector<real_type>& eta_init, //1d intial values
139 thrust::host_vector<real_type>& zeta,
140 thrust::host_vector<real_type>& eta,
142 )
143{
144 Interpolate<real_type> inter( zetaU, etaU, g2d);
145 unsigned N = 1;
146 real_type eps = 1e10, eps_old=2e10;
147 std::array<thrust::host_vector<real_type>,2 > begin;
148 begin[0] = zeta_init, begin[1] = eta_init;
149 //now we have the starting values
150 std::array<thrust::host_vector<real_type>,2 > end(begin), temp(begin);
151 unsigned sizeU = u_vec.size(), sizeV = zeta_init.size();
152 unsigned size2d = sizeU*sizeV;
153 zeta.resize(size2d), eta.resize(size2d);
154 real_type u0=0, u1 = u_vec[0];
155 thrust::host_vector<real_type> zeta_old(zeta), zeta_diff( zeta), eta_old(eta), eta_diff(eta);
156 using Vec = std::array<thrust::host_vector<real_type>,2>;
157 dg::SinglestepTimeloop<Vec> odeint( dg::RungeKutta<Vec>( "Feagin-17-8-10",
158 temp), inter);
159 while( (eps < eps_old || eps > 1e-6) && eps > 1e-7)
160 {
161 zeta_old = zeta, eta_old = eta; eps_old = eps;
162 temp = begin;
164 for( unsigned i=0; i<sizeU; i++)
165 {
166 u0 = i==0 ? 0 : u_vec[i-1], u1 = u_vec[i];
167 odeint.integrate_steps( u0, temp, u1, end, N);
168 for( unsigned j=0; j<sizeV; j++)
169 {
170 unsigned idx = j*sizeU+i;
171 zeta[idx] = end[0][j], eta[idx] = end[1][j];
172 }
173 temp = end;
174 }
175 dg::blas1::axpby( 1., zeta, -1., zeta_old, zeta_diff);
176 dg::blas1::axpby( 1., eta, -1., eta_old, eta_diff);
177 dg::blas1::pointwiseDot( zeta_diff, zeta_diff, zeta_diff);
178 dg::blas1::pointwiseDot( 1., eta_diff, eta_diff, 1., zeta_diff);
179 eps = sqrt( dg::blas1::dot( zeta_diff, zeta_diff)/sizeU/sizeV);
180 //std::cout << "Effective Absolute diff error is "<<eps<<" with "<<N<<" steps\n";
181 N*=2;
182 }
183
184}
185
186template< class Geometry, class container>
187void transform(
188 const container& u_zeta,
189 const container& u_eta,
190 thrust::host_vector<double>& u_x,
191 thrust::host_vector<double>& u_y,
192 const Geometry& g2d)
193{
194 u_x.resize( u_zeta.size()), u_y.resize( u_zeta.size());
195 thrust::host_vector<double> uh_zeta, uh_eta;
196 dg::assign( u_zeta, uh_zeta);
197 dg::assign( u_eta, uh_eta);
199 dg::tensor::multiply2d( jac.transpose(), uh_zeta, uh_eta, u_x, u_y);
200}
201
202}//namespace detail
204
219template <class IMatrix = dg::IHMatrix, class Matrix = dg::HMatrix, class container = dg::HVec>
220struct Hector : public aGenerator2d
221{
236 Hector( const CylindricalFunctorsLvl2& psi, double psi0, double psi1, double X0, double Y0, unsigned n = 13, unsigned Nx = 2, unsigned Ny = 10, double eps_u = 1e-10, bool verbose=false) :
237 m_g2d(dg::geo::RibeiroFluxGenerator(psi, psi0, psi1, X0, Y0,1), n, Nx, Ny, dg::DIR)
238 {
239 //first construct m_u
240 container u = construct_grid_and_u( dg::geo::Constant(1), dg::geo::detail::LaplacePsi(psi), psi0, psi1, X0, Y0, eps_u , verbose);
241 construct( u, psi0, psi1, dg::geo::Constant(1.), dg::geo::Constant(0.), dg::geo::Constant(1.), verbose);
242 m_conformal=m_orthogonal=true;
244 //container psi__;
245 //dg::assign(dg::pullback( psi, m_g2d), psi__);
246 //dg::blas1::axpby( +1., psi__, 1., u); //u = c0(\tilde u + \psi-\psi_0)
247 //dg::blas1::plus( u,-psi0);
248 //dg::blas1::scal( u, m_c0);
249 //dg::assign( u, m_u);
250 }
251
267 Hector( const CylindricalFunctorsLvl2& psi, const CylindricalFunctorsLvl1& chi, double psi0, double psi1, double X0, double Y0, unsigned n = 13, unsigned Nx = 2, unsigned Ny = 10, double eps_u = 1e-10, bool verbose=false) :
268 m_g2d(dg::geo::RibeiroFluxGenerator(psi, psi0, psi1, X0, Y0,1), n, Nx, Ny, dg::DIR)
269 {
270 dg::geo::detail::LaplaceAdaptPsi lapAdaPsi( psi, chi);
271 //first construct m_u
272 container u = construct_grid_and_u( chi.f(), lapAdaPsi, psi0, psi1, X0, Y0, eps_u , verbose);
273 construct( u, psi0, psi1, chi.f(),dg::geo::Constant(0), chi.f(), verbose );
274 m_orthogonal=true;
275 m_conformal=false;
277 //container psi__;
278 //dg::assign(dg::pullback( psi, m_g2d), psi__);
279 //dg::blas1::axpby( +1., psi__, 1., u); //u = c0(\tilde u + \psi-\psi_0)
280 //dg::blas1::plus( u,-psi0);
281 //dg::blas1::scal( u, m_c0);
282 //dg::assign( u, m_u);
283 }
284
301 double psi0, double psi1, double X0, double Y0, unsigned n = 13, unsigned Nx = 2, unsigned Ny = 10, double eps_u = 1e-10, bool verbose=false) :
302 m_g2d(dg::geo::RibeiroFluxGenerator(psi, psi0, psi1, X0, Y0,1), n, Nx, Ny, dg::DIR)
303 {
304 //first construct m_u
305 container u = construct_grid_and_u( psi, chi,
306 psi0, psi1, X0, Y0, eps_u , verbose);
307 construct( u, psi0, psi1, chi.xx(), chi.xy(), chi.yy(), verbose);
308 m_orthogonal=m_conformal=false;
310 //container psi__;
311 //dg::assign(dg::pullback( psi, m_g2d), psi__);
312 //dg::blas1::axpby( +1., psi__, 1., u); //u = c0(\tilde u + \psi-\psi_0)
313 //dg::blas1::plus( u,-psi0);
314 //dg::blas1::scal( u, m_c0);
315 //dg::assign( u, m_u);
316 }
317
318
324 const dg::geo::CurvilinearGrid2d& internal_grid() const {return m_g2d;}
325 virtual Hector* clone() const override final{return new Hector(*this);}
326 bool isConformal() const {return m_conformal;}
327 private:
328 virtual double do_width() const override final {return m_lu;}
329 virtual double do_height() const override final {return 2.*M_PI;}
335 virtual bool do_isOrthogonal() const override final {return m_orthogonal;}
336 virtual void do_generate( const thrust::host_vector<double>& u1d,
337 const thrust::host_vector<double>& v1d,
338 thrust::host_vector<double>& x,
339 thrust::host_vector<double>& y,
340 thrust::host_vector<double>& ux,
341 thrust::host_vector<double>& uy,
342 thrust::host_vector<double>& vx,
343 thrust::host_vector<double>& vy) const override final
344 {
345 thrust::host_vector<double> eta_init, zeta, eta;
346 detail::compute_zev( m_etaV, v1d, eta_init, m_g2d);
347 thrust::host_vector<double> zeta_init( eta_init.size(), 0.);
348 detail::construct_grid( m_zetaU, m_etaU, u1d, zeta_init, eta_init, zeta, eta, m_g2d);
349 //the box is periodic in eta and the y=0 line needs not to coincide with the eta=0 line
350 for( unsigned i=0; i<eta.size(); i++)
351 eta[i] = fmod(eta[i]+2.*M_PI, 2.*M_PI);
352 dg::IHMatrix Q = dg::create::interpolation( zeta, eta, m_g2d);
353
354 dg::blas2::symv( Q, m_g2d.map()[0], x);
355 dg::blas2::symv( Q, m_g2d.map()[1], y);
356 dg::blas2::symv( Q, m_ux, ux);
357 dg::blas2::symv( Q, m_uy, uy);
358 dg::blas2::symv( Q, m_vx, vx);
359 dg::blas2::symv( Q, m_vy, vy);
361 //thrust::host_vector<double> u(u1d.size()*v1d.size());
362 //dg::blas2::symv( Q, m_u, u);
363 //dg::HVec u2d(u1d.size()*v1d.size());
364 //for( unsigned i=0; i<v1d.size(); i++)
365 // for( unsigned j=0; j<u1d.size(); j++)
366 // u2d[i*u1d.size()+j] = u1d[j];
367 //dg::blas1::axpby( 1., u2d, -1., u);
368 //double eps = dg::blas1::dot( u,u);
369 //std::cout << "Error in u is "<<eps<<std::endl;
370 }
371
372 container construct_grid_and_u( const CylindricalFunctor& chi, const CylindricalFunctor& lapChiPsi, double psi0, double psi1, double X0, double Y0, double eps_u , bool verbose)
373 {
374 //first find u( \zeta, \eta)
375 double eps = 1e10, eps_old = 2e10;
376 dg::geo::CurvilinearGrid2d g2d_old = m_g2d;
377 container adapt = dg::pullback(chi, g2d_old);
379 ellipticD_old.set_chi( adapt);
380
381 container u_old = dg::evaluate( dg::zero, g2d_old), u(u_old);
382 dg::PCG<container > invert_old( u_old, g2d_old.size());
383 container lapu = dg::pullback( lapChiPsi, g2d_old);
384 unsigned number = invert_old.solve( ellipticD_old, u_old, lapu, ellipticD_old.precond(), ellipticD_old.weights(), eps_u);
385 if(verbose) std::cout << "Nx "<<m_g2d.Nx()<<" Ny "<<m_g2d.Ny()<<std::flush;
386 if(verbose) std::cout <<" iter "<<number<<" error "<<eps<<"\n";
387 while( (eps < eps_old||eps > 1e-7) && eps > eps_u)
388 {
389 eps = eps_old;
390 m_g2d.multiplyCellNumbers(2,2);
391 if(verbose) std::cout << "Nx "<<m_g2d.Nx()<<" Ny "<<m_g2d.Ny()<<std::flush;
393 adapt = dg::pullback(chi, m_g2d);
394 ellipticD.set_chi( adapt);
395 const container vol2d = dg::create::weights( m_g2d);
396 const IMatrix Q = dg::create::interpolation( m_g2d, g2d_old);
397 container u_diff = dg::evaluate( dg::zero, m_g2d);
398 dg::blas2::gemv( Q, u_old, u_diff);
399 u = u_diff;
400
401 dg::PCG<container > invert( u_diff, m_g2d.size());
402 lapu = dg::pullback( lapChiPsi, m_g2d);
403 number = invert.solve( ellipticD, u, lapu, ellipticD.precond(), ellipticD.weights(), 0.1*eps_u);
404 dg::blas1::axpby( 1. ,u, -1., u_diff);
405 eps = sqrt( dg::blas2::dot( u_diff, vol2d, u_diff) / dg::blas2::dot( u, vol2d, u) );
406 if(verbose) std::cout <<" iter "<<number<<" error "<<eps<<"\n";
407 g2d_old = m_g2d;
408 u_old = u;
409 number++;//get rid of warning
410 }
411 return u;
412 }
413
414 container construct_grid_and_u( const CylindricalFunctorsLvl2& psi,
415 const CylindricalSymmTensorLvl1& chi, double psi0, double psi1, double X0, double Y0, double eps_u, bool verbose )
416 {
417 dg::geo::detail::LaplaceChiPsi lapChiPsi( psi, chi);
418 //first find u( \zeta, \eta)
419 double eps = 1e10, eps_old = 2e10;
420 dg::geo::CurvilinearGrid2d g2d_old = m_g2d;
423 dg::pushForwardPerp( chi.xx(), chi.xy(), chi.yy(), chi_t, g2d_old);
424
425 ellipticD_old.set_chi( chi_t);
426
427 container u_old = dg::evaluate( dg::zero, g2d_old), u(u_old);
428 dg::PCG<container > invert_old( u_old, g2d_old.size());
429 container lapu = dg::pullback( lapChiPsi, g2d_old);
430 unsigned number = invert_old.solve( ellipticD_old, u_old, lapu, ellipticD_old.precond(), ellipticD_old.weights(), eps_u);
431 while( (eps < eps_old||eps > 1e-7) && eps > eps_u)
432 {
433 eps = eps_old;
434 m_g2d.multiplyCellNumbers(2,2);
435 if(verbose) std::cout << "Nx "<<m_g2d.Nx()<<" Ny "<<m_g2d.Ny()<<std::flush;
437 dg::pushForwardPerp( chi.xx(), chi.xy(), chi.yy(), chi_t, m_g2d);
438
439 ellipticD.set_chi( chi_t );
440 const container vol2d = dg::create::weights( m_g2d);
441 const IMatrix Q = dg::create::interpolation( m_g2d, g2d_old);
442 container u_diff = dg::evaluate( dg::zero, m_g2d);
443 dg::blas2::gemv( Q, u_old, u_diff);
444 u = u_diff;
445
446 dg::PCG<container > invert( u_diff, m_g2d.size());
447 lapu = dg::pullback( lapChiPsi, m_g2d);
448 number = invert.solve( ellipticD, u, lapu, ellipticD.precond(), ellipticD.weights(), 0.1*eps_u);
449 dg::blas1::axpby( 1. ,u, -1., u_diff);
450 eps = sqrt( dg::blas2::dot( u_diff, vol2d, u_diff) / dg::blas2::dot( u, vol2d, u) );
451 if(verbose) std::cout <<" iter "<<number<<" error "<<eps<<"\n";
452 g2d_old = m_g2d;
453 u_old = u;
454 number++;//get rid of warning
455 }
456 return u;
457 }
458
459 void construct(const container& u, double psi0, double psi1, const CylindricalFunctor& chi_XX, const CylindricalFunctor& chi_XY, const CylindricalFunctor& chi_YY, bool verbose)
460 {
461 //now compute u_zeta and u_eta
462 Matrix dzeta = dg::create::dx( m_g2d, dg::DIR);
463 Matrix deta = dg::create::dy( m_g2d, dg::PER);
464 container u_zeta(u), u_eta(u);
465 dg::blas2::symv( dzeta, u, u_zeta);
466 dg::blas1::plus( u_zeta, (psi1-psi0)/m_g2d.lx());
467 dg::blas2::symv( deta, u, u_eta);
468
469
470
472 dg::pushForwardPerp( chi_XX, chi_XY, chi_YY, chi, m_g2d);
473
474 //now compute ZetaU and EtaU
475 container temp_zeta(u), temp_eta(u);
476 dg::tensor::multiply2d( chi, u_zeta, u_eta, temp_zeta, temp_eta);
477 container temp_scalar(u);
478 dg::blas1::pointwiseDot( 1., u_eta, temp_eta, 1., u_zeta, temp_zeta, 0., temp_scalar);
479 container zetaU=temp_zeta, etaU=temp_eta;
480 dg::blas1::pointwiseDivide( zetaU, temp_scalar, zetaU);
481 dg::blas1::pointwiseDivide( etaU, temp_scalar, etaU);
482
483 //now compute etaV and its inverse
484 container etaVinv(u_zeta), etaV(etaVinv);
485 container perp_vol = dg::tensor::volume(m_g2d.metric());
486 dg::blas1::pointwiseDot( 1., u_zeta, perp_vol, chi.value(0,0), 0., etaVinv);
487 dg::blas1::transform( etaVinv, etaV, dg::INVERT<double>());
488 thrust::host_vector<double> etaVinv_h;
489 dg::assign( etaVinv, etaVinv_h);
490 //now compute v_zeta and v_eta
491 container v_zeta(u), v_eta(u);
492 dg::blas1::axpby( -1., temp_eta, 0.,v_zeta);
493 dg::blas1::axpby( +1., temp_zeta, 0.,v_eta);
494 dg::blas1::pointwiseDot( v_zeta, perp_vol, v_zeta);
495 dg::blas1::pointwiseDot( v_eta, perp_vol, v_eta);
496
497 //construct c0 and scale all vector components with it
498 m_c0 = fabs( detail::construct_c0( etaVinv_h, m_g2d));
499 if( psi1 < psi0) m_c0*=-1;
500 m_lu = m_c0*(psi1-psi0);
501 if(verbose) std::cout << "c0 is "<<m_c0<<"\n";
502 dg::blas1::scal( etaV, 1./m_c0);
503 dg::blas1::scal( zetaU, 1./m_c0);
504 dg::blas1::scal( etaU, 1./m_c0);
505 dg::blas1::scal( u_zeta, m_c0);
506 dg::blas1::scal( v_zeta, m_c0);
507 dg::blas1::scal( u_eta, m_c0);
508 dg::blas1::scal( v_eta, m_c0);
509 //transfer to host
510 detail::transform( u_zeta, u_eta, m_ux, m_uy, m_g2d);
511 detail::transform( v_zeta, v_eta, m_vx, m_vy, m_g2d);
512 dg::assign( etaV, m_etaV);
513 dg::assign( etaU, m_etaU);
514 dg::assign( zetaU, m_zetaU);
515 }
516 private:
517 bool m_conformal, m_orthogonal;
518 double m_c0, m_lu;
519 thrust::host_vector<double> m_ux, m_uy, m_vx, m_vy;
520 thrust::host_vector<double> m_etaV, m_zetaU, m_etaU;
522
523};
524
525}//namespace geo
526}//namespace dg
#define M_PI
void assign(const from_ContainerType &from, ContainerType &to, Params &&... ps)
static DG_DEVICE double cooX1d(double x)
static DG_DEVICE double zero(double x)
void plus(ContainerType &x, get_value_type< ContainerType > alpha)
void transform(const ContainerType1 &x, ContainerType &y, UnaryOp op)
void axpby(get_value_type< ContainerType > alpha, const ContainerType1 &x, get_value_type< ContainerType > beta, ContainerType &y)
void scal(ContainerType &x, get_value_type< ContainerType > alpha)
void pointwiseDivide(get_value_type< ContainerType > alpha, const ContainerType1 &x1, const ContainerType2 &x2, 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)
get_value_type< ContainerType1 > dot(const ContainerType1 &x, const ContainerType2 &y)
void gemv(get_value_type< ContainerType1 > alpha, MatrixType &&M, const ContainerType1 &x, get_value_type< ContainerType1 > beta, ContainerType2 &y)
void symv(MatrixType &&M, const ContainerType1 &x, ContainerType2 &y)
get_value_type< MatrixType > dot(const ContainerType1 &x, const MatrixType &m, const ContainerType2 &y)
EllSparseBlockMat< real_type > dx(const aRealTopology2d< real_type > &g, bc bcx, direction dir=centered)
EllSparseBlockMat< real_type > dy(const aRealTopology2d< real_type > &g, bc bcy, direction dir=centered)
centered
dg::Operator< T > invert(const dg::Operator< T > &in)
thrust::host_vector< real_type > evaluate(UnaryOp f, const RealGrid1d< real_type > &g)
RealCylindricalFunctor< double > CylindricalFunctor
Most of the times we use double.
Definition: fluxfunctions.h:50
MPI_Vector< thrust::host_vector< real_type > > weights(const aRealMPITopology2d< real_type > &g)
cusp::coo_matrix< int, real_type, cusp::host_memory > interpolation(const thrust::host_vector< real_type > &x, const RealGrid1d< real_type > &g, dg::bc bcx=dg::NEU, std::string method="dg")
real_type interpolate(dg::space sp, const thrust::host_vector< real_type > &v, real_type x, const RealGrid1d< real_type > &g, dg::bc bcx=dg::NEU)
thrust::host_vector< real_type > forward_transform(const thrust::host_vector< real_type > &in, const aRealTopology2d< real_type > &g)
thrust::host_vector< real_type > pullback(const Functor &f, const aRealGeometryX2d< real_type > &g)
void pushForwardPerp(const Functor1 &vR, const Functor2 &vZ, container &vx, container &vy, const Geometry &g)
void multiply2d(const ContainerTypeL &lambda, const SparseTensor< ContainerType0 > &t, const ContainerType1 &in0, const ContainerType2 &in1, const ContainerTypeM &mu, ContainerType3 &out0, ContainerType4 &out1)
ContainerType volume(const SparseTensor< ContainerType > &t)
static auto fast_l2norm
IHMatrix_t< double > IHMatrix
thrust::host_vector< double > HVec
SparseTensor transpose() const
const container & value(size_t i, size_t j) const
std::vector< thrust::host_vector< real_type > > map() const
SparseTensor< thrust::host_vector< real_type > > metric() const
unsigned ny() const
void multiplyCellNumbers(real_type fx, real_type fy)
unsigned size() const
real_type lx() const
unsigned Nx() const
unsigned Ny() const
Definition: fluxfunctions.h:114
This struct bundles a function and its first derivatives.
Definition: fluxfunctions.h:182
const CylindricalFunctor & f() const
Definition: fluxfunctions.h:203
This struct bundles a function and its first and second derivatives.
Definition: fluxfunctions.h:219
Definition: fluxfunctions.h:361
const CylindricalFunctor & yy() const
yy component
Definition: fluxfunctions.h:400
const CylindricalFunctor & xy() const
xy component
Definition: fluxfunctions.h:398
const CylindricalFunctor & xx() const
xy component
Definition: fluxfunctions.h:396
The High PrEcision Conformal grid generaTOR.
Definition: hector.h:221
bool isConformal() const
Definition: hector.h:326
Hector(const CylindricalFunctorsLvl2 &psi, const CylindricalFunctorsLvl1 &chi, double psi0, double psi1, double X0, double Y0, unsigned n=13, unsigned Nx=2, unsigned Ny=10, double eps_u=1e-10, bool verbose=false)
Construct an orthogonal grid with adaption.
Definition: hector.h:267
const dg::geo::CurvilinearGrid2d & internal_grid() const
Return the internally used orthogonal grid.
Definition: hector.h:324
Hector(const CylindricalFunctorsLvl2 &psi, double psi0, double psi1, double X0, double Y0, unsigned n=13, unsigned Nx=2, unsigned Ny=10, double eps_u=1e-10, bool verbose=false)
Construct a conformal grid.
Definition: hector.h:236
virtual Hector * clone() const override final
Abstract clone method that returns a copy on the heap.
Definition: hector.h:325
Hector(const CylindricalFunctorsLvl2 &psi, const CylindricalSymmTensorLvl1 &chi, double psi0, double psi1, double X0, double Y0, unsigned n=13, unsigned Nx=2, unsigned Ny=10, double eps_u=1e-10, bool verbose=false)
Construct a curvilinear grid with monitor metric.
Definition: hector.h:300
Same as the Ribeiro class just but uses psi as a flux label directly.
Definition: flux.h:238
The abstract generator base class.
Definition: generator.h:20