int run(int round, bool tracking, bool skipUntracked) { runge_kutta_dopri5<Phase> stepper; auto ctrdStepper = make_controlled(absoluteStepperError, relativeStepperError, stepper); Simulator<decltype(ctrdStepper)> simulator(ctrdStepper, &bbsystem); uniform_real_distribution<double> distributionNullB2Max(0, b2max); double b = sqrt(distributionNullB2Max(randomEngine)); hydrogen->randomize(randomEngine); hydrogen->setPosition(vector3D(0, 0, 0)); hydrogen->setVelocity(vector3D(0, 0, 0)); bbsystem.setBodyPosition(projectile, vector3D(0, b, -50.0)); bbsystem.setBodyVelocity(projectile, vector3D(0, 0, projectileVelocity)); if (skipUntracked && !tracking) { return 0; } stream << bbsystem.phase; stream.flush(); if (tracking) { printer = new Printer(to_string(round) + ".csv"); printer->addField(&printField); simulator.setObserver(*printer); } if (condition->evaluate(bbsystem.phase, 0)) { stream << "\t" << "Initial condition error" << endl; return -3; } double energy = bbsystem.getSystemEnergy(); double time = simulator.simulate(0.0, 1.0, 0.0001, *condition, 100); bool eBoundToTarget; bool eBoundToProjec; while (true) { if (time < 0.0) { stream << "\t" << "Distance not reached error" << endl; return -1; } if (abs((energy - bbsystem.getSystemEnergy()) / energy) > relativeEnergyError) { stream << "\t" << "Energy error: " << energy << " vs. " << bbsystem.getSystemEnergy() << endl; return -2; } eBoundToTarget = Utils::isBound(bbsystem, hydrogen->getElectron("1s1"), hydrogen->getNucleus()); eBoundToProjec = Utils::isBound(bbsystem, hydrogen->getElectron("1s1"), projectile); if (!eBoundToTarget || !eBoundToProjec) { break; } stream << " " << round << " Extend Run"; simulator.simulate(time, time + 1.0, 0.0001); time += 1.0; extended++; } if (eBoundToTarget && !eBoundToProjec) { stream << endl; } if (!eBoundToTarget && eBoundToProjec) { stream << "\t" << round << " --> Electron Capture" << endl; ecapture++; } if (!eBoundToTarget && !eBoundToProjec) { stream << "\t" << round << " --> Ionization" << endl; ionization++; } if (printer != nullptr) delete printer; stream.flush(); return 0; }
int run(int round, bool tracking, bool skipUntracked) { runge_kutta_dopri5<Phase> stepper; auto ctrdStepper = make_controlled(absoluteStepperError, relativeStepperError, stepper); Simulator<decltype(ctrdStepper)> simulator(ctrdStepper, &bbsystem); uniform_real_distribution<double> distributionNullB2Max(0, b2max); double b = sqrt(distributionNullB2Max(randomEngine)); helium->randomize(randomEngine); helium->setPosition(vector3D(0, 0, 0)); helium->setVelocity(vector3D(0, 0, 0)); bbsystem.setBodyPosition(projectile, vector3D(0, b, -initialDistance)); bbsystem.setBodyVelocity(projectile, vector3D(0, 0, projectileVelocity)); DistanceCondition condition(projectile, helium->getNucleus(), initialDistance + 1.0); if (skipUntracked && !tracking) { return 0; } stream << bbsystem.phase; stream.flush(); if (tracking) { printer = new Printer(to_string(round) + ".csv"); printer->addField(&printField); simulator.setObserver(*printer); } if (condition.evaluate(bbsystem.phase, 0)) { stream << "\t" << "Initial condition error" << endl; return -3; } int maxRounds = (int) (1.2 * (2.0 * initialDistance + 1.0) / projectileVelocity + 1.0); double energy = bbsystem.getSystemEnergy(); double time = simulator.simulate(0.0, 1.0, 0.0001, condition, maxRounds); bool e1s1BoundToTarget, e1s2BoundToTarget; bool e1s1BoundToProjec, e1s2BoundToProjec; while (true) { if (time < 0.0) { stream << "\t" << "Distance not reached error" << endl; return -1; } if (abs((energy - bbsystem.getSystemEnergy()) / energy) > relativeEnergyError) { stream << "\t" << "Energy error: " << energy << " vs. " << bbsystem.getSystemEnergy() << endl; return -2; } e1s1BoundToTarget = Utils::isBound(bbsystem, helium->getElectron("1s1"), helium->getNucleus()); e1s2BoundToTarget = Utils::isBound(bbsystem, helium->getElectron("1s2"), helium->getNucleus()); e1s1BoundToProjec = Utils::isBound(bbsystem, helium->getElectron("1s1"), projectile); e1s2BoundToProjec = Utils::isBound(bbsystem, helium->getElectron("1s2"), projectile); if ((!e1s1BoundToTarget || !e1s1BoundToProjec) && (!e1s2BoundToTarget || !e1s2BoundToProjec)) { break; } stream << " " << round << " Extend Run"; simulator.simulate(time, time + 1.0, 0.0001); time += 1.0; extended++; } string bindings; for (bool bound : { e1s1BoundToTarget, e1s2BoundToTarget, e1s1BoundToProjec, e1s2BoundToProjec }) { if (bound) bindings.append("-"); else bindings.append("+"); } switch (Utils::hash(bindings.c_str())) { case Utils::hash("--++"): stream << endl; break; case Utils::hash("+-++"): case Utils::hash("-+++"): stream << "\t" << round << " --> Single Ionization" << endl; ionization1++; break; case Utils::hash("++++"): stream << "\t" << round << " --> Dual Ionization" << endl; ionization2++; break; case Utils::hash("+--+"): case Utils::hash("-++-"): stream << "\t" << round << " --> Single electron Capture" << endl; ecapture1++; break; case Utils::hash("++--"): stream << "\t" << round << " --> Dual electron Capture" << endl; ecapture2++; break; case Utils::hash("++-+"): case Utils::hash("+++-"): stream << "\t" << round << " --> Ionization And Capture" << endl; ionizationAndCapture++; break; default: throw std::logic_error("Unhandled energy configuration."); } if (printer != nullptr) delete printer; stream.flush(); return 0; }