From a769eedbe5064c9ba7a55f96af691524f161f54d Mon Sep 17 00:00:00 2001 From: Nikos Karastathis <n.karastathis@kit.edu> Date: Sun, 7 Mar 2021 17:57:37 +0100 Subject: [PATCH] some progress in CoREAS debugging --- corsika/modules/radio/CoREAS.hpp | 33 +- .../radio/antennas/TimeDomainAntenna.hpp | 13 +- tests/modules/testRadio.cpp | 513 +++++++++++------- 3 files changed, 340 insertions(+), 219 deletions(-) diff --git a/corsika/modules/radio/CoREAS.hpp b/corsika/modules/radio/CoREAS.hpp index 1ae0114e8..a3e358181 100755 --- a/corsika/modules/radio/CoREAS.hpp +++ b/corsika/modules/radio/CoREAS.hpp @@ -64,7 +64,9 @@ namespace corsika { auto endPoint_ {track.getPosition(1)}; // beta is velocity / speed of light. Start & end should be the same! - auto beta_ {((endPoint_ - startPoint_) / (endTime_ - startTime_)).normalized()}; +// auto beta_ {static_cast<double>((endPoint_.distance_to(startPoint_) / 1_m ) / (endTime_/ 1_s - startTime_/ 1_s) )}; +// auto beta_ {((endPoint_.distance_to(startPoint_)) / (endTime_ - startTime_)).normalized()}; + auto beta_ {((endPoint_ - startPoint_) / (constants::c * (endTime_ - startTime_))).normalized()}; // get particle charge auto const charge_ {get_charge(particle.getPID())}; @@ -93,8 +95,7 @@ namespace corsika { for (auto const& path : paths1) { // calculate preDoppler factor - double preDoppler_{1. - path.average_refractive_index_ * - beta_ * path.emit_}; + auto preDoppler_{1. - path.average_refractive_index_ * beta_.dot(path.emit_)}; // store it to the preDoppler std::vector for later comparisons preDoppler.push_back(preDoppler_); @@ -107,9 +108,15 @@ namespace corsika { // store the receive unit vector ReceiveVectorsStart_.push_back(path.receive_); +// auto kkk{path.receive_.cross(path.receive_.cross(beta_))}; +// auto kk{path.R_distance_ * preDoppler_}; +// auto kkkk{kkk/kk}; +// auto kc{kkkk * (1 / 1_s) /constants::c}; +// auto kosta{charge_ * 1_m}; + //(charge_ / constants::c) * // calculate electric field vector for startpoint - ElectricFieldVector EV1_= (charge_ / constants::c) * + ElectricFieldVector EV1_= (1 / 1_s) * (charge_ / constants::c) * path.receive_.cross(path.receive_.cross(beta_)) / (path.R_distance_ * preDoppler_); @@ -126,7 +133,7 @@ namespace corsika { for (auto const& path : paths2) { double postDoppler_{1. - path.average_refractive_index_ * - beta_ * path.emit_}; // maybe this is path.receive_ (?) + beta_.dot(path.emit_)}; // maybe this is path.receive_ (?) // store it to the postDoppler std::vector for later comparisons postDoppler.push_back(postDoppler_); @@ -243,7 +250,7 @@ namespace corsika { // get the Path (path3) from the middle "endpoint" to the antenna. // This is a SignalPathCollection - auto paths3{this->propagator_.propagate(midPoint_, antenna.getLocation())}; + auto paths3{this->propagator_.propagate(midPoint_, antenna.getLocation(), 1_nm)}; // std::size_t j_index {0}; // this will be useful for multiple paths (aka curved propagators) // now loop over the paths for endpoint that we got above @@ -253,7 +260,7 @@ namespace corsika { // EVend_.erase(EVend_.begin() + index + j_index); // for now just use one index and not j_index since at the moment you are working with StraightPropagator auto const midPointReceiveTime_{path.total_time_ + midTime_}; - auto midDoppler_{1. - path.average_refractive_index_ * beta_ * path.emit_}; + auto midDoppler_{1. - path.average_refractive_index_ * beta_.dot(path.emit_)}; // change the values of the receive unit vectors of start and end ReceiveVectorsStart_.at(index) = path.receive_; @@ -273,7 +280,7 @@ namespace corsika { EVstart_.at(index) = EVmid_; EVend_.at(index) = - EVmid_; - auto deltaT_{midPoint_.getNorm() / (constants::c * beta_ * fabs(midDoppler_))}; + auto deltaT_{(endPoint_ - startPoint_).getNorm() / (constants::c * beta_.getNorm() * fabs(midDoppler_))}; // TODO: Caution with this! if (startTTimes_.at(index) < endTTimes_.at(index)) // EVstart_ arrives earlier { @@ -286,14 +293,14 @@ namespace corsika { endTTimes_.at(index) = midPointReceiveTime_ - 0.5 * deltaT_; } - const long double gridResolution_{antenna.duration_}; + const long double gridResolution_{antenna.duration_ / 1_s}; deltaT_ = endTTimes_.at(index) - startTTimes_.at(index); // redistribute contributions over time scale defined by the observation time resolution - if (fabs(deltaT_) < gridResolution_) { + if (fabs(deltaT_ / 1_s) < gridResolution_) { - EVstart_.at(index) = EVstart_.at(index) * fabs(deltaT_ / gridResolution_); - EVend_.at(index) = EVend_.at(index) * fabs(deltaT_ / gridResolution_); + EVstart_.at(index) = EVstart_.at(index) * fabs((deltaT_ / 1_s) / gridResolution_); + EVend_.at(index) = EVend_.at(index) * fabs((deltaT_ / 1_s) / gridResolution_); const long startBin = static_cast<long>(floor((startTTimes_.at(index) / 1_s)/gridResolution_+0.5l)); const long endBin = static_cast<long>(floor((endTTimes_.at(index) / 1_s) /gridResolution_+0.5l)); @@ -304,7 +311,7 @@ namespace corsika { if (startBin == endBin) { // if startE arrives before endE - if (deltaT_ >= 0) { + if ((deltaT_ / 1_s) >= 0) { if ((startBinFraction >= 0.5) && (endBinFraction >= 0.5)) // both points left of bin center { startTTimes_.at(index) = startTTimes_.at(index) - gridResolution_ * 1_s; // shift EV1_ to previous gridpoint diff --git a/corsika/modules/radio/antennas/TimeDomainAntenna.hpp b/corsika/modules/radio/antennas/TimeDomainAntenna.hpp index 4d095f87d..d2463d505 100644 --- a/corsika/modules/radio/antennas/TimeDomainAntenna.hpp +++ b/corsika/modules/radio/antennas/TimeDomainAntenna.hpp @@ -23,6 +23,13 @@ namespace corsika { */ class TimeDomainAntenna : public Antenna<TimeDomainAntenna> { + +// protected: +// // expose the CRTP interfaces constructor + + public: + // import the methods from the antenna + TimeType const start_time_; ///< The start time of this waveform. TimeType const duration_; ///< The duration of this waveform. InverseTimeType const sample_rate_; ///< The sampling rate of this antenna. @@ -31,12 +38,6 @@ namespace corsika { std::pair<xt::xtensor<double, 2>, xt::xtensor<double,2>> waveform_; ///< useful for .getWaveform() - protected: - // expose the CRTP interfaces constructor - - public: - // import the methods from the antenna - using Antenna<TimeDomainAntenna>::getName; using Antenna<TimeDomainAntenna>::getLocation; diff --git a/tests/modules/testRadio.cpp b/tests/modules/testRadio.cpp index bbc54aaa5..5ac1ec69b 100644 --- a/tests/modules/testRadio.cpp +++ b/tests/modules/testRadio.cpp @@ -64,15 +64,128 @@ double constexpr absMargin = 1.0e-7; TEST_CASE("Radio", "[processes]") { + SECTION("CoREAS process") { + // first step is to construct an environment for the propagation (uni index) + using UniRIndex = + UniformRefractiveIndex<HomogeneousMedium<IRefractiveIndexModel<IMediumModel>>>; + + using EnvType = Environment<IRefractiveIndexModel<IMediumModel>>; + EnvType envZHS; + + // get a coordinate system + const CoordinateSystemPtr rootCSzhs = envZHS.getCoordinateSystem(); + + auto MediumZHS = EnvType::createNode<Sphere>( + Point{rootCSzhs, 0_m, 0_m, 0_m}, 1_km * std::numeric_limits<double>::infinity()); + + auto const propsZHS = MediumZHS->setModelProperties<UniRIndex>( + 1, 1_kg / (1_m * 1_m * 1_m), + NuclearComposition( + std::vector<Code>{Code::Nitrogen}, + std::vector<float>{1.f})); + + envZHS.getUniverse()->addChild(std::move(MediumZHS)); + + + // now create antennas and detectors + // the antennas location + const auto point1{Point(envZHS.getCoordinateSystem(), 1_m, 2_m, 3_m)}; + const auto point2{Point(envZHS.getCoordinateSystem(), 4_m, 5_m, 6_m)}; + const auto point3{Point(envZHS.getCoordinateSystem(), 7_m, 8_m, 9_m)}; + + + // create times for the antenna + const TimeType t1{10_s}; + const TimeType t2{10_s}; + const InverseTimeType t3{1/1_s}; + const TimeType t4{11_s}; + + // check that I can create an antenna at (1, 2, 3) + TimeDomainAntenna ant1("antenna_name", point1, t1, t2, t3); + TimeDomainAntenna ant2("antenna_name2", point2, t4, t2, t3); + + // construct a radio detector instance to store our antennas + AntennaCollection<TimeDomainAntenna> detector; + + detector.addAntenna(ant1); + + // create a particle + auto const particle{Code::Electron}; + const auto pmass{get_mass(particle)}; + + VelocityVector v0(rootCSzhs, {5_m / second, 0_m / second, 0_m / second}); + + Vector B0(rootCSzhs, 5_T, 0_T, 0_T); + + Line const line(point3, v0); + + auto const k{1_m * ((1_m) / ((1_s * 1_s) * 1_V))}; + + auto const t = 10_s; + LeapFrogTrajectory base(point1, v0, B0, k, t); + + // create a new stack for each trial + setup::Stack stack; + + // construct an energy + const HEPEnergyType E0{1_TeV}; + + // compute the necessary momentumn + const HEPMomentumType P0{sqrt(E0 * E0 - pmass * pmass)}; + + // and create the momentum vector + const auto plab{MomentumVector(rootCSzhs, {0_GeV, 0_GeV, P0})}; + + // and create the location of the particle in this coordinate system + const Point pos(rootCSzhs, 50_m, 10_m, 80_m); + + // add the particle to the stack + auto const particle1{stack.addParticle(std::make_tuple(particle, E0, plab, pos, 0_ns))}; + + // set up a track object +// setup::Tracking tracking; + + // Create a ZHS instance + CoREAS<decltype(detector), decltype(StraightPropagator(envZHS))> coreas(detector, envZHS); + + // call CoREAS over the track +// coreas.doContinuous(particle1, tracking); + coreas.simulate(particle1, base); + + coreas.writeOutput(); + } + + SECTION("TimeDomainAntenna") { // create an environment so we can get a coordinate system - using EnvType = setup::Environment; - EnvType env; +// using EnvType = setup::Environment; +// EnvType env; + using EnvType = Environment<IRefractiveIndexModel<IMediumModel>>; + EnvType env6; + + using UniRIndex = + UniformRefractiveIndex<HomogeneousMedium<IRefractiveIndexModel<IMediumModel>>>; + // the antenna location - const auto point1{Point(env.getCoordinateSystem(), 1_m, 2_m, 3_m)}; - const auto point2{Point(env.getCoordinateSystem(), 4_m, 5_m, 6_m)}; + const auto point1{Point(env6.getCoordinateSystem(), 1_m, 2_m, 3_m)}; + const auto point2{Point(env6.getCoordinateSystem(), 4_m, 5_m, 6_m)}; + + + // get a coordinate system + const CoordinateSystemPtr rootCS6 = env6.getCoordinateSystem(); + + auto Medium6 = EnvType::createNode<Sphere>( + Point{rootCS6, 0_m, 0_m, 0_m}, 1_km * std::numeric_limits<double>::infinity()); + + auto const props6 = Medium6->setModelProperties<UniRIndex>( + 1, 1_kg / (1_m * 1_m * 1_m), + NuclearComposition( + std::vector<Code>{Code::Nitrogen}, + std::vector<float>{1.f})); + + env6.getUniverse()->addChild(std::move(Medium6)); // create times for the antenna const TimeType t1{10_s}; @@ -97,18 +210,18 @@ TEST_CASE("Radio", "[processes]") { // // // add this antenna to the process // detector.addAntenna(ant1); -//// detector.addAntenna(ant2); +// detector.addAntenna(ant2); -// // get a unit vector -// Vector<dimensionless_d> v1(rootCS6, {0, 0, 1}); -// QuantityVector<ElectricFieldType::dimension_type> v11{10_V / 1_m, 10_V / 1_m, 10_V / 1_m}; -// -// Vector<dimensionless_d> v2(rootCS6, {0, 1, 0}); -// QuantityVector<ElectricFieldType::dimension_type> v22{20_V / 1_m, 20_V / 1_m, 20_V / 1_m}; -// -// // use receive methods -// ant1.receive(15_s, v1, v11); -// ant2.receive(16_s, v2, v22); + // get a unit vector + Vector<dimensionless_d> v1(rootCS6, {0, 0, 1}); + QuantityVector<ElectricFieldType::dimension_type> v11{10_V / 1_m, 10_V / 1_m, 10_V / 1_m}; + + Vector<dimensionless_d> v2(rootCS6, {0, 1, 0}); + QuantityVector<ElectricFieldType::dimension_type> v22{20_V / 1_m, 20_V / 1_m, 20_V / 1_m}; + + // use receive methods + ant1.receive(15_s, v1, v11); + ant2.receive(16_s, v2, v22); // TODO: this is crucial to be solved I thought it was the getAntenna() method but nope. // Tried the same with a good old out of the box std::vector and still no luck @@ -122,12 +235,12 @@ TEST_CASE("Radio", "[processes]") { // } -// // use getWaveform() method -// auto [t11, E1] = ant1.getWaveform(); -// CHECK(E1(5,0) - 10 == 0); -// -// auto [t222, E2] = ant2.getWaveform(); -// CHECK(E2(5,0) -20 == 0); + // use getWaveform() method + auto [t11, E1] = ant1.getWaveform(); + CHECK(E1(5,0) - 10 == 0); + + auto [t222, E2] = ant2.getWaveform(); + CHECK(E2(5,0) -20 == 0); // the rest is just random ideas @@ -196,185 +309,185 @@ TEST_CASE("Radio", "[processes]") { } // check that I can create working Straight Propagators in different environments -// SECTION("Straight Propagator w/ Uniform Refractive Index") { -// -// // create an environment with uniform refractive index of 1 -// using UniRIndex = -// UniformRefractiveIndex<HomogeneousMedium<IRefractiveIndexModel<IMediumModel>>>; -// -// using EnvType = Environment<IRefractiveIndexModel<IMediumModel>>; -// EnvType env; -// -// // get a coordinate system -// const CoordinateSystemPtr rootCS = env.getCoordinateSystem(); -// -// auto Medium = EnvType::createNode<Sphere>( -// Point{rootCS, 0_m, 0_m, 0_m}, 1_km * std::numeric_limits<double>::infinity()); -// -// auto const props = Medium->setModelProperties<UniRIndex>( -// 1, 1_kg / (1_m * 1_m * 1_m), -// NuclearComposition( -// std::vector<Code>{Code::Nitrogen}, -// std::vector<float>{1.f})); -// -// env.getUniverse()->addChild(std::move(Medium)); -// -// // get some points -// Point p0(rootCS, {0_m, 0_m, 0_m}); -// // Point p1(rootCS, {0_m, 0_m, 1_m}); -// // Point p2(rootCS, {0_m, 0_m, 2_m}); -// // Point p3(rootCS, {0_m, 0_m, 3_m}); -// // Point p4(rootCS, {0_m, 0_m, 4_m}); -// // Point p5(rootCS, {0_m, 0_m, 5_m}); -// // Point p6(rootCS, {0_m, 0_m, 6_m}); -// // Point p7(rootCS, {0_m, 0_m, 7_m}); -// // Point p8(rootCS, {0_m, 0_m, 8_m}); -// // Point p9(rootCS, {0_m, 0_m, 9_m}); -// Point p10(rootCS, {0_m, 0_m, 10_m}); -// -// // get a unit vector -// Vector<dimensionless_d> v1(rootCS, {0, 0, 1}); -// -// // // get a geometrical path of points -// // Path P1({p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10}); -// -// // construct a Straight Propagator given the uniform refractive index environment -// StraightPropagator SP(env); -// -// // store the outcome of the Propagate method to paths_ -// auto const paths_ = SP.propagate(p0, p10, 1_m); -// -// // perform checks to paths_ components -// for (auto const& path : paths_) { -// CHECK((path.total_time_ / 1_s) - ((34_m / (3 * constants::c)) / 1_s) == -// Approx(0).margin(absMargin)); -// CHECK(path.average_refractive_index_ == Approx(1)); -// CHECK(path.emit_.getComponents() == v1.getComponents()); -// CHECK(path.receive_.getComponents() == v1.getComponents()); -// CHECK(path.R_distance_ == 10_m); -// // CHECK(std::equal(P1.begin(), P1.end(), path.points_.begin(),[] -// // (Point a, Point b) { return (a - b).norm() / 1_m < 1e-5;})); -// //TODO:THINK ABOUT THE POINTS IN THE SIGNALPATH.H -// } -// -// CHECK(paths_.size() == 1); -// } -// -// SECTION("Straight Propagator w/ Exponential Refractive Index") { -// -//// logging::set_level(logging::level::info); -//// corsika_logger->set_pattern("[%n:%^%-8l%$] custom pattern: %v"); -// -// // create an environment with exponential refractive index (n_0 = 1 & lambda = 0) -// using ExpoRIndex = ExponentialRefractiveIndex<HomogeneousMedium -// <IRefractiveIndexModel<IMediumModel>>>; -// -// using EnvType = Environment<IRefractiveIndexModel<IMediumModel>>; -// EnvType env1; -// -// //get another coordinate system -// const CoordinateSystemPtr rootCS1 = env1.getCoordinateSystem(); -// -// auto Medium1 = EnvType::createNode<Sphere>( -// Point{rootCS1, 0_m, 0_m, 0_m}, 1_km * std::numeric_limits<double>::infinity()); -// -// auto const props1 = -// Medium1 -// ->setModelProperties<ExpoRIndex>( 1, 0 / 1_m, -// 1_kg / (1_m * 1_m * 1_m), -// NuclearComposition( -// std::vector<Code>{Code::Nitrogen}, -// std::vector<float>{1.f})); -// -// env1.getUniverse()->addChild(std::move(Medium1)); -// -// // get some points -// Point pp0(rootCS1, {0_m, 0_m, 0_m}); -//// Point pp1(rootCS1, {0_m, 0_m, 1_m}); -//// Point pp2(rootCS1, {0_m, 0_m, 2_m}); -//// Point pp3(rootCS1, {0_m, 0_m, 3_m}); -//// Point pp4(rootCS1, {0_m, 0_m, 4_m}); -//// Point pp5(rootCS1, {0_m, 0_m, 5_m}); -//// Point pp6(rootCS1, {0_m, 0_m, 6_m}); -//// Point pp7(rootCS1, {0_m, 0_m, 7_m}); -//// Point pp8(rootCS1, {0_m, 0_m, 8_m}); -//// Point pp9(rootCS1, {0_m, 0_m, 9_m}); -// Point pp10(rootCS1, {0_m, 0_m, 10_m}); -// -// // get a unit vector -// Vector<dimensionless_d> vv1(rootCS1, {0, 0, 1}); -// -// // construct a Straight Propagator given the exponential refractive index environment -// StraightPropagator SP1(env1); -// -// // store the outcome of Propagate method to paths1_ -// auto const paths1_ = SP1.propagate(pp0, pp10, 1_m); -// -// // perform checks to paths1_ components (this is just a sketch for now) -// for (auto const& path :paths1_) { -// CHECK( (path.total_time_ / 1_s) - ((34_m / (3 * constants::c)) / 1_s) -// == Approx(0).margin(absMargin) ); -// CHECK( path.average_refractive_index_ == Approx(1) ); -// CHECK( path.emit_.getComponents() == vv1.getComponents() ); -// CHECK( path.receive_.getComponents() == vv1.getComponents() ); -// CHECK( path.R_distance_ == 10_m ); -// } -// -// CHECK( paths1_.size() == 1 ); -// -// /* -// * A second environment with another exponential refractive index -// */ -// -// // create an environment with exponential refractive index (n_0 = 2 & lambda = 2) -// using ExpoRIndex = ExponentialRefractiveIndex<HomogeneousMedium -// <IRefractiveIndexModel<IMediumModel>>>; -// -// using EnvType = Environment<IRefractiveIndexModel<IMediumModel>>; -// EnvType env2; -// -// //get another coordinate system -// const CoordinateSystemPtr rootCS2 = env2.getCoordinateSystem(); -// -// auto Medium2 = EnvType::createNode<Sphere>( -// Point{rootCS2, 0_m, 0_m, 0_m}, 1_km * std::numeric_limits<double>::infinity()); -// -// auto const props2 = -// Medium2 -// ->setModelProperties<ExpoRIndex>( 2, 2 / 1_m, -// 1_kg / (1_m * 1_m * 1_m), -// NuclearComposition( -// std::vector<Code>{Code::Nitrogen}, -// std::vector<float>{1.f})); -// -// env2.getUniverse()->addChild(std::move(Medium2)); -// -// // get some points -// Point ppp0(rootCS2, {0_m, 0_m, 0_m}); -// Point ppp10(rootCS2, {0_m, 0_m, 10_m}); -// -// // get a unit vector -// Vector<dimensionless_d> vvv1(rootCS2, {0, 0, 1}); -// -// // construct a Straight Propagator given the exponential refractive index environment -// StraightPropagator SP2(env2); -// -// // store the outcome of Propagate method to paths1_ -// auto const paths2_ = SP2.propagate(ppp0, ppp10, 1_m); -// -// // perform checks to paths1_ components (this is just a sketch for now) -// for (auto const& path :paths2_) { -// CHECK( (path.total_time_ / 1_s) - ((3.177511688_m / (3 * constants::c)) / 1_s) -// == Approx(0).margin(absMargin) ); -// CHECK( path.average_refractive_index_ == Approx(0.210275935) ); -// CHECK( path.emit_.getComponents() == vvv1.getComponents() ); -// CHECK( path.receive_.getComponents() == vvv1.getComponents() ); -// CHECK( path.R_distance_ == 10_m ); -// } -// -// CHECK( paths2_.size() == 1 ); -// -// } + SECTION("Straight Propagator w/ Uniform Refractive Index") { + + // create an environment with uniform refractive index of 1 + using UniRIndex = + UniformRefractiveIndex<HomogeneousMedium<IRefractiveIndexModel<IMediumModel>>>; + + using EnvType = Environment<IRefractiveIndexModel<IMediumModel>>; + EnvType env; + + // get a coordinate system + const CoordinateSystemPtr rootCS = env.getCoordinateSystem(); + + auto Medium = EnvType::createNode<Sphere>( + Point{rootCS, 0_m, 0_m, 0_m}, 1_km * std::numeric_limits<double>::infinity()); + + auto const props = Medium->setModelProperties<UniRIndex>( + 1, 1_kg / (1_m * 1_m * 1_m), + NuclearComposition( + std::vector<Code>{Code::Nitrogen}, + std::vector<float>{1.f})); + + env.getUniverse()->addChild(std::move(Medium)); + + // get some points + Point p0(rootCS, {0_m, 0_m, 0_m}); + // Point p1(rootCS, {0_m, 0_m, 1_m}); + // Point p2(rootCS, {0_m, 0_m, 2_m}); + // Point p3(rootCS, {0_m, 0_m, 3_m}); + // Point p4(rootCS, {0_m, 0_m, 4_m}); + // Point p5(rootCS, {0_m, 0_m, 5_m}); + // Point p6(rootCS, {0_m, 0_m, 6_m}); + // Point p7(rootCS, {0_m, 0_m, 7_m}); + // Point p8(rootCS, {0_m, 0_m, 8_m}); + // Point p9(rootCS, {0_m, 0_m, 9_m}); + Point p10(rootCS, {0_m, 0_m, 10_m}); + + // get a unit vector + Vector<dimensionless_d> v1(rootCS, {0, 0, 1}); + + // // get a geometrical path of points + // Path P1({p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10}); + + // construct a Straight Propagator given the uniform refractive index environment + StraightPropagator SP(env); + + // store the outcome of the Propagate method to paths_ + auto const paths_ = SP.propagate(p0, p10, 1_m); + + // perform checks to paths_ components + for (auto const& path : paths_) { + CHECK((path.total_time_ / 1_s) - ((34_m / (3 * constants::c)) / 1_s) == + Approx(0).margin(absMargin)); + CHECK(path.average_refractive_index_ == Approx(1)); + CHECK(path.emit_.getComponents() == v1.getComponents()); + CHECK(path.receive_.getComponents() == v1.getComponents()); + CHECK(path.R_distance_ == 10_m); + // CHECK(std::equal(P1.begin(), P1.end(), path.points_.begin(),[] + // (Point a, Point b) { return (a - b).norm() / 1_m < 1e-5;})); + //TODO:THINK ABOUT THE POINTS IN THE SIGNALPATH.H + } + + CHECK(paths_.size() == 1); + } + + SECTION("Straight Propagator w/ Exponential Refractive Index") { + +// logging::set_level(logging::level::info); +// corsika_logger->set_pattern("[%n:%^%-8l%$] custom pattern: %v"); + + // create an environment with exponential refractive index (n_0 = 1 & lambda = 0) + using ExpoRIndex = ExponentialRefractiveIndex<HomogeneousMedium + <IRefractiveIndexModel<IMediumModel>>>; + + using EnvType = Environment<IRefractiveIndexModel<IMediumModel>>; + EnvType env1; + + //get another coordinate system + const CoordinateSystemPtr rootCS1 = env1.getCoordinateSystem(); + + auto Medium1 = EnvType::createNode<Sphere>( + Point{rootCS1, 0_m, 0_m, 0_m}, 1_km * std::numeric_limits<double>::infinity()); + + auto const props1 = + Medium1 + ->setModelProperties<ExpoRIndex>( 1, 0 / 1_m, + 1_kg / (1_m * 1_m * 1_m), + NuclearComposition( + std::vector<Code>{Code::Nitrogen}, + std::vector<float>{1.f})); + + env1.getUniverse()->addChild(std::move(Medium1)); + + // get some points + Point pp0(rootCS1, {0_m, 0_m, 0_m}); +// Point pp1(rootCS1, {0_m, 0_m, 1_m}); +// Point pp2(rootCS1, {0_m, 0_m, 2_m}); +// Point pp3(rootCS1, {0_m, 0_m, 3_m}); +// Point pp4(rootCS1, {0_m, 0_m, 4_m}); +// Point pp5(rootCS1, {0_m, 0_m, 5_m}); +// Point pp6(rootCS1, {0_m, 0_m, 6_m}); +// Point pp7(rootCS1, {0_m, 0_m, 7_m}); +// Point pp8(rootCS1, {0_m, 0_m, 8_m}); +// Point pp9(rootCS1, {0_m, 0_m, 9_m}); + Point pp10(rootCS1, {0_m, 0_m, 10_m}); + + // get a unit vector + Vector<dimensionless_d> vv1(rootCS1, {0, 0, 1}); + + // construct a Straight Propagator given the exponential refractive index environment + StraightPropagator SP1(env1); + + // store the outcome of Propagate method to paths1_ + auto const paths1_ = SP1.propagate(pp0, pp10, 1_m); + + // perform checks to paths1_ components (this is just a sketch for now) + for (auto const& path :paths1_) { + CHECK( (path.total_time_ / 1_s) - ((34_m / (3 * constants::c)) / 1_s) + == Approx(0).margin(absMargin) ); + CHECK( path.average_refractive_index_ == Approx(1) ); + CHECK( path.emit_.getComponents() == vv1.getComponents() ); + CHECK( path.receive_.getComponents() == vv1.getComponents() ); + CHECK( path.R_distance_ == 10_m ); + } + + CHECK( paths1_.size() == 1 ); + + /* + * A second environment with another exponential refractive index + */ + + // create an environment with exponential refractive index (n_0 = 2 & lambda = 2) + using ExpoRIndex = ExponentialRefractiveIndex<HomogeneousMedium + <IRefractiveIndexModel<IMediumModel>>>; + + using EnvType = Environment<IRefractiveIndexModel<IMediumModel>>; + EnvType env2; + + //get another coordinate system + const CoordinateSystemPtr rootCS2 = env2.getCoordinateSystem(); + + auto Medium2 = EnvType::createNode<Sphere>( + Point{rootCS2, 0_m, 0_m, 0_m}, 1_km * std::numeric_limits<double>::infinity()); + + auto const props2 = + Medium2 + ->setModelProperties<ExpoRIndex>( 2, 2 / 1_m, + 1_kg / (1_m * 1_m * 1_m), + NuclearComposition( + std::vector<Code>{Code::Nitrogen}, + std::vector<float>{1.f})); + + env2.getUniverse()->addChild(std::move(Medium2)); + + // get some points + Point ppp0(rootCS2, {0_m, 0_m, 0_m}); + Point ppp10(rootCS2, {0_m, 0_m, 10_m}); + + // get a unit vector + Vector<dimensionless_d> vvv1(rootCS2, {0, 0, 1}); + + // construct a Straight Propagator given the exponential refractive index environment + StraightPropagator SP2(env2); + + // store the outcome of Propagate method to paths1_ + auto const paths2_ = SP2.propagate(ppp0, ppp10, 1_m); + + // perform checks to paths1_ components (this is just a sketch for now) + for (auto const& path :paths2_) { + CHECK( (path.total_time_ / 1_s) - ((3.177511688_m / (3 * constants::c)) / 1_s) + == Approx(0).margin(absMargin) ); + CHECK( path.average_refractive_index_ == Approx(0.210275935) ); + CHECK( path.emit_.getComponents() == vvv1.getComponents() ); + CHECK( path.receive_.getComponents() == vvv1.getComponents() ); + CHECK( path.R_distance_ == 10_m ); + } + + CHECK( paths2_.size() == 1 ); + + } // SECTION("ZHS process") { // // first step is to construct an environment for the propagation (uni index) -- GitLab