From a9e4841230c9d344277bf43802e03bed4fe31c36 Mon Sep 17 00:00:00 2001
From: Felix Riehn <felix@matilda>
Date: Wed, 13 Feb 2019 19:05:56 +0000
Subject: [PATCH] started nucleus initialization

---
 Processes/Sibyll/NuclearInteraction.cc | 84 ++++++++++++++++++++++++++
 Processes/Sibyll/NuclearInteraction.h  |  5 +-
 Processes/Sibyll/nuclib.h              | 11 ++++
 Processes/Sibyll/signuc.f              | 43 +++++++++++++
 4 files changed, 142 insertions(+), 1 deletion(-)

diff --git a/Processes/Sibyll/NuclearInteraction.cc b/Processes/Sibyll/NuclearInteraction.cc
index 6a3736323..64013f054 100644
--- a/Processes/Sibyll/NuclearInteraction.cc
+++ b/Processes/Sibyll/NuclearInteraction.cc
@@ -54,8 +54,92 @@ namespace corsika::process::sibyll {
     // initialize nuclib
     // TODO: make sure this does not overlap with sibyll
     nuc_nuc_ini_();
+
+    // initialize cross sections
+    InitializeNuclearCrossSections();
+  }
+
+  void NuclearInteraction::InitializeNuclearCrossSections()
+  {
+    using namespace corsika::particles;
+    using namespace units::si;
+    // TODO: get composition of target volumes from environment
+    // now: hard coded list for air
+    constexpr Code target_nuclei[] = { Code::Oxygen, Code::Nitrogen };
+
+    int fNSample = 500; // number of samples in MC estimation of cross section
+
+    cout << "NuclearInteraction: initializing nuclear cross sections..." << endl;
+    
+    // loop over target components, at most 4!!
+    int k =-1;
+    for(auto &ptarg: target_nuclei){
+      ++k;
+      cout << "NuclearInteraction: init target component: " << ptarg << endl;
+      const int ib = GetNucleusA( ptarg );
+      // fill map,list or what ever
+      // TODO
+      // loop over energies, 6 log. energy bins
+      for(int i=0; i<6; ++i){
+	// hard coded energy grid, has to be aligned to definition in signuc2!!, no comment..
+	const units::si::HEPEnergyType Ecm = pow(10., 1. + 1.*i ) * 1_GeV;
+	// get p-p cross sections
+	auto const protonId = Code::Proton;
+	auto const [siginel, sigela, dum ] =
+	  fHadronicInteraction.GetCrossSection(protonId, protonId, Ecm); 
+	const double dsig = siginel / 1_mbarn;
+	const double dsigela = sigela / 1_mbarn;
+	// loop over projectiles
+	for(int j=0; j<56; ++j){
+	  const int jj = j+1;
+	  double sig_out, dsig_out, sigqe_out, dsigqe_out;
+	  // cout << "energy="<< Ecm/1_GeV << " sig_pp=" << dsig
+	  //      << " (A,B)=" << jj << "," << ib
+	  //      << " sig="<<sig_out << " err(%)=" << dsig_out/sig_out*100.
+	  //      << endl;
+	  sigma_mc_(jj,ib,dsig,dsigela,fNSample, sig_out, dsig_out, sigqe_out, dsigqe_out);
+	  // write to table
+	  cnucsignuc_.sigma[j][k][i] = sig_out;
+	  cnucsignuc_.sigqe[j][k][i] = sigqe_out;
+	}
+      }
+    }
+    cout << "NuclearInteraction: cross sections initialized!" << endl;
+    PrintCrossSectionTable(0);
+    PrintCrossSectionTable(1);
+    PrintCrossSectionTable(2);
+    throw std::runtime_error("stop here");
   }
 
+  void NuclearInteraction::PrintCrossSectionTable(int k)
+  {
+    int nuclA  [] = {2,4,8,20,35,56};
+    cout << "en/A ";
+    for(int j=0; j<6; ++j)
+      cout << std::setw(8) << nuclA[j];
+    cout << endl;
+    
+    for(int i=0; i<6; ++i){
+      cout << " " << i << "  ";
+      for(int j=0; j<6; ++j){
+	cout << " " << std::setprecision(5) << std::setw(7) << cnucsignuc_.sigma[nuclA[j]-1][k][i];
+      }
+      cout << endl;      
+    }
+  }
+  
+  units::si::CrossSectionType NuclearInteraction::ReadCrossSectionTable(particles::Code pBeam, particles::Code pTarget, units::si::HEPEnergyType elabnuc)
+  {
+    using namespace corsika::particles;
+    using namespace units::si;
+    const int ia = GetNucleusA(pBeam);
+    const int ib = GetNucleusA(pTarget);
+    const double e0 = elabnuc/ 1_GeV;
+    double sig;
+    signuc2_(ia,ib,e0,sig);
+    return sig * 1_mbarn;
+  }
+  
   // TODO: remove number of nucleons, avg target mass is available in environment
   template <>
   tuple<units::si::CrossSectionType, units::si::CrossSectionType>
diff --git a/Processes/Sibyll/NuclearInteraction.h b/Processes/Sibyll/NuclearInteraction.h
index cf1f65933..0653a0526 100644
--- a/Processes/Sibyll/NuclearInteraction.h
+++ b/Processes/Sibyll/NuclearInteraction.h
@@ -40,7 +40,10 @@ namespace corsika::process::sibyll {
                        corsika::process::sibyll::Interaction& hadint);
     ~NuclearInteraction();
     void Init();
-
+    void InitializeNuclearCrossSections();
+    void PrintCrossSectionTable(int);
+    corsika::units::si::CrossSectionType ReadCrossSectionTable(corsika::particles::Code, corsika::particles::Code, corsika::units::si::HEPEnergyType);
+    
     template <typename Particle>
     std::tuple<corsika::units::si::CrossSectionType, corsika::units::si::CrossSectionType>
     GetCrossSection(Particle& p, const corsika::particles::Code TargetId);
diff --git a/Processes/Sibyll/nuclib.h b/Processes/Sibyll/nuclib.h
index e4b89b52b..ddd1856cd 100644
--- a/Processes/Sibyll/nuclib.h
+++ b/Processes/Sibyll/nuclib.h
@@ -34,6 +34,13 @@ extern struct {
 */
 extern struct { double ppp[60][3]; } fragments_;
 
+  //        COMMON /cnucsignuc/SIGMA(6,4,56), SIGQE(6,4,56)
+  extern struct
+  {
+    double sigma[56][4][6];
+    double sigqe[56][4][6];
+  } cnucsignuc_;
+  
 // NUCLIB
 
 // subroutine to initiate nuclib
@@ -46,5 +53,9 @@ void int_nuc_(const int&, const int&, const double&, const double&);
 void fragm_(const int&, const int&, const int&, const double&, int&, int*);
 
 void signuc_(const int&, const double&, double&);
+
+void signuc2_(const int&, const int&, const double&, double&);
+
+void sigma_mc_(const int&, const int&, const double&, const double&, const int&, double&, double&, double&, double&);
 }
 #endif
diff --git a/Processes/Sibyll/signuc.f b/Processes/Sibyll/signuc.f
index b21bce8cb..b88f2ae0b 100644
--- a/Processes/Sibyll/signuc.f
+++ b/Processes/Sibyll/signuc.f
@@ -274,3 +274,46 @@ C  ADD INELASTIC AND QUASI-ELASTIC CROSS-SECTIONS
 
       RETURN
       END
+
+
+      SUBROUTINE SIGNUC2(IA,IB,E0,SSIGNUC)
+
+C-----------------------------------------------------------------------
+C     SIG(MA) NUC(LEUS)  2
+C     INPUT: IA : projectile mass number
+C     IB : position in cross section table for target nucleus
+C          specified when tables are filled
+C     E0 : Energy per nucleon in GeV in the lab.
+C     OUTPUT: inelastic cross section
+C-----------------------------------------------------------------------
+      IMPLICIT NONE
+      DOUBLE PRECISION SIGMA,SIGQE
+      COMMON /cnucsignuc/SIGMA(6,4,56), SIGQE(6,4,56)
+      DIMENSION        AA(6)
+      DOUBLE PRECISION AA,DA,AMIN,ABEAM,S1,S2,ASQS
+      DOUBLE PRECISION E0,SSIGNUC
+      INTEGER          IA,IB,J,JE,NE 
+      DOUBLE PRECISION QUAD_INT
+      EXTERNAL         QUAD_INT
+      SAVE
+      DATA             NE /6/, AMIN /1.D0/, DA /1.D0/
+      DATA             AA /1.D0,2.D0,3.D0,4.D0,5.D0,6.D0/
+
+C ENERGY E0 IN GEV
+      ASQS  = 0.5D0*LOG10(1.876D0*E0)
+      JE    = MIN( INT( (ASQS-AMIN)/DA )+1, NE-2 )
+      ABEAM = DBLE(IA)
+C  INELASTIC CROSS-SECTION
+      S1 = QUAD_INT( ASQS, AA(JE),AA(JE+1),AA(JE+2),
+     +     SIGMA(JE,IB,IA),SIGMA(JE+1,IB,IA),
+     +     SIGMA(JE+2,IB,IA) )
+C  QUASI ELASTIC CROSS-SECTION
+      S2 = QUAD_INT( ASQS, AA(JE),AA(JE+1),AA(JE+2),
+     +     SIGQE(JE,IB,IA),SIGQE(JE+1,IB,IA),
+     +     SIGQE(JE+2,IB,IA) )
+C  ADD INELASTIC AND QUASI-ELASTIC CROSS-SECTIONS
+      SSIGNUC = S1 + S2
+
+      RETURN
+      END
+      
-- 
GitLab