From d3c475e5f9abc2cc4d3374dc87d6dc1fea49a9a9 Mon Sep 17 00:00:00 2001 From: Andre Schmidt <schmidt-a@iklx288.ikp.kit.edu> Date: Sat, 22 Aug 2020 08:55:50 +0200 Subject: [PATCH] added function for magnetic step --- Framework/Cascade/Cascade.h | 33 +------- Processes/TrackingLine/TrackingLine.h | 117 ++++++++++++++------------ 2 files changed, 66 insertions(+), 84 deletions(-) diff --git a/Framework/Cascade/Cascade.h b/Framework/Cascade/Cascade.h index 9d0a296d5..f4b8e92d2 100644 --- a/Framework/Cascade/Cascade.h +++ b/Framework/Cascade/Cascade.h @@ -214,7 +214,7 @@ namespace corsika::cascade { vParticle.GetEnergy() * units::constants::c; // determine geometric tracking - auto [stepWithoutB, stepWithB, geomMaxLength, nextVol] = fTracking.GetTrack(vParticle); + auto [lineWithoutB, stepWithoutB, stepWithB, geomMaxLength, nextVol] = fTracking.GetTrack(vParticle); [[maybe_unused]] auto const& dummy_nextVol = nextVol; // convert next_step from grammage to length @@ -232,41 +232,16 @@ namespace corsika::cascade { C8LOG_DEBUG("transport particle by : {} m", min_distance / 1_m); - // determine displacement by the magnetic field - auto const* currentLogicalVolumeNode = vParticle.GetNode(); - auto magneticfield = currentLogicalVolumeNode->GetModelProperties().GetMagneticField(vParticle.GetPosition()); - geometry::Vector<SpeedType::dimension_type> velocity = vParticle.GetMomentum() / vParticle.GetEnergy() * - corsika::units::constants::c; - geometry::Vector<dimensionless_d> const directionBefore = velocity.normalized(); - int chargeNumber; - if (corsika::particles::IsNucleus(vParticle.GetPID())) { - chargeNumber = vParticle.GetNuclearZ(); - } else { - chargeNumber = corsika::particles::GetChargeNumber(vParticle.GetPID()); - } - auto k = chargeNumber * corsika::units::constants::cSquared * 1_eV / - (velocity.GetNorm() * vParticle.GetEnergy() * 1_V); - - // First Movement - // assuming magnetic field does not change during movement - auto position = vParticle.GetPosition() + directionBefore * min_distance / 2; - // Change of direction by magnetic field - geometry::Vector<dimensionless_d> const directionAfter = directionBefore + directionBefore.cross(magneticfield) * - min_distance * k; - // Second Movement - position = position + directionAfter * min_distance / 2; + // determine displacement by the magnetic field + auto [line, position, directionAfter] = fTracking.MagneticStep(vParticle, lineWithoutB, min_distance); auto distance = position - vParticle.GetPosition(); // distance.norm() != min_distance if q != 0 // small error can be neglected - if (distance.norm() != 0_m) { - velocity = distance.normalized() * velocity.norm(); - } // no velocity update for very small steps // here the particle is actually moved along the trajectory to new position: // std::visit(setup::ParticleUpdate<Particle>{vParticle}, step); vParticle.SetMomentum(directionAfter.normalized() * vParticle.GetMomentum().norm()); - geometry::Line line(vParticle.GetPosition(), velocity); - geometry::Trajectory<geometry::Line> stepNew(line, distance.norm() / velocity.norm()); + geometry::Trajectory<geometry::Line> stepNew(line, distance.norm() / line.GetV0().norm()); vParticle.SetPosition(position); vParticle.SetTime(vParticle.GetTime() + distance.norm() / units::constants::c); std::cout << "New Position: " << vParticle.GetPosition().GetCoordinates() << std::endl; diff --git a/Processes/TrackingLine/TrackingLine.h b/Processes/TrackingLine/TrackingLine.h index a888cffaa..d68a96d65 100644 --- a/Processes/TrackingLine/TrackingLine.h +++ b/Processes/TrackingLine/TrackingLine.h @@ -62,6 +62,8 @@ namespace corsika::process { << " GeV " << std::endl; std::cout << "TrackingLine v: " << velocity.GetComponents() << std::endl; + geometry::Line line(currentPosition, velocity); + auto const* currentLogicalVolumeNode = p.GetNode(); //~ auto const* currentNumericalVolumeNode = //~ fEnvironment.GetUniverse()->GetContainingNode(currentPosition); @@ -86,8 +88,7 @@ namespace corsika::process { std::cout << " Magnetic Field: " << magneticfield.GetComponents() / 1_uT << " uT " << std::endl; auto k = chargeNumber * corsika::units::constants::cSquared * 1_eV / (velocity.GetNorm() * p.GetEnergy() * 1_V); geometry::Vector<dimensionless_d> const directionBefore = velocity.normalized(); - geometry::Vector<SpeedType::dimension_type> velocity1 = velocity; - geometry::Vector<SpeedType::dimension_type> velocity2 = velocity; + LengthType Steplength = 10_m; // length irrelevant if q=0 and else it gets changed again // for entering from outside auto addIfIntersects = [&](auto const& vtn) { @@ -114,7 +115,6 @@ namespace corsika::process { std::cout << "Solutions for next Volume: " << solutions[i].real() << std::endl; } } - LengthType Steplength; if (tmp.size() > 0) { Steplength = 1_m * *std::min_element(tmp.begin(),tmp.end()); std::cout << "Steplength to next volume = " << Steplength << std::endl; @@ -123,23 +123,15 @@ namespace corsika::process { // what to do when this happens? (very unlikely) } delete [] solutions; - - // First Movement - // assuming magnetic field does not change during movement - auto position = currentPosition + directionBefore * Steplength / 2; - // Change of direction by magnetic field - geometry::Vector<dimensionless_d> const directionAfter = directionBefore + directionBefore.cross(magneticfield) * - Steplength * k; - // Second Movement - position = position + directionAfter * Steplength / 2; - geometry::Vector<dimensionless_d> const direction = (position - currentPosition) / - (position - currentPosition).GetNorm(); - velocity1 = direction * velocity.GetNorm(); - } // instead of changing the line with magnetic field, the TimeOfIntersection() could be changed + + } + + auto [line1, position, direction] = MagneticStep(p, line, Steplength); + // new particle position and direction not needed in this case + // instead of changing the line with magnetic field, the TimeOfIntersection() could be changed // using line has some errors for huge steps - geometry::Line line(currentPosition, velocity1); - if (auto opt = TimeOfIntersection(line, sphere); opt.has_value()) { + if (auto opt = TimeOfIntersection(line1, sphere); opt.has_value()) { auto const [t1, t2] = *opt; C8LOG_DEBUG("intersection times: {} s; {} s", t1 / 1_s, t2 / 1_s); if (t1.magnitude() > 0) @@ -178,34 +170,26 @@ namespace corsika::process { } LengthType Steplength; if (tmp.size() > 0) { - Steplength = 1_m * *std::min_element(tmp.begin(),tmp.end()); - if (numericallyInside == false) { - int p = std::min_element(tmp.begin(),tmp.end()) - tmp.begin(); - tmp.erase(tmp.begin() + p); - Steplength = 1_m * *std::min_element(tmp.begin(),tmp.end()); - } - std::cout << "steplength out of current volume = " << Steplength << std::endl; + Steplength = 1_m * *std::min_element(tmp.begin(),tmp.end()); + if (numericallyInside == false) { + int p = std::min_element(tmp.begin(),tmp.end()) - tmp.begin(); + tmp.erase(tmp.begin() + p); + Steplength = 1_m * *std::min_element(tmp.begin(),tmp.end()); + } + std::cout << "steplength out of current volume = " << Steplength << std::endl; } else { std::cout << "no intersection (2)!" << std::endl; // what to do when this happens? (very unlikely) } delete [] solutions; + } - // First Movement - // assuming magnetic field does not change during movement - auto position = currentPosition + directionBefore * Steplength / 2; - // Change of direction by magnetic field - geometry::Vector<dimensionless_d> const directionAfter = directionBefore + directionBefore.cross(magneticfield) * - Steplength * k; - // Second Movement - position = position + directionAfter * Steplength / 2; - geometry::Vector<dimensionless_d> const direction = (position - currentPosition) / - (position - currentPosition).GetNorm(); - velocity2 = direction * velocity.GetNorm(); - } // instead of changing the line with magnetic field, the TimeOfIntersection() could be changed - geometry::Line line(currentPosition, velocity2); + auto [line2, position, direction] = MagneticStep(p, line, Steplength); + // new particle position and direction not needed in this case + // instead of changing the line with magnetic field, the TimeOfIntersection() could be changed + // using line has some errors for huge steps - [[maybe_unused]] auto const [t1, t2] = *TimeOfIntersection(line, sphere); + [[maybe_unused]] auto const [t1, t2] = *TimeOfIntersection(line2, sphere); [[maybe_unused]] auto dummy_t1 = t1; intersections.emplace_back(t2, currentLogicalVolumeNode->GetParent()); } @@ -228,26 +212,49 @@ namespace corsika::process { << min // << " " << minIter->second->GetModelProperties().GetName() << std::endl; + + auto [lineWithB, position, direction] = MagneticStep(p, line, velocity.norm() * min); + // new particle position and direction not needed in this case + + return std::make_tuple(line, geometry::Trajectory<geometry::Line>(line, min), + geometry::Trajectory<geometry::Line>(lineWithB, min), + velocity.norm() * min, minIter->second); + } + + template <typename Particle> // was Stack previously, and argument was + // Stack::StackIterator + + // determine direction of the particle after adding magnetic field + auto MagneticStep(Particle const& p, corsika::geometry::Line line, corsika::units::si::LengthType Steplength) { + using namespace corsika::units::si; + + //charge of the particle + int chargeNumber; + if (corsika::particles::IsNucleus(p.GetPID())) { + chargeNumber = p.GetNuclearZ(); + } else { + chargeNumber = corsika::particles::GetChargeNumber(p.GetPID()); + } + auto const* currentLogicalVolumeNode = p.GetNode(); + auto magneticfield = currentLogicalVolumeNode->GetModelProperties().GetMagneticField(p.GetPosition()); + auto k = chargeNumber * corsika::units::constants::cSquared * 1_eV / (line.GetV0().norm() * p.GetEnergy() * 1_V); + geometry::Vector<dimensionless_d> const directionBefore = line.GetV0().normalized(); - geometry::Line lineWithoutB(currentPosition, velocity); - // determine direction of the particle after adding magnetic field - // assuming magnetic field does not change during movement // First Movement - auto position = currentPosition + velocity * min / 2; + // assuming magnetic field does not change during movement + auto position = p.GetPosition() + directionBefore * Steplength / 2; // Change of direction by magnetic field - geometry::Vector<dimensionless_d> const directionAfter = directionBefore + velocity.cross(magneticfield) * - min * k; + geometry::Vector<dimensionless_d> const directionAfter = directionBefore + directionBefore.cross(magneticfield) * + Steplength * k; // Second Movement - position = position + directionAfter * velocity.norm() * min / 2; - if ((position - currentPosition).GetNorm() != 0_m) { - geometry::Vector<dimensionless_d> const direction = (position - currentPosition).normalized(); - velocity = direction * velocity.norm(); - } // no velocity update for very small steps - geometry::Line lineWithB(currentPosition, velocity); - - return std::make_tuple(geometry::Trajectory<geometry::Line>(lineWithoutB, min), - geometry::Trajectory<geometry::Line>(lineWithB, min), - velocity.norm() * min, minIter->second); + position = position + directionAfter * Steplength / 2; + auto distance = position - p.GetPosition(); + + if(distance.norm() == 0_m) { + return std::make_tuple(line, position, directionAfter); + } + geometry::Line newLine(p.GetPosition(), distance.normalized() * line.GetV0().norm()); + return std::make_tuple(newLine, position, directionAfter); } }; -- GitLab