From dde62316e863e18392082246e0dbcff6d034b84b Mon Sep 17 00:00:00 2001
From: Maximilian Reininghaus <maximilian.reininghaus@kit.edu>
Date: Thu, 13 Apr 2023 13:34:18 +0200
Subject: [PATCH 1/5] update to latest cxroot master

---
 modules/conex | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/modules/conex b/modules/conex
index 344c875be..c26ca0fad 160000
--- a/modules/conex
+++ b/modules/conex
@@ -1 +1 @@
-Subproject commit 344c875bed534590eb86aa5e12b0382a9868fc64
+Subproject commit c26ca0fada6ef182147d014bb7d413814f9cf202
-- 
GitLab


From 6f04eb6d43d9e1be16cdb4fa5a866ad218c7c77f Mon Sep 17 00:00:00 2001
From: Maximilian Reininghaus <maximilian.reininghaus@kit.edu>
Date: Thu, 13 Apr 2023 13:59:17 +0200
Subject: [PATCH 2/5] add interface for cxair_ common block

---
 corsika/modules/conex/CONEX_f.hpp | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/corsika/modules/conex/CONEX_f.hpp b/corsika/modules/conex/CONEX_f.hpp
index db80137ad..3339903ce 100644
--- a/corsika/modules/conex/CONEX_f.hpp
+++ b/corsika/modules/conex/CONEX_f.hpp
@@ -36,13 +36,18 @@ namespace conex {
 
   extern double double_rndm_interface();
 
-  extern "C" {}
-
   // the CONEX fortran interface
 
   extern "C" {
   extern struct { std::array<double, 16> dptl; } cxoptl_;
 
+  //! common block for atmosphere composition
+  extern struct {
+    std::array<double, 3> airz, aira, airw; //!< nuclear Z, A, composition fraction
+    double airavz, airava;                  //!< average Z, A
+    std::array<double, 3> airi;             //!< ionization potential, not used in cxroot
+  } cxair_;
+
   void cegs4_(int&, int&);
 
   void initconex_(int&, int*, int&, int&,
-- 
GitLab


From 8e7d9024b3dbed0065badcb061dd4f78d1f950c7 Mon Sep 17 00:00:00 2001
From: Maximilian Reininghaus <maximilian.reininghaus@kit.edu>
Date: Thu, 13 Apr 2023 15:03:05 +0200
Subject: [PATCH 3/5] pass callable by value

---
 corsika/detail/media/NuclearComposition.inl | 4 ++--
 corsika/media/NuclearComposition.hpp        | 5 ++---
 2 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/corsika/detail/media/NuclearComposition.inl b/corsika/detail/media/NuclearComposition.inl
index c499a593d..9d1241aab 100644
--- a/corsika/detail/media/NuclearComposition.inl
+++ b/corsika/detail/media/NuclearComposition.inl
@@ -46,7 +46,7 @@ namespace corsika {
   }
 
   template <typename TFunction>
-  inline auto NuclearComposition::getWeighted(TFunction const& func) const {
+  inline auto NuclearComposition::getWeighted(TFunction func) const {
     using ResultQuantity = decltype(func(std::declval<Code>()));
     auto const product = [&](auto const compID, auto const fraction) {
       return func(compID) * fraction;
@@ -66,7 +66,7 @@ namespace corsika {
   } // namespace corsika
 
   template <typename TFunction>
-  inline auto NuclearComposition::getWeightedSum(TFunction const& func) const
+  inline auto NuclearComposition::getWeightedSum(TFunction func) const
       -> decltype(func(std::declval<Code>())) {
     using ResultQuantity = decltype(func(std::declval<Code>()));
 
diff --git a/corsika/media/NuclearComposition.hpp b/corsika/media/NuclearComposition.hpp
index 184853ef2..402969edb 100644
--- a/corsika/media/NuclearComposition.hpp
+++ b/corsika/media/NuclearComposition.hpp
@@ -51,7 +51,7 @@ namespace corsika {
      *  @retval returns the vector with weighted return types of func.
      */
     template <typename TFunction>
-    auto getWeighted(TFunction const& func) const;
+    auto getWeighted(TFunction func) const;
 
     /**
      * Sum all all relative composition weighted by func(element)
@@ -65,8 +65,7 @@ namespace corsika {
      *  @retval returns the weighted sum with the type defined by the return type of func.
      */
     template <typename TFunction>
-    auto getWeightedSum(TFunction const& func) const
-        -> decltype(func(std::declval<Code>()));
+    auto getWeightedSum(TFunction func) const -> decltype(func(std::declval<Code>()));
 
     /**
      * Number of elements in the composition array
-- 
GitLab


From 611b966db663dd0ce2c94679c610cc4f8e034aeb Mon Sep 17 00:00:00 2001
From: Maximilian Reininghaus <maximilian.reininghaus@kit.edu>
Date: Thu, 13 Apr 2023 15:40:31 +0200
Subject: [PATCH 4/5] introduce standardAirComposition object

---
 corsika/detail/media/CORSIKA7Atmospheres.inl | 8 +-------
 corsika/media/CORSIKA7Atmospheres.hpp        | 7 ++++++-
 2 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/corsika/detail/media/CORSIKA7Atmospheres.inl b/corsika/detail/media/CORSIKA7Atmospheres.inl
index 1e18dffb3..3e5c86e76 100644
--- a/corsika/detail/media/CORSIKA7Atmospheres.inl
+++ b/corsika/detail/media/CORSIKA7Atmospheres.inl
@@ -20,13 +20,7 @@ namespace corsika {
         TEnvironmentInterface, TExtraEnv>::create(center, constants::EarthRadius::Mean,
                                                   std::forward<TArgs>(args)...);
 
-    // composition values from AIRES manual
-    builder.setNuclearComposition({{
-                                       Code::Nitrogen,
-                                       Code::Argon,
-                                       Code::Oxygen,
-                                   },
-                                   {0.7847, 0.0047, 1. - 0.7847 - 0.0047}});
+    builder.setNuclearComposition(standardAirComposition);
 
     // add the standard atmosphere layers
     auto const params = atmosphereParameterList[static_cast<uint8_t>(atmId)];
diff --git a/corsika/media/CORSIKA7Atmospheres.hpp b/corsika/media/CORSIKA7Atmospheres.hpp
index 0eb0b6a7a..cba81771f 100644
--- a/corsika/media/CORSIKA7Atmospheres.hpp
+++ b/corsika/media/CORSIKA7Atmospheres.hpp
@@ -11,6 +11,7 @@
 #include <corsika/media/IRefractiveIndexModel.hpp>
 #include <corsika/media/LayeredSphericalAtmosphereBuilder.hpp>
 #include <corsika/framework/utility/ImplementsMixin.hpp>
+#include <corsika/media/NuclearComposition.hpp>
 
 // for detail namespace, NoExtraModelInner, NoExtraModel and traits
 #include <corsika/detail/media/LayeredSphericalAtmosphereBuilder.hpp>
@@ -204,6 +205,10 @@ namespace corsika {
   void create_5layer_atmosphere(TEnvironment& env, AtmosphereId const atmId,
                                 Point const& center, TArgs... args);
 
+  //! The standard/default air composition with fraction values based on CORSIKA 7
+  static inline NuclearComposition const standardAirComposition{
+      {Code::Nitrogen, Code::Oxygen, Code::Argon}, {0.78479, .21052, 0.00469}};
+
 } // namespace corsika
 
-#include <corsika/detail/media/CORSIKA7Atmospheres.inl>
\ No newline at end of file
+#include <corsika/detail/media/CORSIKA7Atmospheres.inl>
-- 
GitLab


From 7fbd71180610712b8be2ef75030013d0434262d4 Mon Sep 17 00:00:00 2001
From: Maximilian Reininghaus <maximilian.reininghaus@kit.edu>
Date: Thu, 13 Apr 2023 15:54:14 +0200
Subject: [PATCH 5/5] initialize cxair_ from standardAirComposition

---
 corsika/detail/modules/conex/CONEXhybrid.inl | 25 +++++++++++++++++++-
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/corsika/detail/modules/conex/CONEXhybrid.inl b/corsika/detail/modules/conex/CONEXhybrid.inl
index e42ca29fc..d2ae2a2b4 100644
--- a/corsika/detail/modules/conex/CONEXhybrid.inl
+++ b/corsika/detail/modules/conex/CONEXhybrid.inl
@@ -7,6 +7,7 @@
  */
 
 #include <corsika/framework/core/Logging.hpp>
+#include <corsika/media/CORSIKA7Atmospheres.hpp>
 #include <corsika/modules/conex/CONEXhybrid.hpp>
 #include <corsika/modules/conex/CONEX_f.hpp>
 #include <corsika/framework/random/RNGManager.hpp>
@@ -17,7 +18,7 @@
 
 #include <algorithm>
 #include <fstream>
-#include <iomanip>
+#include <numeric>
 #include <utility>
 
 namespace corsika {
@@ -83,6 +84,28 @@ namespace corsika {
     CORSIKA_LOG_DEBUG("showerCore (C8): {}",
                       showerCore_.getCoordinates(center.getCoordinateSystem()));
 
+    auto const& components = ::corsika::standardAirComposition.getComponents();
+    auto const& fractions = ::corsika::standardAirComposition.getFractions();
+    if (::corsika::standardAirComposition.getSize() != 3) {
+      throw std::runtime_error{"CONEXhybrid only usable with standard 3-component air"};
+    }
+
+    std::transform(components.cbegin(), components.cend(), ::conex::cxair_.aira.begin(),
+                   get_nucleus_A);
+    std::transform(components.cbegin(), components.cend(), ::conex::cxair_.airz.begin(),
+                   get_nucleus_Z);
+    std::copy(fractions.cbegin(), fractions.cend(), ::conex::cxair_.airw.begin());
+
+    ::conex::cxair_.airava =
+        std::inner_product(::conex::cxair_.airw.cbegin(), ::conex::cxair_.airw.cend(),
+                           ::conex::cxair_.aira.cbegin(), 0.);
+    ::conex::cxair_.airavz =
+        std::inner_product(::conex::cxair_.airw.cbegin(), ::conex::cxair_.airw.cend(),
+                           ::conex::cxair_.airz.cbegin(), 0.);
+
+    // this is the CONEX default but actually unused there
+    ::conex::cxair_.airi = {82.0e-09, 95.0e-09, 188.e-09};
+
     int randomSeeds[3] = {1234, 0,
                           0}; // SEEDS ARE NOT USED. All random numbers are obtained from
                               // the CORSIKA 8 stream "conex" and "epos"!
-- 
GitLab