25template<
class real_type>
26void computeX_rzy(
const CylindricalFunctorsLvl1& psi,
27 const thrust::host_vector<real_type>& y_vec,
28 const unsigned nodeX0,
const unsigned nodeX1,
29 thrust::host_vector<real_type>& r,
30 thrust::host_vector<real_type>& z,
31 const real_type* R_init,
const real_type* Z_init,
33 int mode,
bool verbose =
false )
35 thrust::host_vector<real_type> r_old(y_vec.size(), 0), r_diff( r_old);
36 thrust::host_vector<real_type> z_old(y_vec.size(), 0), z_diff( z_old);
37 r.resize( y_vec.size()),
z.resize(y_vec.size());
38 std::array<real_type,2> begin{ {0,0} }, end(begin), temp(begin);
39 begin[0] = R_init[0], begin[1] = Z_init[0];
40 dg::geo::ribeiro::FieldRZY fieldRZYconf(psi);
41 dg::geo::equalarc::FieldRZY fieldRZYequi(psi);
42 fieldRZYconf.set_f(f_psi);
43 fieldRZYequi.set_f(f_psi);
44 unsigned steps = 1; real_type eps = 1e10, eps_old=2e10;
45 using Vec = std::array<real_type,2>;
53 while( (eps < eps_old||eps > 1e-7) && eps > 1e-11)
55 eps_old = eps, r_old = r, z_old =
z;
59 begin[0] = R_init[1], begin[1] = Z_init[1];
61 r[nodeX0-1] = end[0],
z[nodeX0-1] = end[1];
63 for(
int i=nodeX0-2; i>=0; i--)
67 r[i] = end[0],
z[i] = end[1];
70 begin[0] = R_init[0], begin[1] = Z_init[0];
72 r[nodeX0] = end[0],
z[nodeX0] = end[1];
73 for(
unsigned i=nodeX0+1; i<nodeX1; i++)
77 r[i] = end[0],
z[i] = end[1];
81 eps = sqrt( (end[0]-R_init[0])*(end[0]-R_init[0]) + (end[1]-Z_init[0])*(end[1]-Z_init[0]));
82 if(verbose)std::cout <<
"abs. error is "<<eps<<
" with "<<steps<<
" steps\n";
86 begin[0] = R_init[1], begin[1] = Z_init[1];
88 r[nodeX1] = end[0],
z[nodeX1] = end[1];
90 for(
unsigned i=nodeX1+1; i<y_vec.size(); i++)
94 r[i] = end[0],
z[i] = end[1];
103 eps = sqrt( er + ez)/sqrt(ar+az);
104 if(verbose)std::cout <<
"rel. error is "<<eps<<
" with "<<steps<<
" steps\n";
107 r = r_old,
z = z_old;
122 SimpleOrthogonalX(): f0_(1), firstline_(0){}
123 SimpleOrthogonalX(
const CylindricalFunctorsLvl2& psi,
double psi_0,
124 double xX,
double yX,
double x0,
double y0,
int firstline =0): psi_(psi)
126 firstline_ = firstline;
127 orthogonal::detail::Fpsi fpsi(psi_, CylindricalSymmTensorLvl1(), x0, y0, firstline);
129 f0_ = fpsi.construct_f( psi_0, R0, Z0);
131 dg::geo::orthogonal::detail::InitialX initX(psi_, xX, yX);
132 initX.find_initial(psi_0, R0_, Z0_);
134 virtual SimpleOrthogonalX* clone()const override final{
return new SimpleOrthogonalX(*
this);}
136 bool isConformal()
const{
return false;}
137 virtual bool do_isOrthogonal()const override final{
return true;}
138 double f0()
const{
return f0_;}
139 virtual void do_generate(
140 const thrust::host_vector<double>& zeta1d,
141 const thrust::host_vector<double>& eta1d,
142 unsigned nodeX0,
unsigned nodeX1,
143 thrust::host_vector<double>& x,
144 thrust::host_vector<double>& y,
145 thrust::host_vector<double>& zetaX,
146 thrust::host_vector<double>& zetaY,
147 thrust::host_vector<double>& etaX,
148 thrust::host_vector<double>& etaY)
const override final
151 thrust::host_vector<double> r_init, z_init;
152 orthogonal::detail::computeX_rzy( psi_, eta1d, nodeX0, nodeX1, r_init, z_init, R0_, Z0_, f0_, firstline_);
153 dg::geo::orthogonal::detail::Nemov nemov(psi_, CylindricalSymmTensorLvl1(), f0_, firstline_);
154 thrust::host_vector<double> h;
155 orthogonal::detail::construct_rz(nemov, zeta0_, zeta1d, r_init, z_init, x, y, h);
156 unsigned size =
x.size();
157 zetaX.resize(size), zetaY.resize(size),
158 etaX.resize(size), etaY.resize(size);
159 for(
unsigned idx=0; idx<size; idx++)
161 double psipR = psi_.dfx()(
x[idx],
y[idx]);
162 double psipZ = psi_.dfy()(
x[idx],
y[idx]);
163 zetaX[idx] = f0_*psipR;
164 zetaY[idx] = f0_*psipZ;
165 etaX[idx] = -h[idx]*psipZ;
166 etaY[idx] = +h[idx]*psipR;
169 virtual double do_zeta0(
double fx)
const override final{
return zeta0_; }
170 virtual double do_zeta1(
double fx)
const override final{
return -fx/(1.-fx)*zeta0_;}
171 virtual double do_eta0(
double fy)
const override final{
return -2.*
M_PI*fy/(1.-2.*fy); }
172 virtual double do_eta1(
double fy)
const override final{
return 2.*
M_PI*(1.+fy/(1.-2.*fy));}
173 CylindricalFunctorsLvl2 psi_;
174 double R0_[2], Z0_[2];
207 double xX,
double yX,
double x0,
double y0,
int firstline,
bool verbose =
false ):
208 psi_(psi), chi_(chi),
209 sep_( psi, chi, xX, yX, x0, y0, firstline, verbose)
211 firstline_ = firstline;
217 bool isConformal()
const{
return false;}
218 virtual bool do_isOrthogonal()const override final{
return false;}
219 double f0()
const{
return sep_.get_f();}
220 virtual void do_generate(
221 const thrust::host_vector<double>& zeta1d,
222 const thrust::host_vector<double>& eta1d,
223 unsigned nodeX0,
unsigned nodeX1,
224 thrust::host_vector<double>& x,
225 thrust::host_vector<double>& y,
226 thrust::host_vector<double>& zetaX,
227 thrust::host_vector<double>& zetaY,
228 thrust::host_vector<double>& etaX,
229 thrust::host_vector<double>& etaY)
const override final
232 thrust::host_vector<double> r_init, z_init;
233 sep_.compute_rzy( eta1d, nodeX0, nodeX1, r_init, z_init);
234 dg::geo::orthogonal::detail::Nemov nemov(psi_, chi_, f0_, firstline_);
238 for(
unsigned i=0; i<zeta1d.size(); i++)
239 if( zeta1d[i]< 0) inside++;
240 thrust::host_vector<double> zeta1dI( inside, 0), zeta1dO( zeta1d.size() - inside, 0);
241 for(
unsigned i=0; i<inside; i++)
242 zeta1dI[i] = zeta1d[ inside-1-i];
243 for(
unsigned i=inside; i<zeta1d.size(); i++)
244 zeta1dO[i-inside] = zeta1d[ i];
247 thrust::host_vector<int> idxC, idxF;
248 thrust::host_vector<double> r_initC, r_initF, z_initC, z_initF;
249 for(
unsigned i=0; i<eta1d.size(); i++)
251 if( fabs(eta1d[i]) < 0.05 || fabs( eta1d[i] - 2.*M_PI) < 0.05)
254 r_initC.push_back( r_init[i]);
255 z_initC.push_back( z_init[i]);
260 r_initF.push_back( r_init[i]);
261 z_initF.push_back( z_init[i]);
265 thrust::host_vector<double> xIC, yIC, hIC, xOC,yOC,hOC;
266 thrust::host_vector<double> xIF, yIF, hIF, xOF,yOF,hOF;
267 orthogonal::detail::construct_rz(nemov, 0., zeta1dI, r_initC, z_initC,
269 orthogonal::detail::construct_rz(nemov, 0., zeta1dO, r_initC, z_initC,
271 orthogonal::detail::construct_rz(nemov, 0., zeta1dI, r_initF, z_initF,
273 orthogonal::detail::construct_rz(nemov, 0., zeta1dO, r_initF, z_initF,
276 thrust::host_vector<double> xI(inside*eta1d.size()), xO( (zeta1d.size()-inside)*eta1d.size());
277 thrust::host_vector<double> yI(xI), hI(xI), yO(xO),hO(xO);
278 for(
unsigned i=0; i<idxC.size(); i++)
279 for(
unsigned j=0; j<zeta1dI.size(); j++)
281 xI[idxC[i]*zeta1dI.size() + j] = xIC[i*zeta1dI.size() + j];
282 yI[idxC[i]*zeta1dI.size() + j] = yIC[i*zeta1dI.size() + j];
283 hI[idxC[i]*zeta1dI.size() + j] = hIC[i*zeta1dI.size() + j];
285 for(
unsigned i=0; i<idxF.size(); i++)
286 for(
unsigned j=0; j<zeta1dI.size(); j++)
288 xI[idxF[i]*zeta1dI.size() + j] = xIF[i*zeta1dI.size() + j];
289 yI[idxF[i]*zeta1dI.size() + j] = yIF[i*zeta1dI.size() + j];
290 hI[idxF[i]*zeta1dI.size() + j] = hIF[i*zeta1dI.size() + j];
292 for(
unsigned i=0; i<idxC.size(); i++)
293 for(
unsigned j=0; j<zeta1dO.size(); j++)
295 xO[idxC[i]*zeta1dO.size() + j] = xOC[i*zeta1dO.size() + j];
296 yO[idxC[i]*zeta1dO.size() + j] = yOC[i*zeta1dO.size() + j];
297 hO[idxC[i]*zeta1dO.size() + j] = hOC[i*zeta1dO.size() + j];
299 for(
unsigned i=0; i<idxF.size(); i++)
300 for(
unsigned j=0; j<zeta1dO.size(); j++)
302 xO[idxF[i]*zeta1dO.size() + j] = xOF[i*zeta1dO.size() + j];
303 yO[idxF[i]*zeta1dO.size() + j] = yOF[i*zeta1dO.size() + j];
304 hO[idxF[i]*zeta1dO.size() + j] = hOF[i*zeta1dO.size() + j];
308 unsigned size = zeta1d.size()*eta1d.size();
309 x.resize( size);
y.resize( size);
310 thrust::host_vector<double> h(size);
311 for(
unsigned i=0; i<eta1d.size(); i++)
312 for(
unsigned j=0; j<inside; j++)
314 x[i*zeta1d.size()+j] = xI[i*zeta1dI.size() + inside-1-j];
315 y[i*zeta1d.size()+j] = yI[i*zeta1dI.size() + inside-1-j];
316 h[i*zeta1d.size()+j] = hI[i*zeta1dI.size() + inside-1-j];
318 for(
unsigned i=0; i<eta1d.size(); i++)
319 for(
unsigned j=inside; j<zeta1d.size(); j++)
321 x[i*zeta1d.size()+j] = xO[i*zeta1dO.size() + j-inside];
322 y[i*zeta1d.size()+j] = yO[i*zeta1dO.size() + j-inside];
323 h[i*zeta1d.size()+j] = hO[i*zeta1dO.size() + j-inside];
326 zetaX.resize(size), zetaY.resize(size),
327 etaX.resize(size), etaY.resize(size);
328 for(
unsigned idx=0; idx<size; idx++)
330 double psipX = psi_.
dfx()(
x[idx],
y[idx]);
331 double psipY = psi_.
dfy()(
x[idx],
y[idx]);
332 double chiXX = chi_.
xx()(
x[idx],
y[idx]),
333 chiXY = chi_.
xy()(
x[idx],
y[idx]),
334 chiYY = chi_.
yy()(
x[idx],
y[idx]);
335 zetaX[idx] = f0_*psipX;
336 zetaY[idx] = f0_*psipY;
337 etaX[idx] = -h[idx]*(chiXY*psipX + chiYY*psipY);
338 etaY[idx] = +h[idx]*(chiXX*psipX + chiXY*psipY);
341 virtual double do_zeta0(
double fx)
const override final{
return f0_*psi_0_; }
342 virtual double do_zeta1(
double fx)
const override final{
return -fx/(1.-fx)*f0_*psi_0_;}
343 virtual double do_eta0(
double fy)
const override final{
return -2.*
M_PI*fy/(1.-2.*fy); }
344 virtual double do_eta1(
double fy)
const override final{
return 2.*
M_PI*(1.+fy/(1.-2.*fy));}
348 CylindricalFunctorsLvl2 psi_;
349 CylindricalSymmTensorLvl1 chi_;
350 dg::geo::detail::SeparatriX sep_;
366 double xX,
double yX,
double x0,
double y0,
int firstline,
bool verbose =
false,
double fx = 0 ):
368 m_sep( psi, chi, psi_0, xX, yX, x0, y0, firstline, verbose) { }
371 virtual double do_width() const override final{
374 virtual double do_height() const override final{
return 2.*
M_PI;}
375 virtual bool do_isOrthogonal()const override final{
return false;}
376 virtual void do_generate(
377 const thrust::host_vector<double>& zeta1d,
378 const thrust::host_vector<double>& eta1d,
379 thrust::host_vector<double>& x,
380 thrust::host_vector<double>& y,
381 thrust::host_vector<double>& zetaX,
382 thrust::host_vector<double>& zetaY,
383 thrust::host_vector<double>& etaX,
384 thrust::host_vector<double>& etaY)
const override final
386 double zeta0 = m_sep.
zeta0(m_fx);
387 auto zeta1d_trafo(zeta1d);
389 for(
unsigned i=0; i<zeta1d.size(); i++)
390 zeta1d_trafo[i] += zeta0;
392 throw dg::Error(
dg::Message(_ping_) <<
"Size of zeta1d "<<zeta1d.size()<<
"is not divisable by fx "<<m_fx);
393 m_sep.
generate( zeta1d_trafo, eta1d, 0, eta1d.size(), x, y, zetaX, zetaY, etaX, etaY);
396 SeparatrixOrthogonal m_sep;
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)
bool is_divisable(double a, double b, double eps=1e-15)
dg::geo::aRealGeneratorX2d< double > aGeneratorX2d
Definition: generatorX.h:93
void construct(Params &&...ps)
void integrate_steps(value_type t0, const container_type &u0, value_type t1, container_type &u1, unsigned steps)
This struct bundles a function and its first and second derivatives.
Definition: fluxfunctions.h:219
const CylindricalFunctor & dfy() const
Definition: fluxfunctions.h:247
const CylindricalFunctor & dfx() const
Definition: fluxfunctions.h:245
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
An Adaptor to use SeparatrixOrthogonal as aGenerator2d instead of aGeneratorX2d.
Definition: separatrix_orthogonal.h:360
SeparatrixOrthogonalAdaptor(const CylindricalFunctorsLvl2 &psi, const CylindricalSymmTensorLvl1 &chi, double psi_0, double xX, double yX, double x0, double y0, int firstline, bool verbose=false, double fx=0)
Construct.
Definition: separatrix_orthogonal.h:365
virtual SeparatrixOrthogonalAdaptor * clone() const override final
Abstract clone method that returns a copy on the heap.
Definition: separatrix_orthogonal.h:369
Choose points on separatrix and construct grid from there.
Definition: separatrix_orthogonal.h:192
virtual SeparatrixOrthogonal * clone() const override final
Abstract clone method that returns a copy on the heap.
Definition: separatrix_orthogonal.h:215
SeparatrixOrthogonal(const CylindricalFunctorsLvl2 &psi, const CylindricalSymmTensorLvl1 &chi, double psi_0, double xX, double yX, double x0, double y0, int firstline, bool verbose=false)
Construct.
Definition: separatrix_orthogonal.h:206
The abstract generator base class.
Definition: generator.h:20
The abstract generator base class.
Definition: generatorX.h:19
real_type zeta0(real_type fx) const
Definition: generatorX.h:20
real_type zeta1(real_type fx) const
Definition: generatorX.h:21
void generate(const thrust::host_vector< real_type > &zeta1d, const thrust::host_vector< real_type > &eta1d, unsigned nodeX0, unsigned nodeX1, thrust::host_vector< real_type > &x, thrust::host_vector< real_type > &y, thrust::host_vector< real_type > &zetaX, thrust::host_vector< real_type > &zetaY, thrust::host_vector< real_type > &etaX, thrust::host_vector< real_type > &etaY) const
Generate grid points and elements of the Jacobian.
Definition: generatorX.h:43