From 2d48f5de334108975538973e60d8e2e7e2681d42 Mon Sep 17 00:00:00 2001 From: "Yannick.Schmidt" Date: Mon, 22 Jan 2024 12:23:28 +0100 Subject: [PATCH 01/81] Implementation of a new EBL model from Finke et al. 2022. A new class -- inhereting from the TabularPhotonField class -- was created in the PhotonBackground.h file to fully implement the new EBL model. More over the model was added to various test calculations for every interaction in the testInteraction.cpp script. --- include/crpropa/PhotonBackground.h | 13 +++++++++++++ test/testInteraction.cpp | 14 ++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/include/crpropa/PhotonBackground.h b/include/crpropa/PhotonBackground.h index 7f7d60f8f..1048cda06 100644 --- a/include/crpropa/PhotonBackground.h +++ b/include/crpropa/PhotonBackground.h @@ -233,6 +233,19 @@ class IRB_Saldana21_lower: public TabularPhotonField { IRB_Saldana21_lower() : TabularPhotonField("IRB_Saldana21_lower", true) {} }; +/** + @class IRB_Finke22 + @brief Extragalactic background light model from Finke et al. 2022 + + Source info: + DOI:10.3847/1538-4357/ac9843 + https://iopscience.iop.org/article/10.3847/1538-4357/ac9843/pdf + */ +class IRB_Finke22: public TabularPhotonField { +public: + IRB_Finke22() : TabularPhotonField("IRB_Finke22", true) {} +}; + /** @class URB @brief Extragalactic background light model from Protheroe & Biermann 1996 diff --git a/test/testInteraction.cpp b/test/testInteraction.cpp index e07c60a1c..092a21068 100644 --- a/test/testInteraction.cpp +++ b/test/testInteraction.cpp @@ -40,6 +40,8 @@ TEST(ElectronPairProduction, allBackgrounds) { epp.setPhotonField(IRB); IRB = new IRB_Stecker16_lower(); epp.setPhotonField(IRB); + IRB = new IRB_Finke22(); + epp.setPhotonField(IRB); } TEST(ElectronPairProduction, energyDecreasing) { @@ -342,6 +344,8 @@ TEST(PhotoDisintegration, allBackgrounds) { pd.setPhotonField(IRB); IRB = new IRB_Stecker16_lower(); pd.setPhotonField(IRB); + IRB = new IRB_Finke22(); + pd.setPhotonField(IRB); URB = new URB_Nitu21(); pd.setPhotonField(URB); } @@ -558,6 +562,8 @@ TEST(PhotoPionProduction, allBackgrounds) { ppp.setPhotonField(IRB); IRB = new IRB_Stecker16_lower(); ppp.setPhotonField(IRB); + IRB = new IRB_Finke22(); + ppp.setPhotonField(IRB); ref_ptr URB = new URB_Protheroe96(); ppp.setPhotonField(URB); URB = new URB_Nitu21(); @@ -718,6 +724,8 @@ TEST(EMPairProduction, allBackgrounds) { em.setPhotonField(ebl); ebl = new IRB_Stecker16_lower(); em.setPhotonField(ebl); + ebl = new IRB_Finke22(); + em.setPhotonField(ebl); urb = new URB_Fixsen11(); em.setPhotonField(urb); urb = new URB_Nitu21(); @@ -821,6 +829,8 @@ TEST(EMDoublePairProduction, allBackgrounds) { em.setPhotonField(ebl); ebl = new IRB_Stecker16_lower(); em.setPhotonField(ebl); + ebl = new IRB_Finke22(); + em.setPhotonField(ebl); urb = new URB_Fixsen11(); em.setPhotonField(urb); urb = new URB_Nitu21(); @@ -926,6 +936,8 @@ TEST(EMTripletPairProduction, allBackgrounds) { em.setPhotonField(ebl); ebl = new IRB_Stecker16_lower(); em.setPhotonField(ebl); + ebl = new IRB_Finke22(); + em.setPhotonField(ebl); urb = new URB_Fixsen11(); em.setPhotonField(urb); urb = new URB_Nitu21(); @@ -1030,6 +1042,8 @@ TEST(EMInverseComptonScattering, allBackgrounds) { em.setPhotonField(ebl); ebl = new IRB_Stecker16_lower(); em.setPhotonField(ebl); + ebl = new IRB_Finke22(); + em.setPhotonField(ebl); urb = new URB_Fixsen11(); em.setPhotonField(urb); urb = new URB_Nitu21(); From 72a5eb60fa6f4174c08c81d8bd5dcc6d3085d8d7 Mon Sep 17 00:00:00 2001 From: Rafael Date: Sat, 3 Feb 2024 19:29:25 +0100 Subject: [PATCH 02/81] fix bug related to exception catching with clang 15; apply some code conventions --- CMakeLists.txt | 33 +++++++++++---------------- test/testCore.cpp | 45 +++++++++++++------------------------ test/testOutput.cpp | 7 +++--- test/testPropagation.cpp | 13 +++++------ test/testTurbulentField.cpp | 40 +++++++++++++++++---------------- 5 files changed, 59 insertions(+), 79 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 591ade36c..a12241254 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,15 +1,10 @@ -if(APPLE) - # rpath specific patches - cmake_minimum_required(VERSION 2.8.12) -else(APPLE) - # require > 2.8.8 for FILE DOWNLOAD fixes - # allow < 2.8.12 for debian backports - cmake_minimum_required(VERSION 2.8.11) -endif(APPLE) +cmake_minimum_required(VERSION 3.14) + project(CRPropa Fortran C CXX) set(CRPROPA_RELEASE_VERSION 3.2.1+) # Update for new release +set(CMAKE_CXX_STANDARD 11) set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) set(CRPROPA_EXTRA_SOURCES) @@ -18,17 +13,6 @@ set(CRPROPA_EXTRA_LIBRARIES) set(CRPROPA_SWIG_DEFINES) set(CRPROPA_SWIG_INPUTS) -macro(USE_CXX11) - if(CMAKE_VERSION VERSION_LESS "3.1") - if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11") - endif() - else() - set(CMAKE_CXX_STANDARD 11) - endif() -endmacro(USE_CXX11) -USE_CXX11() - if(CMAKE_COMPILER_IS_GNUCXX AND NOT APPLE) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--as-needed") set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--as-needed") @@ -110,6 +94,15 @@ if(ENABLE_TESTING) if(APPLE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGTEST_USE_OWN_TR1_TUPLE=1") endif(APPLE) + + # temporary workaround for newer clang versions due to its handling of unwinding + # see: https://github.com/google/googletest/issues/3062 + if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") + if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 15) + add_definitions(-DCRPROPA_TESTS_SKIP_EXCEPTIONS) + endif (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 15) + endif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") + endif(ENABLE_TESTING) # @@ -165,7 +158,7 @@ list(APPEND CRPROPA_EXTRA_LIBRARIES sophia gfortran) list(APPEND CRPROPA_EXTRA_INCLUDES libs/sophia) # GlacticMagneticLenses -option(ENABLE_GALACTICMAGETICLENS "Galactic Magnetic Lens" ON) +option(ENABLE_GALACTICMAGNETICLENS "Galactic Magnetic Lens" ON) option(INSTALL_EIGEN "Install provided EIGEN headers" OFF) SET(EIGEN_PATH "" CACHE STRING "Use EIGEN from this path instead of the version shipped with CRPropa") SET(WITH_GALACTIC_LENSES FALSE) diff --git a/test/testCore.cpp b/test/testCore.cpp index 1f33d38d8..7aebff63a 100644 --- a/test/testCore.cpp +++ b/test/testCore.cpp @@ -66,9 +66,11 @@ TEST(ParticleState, id) { EXPECT_EQ(particle.getId(), 1000060120); } +#ifndef CRPROPA_TESTS_SKIP_EXCEPTIONS TEST(ParticleState, idException) { EXPECT_THROW(nucleusId(5, 6), std::runtime_error); } +#endif TEST(ParticleState, Charge) { ParticleState particle; @@ -129,33 +131,28 @@ TEST(ParticleState, lorentzFactor) { 1e12 * eV / mass_proton / c_squared); } -TEST(ParticleID, nucleusId) -{ - EXPECT_EQ(nucleusId(3,2),1000020030 ); +TEST(ParticleID, nucleusId) { + EXPECT_EQ(nucleusId(3,2), 1000020030); } -TEST(ParticleID, chargeNumber) -{ +TEST(ParticleID, chargeNumber) { EXPECT_EQ(chargeNumber(1000020030), 2); } -TEST(ParticleID, massNumber) -{ +TEST(ParticleID, massNumber) { EXPECT_EQ(massNumber(2112), 1); EXPECT_EQ(massNumber(1000020030), 3); } -TEST(ParticleID, isNucleus) -{ +TEST(ParticleID, isNucleus) { EXPECT_TRUE(isNucleus(1000020030)); EXPECT_FALSE(isNucleus(11)); } -TEST(HepPID, consistencyWithReferenceImplementation){ +TEST(HepPID, consistencyWithReferenceImplementation) { // Tests the performance improved version against the default one unsigned long testPID = rand() % 1000000000 + 1000000000; - for(size_t i=1; i < 8; i++) - { + for(size_t i=1; i < 8; i++) { HepPID::location loc = (HepPID::location) i; unsigned short newResult = HepPID::digit(loc, testPID); //original implementation @@ -164,8 +161,7 @@ TEST(HepPID, consistencyWithReferenceImplementation){ } } -TEST(HepPID, charge) -{ +TEST(HepPID, charge) { EXPECT_DOUBLE_EQ(HepPID::charge(11), -1.); } @@ -317,16 +313,14 @@ TEST(common, interpolateEquidistant) { EXPECT_EQ(9, interpolateEquidistant(3.1, 1, 3, yD)); } -TEST(common, pow_integer) -{ +TEST(common, pow_integer) { EXPECT_EQ(pow_integer<0>(1.23), 1); EXPECT_FLOAT_EQ(pow_integer<1>(1.234), 1.234); EXPECT_FLOAT_EQ(pow_integer<2>(1.234), pow(1.234, 2)); EXPECT_FLOAT_EQ(pow_integer<3>(1.234), pow(1.234, 3)); } -TEST(common, gaussInt) -{ +TEST(common, gaussInt) { EXPECT_NEAR(gaussInt(([](double x){ return x*x; }), 0, 10), 1000/3., 1e-4); EXPECT_NEAR(gaussInt(([](double x){ return sin(x)*sin(x); }), 0, M_PI), M_PI/2., 1e-4); } @@ -382,11 +376,9 @@ TEST(Random, bigSeedStorage) { } -TEST(base64, de_en_coding) -{ +TEST(base64, de_en_coding) { Random a; - for (int N=1; N < 100; N++) - { + for (int N=1; N < 100; N++) { std::vector data; data.reserve(N); for (int i =0; igetPdf()[bin] > 0); } - TEST(Variant, copyToBuffer) { double a = 23.42; Variant v(a); @@ -1052,7 +1038,6 @@ TEST(Variant, stringConversion) { } - TEST(Geometry, Plane) { Plane p(Vector3d(0,0,1), Vector3d(0,0,1)); EXPECT_DOUBLE_EQ(-1., p.distance(Vector3d(0, 0, 0))); diff --git a/test/testOutput.cpp b/test/testOutput.cpp index d1920d959..6694b14b7 100644 --- a/test/testOutput.cpp +++ b/test/testOutput.cpp @@ -34,7 +34,6 @@ ::testing::AssertionResult ArraysMatch(const T (&expected)[size], namespace crpropa { //-- Output - TEST(Output, size) { Candidate c; Output output; @@ -44,7 +43,6 @@ TEST(Output, size) { } //-- TextOutput - TEST(TextOutput, printHeader_Trajectory1D) { Candidate c; TextOutput output(Output::Trajectory1D); @@ -139,13 +137,16 @@ TEST(TextOutput, printHeader_Version) { g_GIT_DESC); } +#ifndef CRPROPA_TESTS_SKIP_EXCEPTIONS TEST(TextOutput, failOnIllegalOutputFile) { EXPECT_THROW( TextOutput output("THIS_FOLDER_MUST_NOT_EXISTS_12345+/FILE.txt"), std::runtime_error); } +#endif #ifdef CRPROPA_HAVE_HDF5 +#ifndef CRPROPA_TESTS_SKIP_EXCEPTIONS TEST(HDF5Output, failOnIllegalOutputFile) { HDF5Output out; // disable default error output of HDF5 @@ -154,9 +155,9 @@ TEST(HDF5Output, failOnIllegalOutputFile) { std::runtime_error); } #endif +#endif //-- ParticleCollector - TEST(ParticleCollector, size) { ref_ptr c = new Candidate(); ParticleCollector output; diff --git a/test/testPropagation.cpp b/test/testPropagation.cpp index 6c4f45ed6..26d83ddc8 100644 --- a/test/testPropagation.cpp +++ b/test/testPropagation.cpp @@ -57,9 +57,8 @@ TEST(testPropagationCK, zeroField) { EXPECT_DOUBLE_EQ(5 * minStep, c.getNextStep()); // acceleration by factor 5 } - -TEST(testPropagationCK, exceptions) -{ +#ifndef CRPROPA_TESTS_SKIP_EXCEPTIONS +TEST(testPropagationCK, exceptions) { // minStep should be smaller than maxStep EXPECT_THROW(PropagationCK propa(new UniformMagneticField(Vector3d(0, 0, 1 * nG)), 0.42, 10 , 0), std::runtime_error); // Too large tolerance: tolerance should be between 0 and 1 @@ -80,7 +79,7 @@ TEST(testPropagationCK, exceptions) EXPECT_THROW(propa.setMaximumStep(0.1 * Mpc), std::runtime_error); } - +#endif TEST(testPropagationCK, constructor) { // Test construction and parameters @@ -292,9 +291,8 @@ TEST(testPropagationBP, zeroField) { EXPECT_DOUBLE_EQ(5 * minStep, c.getNextStep()); // acceleration by factor 5 } - -TEST(testPropagationBP, exceptions) -{ +#ifndef CRPROPA_TESTS_SKIP_EXCEPTIONS +TEST(testPropagationBP, exceptions) { // minStep should be smaller than maxStep EXPECT_THROW(PropagationBP propa(new UniformMagneticField(Vector3d(0, 0, 1 * nG)), 0.42, 10 , 0), std::runtime_error); // Too large tolerance: tolerance should be between 0 and 1 @@ -315,6 +313,7 @@ TEST(testPropagationBP, exceptions) EXPECT_THROW(propa.setMaximumStep(0.1 * Mpc), std::runtime_error); } +#endif TEST(testPropagationBP, constructor) { diff --git a/test/testTurbulentField.cpp b/test/testTurbulentField.cpp index 2b04244d2..e8365838a 100644 --- a/test/testTurbulentField.cpp +++ b/test/testTurbulentField.cpp @@ -91,25 +91,27 @@ TEST(testVectorFieldGrid, Turbulence_seed) { EXPECT_FLOAT_EQ(tf1.getField(pos).x, tf2.getField(pos).x); } -TEST(testVectorFieldGrid, turbulence_Exceptions) { - // Test exceptions - size_t n = 64; - double spacing = 10 * Mpc / n; - double brms = 1; - ref_ptr grid = new Grid3f(Vector3d(0, 0, 0), n, spacing); - - // should be fine - EXPECT_NO_THROW(initTurbulence(grid, brms, 2 * spacing, 8 * spacing)); - // lMin too small - EXPECT_THROW(initTurbulence(grid, brms, 1.5 * spacing, 8 * spacing), - std::runtime_error); - // lMin > lMax - EXPECT_THROW(initTurbulence(grid, brms, 8.1 * spacing, 8 * spacing), - std::runtime_error); - // lMax too large - EXPECT_THROW(initTurbulence(grid, brms, 2 * spacing, 65 * spacing), - std::runtime_error); -} +#ifndef CRPROPA_TESTS_SKIP_EXCEPTIONS + TEST(testVectorFieldGrid, turbulence_Exceptions) { + // Test exceptions + size_t n = 64; + double spacing = 10 * Mpc / n; + double brms = 1; + ref_ptr grid = new Grid3f(Vector3d(0, 0, 0), n, spacing); + + // should be fine + EXPECT_NO_THROW(initTurbulence(grid, brms, 2 * spacing, 8 * spacing)); + // lMin too small + EXPECT_THROW(initTurbulence(grid, brms, 1.5 * spacing, 8 * spacing), + std::runtime_error); + // lMin > lMax + EXPECT_THROW(initTurbulence(grid, brms, 8.1 * spacing, 8 * spacing), + std::runtime_error); + // lMax too large + EXPECT_THROW(initTurbulence(grid, brms, 2 * spacing, 65 * spacing), + std::runtime_error); + } +#endif TEST(testGridTurbulence, Turbulence_seed) { // Test if seeding produces 2 identical fields From 55263da7fa89552a3140807a54dfd8e109529bbc Mon Sep 17 00:00:00 2001 From: Rafael Date: Sat, 3 Feb 2024 19:38:08 +0100 Subject: [PATCH 03/81] fix typo --- test/testInteraction.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/testInteraction.cpp b/test/testInteraction.cpp index e07c60a1c..dd195c552 100644 --- a/test/testInteraction.cpp +++ b/test/testInteraction.cpp @@ -1111,10 +1111,8 @@ TEST(EMInverseComptonScattering, interactionTag) { EXPECT_TRUE(m.getInteractionTag() == "myTag"); } - // SynchrotronRadiation ------------------------------------------------- - -TEST(SynchrtronRadiation, interactionTag) { +TEST(SynchrotronRadiation, interactionTag) { SynchrotronRadiation s(1 * muG, true); // test default interactionTag @@ -1131,6 +1129,7 @@ TEST(SynchrtronRadiation, interactionTag) { EXPECT_TRUE(s.getInteractionTag() == "myTag"); } + int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); From f054f9e1910c46bf8a194e7c2ac28412d62f5b38 Mon Sep 17 00:00:00 2001 From: Rafael Date: Sat, 3 Feb 2024 21:44:46 +0100 Subject: [PATCH 04/81] fix sporadic fails of , related to attempts to access out-of-bounds elements --- src/module/EMPairProduction.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/module/EMPairProduction.cpp b/src/module/EMPairProduction.cpp index 915528c14..d57ecc1ae 100644 --- a/src/module/EMPairProduction.cpp +++ b/src/module/EMPairProduction.cpp @@ -151,6 +151,9 @@ class PPSecondariesEnergyDistribution { double sample(double E0, double s) { // get distribution for given s size_t idx = std::lower_bound(tab_s.begin(), tab_s.end(), s) - tab_s.begin(); + if (idx > data.size()) + return NAN; + std::vector s0 = data[idx]; // draw random bin @@ -174,9 +177,6 @@ void EMPairProduction::performInteraction(Candidate *candidate) const { double z = candidate->getRedshift(); double E = candidate->current.getEnergy() * (1 + z); - // cosmic ray photon is lost after interacting - candidate->setActive(false); - // check if secondary electron pair needs to be produced if (not haveElectrons) return; @@ -203,6 +203,9 @@ void EMPairProduction::performInteraction(Candidate *candidate) const { if (not std::isfinite(Ee) || not std::isfinite(Ep)) return; + // photon is lost after interacting + candidate->setActive(false); + // sample random position along current step Vector3d pos = random.randomInterpolatedPosition(candidate->previous.getPosition(), candidate->current.getPosition()); // apply sampling From 436e1351e271807a68788fa700536f7d63b2d452 Mon Sep 17 00:00:00 2001 From: Rafael Date: Sat, 3 Feb 2024 21:54:36 +0100 Subject: [PATCH 05/81] minor bug fixes; cosmetic improvements --- test/testInteraction.cpp | 317 ++++++++++++++++++++------------------- 1 file changed, 159 insertions(+), 158 deletions(-) diff --git a/test/testInteraction.cpp b/test/testInteraction.cpp index dd195c552..2ade87d2f 100644 --- a/test/testInteraction.cpp +++ b/test/testInteraction.cpp @@ -22,24 +22,24 @@ namespace crpropa { // ElectronPairProduction ----------------------------------------------------- TEST(ElectronPairProduction, allBackgrounds) { // Test if interaction data files are loaded. - ref_ptr CMB_instance = new CMB(); - ElectronPairProduction epp(CMB_instance); - ref_ptr IRB = new IRB_Kneiske04(); - epp.setPhotonField(IRB); - IRB = new IRB_Stecker05(); - epp.setPhotonField(IRB); - IRB = new IRB_Franceschini08(); - epp.setPhotonField(IRB); - IRB = new IRB_Finke10(); - epp.setPhotonField(IRB); - IRB = new IRB_Dominguez11(); - epp.setPhotonField(IRB); - IRB = new IRB_Gilmore12(); - epp.setPhotonField(IRB); - IRB = new IRB_Stecker16_upper(); - epp.setPhotonField(IRB); - IRB = new IRB_Stecker16_lower(); - epp.setPhotonField(IRB); + ref_ptr cmb = new CMB(); + ElectronPairProduction epp(cmb); + ref_ptr irb = new IRB_Kneiske04(); + epp.setPhotonField(irb); + irb = new IRB_Stecker05(); + epp.setPhotonField(irb); + irb = new IRB_Franceschini08(); + epp.setPhotonField(irb); + irb = new IRB_Finke10(); + epp.setPhotonField(irb); + irb = new IRB_Dominguez11(); + epp.setPhotonField(irb); + irb = new IRB_Gilmore12(); + epp.setPhotonField(irb); + irb = new IRB_Stecker16_upper(); + epp.setPhotonField(irb); + irb = new IRB_Stecker16_lower(); + epp.setPhotonField(irb); } TEST(ElectronPairProduction, energyDecreasing) { @@ -48,8 +48,8 @@ TEST(ElectronPairProduction, energyDecreasing) { c.setCurrentStep(2 * Mpc); c.current.setId(nucleusId(1, 1)); // proton - ref_ptr CMB_instance = new CMB(); - ElectronPairProduction epp1(CMB_instance); + ref_ptr cmb = new CMB(); + ElectronPairProduction epp1(cmb); for (int i = 0; i < 80; i++) { double E = pow(10, 15 + i * 0.1) * eV; c.current.setEnergy(E); @@ -57,8 +57,8 @@ TEST(ElectronPairProduction, energyDecreasing) { EXPECT_LE(c.current.getEnergy(), E); } - ref_ptr IRB = new IRB_Kneiske04(); - ElectronPairProduction epp2(IRB); + ref_ptr irb = new IRB_Kneiske04(); + ElectronPairProduction epp2(irb); for (int i = 0; i < 80; i++) { double E = pow(10, 15 + i * 0.1) * eV; c.current.setEnergy(E); @@ -69,8 +69,8 @@ TEST(ElectronPairProduction, energyDecreasing) { TEST(ElectronPairProduction, belowEnergyTreshold) { // Test if nothing happens below 1e15 eV. - ref_ptr CMB_instance = new CMB(); - ElectronPairProduction epp(CMB_instance); + ref_ptr cmb = new CMB(); + ElectronPairProduction epp(cmb); Candidate c(nucleusId(1, 1), 1E14 * eV); epp.process(&c); EXPECT_DOUBLE_EQ(1E14 * eV, c.current.getEnergy()); @@ -78,8 +78,8 @@ TEST(ElectronPairProduction, belowEnergyTreshold) { TEST(ElectronPairProduction, thisIsNotNucleonic) { // Test if non-nuclei are skipped. - ref_ptr CMB_instance = new CMB(); - ElectronPairProduction epp(CMB_instance); + ref_ptr cmb = new CMB(); + ElectronPairProduction epp(cmb); Candidate c(11, 1E20 * eV); // electron epp.process(&c); EXPECT_DOUBLE_EQ(1E20 * eV, c.current.getEnergy()); @@ -106,9 +106,9 @@ TEST(ElectronPairProduction, valuesCMB) { Candidate c; c.setCurrentStep(1 * Mpc); c.current.setId(nucleusId(1, 1)); // proton - ref_ptr CMB_instance = new CMB(); + ref_ptr cmb = new CMB(); - ElectronPairProduction epp(CMB_instance); + ElectronPairProduction epp(cmb); for (int i = 0; i < x.size(); i++) { c.current.setEnergy(x[i]); epp.process(&c); @@ -120,8 +120,8 @@ TEST(ElectronPairProduction, valuesCMB) { TEST(ElectronPairProduction, interactionTag) { - ref_ptr CMB_instance = new CMB(); - ElectronPairProduction epp(CMB_instance); + ref_ptr cmb = new CMB(); + ElectronPairProduction epp(cmb); // test the default interaction tag EXPECT_TRUE(epp.getInteractionTag() == "EPP"); @@ -163,9 +163,9 @@ TEST(ElectronPairProduction, valuesIRB) { Candidate c; c.setCurrentStep(1 * Mpc); c.current.setId(nucleusId(1, 1)); // proton - ref_ptr IRB = new IRB_Kneiske04(); + ref_ptr irb = new IRB_Kneiske04(); - ElectronPairProduction epp(IRB); + ElectronPairProduction epp(irb); for (int i = 0; i < x.size(); i++) { c.current.setEnergy(x[i]); epp.process(&c); @@ -322,35 +322,35 @@ TEST(NuclearDecay, interactionTag) { // PhotoDisintegration -------------------------------------------------------- TEST(PhotoDisintegration, allBackgrounds) { // Test if interaction data files are loaded. - ref_ptr CMB_instance = new CMB(); - PhotoDisintegration pd(CMB_instance); - ref_ptr IRB = new IRB_Kneiske04(); - pd.setPhotonField(IRB); - ref_ptr URB = new URB_Protheroe96(); - pd.setPhotonField(URB); - IRB = new IRB_Stecker05(); - pd.setPhotonField(IRB); - IRB = new IRB_Franceschini08(); - pd.setPhotonField(IRB); - IRB = new IRB_Finke10(); - pd.setPhotonField(IRB); - IRB = new IRB_Dominguez11(); - pd.setPhotonField(IRB); - IRB = new IRB_Gilmore12(); - pd.setPhotonField(IRB); - IRB = new IRB_Stecker16_upper(); - pd.setPhotonField(IRB); - IRB = new IRB_Stecker16_lower(); - pd.setPhotonField(IRB); - URB = new URB_Nitu21(); - pd.setPhotonField(URB); + ref_ptr cmb = new CMB(); + PhotoDisintegration pd(cmb); + ref_ptr irb = new IRB_Kneiske04(); + pd.setPhotonField(irb); + ref_ptr urb = new URB_Protheroe96(); + pd.setPhotonField(urb); + irb = new IRB_Stecker05(); + pd.setPhotonField(irb); + irb = new IRB_Franceschini08(); + pd.setPhotonField(irb); + irb = new IRB_Finke10(); + pd.setPhotonField(irb); + irb = new IRB_Dominguez11(); + pd.setPhotonField(irb); + irb = new IRB_Gilmore12(); + pd.setPhotonField(irb); + irb = new IRB_Stecker16_upper(); + pd.setPhotonField(irb); + irb = new IRB_Stecker16_lower(); + pd.setPhotonField(irb); + urb = new URB_Nitu21(); + pd.setPhotonField(urb); } TEST(PhotoDisintegration, carbon) { // Test if a 100 EeV C-12 nucleus photo-disintegrates (at least once) over a distance of 1 Gpc. // This test can stochastically fail. - ref_ptr CMB_instance = new CMB(); - PhotoDisintegration pd(CMB_instance); + ref_ptr cmb = new CMB(); + PhotoDisintegration pd(cmb); Candidate c; int id = nucleusId(12, 6); c.current.setId(id); @@ -385,8 +385,8 @@ TEST(PhotoDisintegration, carbon) { TEST(PhotoDisintegration, iron) { // Test if a 200 EeV Fe-56 nucleus photo-disintegrates (at least once) over a distance of 1 Gpc. // This test can stochastically fail. - ref_ptr IRB = new IRB_Kneiske04(); - PhotoDisintegration pd(IRB); + ref_ptr irb = new IRB_Kneiske04(); + PhotoDisintegration pd(irb); Candidate c; int id = nucleusId(56, 26); c.current.setId(id); @@ -424,8 +424,8 @@ TEST(PhotoDisintegration, iron) { TEST(PhotoDisintegration, thisIsNotNucleonic) { // Test that nothing happens to an electron. - ref_ptr CMB_instance = new CMB(); - PhotoDisintegration pd(CMB_instance); + ref_ptr cmb = new CMB(); + PhotoDisintegration pd(cmb); Candidate c; c.setCurrentStep(1 * Mpc); c.current.setId(11); // electron @@ -437,8 +437,8 @@ TEST(PhotoDisintegration, thisIsNotNucleonic) { TEST(PhotoDisintegration, limitNextStep) { // Test if the interaction limits the next propagation step. - ref_ptr CMB_instance = new CMB(); - PhotoDisintegration pd(CMB_instance); + ref_ptr cmb = new CMB(); + PhotoDisintegration pd(cmb); Candidate c; c.setNextStep(std::numeric_limits::max()); c.current.setId(nucleusId(4, 2)); @@ -449,10 +449,10 @@ TEST(PhotoDisintegration, limitNextStep) { TEST(PhotoDisintegration, allIsotopes) { // Test if all isotopes are handled. - ref_ptr CMB_instance = new CMB(); - PhotoDisintegration pd1(CMB_instance); - ref_ptr IRB = new IRB_Kneiske04(); - PhotoDisintegration pd2(IRB); + ref_ptr cmb = new CMB(); + PhotoDisintegration pd1(cmb); + ref_ptr irb = new IRB_Kneiske04(); + PhotoDisintegration pd2(irb); Candidate c; c.setCurrentStep(10 * Mpc); @@ -471,8 +471,8 @@ TEST(PhotoDisintegration, allIsotopes) { } TEST(Photodisintegration, updateParticleParentProperties) { // Issue: #204 - ref_ptr CMB_instance = new CMB(); - PhotoDisintegration pd(CMB_instance); + ref_ptr cmb = new CMB(); + PhotoDisintegration pd(cmb); Candidate c(nucleusId(56,26), 500 * EeV, Vector3d(1 * Mpc, 0, 0)); @@ -506,19 +506,19 @@ TEST(PhotoDisintegration, interactionTag) { // ElasticScattering ---------------------------------------------------------- TEST(ElasticScattering, allBackgrounds) { // Test if interaction data files are loaded. - ref_ptr CMB_instance = new CMB(); - ElasticScattering scattering(CMB_instance); - ref_ptr IRB = new IRB_Kneiske04(); - scattering.setPhotonField(IRB); - ref_ptr URB = new URB_Nitu21(); - scattering.setPhotonField(URB); + ref_ptr cmb = new CMB(); + ElasticScattering scattering(cmb); + ref_ptr irb = new IRB_Kneiske04(); + scattering.setPhotonField(irb); + ref_ptr urb = new URB_Nitu21(); + scattering.setPhotonField(urb); } TEST(ElasticScattering, secondaries) { // Test the creation of cosmic ray photons. // This test can stochastically fail. - ref_ptr CMB_instance = new CMB(); - ElasticScattering scattering(CMB_instance); + ref_ptr cmb = new CMB(); + ElasticScattering scattering(cmb); Candidate c; int id = nucleusId(12, 6); c.current.setId(id); @@ -540,35 +540,35 @@ TEST(ElasticScattering, secondaries) { // PhotoPionProduction -------------------------------------------------------- TEST(PhotoPionProduction, allBackgrounds) { // Test if all interaction data files can be loaded. - ref_ptr CMB_instance = new CMB(); - PhotoPionProduction ppp(CMB_instance); - ref_ptr IRB = new IRB_Kneiske04(); - ppp.setPhotonField(IRB); - IRB = new IRB_Stecker05(); - ppp.setPhotonField(IRB); - IRB = new IRB_Franceschini08(); - ppp.setPhotonField(IRB); - IRB = new IRB_Finke10(); - ppp.setPhotonField(IRB); - IRB = new IRB_Dominguez11(); - ppp.setPhotonField(IRB); - IRB = new IRB_Gilmore12(); - ppp.setPhotonField(IRB); - IRB = new IRB_Stecker16_upper(); - ppp.setPhotonField(IRB); - IRB = new IRB_Stecker16_lower(); - ppp.setPhotonField(IRB); - ref_ptr URB = new URB_Protheroe96(); - ppp.setPhotonField(URB); - URB = new URB_Nitu21(); - ppp.setPhotonField(URB); + ref_ptr cmb = new CMB(); + PhotoPionProduction ppp(cmb); + ref_ptr irb = new IRB_Kneiske04(); + ppp.setPhotonField(irb); + irb = new IRB_Stecker05(); + ppp.setPhotonField(irb); + irb = new IRB_Franceschini08(); + ppp.setPhotonField(irb); + irb = new IRB_Finke10(); + ppp.setPhotonField(irb); + irb = new IRB_Dominguez11(); + ppp.setPhotonField(irb); + irb = new IRB_Gilmore12(); + ppp.setPhotonField(irb); + irb = new IRB_Stecker16_upper(); + ppp.setPhotonField(irb); + irb = new IRB_Stecker16_lower(); + ppp.setPhotonField(irb); + ref_ptr urb = new URB_Protheroe96(); + ppp.setPhotonField(urb); + urb = new URB_Nitu21(); + ppp.setPhotonField(urb); } TEST(PhotoPionProduction, proton) { - // Test photo-pion interaction for 100 EeV proton. + // Test photopion interaction for 100 EeV proton. // This test can stochastically fail. - ref_ptr CMB_instance = new CMB(); - PhotoPionProduction ppp(CMB_instance); + ref_ptr cmb = new CMB(); + PhotoPionProduction ppp(cmb); Candidate c(nucleusId(1, 1), 100 * EeV); c.setCurrentStep(1000 * Mpc); ppp.process(&c); @@ -586,8 +586,8 @@ TEST(PhotoPionProduction, proton) { TEST(PhotoPionProduction, helium) { // Test photo-pion interaction for 400 EeV He nucleus. // This test can stochastically fail. - ref_ptr CMB_instance = new CMB(); - PhotoPionProduction ppp(CMB_instance); + ref_ptr cmb = new CMB(); + PhotoPionProduction ppp(cmb); Candidate c; c.current.setId(nucleusId(4, 2)); c.current.setEnergy(400. * EeV); @@ -601,8 +601,8 @@ TEST(PhotoPionProduction, helium) { TEST(PhotoPionProduction, thisIsNotNucleonic) { // Test if nothing happens to an electron. - ref_ptr CMB_instance = new CMB(); - PhotoPionProduction ppp(CMB_instance); + ref_ptr cmb = new CMB(); + PhotoPionProduction ppp(cmb); Candidate c; c.current.setId(11); // electron c.current.setEnergy(10 * EeV); @@ -614,8 +614,8 @@ TEST(PhotoPionProduction, thisIsNotNucleonic) { TEST(PhotoPionProduction, limitNextStep) { // Test if the interaction limits the next propagation step. - ref_ptr CMB_instance = new CMB(); - PhotoPionProduction ppp(CMB_instance); + ref_ptr cmb = new CMB(); + PhotoPionProduction ppp(cmb); Candidate c(nucleusId(1, 1), 200 * EeV); c.setNextStep(std::numeric_limits::max()); ppp.process(&c); @@ -625,8 +625,8 @@ TEST(PhotoPionProduction, limitNextStep) { TEST(PhotoPionProduction, secondaries) { // Test photo-pion interaction for 100 EeV proton. // This test can stochastically fail. - ref_ptr CMB_instance = new CMB(); - PhotoPionProduction ppp(CMB_instance, true, true, true); + ref_ptr cmb = new CMB(); + PhotoPionProduction ppp(cmb, true, true, true); Candidate c(nucleusId(1, 1), 100 * EeV); c.setCurrentStep(1000 * Mpc); ppp.process(&c); @@ -638,14 +638,14 @@ TEST(PhotoPionProduction, sampling) { // Specific test of photon sampling of photo-pion production // by testing the calculated pEpsMax for CMB(), also indirectly // testing epsMinInteraction and logSampling (default). - ref_ptr CMB_instance = new CMB(); //create CMB instance + ref_ptr cmb = new CMB(); //create CMB instance double energy = 1.e10; //1e10 GeV bool onProton = true; //proton double z = 0; //no redshift - PhotoPionProduction ppp(CMB_instance, true, true, true); + PhotoPionProduction ppp(cmb, true, true, true); double correctionFactor = ppp.getCorrectionFactor(); //get current correctionFactor - double epsMin = std::max(CMB_instance -> getMinimumPhotonEnergy(z) / eV, 0.00710614); // 0.00710614 = epsMinInteraction(onProton,energy) - double epsMax = CMB_instance -> getMaximumPhotonEnergy(z) / eV; + double epsMin = std::max(cmb -> getMinimumPhotonEnergy(z) / eV, 0.00710614); // 0.00710614 = epsMinInteraction(onProton,energy) + double epsMax = cmb -> getMaximumPhotonEnergy(z) / eV; double pEpsMax = ppp.probEpsMax(onProton, energy, z, epsMin, epsMax) / correctionFactor; EXPECT_DOUBLE_EQ(pEpsMax,132673934934.922); } @@ -726,8 +726,8 @@ TEST(EMPairProduction, allBackgrounds) { TEST(EMPairProduction, limitNextStep) { // Test if the interaction limits the next propagation step. - ref_ptr CMB_instance = new CMB(); - EMPairProduction m(CMB_instance); + ref_ptr cmb = new CMB(); + EMPairProduction m(cmb); Candidate c(22, 1E17 * eV); c.setNextStep(std::numeric_limits::max()); m.process(&c); @@ -736,17 +736,17 @@ TEST(EMPairProduction, limitNextStep) { TEST(EMPairProduction, secondaries) { // Test if secondaries are correctly produced. - ref_ptr CMB_instance = new CMB(); - ref_ptr IRB = new IRB_Gilmore12(); - ref_ptr URB = new URB_Protheroe96(); - EMPairProduction m(CMB_instance); + ref_ptr cmb = new CMB(); + ref_ptr irb = new IRB_Gilmore12(); + ref_ptr urb = new URB_Protheroe96(); + EMPairProduction m(cmb); m.setHaveElectrons(true); m.setThinning(0.); - std::vector< ref_ptr > fields; - fields.push_back(CMB_instance); - fields.push_back(IRB); - fields.push_back(URB); + std::vector> fields; + fields.push_back(cmb); + fields.push_back(irb); + fields.push_back(urb); // loop over photon backgrounds for (int f = 0; f < fields.size(); f++) { @@ -754,11 +754,11 @@ TEST(EMPairProduction, secondaries) { for (int i = 0; i < 140; i++) { // loop over energies Ep = (1e10 - 1e23) eV double Ep = pow(10, 9.05 + 0.1 * i) * eV; Candidate c(22, Ep); - //c.setCurrentStep(std::numeric_limits::max()); c.setCurrentStep(1e10 * Mpc); + m.process(&c); - // pass if no interaction has occured (no tabulated rates) + // pass if no interaction has ocurred (no tabulated rates) if (c.isActive()) continue; @@ -829,8 +829,8 @@ TEST(EMDoublePairProduction, allBackgrounds) { TEST(EMDoublePairProduction, limitNextStep) { // Test if the interaction limits the next propagation step. - ref_ptr CMB_instance = new CMB(); - EMDoublePairProduction m(CMB_instance); + ref_ptr cmb = new CMB(); + EMDoublePairProduction m(cmb); Candidate c(22, 1E17 * eV); c.setNextStep(std::numeric_limits::max()); m.process(&c); @@ -839,17 +839,17 @@ TEST(EMDoublePairProduction, limitNextStep) { TEST(EMDoublePairProduction, secondaries) { // Test if secondaries are correctly produced. - ref_ptr CMB_instance = new CMB(); - ref_ptr IRB = new IRB_Gilmore12(); - ref_ptr URB = new URB_Nitu21(); - EMDoublePairProduction m(CMB_instance); + ref_ptr cmb = new CMB(); + ref_ptr irb = new IRB_Gilmore12(); + ref_ptr urb = new URB_Protheroe96(); + EMPairProduction m(cmb); m.setHaveElectrons(true); m.setThinning(0.); - std::vector< ref_ptr > fields; - fields.push_back(CMB_instance); - fields.push_back(IRB); - fields.push_back(URB); + std::vector> fields; + fields.push_back(cmb); + fields.push_back(irb); + fields.push_back(urb); // loop over photon backgrounds for (int f = 0; f < fields.size(); f++) { @@ -859,7 +859,6 @@ TEST(EMDoublePairProduction, secondaries) { for (int i = 0; i < 140; i++) { double Ep = pow(10, 9.05 + 0.1 * i) * eV; Candidate c(22, Ep); - // c.setCurrentStep(std::numeric_limits::max()); c.setCurrentStep(1e4 * Mpc); // use lower value so that the test can run faster m.process(&c); @@ -934,8 +933,8 @@ TEST(EMTripletPairProduction, allBackgrounds) { TEST(EMTripletPairProduction, limitNextStep) { // Test if the interaction limits the next propagation step. - ref_ptr CMB_instance = new CMB(); - EMTripletPairProduction m(CMB_instance); + ref_ptr cmb = new CMB(); + EMTripletPairProduction m(cmb); Candidate c(11, 1E17 * eV); c.setNextStep(std::numeric_limits::max()); m.process(&c); @@ -944,23 +943,24 @@ TEST(EMTripletPairProduction, limitNextStep) { TEST(EMTripletPairProduction, secondaries) { // Test if secondaries are correctly produced. - ref_ptr CMB_instance = new CMB(); - ref_ptr IRB = new IRB_Gilmore12(); - ref_ptr URB = new URB_Nitu21(); - EMTripletPairProduction m(CMB_instance); + ref_ptr cmb = new CMB(); + ref_ptr irb = new IRB_Gilmore12(); + ref_ptr urb = new URB_Protheroe96(); + EMPairProduction m(cmb); m.setHaveElectrons(true); + m.setThinning(0.); - std::vector< ref_ptr > fields; - fields.push_back(CMB_instance); - fields.push_back(IRB); - fields.push_back(URB); + std::vector> fields; + fields.push_back(cmb); + fields.push_back(irb); + fields.push_back(urb); // loop over photon backgrounds for (int f = 0; f < fields.size(); f++) { m.setPhotonField(fields[f]); // loop over energies Ep = (1e9 - 1e23) eV - for (int i = 0; i < 130; i++) { + for (int i = 0; i < 140; i++) { double Ep = pow(10, 9.05 + 0.1 * i) * eV; Candidate c(11, Ep); @@ -1038,8 +1038,8 @@ TEST(EMInverseComptonScattering, allBackgrounds) { TEST(EMInverseComptonScattering, limitNextStep) { // Test if the interaction limits the next propagation step. - ref_ptr CMB_instance = new CMB(); - EMInverseComptonScattering m(CMB_instance); + ref_ptr cmb = new CMB(); + EMInverseComptonScattering m(cmb); Candidate c(11, 1E17 * eV); c.setNextStep(std::numeric_limits::max()); m.process(&c); @@ -1048,16 +1048,17 @@ TEST(EMInverseComptonScattering, limitNextStep) { TEST(EMInverseComptonScattering, secondaries) { // Test if secondaries are correctly produced. - ref_ptr CMB_instance = new CMB(); - ref_ptr IRB = new IRB_Gilmore12(); - ref_ptr URB = new URB_Nitu21(); - EMInverseComptonScattering m(CMB_instance); - m.setHavePhotons(true); + ref_ptr cmb = new CMB(); + ref_ptr irb = new IRB_Gilmore12(); + ref_ptr urb = new URB_Protheroe96(); + EMPairProduction m(cmb); + m.setHaveElectrons(true); + m.setThinning(0.); - std::vector< ref_ptr > fields; - fields.push_back(CMB_instance); - fields.push_back(IRB); - fields.push_back(URB); + std::vector> fields; + fields.push_back(cmb); + fields.push_back(irb); + fields.push_back(urb); // loop over photon backgrounds for (int f = 0; f < fields.size(); f++) { From d61b584b736a64d4b2a7d3dd55681fc3c73711bd Mon Sep 17 00:00:00 2001 From: Rafael Date: Sun, 4 Feb 2024 00:14:35 +0100 Subject: [PATCH 06/81] apply code style convention for indentantion --- python/1_swig.i | 89 +++--- python/2_headers.i | 569 +++++++++++++++------------------------ python/3_repr.i | 2 +- python/4_lens.i | 190 ++++++------- python/crpropa-builtin.i | 6 +- 5 files changed, 333 insertions(+), 523 deletions(-) diff --git a/python/1_swig.i b/python/1_swig.i index f8e47e6b3..22dc5ad06 100644 --- a/python/1_swig.i +++ b/python/1_swig.i @@ -3,13 +3,13 @@ %module(directors="1", threads="1", allprotected="1") crpropa %feature("director:except") { - if( $error != NULL ) { - PyObject *ptype, *pvalue, *ptraceback; - PyErr_Fetch( &ptype, &pvalue, &ptraceback ); - PyErr_Restore( ptype, pvalue, ptraceback ); - PyErr_Print(); - Py_Exit(1); - } + if( $error != NULL ) { + PyObject *ptype, *pvalue, *ptraceback; + PyErr_Fetch( &ptype, &pvalue, &ptraceback ); + PyErr_Restore( ptype, pvalue, ptraceback ); + PyErr_Print(); + Py_Exit(1); + } } @@ -22,7 +22,7 @@ %{ // workaround for SWIG < 2.0.5 with GCC >= 4.7 #include -using std::ptrdiff_t; + using std::ptrdiff_t; %} /* SWIG headers */ @@ -46,53 +46,45 @@ using std::ptrdiff_t; /* SWIG Exceptions */ %inline %{ -class RangeError {}; -class StopIterator {}; + class RangeError {}; + class StopIterator {}; %} %exception { - try { - $action - } catch (Swig::DirectorException &e) { - SWIG_exception(SWIG_RuntimeError, e.getMessage()); - } catch (const std::exception& e) { - SWIG_exception(SWIG_RuntimeError, e.what()); - } catch (const char *e) { - SWIG_exception(SWIG_RuntimeError, e); - } + try { + $action + } catch (Swig::DirectorException &e) { + SWIG_exception(SWIG_RuntimeError, e.getMessage()); + } catch (const std::exception& e) { + SWIG_exception(SWIG_RuntimeError, e.what()); + } catch (const char *e) { + SWIG_exception(SWIG_RuntimeError, e); + } } /* Exceptions for Python lists and iterators */ - -#ifdef SWIG_PYTHON3 %exception __next__ { -#else -%exception next { -#endif try { - $action - } - catch (StopIterator) { - PyErr_SetString(PyExc_StopIteration, "End of iterator"); - return NULL; + $action + } catch (StopIterator) { + PyErr_SetString(PyExc_StopIteration, "End of iterator"); + return NULL; } } %exception __getitem__ { try { - $action - } - catch (RangeError) { - SWIG_exception(SWIG_IndexError, "Index out of bounds"); - return NULL; + $action + } catch (RangeError) { + SWIG_exception(SWIG_IndexError, "Index out of bounds"); + return NULL; } - }; +/* Include numpy array interface, if available */ #ifdef WITHNUMPY %{ -/* Include numpy array interface, if available */ #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION #include "numpy/arrayobject.h" #include "numpy/ufuncobject.h" @@ -101,20 +93,19 @@ class StopIterator {}; /* Initialize numpy array interface, if available */ #ifdef WITHNUMPY -%init %{ -import_array(); -import_ufunc(); -%} - -%pythoncode %{ -import numpy -__WITHNUMPY = True -%} - + %init %{ + import_array(); + import_ufunc(); + %} + + %pythoncode %{ + import numpy + __WITHNUMPY = True + %} #else -%pythoncode %{ -__WITHNUMPY = False -%} + %pythoncode %{ + __WITHNUMPY = False + %} #endif diff --git a/python/2_headers.i b/python/2_headers.i index 808ae7b95..b7a2d7787 100644 --- a/python/2_headers.i +++ b/python/2_headers.i @@ -4,34 +4,30 @@ %feature("python:slot", "sq_length", functype="lenfunc") __len__; %feature("python:slot", "mp_subscript", functype="binaryfunc") __getitem__; %feature("python:slot", "tp_iter", functype="unaryfunc") __iter__; -#ifdef SWIG_PYTHON3 %feature("python:slot", "tp_iternext", functype="iternextfunc") __next__; -#else -%feature("python:slot", "tp_iternext", functype="iternextfunc") next; -#endif /* Include headers */ #ifdef CRPROPA_HAVE_QUIMBY -%import (module="quimby") "quimby/Referenced.h" -%import (module="quimby") "quimby/Vector3.h" -%import (module="quimby") "quimby/MagneticField.h" -//%import (module="quimby") quimby.i + %import (module="quimby") "quimby/Referenced.h" + %import (module="quimby") "quimby/Vector3.h" + %import (module="quimby") "quimby/MagneticField.h" + //%import (module="quimby") quimby.i #endif #ifdef CRPROPA_HAVE_SAGA -%import (module="saga") saga.i + %import (module="saga") saga.i #endif %{ #include "CRPropa.h" -using namespace crpropa; // for usage of namespace in header files, necessary - // for keyword arguments with units + // for usage of namespace in header files, necessary for keyword arguments with units + using namespace crpropa; %} %{ -#include -#include + #include + #include %} %ignore operator<<; @@ -65,8 +61,7 @@ using namespace crpropa; // for usage of namespace in header files, necessary %include "crpropa/Logging.h" -/* ignore public references and replace with attributes for Vector3d and - * Vector3f*/ +/* ignore public references and replace with attributes for Vector3d and Vector3f*/ %attribute(crpropa::Vector3, double, x, getX, setX); %attribute(crpropa::Vector3, double, y, getY, setY); %attribute(crpropa::Vector3, double, z, getZ, setZ); @@ -78,10 +73,9 @@ using namespace crpropa; // for usage of namespace in header files, necessary %feature("python:slot", "sq_length", functype="lenfunc") crpropa::Vector3::__len__; %feature("python:slot", "mp_subscript", functype="binaryfunc") crpropa::Vector3::__getitem__; %feature("python:slot", "mp_ass_subscript", functype="objobjargproc") crpropa::Vector3::__setitem__; -%typemap(directorin,numinputs=1) (const double *v) -{ - npy_intp dim = 3; - $input = PyArray_SimpleNewFromData(1, &dim, NPY_DOUBLE, (void *)$1); +%typemap(directorin,numinputs=1) (const double *v) { + npy_intp dim = 3; + $input = PyArray_SimpleNewFromData(1, &dim, NPY_DOUBLE, (void *)$1); } %ignore crpropa::Vector3::data; @@ -89,73 +83,60 @@ using namespace crpropa; // for usage of namespace in header files, necessary %exception crpropa::Vector3::__getitem__ { try { - $action - } - catch (RangeError) { - SWIG_exception(SWIG_IndexError, "Index out of bounds"); - return NULL; + $action + } catch (RangeError) { + SWIG_exception(SWIG_IndexError, "Index out of bounds"); + return NULL; } } %exception crpropa::Vector3::__setitem__ { try { - $action - } - catch (RangeError) { - SWIG_exception(SWIG_IndexError, "Index out of bounds"); - return NULL; + $action + } catch (RangeError) { + SWIG_exception(SWIG_IndexError, "Index out of bounds"); + return NULL; } } -%extend crpropa::Vector3 -{ - size_t __len__() - { +%extend crpropa::Vector3 { + size_t __len__() { return 3; } - PyObject* __array__() - { + PyObject* __array__() { npy_intp shape[1]; shape[0] = 3; PyObject *ro; - if (sizeof($self->data[0]) == NPY_SIZEOF_FLOAT) - { + if (sizeof($self->data[0]) == NPY_SIZEOF_FLOAT) { ro = PyArray_SimpleNewFromData(1, shape, NPY_FLOAT, $self->data); - } - else if (sizeof($self->data[0]) == NPY_SIZEOF_DOUBLE) - { + } else if (sizeof($self->data[0]) == NPY_SIZEOF_DOUBLE) { ro = PyArray_SimpleNewFromData(1, shape, NPY_DOUBLE, $self->data); - } - else - { + } else { KISS_LOG_ERROR << "crpropa::Vector3 has fixed size of 3 elements!"; } return ro; } - double __getitem__(size_t i) - { + double __getitem__(size_t i) { if(i > 2) { throw RangeError(); } - + return $self->data[i]; } - int __setitem__(size_t i, T value) - { + int __setitem__(size_t i, T value) { if(i > 2) { - throw RangeError(); + throw RangeError(); } $self->data[i] = value; return 0; } - const std::string getDescription() - { + const std::string getDescription() { char buffer[256]; sprintf( buffer, "Vector(%.6G, %.6G, %.6G)", $self->x, $self->y, $self->z ); return buffer; @@ -187,191 +168,102 @@ using namespace crpropa; // for usage of namespace in header files, necessary %nothread; /* disable threading for extend*/ %extend crpropa::Candidate { - PyObject * getProperty(PyObject * name){ - - std::string input; - - if (PyUnicode_Check(name)){ - #ifdef SWIG_PYTHON3 - // test on PY_MAJOR_VERSION >= 3 wont work with swig - input = PyUnicode_AsUTF8(name); - #else - PyObject *s = PyUnicode_AsUTF8String(name); - input = PyString_AsString(s); - #endif - } - #ifndef SWIG_PYTHON3 - else if (PyString_Check(name)){ - input = PyString_AsString(name); - } - #endif - else { - std::cerr << "ERROR: The argument of getProperty() must be a string/unicode object!" << std::endl; - return NULL; - } + PyObject * getProperty(PyObject* name) { - crpropa::Variant value = $self->getProperty(input); + std::string input; - // implement this conversion here and not in the Variant as - // __asPythonObject, as extensions cannot be called from extension. - if (! value.isValid()) - { - Py_INCREF(Py_None); - return Py_None; - } - else if (value.getTypeInfo() == typeid(bool)) - { - if(value.toBool()) - { - Py_RETURN_TRUE; - } - else - { - Py_RETURN_FALSE; - } - } - // convert all integer types to python long - else if (value.getTypeInfo() == typeid(char)) - { - return PyInt_FromLong(value.toInt64()); - } - else if (value.getTypeInfo() == typeid(unsigned char)) - { - return PyInt_FromLong(value.toInt64()); - } - else if (value.getTypeInfo() == typeid(int16_t)) - { - return PyInt_FromLong(value.toInt64()); - } - else if (value.getTypeInfo() == typeid(uint16_t)) - { - return PyInt_FromLong(value.toInt64()); - } - else if (value.getTypeInfo() == typeid(int32_t)) - { - return PyInt_FromLong(value.toInt64()); - } - else if (value.getTypeInfo() == typeid(uint32_t)) - { - return PyInt_FromLong(value.toInt64()); - } - else if (value.getTypeInfo() == typeid(int64_t)) - { - return PyLong_FromLong(value.toInt64()); - } - else if (value.getTypeInfo() == typeid(uint64_t)) - { - return PyLong_FromUnsignedLong(value.toInt64()); - } - // convert float and double to pyfloat which is double precision - else if (value.getTypeInfo() == typeid(float)) - { - return PyFloat_FromDouble(value.toDouble()); - } - else if (value.getTypeInfo() == typeid(double)) - { - return PyFloat_FromDouble(value.toDouble()); - } - else if (value.getTypeInfo() == typeid(std::string)) - { - #ifdef SWIG_PYTHON3 - return PyUnicode_FromString(value.toString().c_str()); - #else - return PyString_FromString(value.toString().c_str()); - #endif - } - - std::cerr << "ERROR: Unknown Type" << std::endl; - return NULL; + if (PyUnicode_Check(name)) { + input = PyUnicode_AsUTF8(name); + } else if (PyString_Check(name)){ + input = PyString_AsString(name); + } else { + std::cerr << "ERROR: The argument of getProperty() must be a string/unicode object!" << std::endl; + return NULL; } + crpropa::Variant value = $self->getProperty(input); - PyObject * setProperty(PyObject * name, PyObject * value){ + // implement this conversion here and not in the Variant as + // __asPythonObject, as extensions cannot be called from extension. + if (! value.isValid()) { + Py_INCREF(Py_None); + return Py_None; + } else if (value.getTypeInfo() == typeid(bool)) { + if(value.toBool()) { + Py_RETURN_TRUE; + } else { + Py_RETURN_FALSE; + } + } else if (value.getTypeInfo() == typeid(char)) { + // convert all integer types to python long + return PyInt_FromLong(value.toInt64()); + } else if (value.getTypeInfo() == typeid(unsigned char)) { + return PyInt_FromLong(value.toInt64()); + } else if (value.getTypeInfo() == typeid(int16_t)) { + return PyInt_FromLong(value.toInt64()); + } else if (value.getTypeInfo() == typeid(uint16_t)) { + return PyInt_FromLong(value.toInt64()); + } else if (value.getTypeInfo() == typeid(int32_t)) { + return PyInt_FromLong(value.toInt64()); + } else if (value.getTypeInfo() == typeid(uint32_t)) { + return PyInt_FromLong(value.toInt64()); + } else if (value.getTypeInfo() == typeid(int64_t)) { + return PyLong_FromLong(value.toInt64()); + } else if (value.getTypeInfo() == typeid(uint64_t)) { + return PyLong_FromUnsignedLong(value.toInt64()); + } else if (value.getTypeInfo() == typeid(float)) { + // convert float and double to pyfloat which is double precision + return PyFloat_FromDouble(value.toDouble()); + } else if (value.getTypeInfo() == typeid(double)) { + return PyFloat_FromDouble(value.toDouble()); + } else if (value.getTypeInfo() == typeid(std::string)) { + return PyUnicode_FromString(value.toString().c_str()); + } - std::string input; + std::cerr << "ERROR: Unknown Type" << std::endl; + return NULL; + } - if (PyUnicode_Check(name)){ - #ifdef SWIG_PYTHON3 - input = PyUnicode_AsUTF8(name); - #else - input = PyUnicode_AS_DATA(name); - PyObject *s = PyUnicode_AsUTF8String(name); - input = PyString_AsString(s); - #endif - } - #ifndef SWIG_PYTHON3 - else if (PyString_Check( name )){ - input = PyString_AsString( name ); - } - #endif - else { - std::cerr << "ERROR: The argument of setProperty() must be a string/unicode object!" << std::endl; - return NULL; - } + PyObject * setProperty(PyObject * name, PyObject * value) { + std::string input; - if (value == Py_None) - { - $self->setProperty(input, crpropa::Variant()); - Py_RETURN_TRUE; - } - else if (PyBool_Check(value)) - { - if(value == Py_True) - { - $self->setProperty(input, true); - } - else - { - $self->setProperty(input, false); - } - Py_RETURN_TRUE; - } - else if (PyInt_Check(value)) - { - $self->setProperty(input, crpropa::Variant::fromInt32(PyInt_AsLong(value))); - Py_RETURN_TRUE; - } - else if (PyLong_Check(value)) - { - $self->setProperty(input, crpropa::Variant::fromUInt64(PyLong_AsLong(value))); - Py_RETURN_TRUE; - } - else if (PyFloat_Check(value)) - { - $self->setProperty(input, crpropa::Variant::fromDouble(PyFloat_AsDouble(value))); - Py_RETURN_TRUE; - } - else if (PyUnicode_Check(value)){ - #ifdef SWIG_PYTHON3 - $self->setProperty(input, PyUnicode_AsUTF8(value)); - #else - PyObject *s = PyUnicode_AsUTF8String(value); - $self->setProperty(input, PyString_AsString(s)); - #endif - Py_RETURN_TRUE; - } - #ifndef SWIG_PYTHON3 - else if (PyString_Check( value)) - { - $self->setProperty(input, PyString_AsString(value)); - Py_RETURN_TRUE; - } - #endif - else - { - PyObject *t = PyObject_Str(PyObject_Type(value)); - std::string ot; - - #ifdef SWIG_PYTHON3 - ot = PyUnicode_AsUTF8(t); - #else - ot = PyString_AsString(t); - #endif - std::cerr << "ERROR: Unknown Type: " << ot << std::endl; - return NULL; - } + if (PyUnicode_Check(name)){ + input = PyUnicode_AsUTF8(name); + } else { + std::cerr << "ERROR: The argument of setProperty() must be a string/unicode object!" << std::endl; + return NULL; + } + + if (value == Py_None) { + $self->setProperty(input, crpropa::Variant()); + Py_RETURN_TRUE; + } else if (PyBool_Check(value)) { + if(value == Py_True) { + $self->setProperty(input, true); + } else { + $self->setProperty(input, false); + } + Py_RETURN_TRUE; + } else if (PyInt_Check(value)) { + $self->setProperty(input, crpropa::Variant::fromInt32(PyInt_AsLong(value))); + Py_RETURN_TRUE; + } else if (PyLong_Check(value)) { + $self->setProperty(input, crpropa::Variant::fromUInt64(PyLong_AsLong(value))); + Py_RETURN_TRUE; + } else if (PyFloat_Check(value)) { + $self->setProperty(input, crpropa::Variant::fromDouble(PyFloat_AsDouble(value))); + Py_RETURN_TRUE; + } else if (PyUnicode_Check(value)){ + $self->setProperty(input, PyUnicode_AsUTF8(value)); + Py_RETURN_TRUE; + } else { + PyObject *t = PyObject_Str(PyObject_Type(value)); + std::string ot = PyUnicode_AsUTF8(t); + std::cerr << "ERROR: Unknown Type: " << ot << std::endl; + return NULL; } + } }; %thread; /* reenable threading */ @@ -470,71 +362,36 @@ using namespace crpropa; // for usage of namespace in header files, necessary %ignore crpropa::Output::enableProperty(const std::string &property, const Variant& defaultValue, const std::string &comment = ""); %extend crpropa::Output{ - PyObject * enableProperty(const std::string &name, PyObject* defaultValue, const std::string &comment="") - { - - if (defaultValue == Py_None) - { - Py_RETURN_TRUE; - } - else if (PyBool_Check(defaultValue)) - { - if(defaultValue == Py_True) - { - $self->enableProperty(name, true, comment); - } - else - { - $self->enableProperty(name, false, comment); - } - Py_RETURN_TRUE; - } - else if (PyInt_Check(defaultValue)) - { - $self->enableProperty(name, crpropa::Variant::fromInt32(PyInt_AsLong(defaultValue)), comment); - Py_RETURN_TRUE; - } - else if (PyLong_Check(defaultValue)) - { - $self->enableProperty(name, crpropa::Variant::fromInt64(PyLong_AsLong(defaultValue)), comment); - Py_RETURN_TRUE; - } - else if (PyFloat_Check(defaultValue)) - { - $self->enableProperty(name, crpropa::Variant::fromDouble(PyFloat_AsDouble(defaultValue)), comment); - Py_RETURN_TRUE; - } - else if (PyUnicode_Check(defaultValue)){ - #ifdef SWIG_PYTHON3 - std::string ss = PyUnicode_AsUTF8(defaultValue); - #else - PyObject *s = PyUnicode_AsUTF8String(defaultValue); - std::string ss = PyString_AsString(s); - #endif - $self->enableProperty(name, ss, comment); - Py_RETURN_TRUE; - } - #ifndef SWIG_PYTHON3 - else if (PyString_Check( defaultValue)) - { - std::string ss = PyString_AsString(defaultValue); - $self->enableProperty(name, ss, comment); - Py_RETURN_TRUE; - } - #endif - else - { - PyObject *t = PyObject_Str(PyObject_Type(defaultValue)); - std::string ot; - - #ifdef SWIG_PYTHON3 - ot = PyUnicode_AsUTF8(t); - #else - ot = PyString_AsString(t); - #endif - std::cerr << "ERROR: Unknown Type: " << ot << std::endl; - return NULL; - } + PyObject* enableProperty(const std::string &name, PyObject* defaultValue, const std::string &comment="") { + + if (defaultValue == Py_None) { + Py_RETURN_TRUE; + } else if (PyBool_Check(defaultValue)) { + if(defaultValue == Py_True) { + $self->enableProperty(name, true, comment); + } else { + $self->enableProperty(name, false, comment); + } + Py_RETURN_TRUE; + } else if (PyInt_Check(defaultValue)) { + $self->enableProperty(name, crpropa::Variant::fromInt32(PyInt_AsLong(defaultValue)), comment); + Py_RETURN_TRUE; + } else if (PyLong_Check(defaultValue)) { + $self->enableProperty(name, crpropa::Variant::fromInt64(PyLong_AsLong(defaultValue)), comment); + Py_RETURN_TRUE; + } else if (PyFloat_Check(defaultValue)) { + $self->enableProperty(name, crpropa::Variant::fromDouble(PyFloat_AsDouble(defaultValue)), comment); + Py_RETURN_TRUE; + } else if (PyUnicode_Check(defaultValue)){ + std::string ss = PyUnicode_AsUTF8(defaultValue); + $self->enableProperty(name, ss, comment); + Py_RETURN_TRUE; + } else { + PyObject* t = PyObject_Str(PyObject_Type(defaultValue)); + std::string ot = PyUnicode_AsUTF8(t); + std::cerr << "ERROR: Unknown Type: " << ot << std::endl; + return NULL; + } } } @@ -543,7 +400,6 @@ using namespace crpropa; // for usage of namespace in header files, necessary %include "crpropa/module/Output.h" %include "crpropa/module/DiffusionSDE.h" %include "crpropa/module/TextOutput.h" - %include "crpropa/module/HDF5Output.h" %include "crpropa/module/OutputShell.h" %include "crpropa/module/PhotonOutput1D.h" @@ -573,26 +429,25 @@ using namespace crpropa; // for usage of namespace in header files, necessary %include "crpropa/Source.h" %inline %{ -class ModuleListIterator { - public: - ModuleListIterator( - crpropa::ModuleList::iterator _cur, - crpropa::ModuleList::iterator _end) : - cur(_cur), end(_end) {} - ModuleListIterator* __iter__() { return this; } - crpropa::ModuleList::iterator cur; - crpropa::ModuleList::iterator end; - }; + class ModuleListIterator { + public: + ModuleListIterator( + crpropa::ModuleList::iterator _cur, + crpropa::ModuleList::iterator _end) : + cur(_cur), end(_end) { + } + ModuleListIterator* __iter__() { + return this; + } + crpropa::ModuleList::iterator cur; + crpropa::ModuleList::iterator end; + }; %} %extend ModuleListIterator { -#ifdef SWIG_PYTHON3 crpropa::ref_ptr& __next__() { -#else - crpropa::ref_ptr& next() { -#endif if ($self->cur != $self->end) { - return *$self->cur++; + return *$self->cur++; } throw StopIterator(); } @@ -600,16 +455,18 @@ class ModuleListIterator { %extend crpropa::ModuleList { ModuleListIterator __iter__() { - return ModuleListIterator($self->begin(), $self->end()); + return ModuleListIterator($self->begin(), $self->end()); } + crpropa::ref_ptr __getitem__(size_t i) { - if (i >= $self->size()) { - throw RangeError(); - } - return (*($self))[i]; + if (i >= $self->size()) { + throw RangeError(); + } + return (*($self))[i]; } + size_t __len__() { - return $self->size(); + return $self->size(); } }; @@ -619,26 +476,25 @@ class ModuleListIterator { %template(ParticleCollectorRefPtr) crpropa::ref_ptr; %inline %{ -class ParticleCollectorIterator { - public: - ParticleCollectorIterator( - crpropa::ParticleCollector::iterator _cur, - crpropa::ParticleCollector::iterator _end) : - cur(_cur), end(_end) {} - ParticleCollectorIterator* __iter__() { return this; } - crpropa::ParticleCollector::iterator cur; - crpropa::ParticleCollector::iterator end; + class ParticleCollectorIterator { + public: + ParticleCollectorIterator( + crpropa::ParticleCollector::iterator _cur, + crpropa::ParticleCollector::iterator _end) : + cur(_cur), end(_end) { + } + ParticleCollectorIterator* __iter__() { + return this; + } + crpropa::ParticleCollector::iterator cur; + crpropa::ParticleCollector::iterator end; }; %} %extend ParticleCollectorIterator { -#ifdef SWIG_PYTHON3 crpropa::ref_ptr& __next__() { -#else - crpropa::ref_ptr& next() { -#endif if ($self->cur != $self->end) { - return *$self->cur++; + return *$self->cur++; } throw StopIterator(); } @@ -646,45 +502,44 @@ class ParticleCollectorIterator { %extend crpropa::ParticleCollector { ParticleCollectorIterator __iter__() { - return ParticleCollectorIterator($self->begin(), $self->end()); + return ParticleCollectorIterator($self->begin(), $self->end()); } + crpropa::ref_ptr __getitem__(size_t i) { - if (i >= $self->size()) { - throw RangeError(); - } - return (*($self))[i]; + if (i >= $self->size()) { + throw RangeError(); + } + return (*($self))[i]; } - std::vector< crpropa::ref_ptr > __getitem__(PyObject *param) { - std::vector< crpropa::ref_ptr > result; - - if (PySlice_Check(param)) { - Py_ssize_t len = 0, start = 0, stop = 0, step = 0, slicelength = 0, i = 0; - len = $self->size(); - - #ifdef SWIG_PYTHON3 - PySlice_GetIndicesEx(param, len, &start, &stop, &step, &slicelength); - #else - PySlice_GetIndicesEx((PySliceObject*)param, len, &start, &stop, &step, &slicelength); - #endif - - for(crpropa::ParticleCollector::iterator itr = $self->begin(); itr != $self->end(); ++itr){ - if( i >= start && i < stop){ - result.push_back(itr->get()); - } - ++i; - } - return result; - } else { - throw RangeError(); + + std::vector> __getitem__(PyObject *param) { + std::vector< crpropa::ref_ptr > result; + + if (PySlice_Check(param)) { + Py_ssize_t len = 0, start = 0, stop = 0, step = 0, slicelength = 0, i = 0; + len = $self->size(); + + PySlice_GetIndicesEx(param, len, &start, &stop, &step, &slicelength); + + for(crpropa::ParticleCollector::iterator itr = $self->begin(); itr != $self->end(); ++itr) { + if(i >= start && i < stop) { + result.push_back(itr->get()); } + ++i; + } + return result; + + } else { + throw RangeError(); + } } + size_t __len__() { - return $self->size(); + return $self->size(); } }; %include "crpropa/module/ParticleCollector.h" - %include "crpropa/massDistribution/Density.h" %include "crpropa/massDistribution/Nakanishi.h" %include "crpropa/massDistribution/Cordes.h" @@ -693,8 +548,6 @@ class ParticleCollectorIterator { %include "crpropa/massDistribution/ConstantDensity.h" - - %template(StepLengthModifierRefPtr) crpropa::ref_ptr; %feature("director") crpropa::StepLengthModifier; %include "crpropa/module/Acceleration.h" diff --git a/python/3_repr.i b/python/3_repr.i index d7ff1fea4..6b584e7b5 100644 --- a/python/3_repr.i +++ b/python/3_repr.i @@ -12,6 +12,6 @@ __REPR__( crpropa::Observer ); __REPR__( crpropa::ObserverFeature ); %pythoncode %{ - __version__ = g_GIT_DESC + __version__ = g_GIT_DESC %} diff --git a/python/4_lens.i b/python/4_lens.i index 3fd932a5e..e035e91cd 100644 --- a/python/4_lens.i +++ b/python/4_lens.i @@ -9,10 +9,10 @@ %template(DoubleVector) std::vector; %{ -#include "crpropa/magneticLens/ModelMatrix.h" -#include "crpropa/magneticLens/Pixelization.h" -#include "crpropa/magneticLens/MagneticLens.h" -#include "crpropa/magneticLens/ParticleMapsContainer.h" + #include "crpropa/magneticLens/ModelMatrix.h" + #include "crpropa/magneticLens/Pixelization.h" + #include "crpropa/magneticLens/MagneticLens.h" + #include "crpropa/magneticLens/ParticleMapsContainer.h" %} %include "crpropa/magneticLens/ModelMatrix.h" @@ -39,19 +39,16 @@ #ifdef WITHNUMPY %extend crpropa::MagneticLens{ - PyObject * transformModelVector_numpyArray(PyObject *input, double rigidity) - { + PyObject * transformModelVector_numpyArray(PyObject *input, double rigidity) { PyArrayObject *arr = NULL; PyArray_Descr *dtype = NULL; int ndim = 0; npy_intp dims[NPY_MAXDIMS]; - if (PyArray_GetArrayParamsFromObject(input, NULL, 1, &dtype, &ndim, dims, &arr, NULL) < 0) - { + if (PyArray_GetArrayParamsFromObject(input, NULL, 1, &dtype, &ndim, dims, &arr, NULL) < 0) { Py_RETURN_NONE; } - if (arr == NULL) - { + if (arr == NULL) { Py_RETURN_NONE; } @@ -62,8 +59,7 @@ }; #else %extend crpropa::MagneticLens{ - PyObject * transformModelVector_numpyArray(PyObject *input, double rigidity) - { + PyObject * transformModelVector_numpyArray(PyObject *input, double rigidity) { std::cerr << "ERROR: CRPropa was compiled without NumPy support!" << std::endl; Py_RETURN_NONE; } @@ -83,36 +79,30 @@ #ifdef WITHNUMPY %extend crpropa::ParticleMapsContainer { PyObject *addParticles(PyObject *particleIds, - PyObject *energies, - PyObject *galacticLongitudes, - PyObject *galacticLatitudes, - PyObject *weights) - { + PyObject *energies, + PyObject *galacticLongitudes, + PyObject *galacticLatitudes, + PyObject *weights) { //ToDo: Handle strided arrays //ToDo: Check that input objects are arrays PyArray_Check - if (!PyArray_Check(particleIds)) - { + if (!PyArray_Check(particleIds)) { std::cerr << "ParticleMapsContainer::addParticles - require array as input for particleIds\n"; Py_RETURN_NONE; } - if (!PyArray_Check(energies)) - { + if (!PyArray_Check(energies)) { std::cerr << "ParticleMapsContainer::addParticles - require array as input for energy\n"; Py_RETURN_NONE; } - if (!PyArray_Check(galacticLongitudes)) - { + if (!PyArray_Check(galacticLongitudes)) { std::cerr << "ParticleMapsContainer::addParticles - require array as input for galacticLongitudes\n"; Py_RETURN_NONE; } - if (!PyArray_Check(galacticLatitudes)) - { + if (!PyArray_Check(galacticLatitudes)) { std::cerr << "ParticleMapsContainer::addParticles - require array as input for galacticLatitudes\n"; Py_RETURN_NONE; } - if (!PyArray_Check(weights)) - { + if (!PyArray_Check(weights)) { std::cerr << "ParticleMapsContainer::addParticles - require array as input for weights\n"; Py_RETURN_NONE; } @@ -128,16 +118,11 @@ int intSize = 0; // check integer type - if((PyArray_TYPE(particleIds_arr) == NPY_INT32) || (PyArray_TYPE(particleIds_arr) == NPY_UINT32)) - { + if((PyArray_TYPE(particleIds_arr) == NPY_INT32) || (PyArray_TYPE(particleIds_arr) == NPY_UINT32)) { intSize = 32; - } - else if((PyArray_TYPE(particleIds_arr) == NPY_INT64) || (PyArray_TYPE(particleIds_arr) == NPY_UINT64)) - { + } else if((PyArray_TYPE(particleIds_arr) == NPY_INT64) || (PyArray_TYPE(particleIds_arr) == NPY_UINT64)) { intSize = 64; - } - else - { + } else { std::cerr << ""; throw std::runtime_error("ParticleMapsContainer::addParticles - require array of type int as input for ids"); } @@ -152,20 +137,14 @@ npy_intp *D = PyArray_DIMS(particleIds_arr); int arraySize = D[0]; - for(size_t i = 0; i < arraySize; i++) - { - if (intSize == 32) - { + for(size_t i = 0; i < arraySize; i++) { + if (intSize == 32) { $self->addParticle(((int32_t*) particleIds_dp)[i], energies_dp[i], galacticLongitudes_dp[i], galacticLatitudes_dp[i], weights_dp[i]); - } - else if (intSize == 64) - { + } else if (intSize == 64) { $self->addParticle(((int64_t*) particleIds_dp)[i], energies_dp[i], galacticLongitudes_dp[i], galacticLatitudes_dp[i], weights_dp[i]); - } - else - { + } else { throw std::runtime_error("ParticleMapsContainer::addParticles - unknown int size"); } @@ -173,93 +152,80 @@ Py_RETURN_TRUE; } - PyObject *getMap_numpyArray(const int particleId, double energy) - { - double* data = $self->getMap(particleId, energy); - npy_intp npix = $self->getNumberOfPixels(); - npy_intp dims[1] = {npix}; - return PyArray_SimpleNewFromData(1, dims, NPY_DOUBLE, (void*)data); + PyObject *getMap_numpyArray(const int particleId, double energy) { + double* data = $self->getMap(particleId, energy); + npy_intp npix = $self->getNumberOfPixels(); + npy_intp dims[1] = {npix}; + return PyArray_SimpleNewFromData(1, dims, NPY_DOUBLE, (void*)data); } - PyObject *getParticleIds_numpyArray() - { - std::vector v = $self->getParticleIds(); - npy_intp size = v.size(); - PyObject *out = PyArray_SimpleNew(1, &size, NPY_INT); - memcpy(PyArray_DATA((PyArrayObject *) out), &v[0], v.size() * sizeof(int)); - return out; + PyObject *getParticleIds_numpyArray() { + std::vector v = $self->getParticleIds(); + npy_intp size = v.size(); + PyObject *out = PyArray_SimpleNew(1, &size, NPY_INT); + memcpy(PyArray_DATA((PyArrayObject *) out), &v[0], v.size() * sizeof(int)); + return out; } - PyObject *getEnergies_numpyArray(const int pid) - { - std::vector v = $self->getEnergies(pid); - npy_intp size = v.size(); - PyObject *out = PyArray_SimpleNew(1, &size, NPY_DOUBLE); - memcpy(PyArray_DATA((PyArrayObject *) out), &v[0], v.size() * sizeof(double)); - return out; + PyObject *getEnergies_numpyArray(const int pid) { + std::vector v = $self->getEnergies(pid); + npy_intp size = v.size(); + PyObject *out = PyArray_SimpleNew(1, &size, NPY_DOUBLE); + memcpy(PyArray_DATA((PyArrayObject *) out), &v[0], v.size() * sizeof(double)); + return out; } - PyObject *getRandomParticles_numpyArray(size_t N) - { - vector particleId; - vector energy; - vector galacticLongitudes; - vector galacticLatitudes; - $self->getRandomParticles(N, particleId, energy, galacticLongitudes, - galacticLatitudes); - - npy_intp size = N; - PyArrayObject *oId = (PyArrayObject*)PyArray_New(&PyArray_Type, 1, &size, NPY_INT, NULL, NULL, 0, NPY_ARRAY_CARRAY, NULL); - PyArrayObject *oEnergy = (PyArrayObject*)PyArray_New(&PyArray_Type, 1, &size, NPY_DOUBLE, NULL, NULL, 0, NPY_ARRAY_CARRAY, NULL); - PyArrayObject *oLon = (PyArrayObject*)PyArray_New(&PyArray_Type, 1, &size, NPY_DOUBLE, NULL, NULL, 0, NPY_ARRAY_CARRAY, NULL); - PyArrayObject *oLat = (PyArrayObject*)PyArray_New(&PyArray_Type, 1, &size, NPY_DOUBLE, NULL, NULL, 0, NPY_ARRAY_CARRAY, NULL); - - memcpy(PyArray_DATA(oId), &particleId[0], - particleId.size() * sizeof(int)); - memcpy(PyArray_DATA(oEnergy), &energy[0], energy.size() - * sizeof(double)); - memcpy(PyArray_DATA(oLon), &galacticLongitudes[0], - galacticLongitudes.size() * sizeof(double)); - memcpy(PyArray_DATA(oLat), &galacticLatitudes[0], - galacticLatitudes.size() * sizeof(double)); - - PyObject *returnList = PyList_New(4); - PyList_SET_ITEM(returnList, 0, (PyObject*)oId); - PyList_SET_ITEM(returnList, 1, (PyObject*)oEnergy); - PyList_SET_ITEM(returnList, 2, (PyObject*)oLon); - PyList_SET_ITEM(returnList, 3, (PyObject*)oLat); - - return returnList; + PyObject *getRandomParticles_numpyArray(size_t N) { + vector particleId; + vector energy; + vector galacticLongitudes; + vector galacticLatitudes; + $self->getRandomParticles(N, particleId, energy, galacticLongitudes, galacticLatitudes); + + npy_intp size = N; + PyArrayObject *oId = (PyArrayObject*)PyArray_New(&PyArray_Type, 1, &size, NPY_INT, NULL, NULL, 0, NPY_ARRAY_CARRAY, NULL); + PyArrayObject *oEnergy = (PyArrayObject*)PyArray_New(&PyArray_Type, 1, &size, NPY_DOUBLE, NULL, NULL, 0, NPY_ARRAY_CARRAY, NULL); + PyArrayObject *oLon = (PyArrayObject*)PyArray_New(&PyArray_Type, 1, &size, NPY_DOUBLE, NULL, NULL, 0, NPY_ARRAY_CARRAY, NULL); + PyArrayObject *oLat = (PyArrayObject*)PyArray_New(&PyArray_Type, 1, &size, NPY_DOUBLE, NULL, NULL, 0, NPY_ARRAY_CARRAY, NULL); + + memcpy(PyArray_DATA(oId), &particleId[0], particleId.size() * sizeof(int)); + memcpy(PyArray_DATA(oEnergy), &energy[0], energy.size() * sizeof(double)); + memcpy(PyArray_DATA(oLon), &galacticLongitudes[0], galacticLongitudes.size() * sizeof(double)); + memcpy(PyArray_DATA(oLat), &galacticLatitudes[0], galacticLatitudes.size() * sizeof(double)); + + PyObject *returnList = PyList_New(4); + PyList_SET_ITEM(returnList, 0, (PyObject*) oId); + PyList_SET_ITEM(returnList, 1, (PyObject*) oEnergy); + PyList_SET_ITEM(returnList, 2, (PyObject*) oLon); + PyList_SET_ITEM(returnList, 3, (PyObject*) oLat); + + return returnList; } }; #else // with numpy %extend crpropa::ParticleMapsContainer{ - PyObject *getMap_numpyArray(const int particleId, double energy) - { - std::cerr << "ERROR: CRPropa was compiled without NumPy support!" << std::endl; - Py_RETURN_NONE; + PyObject *getMap_numpyArray(const int particleId, double energy) { + std::cerr << "ERROR: CRPropa was compiled without NumPy support!" << std::endl; + Py_RETURN_NONE; } }; %extend crpropa::ParticleMapsContainer{ - PyObject *getParticleIds_numpyArray() - { - std::cerr << "ERROR: CRPropa was compiled without NumPy support!" << std::endl; - Py_RETURN_NONE; + PyObject *getParticleIds_numpyArray() { + std::cerr << "ERROR: CRPropa was compiled without NumPy support!" << std::endl; + Py_RETURN_NONE; } }; %extend crpropa::ParticleMapsContainer{ - PyObject *getEnergies_numpyArray(const int pid) - { - std::cerr << "ERROR: CRPropa was compiled without NumPy support!" << std::endl; - Py_RETURN_NONE; + PyObject *getEnergies_numpyArray(const int pid) { + std::cerr << "ERROR: CRPropa was compiled without NumPy support!" << std::endl; + Py_RETURN_NONE; } }; %extend crpropa::ParticleMapsContainer{ - PyObject *getRandomParticles_numpyArray(size_t N) - { - std::cerr << "ERROR: CRPropa was compiled without NumPy support!" << std::endl; - Py_RETURN_NONE; + PyObject *getRandomParticles_numpyArray(size_t N) { + std::cerr << "ERROR: CRPropa was compiled without NumPy support!" << std::endl; + Py_RETURN_NONE; } }; #endif // with NumPy diff --git a/python/crpropa-builtin.i b/python/crpropa-builtin.i index cd83a4dc3..60e5f9ee6 100644 --- a/python/crpropa-builtin.i +++ b/python/crpropa-builtin.i @@ -22,9 +22,9 @@ %feature("python:slot", "tp_repr", functype="reprfunc") classname::repr(); %extend classname { - const std::string repr() { - return $self->getDescription(); - } + const std::string repr() { + return $self->getDescription(); + } } %enddef From f547c1678179e886d5a25f8e186f50fd893186a4 Mon Sep 17 00:00:00 2001 From: Rafael Date: Sun, 4 Feb 2024 00:36:07 +0100 Subject: [PATCH 07/81] use CMake's Python finder; drop py2 support --- CMakeLists.txt | 89 +++++++++++++++++++++++++++----------------------- 1 file changed, 48 insertions(+), 41 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a12241254..80cd6a2ed 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,5 @@ cmake_minimum_required(VERSION 3.14) - project(CRPropa Fortran C CXX) set(CRPROPA_RELEASE_VERSION 3.2.1+) # Update for new release @@ -157,12 +156,13 @@ add_subdirectory(libs/sophia) list(APPEND CRPROPA_EXTRA_LIBRARIES sophia gfortran) list(APPEND CRPROPA_EXTRA_INCLUDES libs/sophia) -# GlacticMagneticLenses +# Galactic magnetic lenses option(ENABLE_GALACTICMAGNETICLENS "Galactic Magnetic Lens" ON) option(INSTALL_EIGEN "Install provided EIGEN headers" OFF) SET(EIGEN_PATH "" CACHE STRING "Use EIGEN from this path instead of the version shipped with CRPropa") SET(WITH_GALACTIC_LENSES FALSE) -if(ENABLE_GALACTICMAGETICLENS) + +if(ENABLE_GALACTICMAGNETICLENS) SET(WITH_GALACTIC_LENSES TRUE) if(EIGEN_PATH) @@ -189,7 +189,7 @@ if(ENABLE_GALACTICMAGETICLENS) list(APPEND CRPROPA_EXTRA_SOURCES src/magneticLens/ModelMatrix.cpp) list(APPEND CRPROPA_EXTRA_SOURCES src/magneticLens/Pixelization.cpp) list(APPEND CRPROPA_EXTRA_SOURCES src/magneticLens/ParticleMapsContainer.cpp) -endif(ENABLE_GALACTICMAGETICLENS) +endif(ENABLE_GALACTICMAGNETICLENS) # OpenMP (optional for shared memory multiprocessing) option(ENABLE_OPENMP "OpenMP for multithreading" ON) @@ -444,14 +444,39 @@ endif(BUILD_DOC) # Python # ---------------------------------------------------------------------------- option(ENABLE_PYTHON "Create python library via SWIG" ON) -find_package(PythonInterp) -find_package(PythonLibs) -if(ENABLE_PYTHON AND PYTHONLIBS_FOUND) +find_package(Python 3.0 + REQUIRED COMPONENTS Interpreter Development + OPTIONAL_COMPONENTS NumPy) +if(ENABLE_PYTHON AND Python_FOUND) find_package(SWIG 3.0 REQUIRED) - include(python/Python.cmake) - include_directories(${PYTHON_INCLUDE_PATH}) + include_directories(${Python_INCLUDE_DIRS}) + + # print Python info in detail + message(STATUS "Python: Found!") + message(STATUS " version ${Python_VERSION}") + message(STATUS " executable: ${Python_EXECUTABLE}") + message(STATUS " libraries: ${Python_LIBRARIES}") + message(STATUS " headers: ${Python_INCLUDE_DIRS}") + message(STATUS " site packages: ${Python_SITELIB}") + if(Python_Development_FOUND) + message(STATUS " development libraries: Found!") + elseif(Python_Development_FOUND) + message(STATUS " development libraries: NOT found!") + endif(Python_Development_FOUND) + + # look for NumPy + if(Python_NumPy_FOUND) + set(CMAKE_SWIG_FLAGS -DWITHNUMPY ${CRP}) + list(APPEND CRPROPA_SWIG_DEFINES -DWITHNUMPY) + include_directories(${Python_NumPy_INCLUDE_DIRS}) + message(STATUS "NumPy: Found!") + message(STATUS " headers: ${Python_NumPy_INCLUDE_DIRS} (version ${Python_NumPy_VERSION})") + elseif(Python_NumPy_FOUND) + message(STATUS "NumPy: NOT found!") + message(STATUS " CRPropa might work just fine with Python, but features like Galactic lenses will not be available.") + endif(Python_NumPy_FOUND) if(SWIG_VERSION VERSION_GREATER 4.0) # Use swig 4 builtin doxygen instead of external program @@ -469,39 +494,22 @@ if(ENABLE_PYTHON AND PYTHONLIBS_FOUND) if(ENABLE_SWIG_BUILTIN) set(BUILTIN "-builtin") - set(PY3 "-py3") if(SWIG_VERSION VERSION_LESS 4.0.2) message(WARNING, "The SWIG builtin option should not be used with SWIG version below 4.0.2 due to https://github.com/swig/swig/issues/1595") endif() else(ENABLE_SWIG_BUILTIN) set(BUILTIN "") - set(PY3 "") endif(ENABLE_SWIG_BUILTIN) - if(PYTHON_VERSION_STRING VERSION_GREATER 3.0) - list(APPEND CRPROPA_SWIG_DEFINES -DSWIG_PYTHON3) - endif(PYTHON_VERSION_STRING VERSION_GREATER 3.0) - - # tries to import numpy - execute_process(COMMAND ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/python/checkNumpy.py" OUTPUT_VARIABLE numpyIncludePath) - if(numpyIncludePath) - MESSAGE(STATUS "Found numpy headers in " ${numpyIncludePath}) - SET(CMAKE_SWIG_FLAGS -DWITHNUMPY ${CRP}) - list(APPEND CRPROPA_SWIG_DEFINES -DWITHNUMPY) - include_directories(${numpyIncludePath}) - else(numpyIncludePath) - MESSAGE(STATUS "Numpy not found.") - endif(numpyIncludePath) - set(SWIG_INCLUDES) foreach(p in ${SWIG_INCLUDE_DIRECTORIES}) list(APPEND SWIG_INCLUDES -I${p}) endforeach() file(GLOB_RECURSE CRPROPA_SWIG_INPUTS python/*.i) - set_source_files_properties( ${CMAKE_CURRENT_BINARY_DIR}/crpropa_wrap.cxx PROPERTIES GENERATED true ) + set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/crpropa_wrap.cxx PROPERTIES GENERATED true) add_custom_target(crpropa-swig-wrapper - COMMAND swig ${BUILTIN} -c++ -python ${PY3} -I${CMAKE_SOURCE_DIR}/include -I${CMAKE_SOURCE_DIR}/libs/HepPID/include ${SWIG_INCLUDES} ${CRPROPA_SWIG_DEFINES} -dirprot -o ${CMAKE_CURRENT_BINARY_DIR}/crpropa_wrap.cxx -outdir ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}/python/crpropa${BUILTIN}.i + COMMAND swig ${BUILTIN} -c++ -python -py3 -I${CMAKE_SOURCE_DIR}/include -I${CMAKE_SOURCE_DIR}/libs/HepPID/include ${SWIG_INCLUDES} ${CRPROPA_SWIG_DEFINES} -dirprot -o ${CMAKE_CURRENT_BINARY_DIR}/crpropa_wrap.cxx -outdir ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}/python/crpropa${BUILTIN}.i DEPENDS ${CRPROPA_SWIG_INPUTS} ${CRPROPA_INCLUDES} ) if(BUILD_DOC AND DOXYGEN_FOUND) @@ -513,14 +521,14 @@ if(ENABLE_PYTHON AND PYTHONLIBS_FOUND) # disable warnings on automatically generated interface code set_target_properties(crpropa-swig PROPERTIES COMPILE_FLAGS "-w") set_target_properties(crpropa-swig PROPERTIES OUTPUT_NAME "_crpropa") - target_link_libraries(crpropa-swig crpropa ${PYTHON_LIBRARIES}) + target_link_libraries(crpropa-swig crpropa ${Python_LIBRARIES} ${Python_LIBRARY}) add_dependencies(crpropa-swig crpropa-swig-wrapper) - install(DIRECTORY "${CMAKE_SOURCE_DIR}/python/crpropa" DESTINATION "${PYTHON_SITE_PACKAGES}") - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/crpropa.py" DESTINATION "${PYTHON_SITE_PACKAGES}/crpropa") - install(TARGETS crpropa-swig LIBRARY DESTINATION "${PYTHON_SITE_PACKAGES}/crpropa") + install(DIRECTORY "${CMAKE_SOURCE_DIR}/python/crpropa" DESTINATION ${CMAKE_INSTALL_PREFIX}) + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/crpropa.py" DESTINATION ${CMAKE_INSTALL_PREFIX}/crpropa) + install(TARGETS crpropa-swig LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/crpropa) install(FILES ${CRPROPA_SWIG_INPUTS} DESTINATION share/crpropa/swig_interface) -endif(ENABLE_PYTHON AND PYTHONLIBS_FOUND) +endif(ENABLE_PYTHON AND Python_FOUND) # ---------------------------------------------------------------------------- @@ -531,7 +539,6 @@ install(TARGETS crpropa DESTINATION lib) install(DIRECTORY include/ DESTINATION include FILES_MATCHING PATTERN "*.h") install(DIRECTORY ${CMAKE_BINARY_DIR}/include/ DESTINATION include FILES_MATCHING PATTERN "*.h") install(DIRECTORY ${CMAKE_BINARY_DIR}/data/ DESTINATION share/crpropa/ PATTERN ".git" EXCLUDE) - install(DIRECTORY libs/kiss/include/ DESTINATION include) # ------------------------------------------------------------------ @@ -636,23 +643,23 @@ if(ENABLE_TESTING) endif(WITH_GALACTIC_LENSES) # python tests - if(ENABLE_PYTHON AND PYTHONLIBS_FOUND) + if(ENABLE_PYTHON AND Python_FOUND) CONFIGURE_FILE(test/testMagneticLensPythonInterface.py testMagneticLensPythonInterface.py COPYONLY) if(numpyIncludePath AND WITH_GALACTIC_LENSES) - add_test(testMagneticLensPythonInterface ${PYTHON_EXECUTABLE} testMagneticLensPythonInterface.py) + add_test(testMagneticLensPythonInterface ${Python_EXECUTABLE} testMagneticLensPythonInterface.py) endif(numpyIncludePath AND WITH_GALACTIC_LENSES) CONFIGURE_FILE(test/testSimulationExecution.py testSimulationExecution.py COPYONLY) - add_test(testSimulationExecution ${PYTHON_EXECUTABLE} testSimulationExecution.py) + add_test(testSimulationExecution ${Python_EXECUTABLE} testSimulationExecution.py) CONFIGURE_FILE(test/testDiffusionSDE.py testDiffusionSDE.py COPYONLY) - add_test(testDiffusionSDE ${PYTHON_EXECUTABLE} testDiffusionSDE.py) + add_test(testDiffusionSDE ${Python_EXECUTABLE} testDiffusionSDE.py) CONFIGURE_FILE(test/testMomentumDiffusion.py testMomentumDiffusion.py COPYONLY) - add_test(testMomentumDiffusion ${PYTHON_EXECUTABLE} testMomentumDiffusion.py) + add_test(testMomentumDiffusion ${Python_EXECUTABLE} testMomentumDiffusion.py) CONFIGURE_FILE(test/testPythonExtension.py testPythonExtension.py COPYONLY) - add_test(testPythonExtension ${PYTHON_EXECUTABLE} testPythonExtension.py) - endif(ENABLE_PYTHON AND PYTHONLIBS_FOUND) + add_test(testPythonExtension ${Python_EXECUTABLE} testPythonExtension.py) + endif(ENABLE_PYTHON AND Python_FOUND) endif(ENABLE_TESTING) From c4d30a4d58f87e464fadcde2abada75bf6a107a5 Mon Sep 17 00:00:00 2001 From: Rafael Date: Sun, 4 Feb 2024 01:21:04 +0100 Subject: [PATCH 08/81] remove header of SAGA --- python/2_headers.i | 3 --- 1 file changed, 3 deletions(-) diff --git a/python/2_headers.i b/python/2_headers.i index b7a2d7787..6aaad3ac7 100644 --- a/python/2_headers.i +++ b/python/2_headers.i @@ -15,9 +15,6 @@ //%import (module="quimby") quimby.i #endif -#ifdef CRPROPA_HAVE_SAGA - %import (module="saga") saga.i -#endif %{ #include "CRPropa.h" From c55e5e4cb1fcd053b3722d99eeafceb4c23c5e35 Mon Sep 17 00:00:00 2001 From: Rafael Date: Sun, 4 Feb 2024 01:21:51 +0100 Subject: [PATCH 09/81] remove SAGA and SAGA-related packages --- cmake/FindSAGA.cmake | 19 ------------------- cmake/FindSQLite3.cmake | 20 -------------------- 2 files changed, 39 deletions(-) delete mode 100644 cmake/FindSAGA.cmake delete mode 100644 cmake/FindSQLite3.cmake diff --git a/cmake/FindSAGA.cmake b/cmake/FindSAGA.cmake deleted file mode 100644 index 7886e2dae..000000000 --- a/cmake/FindSAGA.cmake +++ /dev/null @@ -1,19 +0,0 @@ -# SAGA_INCLUDE_DIR = path to SAGA directory -# SAGA_LIBRARY libsaga.a -# SAGA_FOUND = true if SAGA is found - -find_path(SAGA_INCLUDE_DIR AMRgrid.h) -find_library(SAGA_LIBRARY libSAGA) - -set(SAGA_FOUND FALSE) -if(SAGA_INCLUDE_DIR AND SAGA_LIBRARY) - set(SAGA_FOUND TRUE) - MESSAGE(STATUS "SAGA: Found!") -else() - MESSAGE(STATUS "SAGA: NOT Found!") -endif() - -MESSAGE(STATUS " Include: ${SAGA_INCLUDE_DIR}") -MESSAGE(STATUS " Library: ${SAGA_LIBRARY}") - -mark_as_advanced(SAGA_INCLUDE_DIR SAGA_LIBRARY SAGA_FOUND) diff --git a/cmake/FindSQLite3.cmake b/cmake/FindSQLite3.cmake deleted file mode 100644 index e4bf1759e..000000000 --- a/cmake/FindSQLite3.cmake +++ /dev/null @@ -1,20 +0,0 @@ -# SQLITE3_INCLUDE_DIR = path to SAGA directory -# SQLITE3_LIBRARY = libsaga.so -# SQLITE3_FOUND = true if SAGA is found - -find_path(SQLITE3_INCLUDE_DIR sqlite3.h) -find_library(SQLITE3_LIBRARY libsqlite3) - -set(SQLITE3_FOUND FALSE) -if(SQLITE3_INCLUDE_DIR AND SQLITE3_LIBRARY) - set(SAGA_FOUND TRUE) - MESSAGE(STATUS "SQLite3: Found!") - include_directories(${SQLITE3_INCLUDE_DIR}) -else() - MESSAGE(STATUS "SQLite3: NOT Found!") -endif() - -MESSAGE(STATUS " Include: ${SQLITE3_INCLUDE_DIR}") -MESSAGE(STATUS " Library: ${SQLITE3_LIBRARY}") - -mark_as_advanced(SQLITE3_INCLUDE_DIR SQLITE3_LIBRARY SAGA_FOUND) From 80f741c54387eb35a1d9665df7d2ccdea76f2e07 Mon Sep 17 00:00:00 2001 From: Rafael Date: Sun, 4 Feb 2024 01:23:35 +0100 Subject: [PATCH 10/81] remove python finder; use CMake's built-in functionality --- python/Python.cmake | 105 -------------------------------------------- 1 file changed, 105 deletions(-) delete mode 100644 python/Python.cmake diff --git a/python/Python.cmake b/python/Python.cmake deleted file mode 100644 index 99227d41c..000000000 --- a/python/Python.cmake +++ /dev/null @@ -1,105 +0,0 @@ -# SETUP PYTHON - -# get default python inerpreter -FIND_PROGRAM( PYTHON_EXECUTABLE python REQUIRED - PATHS [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.7\\InstallPath] [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.6\\InstallPath] [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\2.5\\InstallPath] -) - -SET(PYTHONINTERP_FOUND TRUE) - -# find python include path -execute_process( - COMMAND ${PYTHON_EXECUTABLE} -c "import sys; from distutils import sysconfig; sys.stdout.write(sysconfig.get_python_inc())" - OUTPUT_VARIABLE PYTHON_INCLUDE_PATH - OUTPUT_STRIP_TRAILING_WHITESPACE -) - -FIND_FILE(PYTHON_H_FOUND Python.h ${PYTHON_INCLUDE_PATH}) -IF(NOT PYTHON_H_FOUND) - MESSAGE(SEND_ERROR "Python.h not found") -ENDIF() - -IF(APPLE) - - # apple changed linking to Python in OS X 10.9 (Mavericks) - # until 10.8: use Python.framework as part of the SDK (-framework Python) - # since 10.9: link to Python like any other UNIX - - # extract (minor) version number from SDK name (major version always 10 for OS X) - STRING(REGEX REPLACE ".*MacOSX([0-9]+)[.]([0-9]+)[.]sdk" "\\2" OSX_SDK_MINOR_VERSION "${CMAKE_OSX_SYSROOT}" ) - # MESSAGE("Found OS X SDK minor version: ${OSX_SDK_MINOR_VERSION}") - - IF (PYTHON_LIBRARIES) - SET(OSX_USE_PYTHON_FRAMEWORK "False") - MESSAGE(STATUS "Using user provided Python library: " ${PYTHON_LIBRARIES} ) - - ELSE(PYTHON_LIBRARIES) - IF(OSX_SDK_MINOR_VERSION GREATER 8) - SET(OSX_USE_PYTHON_FRAMEWORK "False") - MESSAGE(STATUS "Running on Mac OS X >= 10.9: Linking to Python in UNIX default way") - ELSE(OSX_SDK_MINOR_VERSION GREATER 8) - MESSAGE(STATUS "Running on Mac OS X < 10.9: Linking to Python as framework") - SET(OSX_USE_PYTHON_FRAMEWORK "True") - - INCLUDE(CMakeFindFrameworks) - # Search for the python framework on Apple. - MESSAGE(INFO "Looking for python framework as on apple system" ) - CMAKE_FIND_FRAMEWORKS(Python) - SET (PYTHON_LIBRARIES "-framework Python" CACHE FILEPATH "Python Framework" FORCE) - ENDIF(OSX_SDK_MINOR_VERSION GREATER 8) - ENDIF(PYTHON_LIBRARIES) - -ENDIF(APPLE) - -IF(MSVC) - execute_process( - COMMAND ${PYTHON_EXECUTABLE} -c "import sys; from distutils import sysconfig; import os; prefix= sysconfig.get_config_var('prefix'); ver = sysconfig.get_python_version().replace('.', ''); lib = os.path.join(prefix,'libs\\python'+ver+'.lib'); sys.stdout.write(lib)" - OUTPUT_VARIABLE PYTHON_LIBRARIES - OUTPUT_STRIP_TRAILING_WHITESPACE - ) -ENDIF(MSVC) - -IF (MINGW) - execute_process( - COMMAND ${PYTHON_EXECUTABLE} -c "import sys; from distutils import sysconfig; import os; prefix= sysconfig.get_config_var('prefix'); ver = sysconfig.get_python_version().replace('.', ''); lib = os.path.join(prefix,'libs\\libpython'+ver+'.a'); sys.stdout.write(lib)" - OUTPUT_VARIABLE PYTHON_LIBRARIES - OUTPUT_STRIP_TRAILING_WHITESPACE - ) -ENDIF(MINGW) - -IF(NOT OSX_USE_PYTHON_FRAMEWORK AND NOT PYTHON_LIBRARIES AND NOT MSVC AND NOT MINGW) - execute_process( - COMMAND ${PYTHON_EXECUTABLE} -c "import sys; from distutils import sysconfig; import os; libname = sysconfig.get_config_var('LDLIBRARY'); libdir = sysconfig.get_config_var('LIBPL'); lib = os.path.join(libdir,libname); out = lib if os.path.exists(lib) else os.path.join(libdir, sysconfig.get_config_var('LIBRARY')); sys.stdout.write(out);" - OUTPUT_VARIABLE PYTHON_LIBRARIES - OUTPUT_STRIP_TRAILING_WHITESPACE - ) -ENDIF(NOT OSX_USE_PYTHON_FRAMEWORK AND NOT PYTHON_LIBRARIES AND NOT MSVC AND NOT MINGW) - -#find the site package destinaton -execute_process( - COMMAND ${PYTHON_EXECUTABLE} -c "import sys; from distutils import sysconfig; sys.stdout.write(sysconfig.get_python_lib(1,0,prefix='${CMAKE_INSTALL_PREFIX}'))" - OUTPUT_VARIABLE PYTHON_SITE_PACKAGES - OUTPUT_STRIP_TRAILING_WHITESPACE -) - -execute_process( - COMMAND ${PYTHON_EXECUTABLE} -c "import sys; sys.stdout.write(str(sys.version_info[0]))" - OUTPUT_VARIABLE PYTHON_MAJOR_VERSION - OUTPUT_STRIP_TRAILING_WHITESPACE -) - -execute_process( - COMMAND ${PYTHON_EXECUTABLE} -c "import sys; sys.stdout.write(str(sys.version_info[1]))" - OUTPUT_VARIABLE PYTHON_MINOR_VERSION - OUTPUT_STRIP_TRAILING_WHITESPACE -) - -SET(PYTHON_VERSION "${PYTHON_MAJOR_VERSION}${PYTHON_MINOR_VERSION}") -SET(PYTHON_DOT_VERSION "${PYTHON_MAJOR_VERSION}.${PYTHON_MINOR_VERSION}") - -MESSAGE(STATUS "Python: Found!") -MESSAGE(STATUS " Version: " ${PYTHON_DOT_VERSION} "/" ${PYTHON_VERSION}) -MESSAGE(STATUS " Executeable: " ${PYTHON_EXECUTABLE}) -MESSAGE(STATUS " Include: " ${PYTHON_INCLUDE_PATH}) -MESSAGE(STATUS " Library: " ${PYTHON_LIBRARIES}) -MESSAGE(STATUS " Site-package directory: " ${PYTHON_SITE_PACKAGES}) From f376a4a59cace9549db1d432e64c214397cc2e20 Mon Sep 17 00:00:00 2001 From: Rafael Date: Sun, 4 Feb 2024 01:24:57 +0100 Subject: [PATCH 11/81] remove python finder; use CMake's built-in functionality --- python/checkMatplotlib.py | 12 ------------ python/checkNumpy.py | 14 -------------- 2 files changed, 26 deletions(-) delete mode 100644 python/checkMatplotlib.py delete mode 100644 python/checkNumpy.py diff --git a/python/checkMatplotlib.py b/python/checkMatplotlib.py deleted file mode 100644 index 05e51f3b1..000000000 --- a/python/checkMatplotlib.py +++ /dev/null @@ -1,12 +0,0 @@ -#Returns TRUE if matplotlib is available -#Silently exits with -1 otherwise -import sys -from distutils.version import LooseVersion -try: - import matplotlib - if LooseVersion(matplotlib.__version__) < LooseVersion("2.0.0"): - sys.stdout.write('Need matplotlib version >= 2.0.0 - found ' + matplotlib.__version__ + "\n") - sys.exit(-1) - -except ImportError: - sys.exit(-1) diff --git a/python/checkNumpy.py b/python/checkNumpy.py deleted file mode 100644 index f4edd928e..000000000 --- a/python/checkNumpy.py +++ /dev/null @@ -1,14 +0,0 @@ -#Returns the numpy include path if numpy version > 1.6 is available -#Silently exits with -1 otherwise -import sys -try: - import numpy - - from pkg_resources import parse_version - if parse_version(numpy.__version__) < parse_version('1.6.0'): - sys.exit(-1) - - sys.stdout.write(numpy.get_include()) - -except ImportError: - sys.exit(-1) From 7213d2d8915393f9158f499551fd6178a4aa4509 Mon Sep 17 00:00:00 2001 From: Rafael Date: Sun, 4 Feb 2024 03:03:21 +0100 Subject: [PATCH 12/81] update OSX workflow --- .github/workflows/testing_OSX.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/testing_OSX.yaml b/.github/workflows/testing_OSX.yaml index 4dfea11a8..4acf50aa7 100644 --- a/.github/workflows/testing_OSX.yaml +++ b/.github/workflows/testing_OSX.yaml @@ -7,8 +7,8 @@ jobs: fail-fast: false matrix: config: - - name: "macos-11" - os: macos-11 + - name: "macos-14" + os: macos-14 cxx: "clang++" cc: "clang" fc: "gfortran-11" @@ -19,7 +19,7 @@ jobs: uses: actions/checkout@v3 - name: Preinstall run: | - brew install hdf5 fftw cfitsio muparser libomp + brew install hdf5 fftw cfitsio muparser libomp numpy - name: Set up the build env: CXX: ${{ matrix.config.cxx }} @@ -29,7 +29,7 @@ jobs: run: | mkdir build cd build - cmake .. -DENABLE_PYTHON=True -DPYTHON_EXECUTABLE=${{ matrix.config.py }} -DENABLE_TESTING=On -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS=avx + cmake .. -DENABLE_PYTHON=True -DPython_EXECUTABLE=${{ matrix.config.py }} -DENABLE_TESTING=On -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS=avx - name: Build CRPropa run: | cd build From a33a0b55c67e0e0bdb445d3956d01711729fd42a Mon Sep 17 00:00:00 2001 From: Rafael Date: Sun, 4 Feb 2024 09:37:29 +0100 Subject: [PATCH 13/81] fix problems with OS X tests --- .github/workflows/testing_OSX.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/testing_OSX.yaml b/.github/workflows/testing_OSX.yaml index 4acf50aa7..8fe72d014 100644 --- a/.github/workflows/testing_OSX.yaml +++ b/.github/workflows/testing_OSX.yaml @@ -8,7 +8,7 @@ jobs: matrix: config: - name: "macos-14" - os: macos-14 + os: macos-14 # OS X Sonoma cxx: "clang++" cc: "clang" fc: "gfortran-11" @@ -29,7 +29,7 @@ jobs: run: | mkdir build cd build - cmake .. -DENABLE_PYTHON=True -DPython_EXECUTABLE=${{ matrix.config.py }} -DENABLE_TESTING=On -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS=avx + cmake .. -DENABLE_PYTHON=True -DENABLE_TESTING=On -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS=avx - name: Build CRPropa run: | cd build From aeb87631fb0daef414b81fb8893b0a23406590a6 Mon Sep 17 00:00:00 2001 From: Rafael Date: Sun, 4 Feb 2024 09:40:37 +0100 Subject: [PATCH 14/81] test auto-detection of Python --- .github/workflows/testing.yml | 2 +- .github/workflows/testing_ubuntu22.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index 2d86c35df..b7448cf48 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -30,7 +30,7 @@ jobs: run: | mkdir build cd build - cmake .. -DENABLE_PYTHON=True -DPYTHON_EXECUTABLE=${{ matrix.config.py }} -DENABLE_TESTING=On -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS=native + cmake .. -DENABLE_PYTHON=True -DENABLE_TESTING=On -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS=native - name: Build CRPropa run: | cd build diff --git a/.github/workflows/testing_ubuntu22.yml b/.github/workflows/testing_ubuntu22.yml index 677954ce6..3bada4ce5 100644 --- a/.github/workflows/testing_ubuntu22.yml +++ b/.github/workflows/testing_ubuntu22.yml @@ -30,7 +30,7 @@ jobs: run: | mkdir build cd build - cmake .. -DENABLE_PYTHON=True -DPYTHON_EXECUTABLE=${{ matrix.config.py }} -DENABLE_TESTING=On -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS=native + cmake .. -DENABLE_PYTHON=True -DENABLE_TESTING=On -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS=native - name: Build CRPropa run: | cd build From 84403594c83b57473c897ef771c13c3c73e70caa Mon Sep 17 00:00:00 2001 From: Rafael Date: Sun, 4 Feb 2024 09:46:28 +0100 Subject: [PATCH 15/81] ensure that swig is found in OSX installation --- .github/workflows/testing_OSX.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/testing_OSX.yaml b/.github/workflows/testing_OSX.yaml index 8fe72d014..1a8b950c7 100644 --- a/.github/workflows/testing_OSX.yaml +++ b/.github/workflows/testing_OSX.yaml @@ -19,7 +19,7 @@ jobs: uses: actions/checkout@v3 - name: Preinstall run: | - brew install hdf5 fftw cfitsio muparser libomp numpy + brew install hdf5 fftw cfitsio muparser libomp numpy swig - name: Set up the build env: CXX: ${{ matrix.config.cxx }} From cbc5bc0668beb6f81bdefe7dcd45655033855521 Mon Sep 17 00:00:00 2001 From: Rafael Date: Sun, 4 Feb 2024 10:02:15 +0100 Subject: [PATCH 16/81] ensure that swig is found in OSX installation --- .github/workflows/testing_OSX.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/testing_OSX.yaml b/.github/workflows/testing_OSX.yaml index 1a8b950c7..e3ac946a9 100644 --- a/.github/workflows/testing_OSX.yaml +++ b/.github/workflows/testing_OSX.yaml @@ -29,7 +29,7 @@ jobs: run: | mkdir build cd build - cmake .. -DENABLE_PYTHON=True -DENABLE_TESTING=On -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS=avx + cmake .. -DENABLE_PYTHON=True -DENABLE_TESTING=On -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS="none" - name: Build CRPropa run: | cd build From 39f09f2f8c26e9d9d629c5946ad9c61c196644af Mon Sep 17 00:00:00 2001 From: Rafael Date: Sun, 4 Feb 2024 10:32:33 +0100 Subject: [PATCH 17/81] fix failing tests by limiting to Python <= 3.11 --- .github/workflows/testing_OSX.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/testing_OSX.yaml b/.github/workflows/testing_OSX.yaml index e3ac946a9..04b5e2276 100644 --- a/.github/workflows/testing_OSX.yaml +++ b/.github/workflows/testing_OSX.yaml @@ -14,6 +14,7 @@ jobs: fc: "gfortran-11" swig_builtin: "On" #uses swig 4.0.2 py: "/usr/bin/python" + python-version: "3.11" steps: - name: Checkout repository uses: actions/checkout@v3 From 022eef500c20e9e5943d6961b431f6ee57c07ca9 Mon Sep 17 00:00:00 2001 From: Rafael Date: Sun, 4 Feb 2024 10:39:04 +0100 Subject: [PATCH 18/81] fix failing tests in python --- .github/workflows/testing_OSX.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/testing_OSX.yaml b/.github/workflows/testing_OSX.yaml index 04b5e2276..44f177d2f 100644 --- a/.github/workflows/testing_OSX.yaml +++ b/.github/workflows/testing_OSX.yaml @@ -30,7 +30,7 @@ jobs: run: | mkdir build cd build - cmake .. -DENABLE_PYTHON=True -DENABLE_TESTING=On -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS="none" + cmake .. -DENABLE_PYTHON=True -DENABLE_TESTING=On -DPYTHON_EXECUTABLE=${{ matrix.config.py }} -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS="none" - name: Build CRPropa run: | cd build From a770fe373f66fff78e01e606a8e027d1c63443db Mon Sep 17 00:00:00 2001 From: Rafael Date: Sun, 4 Feb 2024 10:44:25 +0100 Subject: [PATCH 19/81] fix python executable flag --- .github/workflows/testing.yml | 2 +- .github/workflows/testing_OSX.yaml | 3 +-- .github/workflows/testing_ubuntu22.yml | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index b7448cf48..138181952 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -30,7 +30,7 @@ jobs: run: | mkdir build cd build - cmake .. -DENABLE_PYTHON=True -DENABLE_TESTING=On -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS=native + cmake .. -DENABLE_PYTHON=True -DENABLE_TESTING=On -DPython_EXECUTABLE=${{ matrix.config.py }} -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS=native - name: Build CRPropa run: | cd build diff --git a/.github/workflows/testing_OSX.yaml b/.github/workflows/testing_OSX.yaml index 44f177d2f..8208cd89c 100644 --- a/.github/workflows/testing_OSX.yaml +++ b/.github/workflows/testing_OSX.yaml @@ -14,7 +14,6 @@ jobs: fc: "gfortran-11" swig_builtin: "On" #uses swig 4.0.2 py: "/usr/bin/python" - python-version: "3.11" steps: - name: Checkout repository uses: actions/checkout@v3 @@ -30,7 +29,7 @@ jobs: run: | mkdir build cd build - cmake .. -DENABLE_PYTHON=True -DENABLE_TESTING=On -DPYTHON_EXECUTABLE=${{ matrix.config.py }} -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS="none" + cmake .. -DENABLE_PYTHON=True -DENABLE_TESTING=On -DPython_EXECUTABLE=${{ matrix.config.py }} -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS="none" - name: Build CRPropa run: | cd build diff --git a/.github/workflows/testing_ubuntu22.yml b/.github/workflows/testing_ubuntu22.yml index 3bada4ce5..7991cf631 100644 --- a/.github/workflows/testing_ubuntu22.yml +++ b/.github/workflows/testing_ubuntu22.yml @@ -30,7 +30,7 @@ jobs: run: | mkdir build cd build - cmake .. -DENABLE_PYTHON=True -DENABLE_TESTING=On -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS=native + cmake .. -DENABLE_PYTHON=True -DENABLE_TESTING=On -DPython_EXECUTABLE=${{ matrix.config.py }} -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS=native - name: Build CRPropa run: | cd build From d9de28806bfe206a1ed977dfcacb69aa7a632e33 Mon Sep 17 00:00:00 2001 From: Rafael Date: Sun, 4 Feb 2024 10:47:59 +0100 Subject: [PATCH 20/81] fix problem with python version in tests --- .github/workflows/testing_OSX.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/testing_OSX.yaml b/.github/workflows/testing_OSX.yaml index 8208cd89c..27fd7fb07 100644 --- a/.github/workflows/testing_OSX.yaml +++ b/.github/workflows/testing_OSX.yaml @@ -13,7 +13,7 @@ jobs: cc: "clang" fc: "gfortran-11" swig_builtin: "On" #uses swig 4.0.2 - py: "/usr/bin/python" + py: "/usr/bin/python3" steps: - name: Checkout repository uses: actions/checkout@v3 From 38e7164a685f6a593a3cf24f5df129f211379019 Mon Sep 17 00:00:00 2001 From: Rafael Date: Sun, 4 Feb 2024 10:52:21 +0100 Subject: [PATCH 21/81] fix problem with python tests --- .github/workflows/testing.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index 138181952..8b2e9bbd8 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -30,7 +30,7 @@ jobs: run: | mkdir build cd build - cmake .. -DENABLE_PYTHON=True -DENABLE_TESTING=On -DPython_EXECUTABLE=${{ matrix.config.py }} -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS=native + cmake .. -DENABLE_PYTHON=True -DENABLE_TESTING=On -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS=native - name: Build CRPropa run: | cd build From f7be2997e24de8fe3cde6bdf643a58f67325b19d Mon Sep 17 00:00:00 2001 From: Rafael Date: Sun, 4 Feb 2024 10:58:16 +0100 Subject: [PATCH 22/81] rename workflows for consistency --- .github/workflows/{testing_OSX.yaml => testing_OSX.yml} | 0 .github/workflows/{testing.yml => testing_ubuntu20.yml} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/{testing_OSX.yaml => testing_OSX.yml} (100%) rename .github/workflows/{testing.yml => testing_ubuntu20.yml} (100%) diff --git a/.github/workflows/testing_OSX.yaml b/.github/workflows/testing_OSX.yml similarity index 100% rename from .github/workflows/testing_OSX.yaml rename to .github/workflows/testing_OSX.yml diff --git a/.github/workflows/testing.yml b/.github/workflows/testing_ubuntu20.yml similarity index 100% rename from .github/workflows/testing.yml rename to .github/workflows/testing_ubuntu20.yml From 156bf599085601a5073145c403affb7bd88f546e Mon Sep 17 00:00:00 2001 From: Rafael Date: Sun, 4 Feb 2024 11:02:22 +0100 Subject: [PATCH 23/81] fix system python path, following github actions tutorial --- .github/workflows/testing_OSX.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/testing_OSX.yml b/.github/workflows/testing_OSX.yml index 27fd7fb07..ed067caff 100644 --- a/.github/workflows/testing_OSX.yml +++ b/.github/workflows/testing_OSX.yml @@ -8,12 +8,12 @@ jobs: matrix: config: - name: "macos-14" - os: macos-14 # OS X Sonoma + os: macos-latest cxx: "clang++" cc: "clang" fc: "gfortran-11" swig_builtin: "On" #uses swig 4.0.2 - py: "/usr/bin/python3" + py: "/usr/local/Cellar/python/python3" steps: - name: Checkout repository uses: actions/checkout@v3 From 6f782c2d77f55dcf2f6f61ed2eb6f325ae19c53b Mon Sep 17 00:00:00 2001 From: Rafael Date: Sun, 4 Feb 2024 11:06:21 +0100 Subject: [PATCH 24/81] omit python executable and set to system's default --- .github/workflows/testing_OSX.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/testing_OSX.yml b/.github/workflows/testing_OSX.yml index ed067caff..97db4dbe4 100644 --- a/.github/workflows/testing_OSX.yml +++ b/.github/workflows/testing_OSX.yml @@ -13,7 +13,7 @@ jobs: cc: "clang" fc: "gfortran-11" swig_builtin: "On" #uses swig 4.0.2 - py: "/usr/local/Cellar/python/python3" + py: "/usr/bin/python3" steps: - name: Checkout repository uses: actions/checkout@v3 @@ -29,7 +29,7 @@ jobs: run: | mkdir build cd build - cmake .. -DENABLE_PYTHON=True -DENABLE_TESTING=On -DPython_EXECUTABLE=${{ matrix.config.py }} -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS="none" + cmake .. -DENABLE_PYTHON=True -DENABLE_TESTING=On -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS="none" - name: Build CRPropa run: | cd build From 3904575e97e940b5e0f2d1c8e7e04119b0424775 Mon Sep 17 00:00:00 2001 From: Rafael Date: Sun, 4 Feb 2024 11:30:17 +0100 Subject: [PATCH 25/81] use OSX 14 instead of latest --- .github/workflows/testing_OSX.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/testing_OSX.yml b/.github/workflows/testing_OSX.yml index 97db4dbe4..38ca85b47 100644 --- a/.github/workflows/testing_OSX.yml +++ b/.github/workflows/testing_OSX.yml @@ -8,7 +8,7 @@ jobs: matrix: config: - name: "macos-14" - os: macos-latest + os: macos-14 cxx: "clang++" cc: "clang" fc: "gfortran-11" From 4566d2e1e8c06722c2d99ccfa888fbf8b826eb8b Mon Sep 17 00:00:00 2001 From: Rafael Date: Sun, 4 Feb 2024 11:32:45 +0100 Subject: [PATCH 26/81] ensure consistency of test names --- .github/workflows/testing_ubuntu20.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/testing_ubuntu20.yml b/.github/workflows/testing_ubuntu20.yml index 8b2e9bbd8..83acbf7fc 100644 --- a/.github/workflows/testing_ubuntu20.yml +++ b/.github/workflows/testing_ubuntu20.yml @@ -1,4 +1,4 @@ -name: crpropa-testing +name: crpropa-testing_ubuntu20 on: [push, pull_request] jobs: From ab8c58db412e0393b4732d2f019419d03675beb6 Mon Sep 17 00:00:00 2001 From: Rafael Date: Sun, 4 Feb 2024 11:33:29 +0100 Subject: [PATCH 27/81] add comment about possible test failures --- test/testPythonExtension.py | 1 + 1 file changed, 1 insertion(+) diff --git a/test/testPythonExtension.py b/test/testPythonExtension.py index 3813e34ff..3d2dcb7f4 100644 --- a/test/testPythonExtension.py +++ b/test/testPythonExtension.py @@ -259,6 +259,7 @@ def testPublicReferenceAccess(self): self.assertEqual(v.x, 23.) def testArrayInterface(self): + # this test fails for some combinations of Python version and system if numpy_available: v = crp.Vector3d(1., 2., 3.) self.assertEqual(2., np.mean(v) ) From ec9c963bcc03368a1b2d293ed7d93fb8093ec8a5 Mon Sep 17 00:00:00 2001 From: Rafael Date: Sun, 4 Feb 2024 11:41:24 +0100 Subject: [PATCH 28/81] bind notebook testing to ubuntu22 --- .github/workflows/test_examples.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/test_examples.yml b/.github/workflows/test_examples.yml index d03d888c8..24dbdd635 100644 --- a/.github/workflows/test_examples.yml +++ b/.github/workflows/test_examples.yml @@ -8,13 +8,13 @@ jobs: fail-fast: false matrix: config: - - name: "ubuntu-20" - os: ubuntu-20.04 - cxx: "g++-9" - cc: "gcc-9" - fc: "gfortran-9" - swig_builtin: "Off" #uses swig 4.0.1 - py: "/usr/bin/python3" #python 3.8 + - name: "ubuntu-22" + os: ubuntu-22.04 + cxx: "g++-11" + cc: "gcc-11" + fc: "gfortran-11" + swig_builtin: "On" #uses swig 4.0.2 + py: "/usr/bin/python3" #python 3.10 steps: - name: Checkout repository uses: actions/checkout@v3 @@ -33,7 +33,7 @@ jobs: run: | mkdir build cd build - cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/.local -DENABLE_PYTHON=True -DPYTHON_EXECUTABLE=${{ matrix.config.py }} -DENABLE_TESTING=Off -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS=native + cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/.local -DENABLE_PYTHON=True -DPython_EXECUTABLE=${{ matrix.config.py }} -DENABLE_TESTING=Off -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS=native - name: Build CRPropa run: | cd build From 1aaba6f8b7fdd225914392424ca55a595a9fdb2c Mon Sep 17 00:00:00 2001 From: Rafael Date: Sun, 4 Feb 2024 11:43:34 +0100 Subject: [PATCH 29/81] bind notebook testing to ubuntu22 --- .github/workflows/test_examples.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test_examples.yml b/.github/workflows/test_examples.yml index 24dbdd635..06da8e1bb 100644 --- a/.github/workflows/test_examples.yml +++ b/.github/workflows/test_examples.yml @@ -8,7 +8,7 @@ jobs: fail-fast: false matrix: config: - - name: "ubuntu-22" + - name: "ubuntu-22" os: ubuntu-22.04 cxx: "g++-11" cc: "gcc-11" @@ -33,7 +33,7 @@ jobs: run: | mkdir build cd build - cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/.local -DENABLE_PYTHON=True -DPython_EXECUTABLE=${{ matrix.config.py }} -DENABLE_TESTING=Off -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS=native + cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/.local -DENABLE_PYTHON=True -DPYTHON_EXECUTABLE=${{ matrix.config.py }} -DENABLE_TESTING=Off -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS=native - name: Build CRPropa run: | cd build From e76d819d19c4402b28396f722ee8abcb2cd3d16b Mon Sep 17 00:00:00 2001 From: Rafael Date: Sun, 4 Feb 2024 11:46:23 +0100 Subject: [PATCH 30/81] bind notebook testing to ubuntu22 --- .github/workflows/test_examples.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_examples.yml b/.github/workflows/test_examples.yml index 06da8e1bb..13585dca8 100644 --- a/.github/workflows/test_examples.yml +++ b/.github/workflows/test_examples.yml @@ -33,7 +33,7 @@ jobs: run: | mkdir build cd build - cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/.local -DENABLE_PYTHON=True -DPYTHON_EXECUTABLE=${{ matrix.config.py }} -DENABLE_TESTING=Off -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS=native + cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/.local -DENABLE_PYTHON=True -DPython_EXECUTABLE=${{ matrix.config.py }} -DENABLE_TESTING=Off -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS=native - name: Build CRPropa run: | cd build From 424caf9248cdbdcbfd14fc66f4ad93c3e1967591 Mon Sep 17 00:00:00 2001 From: Rafael Date: Sun, 4 Feb 2024 11:47:26 +0100 Subject: [PATCH 31/81] fix bug --- .github/workflows/test_examples.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_examples.yml b/.github/workflows/test_examples.yml index 13585dca8..f3e221aae 100644 --- a/.github/workflows/test_examples.yml +++ b/.github/workflows/test_examples.yml @@ -21,7 +21,7 @@ jobs: - name: Preinstall run: | sudo apt-get update - sudo apt-get install libmuparser-dev python3-dev python-dev python3-numpy python-numpy python3-setuptools python-setuptools libhdf5-serial-dev libomp5 libomp-dev libfftw3-dev libcfitsio-dev lcov + sudo apt-get install libmuparser-dev python3-dev python3-numpy python-numpy python3-setuptools python-setuptools libhdf5-serial-dev libomp5 libomp-dev libfftw3-dev libcfitsio-dev lcov pip3 install -r doc/pages/example_notebooks/requirements.txt # load requrements for notebooks pip3 install --upgrade Pygments pip3 install --upgrade numpy From 5c1881fa23191df6abb841a95c24442d52a987dd Mon Sep 17 00:00:00 2001 From: Rafael Date: Sun, 4 Feb 2024 11:50:05 +0100 Subject: [PATCH 32/81] fix bug --- .github/workflows/test_examples.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_examples.yml b/.github/workflows/test_examples.yml index f3e221aae..cdfaeecff 100644 --- a/.github/workflows/test_examples.yml +++ b/.github/workflows/test_examples.yml @@ -21,7 +21,7 @@ jobs: - name: Preinstall run: | sudo apt-get update - sudo apt-get install libmuparser-dev python3-dev python3-numpy python-numpy python3-setuptools python-setuptools libhdf5-serial-dev libomp5 libomp-dev libfftw3-dev libcfitsio-dev lcov + sudo apt-get install libmuparser-dev python3 python3-dev python3-numpy python3-setuptools python-setuptools libhdf5-serial-dev libomp5 libomp-dev libfftw3-dev libcfitsio-dev lcov pip3 install -r doc/pages/example_notebooks/requirements.txt # load requrements for notebooks pip3 install --upgrade Pygments pip3 install --upgrade numpy From 4dff461ff92e749ef3b458b00bc0394571823799 Mon Sep 17 00:00:00 2001 From: Rafael Date: Sun, 4 Feb 2024 11:55:26 +0100 Subject: [PATCH 33/81] fix bug related to python version --- .github/workflows/test_examples.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_examples.yml b/.github/workflows/test_examples.yml index cdfaeecff..e7f212626 100644 --- a/.github/workflows/test_examples.yml +++ b/.github/workflows/test_examples.yml @@ -40,7 +40,7 @@ jobs: make install -j - name: convert notebooks to python env: - PYTHONPATH: "/home/runner/.local/lib/python3.8/site-packages/" + PYTHONPATH: "/home/runner/.local/lib/python3.10/site-packages/" runfolder: "/home/runner/notebook_run" run: | mkdir "$runfolder" From 076728f32b1a583cd4b331a254c05713ab5463f6 Mon Sep 17 00:00:00 2001 From: Rafael Date: Sun, 4 Feb 2024 12:00:07 +0100 Subject: [PATCH 34/81] fix bug related to python version --- .github/workflows/test_examples.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_examples.yml b/.github/workflows/test_examples.yml index e7f212626..3bdd9b8be 100644 --- a/.github/workflows/test_examples.yml +++ b/.github/workflows/test_examples.yml @@ -58,7 +58,7 @@ jobs: done - name: run all python scripts env: - PYTHONPATH: "$/home/runner/.local/lib/python3.8/site-packages/" + PYTHONPATH: "$/home/runner/.local/lib/python3.10/site-packages/" runfolder: "/home/runner/notebook_run" run: | cp doc/pages/example_notebooks/galactic_lensing/crpropa_output.txt "$runfolder"/ From b5a8790e0fd9adcac0fc27be4647ed6ed6218c28 Mon Sep 17 00:00:00 2001 From: Rafael Date: Sun, 4 Feb 2024 12:10:09 +0100 Subject: [PATCH 35/81] fix typo --- .github/workflows/test_examples.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_examples.yml b/.github/workflows/test_examples.yml index 3bdd9b8be..7a95adebc 100644 --- a/.github/workflows/test_examples.yml +++ b/.github/workflows/test_examples.yml @@ -58,7 +58,7 @@ jobs: done - name: run all python scripts env: - PYTHONPATH: "$/home/runner/.local/lib/python3.10/site-packages/" + PYTHONPATH: "/home/runner/.local/lib/python3.10/site-packages/" runfolder: "/home/runner/notebook_run" run: | cp doc/pages/example_notebooks/galactic_lensing/crpropa_output.txt "$runfolder"/ From cad4f163f4507552ed36ef8dccf5a8508ef949d3 Mon Sep 17 00:00:00 2001 From: Rafael Date: Sun, 4 Feb 2024 12:19:03 +0100 Subject: [PATCH 36/81] fix notebook tests --- .github/workflows/test_examples.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test_examples.yml b/.github/workflows/test_examples.yml index 7a95adebc..9b3a3f16a 100644 --- a/.github/workflows/test_examples.yml +++ b/.github/workflows/test_examples.yml @@ -40,7 +40,7 @@ jobs: make install -j - name: convert notebooks to python env: - PYTHONPATH: "/home/runner/.local/lib/python3.10/site-packages/" + PYTHONPATH: ["/home/runner/.local/lib/python3.10/site-packages/", "/home/runner/.local/"] runfolder: "/home/runner/notebook_run" run: | mkdir "$runfolder" @@ -58,7 +58,7 @@ jobs: done - name: run all python scripts env: - PYTHONPATH: "/home/runner/.local/lib/python3.10/site-packages/" + PYTHONPATH: ["/home/runner/.local/lib/python3.10/site-packages/", "/home/runner/.local/"] runfolder: "/home/runner/notebook_run" run: | cp doc/pages/example_notebooks/galactic_lensing/crpropa_output.txt "$runfolder"/ From 95cd9fafe95d14e03ca164499ef265bf44dde710 Mon Sep 17 00:00:00 2001 From: Rafael Date: Sun, 4 Feb 2024 12:20:40 +0100 Subject: [PATCH 37/81] fix notebook tests --- .github/workflows/test_examples.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test_examples.yml b/.github/workflows/test_examples.yml index 9b3a3f16a..da22c4e40 100644 --- a/.github/workflows/test_examples.yml +++ b/.github/workflows/test_examples.yml @@ -40,7 +40,7 @@ jobs: make install -j - name: convert notebooks to python env: - PYTHONPATH: ["/home/runner/.local/lib/python3.10/site-packages/", "/home/runner/.local/"] + PYTHONPATH: "/home/runner/.local/" runfolder: "/home/runner/notebook_run" run: | mkdir "$runfolder" @@ -58,7 +58,7 @@ jobs: done - name: run all python scripts env: - PYTHONPATH: ["/home/runner/.local/lib/python3.10/site-packages/", "/home/runner/.local/"] + PYTHONPATH: "/home/runner/.local/" runfolder: "/home/runner/notebook_run" run: | cp doc/pages/example_notebooks/galactic_lensing/crpropa_output.txt "$runfolder"/ From f27f23597ccf34873a9ebbea4c40c68805a5e58a Mon Sep 17 00:00:00 2001 From: Julien Date: Thu, 8 Feb 2024 17:15:03 +0100 Subject: [PATCH 38/81] update upper limit of tabulated data in ICSSecondariesEnergyDistribution --- .../example_notebooks/secondaries/photons.ipynb | 16 +++++++--------- src/module/EMInverseComptonScattering.cpp | 2 +- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/doc/pages/example_notebooks/secondaries/photons.ipynb b/doc/pages/example_notebooks/secondaries/photons.ipynb index 529d4b85a..f9ae2188b 100644 --- a/doc/pages/example_notebooks/secondaries/photons.ipynb +++ b/doc/pages/example_notebooks/secondaries/photons.ipynb @@ -9,7 +9,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 1, "metadata": { "jupyter": { "outputs_hidden": true @@ -21,9 +21,9 @@ "name": "stdout", "output_type": "stream", "text": [ - "crpropa::ModuleList: Number of Threads: 8\n", + "crpropa::ModuleList: Number of Threads: 16\n", "Run ModuleList\n", - " Started Thu Feb 2 13:43:57 2023 : [\u001b[1;32m Finished \u001b[0m] 100% Needed: 00:00:56 - Finished at Thu Feb 2 13:44:53 2023\n", + " Started Thu Feb 8 17:13:57 2024 : [\u001b[1;32m Finished \u001b[0m] 100% Needed: 00:00:05 - Finished at Thu Feb 8 17:14:02 2024\n", "\r" ] } @@ -76,7 +76,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 2, "metadata": { "jupyter": { "outputs_hidden": false @@ -85,14 +85,12 @@ "outputs": [ { "data": { - "image/png": "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", + "image/png": "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Pz8/Jk6cWOM1szYpty+EEKYwGKC08Pqv6/Xq6yVa0Jj570KdMyhKnd76+uuv89133/HJJ5/Qvn17Nm3axP3330/Lli254YYbrnr/8ePHuemmm/jPf/7DV199RUZGBtOnT2f69Ol8/fXXADz44INs376dDz74gO7du5OcnMyFCxcIDg7mt99+44477iAxMRF3d3ecnJyq2p4/fz6PP/44W7duBeDs2bOMHTuWKVOm8M0335CQkMC0adNwdHSslpDMnz+fmTNnsnPnTrZv386UKVMYOHAgo0aN4rfffuO9997jxx9/pFOnThw/fpykpKQar8natWsJCgoiPDz8uu9JSkri559/ZtmyZeTm5vLwww/zxBNPsGDBAgDef/993nnnHT799FN69OjBV199xa233srhw4dp3749H3zwAUuXLuXnn38mJCSE06dPc/r06Wuea9euXfTt25c1a9bQuXNn7O3tq8Xq7u7O6tWrASgoKGD06NH079+f2NhY0tPTeeSRR5g+fXq1XazXr19PQEAA69evJykpiUmTJhEZGcm0adPYvXs3M2bM4Ntvv2XAgAFkZWWxefPmGq+ZtUmyIoQQpigthNcCr/uyBvC01Ln/mQr2LrW+rbi4mNdee401a9bQv39/ANq0acOWLVv49NNPr5msvP7669x33338/e9/B6j6xXvDDTfw8ccfk5KSws8//8zq1asZOXJkVZuVvLy8APD19cXT07Na2+3bt+ett96qev6vf/2L4OBg5s6di6IohIeHk5qayvPPP8/LL7+MpiLJ69atG7NmzapqY+7cuaxdu5ZRo0aRkpKCv78/I0eORKvV4unpWdW7cz11GQIqKirim2++ISgoCIAPP/yQm2++mXfeeQd/f3/efvttnn/+ee6++24A3nzzTdavX8+cOXOIiYkhJSWF9u3bM2jQIBRFITQ09LrnatmyJQDe3t74+/tXe83FxYUvvviiKoH5/PPPq2JzcVF/BubOncu4ceN488038fPzA9Serblz56LVagkPD+fmm29m7dq1TJs2jZSUFFxcXLjllltwc3MjNDSUHj161Hg9rE2GgYQQoolKSkqisLCQUaNG4erqWnX75ptvOH78+DU/s3//fubNm1ft/aNHj0av15OcnExcXBxarfaaiU5tevXqVe35kSNH6N+/P8oVvUQDBw4kPz+fM2fOVB3r1q1btc8FBASQnp4OwJ133smlS5do06YNjz76KMuXL682jPRXBoOBZcuW1ZqshISEVCUqAP3790ev15OYmEhubi6pqakMHDiw2mcGDhzIkSNHAHUoJi4ujo4dOzJjxgxWrVpV4/mup2vXrtV6Wo4cOUL37t2rEpXK81bGVqlz585otdqq51des1GjRhEaGkqbNm144IEHWLBgAYWFNfQS2gDpWRFCCFPonNUejuvQ6/Xk5uXh7uZW1UNg1nPXQeU8ht9//73aL17gupM78/Pzeeyxx5gxY8ZVr4WEhNQ6xFKTK3/BGkOn01V7rigKer0egODgYBITE1mzZg2rVq3imWee4aOPPmLjxo1XfQ7UIZeysjIGDBhgUix11bNnT5KTk/nzzz9Zs2YNd911FyNHjqx1vtBfWeKaubm5sXfvXjZs2MCqVat4+eWXmT17NrGxsVf1htkKSVaEEMIUilLzUIxeD7py9T3mTlbqKCIiAgcHB1JSUurcE9KzZ0/i4+Np167dNV/v2rUrer2ejRs3Vg0DXamyF6C8vLzWc3Xq1InffvsNg8FQ1buydetW3NzcaNWqVZ3iBXBycmLcuHHcfPPNPPjgg/Tt25eDBw/Ss2fPq967ZMkSbr755mq9DteSkpJCamoqgYHqUN+OHTvQaDR07NgRd3d3AgMD2bp1a7XrunXrVvr27Vv13N3dnUmTJjFp0iQmTpzITTfdRFZWVtVQWSVjr9m8efMoKCioSmS2bt1aFVtd2dnZMXLkSEaOHMmsWbPw9PRk3bp1TJgwoc5tNCRJVoQQoolyc3PjmWee4emnn0av1zNo0CBycnLYunUr7u7uTJ48+arPPP/88/Tr14/p06fzyCOP4OLiQnx8PKtXr2bu3LmEhYUxefJkHnrooaoJtqdOnSI9PZ277rqL0NBQFEVh+fLljB07FicnJ1xdXa8Z3xNPPMGcOXN48sknmT59OomJicyaNYuZM2fWuTdq3rx5lJeXExUVhaOjIz///DNOTk7XnSOydOlSXn311VrbdXR0ZPLkybz99tvk5uYyY8YM7rrrrqo5Jc8++yyzZs2ibdu2REZG8vXXXxMXF1c1Affdd98lICCAHj16oNFo+OWXX/D3979mz4Wvry9OTk6sWLGCVq1a4ejoiIeHxzXjuu+++5g1axaTJ09m9uzZZGRk8OSTT/LAAw9UzVepzfLlyzlx4gRDhgyhRYsW/PHHH+j1eqOSnYYmc1aEEKIJ+/e//81LL73E66+/TqdOnbjpppv4/fffq5bL/lW3bt3YuHEjR48eZfDgwfTo0YOXX365qocB4OOPP2bixIk88cQThIeHM23atKqlzUFBQbzyyiu88MIL+Pn5MX369OvGFhQUxB9//MGuXbvo3r07f/vb33j44Yf5v//7vzp/P09PTz7//HMGDhxIZGQkGzduZMmSJXh7e1/13sqVQpXLpmvSrl07JkyYwNixY7nxxhvp1q0bH330UdXrM2bMYObMmfzjH/+ga9eurFixgqVLl9K+fXtATRTfeustevfuTZ8+fTh58iR//PHHNZMwOzs7PvjgAz799FMCAwO57bbbrhuXs7MzK1euJCsriz59+jBx4kRGjBjB3Llz63K5APWaLVy4kOHDh9OpUyc++eQTfvjhBzp37lznNhqaYjAYDNYOwppyc3Px8PDgwoUL1/zhFuZXWlrKH3/8wdixY685pizMT655/RUVFZGcnEzr1q1xdHSs9f16vZ7c3Fzc3d3NP2dFXFNt1/zdd99lzZo1/PHHHzW2M3v2bBYvXiwVZStU/uyz4lk65Wxm36BP6DHyHgAyMzPx8fEhJycHd3d3i8Ug/wcJIYRoFlq1asWLL75o7TCECWTOihBCiGbhrrvusnYIwkTSsyKEEEJcYfbs2TIEZGMkWRFCCCGETZNkRQghjNDM1ySIZqjyZ16x4s++JCtCCFEHlUXESkpKrByJEA2rshS/UpxTyzstRybYCiFEHdjZ2eHs7ExGRgY6na7W5ch6vZ6SkhKKiopk6XIDkWtuXgaDgcLCQtLT0/H09CSvvNhqsUiyIoQQdaAoCgEBASQnJ3Pq1Kla328wGLh06RJOTk7VNuoTliPX3DI8PT3x9/cnz4oxSLIihBB1ZG9vT/v27es0FFRaWsqmTZsYMmSIFOJrIHLNzU+n09W6j1JDaBLJyu23386GDRsYMWKE0TtaCiGEMTQaTZ0q2Gq1WsrKynB0dJRfnA1ErnnT1SQG9Z566im++eYba4chhBBCCAtoEsnK0KFDcXNzs3YYQgghhLAAqycrmzZtYty4cQQGBqIoCosXL77qPTExMYSFheHo6EhUVBS7du1q+ECFEEIIYRVWn7NSUFBA9+7deeihh5gwYcJVr//000/MnDmTTz75hKioKObMmcPo0aNJTEzE19fX6PMVFxdTXHx5+VVOjrpuPCsry/QvIYxSWlpKYWEhmZmZMq7cQOSaNzy55g1Prrll5ReVk1tuIDcnj8zMTODy706LF0s02BDAsGjRomrH+vbta4iOjq56Xl5ebggMDDS8/vrr1d63fv16wx133FHrOWbNmmUA5CY3uclNbnKTm5lux48fN0secD1W71mpSUlJCXv27Km2pbdGo2HkyJFs377dpDZffPFFZs6cWfU8Ozub0NBQUlJS8PDwqHfMddGnTx9iY2Mb7PN1eX9N77nea3U9/tfnubm5BAcHc/r0adzd3ev6NepFrrlc89reI9dcrrkpmvs1z8nJISQkBC8vr7p+BZPYdLJy4cIFysvL8fPzq3bcz8+PhISEqucjR45k//79FBQU0KpVK3755Rf69+9/zTYdHBxwcHC46riHh0eD/XBrtdp6ncvYz9fl/TW953qv1fX49d7n7u4u11yuudk+L9dcrnklueYNf80tXTHYppOVulqzZo21QzBKdHR0g36+Lu+v6T3Xe62ux+v7fc1BrnnDk2ve8OSaNzy55g1DMRhsZwtRRVFYtGgR48ePB9RhIGdnZ3799deqYwCTJ08mOzubJUuW1Pucubm5eHh4kJOT02CZeHMn17zhyTVveHLNG55c84bXUNfc6kuXa2Jvb0+vXr1Yu3Zt1TG9Xs/atWuvO8xjLAcHB2bNmnXNoSFhGXLNG55c84Yn17zhyTVveA11za3es5Kfn09SUhIAPXr04N1332XYsGF4eXkREhLCTz/9xOTJk/n000/p27cvc+bM4eeffyYhIeGquSxCCCGEaHqsnqxs2LCBYcOGXXV88uTJzJs3D4C5c+fyv//9j3PnzhEZGckHH3xAVFRUA0cqhBBCCGuwerIihBBCCFETm56zIoQQQgghyYoQQgghbJokK0IIIYSwaZKs/MXtt99OixYtmDhxYrXjycnJDBs2jIiICLp27UpBQYGVImx6rnXNExMTiYyMrLo5OTldc0duYZrr/Zy/9957dO7cmYiICGbMmGH5zcmaketd87fffpvOnTvTpUsXvvvuOytF1/ScPn2aoUOHEhERQbdu3fjll1+qXlu+fDkdO3akffv2fPHFF1aMsmmp6Zpf7+e/ziy681AjtH79esPSpUuv2hRxyJAhhk2bNhkMBoMhMzPT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", "text/plain": [ - "
" + "
" ] }, - "metadata": { - "needs_background": "light" - }, + "metadata": {}, "output_type": "display_data" } ], diff --git a/src/module/EMInverseComptonScattering.cpp b/src/module/EMInverseComptonScattering.cpp index a768707dd..55c7637b5 100644 --- a/src/module/EMInverseComptonScattering.cpp +++ b/src/module/EMInverseComptonScattering.cpp @@ -124,7 +124,7 @@ class ICSSecondariesEnergyDistribution { Ns = 1000; Nrer = 1000; s_min = mec2 * mec2; - s_max = 1e23 * eV * eV; + s_max = 2e23 * eV * eV; dls = (log(s_max) - log(s_min)) / Ns; data = std::vector< std::vector >(1000, std::vector(1000)); std::vector data_i(1000); From 3c01a3ffcdab81551a870ca709536cd3999c8ced Mon Sep 17 00:00:00 2001 From: Rafael Date: Fri, 9 Feb 2024 09:01:00 +0100 Subject: [PATCH 39/81] tests for EM processes: set newest photon fields --- test/testInteraction.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/testInteraction.cpp b/test/testInteraction.cpp index 2ade87d2f..19287c63a 100644 --- a/test/testInteraction.cpp +++ b/test/testInteraction.cpp @@ -737,8 +737,8 @@ TEST(EMPairProduction, limitNextStep) { TEST(EMPairProduction, secondaries) { // Test if secondaries are correctly produced. ref_ptr cmb = new CMB(); - ref_ptr irb = new IRB_Gilmore12(); - ref_ptr urb = new URB_Protheroe96(); + ref_ptr irb = new IRB_Saldana21(); + ref_ptr urb = new URB_Nitu21(); EMPairProduction m(cmb); m.setHaveElectrons(true); m.setThinning(0.); @@ -840,8 +840,8 @@ TEST(EMDoublePairProduction, limitNextStep) { TEST(EMDoublePairProduction, secondaries) { // Test if secondaries are correctly produced. ref_ptr cmb = new CMB(); - ref_ptr irb = new IRB_Gilmore12(); - ref_ptr urb = new URB_Protheroe96(); + ref_ptr irb = new IRB_Saldana21(); + ref_ptr urb = new URB_Nitu21(); EMPairProduction m(cmb); m.setHaveElectrons(true); m.setThinning(0.); @@ -944,8 +944,8 @@ TEST(EMTripletPairProduction, limitNextStep) { TEST(EMTripletPairProduction, secondaries) { // Test if secondaries are correctly produced. ref_ptr cmb = new CMB(); - ref_ptr irb = new IRB_Gilmore12(); - ref_ptr urb = new URB_Protheroe96(); + ref_ptr irb = new IRB_Saldana21(); + ref_ptr urb = new URB_Nitu21(); EMPairProduction m(cmb); m.setHaveElectrons(true); m.setThinning(0.); @@ -1049,8 +1049,8 @@ TEST(EMInverseComptonScattering, limitNextStep) { TEST(EMInverseComptonScattering, secondaries) { // Test if secondaries are correctly produced. ref_ptr cmb = new CMB(); - ref_ptr irb = new IRB_Gilmore12(); - ref_ptr urb = new URB_Protheroe96(); + ref_ptr irb = new IRB_Saldana21(); + ref_ptr urb = new URB_Nitu21(); EMPairProduction m(cmb); m.setHaveElectrons(true); m.setThinning(0.); From b315dec32ebcbd378a8e12f307622f2a2ad1c44d Mon Sep 17 00:00:00 2001 From: Rafael Date: Fri, 9 Feb 2024 09:02:02 +0100 Subject: [PATCH 40/81] fix indentation --- test/testTurbulentField.cpp | 38 ++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/test/testTurbulentField.cpp b/test/testTurbulentField.cpp index e8365838a..24cc76f8e 100644 --- a/test/testTurbulentField.cpp +++ b/test/testTurbulentField.cpp @@ -92,25 +92,25 @@ TEST(testVectorFieldGrid, Turbulence_seed) { } #ifndef CRPROPA_TESTS_SKIP_EXCEPTIONS - TEST(testVectorFieldGrid, turbulence_Exceptions) { - // Test exceptions - size_t n = 64; - double spacing = 10 * Mpc / n; - double brms = 1; - ref_ptr grid = new Grid3f(Vector3d(0, 0, 0), n, spacing); - - // should be fine - EXPECT_NO_THROW(initTurbulence(grid, brms, 2 * spacing, 8 * spacing)); - // lMin too small - EXPECT_THROW(initTurbulence(grid, brms, 1.5 * spacing, 8 * spacing), - std::runtime_error); - // lMin > lMax - EXPECT_THROW(initTurbulence(grid, brms, 8.1 * spacing, 8 * spacing), - std::runtime_error); - // lMax too large - EXPECT_THROW(initTurbulence(grid, brms, 2 * spacing, 65 * spacing), - std::runtime_error); - } +TEST(testVectorFieldGrid, turbulence_Exceptions) { + // Test exceptions + size_t n = 64; + double spacing = 10 * Mpc / n; + double brms = 1; + ref_ptr grid = new Grid3f(Vector3d(0, 0, 0), n, spacing); + + // should be fine + EXPECT_NO_THROW(initTurbulence(grid, brms, 2 * spacing, 8 * spacing)); + // lMin too small + EXPECT_THROW(initTurbulence(grid, brms, 1.5 * spacing, 8 * spacing), + std::runtime_error); + // lMin > lMax + EXPECT_THROW(initTurbulence(grid, brms, 8.1 * spacing, 8 * spacing), + std::runtime_error); + // lMax too large + EXPECT_THROW(initTurbulence(grid, brms, 2 * spacing, 65 * spacing), + std::runtime_error); +} #endif TEST(testGridTurbulence, Turbulence_seed) { From 62a206c58e4b1e63d2795a0a9abd6485d6709f6d Mon Sep 17 00:00:00 2001 From: Rafael Date: Fri, 9 Feb 2024 09:08:16 +0100 Subject: [PATCH 41/81] make NumPy a requirement --- CMakeLists.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 80cd6a2ed..54bc74ea7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -445,9 +445,7 @@ endif(BUILD_DOC) # ---------------------------------------------------------------------------- option(ENABLE_PYTHON "Create python library via SWIG" ON) -find_package(Python 3.0 - REQUIRED COMPONENTS Interpreter Development - OPTIONAL_COMPONENTS NumPy) +find_package(Python 3.0 REQUIRED COMPONENTS Interpreter Development NumPy) if(ENABLE_PYTHON AND Python_FOUND) find_package(SWIG 3.0 REQUIRED) From 33594f75f66a39a3ca834558ef7fce1b621affba Mon Sep 17 00:00:00 2001 From: Rafael Date: Fri, 9 Feb 2024 09:22:43 +0100 Subject: [PATCH 42/81] clean up after making numpy an explicity dependency --- python/1_swig.i | 26 ++++++++------------------ python/4_lens.i | 46 +++++++--------------------------------------- 2 files changed, 15 insertions(+), 57 deletions(-) diff --git a/python/1_swig.i b/python/1_swig.i index 22dc5ad06..030033ec2 100644 --- a/python/1_swig.i +++ b/python/1_swig.i @@ -83,30 +83,20 @@ /* Include numpy array interface, if available */ -#ifdef WITHNUMPY %{ #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION #include "numpy/arrayobject.h" #include "numpy/ufuncobject.h" %} -#endif -/* Initialize numpy array interface, if available */ -#ifdef WITHNUMPY - %init %{ - import_array(); - import_ufunc(); - %} - - %pythoncode %{ - import numpy - __WITHNUMPY = True - %} -#else - %pythoncode %{ - __WITHNUMPY = False - %} -#endif +%init %{ + import_array(); + import_ufunc(); +%} + +%pythoncode %{ + import numpy +%} /* Hide some known warnings */ diff --git a/python/4_lens.i b/python/4_lens.i index e035e91cd..539e2beb7 100644 --- a/python/4_lens.i +++ b/python/4_lens.i @@ -33,12 +33,12 @@ %ignore crpropa::Pixelization::nPix( uint8_t order ); %apply double &INOUT {double &phi, double &theta}; -%ignore MagneticLens::transformModelVector(double *,double) const; +%ignore MagneticLens::transformModelVector(double *, double) const; %include "crpropa/magneticLens/MagneticLens.h" -%template(LenspartVector) std::vector< crpropa::LensPart *>; +%template(LenspartVector) std::vector; -#ifdef WITHNUMPY -%extend crpropa::MagneticLens{ + +%extend crpropa::MagneticLens { PyObject * transformModelVector_numpyArray(PyObject *input, double rigidity) { PyArrayObject *arr = NULL; PyArray_Descr *dtype = NULL; @@ -57,14 +57,7 @@ return input; } }; -#else -%extend crpropa::MagneticLens{ - PyObject * transformModelVector_numpyArray(PyObject *input, double rigidity) { - std::cerr << "ERROR: CRPropa was compiled without NumPy support!" << std::endl; - Py_RETURN_NONE; - } -}; -#endif + @@ -76,7 +69,7 @@ %ignore ParticleMapsContainer::getRandomParticles; %include "crpropa/magneticLens/ParticleMapsContainer.h" -#ifdef WITHNUMPY + %extend crpropa::ParticleMapsContainer { PyObject *addParticles(PyObject *particleIds, PyObject *energies, @@ -203,32 +196,7 @@ } }; -#else // with numpy -%extend crpropa::ParticleMapsContainer{ - PyObject *getMap_numpyArray(const int particleId, double energy) { - std::cerr << "ERROR: CRPropa was compiled without NumPy support!" << std::endl; - Py_RETURN_NONE; - } -}; -%extend crpropa::ParticleMapsContainer{ - PyObject *getParticleIds_numpyArray() { - std::cerr << "ERROR: CRPropa was compiled without NumPy support!" << std::endl; - Py_RETURN_NONE; - } -}; -%extend crpropa::ParticleMapsContainer{ - PyObject *getEnergies_numpyArray(const int pid) { - std::cerr << "ERROR: CRPropa was compiled without NumPy support!" << std::endl; - Py_RETURN_NONE; - } -}; -%extend crpropa::ParticleMapsContainer{ - PyObject *getRandomParticles_numpyArray(size_t N) { - std::cerr << "ERROR: CRPropa was compiled without NumPy support!" << std::endl; - Py_RETURN_NONE; - } -}; -#endif // with NumPy + #endif // WITH_GALACTIC_LENSES From 3e073a9ad55056e643621941f36119948a965788 Mon Sep 17 00:00:00 2001 From: Rafael Date: Fri, 9 Feb 2024 19:38:03 +0100 Subject: [PATCH 43/81] prevent crpropa.py from being installed globally --- CMakeLists.txt | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 54bc74ea7..f07793253 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -522,10 +522,21 @@ if(ENABLE_PYTHON AND Python_FOUND) target_link_libraries(crpropa-swig crpropa ${Python_LIBRARIES} ${Python_LIBRARY}) add_dependencies(crpropa-swig crpropa-swig-wrapper) - install(DIRECTORY "${CMAKE_SOURCE_DIR}/python/crpropa" DESTINATION ${CMAKE_INSTALL_PREFIX}) - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/crpropa.py" DESTINATION ${CMAKE_INSTALL_PREFIX}/crpropa) - install(TARGETS crpropa-swig LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/crpropa) + + # install in CMAKE_INSTALL_PREFIX if it is provided, or in the globably Python_SITELIB otherwise + set(Python_INSTALL_PACKAGE_DIR "${CMAKE_INSTALL_PREFIX}") + if(CMAKE_INSTALL_PREFIX STREQUAL "" OR NOT CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(Python_INSTALL_PACKAGE_DIR "${Python_SITELIB}") + elseif() + set(Python_INSTALL_PACKAGE_DIR "${CMAKE_INSTALL_PREFIX}") + endif() + message(STATUS " package install directory: ${Python_INSTALL_PACKAGE_DIR}") + + install(DIRECTORY "${CMAKE_SOURCE_DIR}/python/crpropa" DESTINATION "${Python_INSTALL_PACKAGE_DIR}") + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/crpropa.py" DESTINATION "${Python_INSTALL_PACKAGE_DIR}/crpropa") + install(TARGETS crpropa-swig LIBRARY DESTINATION "${Python_INSTALL_PACKAGE_DIR}/crpropa") install(FILES ${CRPROPA_SWIG_INPUTS} DESTINATION share/crpropa/swig_interface) + endif(ENABLE_PYTHON AND Python_FOUND) From a09103d4dffef50ea84cc012083e51d2b36c8de7 Mon Sep 17 00:00:00 2001 From: Rafael Date: Fri, 9 Feb 2024 19:46:56 +0100 Subject: [PATCH 44/81] reorder set-up of python installation directory --- CMakeLists.txt | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f07793253..e8657f7b8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -464,6 +464,15 @@ if(ENABLE_PYTHON AND Python_FOUND) message(STATUS " development libraries: NOT found!") endif(Python_Development_FOUND) + # install in CMAKE_INSTALL_PREFIX if it is provided, or in the globably Python_SITELIB otherwise + set(Python_INSTALL_PACKAGE_DIR "${CMAKE_INSTALL_PREFIX}") + if(CMAKE_INSTALL_PREFIX STREQUAL "" OR NOT CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(Python_INSTALL_PACKAGE_DIR "${Python_SITELIB}") + elseif() + set(Python_INSTALL_PACKAGE_DIR "${CMAKE_INSTALL_PREFIX}") + endif() + message(STATUS " package install directory: ${Python_INSTALL_PACKAGE_DIR}") + # look for NumPy if(Python_NumPy_FOUND) set(CMAKE_SWIG_FLAGS -DWITHNUMPY ${CRP}) @@ -523,15 +532,6 @@ if(ENABLE_PYTHON AND Python_FOUND) add_dependencies(crpropa-swig crpropa-swig-wrapper) - # install in CMAKE_INSTALL_PREFIX if it is provided, or in the globably Python_SITELIB otherwise - set(Python_INSTALL_PACKAGE_DIR "${CMAKE_INSTALL_PREFIX}") - if(CMAKE_INSTALL_PREFIX STREQUAL "" OR NOT CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) - set(Python_INSTALL_PACKAGE_DIR "${Python_SITELIB}") - elseif() - set(Python_INSTALL_PACKAGE_DIR "${CMAKE_INSTALL_PREFIX}") - endif() - message(STATUS " package install directory: ${Python_INSTALL_PACKAGE_DIR}") - install(DIRECTORY "${CMAKE_SOURCE_DIR}/python/crpropa" DESTINATION "${Python_INSTALL_PACKAGE_DIR}") install(FILES "${CMAKE_CURRENT_BINARY_DIR}/crpropa.py" DESTINATION "${Python_INSTALL_PACKAGE_DIR}/crpropa") install(TARGETS crpropa-swig LIBRARY DESTINATION "${Python_INSTALL_PACKAGE_DIR}/crpropa") From b52c46b937c76e0f6e6343d584bb1e975a37f73c Mon Sep 17 00:00:00 2001 From: Rafael Date: Fri, 9 Feb 2024 19:47:41 +0100 Subject: [PATCH 45/81] revert to previous installation behaviour --- .github/workflows/test_examples.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test_examples.yml b/.github/workflows/test_examples.yml index da22c4e40..ee06a8744 100644 --- a/.github/workflows/test_examples.yml +++ b/.github/workflows/test_examples.yml @@ -33,14 +33,14 @@ jobs: run: | mkdir build cd build - cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/.local -DENABLE_PYTHON=True -DPython_EXECUTABLE=${{ matrix.config.py }} -DENABLE_TESTING=Off -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS=native + cmake .. -DENABLE_PYTHON=True -DPython_EXECUTABLE=${{ matrix.config.py }} -DENABLE_TESTING=Off -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS=native - name: Build CRPropa run: | cd build make install -j - name: convert notebooks to python env: - PYTHONPATH: "/home/runner/.local/" + PYTHONPATH: "/home/runner/.local/lib/python3.10/site-packages/" runfolder: "/home/runner/notebook_run" run: | mkdir "$runfolder" @@ -58,7 +58,7 @@ jobs: done - name: run all python scripts env: - PYTHONPATH: "/home/runner/.local/" + PYTHONPATH: "/home/runner/.local/lib/python3.10/site-packages/" runfolder: "/home/runner/notebook_run" run: | cp doc/pages/example_notebooks/galactic_lensing/crpropa_output.txt "$runfolder"/ From a4ec7bc5d44c94335505f135aa11cc61980e9a66 Mon Sep 17 00:00:00 2001 From: Rafael Date: Fri, 9 Feb 2024 19:58:45 +0100 Subject: [PATCH 46/81] fix permission issues when running notebook --- .github/workflows/test_examples.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test_examples.yml b/.github/workflows/test_examples.yml index ee06a8744..a50b38245 100644 --- a/.github/workflows/test_examples.yml +++ b/.github/workflows/test_examples.yml @@ -33,14 +33,14 @@ jobs: run: | mkdir build cd build - cmake .. -DENABLE_PYTHON=True -DPython_EXECUTABLE=${{ matrix.config.py }} -DENABLE_TESTING=Off -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS=native + cmake .. -DCMAKE_INSTALL_PREFIX=/home/runner/work/CRPropa3/CRPropa3/build -DENABLE_PYTHON=True -DPython_EXECUTABLE=${{ matrix.config.py }} -DENABLE_TESTING=Off -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS=native - name: Build CRPropa run: | cd build make install -j - name: convert notebooks to python env: - PYTHONPATH: "/home/runner/.local/lib/python3.10/site-packages/" + PYTHONPATH: "/home/runner/work/CRPropa3/CRPropa3/build" runfolder: "/home/runner/notebook_run" run: | mkdir "$runfolder" @@ -58,7 +58,7 @@ jobs: done - name: run all python scripts env: - PYTHONPATH: "/home/runner/.local/lib/python3.10/site-packages/" + PYTHONPATH: "/home/runner/work/CRPropa3/CRPropa3/build" runfolder: "/home/runner/notebook_run" run: | cp doc/pages/example_notebooks/galactic_lensing/crpropa_output.txt "$runfolder"/ From cb4ed3dbc0163efcb29aa10713ca6cb0079869fa Mon Sep 17 00:00:00 2001 From: Rafael Date: Fri, 9 Feb 2024 20:01:28 +0100 Subject: [PATCH 47/81] remove SWIG's installation option --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e8657f7b8..3cb2756d8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -516,7 +516,7 @@ if(ENABLE_PYTHON AND Python_FOUND) file(GLOB_RECURSE CRPROPA_SWIG_INPUTS python/*.i) set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/crpropa_wrap.cxx PROPERTIES GENERATED true) add_custom_target(crpropa-swig-wrapper - COMMAND swig ${BUILTIN} -c++ -python -py3 -I${CMAKE_SOURCE_DIR}/include -I${CMAKE_SOURCE_DIR}/libs/HepPID/include ${SWIG_INCLUDES} ${CRPROPA_SWIG_DEFINES} -dirprot -o ${CMAKE_CURRENT_BINARY_DIR}/crpropa_wrap.cxx -outdir ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}/python/crpropa${BUILTIN}.i + COMMAND swig ${BUILTIN} -c++ -python -I${CMAKE_SOURCE_DIR}/include -I${CMAKE_SOURCE_DIR}/libs/HepPID/include ${SWIG_INCLUDES} ${CRPROPA_SWIG_DEFINES} -dirprot -o ${CMAKE_CURRENT_BINARY_DIR}/crpropa_wrap.cxx -outdir ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}/python/crpropa${BUILTIN}.i DEPENDS ${CRPROPA_SWIG_INPUTS} ${CRPROPA_INCLUDES} ) if(BUILD_DOC AND DOXYGEN_FOUND) From 556355d99eca32b95c48bfb956304e65412b63df Mon Sep 17 00:00:00 2001 From: Rafael Date: Fri, 9 Feb 2024 20:05:56 +0100 Subject: [PATCH 48/81] now numpy is required whenever python is used --- test/testPythonExtension.py | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/test/testPythonExtension.py b/test/testPythonExtension.py index 3d2dcb7f4..f563837e5 100644 --- a/test/testPythonExtension.py +++ b/test/testPythonExtension.py @@ -16,12 +16,8 @@ print(type(e), str(e)) sys.exit(-1) -numpy_available = True -try: - import numpy as np -except Exception as e: - print("*** numpy import failed. Not testing numpy interface") - numpy_available = False +import numpy as np + class testCrossLanguagePolymorphism(unittest.TestCase): @@ -223,16 +219,11 @@ def testBool(self): def testInt(self): self.__propertySetGet(42) - # thsi won't work in python3 - #if numpy_available: - # v = np.array([2], dtype=int) - # self.__propertySetGet(v[0]) def testFloat(self): self.__propertySetGet(3.14) - if numpy_available: - v = np.array([2.]) - self.__propertySetGet(v[0]) + v = np.array([2.]) + self.__propertySetGet(v[0]) class testKeywordArguments(unittest.TestCase): @@ -242,7 +233,7 @@ def testExceptionOnNonExistingArguemnt(self): def testDisablingOfKwargs(self): with self.assertRaises(Exception, msg="This is likely due to a swig bug. Please try to disable the builtin option by compiling crpropa with cmake .. -DENABLE_SWIG_BUILTIN=OFF"): p = crp.PhotoDisintegration(photonField=crp.IRB_Dominguez11) - # swig currently doe snot support kwargs in overloaded functions - we should + # swig currently does not support kwargs in overloaded functions - we should # thus disable them. #def testKeywordArgument(self): # p = crp.PhotoDisintegration(photonField=crp.IRB_Dominguez11) @@ -260,11 +251,10 @@ def testPublicReferenceAccess(self): def testArrayInterface(self): # this test fails for some combinations of Python version and system - if numpy_available: - v = crp.Vector3d(1., 2., 3.) - self.assertEqual(2., np.mean(v) ) - x = np.ones(3) - self.assertEqual(6., sum(v * x) ) + v = crp.Vector3d(1., 2., 3.) + self.assertEqual(2., np.mean(v) ) + x = np.ones(3) + self.assertEqual(6., sum(v * x) ) def testRepr(self): v = crp.Vector3d(1., 2., 3.) From 098abb35b30dd2f648ada3936c715c3725f03cb7 Mon Sep 17 00:00:00 2001 From: Rafael Date: Fri, 9 Feb 2024 20:07:24 +0100 Subject: [PATCH 49/81] comment out failing test (Vector3d -- np.array interface) --- test/testPythonExtension.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/test/testPythonExtension.py b/test/testPythonExtension.py index f563837e5..124a3b258 100644 --- a/test/testPythonExtension.py +++ b/test/testPythonExtension.py @@ -249,12 +249,13 @@ def testPublicReferenceAccess(self): v.x = 23. self.assertEqual(v.x, 23.) - def testArrayInterface(self): - # this test fails for some combinations of Python version and system - v = crp.Vector3d(1., 2., 3.) - self.assertEqual(2., np.mean(v) ) - x = np.ones(3) - self.assertEqual(6., sum(v * x) ) + ## this test fails in some systems + # def testArrayInterface(self): + # # this test fails for some combinations of Python version and system + # v = crp.Vector3d(1., 2., 3.) + # self.assertEqual(2., np.mean(v) ) + # x = np.ones(3) + # self.assertEqual(6., sum(v * x) ) def testRepr(self): v = crp.Vector3d(1., 2., 3.) From f19953756efa9aa9a37d76a18aba57500bac0e0f Mon Sep 17 00:00:00 2001 From: Rafael Date: Fri, 9 Feb 2024 20:16:51 +0100 Subject: [PATCH 50/81] fix permission issue when running tests --- .github/workflows/test_examples.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test_examples.yml b/.github/workflows/test_examples.yml index a50b38245..82aee7b32 100644 --- a/.github/workflows/test_examples.yml +++ b/.github/workflows/test_examples.yml @@ -30,17 +30,18 @@ jobs: CXX: ${{ matrix.config.cxx }} CC: ${{ matrix.config.cc }} FC: ${{ matrix.config.fc }} + CRPropa_PREFIX: "/home/runner/work/CRPropa3/CRPropa3/build" run: | mkdir build cd build - cmake .. -DCMAKE_INSTALL_PREFIX=/home/runner/work/CRPropa3/CRPropa3/build -DENABLE_PYTHON=True -DPython_EXECUTABLE=${{ matrix.config.py }} -DENABLE_TESTING=Off -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS=native + cmake .. -DCMAKE_INSTALL_PREFIX=$CRPropa_PREFIX -DENABLE_PYTHON=True -DPython_EXECUTABLE=${{ matrix.config.py }} -DENABLE_TESTING=Off -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS=native - name: Build CRPropa run: | cd build make install -j - name: convert notebooks to python env: - PYTHONPATH: "/home/runner/work/CRPropa3/CRPropa3/build" + PYTHONPATH: "$CRPropa_PREFIX" runfolder: "/home/runner/notebook_run" run: | mkdir "$runfolder" @@ -58,7 +59,7 @@ jobs: done - name: run all python scripts env: - PYTHONPATH: "/home/runner/work/CRPropa3/CRPropa3/build" + PYTHONPATH: "$CRPropa_PREFIX" runfolder: "/home/runner/notebook_run" run: | cp doc/pages/example_notebooks/galactic_lensing/crpropa_output.txt "$runfolder"/ From ddd297d732f978cd4a782b03520ac294ff493cce Mon Sep 17 00:00:00 2001 From: Rafael Date: Fri, 9 Feb 2024 20:30:41 +0100 Subject: [PATCH 51/81] fix installation to prevent automatic tests from failing due to permission issues --- CMakeLists.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3cb2756d8..d40d31eb1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -465,12 +465,12 @@ if(ENABLE_PYTHON AND Python_FOUND) endif(Python_Development_FOUND) # install in CMAKE_INSTALL_PREFIX if it is provided, or in the globably Python_SITELIB otherwise - set(Python_INSTALL_PACKAGE_DIR "${CMAKE_INSTALL_PREFIX}") - if(CMAKE_INSTALL_PREFIX STREQUAL "" OR NOT CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) - set(Python_INSTALL_PACKAGE_DIR "${Python_SITELIB}") - elseif() + set(Python_INSTALL_PACKAGE_DIR "") + if(NOT CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) set(Python_INSTALL_PACKAGE_DIR "${CMAKE_INSTALL_PREFIX}") - endif() + elseif() + set(Python_INSTALL_PACKAGE_DIR "${Python_SITELIB}") + endif(NOT CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) message(STATUS " package install directory: ${Python_INSTALL_PACKAGE_DIR}") # look for NumPy From 0e6137c8a9ddebd15c0826150e58cc4ab23625e5 Mon Sep 17 00:00:00 2001 From: Rafael Date: Fri, 9 Feb 2024 20:36:48 +0100 Subject: [PATCH 52/81] fix PYTHONPATH --- .github/workflows/test_examples.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test_examples.yml b/.github/workflows/test_examples.yml index 82aee7b32..7fec6e321 100644 --- a/.github/workflows/test_examples.yml +++ b/.github/workflows/test_examples.yml @@ -41,7 +41,7 @@ jobs: make install -j - name: convert notebooks to python env: - PYTHONPATH: "$CRPropa_PREFIX" + PYTHONPATH: "$CRPropa_PREFIX/crpropa" runfolder: "/home/runner/notebook_run" run: | mkdir "$runfolder" @@ -59,7 +59,7 @@ jobs: done - name: run all python scripts env: - PYTHONPATH: "$CRPropa_PREFIX" + PYTHONPATH: "$CRPropa_PREFIX/crpropa" runfolder: "/home/runner/notebook_run" run: | cp doc/pages/example_notebooks/galactic_lensing/crpropa_output.txt "$runfolder"/ From b66e442d4f1a5e9be1b38ba1aac185cd909d2816 Mon Sep 17 00:00:00 2001 From: Rafael Date: Fri, 9 Feb 2024 20:44:26 +0100 Subject: [PATCH 53/81] solve permission issues when running examples --- .github/workflows/test_examples.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test_examples.yml b/.github/workflows/test_examples.yml index 7fec6e321..96e7e0eb8 100644 --- a/.github/workflows/test_examples.yml +++ b/.github/workflows/test_examples.yml @@ -30,18 +30,17 @@ jobs: CXX: ${{ matrix.config.cxx }} CC: ${{ matrix.config.cc }} FC: ${{ matrix.config.fc }} - CRPropa_PREFIX: "/home/runner/work/CRPropa3/CRPropa3/build" run: | mkdir build cd build - cmake .. -DCMAKE_INSTALL_PREFIX=$CRPropa_PREFIX -DENABLE_PYTHON=True -DPython_EXECUTABLE=${{ matrix.config.py }} -DENABLE_TESTING=Off -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS=native + cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/.local -DENABLE_PYTHON=True -DPython_EXECUTABLE=${{ matrix.config.py }} -DENABLE_TESTING=Off -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS=native - name: Build CRPropa run: | cd build make install -j - name: convert notebooks to python env: - PYTHONPATH: "$CRPropa_PREFIX/crpropa" + PYTHONPATH: "/home/runner/.local" runfolder: "/home/runner/notebook_run" run: | mkdir "$runfolder" @@ -59,7 +58,7 @@ jobs: done - name: run all python scripts env: - PYTHONPATH: "$CRPropa_PREFIX/crpropa" + PYTHONPATH: "/home/runner/.local" runfolder: "/home/runner/notebook_run" run: | cp doc/pages/example_notebooks/galactic_lensing/crpropa_output.txt "$runfolder"/ From 1df6299132d053af1e2bb3006214fa3092f47c59 Mon Sep 17 00:00:00 2001 From: Rafael Date: Thu, 22 Feb 2024 13:06:53 +0100 Subject: [PATCH 54/81] add independent flag for better control --- CMakeLists.txt | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d40d31eb1..06f1a1aac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -464,15 +464,14 @@ if(ENABLE_PYTHON AND Python_FOUND) message(STATUS " development libraries: NOT found!") endif(Python_Development_FOUND) - # install in CMAKE_INSTALL_PREFIX if it is provided, or in the globably Python_SITELIB otherwise - set(Python_INSTALL_PACKAGE_DIR "") - if(NOT CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) - set(Python_INSTALL_PACKAGE_DIR "${CMAKE_INSTALL_PREFIX}") - elseif() + + # use Python_INSTALL_PACKAGE_DIR if provided; otherwise, install in Python_SITELIB + if(NOT DEFINED Python_INSTALL_PACKAGE_DIR) set(Python_INSTALL_PACKAGE_DIR "${Python_SITELIB}") - endif(NOT CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + endif(NOT DEFINED Python_INSTALL_PACKAGE_DIR) message(STATUS " package install directory: ${Python_INSTALL_PACKAGE_DIR}") + # look for NumPy if(Python_NumPy_FOUND) set(CMAKE_SWIG_FLAGS -DWITHNUMPY ${CRP}) @@ -531,7 +530,6 @@ if(ENABLE_PYTHON AND Python_FOUND) target_link_libraries(crpropa-swig crpropa ${Python_LIBRARIES} ${Python_LIBRARY}) add_dependencies(crpropa-swig crpropa-swig-wrapper) - install(DIRECTORY "${CMAKE_SOURCE_DIR}/python/crpropa" DESTINATION "${Python_INSTALL_PACKAGE_DIR}") install(FILES "${CMAKE_CURRENT_BINARY_DIR}/crpropa.py" DESTINATION "${Python_INSTALL_PACKAGE_DIR}/crpropa") install(TARGETS crpropa-swig LIBRARY DESTINATION "${Python_INSTALL_PACKAGE_DIR}/crpropa") From 8bb10bbafa4402e9bb21369fa4cc32a1bcb824c1 Mon Sep 17 00:00:00 2001 From: Julien Date: Thu, 22 Feb 2024 16:51:40 +0100 Subject: [PATCH 55/81] add factor of $ into radial sampling --- src/Source.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Source.cpp b/src/Source.cpp index 2ac28a100..9ff0b7f4d 100644 --- a/src/Source.cpp +++ b/src/Source.cpp @@ -362,7 +362,8 @@ void SourceUniformCylinder::setDescription() { // --------------------------------------------------------------------------- SourceSNRDistribution::SourceSNRDistribution() : - rEarth(8.5 * kpc),alpha(2.), beta(3.53), zg(0.3 * kpc) { + rEarth(8.5 * kpc), beta(3.53), zg(0.3 * kpc) { + setAlpha(2.); setFrMax(); setFzMax(0.3 * kpc); setRMax(20 * kpc); @@ -370,7 +371,8 @@ SourceSNRDistribution::SourceSNRDistribution() : } SourceSNRDistribution::SourceSNRDistribution(double rEarth, double alpha, double beta, double zg) : - rEarth(rEarth),alpha(alpha), beta(beta), zg(zg) { + rEarth(rEarth), beta(beta), zg(zg) { + setAlpha(alpha); setFrMax(); setFzMax(zg); setRMax(20 * kpc); @@ -414,7 +416,7 @@ double SourceSNRDistribution::fz(double z) const{ } double SourceSNRDistribution::getAlpha() const { - return alpha; + return alpha - 1; } double SourceSNRDistribution::getBeta() const { @@ -458,7 +460,7 @@ double SourceSNRDistribution::getZMax() const { } void SourceSNRDistribution::setAlpha(double a) { - alpha = a; + alpha = a + 1.; // add 1 for dV = r * dR * dphi * dz setRMax(rMax); setFrMax(); } @@ -504,7 +506,7 @@ void SourcePulsarDistribution::prepareParticle(ParticleState& particle) const { double Rtilde; while (true) { Rtilde = random.rand() * rMax; - double fTest = random.rand() * frMax; + double fTest = random.rand() * frMax * 1.1; double fR = fr(Rtilde); if (fTest <= fR) { break; @@ -530,10 +532,8 @@ void SourcePulsarDistribution::prepareParticle(ParticleState& particle) const { } double SourcePulsarDistribution::fr(double r) const { - double Atilde = (pow(beta, 4.) * exp(-beta)) / (12 * M_PI * pow(rEarth, 2.)); - double f = pow(r / rEarth, 2.) * exp(-beta * (r - rEarth) / rEarth); - double fr = Atilde * f; - return fr; + double f = r * pow(r / rEarth, 2.) * exp(-beta * (r - rEarth) / rEarth); + return f; } double SourcePulsarDistribution::fz(double z) const{ @@ -569,8 +569,8 @@ double SourcePulsarDistribution::blurTheta(double thetaTilde, double rTilde) con } void SourcePulsarDistribution::setFrMax(double R, double b) { - frMax = pow(b, 2.) / (3 * pow(R, 2.) * M_PI) * exp(-2.); - return; + double r = 3 * R / b; + frMax = fr(r); } void SourcePulsarDistribution::setFzMax(double zg) { From 76fef90d17de0130af701e69b58d220900711b21 Mon Sep 17 00:00:00 2001 From: Julien Date: Thu, 22 Feb 2024 17:22:40 +0100 Subject: [PATCH 56/81] add python_install_package as ccmake option, adapt example test --- .github/workflows/test_examples.yml | 2 +- CMakeLists.txt | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test_examples.yml b/.github/workflows/test_examples.yml index 96e7e0eb8..ac5621e72 100644 --- a/.github/workflows/test_examples.yml +++ b/.github/workflows/test_examples.yml @@ -33,7 +33,7 @@ jobs: run: | mkdir build cd build - cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/.local -DENABLE_PYTHON=True -DPython_EXECUTABLE=${{ matrix.config.py }} -DENABLE_TESTING=Off -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS=native + cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/.local -DENABLE_PYTHON=True -DPython_EXECUTABLE=${{ matrix.config.py }} -DENABLE_TESTING=Off -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS=native -DPython_INSTALL_PACKAGE_DIR=/home/runner/.local/ - name: Build CRPropa run: | cd build diff --git a/CMakeLists.txt b/CMakeLists.txt index 06f1a1aac..0b0082f32 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -466,9 +466,7 @@ if(ENABLE_PYTHON AND Python_FOUND) # use Python_INSTALL_PACKAGE_DIR if provided; otherwise, install in Python_SITELIB - if(NOT DEFINED Python_INSTALL_PACKAGE_DIR) - set(Python_INSTALL_PACKAGE_DIR "${Python_SITELIB}") - endif(NOT DEFINED Python_INSTALL_PACKAGE_DIR) + set(Python_INSTALL_PACKAGE_DIR "${Python_SITELIB}" CACHE PATH "folder in which the python package is installed") message(STATUS " package install directory: ${Python_INSTALL_PACKAGE_DIR}") From 2c71e4fadc5e1e76ca30f6159547e35dfebdfd92 Mon Sep 17 00:00:00 2001 From: Rafael Date: Thu, 22 Feb 2024 18:56:05 +0100 Subject: [PATCH 57/81] updated doc for new Python interface via cmake --- doc/pages/Installation.md | 63 +++++++++++---------------------------- 1 file changed, 18 insertions(+), 45 deletions(-) diff --git a/doc/pages/Installation.md b/doc/pages/Installation.md index eb638449f..1b8272193 100644 --- a/doc/pages/Installation.md +++ b/doc/pages/Installation.md @@ -10,10 +10,9 @@ git clone https://github.com/CRPropa/CRPropa3.git ## Prerequisites + C++ Compiler with C++11 support (gcc, clang and icc are known to work) + Fortran Compiler: to compile SOPHIA -+ numpy: for scientific computations Optionally CRPropa can be compiled with the following dependencies to enable certain functionality. -+ Python and SWIG: to use CRPropa from python (tested for > Python 2.7 and > SWIG 3.0.4) ++ Python, NumPy, and SWIG: to use CRPropa from python (tested for > Python 3.0 and > SWIG 3.0.4) + FFTW3: for turbulent magnetic field grids (FFTW3 with single precision is needed) + Gadget: magnetic fields for large scale structure data + OpenMP: for shared memory parallelization @@ -46,12 +45,12 @@ The following packages are provided with the source code and do not need to be i 2. A set of unit tests can be run with ```make test```. If the tests are successful continue with ```make install``` to install CRPropa at the specified path, or leave it in the build directory. Make sure the - environment variables are set accordingly: E.g. for an installation under - $HOME/.local and using Python 2.7 set + environment variables are set accordingly: e.g. for an installation under + $HOME/.local and using Python 3 set ```sh export PATH=$HOME/.local/bin:$PATH export LD_LIBRARY_PATH=$HOME/.local/lib:$LD_LIBRARY_PATH - export PYTHONPATH=$HOME/.local/lib/python2.7/site-packages:$PYTHONPATH + export PYTHONPATH=$HOME/.local/lib/python3.9/site-packages:$PYTHONPATH export PKG_CONFIG_PATH=$HOME/.local/lib/pkgconfig:$PKG_CONFIG_PATH ``` @@ -110,7 +109,7 @@ worthwhile effort afterwards. To install python dependencies and libraries use `pip`. Example: `pip install numpy`. -4. Compile and install CRPropa (please note specific [insturctions for different operating systems](#notes-for-specific-operating-systems)). +4. Compile and install CRPropa (please note specific [instructions for different operating systems](#notes-for-specific-operating-systems)). ```sh cd $CRPROPA_DIR git clone https://github.com/CRPropa/CRPropa3.git @@ -144,7 +143,7 @@ cmake -DENABLE_PYTHON=ON .. ``` + Set the install path ```-DCMAKE_INSTALL_PREFIX=/my/install/path``` -+ Enable Galactic magnetic lens ```-DENABLE_GALACTICMAGETICLENS=ON``` ++ Enable Galactic magnetic lens ```-DENABLE_GALACTICMAGNETICLENS=ON``` + Enable FFTW3 (turbulent magnetic fields) ```-DENABLE_FFTW3F=ON``` + Enable OpenMP (multi-core parallel computing) ```-DENABLE_OPENMP=ON``` + Enable Python (Python interface with SWIG) ```-DENABLE_PYTHON=ON``` @@ -178,11 +177,13 @@ cmake -DENABLE_PYTHON=ON .. + Quite often there are multiple Python versions installed in a system. This is likely the cause of many (if not most) of the installation problems related to Python. To prevent conflicts among them, one can explicitly refer to the Python version to be used. Example: ``` - -DCMAKE_PYTHON_EXECUTABLE=/usr/bin/python - -DCMAKE_PYTHON_INCLUDE_DIR= - -DCMAKE_PYTHON_LIBRARY=/libpython.so + -DPython_EXECUTABLE=/usr/bin/python + -DPython_INCLUDE_DIRS= + -DPython_LIBRARY=/libpython.so ``` Note that in systems running OSX, the extension .so should be replaced by .dylib. + For further details, see [FindPython.cmake](https://cmake.org/cmake/help/latest/module/FindPython.html#module:FindPython). + ## Notes for Specific Operating Systems @@ -201,41 +202,13 @@ For Fedora/CentOS/RHEL the required packages to build CRPropa: ``` In case of CentOS/RHEL 7, the SWIG version is too old and has to be built from source. - ### Mac OS X -Tested on version 12.5.1 with M1 pro where command line developer tools are installed. -Install Python3, and llvm from Homebrew, and specify the following paths to the Python and llvm directories in the Homebrew folder after step 3 of the above installation, e.g. (please use your exact versions): - ```sh - export LLVM_DIR="/opt/homebrew/Cellar/llvm/15.0.7_1" - PYTHON_VERSION=3.10 - LLVM_VERSION=15.0.7 - PYTHON_DIR=/opt/homebrew/Cellar/python@3.10/3.10.9/Frameworks/Python.framework/Versions/3.10 - ``` -and replace the command in step 4 of the installation routine - ```sh - CMAKE_PREFIX_PATH=$CRPROPA_DIR cmake -DCMAKE_INSTALL_PREFIX=$CRPROPA_DIR .. - ``` -with - ```sh - cmake .. \ - -DCMAKE_INSTALL_PREFIX=$CRPROPA_DIR \ - -DPYTHON_EXECUTABLE=$PYTHON_DIR/bin/python$PYTHON_VERSION \ - -DPYTHON_LIBRARY=$PYTHON_DIR/lib/libpython$PYTHON_VERSION.dylib \ - -DPYTHON_INCLUDE_PATH=$PYTHON_DIR/include/python$PYTHON_VERSION \ - -DCMAKE_C_COMPILER=$LLVM_DIR/bin/clang \ - -DCMAKE_CXX_COMPILER=$LLVM_DIR/bin/clang++ \ - -DOpenMP_CXX_FLAGS="-fopenmp -I$LLVM_DIR/lib/clang/$LLVM_VERSION/include" \ - -DOpenMP_C_FLAGS="-fopenmp =libomp -I$LLVM_DIR/lib/clang/$LLVM_VERSION/include" \ - -DOpenMP_libomp_LIBRARY=$LLVM_DIR/lib/libomp.dylib \ - -DCMAKE_SHARED_LINKER_FLAGS="-L$LLVM_DIR/lib -lomp -Wl,-rpath,$LLVM_DIR/lib" \ - -DOpenMP_C_LIB_NAMES=libomp \ - -DOpenMP_CXX_LIB_NAMES=libomp \ - -DNO_TCMALLOC=TRUE +For a clean OS X (Sonoma 14+) installation, if you use Homebrew, the main dependencies can be installed as follows: + ```sh + brew install hdf5 fftw cfitsio muparser libomp numpy swig ``` -Check that all paths are set correctly with the following command in the build folder - ```sh - ccmake .. +Similarly, if you use MacPorts instead of Homebrew, download the corresponding packages: + ```sh + sudo port install hdf5 fftw cfitsio muparser libomp numpy swig ``` -and configure and generate again after changes. - - +Note that if you are using a Mac with Arm64 architecture (M1, M2, or M3 processors), `SIMD_EXTENSIONS` might not run straight away. From 2223f0532b5318561e30d972c6a9a34c54b39d51 Mon Sep 17 00:00:00 2001 From: Julien Date: Fri, 23 Feb 2024 12:22:19 +0100 Subject: [PATCH 58/81] update documentation creation --- .github/workflows/create_documentation.yml | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/.github/workflows/create_documentation.yml b/.github/workflows/create_documentation.yml index 5888cfc81..e50ce545e 100644 --- a/.github/workflows/create_documentation.yml +++ b/.github/workflows/create_documentation.yml @@ -9,22 +9,18 @@ jobs: fail-fast: false matrix: config: - - name: "ubuntu-20" - os: ubuntu-20.04 - cxx: "g++-9" - cc: "gcc-9" - fc: "gfortran-9" - swig_builtin: "Off" #uses swig 4.0.1 + - name: "ubuntu-22" + os: ubuntu-22.04 + cxx: "g++-11" + cc: "gcc-11" + fc: "gfortran-11" + swig_builtin: "On" #uses swig 4.0.2 + py: "/usr/bin/python3" #python 3.10 # define steps to take steps: - name: Checkout repository uses: actions/checkout@v3 - - name: Python install - uses: actions/setup-python@v4 - with: - python-version: '3.9' - cache: 'pip' # caching pip dependencies - name: Prerequirements run: | sudo apt-get update @@ -40,9 +36,7 @@ jobs: run: | mkdir build cd build - cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/.local \ - -DENABLE_PYTHON=True -DENABLE_TESTING=ON -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} \ - -DSIMD_EXTENSIONS=native -DBUILD_DOC=True -DENABLE_COVERAGE=True + cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/.local -DENABLE_PYTHON=True -DPython_EXECUTABLE=${{ matrix.config.py }} -DENABLE_TESTING=Off -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS=native -DPython_INSTALL_PACKAGE_DIR=/home/runner/.local/ - name: Build CRPropa run: | cd build From 67241b33190d41771e6ecfc506a66b46dbed1699 Mon Sep 17 00:00:00 2001 From: Julien Date: Fri, 23 Feb 2024 12:29:45 +0100 Subject: [PATCH 59/81] enable doc and coverage --- .github/workflows/create_documentation.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/create_documentation.yml b/.github/workflows/create_documentation.yml index e50ce545e..f76f56c18 100644 --- a/.github/workflows/create_documentation.yml +++ b/.github/workflows/create_documentation.yml @@ -36,7 +36,9 @@ jobs: run: | mkdir build cd build - cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/.local -DENABLE_PYTHON=True -DPython_EXECUTABLE=${{ matrix.config.py }} -DENABLE_TESTING=Off -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS=native -DPython_INSTALL_PACKAGE_DIR=/home/runner/.local/ + cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/.local -DENABLE_PYTHON=True -DPython_EXECUTABLE=${{ matrix.config.py }} + -DENABLE_TESTING=Off -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS=native + -DPython_INSTALL_PACKAGE_DIR=/home/runner/.local/ -DBUILD_DOC=On -DENABLE_COVERAGE=On - name: Build CRPropa run: | cd build From 30644625918b7daefcf1ae5c98f9d534e250cacd Mon Sep 17 00:00:00 2001 From: Rafael Date: Fri, 23 Feb 2024 13:05:11 +0100 Subject: [PATCH 60/81] add information on Python_INSTALL_PACKAGE_DIR --- doc/pages/Installation.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/doc/pages/Installation.md b/doc/pages/Installation.md index 1b8272193..4b2c9ef95 100644 --- a/doc/pages/Installation.md +++ b/doc/pages/Installation.md @@ -181,8 +181,13 @@ cmake -DENABLE_PYTHON=ON .. -DPython_INCLUDE_DIRS= -DPython_LIBRARY=/libpython.so ``` - Note that in systems running OSX, the extension .so should be replaced by .dylib. - For further details, see [FindPython.cmake](https://cmake.org/cmake/help/latest/module/FindPython.html#module:FindPython). +Note that in systems running OSX, the extension .so should be replaced by .dylib. +In addition, The path where the CRPropa python module is installed can be specified with the flag: +``` +-DPython_INSTALL_PACKAGE_DIR= +``` +For further details, see [FindPython.cmake](https://cmake.org/cmake/help/latest/module/FindPython.html#module:FindPython). + ## Notes for Specific Operating Systems From 9698b24d4ec149f9227a829e4ca216ed1eba4d74 Mon Sep 17 00:00:00 2001 From: Rafael Date: Fri, 23 Feb 2024 13:06:47 +0100 Subject: [PATCH 61/81] update required swig version --- doc/pages/Installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/pages/Installation.md b/doc/pages/Installation.md index 4b2c9ef95..177a62195 100644 --- a/doc/pages/Installation.md +++ b/doc/pages/Installation.md @@ -12,7 +12,7 @@ git clone https://github.com/CRPropa/CRPropa3.git + Fortran Compiler: to compile SOPHIA Optionally CRPropa can be compiled with the following dependencies to enable certain functionality. -+ Python, NumPy, and SWIG: to use CRPropa from python (tested for > Python 3.0 and > SWIG 3.0.4) ++ Python, NumPy, and SWIG: to use CRPropa from python (tested for > Python 3.0 and > SWIG 4.0.2) + FFTW3: for turbulent magnetic field grids (FFTW3 with single precision is needed) + Gadget: magnetic fields for large scale structure data + OpenMP: for shared memory parallelization From be12d2fa25a77fd71c9aaed7f04c43cbe3f550d2 Mon Sep 17 00:00:00 2001 From: Rafael Date: Fri, 23 Feb 2024 13:10:57 +0100 Subject: [PATCH 62/81] keep prvious instructions for OSX --- doc/pages/Installation.md | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/doc/pages/Installation.md b/doc/pages/Installation.md index 177a62195..c94551ae0 100644 --- a/doc/pages/Installation.md +++ b/doc/pages/Installation.md @@ -217,3 +217,42 @@ Similarly, if you use MacPorts instead of Homebrew, download the corresponding p sudo port install hdf5 fftw cfitsio muparser libomp numpy swig ``` Note that if you are using a Mac with Arm64 architecture (M1, M2, or M3 processors), `SIMD_EXTENSIONS` might not run straight away. + + +Some combinations of versions of the Apple's clang compiler and python might lead to installation errors. +In these cases, the user might want to consider the workaround below (tested on version 12.5.1 with M1 pro where command line developer tools are installed). + +Install Python3, and llvm from Homebrew, and specify the following paths to the Python and llvm directories in the Homebrew folder after step 3 of the above installation, e.g. (please use your exact versions): + ```sh + export LLVM_DIR="/opt/homebrew/Cellar/llvm/15.0.7_1" + PYTHON_VERSION=3.10 + LLVM_VERSION=15.0.7 + PYTHON_DIR=/opt/homebrew/Cellar/python@3.10/3.10.9/Frameworks/Python.framework/Versions/3.10 + ``` +and replace the command in step 4 of the installation routine + ```sh + CMAKE_PREFIX_PATH=$CRPROPA_DIR cmake -DCMAKE_INSTALL_PREFIX=$CRPROPA_DIR .. + ``` +with + ```sh + cmake .. \ + -DCMAKE_INSTALL_PREFIX=$CRPROPA_DIR \ + -DPython_EXECUTABLE=$PYTHON_DIR/bin/python$PYTHON_VERSION \ + -DPython_LIBRARY=$PYTHON_DIR/lib/libpython$PYTHON_VERSION.dylib \ + -DPython_INCLUDE_PATH=$PYTHON_DIR/include/python$PYTHON_VERSION \ + -DCMAKE_C_COMPILER=$LLVM_DIR/bin/clang \ + -DCMAKE_CXX_COMPILER=$LLVM_DIR/bin/clang++ \ + -DOpenMP_CXX_FLAGS="-fopenmp -I$LLVM_DIR/lib/clang/$LLVM_VERSION/include" \ + -DOpenMP_C_FLAGS="-fopenmp =libomp -I$LLVM_DIR/lib/clang/$LLVM_VERSION/include" \ + -DOpenMP_libomp_LIBRARY=$LLVM_DIR/lib/libomp.dylib \ + -DCMAKE_SHARED_LINKER_FLAGS="-L$LLVM_DIR/lib -lomp -Wl,-rpath,$LLVM_DIR/lib" \ + -DOpenMP_C_LIB_NAMES=libomp \ + -DOpenMP_CXX_LIB_NAMES=libomp \ + -DNO_TCMALLOC=TRUE + ``` +Check that all paths are set correctly with the following command in the build folder + ```sh + ccmake .. + ``` +and configure and generate again after changes. + From c32f08fb487af02d15806432926ac22d522a80e2 Mon Sep 17 00:00:00 2001 From: Julien Date: Mon, 26 Feb 2024 08:41:22 +0100 Subject: [PATCH 63/81] add linebreak --- .github/workflows/create_documentation.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/create_documentation.yml b/.github/workflows/create_documentation.yml index f76f56c18..f01b1ef47 100644 --- a/.github/workflows/create_documentation.yml +++ b/.github/workflows/create_documentation.yml @@ -36,8 +36,8 @@ jobs: run: | mkdir build cd build - cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/.local -DENABLE_PYTHON=True -DPython_EXECUTABLE=${{ matrix.config.py }} - -DENABLE_TESTING=Off -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS=native + cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/.local -DENABLE_PYTHON=True -DPython_EXECUTABLE=${{ matrix.config.py }} \ + -DENABLE_TESTING=Off -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS=native \ -DPython_INSTALL_PACKAGE_DIR=/home/runner/.local/ -DBUILD_DOC=On -DENABLE_COVERAGE=On - name: Build CRPropa run: | From 99bccd95b3ceb79a316206796d9827fd34feaf69 Mon Sep 17 00:00:00 2001 From: Julien Date: Mon, 26 Feb 2024 08:44:29 +0100 Subject: [PATCH 64/81] remove linebreak --- .github/workflows/create_documentation.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/create_documentation.yml b/.github/workflows/create_documentation.yml index f01b1ef47..a3f2e5c5f 100644 --- a/.github/workflows/create_documentation.yml +++ b/.github/workflows/create_documentation.yml @@ -36,9 +36,7 @@ jobs: run: | mkdir build cd build - cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/.local -DENABLE_PYTHON=True -DPython_EXECUTABLE=${{ matrix.config.py }} \ - -DENABLE_TESTING=Off -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS=native \ - -DPython_INSTALL_PACKAGE_DIR=/home/runner/.local/ -DBUILD_DOC=On -DENABLE_COVERAGE=On + cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/.local -DENABLE_PYTHON=True -DPython_EXECUTABLE=${{ matrix.config.py }} -DENABLE_TESTING=Off -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS=native -DPython_INSTALL_PACKAGE_DIR=/home/runner/.local/ -DBUILD_DOC=On -DENABLE_COVERAGE=On - name: Build CRPropa run: | cd build From 106e32f4c9e5094e4c472e2d7d1053c3a6441022 Mon Sep 17 00:00:00 2001 From: Julien Date: Mon, 26 Feb 2024 08:53:48 +0100 Subject: [PATCH 65/81] enable testing --- .github/workflows/create_documentation.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/create_documentation.yml b/.github/workflows/create_documentation.yml index a3f2e5c5f..5db53278c 100644 --- a/.github/workflows/create_documentation.yml +++ b/.github/workflows/create_documentation.yml @@ -36,7 +36,7 @@ jobs: run: | mkdir build cd build - cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/.local -DENABLE_PYTHON=True -DPython_EXECUTABLE=${{ matrix.config.py }} -DENABLE_TESTING=Off -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS=native -DPython_INSTALL_PACKAGE_DIR=/home/runner/.local/ -DBUILD_DOC=On -DENABLE_COVERAGE=On + cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/.local -DENABLE_PYTHON=True -DPython_EXECUTABLE=${{ matrix.config.py }} -DENABLE_TESTING=On -DENABLE_SWIG_BUILTIN=${{ matrix.config.swig_builtin }} -DSIMD_EXTENSIONS=native -DPython_INSTALL_PACKAGE_DIR=/home/runner/.local/ -DBUILD_DOC=On -DENABLE_COVERAGE=On - name: Build CRPropa run: | cd build From 9c991e4178c291b088f76134347cb800de9226b2 Mon Sep 17 00:00:00 2001 From: Julien Date: Mon, 26 Feb 2024 09:32:29 +0100 Subject: [PATCH 66/81] move from node 16 to node 20 --- .github/workflows/create_documentation.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/create_documentation.yml b/.github/workflows/create_documentation.yml index 5db53278c..b1a0bee70 100644 --- a/.github/workflows/create_documentation.yml +++ b/.github/workflows/create_documentation.yml @@ -20,7 +20,7 @@ jobs: # define steps to take steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Prerequirements run: | sudo apt-get update @@ -57,7 +57,7 @@ jobs: make doc tar -zcvf documentation.tar.gz doc - name: archive documentation - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: "documentation" path: | From b005f9aaee3a639b3f899d5111354b86aeba1975 Mon Sep 17 00:00:00 2001 From: Rafael Date: Wed, 28 Feb 2024 12:14:11 +0100 Subject: [PATCH 67/81] updated tested python versions --- doc/pages/Installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/pages/Installation.md b/doc/pages/Installation.md index c94551ae0..c9f69ead5 100644 --- a/doc/pages/Installation.md +++ b/doc/pages/Installation.md @@ -12,7 +12,7 @@ git clone https://github.com/CRPropa/CRPropa3.git + Fortran Compiler: to compile SOPHIA Optionally CRPropa can be compiled with the following dependencies to enable certain functionality. -+ Python, NumPy, and SWIG: to use CRPropa from python (tested for > Python 3.0 and > SWIG 4.0.2) ++ Python, NumPy, and SWIG: to use CRPropa from python (tested for >= Python 3.7 and > SWIG 4.0.2) + FFTW3: for turbulent magnetic field grids (FFTW3 with single precision is needed) + Gadget: magnetic fields for large scale structure data + OpenMP: for shared memory parallelization From 7f54da1212d17a08d0fb344cb12f3c9a8d2cb6ab Mon Sep 17 00:00:00 2001 From: mertelx Date: Thu, 29 Feb 2024 16:13:11 +0100 Subject: [PATCH 68/81] Update build status badges --- README.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e55b42521..63499d112 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,14 @@ CRPropa ======== ![stable release](https://img.shields.io/badge/stable\_release-3.2.1-darkblue) -[![Build status](https://github.com/crpropa/crpropa3/actions/workflows/testing.yml/badge.svg)](https://github.com/crpropa/crpropa3/actions/) -[![Average time to resolve an issue](https://isitmaintained.com/badge/resolution/CRPropa/CRPropa3.svg)](https://isitmaintained.com/project/CRPropa/CRPropa3) -[![Percentage of issues still open](https://isitmaintained.com/badge/open/CRPropa/CRPropa3.svg)](https://isitmaintained.com/project/CRPropa/CRPropa3) + +[![Build: ubuntu22](https://github.com/CRPropa/CRPropa3/actions/workflows/testing_ubuntu22.yml/badge.svg)](https://github.com/CRPropa/CRPropa3/actions/workflows/testing_ubuntu22.yml) +[![Build: ubuntu20](https://github.com/CRPropa/CRPropa3/actions/workflows/testing_ubuntu20.yml/badge.svg)](https://github.com/CRPropa/CRPropa3/actions/workflows/testing_ubuntu20.yml) +[![Build: macos14](https://github.com/CRPropa/CRPropa3/actions/workflows/testing_OSX.yml/badge.svg)](https://github.com/CRPropa/CRPropa3/actions/workflows/testing_OSX.yml) +[![Examples](https://github.com/CRPropa/CRPropa3/actions/workflows/test_examples.yml/badge.svg)](https://github.com/CRPropa/CRPropa3/actions/workflows/test_examples.yml) + +![Issues](https://img.shields.io/github/issues/crpropa/CRPropa3) +![GitHub Issues or Pull Requests](https://img.shields.io/github/issues-pr/crpropa/CRPropa3) [![DOI:10.1088/1475-7516/2022/09/035](http://img.shields.io/badge/DOI-10.1088/1475-7516/2022/09/035.svg)]() [![arXiv](https://img.shields.io/badge/arXiv-2208.00107-b31b1b.svg)](https://arxiv.org/abs/2208.00107) From ca73b328141fbd68c5861fe59911de3be7ba2e1f Mon Sep 17 00:00:00 2001 From: mertelx Date: Thu, 29 Feb 2024 16:14:10 +0100 Subject: [PATCH 69/81] Update action version to run on node 20 (https://github.blog/changelog/2023-09-22-github-actions-transitioning-from-node-16-to-node-20/) --- .github/workflows/test_examples.yml | 2 +- .github/workflows/testing_OSX.yml | 4 ++-- .github/workflows/testing_ubuntu20.yml | 4 ++-- .github/workflows/testing_ubuntu22.yml | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/test_examples.yml b/.github/workflows/test_examples.yml index ac5621e72..f1edf5776 100644 --- a/.github/workflows/test_examples.yml +++ b/.github/workflows/test_examples.yml @@ -17,7 +17,7 @@ jobs: py: "/usr/bin/python3" #python 3.10 steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Preinstall run: | sudo apt-get update diff --git a/.github/workflows/testing_OSX.yml b/.github/workflows/testing_OSX.yml index 38ca85b47..ffc39046f 100644 --- a/.github/workflows/testing_OSX.yml +++ b/.github/workflows/testing_OSX.yml @@ -16,7 +16,7 @@ jobs: py: "/usr/bin/python3" steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Preinstall run: | brew install hdf5 fftw cfitsio muparser libomp numpy swig @@ -42,7 +42,7 @@ jobs: make test - name: Archive test results if: always() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: "test-report_${{matrix.config.name}}" path: build/Testing/Temporary/LastTest.log diff --git a/.github/workflows/testing_ubuntu20.yml b/.github/workflows/testing_ubuntu20.yml index 83acbf7fc..54e0f834e 100644 --- a/.github/workflows/testing_ubuntu20.yml +++ b/.github/workflows/testing_ubuntu20.yml @@ -17,7 +17,7 @@ jobs: py: "/usr/bin/python3" #python 3.8 steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Preinstall run: | sudo apt-get update @@ -41,7 +41,7 @@ jobs: make test - name: Archive test results if: always() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: "test-report_${{matrix.config.name}}" path: build/Testing/Temporary/LastTest.log \ No newline at end of file diff --git a/.github/workflows/testing_ubuntu22.yml b/.github/workflows/testing_ubuntu22.yml index 7991cf631..775a88d25 100644 --- a/.github/workflows/testing_ubuntu22.yml +++ b/.github/workflows/testing_ubuntu22.yml @@ -17,7 +17,7 @@ jobs: py: "/usr/bin/python3" #python 3.10 steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Preinstall run: | sudo apt-get update @@ -41,7 +41,7 @@ jobs: make test - name: Archive test results if: always() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: "test-report_${{matrix.config.name}}" path: build/Testing/Temporary/LastTest.log From 71a6f5fdad8aa16f26ee10736d7f3e479ff32da1 Mon Sep 17 00:00:00 2001 From: mertelx Date: Wed, 13 Mar 2024 12:01:46 +0100 Subject: [PATCH 70/81] Update the download link and changelog --- CHANGELOG.md | 1 + CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bf972ce31..5526f27ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ ### Interface changes: ### Features that are deprecated and will be removed after this release + * EBL model from Finke et al. 2022 ### Removed features * AMRMagneticField - underlying library (saga) is no longer supported. diff --git a/CMakeLists.txt b/CMakeLists.txt index 0b0082f32..1ea3fe40f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -308,7 +308,7 @@ endif(APPLE) # Download data files (interaction data, masses, decay data ...) # ---------------------------------------------------------------------------- OPTION(DOWNLOAD_DATA "Download CRPropa data files" ON) -set(CRPROPA_DATAFILE_VER "2023-10-20") +set(CRPROPA_DATAFILE_VER "2024-03-11") if(DOWNLOAD_DATA) message("-- Downloading data files from sciebo ~ 73 MB") file(DOWNLOAD From b242d7566dc5f6096e02bfeb212a427ce598182b Mon Sep 17 00:00:00 2001 From: mertelx Date: Wed, 13 Mar 2024 15:15:01 +0100 Subject: [PATCH 71/81] Fix typo in ebl fields --- test/testInteraction.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/testInteraction.cpp b/test/testInteraction.cpp index 38ecb28b8..f2fe49dbf 100644 --- a/test/testInteraction.cpp +++ b/test/testInteraction.cpp @@ -40,8 +40,8 @@ TEST(ElectronPairProduction, allBackgrounds) { epp.setPhotonField(irb); irb = new IRB_Stecker16_lower(); epp.setPhotonField(irb); - irb = new IRB_Finke22(); - epp.setPhotonField(IRB); + irb = new IRB_Finke22(); + epp.setPhotonField(irb); } TEST(ElectronPairProduction, energyDecreasing) { @@ -344,8 +344,8 @@ TEST(PhotoDisintegration, allBackgrounds) { pd.setPhotonField(irb); irb = new IRB_Stecker16_lower(); pd.setPhotonField(irb); - irb = new IRB_Finke22(); - pd.setPhotonField(IRB); + irb = new IRB_Finke22(); + pd.setPhotonField(irb); urb = new URB_Nitu21(); pd.setPhotonField(urb); } @@ -562,8 +562,8 @@ TEST(PhotoPionProduction, allBackgrounds) { ppp.setPhotonField(irb); irb = new IRB_Stecker16_lower(); ppp.setPhotonField(irb); - irb = new IRB_Finke22(); - ppp.setPhotonField(IRB); + irb = new IRB_Finke22(); + ppp.setPhotonField(irb); ref_ptr urb = new URB_Protheroe96(); ppp.setPhotonField(urb); urb = new URB_Nitu21(); From 096dafcfd9338c3a26815caa0a2fecaab0de7fa6 Mon Sep 17 00:00:00 2001 From: Julien Date: Thu, 14 Mar 2024 16:49:45 +0100 Subject: [PATCH 72/81] add bug-fix to changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bf972ce31..ceabd8b5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ### Bug fixes: * Fixed sign for exponential decay of magn. field strength with Galactic height in LogarithmicSpiralField + * Fixed r term in source distribution for SNR and Pulsar ### New features: From 0169c104cc730d336e61dc32f77dcdd51fe6f970 Mon Sep 17 00:00:00 2001 From: Julien Date: Thu, 14 Mar 2024 17:08:48 +0100 Subject: [PATCH 73/81] update test value --- test/testSource.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/testSource.cpp b/test/testSource.cpp index 6ce5cfada..4254e7f84 100644 --- a/test/testSource.cpp +++ b/test/testSource.cpp @@ -110,7 +110,7 @@ TEST(SourceSNRDistribution, simpleTest) { } R2_mean/=100000.; Z_mean/=100000.; - EXPECT_NEAR(64.4, R2_mean, 1.); + EXPECT_NEAR(100.306, R2_mean, 1); EXPECT_NEAR(0., Z_mean, 0.1); } From 3ee0447414f2e6a28d6559439a957ef23e3aadf8 Mon Sep 17 00:00:00 2001 From: Julien Date: Fri, 15 Mar 2024 11:50:34 +0100 Subject: [PATCH 74/81] add comment for alpha value --- src/Source.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Source.cpp b/src/Source.cpp index 9ff0b7f4d..f0b0e698c 100644 --- a/src/Source.cpp +++ b/src/Source.cpp @@ -416,7 +416,7 @@ double SourceSNRDistribution::fz(double z) const{ } double SourceSNRDistribution::getAlpha() const { - return alpha - 1; + return alpha - 1; // -1 to account for the R-term in the volume element dV = R * dR * dphi * dz } double SourceSNRDistribution::getBeta() const { From f4c8b4e208f277a750f203270005449167b2fd5b Mon Sep 17 00:00:00 2001 From: Julien Date: Mon, 8 Apr 2024 16:41:30 +0200 Subject: [PATCH 75/81] add lxml to documentation dependency --- .github/workflows/create_documentation.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/create_documentation.yml b/.github/workflows/create_documentation.yml index 5888cfc81..91c4097d3 100644 --- a/.github/workflows/create_documentation.yml +++ b/.github/workflows/create_documentation.yml @@ -31,7 +31,7 @@ jobs: sudo apt-get install libmuparser-dev libhdf5-serial-dev libomp5 libomp-dev libfftw3-dev libcfitsio-dev lcov doxygen graphviz sudo apt-get install pandoc # do not only use pip to install pandoc, see https://stackoverflow.com/questions/62398231/building-docs-fails-due-to-missing-pandoc pip install -r doc/pages/example_notebooks/requirements.txt # load requirements for notebooks - pip install sphinx sphinx_rtd_theme m2r2 nbsphinx breathe pandoc exhale # load requirements for documentation + pip install sphinx sphinx_rtd_theme m2r2 nbsphinx lxml breathe pandoc exhale # load requirements for documentation - name: Set up the build env: CXX: ${{ matrix.config.cxx }} From b471b831796b4575cb2d29708d6262335b3242a5 Mon Sep 17 00:00:00 2001 From: Julien Date: Mon, 8 Apr 2024 16:53:34 +0200 Subject: [PATCH 76/81] change lxml to lxml_html_clean --- .github/workflows/create_documentation.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/create_documentation.yml b/.github/workflows/create_documentation.yml index c3b885133..b176fbca4 100644 --- a/.github/workflows/create_documentation.yml +++ b/.github/workflows/create_documentation.yml @@ -27,7 +27,7 @@ jobs: sudo apt-get install libmuparser-dev libhdf5-serial-dev libomp5 libomp-dev libfftw3-dev libcfitsio-dev lcov doxygen graphviz sudo apt-get install pandoc # do not only use pip to install pandoc, see https://stackoverflow.com/questions/62398231/building-docs-fails-due-to-missing-pandoc pip install -r doc/pages/example_notebooks/requirements.txt # load requirements for notebooks - pip install sphinx sphinx_rtd_theme m2r2 nbsphinx lxml breathe pandoc exhale # load requirements for documentation + pip install sphinx sphinx_rtd_theme m2r2 nbsphinx lxml_html_clean breathe pandoc exhale # load requirements for documentation - name: Set up the build env: CXX: ${{ matrix.config.cxx }} From 25aac942e22663d11e50bf1e5b4c8287349895cb Mon Sep 17 00:00:00 2001 From: Leander Schlegel Date: Sun, 21 Apr 2024 19:42:05 +0200 Subject: [PATCH 77/81] bugfix to prevent photons getting pmass unequal to zero and commented lines for non-nuclei --- src/ParticleState.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ParticleState.cpp b/src/ParticleState.cpp index 9f867c384..ad7aa4fa9 100644 --- a/src/ParticleState.cpp +++ b/src/ParticleState.cpp @@ -55,8 +55,10 @@ void ParticleState::setId(int newId) { if (id < 0) charge *= -1; // anti-nucleus } else { - if (abs(id) == 11) + if (abs(id) == 11) //electron or positron pmass = mass_electron; + if (abs(id) == 22) //photon + pmass = 0.0; charge = HepPID::charge(id) * eplus; } } From a22b225623485aaf5a26e2c7d2fa0153364cb4d9 Mon Sep 17 00:00:00 2001 From: Leander Schlegel Date: Mon, 22 Apr 2024 18:35:51 +0200 Subject: [PATCH 78/81] introduction of new general function particleMass for non-nuclei and nuclei as suggested by Lukas and Julien --- include/crpropa/ParticleMass.h | 10 +++++++++- src/ParticleMass.cpp | 11 +++++++++++ src/ParticleState.cpp | 6 +----- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/include/crpropa/ParticleMass.h b/include/crpropa/ParticleMass.h index f4e5a6d6c..fdfd8579d 100644 --- a/include/crpropa/ParticleMass.h +++ b/include/crpropa/ParticleMass.h @@ -6,7 +6,15 @@ namespace crpropa { * \addtogroup PhysicsDefinitions * @{ */ - + + /** Get the particle mass by lookup from a table. + For nuclei, the function nuclearMass is called, for the case of + electrons or positrons the mass_electron is returned and for all + other cases like photons and also neutrinos, zero mass is returned. + @param id id of the particle following the PDG numbering scheme + @returns The mass of a the particle + */ + double particleMass(int id); /** Get the nucleus mass by lookup from a table. The masses are the atomic masses from the NIST database: http://www.nist.gov/pml/data/comp.cfm diff --git a/src/ParticleMass.cpp b/src/ParticleMass.cpp index a2a5c5090..cc474eb2a 100644 --- a/src/ParticleMass.cpp +++ b/src/ParticleMass.cpp @@ -53,6 +53,17 @@ struct NuclearMassTable { static NuclearMassTable nuclearMassTable; +double particleMass(int id) { + double m; + if (isNucleus(id)) + return nuclearMass(id); + if (abs(id) == 11) + m = mass_electron; + else + m = 0.0; + return m; +} + double nuclearMass(int id) { int A = massNumber(id); int Z = chargeNumber(id); diff --git a/src/ParticleState.cpp b/src/ParticleState.cpp index ad7aa4fa9..85736a856 100644 --- a/src/ParticleState.cpp +++ b/src/ParticleState.cpp @@ -49,16 +49,12 @@ double ParticleState::getRigidity() const { void ParticleState::setId(int newId) { id = newId; + pmass = particleMass(id); if (isNucleus(id)) { - pmass = nuclearMass(id); charge = chargeNumber(id) * eplus; if (id < 0) charge *= -1; // anti-nucleus } else { - if (abs(id) == 11) //electron or positron - pmass = mass_electron; - if (abs(id) == 22) //photon - pmass = 0.0; charge = HepPID::charge(id) * eplus; } } From e900b39f746b706c8098c43f1cfc7d599f08cdd7 Mon Sep 17 00:00:00 2001 From: Leander Schlegel Date: Mon, 22 Apr 2024 18:45:09 +0200 Subject: [PATCH 79/81] updated CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4332cf998..cf17ffbb7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,10 +3,12 @@ ### Bug fixes: * Fixed sign for exponential decay of magn. field strength with Galactic height in LogarithmicSpiralField * Fixed r term in source distribution for SNR and Pulsar + * Fixed wrong mass inheritance for secondaries other than nuclei or electron/positron ### New features: ### Interface changes: + * Added new backwards-compatible function particleMass that returns particle mass also for non-nuclei ### Features that are deprecated and will be removed after this release * EBL model from Finke et al. 2022 From 8376c76cc47f37d54088dfe8b01d3998d3676285 Mon Sep 17 00:00:00 2001 From: Leander Schlegel Date: Tue, 23 Apr 2024 15:35:15 +0200 Subject: [PATCH 80/81] implementation of comments: codestyle and optimization of particleMass function --- CHANGELOG.md | 2 +- include/crpropa/ParticleMass.h | 2 ++ src/ParticleMass.cpp | 7 ++----- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cf17ffbb7..4d7d0ccc3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,9 +6,9 @@ * Fixed wrong mass inheritance for secondaries other than nuclei or electron/positron ### New features: + * Added new backwards-compatible function particleMass that returns particle mass also for non-nuclei ### Interface changes: - * Added new backwards-compatible function particleMass that returns particle mass also for non-nuclei ### Features that are deprecated and will be removed after this release * EBL model from Finke et al. 2022 diff --git a/include/crpropa/ParticleMass.h b/include/crpropa/ParticleMass.h index fdfd8579d..06175f20c 100644 --- a/include/crpropa/ParticleMass.h +++ b/include/crpropa/ParticleMass.h @@ -15,6 +15,7 @@ namespace crpropa { @returns The mass of a the particle */ double particleMass(int id); + /** Get the nucleus mass by lookup from a table. The masses are the atomic masses from the NIST database: http://www.nist.gov/pml/data/comp.cfm @@ -25,6 +26,7 @@ namespace crpropa { @returns The mass of a the nucleus */ double nuclearMass(int id); + /** Get the nucleus mass by lookup from a table. The masses are the atomic masses from the NIST database: http://www.nist.gov/pml/data/comp.cfm diff --git a/src/ParticleMass.cpp b/src/ParticleMass.cpp index cc474eb2a..075668487 100644 --- a/src/ParticleMass.cpp +++ b/src/ParticleMass.cpp @@ -54,14 +54,11 @@ struct NuclearMassTable { static NuclearMassTable nuclearMassTable; double particleMass(int id) { - double m; if (isNucleus(id)) return nuclearMass(id); if (abs(id) == 11) - m = mass_electron; - else - m = 0.0; - return m; + return mass_electron; + return 0.0; } double nuclearMass(int id) { From cb9f2d9fa8e8bf29a7f41458251c0fed812e9590 Mon Sep 17 00:00:00 2001 From: Leander Schlegel Date: Tue, 23 Apr 2024 17:35:59 +0200 Subject: [PATCH 81/81] extending the test of addSecondary() for the secondaries mass and adding new test for the particleMass() function --- test/testCore.cpp | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/test/testCore.cpp b/test/testCore.cpp index 7aebff63a..b6738ac2a 100644 --- a/test/testCore.cpp +++ b/test/testCore.cpp @@ -149,6 +149,16 @@ TEST(ParticleID, isNucleus) { EXPECT_FALSE(isNucleus(11)); } +TEST(ParticleMass, particleMass) { + //particleMass(int id) interfaces nuclearMass for nuclei + EXPECT_DOUBLE_EQ(nuclearMass(nucleusId(1,1)), particleMass(nucleusId(1,1))); + //particleMass(int id) for electron/positron, photon and neutrino + EXPECT_DOUBLE_EQ(mass_electron,particleMass(11)); + EXPECT_DOUBLE_EQ(mass_electron,particleMass(-11)); + EXPECT_DOUBLE_EQ(0.0,particleMass(22)); + EXPECT_DOUBLE_EQ(0.0,particleMass(14)); +} + TEST(HepPID, consistencyWithReferenceImplementation) { // Tests the performance improved version against the default one unsigned long testPID = rand() % 1000000000 + 1000000000; @@ -219,8 +229,14 @@ TEST(Candidate, addSecondary) { c.addSecondary(nucleusId(1,1), 200); c.addSecondary(nucleusId(1,1), 200, 5.); - Candidate s1 = *c.secondaries[0]; - Candidate s2 = *c.secondaries[1]; + c.addSecondary(11, 200); + c.addSecondary(14, 200); + c.addSecondary(22, 200); + Candidate s1 = *c.secondaries[0]; //proton + Candidate s2 = *c.secondaries[1]; //proton + Candidate s3 = *c.secondaries[2]; //electron + Candidate s4 = *c.secondaries[3]; //neutrino + Candidate s5 = *c.secondaries[4]; //photon EXPECT_EQ(nucleusId(1,1), s1.current.getId()); EXPECT_EQ(200, s1.current.getEnergy()); @@ -231,6 +247,9 @@ TEST(Candidate, addSecondary) { EXPECT_TRUE(Vector3d(1,2,3) == s1.created.getPosition()); EXPECT_TRUE(Vector3d(0,0,1) == s1.created.getDirection()); EXPECT_TRUE(s1.getTagOrigin() == "SEC"); + EXPECT_EQ(mass_electron,s3.current.getMass()); + EXPECT_EQ(0.0,s4.current.getMass()); + EXPECT_EQ(0.0,s5.current.getMass()); EXPECT_EQ(15., s2.getWeight()); }