From 0c5ad7a6d3071dd3fe763ffc31fceb74034d0aad Mon Sep 17 00:00:00 2001 From: Andre Schmidt <schmidt-a@iklx288.ikp.kit.edu> Date: Sat, 8 Aug 2020 10:57:45 +0200 Subject: [PATCH] Added Intersection --- Framework/Cascade/Cascade.h | 22 +-- Processes/TrackingLine/TrackingLine.h | 178 ++++++++++++------ .../TrackingLine/TrackingLine_interpolation.h | 7 + 3 files changed, 135 insertions(+), 72 deletions(-) diff --git a/Framework/Cascade/Cascade.h b/Framework/Cascade/Cascade.h index 4afbaf844..c7aec5de0 100644 --- a/Framework/Cascade/Cascade.h +++ b/Framework/Cascade/Cascade.h @@ -247,26 +247,24 @@ namespace corsika::cascade { 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; + auto position = vParticle.GetPosition() + directionBefore * min_distance / 2; // Change of direction by magnetic field geometry::Vector<dimensionless_d> const directionAfter = directionBefore + directionBefore.cross(magneticfield) * - Steplength * k; + min_distance * 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()); + position = position + directionAfter * min_distance / 2; + // 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().GetNorm()); + vParticle.SetPosition(position); + } else { + vParticle.SetPosition(step.PositionFromArclength(min_distance)); } - - // 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.SetTime(vParticle.GetTime() + min_distance / units::constants::c); + std::cout << "New Position: " << vParticle.GetPosition().GetCoordinates() << std::endl; step.LimitEndTo(min_distance); diff --git a/Processes/TrackingLine/TrackingLine.h b/Processes/TrackingLine/TrackingLine.h index de024f564..138c2f191 100644 --- a/Processes/TrackingLine/TrackingLine.h +++ b/Processes/TrackingLine/TrackingLine.h @@ -58,77 +58,36 @@ namespace corsika::process { // << " [" << p.GetNode()->GetModelProperties().GetName() << "]" << std::endl; std::cout << "TrackingLine E: " << p.GetEnergy() / 1_GeV << " GeV" << std::endl; - - // determine direction of the particle after adding magnetic field - auto const* currentLogicalVolumeNode = p.GetNode(); - int chargeNumber; - if(corsika::particles::IsNucleus(p.GetPID())) { - chargeNumber = p.GetNuclearZ(); - } else { - chargeNumber = corsika::particles::GetChargeNumber(p.GetPID()); - } - if(chargeNumber != 0) { - auto magneticfield = currentLogicalVolumeNode->GetModelProperties().GetMagneticField(currentPosition); - std::cout << "TrackingLine B: " << 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(); - //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; - } + std::cout << "TrackingLine p: " << p.GetMomentum().GetComponents() / 1_GeV + << " GeV " << std::endl; std::cout << "TrackingLine v: " << velocity.GetComponents() << std::endl; - geometry::Line line(currentPosition, velocity); - - //auto const* currentLogicalVolumeNode = p.GetNode(); + auto const* currentLogicalVolumeNode = p.GetNode(); //~ auto const* currentNumericalVolumeNode = //~ fEnvironment.GetUniverse()->GetContainingNode(currentPosition); auto const numericallyInside = currentLogicalVolumeNode->GetVolume().Contains(currentPosition); - C8LOG_DEBUG("numericallyInside = {} ", - currentLogicalVolumeNode->GetVolume().Contains(currentPosition)); + std::cout << "numericallyInside = " << (numericallyInside ? "true" : "false") << std::endl; auto const& children = currentLogicalVolumeNode->GetChildNodes(); auto const& excluded = currentLogicalVolumeNode->GetExcludedNodes(); std::vector<std::pair<TimeType, decltype(p.GetNode())>> intersections; + + //charge of the particle + int chargeNumber; + if(corsika::particles::IsNucleus(p.GetPID())) { + chargeNumber = p.GetNuclearZ(); + } else { + chargeNumber = corsika::particles::GetChargeNumber(p.GetPID()); + } + auto magneticfield = currentLogicalVolumeNode->GetModelProperties().GetMagneticField(currentPosition); + 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; // for entering from outside auto addIfIntersects = [&](auto const& vtn) { @@ -136,6 +95,47 @@ namespace corsika::process { auto const& sphere = dynamic_cast<geometry::Sphere const&>( volume); // for the moment we are a bit bold here and assume // everything is a sphere, crashes with exception if not + + //creating Line with magnetic field + if(chargeNumber != 0) { + //determine steplength to next volume + double a = ((directionBefore.cross(magneticfield)).dot(currentPosition - sphere.GetCenter()) * k + 1) * 4 / + (1_m * 1_m * (directionBefore.cross(magneticfield)).GetSquaredNorm() * k * k); + double b = directionBefore.dot(currentPosition - sphere.GetCenter()) * 8 / + ((directionBefore.cross(magneticfield)).GetSquaredNorm() * k * k * 1_m * 1_m * 1_m); + double c = ((currentPosition - sphere.GetCenter()).GetSquaredNorm() - + (sphere.GetRadius() * sphere.GetRadius())) * 4 / + ((directionBefore.cross(magneticfield)).GetSquaredNorm() * k * k * 1_m * 1_m * 1_m * 1_m); + 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 Steplength; + if(tmp.size() > 0) { + Steplength = 1_m * *std::min_element(tmp.begin(),tmp.end()); + std::cout << "s = " << Steplength << std::endl; + } else { + std::cout << "no intersection (1)!" << 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(); + velocity1 = direction * velocity.GetNorm(); + } //instead of changing the line with magnetic field, the TimeOfIntersection() could be changed + //line has some errors + geometry::Line line(currentPosition, velocity1); if (auto opt = TimeOfIntersection(line, sphere); opt.has_value()) { auto const [t1, t2] = *opt; @@ -155,6 +155,47 @@ namespace corsika::process { currentLogicalVolumeNode->GetVolume()); // for the moment we are a bit bold here and assume // everything is a sphere, crashes with exception if not + + //creating Line with magnetic field + if(chargeNumber != 0) { + //determine steplength to next volume + double a = ((directionBefore.cross(magneticfield)).dot(currentPosition - sphere.GetCenter()) * k + 1) * 4 / + (1_m * 1_m * (directionBefore.cross(magneticfield)).GetSquaredNorm() * k * k); + double b = directionBefore.dot(currentPosition - sphere.GetCenter()) * 8 / + ((directionBefore.cross(magneticfield)).GetSquaredNorm() * k * k * 1_m * 1_m * 1_m); + double c = ((currentPosition - sphere.GetCenter()).GetSquaredNorm() - + (sphere.GetRadius() * sphere.GetRadius())) * 4 / + ((directionBefore.cross(magneticfield)).GetSquaredNorm() * k * k * 1_m * 1_m * 1_m * 1_m); + 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 Steplength; + if(tmp.size() > 0) { + Steplength = 1_m * *std::min_element(tmp.begin(),tmp.end()); + std::cout << "s = " << Steplength << std::endl; + } else { + std::cout << "no intersection (2)!" << 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(); + velocity2 = direction * velocity.GetNorm(); + }//instead of changing the line with magnetic field, the TimeOfIntersection() could be changed + geometry::Line line(currentPosition, velocity2); + [[maybe_unused]] auto const [t1, t2] = *TimeOfIntersection(line, sphere); [[maybe_unused]] auto dummy_t1 = t1; intersections.emplace_back(t2, currentLogicalVolumeNode->GetParent()); @@ -174,7 +215,24 @@ namespace corsika::process { min = minIter->first; } - C8LOG_DEBUG(" t-intersect: {} ", min); + std::cout << " t-intersect: " + << min + // << " " << minIter->second->GetModelProperties().GetName() + << std::endl; + + // 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; + // Change of direction by magnetic field + geometry::Vector<dimensionless_d> const directionAfter = directionBefore + velocity.cross(magneticfield) * + min * k; + // Second Movement + position = position + directionAfter * velocity.norm() * min / 2; + geometry::Vector<dimensionless_d> const direction = (position - currentPosition) / + (position - currentPosition).GetNorm(); + velocity = direction * velocity.GetNorm(); + geometry::Line line(currentPosition, velocity); return std::make_tuple(geometry::Trajectory<geometry::Line>(line, min), velocity.norm() * min, minIter->second); diff --git a/Processes/TrackingLine/TrackingLine_interpolation.h b/Processes/TrackingLine/TrackingLine_interpolation.h index 228855cfe..ea0c39d21 100644 --- a/Processes/TrackingLine/TrackingLine_interpolation.h +++ b/Processes/TrackingLine/TrackingLine_interpolation.h @@ -115,6 +115,11 @@ namespace corsika::process { 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(); + double test =((directionBefore.cross(magneticfield)).dot(position-currentPosition) * k + 1) / (1_m * 1_m * (directionBefore.cross(magneticfield)).GetSquaredNorm() * k * k); + std::cout << "Test: " << test << k << std::endl; + } else { std::cout << "TrackingLine p: " << p.GetMomentum().GetComponents() / 1_GeV << " GeV " << std::endl; @@ -143,6 +148,8 @@ namespace corsika::process { auto const& sphere = dynamic_cast<geometry::Sphere const&>( volume); // for the moment we are a bit bold here and assume // everything is a sphere, crashes with exception if not + + std::cout << "Mittelpunkt: " << sphere.GetCenter().GetCoordinates() << std::endl; if (auto opt = TimeOfIntersection(line, sphere); opt.has_value()) { auto const [t1, t2] = *opt; -- GitLab