// Iterative method to calculate new X and Z values for the specified time of flight static inline void CalcXandZ(double &X, double &Z, const VECTOR3 Pos, const VECTOR3 Vel, double a, const double Time, const double SqrtMu) { const double MAX_ITERS = 10; double C, S, T, dTdX, DeltaTime, r = Mag(Pos), IterNum = 0; // These don't change over the iterations double RVMu = (Pos * Vel) / SqrtMu; // Dot product of position and velocity divided // by the squareroot of Mu double OneRA = (1 - (r / a)); // One minus Pos over the semi-major axis C = CalcC(Z); S = CalcS(Z); T = ((RVMu * pow(X, 2) * C) + (OneRA * pow(X, 3) * S) + (r * X)) / SqrtMu; DeltaTime = Time - T; // Iterate while the result isn't within tolerances while (fabs(DeltaTime) > EPSILON && IterNum++ < MAX_ITERS) { dTdX = ((pow(X, 2) * C) + (RVMu * X * (1 - Z * S)) + (r * (1 - Z * C))) / SqrtMu; X = X + (DeltaTime / dTdX); Z = CalcZ(X, a); C = CalcC(Z); S = CalcS(Z); T = ((RVMu * pow(X, 2) * C) + (OneRA * pow(X, 3) * S) + (r * X)) / SqrtMu; DeltaTime = Time - T; } }
// Given the specified position and velocity vectors for a given orbit, retuns the position // and velocity vectors after a specified time void PredictPosVelVectors(const VECTOR3 &Pos, const VECTOR3 &Vel, double a, double Mu, double Time, VECTOR3 &NewPos, VECTOR3 &NewVel, double &NewVelMag) { double SqrtMu = sqrt(Mu); // Variables for computation double X = (SqrtMu * Time) / a; // Initial guesses for X double Z = CalcZ(X, a); // and Z double C, S; // C(Z) and S(Z) double F, FDot, G, GDot; // Calculate the X and Z for the specified time of flight CalcXandZ(X, Z, Pos, Vel, a, Time, SqrtMu); // Calculate C(Z) and S(Z) C = CalcC(Z); S = CalcS(Z); // Calculate the new position and velocity vectors F = CalcF(X, C, Mag(Pos)); G = CalcG(Time, X, S, SqrtMu); NewPos = (Pos * F) + (Vel * G); FDot = CalcFDot(SqrtMu, Mag(Pos), Mag(NewPos), X, Z, S); GDot = CalcGDot(X, C, Mag(NewPos)); NewVel = (Pos * FDot) + (Vel * GDot); NewVelMag = Mag(NewVel); }
ribi::PlaneZ::Coordinats2D ribi::PlaneZ::CalcProjection( const Coordinats3D& points ) const { assert(points.size() >= 3); const double x_origin = 0.0; const double y_origin = 0.0; const double z_origin = CalcZ(x_origin,y_origin); Coordinats2D v; for (const auto& point: points) { const Double x(boost::geometry::get<0>(point)); const Double y(boost::geometry::get<1>(point)); const Double z(boost::geometry::get<2>(point)); const Double dx = sqrt( //Apfloat does not add the std:: ((x - x_origin) * (x - x_origin)) + ((z - z_origin) * (z - z_origin)) ) * (x - x_origin) ; const Double dy = sqrt( //Apfloat does not add the std:: ((y - y_origin) * (y - y_origin)) + ((z - z_origin) * (z - z_origin)) ) * (y - y_origin) ; Coordinat2D point_xy(dx,dy); v.push_back(point_xy); } return v; }
double ribi::PlaneZ::CalcError(const Coordinat3D& coordinat) const noexcept { const double x = boost::geometry::get<0>(coordinat); const double y = boost::geometry::get<1>(coordinat); const double z = boost::geometry::get<2>(coordinat); const double expected{z}; const double calculated{CalcZ(x,y)}; const double error{std::abs(calculated - expected)}; return error; }
double CalcR(double (*y)(double), double a, double b) { double z = CalcZ(y,a,b); double w = CalcW(y,a,b); return a+(b-a)*(z-derevative(y,a)+w)/(derevative(y,b)-derevative(y,a)+2*w); }
double CalcW(double (*y)(double), double a, double b) { double z = CalcZ(y,a,b); return sqrt(z*z - derevative(y,a)*derevative(y,b)); }
void SmallFlowStep(ConfigData *config) { // Here we have to implement the RK scheme from 1006.4518 [hep-lat] // Appendix C // W_0 = V_t // W_1 = exp(1/4 Z_0) W_0 // W_2 = exp(8/9 Z_1 - 17/36 Z_0) W_1 // W_t+eps = exp(3/4 Z_2 - 8/9 Z_1 + 17/36 Z_0) W_2 // // Z_i = eps Z(W_i) // // The input configuration 'config' will be overwritten with the // configuration at flow time t'=t+eps. // We allocate a new ConfigData // W_0 = V_t : W0 = config; ConfigData *S0 = new ConfigData(opt.ns, opt.ns, opt.ns, opt.nt, 3); // W_1 = exp(1/4 Z_0) W_0 ConfigData *W1 = new ConfigData(opt.ns, opt.ns, opt.ns, opt.nt, 3); #pragma omp parallel for for (int x=0; x<opt.ns*opt.ns*opt.ns*opt.nt; x++) { std::complex<double> U[3][3], Z0[3][3], A[3][3], expA[3][3], newU[3][3]; for (int mu=0; mu<4; mu++) { // For link U_x,mu CalcZ(Z0, config, x, mu); S0->replace(*Z0, x, mu); // save this into ConfigData for Z0s za(A, 1.0/4.0*opt.eps, Z0); expM(expA, A); config->extract(*U, x, mu); axb(newU, expA, U); #ifdef DEBUG if (testUnitarity(newU) > 1e-5) { std::cout << "WARNING: New link in SmallFlowStep() not unitary anymore!" << std::endl; } #endif W1->replace(*newU, x, mu); } } // W_2 = exp(8/9 Z_1 - 17/36 Z_0) W_1 ConfigData *W2 = new ConfigData(opt.ns, opt.ns, opt.ns, opt.nt, 3); #pragma omp parallel for for (int x=0; x<opt.ns*opt.ns*opt.ns*opt.nt; x++) { std::complex<double> U[3][3], Z0[3][3], Z1[3][3], A[3][3], A2[3][3], expA[3][3], newU[3][3]; for (int mu=0; mu<4; mu++) { // First part with Z0 S0->extract(*Z0, x, mu); // get this from ConfigData for Z0s za(A, -17.0/36.0*opt.eps, Z0); // Add second part with Z1 CalcZ(Z1, W1, x, mu); za(A2, 8.0/9.0*opt.eps, Z1); // Add both parts apb(A,A2); S0->replace(*A, x, mu); // save this into ConfigData S0 (A=-17/36*Z0 + 8/9*Z1) expM(expA, A); W1->extract(*U, x, mu); axb(newU, expA, U); #ifdef DEBUG if (testUnitarity(newU) > 1e-5) { std::cout << "WARNING: New link in SmallFlowStep() not unitary anymore!" << std::endl; } #endif W2->replace(*newU, x, mu); } } delete W1; W1 = 0; // W_t+eps = exp(3/4 Z_2 - 8/9 Z_1 + 17/36 Z_0) W_2 #pragma omp parallel for for (int x=0; x<opt.ns*opt.ns*opt.ns*opt.nt; x++) { std::complex<double> U[3][3], Z0[3][3], Z2[3][3], A[3][3], A2[3][3], expA[3][3], newU[3][3]; for (int mu=0; mu<4; mu++) { // For link U_x,mu // First part with Z0 and Z1 S0->extract(*Z0, x, mu); // load -17/36*Z0 + 8/9*Z1 za(A, -1.0, Z0); // switch the sign // Add third part with Z2 CalcZ(Z2, W2, x, mu); za(A2, 3.0/4.0*opt.eps, Z2); // Add both parts apb(A,A2); expM(expA, A); W2->extract(*U, x, mu); axb(newU, expA, U); #ifdef DEBUG if (testUnitarity(newU) > 1e-5) { std::cout << "WARNING: New link in SmallFlowStep() not unitary anymore!" << std::endl; } #endif config->replace(*newU, x, mu); } } // Cleaning up delete W2; W2 = 0; delete S0; S0 = 0; }