From 9bc74cc694b46a628ba21811f9e5b22ce5ff7200 Mon Sep 17 00:00:00 2001 From: Andre Schmidt <schmidt-a@iklx288.ikp.kit.edu> Date: Thu, 6 Aug 2020 11:02:14 +0200 Subject: [PATCH] change Steplength --- Documentation/Examples/vertical_EAS.cc | 2 + Framework/Cascade/Cascade.h | 40 ++++++++++-- Framework/Utilities/CMakeLists.txt | 2 + Processes/TrackingLine/TrackingLine.h | 74 ++++++++++++---------- Processes/TrackingLine/testTrackingLine.cc | 2 +- 5 files changed, 81 insertions(+), 39 deletions(-) diff --git a/Documentation/Examples/vertical_EAS.cc b/Documentation/Examples/vertical_EAS.cc index 0f4d57c87..25f246748 100644 --- a/Documentation/Examples/vertical_EAS.cc +++ b/Documentation/Examples/vertical_EAS.cc @@ -34,6 +34,7 @@ #include <corsika/process/particle_cut/ParticleCut.h> #include <corsika/process/proposal/ContinuousProcess.h> #include <corsika/process/proposal/Interaction.h> +#include <corsika/process/track_writer/TrackWriter.h> #include <corsika/process/pythia/Decay.h> #include <corsika/process/sibyll/Decay.h> #include <corsika/process/sibyll/Interaction.h> @@ -226,6 +227,7 @@ int main(int argc, char** argv) { process::on_shell_check::OnShellCheck reset_particle_mass(1.e-3, 1.e-1, false); + process::track_writer::TrackWriter trackWriter("tracks.dat"); process::longitudinal_profile::LongitudinalProfile longprof{showerAxis}; Plane const obsPlane(showerCore, Vector<dimensionless_d>(rootCS, {0., 0., 1.})); diff --git a/Framework/Cascade/Cascade.h b/Framework/Cascade/Cascade.h index 4481e8a24..fe5ecaaff 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 [step, geomMaxLength, nextVol, magMaxLength, directionBefore, directionAfter] = fTracking.GetTrack(vParticle); + auto [step, geomMaxLength, nextVol] = fTracking.GetTrack(vParticle); [[maybe_unused]] auto const& dummy_nextVol = nextVol; // convert next_step from grammage to length @@ -226,18 +226,46 @@ namespace corsika::cascade { LengthType const distance_max = fProcessSequence.MaxStepLength(vParticle, step); std::cout << "distance_max=" << distance_max << std::endl; - // take minimum of geometry, interaction, decay for next step + // take minimum of geometry, interaction, decay, magnetic field for next step auto const min_distance = std::min( - {distance_interact, distance_decay, distance_max, geomMaxLength, magMaxLength}); + {distance_interact, distance_decay, distance_max, geomMaxLength}); C8LOG_DEBUG("transport particle by : {} m", min_distance / 1_m); + //determine displacement by the magnetic field + auto const* currentLogicalVolumeNode = vParticle.GetNode(); + int chargeNumber; + if(corsika::particles::IsNucleus(vParticle.GetPID())) { + chargeNumber = vParticle.GetNuclearZ(); + } else { + chargeNumber = corsika::particles::GetChargeNumber(vParticle.GetPID()); + } + if(chargeNumber != 0) { + 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(); + auto k = chargeNumber * corsika::units::constants::cSquared * 1_eV / + (velocity.GetNorm() * vParticle.GetEnergy() * 1_V); + LengthType const steplength = min_distance / + (directionBefore + directionBefore.cross(magneticfield) * k / 2).GetNorm(); + // First Movement + //assuming magnetic field does not change during movement + auto position = vParticle.GetPosition() + 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 - vParticle.GetPosition()) / + (position - vParticle.GetPosition()).GetNorm(); + vParticle.SetMomentum(direction * vParticle.GetMomentum().GetNorm()); + } + // here the particle is actually moved along the trajectory to new position: // std::visit(setup::ParticleUpdate<Particle>{vParticle}, step); vParticle.SetPosition(step.PositionFromArclength(min_distance)); // .... also update time, momentum, direction, ... - vParticle.SetMomentum((directionBefore * (1 - min_distance / magMaxLength) + - directionAfter * min_distance /magMaxLength) * vParticle.GetMomentum().GetNorm()); vParticle.SetTime(vParticle.GetTime() + min_distance / units::constants::c); step.LimitEndTo(min_distance); @@ -263,7 +291,7 @@ namespace corsika::cascade { TStackView secondaries(vParticle); - if (min_distance != distance_max && min_distance != magMaxLength) { + if (min_distance != distance_max) { /* Create SecondaryView object on Stack. The data container remains untouched and identical, and 'projectil' is identical diff --git a/Framework/Utilities/CMakeLists.txt b/Framework/Utilities/CMakeLists.txt index 95170d4a3..3373c0171 100644 --- a/Framework/Utilities/CMakeLists.txt +++ b/Framework/Utilities/CMakeLists.txt @@ -20,6 +20,7 @@ set ( UTILITIES_SOURCES COMBoost.cc CorsikaData.cc + quartic.cpp ${CORSIKA_FENV}) set ( @@ -31,6 +32,7 @@ set ( sgn.h CorsikaFenv.h MetaProgramming.h + quartic.h ) set ( diff --git a/Processes/TrackingLine/TrackingLine.h b/Processes/TrackingLine/TrackingLine.h index 5282f5a57..de024f564 100644 --- a/Processes/TrackingLine/TrackingLine.h +++ b/Processes/TrackingLine/TrackingLine.h @@ -15,8 +15,7 @@ #include <corsika/geometry/Vector.h> #include <corsika/particles/ParticleProperties.h> #include <corsika/units/PhysicalUnits.h> -#include <corsika/logging/Logging.h> - +#include <corsika/utl/quartic.h> #include <optional> #include <type_traits> #include <utility> @@ -60,7 +59,7 @@ namespace corsika::process { << std::endl; std::cout << "TrackingLine E: " << p.GetEnergy() / 1_GeV << " GeV" << std::endl; - // determine velocity after adding magnetic field + // determine direction of the particle after adding magnetic field auto const* currentLogicalVolumeNode = p.GetNode(); int chargeNumber; if(corsika::particles::IsNucleus(p.GetPID())) { @@ -68,39 +67,51 @@ namespace corsika::process { } else { chargeNumber = corsika::particles::GetChargeNumber(p.GetPID()); } - geometry::Vector<dimensionless_d> const directionBefore = velocity.normalized(); - auto magMaxLength = 1_m/0; - auto directionAfter = directionBefore; if(chargeNumber != 0) { auto magneticfield = currentLogicalVolumeNode->GetModelProperties().GetMagneticField(currentPosition); std::cout << "TrackingLine B: " << magneticfield.GetComponents() / 1_uT << " uT " << std::endl; - geometry::Vector<SpeedType::dimension_type> const velocityVerticalMag = velocity - - velocity.parallelProjectionOnto(magneticfield); - LengthType const gyroradius = p.GetEnergy() * velocityVerticalMag.GetNorm() * 1_V / - (corsika::units::constants::cSquared * abs(chargeNumber) * - magneticfield.GetNorm() * 1_eV); - //steplength depending on how exact it should be - LengthType const Steplength = 0.01 * gyroradius; - // First Movement - auto position = currentPosition + directionBefore * Steplength / 2; - // Change of direction by magnetic field at position - magneticfield = currentLogicalVolumeNode->GetModelProperties().GetMagneticField(position); - directionAfter = directionBefore + directionBefore.cross(magneticfield) * chargeNumber * - Steplength * corsika::units::constants::cSquared * 1_eV / - (p.GetEnergy() * velocity.GetNorm() * 1_V); - // Second Movement - position = position + directionAfter * Steplength / 2; - magMaxLength = (position - currentPosition).GetNorm(); - geometry::Vector<dimensionless_d> const direction = (position - currentPosition) / - magMaxLength; - velocity = direction * velocity.GetNorm(); - std::cout << "TrackingLine p: " << (direction * p.GetMomentum().GetNorm()).GetComponents() / 1_GeV - << " GeV " << 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(); + //determine steplength to next volume + double a = ((directionBefore.cross(magneticfield)).dot(currentPosition - .GetCenter()) * k + 1) / + ((directionBefore.cross(magneticfield)).GetSquaredNorm() * k^2 * 1_m * 1_m / 4); + double b = directionBefore.dot(currentPosition - .GetCenter()) * 2 / + ((directionBefore.cross(magneticfield)).GetSquaredNorm() * k^2 * 1_m / 4); + double c = ((currentPosition - .GetCenter()).GetSquaredNorm() - .GetRadius^2) / + ((directionBefore.cross(magneticfield)).GetSquaredNorm() * k^2 / 4); + std::complex<double>* solutions = solve_quartic(0, a, b, c); + std::vector<double> tmp; + for(int i = 0; i < 4; i++) { + if(solutions[i].imag() == 0 && solutions[i].real() > 0) { + tmp.push_back(solutions[i].real()); + } + } + LengthType const Steplength; + if(tmp.size() > 0) { + Steplength = *std::min_element(tmp.begin(),tmp.end()) * 1_m; + std::cout << "s = " << Steplength << std::endl; + } else { + std::cout << "no intersection with anything!" << std::endl; + //what to do when this happens? + } + + // 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(); + velocity = direction * velocity.GetNorm(); + std::cout << "TrackingLine p: " << (direction * p.GetMomentum().GetNorm()).GetComponents() / 1_GeV + << " GeV " << std::endl; } else { std::cout << "TrackingLine p: " << p.GetMomentum().GetComponents() / 1_GeV - << " GeV " << std::endl; + << " GeV " << std::endl; } - std::cout << "TrackingLine v: " << velocity.GetComponents() << std::endl; geometry::Line line(currentPosition, velocity); @@ -166,8 +177,7 @@ namespace corsika::process { C8LOG_DEBUG(" t-intersect: {} ", min); return std::make_tuple(geometry::Trajectory<geometry::Line>(line, min), - velocity.norm() * min, minIter->second, magMaxLength, - directionBefore, directionAfter); + velocity.norm() * min, minIter->second); } }; diff --git a/Processes/TrackingLine/testTrackingLine.cc b/Processes/TrackingLine/testTrackingLine.cc index 4cfa2bd60..a72e870b7 100644 --- a/Processes/TrackingLine/testTrackingLine.cc +++ b/Processes/TrackingLine/testTrackingLine.cc @@ -86,7 +86,7 @@ TEST_CASE("TrackingLine") { 0_m / second, 1_m / second); Line line(origin, v); - auto const [traj, geomMaxLength, nextVol] = tracking.GetTrack(p); + auto const [traj, geomMaxLength, nextVol, magMaxLength, beforeDirection, afterDirection] = tracking.GetTrack(p); [[maybe_unused]] auto dummy_geomMaxLength = geomMaxLength; [[maybe_unused]] auto dummy_nextVol = nextVol; -- GitLab