22 FpsiX(
const CylindricalFunctorsLvl1& psi,
double xX,
double yX,
double x0,
double y0):
23 initX_(psi, xX, yX), fieldRZYT_(psi, x0, y0), fieldRZYZ_(psi)
26 void find_initial(
double psi,
double* R_0,
double* Z_0)
28 initX_.find_initial(psi, R_0, Z_0);
32 double construct_f(
double psi,
double* R_i,
double* Z_i)
34 find_initial( psi, R_i, Z_i);
38 std::array<double, 3> begin{ {0,0,0} }, end(begin), end_old(begin);
39 begin[0] = R_i[0], begin[1] = Z_i[0];
41 double eps = 1e10, eps_old = 2e10;
44 using Vec = std::array<double,3>;
46 "Feagin-17-8-10", begin), fieldRZYT_);;
47 while( (eps < eps_old || eps > 1e-7) && N < 1e6)
50 eps_old = eps, end_old = end;
56 odeintT.integrate_steps( 0., begin, 2.*M_PI, end, N);
58 eps = sqrt( (end[0]-begin[0])*(end[0]-begin[0]) + (end[1]-begin[1])*(end[1]-begin[1]));
63 "Feagin-17-8-10", begin), fieldRZYZ_);;
64 odeintZ.integrate_steps( begin[1], begin, 0., end, N);
65 std::array<double,3> temp(end);
66 odeintT.integrate_steps( 0., begin, M_PI, end, N);
68 odeintZ.integrate_steps( temp[1], temp, Z_i[1], end, N);
69 eps = sqrt( (end[0]-R_i[1])*(end[0]-R_i[1]) + (end[1]-Z_i[1])*(end[1]-Z_i[1]));
71 if( std::isnan(eps)) { eps = eps_old/2.; end = end_old;
78 double f_psi = 2.*
M_PI/end_old[2];
83 double operator()(
double psi)
85 double R_0[2], Z_0[2];
86 return construct_f( psi, R_0, Z_0);
94 double find_x(
double psi )
97 double x0 = 0, x0_old = 0;
98 double eps=1e10, eps_old=2e10;
100 while( (eps < eps_old||eps>1e-7) && P < 20 )
102 eps_old = eps; x0_old = x0;
116 thrust::host_vector<double> f_vec(grid.size(), 0);
118 for(
unsigned i=0; i<psi_vec.size(); i++)
120 f_vec[i] = this->operator()( psi_vec[i]);
128 eps = fabs((x0 - x0_old)/x0);
129 if( std::isnan(eps)) { std::cerr <<
"Attention!!\n"; eps = eps_old -1e-15; x0 = x0_old;}
130 std::cout <<
"X = "<<-x0<<
" rel. error "<<eps<<
" with "<<P<<
" polynomials\n";
136 double f_prime(
double psi)
139 double deltaPsi = fabs(psi)/100.;
141 fofpsi[1] = operator()(psi-deltaPsi);
142 fofpsi[2] = operator()(psi+deltaPsi);
143 double fprime = (-0.5*fofpsi[1]+0.5*fofpsi[2])/deltaPsi, fprime_old;
144 double eps = 1e10, eps_old=2e10;
145 while( eps < eps_old || eps > 1e-7)
150 fofpsi[0] = fofpsi[1], fofpsi[3] = fofpsi[2];
151 fofpsi[1] = operator()(psi-deltaPsi);
152 fofpsi[2] = operator()(psi+deltaPsi);
154 fprime = (+ 1./12.*fofpsi[0]
159 eps = fabs((fprime - fprime_old)/fprime);
165 dg::geo::orthogonal::detail::InitialX initX_;
166 const dg::geo::ribeiro::FieldRZYT fieldRZYT_;
167 const dg::geo::ribeiro::FieldRZYZ fieldRZYZ_;
174 XFieldFinv(
const CylindricalFunctorsLvl1& psi,
double xX,
double yX,
double x0,
double y0,
unsigned N_steps = 500):
175 fpsi_(psi, xX, yX, x0, y0), fieldRZYT_(psi, x0, y0), fieldRZYZ_(psi) , N_steps(N_steps)
176 { xAtOne_ = fpsi_.find_x(0.1); }
177 void operator()(
double ttt,
double psi,
double& fpsiM)
179 std::array<double, 3> begin{ {0,0,0} }, end(begin);
180 double R_i[2], Z_i[2];
183 fpsi_.find_initial( psi, R_i, Z_i);
187 begin[0] = R_i[0], begin[1] = Z_i[0];
188 unsigned N = N_steps;
189 using Vec = std::array<double,3>;
191 "Feagin-17-8-10", begin), fieldRZYT_);;
192 if( psi < -1. && psi > -2.) N*=2;
193 if( psi < 0 && psi > -1.) N*=10;
195 odeintT.integrate_steps( 0., begin, 2.*M_PI, end, N);
199 "Feagin-17-8-10", begin), fieldRZYZ_);;
200 odeintZ.integrate_steps( begin[1], begin, 0., end, N);
201 std::array<double,3> temp(end);
202 odeintT.integrate_steps( 0., temp, M_PI, end, N/2);
204 odeintZ.integrate_steps( temp[1], temp, Z_i[1], end, N);
207 fpsiM = end[2]/2./
M_PI;
213 double find_psi(
double x)
218 double begin( 0.1), end(begin), end_old(begin);
219 double eps = 1e10, eps_old = 2e10;
221 while( eps < eps_old && N < 1e6 && eps > 1e-9)
223 eps_old = eps, end_old = end;
225 "Feagin-17-8-10", begin), *
this);
226 N*=2; odeint.integrate_steps( x0, begin, x, end, N);
227 eps = fabs( end- end_old);
235 dg::geo::ribeiro::FieldRZYT fieldRZYT_;
236 dg::geo::ribeiro::FieldRZYZ fieldRZYZ_;
237 thrust::host_vector<double> fpsi_neg_inv;
255 double xX,
double yX,
double x0,
double y0):
256 psi_(psi), fpsi_(psi, xX, yX, x0,y0), fpsiMinv_(psi, xX, yX, x0,y0, 500)
259 zeta0_ = fpsi_.find_x( psi_0);
260 zeta1_= -fx/(1.-fx)*zeta0_;
266 bool isConformal()
const{
return false;}
267 virtual bool do_isOrthogonal()const override final{
return false;}
268 virtual void do_generate(
269 const thrust::host_vector<double>& zeta1d,
270 const thrust::host_vector<double>& eta1d,
271 unsigned nodeX0,
unsigned nodeX1,
272 thrust::host_vector<double>& x,
273 thrust::host_vector<double>& y,
274 thrust::host_vector<double>& zetaX,
275 thrust::host_vector<double>& zetaY,
276 thrust::host_vector<double>& etaX,
277 thrust::host_vector<double>& etaY)
const override final
281 for(
unsigned i=0; i<zeta1d.size(); i++)
282 if( zeta1d[i]< 0) inside++;
283 thrust::host_vector<double> psi_x, fx_;
284 dg::geo::detail::construct_psi_values( fpsiMinv_, psi0_, zeta0_, zeta1d, zeta1_, inside, psi_x);
287 dg::geo::ribeiro::FieldRZYRYZY fieldRZYRYZYribeiro(psi_);
288 unsigned size = zeta1d.size()*eta1d.size();
289 x.resize(size),
y.resize(size);
290 zetaX = zetaY = etaX = etaY =
x ;
291 unsigned Nx = zeta1d.size(), Ny = eta1d.size();
293 for(
unsigned i=0; i<zeta1d.size(); i++)
295 thrust::host_vector<double> ry, zy;
296 thrust::host_vector<double> yr,
yz, xr,
xz;
298 dg::geo::detail::computeX_rzy( fpsi_, fieldRZYRYZYribeiro, psi_x[i], eta1d, nodeX0, nodeX1, ry, zy, yr, yz, xr, xz, R0, Z0, fx_[i]);
299 for(
unsigned j=0; j<Ny; j++)
301 x[j*Nx+i] = ry[j],
y[j*Nx+i] = zy[j];
302 etaX[j*Nx+i] = yr[j], etaY[j*Nx+i] =
yz[j];
303 zetaX[j*Nx+i] = xr[j], zetaY[j*Nx+i] =
xz[j];
308 virtual double do_zeta0(
double fx)
const override final {
return zeta0_; }
309 virtual double do_zeta1(
double fx)
const override final {
return zeta1_;}
310 virtual double do_eta0(
double fy)
const override final {
return -2.*
M_PI*fy/(1.-2.*fy); }
311 virtual double do_eta1(
double fy)
const override final {
return 2.*
M_PI*(1.+fy/(1.-2.*fy));}
313 CylindricalFunctorsLvl2 psi_;
314 dg::geo::ribeiro::detail::FpsiX fpsi_;
315 dg::geo::ribeiro::detail::XFieldFinv fpsiMinv_;
316 double zeta0_, zeta1_;
static DG_DEVICE double cooX1d(double x)
get_value_type< ContainerType1 > dot(const ContainerType1 &x, const ContainerType2 &y)
thrust::host_vector< real_type > evaluate(UnaryOp f, const RealGrid1d< real_type > &g)
MPI_Vector< thrust::host_vector< real_type > > weights(const aRealMPITopology2d< real_type > &g)
This struct bundles a function and its first and second derivatives.
Definition: fluxfunctions.h:219
A two-dimensional grid based on "almost-conformal" coordinates by Ribeiro and Scott 2010.
Definition: ribeiroX.h:253
virtual RibeiroX * clone() const override final
Abstract clone method that returns a copy on the heap.
Definition: ribeiroX.h:264
RibeiroX(const CylindricalFunctorsLvl2 &psi, double psi_0, double fx, double xX, double yX, double x0, double y0)
Definition: ribeiroX.h:254
The abstract generator base class.
Definition: generatorX.h:19