From 03d6cedfdabe7bde37f19cd70fbaba5cda68bb07 Mon Sep 17 00:00:00 2001
From: Maximilian Reininghaus <maximilian.reininghaus@tu-dortmund.de>
Date: Mon, 3 Dec 2018 01:09:19 +0100
Subject: [PATCH] "mechanical" interface seems to work

---
 CMakeLists.txt                      |  1 +
 Environment/CMakeLists.txt          | 51 +++++++++++++++++++++++++++++
 Environment/HomogeneousMedium.h     | 25 ++++++++++++--
 Environment/IMediumModel.h          |  8 +++--
 Environment/NuclearComposition.h    |  7 ++--
 Environment/VolumeTreeNode.h        |  7 ++--
 Environment/testEnvironment.cc      | 20 +++++++++++
 Framework/Geometry/BaseTrajectory.h |  3 ++
 Framework/Geometry/Helix.h          |  9 +++--
 Framework/Geometry/LineTrajectory.h |  5 +++
 Framework/Geometry/Sphere.h         |  2 +-
 Framework/Geometry/Volume.h         |  4 +--
 Framework/Units/PhysicalUnits.h     |  2 +-
 13 files changed, 127 insertions(+), 17 deletions(-)
 create mode 100644 Environment/CMakeLists.txt
 create mode 100644 Environment/testEnvironment.cc

diff --git a/CMakeLists.txt b/CMakeLists.txt
index a04d2acbb..ad72d64fd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -44,6 +44,7 @@ find_package (Eigen3 REQUIRED)
 # order of subdirectories 
 add_subdirectory (ThirdParty)
 add_subdirectory (Framework)
+add_subdirectory (Environment)
 add_subdirectory (Stack)
 add_subdirectory (Processes)
 add_subdirectory (Documentation)
diff --git a/Environment/CMakeLists.txt b/Environment/CMakeLists.txt
new file mode 100644
index 000000000..c69ef3655
--- /dev/null
+++ b/Environment/CMakeLists.txt
@@ -0,0 +1,51 @@
+set (
+  ENVIRONMENT_HEADERS
+  VolumeTreeNode.h
+  IMediumModel.h
+  NuclearComposition.h
+  HomogeneousMedium.h
+  )
+
+set (
+  ENVIRONMENT_NAMESPACE
+  corsika/environment
+  )
+
+add_library (CORSIKAenvironment INTERFACE)
+CORSIKA_COPY_HEADERS_TO_NAMESPACE (CORSIKAenvironment ${ENVIRONMENT_NAMESPACE} ${ENVIRONMENT_HEADERS})
+
+# target dependencies on other libraries (also the header onlys)
+target_link_libraries (
+  CORSIKAenvironment
+  INTERFACE
+  CORSIKAgeometry
+  CORSIKAparticles
+  CORSIKAunits
+  )
+
+target_include_directories (
+  CORSIKAenvironment
+  INTERFACE
+  $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include>
+  $<INSTALL_INTERFACE:include>
+  )
+
+install (
+  TARGETS CORSIKAenvironment
+  LIBRARY DESTINATION lib
+  ARCHIVE DESTINATION lib
+  PUBLIC_HEADER DESTINATION include/${ENVIRONMENT_NAMESPACE}
+  )
+
+# --------------------
+# code unit testing
+add_executable (testEnvironment testEnvironment.cc)
+
+target_link_libraries (
+  testEnvironment
+  CORSIKAenvironment
+  CORSIKAthirdparty # for catch2
+  )
+
+add_test (NAME testGeometry COMMAND testGeometry)
+
diff --git a/Environment/HomogeneousMedium.h b/Environment/HomogeneousMedium.h
index b1a465959..60800a977 100644
--- a/Environment/HomogeneousMedium.h
+++ b/Environment/HomogeneousMedium.h
@@ -2,6 +2,8 @@
 #define _include_HomogeneousMedium_h_
 
 #include <corsika/environment/NuclearComposition.h>
+#include <corsika/geometry/BaseTrajectory.h>
+#include <corsika/geometry/Point.h>
 #include <corsika/particles/ParticleProperties.h>
 #include <corsika/units/PhysicalUnits.h>
 
@@ -13,16 +15,33 @@ namespace corsika::environment {
 
   template <class T>
   class HomogeneousMedium : T {
-    MassDensityType const fDensity;
+    corsika::units::si::MassDensityType const fDensity;
     NuclearComposition const fNuclComp;
 
   public:
-    HomogeneousMedium(MassDensityType pDensity, NuclearComposition pNuclComp)
+    HomogeneousMedium(corsika::units::si::MassDensityType pDensity,
+                      NuclearComposition pNuclComp)
         : fDensity(pDensity)
         , fNuclComp(pNuclComp){};
 
-    MassDensityType GetMassDensity(Point const& p) const override { return fDensity; }
+    corsika::units::si::MassDensityType GetMassDensity([
+        [maybe_unused]] corsika::geometry::Point const& p) const override {
+      return fDensity;
+    }
     NuclearComposition const& GetNuclearComposition() const override { return fNuclComp; }
+
+    corsika::units::si::GrammageType IntegratedGrammage(
+        corsika::geometry::BaseTrajectory const& pTraj,
+        corsika::units::si::TimeType pTo) const override {
+      using namespace corsika::units::si;
+      return pTraj.DistanceBetween(0_s, pTo) * fDensity;
+    }
+
+    corsika::units::si::TimeType FromGrammage(
+        corsika::geometry::BaseTrajectory const& pTraj,
+        corsika::units::si::GrammageType pGrammage) const override {
+      return pTraj.TimeFromArclength(pGrammage / fDensity);
+    }
   };
 
 } // namespace corsika::environment
diff --git a/Environment/IMediumModel.h b/Environment/IMediumModel.h
index f291246cb..8b4548ae7 100644
--- a/Environment/IMediumModel.h
+++ b/Environment/IMediumModel.h
@@ -3,6 +3,7 @@
 
 #include <corsika/environment/NuclearComposition.h>
 #include <corsika/geometry/BaseTrajectory.h>
+#include <corsika/geometry/Point.h>
 #include <corsika/units/PhysicalUnits.h>
 #include <tuple>
 #include <vector>
@@ -15,8 +16,11 @@ namespace corsika::environment {
 
     virtual corsika::units::si::MassDensityType GetMassDensity(
         corsika::geometry::Point const&) const = 0;
-    virtual corsika::units::si::GrammageType IntegratedGrammage(BaseTrajectory const&,
-                                                                double, double) const = 0;
+    virtual corsika::units::si::GrammageType IntegratedGrammage(
+        corsika::geometry::BaseTrajectory const&, corsika::units::si::TimeType) const = 0;
+    virtual corsika::units::si::TimeType FromGrammage(
+        corsika::geometry::BaseTrajectory const&,
+        corsika::units::si::GrammageType) const = 0;
     virtual NuclearComposition const& GetNuclearComposition() const = 0;
   };
 
diff --git a/Environment/NuclearComposition.h b/Environment/NuclearComposition.h
index 0fda0ee44..484f98375 100644
--- a/Environment/NuclearComposition.h
+++ b/Environment/NuclearComposition.h
@@ -1,12 +1,13 @@
 #ifndef _include_NuclearComposition_h
 #define _include_NuclearComposition_h
 
-#include <algorithm>
+#include <corsika/particles/ParticleProperties.h>
+#include <numeric>
 #include <vector>
 
 namespace corsika::environment {
   class NuclearComposition {
-    std::vector<float> const fNumberFractions; //<! relative fractions of number density
+    std::vector<float> const fNumberFractions; //!< relative fractions of number density
     std::vector<corsika::particles::Code> const
         fComponents; //!< particle codes of consitutents
 
@@ -18,7 +19,7 @@ namespace corsika::environment {
       auto const sumFractions =
           std::accumulate(pFractions.cbegin(), pFractions.cend(), 0.f);
 
-      if (!(0.999f < sum && sum < 1.001f)) {
+      if (!(0.999f < sumFractions && sumFractions < 1.001f)) {
         throw std::string("element fractions do not add up to 1");
       }
     }
diff --git a/Environment/VolumeTreeNode.h b/Environment/VolumeTreeNode.h
index 7026ff06e..a1f705542 100644
--- a/Environment/VolumeTreeNode.h
+++ b/Environment/VolumeTreeNode.h
@@ -81,7 +81,7 @@ namespace corsika::environment {
       fModelProperties = std::make_unique<ModelProperties>(std::forward<Args>(args)...);
     }
 
-    auto SetModelProperties(IMPSharedPtr ptr) { fModelProperties = IMPSharedPtr; }
+    void SetModelProperties(IMPSharedPtr ptr) { fModelProperties = ptr; }
 
     template <class MediumType, typename... Args>
     static auto CreateMedium(Args&&... args) {
@@ -94,8 +94,9 @@ namespace corsika::environment {
     // factory methods for creation of nodes
     template <class VolumeType, typename... Args>
     static auto CreateNode(Args&&... args) {
-      static_assert(std::is_base_of_v<Volume, VolumeType>,
-                    "unusable type provided, needs to be derived from \"Volume\"");
+      static_assert(std::is_base_of_v<corsika::geometry::Volume, VolumeType>,
+                    "unusable type provided, needs to be derived from "
+                    "\"corsika::geometry::Volume\"");
 
       return std::make_unique<VolumeTreeNode<IModelProperties>>(
           std::make_unique<VolumeType>(std::forward<Args>(args)...));
diff --git a/Environment/testEnvironment.cc b/Environment/testEnvironment.cc
new file mode 100644
index 000000000..1efbc4e8f
--- /dev/null
+++ b/Environment/testEnvironment.cc
@@ -0,0 +1,20 @@
+#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one
+                          // cpp file
+
+#include <corsika/environment/HomogeneousMedium.h>
+#include <corsika/environment/IMediumModel.h>
+#include <corsika/environment/NuclearComposition.h>
+#include <corsika/environment/VolumeTreeNode.h>
+#include <corsika/particles/ParticleProperties.h>
+#include <catch2/catch.hpp>
+
+using namespace corsika::geometry;
+using namespace corsika::environment;
+using namespace corsika::units::si;
+
+TEST_CASE("HomogeneousMedium") {
+  NuclearComposition const protonComposition(
+      std::vector<corsika::particles::Code>{corsika::particles::Code::Proton},
+      std::vector<float>{1.f});
+  HomogeneousMedium<IMediumModel> const medium(19.2_g / cube(1_cm), protonComposition);
+}
diff --git a/Framework/Geometry/BaseTrajectory.h b/Framework/Geometry/BaseTrajectory.h
index e4eafb853..1b4fd8416 100644
--- a/Framework/Geometry/BaseTrajectory.h
+++ b/Framework/Geometry/BaseTrajectory.h
@@ -24,6 +24,9 @@ namespace corsika::geometry {
 
     virtual LengthType DistanceBetween(corsika::units::si::TimeType t1,
                                        corsika::units::si::TimeType t2) const = 0;
+
+    virtual corsika::units::si::TimeType TimeFromArclength(
+        corsika::units::si::LengthType) const = 0;
   };
 
 } // namespace corsika::geometry
diff --git a/Framework/Geometry/Helix.h b/Framework/Geometry/Helix.h
index bd62d1919..5d9001d34 100644
--- a/Framework/Geometry/Helix.h
+++ b/Framework/Geometry/Helix.h
@@ -47,10 +47,15 @@ namespace corsika::geometry {
 
     auto GetRadius() const { return radius; }
 
-    LengthType DistanceBetween(corsika::units::si::TimeType t1,
-                               corsika::units::si::TimeType t2) const override {
+    corsika::units::si::LengthType DistanceBetween(
+        corsika::units::si::TimeType t1, corsika::units::si::TimeType t2) const override {
       return (vPar + vPerp).norm() * (t2 - t1);
     }
+
+    corsika::units::si::TimeType TimeFromArclength(
+        corsika::units::si::LengthType t) const override {
+      return t / (vPar + vPerp).norm();
+    }
   };
 
 } // namespace corsika::geometry
diff --git a/Framework/Geometry/LineTrajectory.h b/Framework/Geometry/LineTrajectory.h
index ee65b5e54..996d0c431 100644
--- a/Framework/Geometry/LineTrajectory.h
+++ b/Framework/Geometry/LineTrajectory.h
@@ -28,6 +28,11 @@ namespace corsika::geometry {
       assert(t2 >= t1);
       return v0.norm() * (t2 - t1);
     }
+
+    corsika::units::si::TimeType TimeFromArclength(
+        corsika::units::si::LengthType t) const override {
+      return t / v0.norm();
+    }
   };
 
 } // namespace corsika::geometry
diff --git a/Framework/Geometry/Sphere.h b/Framework/Geometry/Sphere.h
index 76699690c..cba9726bc 100644
--- a/Framework/Geometry/Sphere.h
+++ b/Framework/Geometry/Sphere.h
@@ -1,8 +1,8 @@
 #ifndef _include_SPHERE_H_
 #define _include_SPHERE_H_
 
-#include <corsika/geometry/Volume.h>
 #include <corsika/geometry/Point.h>
+#include <corsika/geometry/Volume.h>
 #include <corsika/units/PhysicalUnits.h>
 
 namespace corsika::geometry {
diff --git a/Framework/Geometry/Volume.h b/Framework/Geometry/Volume.h
index badbeb9df..ac892e50b 100644
--- a/Framework/Geometry/Volume.h
+++ b/Framework/Geometry/Volume.h
@@ -6,11 +6,11 @@
 namespace corsika::geometry {
 
   class Volume {
-  
+
   public:
     //! returns true if the Point p is within the volume
     virtual bool Contains(Point const& p) const = 0;
-    
+
     virtual ~Volume() = default;
   };
 
diff --git a/Framework/Units/PhysicalUnits.h b/Framework/Units/PhysicalUnits.h
index 515db9e08..a37c1d4b7 100644
--- a/Framework/Units/PhysicalUnits.h
+++ b/Framework/Units/PhysicalUnits.h
@@ -38,7 +38,7 @@ namespace corsika::units::si {
   using EnergyType = phys::units::quantity<phys::units::energy_d, double>;
   using MassType = phys::units::quantity<phys::units::mass_d, double>;
   using MassDensityType = phys::units::quantity<phys::units::mass_density_d, double>;
-  using GrammageType = phys::units::quantity<phys::units::dimensions<-2,1>, double>;
+  using GrammageType = phys::units::quantity<phys::units::dimensions<-2, 1, 0>, double>;
 
 } // end namespace corsika::units::si
 
-- 
GitLab