IAP GITLAB

Skip to content
Snippets Groups Projects
testRadio.cpp 18.7 KiB
Newer Older
/*
 * (c) Copyright 2020 CORSIKA Project, corsika-project@lists.kit.edu
 *
 * This software is distributed under the terms of the GNU General Public
 * Licence version 3 (GPL Version 3). See file LICENSE for a full version of
 * the license.
 */
#include <catch2/catch.hpp>

#include <corsika/modules/radio/ZHS.hpp>
#include <corsika/modules/radio/CoREAS.hpp>
#include <corsika/modules/radio/antennas/TimeDomainAntenna.hpp>
#include <corsika/modules/radio/detectors/RadioDetector.hpp>
#include <corsika/modules/radio/propagators/StraightPropagator.hpp>
#include <corsika/modules/radio/propagators/SignalPath.hpp>
#include <corsika/modules/radio/propagators/RadioPropagator.hpp>

#include <vector>
#include <xtensor/xtensor.hpp>
#include <xtensor/xbuilder.hpp>
#include <xtensor/xio.hpp>
#include <xtensor/xcsv.hpp>
#include <istream>
#include <fstream>
#include <iostream>

#include <corsika/media/Environment.hpp>
#include <corsika/media/FlatExponential.hpp>
#include <corsika/media/HomogeneousMedium.hpp>
#include <corsika/media/IMagneticFieldModel.hpp>
#include <corsika/media/LayeredSphericalAtmosphereBuilder.hpp>
#include <corsika/media/NuclearComposition.hpp>
#include <corsika/media/MediumPropertyModel.hpp>
#include <corsika/media/UniformMagneticField.hpp>
#include <corsika/media/SlidingPlanarExponential.hpp>


#include <corsika/media/Environment.hpp>
#include <corsika/media/HomogeneousMedium.hpp>
#include <corsika/media/IMediumModel.hpp>
#include <corsika/media/IRefractiveIndexModel.hpp>
#include <corsika/media/LayeredSphericalAtmosphereBuilder.hpp>
#include <corsika/media/UniformRefractiveIndex.hpp>
#include <corsika/media/ExponentialRefractiveIndex.hpp>
#include <corsika/media/VolumeTreeNode.hpp>
#include <corsika/framework/geometry/CoordinateSystem.hpp>
#include <corsika/framework/geometry/Line.hpp>
#include <corsika/framework/geometry/Point.hpp>
#include <corsika/framework/geometry/RootCoordinateSystem.hpp>
#include <corsika/framework/geometry/Vector.hpp>
#include <corsika/setup/SetupStack.hpp>
#include <corsika/setup/SetupEnvironment.hpp>
#include <corsika/setup/SetupTrajectory.hpp>
#include <corsika/framework/core/PhysicalUnits.hpp>
#include <corsika/framework/core/PhysicalConstants.hpp>
#include <corsika/media/UniformMagneticField.hpp>



using namespace corsika;

double constexpr absMargin = 1.0e-7;

TEST_CASE("Radio", "[processes]") {

  SECTION("CoREAS process") {
      // first step is to construct an environment for the propagation (uniform index 1)
    using UniRIndex =
    UniformRefractiveIndex<HomogeneousMedium<IRefractiveIndexModel<IMediumModel>>>;

    using EnvType = Environment<IRefractiveIndexModel<IMediumModel>>;
    EnvType envCoREAS;

    // get a coordinate system
    const CoordinateSystemPtr rootCSCoREAS = envCoREAS.getCoordinateSystem();
    auto MediumCoREAS = EnvType::createNode<Sphere>(
        Point{rootCSCoREAS, 0_m, 0_m, 0_m}, 1_km * std::numeric_limits<double>::infinity());
    auto const propsZHS = MediumCoREAS->setModelProperties<UniRIndex>(
        1, 1_kg / (1_m * 1_m * 1_m),
        NuclearComposition(
            std::vector<Code>{Code::Nitrogen},
            std::vector<float>{1.f}));

    envCoREAS.getUniverse()->addChild(std::move(MediumCoREAS));


    // now create antennas and detectors
    // the antennas location
Nikos Karastathis's avatar
Nikos Karastathis committed
    const auto point1{Point(envCoREAS.getCoordinateSystem(), 100_m, 2_m, 3_m)};
    const auto point2{Point(envCoREAS.getCoordinateSystem(), 4_m, 80_m, 6_m)};
    const auto point3{Point(envCoREAS.getCoordinateSystem(), 7_m, 8_m, 9_m)};
Nikos Karastathis's avatar
Nikos Karastathis committed
    const auto point4{Point(envCoREAS.getCoordinateSystem(), 5_m, 5_m, 10_m)};


    // create times for the antenna
Nikos Karastathis's avatar
Nikos Karastathis committed
    const TimeType t1{0_s};
    const TimeType t2{100_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);
Nikos Karastathis's avatar
Nikos Karastathis committed
    TimeDomainAntenna ant2("antenna_name2", point2, t1, t2, t3);

    // construct a radio detector instance to store our antennas
    AntennaCollection<TimeDomainAntenna> detector;

Nikos Karastathis's avatar
Nikos Karastathis committed
    // add the antennas to the detector
    detector.addAntenna(ant1);
Nikos Karastathis's avatar
Nikos Karastathis committed
    detector.addAntenna(ant2);


    // create a particle
    auto const particle{Code::Electron};
Nikos Karastathis's avatar
Nikos Karastathis committed
//    auto const particle{Code::Gamma};
    const auto pmass{get_mass(particle)};


Nikos Karastathis's avatar
Nikos Karastathis committed
    VelocityVector v0(rootCSCoREAS, {5e+2_m / second, 5e+2_m / second, 5e+2_m / second});

    Vector B0(rootCSCoREAS, 5_T, 5_T, 5_T);

    Line const line(point3, v0);

    auto const k{1_m * ((1_m) / ((1_s * 1_s) * 1_V))};

Nikos Karastathis's avatar
Nikos Karastathis committed
    auto const t = 10000_ms;
    LeapFrogTrajectory base(point4, 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(rootCSCoREAS, {0_GeV, 0_GeV, P0})};

    // and create the location of the particle in this coordinate system
    const Point pos(rootCSCoREAS, 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))};

    auto const charge_ {get_charge(particle1.getPID())};
Nikos Karastathis's avatar
Nikos Karastathis committed
//    std::cout << "charge: " << charge_ << std::endl;
//    std::cout << "1 / c: " << 1. / constants::c << std::endl;
    // set up a track object
//      setup::Tracking tracking;

Nikos Karastathis's avatar
Nikos Karastathis committed
//    auto startPoint_ {base.getPosition(0)};
//    auto midPoint_ {base.getPosition(0.5)};
//    auto endPoint_ {base.getPosition(1)};
//    std::cout << "startPoint_: " << startPoint_ << std::endl;
//    std::cout << "midPoint_: " << midPoint_ << std::endl;
//    std::cout << "endPoint_: " << endPoint_ << std::endl;
Nikos Karastathis's avatar
Nikos Karastathis committed
//    auto velo_ {base.getVelocity(0)};
//    std::cout << "velocity: " << velo_ << std::endl;
Nikos Karastathis's avatar
Nikos Karastathis committed
//    auto startTime_ {particle1.getTime() - base.getDuration()}; // time at the start point of the track hopefully.
//    auto endTime_ {particle1.getTime()};
//    std::cout << "startTime_: " << startTime_ << std::endl;
//    std::cout << "endTime_: " << endTime_ << std::endl;
//
//    auto beta_ {((endPoint_ - startPoint_) / (constants::c * (endTime_ - startTime_))).normalized()};
//    std::cout << "beta_: " << beta_ << std::endl;
Nikos Karastathis's avatar
Nikos Karastathis committed
//    Vector<dimensionless_d> v1(rootCSCoREAS, {0, 0, 1});
//    std::cout << "v1: " << v1.getComponents() << std::endl;
//
//    std::cout << "beta_.dot(v1): " << beta_.dot(v1) << std::endl;
//
//    std::cout << "Pi: " << 1/M_PI << std::endl;
//
//    std::cout << "speed of light: " << constants::c << std::endl;
//
//    std::cout << "vacuum permitivity: " << constants::epsilonZero << std::endl;
Nikos Karastathis's avatar
Nikos Karastathis committed
    // Create a CoREAS instance
//    CoREAS<decltype(detector), decltype(StraightPropagator(envCoREAS))> coreas1(detector, envCoREAS);
Nikos Karastathis's avatar
Nikos Karastathis committed
    // create a radio process instance using CoREAS
    RadioProcess<decltype(detector), CoREAS<decltype(detector), decltype(StraightPropagator(envCoREAS))>, decltype(StraightPropagator(envCoREAS))>
        coreas(detector, envCoREAS);
Nikos Karastathis's avatar
Nikos Karastathis committed
    // check doContinuous and simulate methods
    coreas.doContinuous(particle1, base);
//    coreas1.simulate(particle1, base);
Nikos Karastathis's avatar
Nikos Karastathis committed
    // check writeOutput method -> should produce 2 csv files for each antenna
    coreas.writeOutput();
Nikos Karastathis's avatar
Nikos Karastathis committed
//  SECTION("TimeDomainAntenna") {
//
//    // create an environment so we can get a coordinate system
//    using EnvType = Environment<IRefractiveIndexModel<IMediumModel>>;
//    EnvType env6;
//
//    using UniRIndex =
//    UniformRefractiveIndex<HomogeneousMedium<IRefractiveIndexModel<IMediumModel>>>;
//
//
//    // the antenna location
//    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};
//    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);
//
//    // assert that the antenna name is correct
//    REQUIRE(ant1.getName() == "antenna_name");
//    REQUIRE(ant2.getName() == "antenna_name2");
//
//    // and check that the antenna is at the right location
//    REQUIRE((ant1.getLocation() - point1).getNorm() < 1e-12 * 1_m);
//    REQUIRE((ant2.getLocation() - point2).getNorm() < 1e-12 * 1_m);
//
//    // construct a radio detector instance to store our antennas
//    AntennaCollection<TimeDomainAntenna> detector;
//
//    // add this antenna to the process
//    detector.addAntenna(ant1);
//    detector.addAntenna(ant2);
//    CHECK(detector.size() == 2);
//
//    // 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);
//
//    // use getWaveform() method
//    auto [t111, E1] = ant1.getWaveform();
//    CHECK(E1(5,0) - 10 == 0);
//    auto [t222, E2] = ant2.getWaveform();
//    CHECK(E2(5,0) -20 == 0);
//
//    // use the receive method in a for loop. It works now!
//    for (auto& xx : detector.getAntennas()) {
Nikos Karastathis's avatar
Nikos Karastathis committed
//      xx.receive(15_s, v1, v11);
Nikos Karastathis's avatar
Nikos Karastathis committed
//    // t & E are correct! uncomment to see them
////    for (auto& xx : detector.getAntennas()) {
////      auto [t,E] = xx.getWaveform();
////      std::cout << t << std::endl;
////      std::cout << " ... "<< std::endl;
////      std::cout << E << std::endl;
////      std::cout << " ... "<< std::endl;
////    }
//
//    // check output files. It works, uncomment to see.
////    int i = 1;
////    for (auto& antenna : detector.getAntennas()) {
////
////      auto [t,E] = antenna.getWaveform();
////      auto c0 = xt::hstack(xt::xtuple(t,E));
////      std::ofstream out_file ("antenna" + to_string(i) + "_output.csv");
////      xt::dump_csv(out_file, c0);
////      out_file.close();
////      ++i;
////
////    }
//
//    // check reset method for antennas. Uncomment to see they are zero
////    ant1.reset();
////    ant2.reset();
////
////    std::cout << ant1.waveformE_ << std::endl;
////    std::cout << ant2.waveformE_ << std::endl;
////
////    std::cout << " ... "<< std::endl;
////    std::cout << " ... "<< std::endl;
//
//    // check reset method for antenna collection. Uncomment to see they are zero
////    detector.reset();
////    for (auto& xx : detector.getAntennas()) {
////      std::cout << xx.waveformE_ << std::endl;
////      std::cout << " ... "<< std::endl;
////    }
//
//
//  }
//
//  // 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
//
////      std::cout << "path.total_time_: " << path.total_time_ << std::endl;
////      std::cout << "path.average_refractive_index_: " << path.average_refractive_index_ << std::endl;
////      std::cout << "path.emit_: " << path.emit_.getComponents() << std::endl;
////      std::cout << "path.R_distance_: " << path.R_distance_ << std::endl;
//
Nikos Karastathis's avatar
Nikos Karastathis committed
//    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 );

} // END: TEST_CASE("Radio", "[processes]")