IAP GITLAB

Skip to content
Snippets Groups Projects
Commit 956d5ae4 authored by ralfulrich's avatar ralfulrich
Browse files

update to magnetic field model testing

parent 97586ab6
No related branches found
No related tags found
1 merge request!404adding Geomagnetic Models
...@@ -7,9 +7,6 @@ ...@@ -7,9 +7,6 @@
*/ */
#include <corsika/framework/core/Logging.hpp> #include <corsika/framework/core/Logging.hpp>
#include <corsika/framework/utility/CorsikaData.hpp>
#include <boost/filesystem.hpp>
#include <stdexcept> #include <stdexcept>
#include <string> #include <string>
...@@ -18,16 +15,15 @@ ...@@ -18,16 +15,15 @@
namespace corsika { namespace corsika {
inline GeomagneticModel::GeomagneticModel(Point const& center, inline GeomagneticModel::GeomagneticModel(Point const& center,
std::string const& dataFile) boost::filesystem::path const path)
: center_(center) { : center_(center) {
// Read in coefficients // Read in coefficients
boost::filesystem::path const path = corsika::corsika_data(dataFile);
boost::filesystem::ifstream file(path, std::ios::in); boost::filesystem::ifstream file(path, std::ios::in);
// Exit if file opening failed // Exit if file opening failed
if (!file.is_open()) { if (!file.is_open()) {
CORSIKA_LOG_ERROR("Failed opening data file {}", dataFile); CORSIKA_LOG_ERROR("Failed opening data file {}", path);
throw std::runtime_error("Cannot load GeomagneticModel data."); throw std::runtime_error("Cannot load GeomagneticModel data.");
} }
...@@ -93,6 +89,11 @@ namespace corsika { ...@@ -93,6 +89,11 @@ namespace corsika {
} }
} }
file.close(); file.close();
if (parameters_.size() == 0) {
CORSIKA_LOG_ERROR("No input data read!");
throw std::runtime_error("No input data read");
}
} }
inline MagneticFieldVector GeomagneticModel::getField(double const year, inline MagneticFieldVector GeomagneticModel::getField(double const year,
...@@ -101,17 +102,14 @@ namespace corsika { ...@@ -101,17 +102,14 @@ namespace corsika {
double const longitude) { double const longitude) {
int iYear = int(year); int iYear = int(year);
int iEpoch = 0; auto iEpoch = parameters_.rbegin();
for (auto parIt = parameters_.rbegin(); parIt != parameters_.rend(); ++parIt) { for (; iEpoch != parameters_.rend(); ++iEpoch) {
if (parIt->first <= iYear) { if (iEpoch->first <= iYear) { break; }
iEpoch = parIt->first;
break;
}
} }
double epoch = double(iEpoch); CORSIKA_LOG_DEBUG("Found Epoch {} for year {}", iEpoch->first, year);
CORSIKA_LOG_DEBUG("Found Epoch {} for year {}", iEpoch, year); if (iEpoch == parameters_.rend()) {
if (iEpoch == 0) {
CORSIKA_LOG_WARN("Year {} is before first EPOCH. Results unclear.", year); CORSIKA_LOG_WARN("Year {} is before first EPOCH. Results unclear.", year);
iEpoch--; // move one epoch back
} }
if (altitude < -1_km || altitude > 600_km) { if (altitude < -1_km || altitude > 600_km) {
CORSIKA_LOG_WARN("Altitude should be between -1_km and 600_km."); CORSIKA_LOG_WARN("Altitude should be between -1_km and 600_km.");
...@@ -125,6 +123,7 @@ namespace corsika { ...@@ -125,6 +123,7 @@ namespace corsika {
if (longitude < -180 || longitude > 180) { if (longitude < -180 || longitude > 180) {
CORSIKA_LOG_WARN("Longitude should be between -180 and 180 degree."); CORSIKA_LOG_WARN("Longitude should be between -180 and 180 degree.");
} }
double epoch = double(iEpoch->first);
const double lat_geo = latitude * constants::pi / 180; const double lat_geo = latitude * constants::pi / 180;
const double lon = longitude * constants::pi / 180; const double lon = longitude * constants::pi / 180;
...@@ -142,17 +141,23 @@ namespace corsika { ...@@ -142,17 +141,23 @@ namespace corsika {
double legendre, next_legendre, derivate_legendre; double legendre, next_legendre, derivate_legendre;
double magneticfield[3] = {0, 0, 0}; double magneticfield[3] = {0, 0, 0};
for (size_t j = 0; j < parameters_[iEpoch].size(); j++) { for (size_t j = 0; j < iEpoch->second.size(); j++) {
ParameterLine p = parameters_[iEpoch][j]; ParameterLine p = iEpoch->second[j];
// Time interpolation // Time interpolation
p.g = p.g + (year - epoch) * p.dg; if (iEpoch == parameters_.rbegin() || p.dg != 0 || p.dh != 0) {
p.h = p.h + (year - epoch) * p.dh; // this is the latest epoch in time, or time-dependence (dg/dh) was specified
if (iEpoch < 2020) { // we use the extrapolation factors dg/dh:
ParameterLine next_p = parameters_[iEpoch + 5][j]; p.g = p.g + (year - epoch) * p.dg;
p.g = p.g + (next_p.g - p.g) * (year - epoch) / 5; p.h = p.h + (year - epoch) * p.dh;
p.h = p.h + (next_p.h - p.h) * (year - epoch) / 5; } else {
// we linearly interpolate between two epochs
auto const nextEpoch = --iEpoch; // next epoch
ParameterLine const next_p = nextEpoch->second[j];
const double length = nextEpoch->first - epoch;
p.g = p.g + (next_p.g - p.g) * (year - epoch) / length;
p.h = p.h + (next_p.h - p.h) * (year - epoch) / length;
} }
legendre = pow(-1, p.m) * std::assoc_legendre(p.n, p.m, sin(lat_sph)); legendre = pow(-1, p.m) * std::assoc_legendre(p.n, p.m, sin(lat_sph));
......
...@@ -10,7 +10,9 @@ ...@@ -10,7 +10,9 @@
#include <corsika/framework/core/PhysicalUnits.hpp> #include <corsika/framework/core/PhysicalUnits.hpp>
#include <corsika/framework/geometry/PhysicalGeometry.hpp> #include <corsika/framework/geometry/PhysicalGeometry.hpp>
#include <corsika/framework/utility/CorsikaData.hpp>
#include <boost/filesystem.hpp>
#include <fstream> #include <fstream>
#include <string> #include <string>
...@@ -44,7 +46,8 @@ namespace corsika { ...@@ -44,7 +46,8 @@ namespace corsika {
* @param center Center of Earth. * @param center Center of Earth.
* @param data Data table to read. * @param data Data table to read.
*/ */
GeomagneticModel(Point const& center, std::string const& data = "GeoMag/WMM.COF"); GeomagneticModel(Point const& center, boost::filesystem::path const path =
corsika::corsika_data("GeoMag/WMM.COF"));
/** /**
* Calculates the value of the magnetic field. * Calculates the value of the magnetic field.
......
...@@ -12,3 +12,9 @@ set (test_media_sources ...@@ -12,3 +12,9 @@ set (test_media_sources
CORSIKA_ADD_TEST (testMedia SOURCES ${test_media_sources}) CORSIKA_ADD_TEST (testMedia SOURCES ${test_media_sources})
target_link_libraries (testMedia CONAN_PKG::boost) # for math/quadrature/gauss_kronrod.hpp target_link_libraries (testMedia CONAN_PKG::boost) # for math/quadrature/gauss_kronrod.hpp
target_compile_definitions (
testMedia
PRIVATE
REFDATADIR="${CMAKE_CURRENT_SOURCE_DIR}"
)
# no data here...
\ No newline at end of file
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <corsika/framework/core/ParticleProperties.hpp> #include <corsika/framework/core/ParticleProperties.hpp>
#include <corsika/framework/core/PhysicalUnits.hpp> #include <corsika/framework/core/PhysicalUnits.hpp>
#include <corsika/framework/geometry/RootCoordinateSystem.hpp> #include <corsika/framework/geometry/RootCoordinateSystem.hpp>
#include <corsika/framework/utility/CorsikaData.hpp>
#include <corsika/media/HomogeneousMedium.hpp> #include <corsika/media/HomogeneousMedium.hpp>
#include <corsika/media/IMediumModel.hpp> #include <corsika/media/IMediumModel.hpp>
#include <corsika/media/UniformMagneticField.hpp> #include <corsika/media/UniformMagneticField.hpp>
...@@ -19,10 +20,13 @@ ...@@ -19,10 +20,13 @@
#include <SetupTestTrajectory.hpp> #include <SetupTestTrajectory.hpp>
#include <corsika/setup/SetupTrajectory.hpp> #include <corsika/setup/SetupTrajectory.hpp>
#include <boost/filesystem.hpp>
#include <catch2/catch.hpp> #include <catch2/catch.hpp>
using namespace corsika; using namespace corsika;
const std::string refDataDir = std::string(REFDATADIR); // from cmake
TEST_CASE("UniformMagneticField w/ Homogeneous Medium") { TEST_CASE("UniformMagneticField w/ Homogeneous Medium") {
logging::set_level(logging::level::trace); logging::set_level(logging::level::trace);
...@@ -75,15 +79,19 @@ TEST_CASE("UniformMagneticField w/ Homogeneous Medium") { ...@@ -75,15 +79,19 @@ TEST_CASE("UniformMagneticField w/ Homogeneous Medium") {
SECTION("GeomagneticModel") { SECTION("GeomagneticModel") {
CHECK_THROWS(GeomagneticModel(gOrigin, "GeoMag/IDoNotExist.COF")); // non existing data file
CHECK_THROWS(GeomagneticModel(gOrigin, corsika_data("GeoMag/IDoNotExist.COF")));
// and empty data file
CHECK_THROWS(GeomagneticModel(gOrigin, refDataDir + "/EmptyGeomagneticData.COF"));
{ {
GeomagneticModel wmm(gOrigin, "GeoMag/WMM.COF"); GeomagneticModel wmm(gOrigin, corsika_data("GeoMag/WMM.COF"));
// create earth magnetic field vector // create earth magnetic field vector
MagneticFieldVector Earth_B_1 = wmm.getField(2022.5, 100_km, -80, -120); MagneticFieldVector Earth_B_1 = wmm.getField(2022.5, 100_km, -80, -120);
MagneticFieldVector Earth_B_2 = wmm.getField(2022.5, 0_km, 0, 120); MagneticFieldVector Earth_B_2 = wmm.getField(2022.5, 0_km, 0, 120);
MagneticFieldVector Earth_B_3 = wmm.getField(2020, 100_km, 80, 0); MagneticFieldVector Earth_B_3 = wmm.getField(2020, 100_km, 80, 0);
MagneticFieldVector Earth_B_4 = wmm.getField(2019.999, 100_km, 80, 0);
CHECK(Earth_B_1.getX(gCS) / 1_nT == Approx(5815).margin(0.05)); CHECK(Earth_B_1.getX(gCS) / 1_nT == Approx(5815).margin(0.05));
CHECK(Earth_B_1.getY(gCS) / 1_nT == Approx(-14803).margin(0.05)); CHECK(Earth_B_1.getY(gCS) / 1_nT == Approx(-14803).margin(0.05));
CHECK(Earth_B_1.getZ(gCS) / 1_nT == Approx(49755.3).margin(0.05)); CHECK(Earth_B_1.getZ(gCS) / 1_nT == Approx(49755.3).margin(0.05));
...@@ -93,9 +101,12 @@ TEST_CASE("UniformMagneticField w/ Homogeneous Medium") { ...@@ -93,9 +101,12 @@ TEST_CASE("UniformMagneticField w/ Homogeneous Medium") {
CHECK(Earth_B_3.getX(gCS) / 1_nT == Approx(6261.8).margin(0.05)); CHECK(Earth_B_3.getX(gCS) / 1_nT == Approx(6261.8).margin(0.05));
CHECK(Earth_B_3.getY(gCS) / 1_nT == Approx(185.5).margin(0.05)); CHECK(Earth_B_3.getY(gCS) / 1_nT == Approx(185.5).margin(0.05));
CHECK(Earth_B_3.getZ(gCS) / 1_nT == Approx(-52429.1).margin(0.05)); CHECK(Earth_B_3.getZ(gCS) / 1_nT == Approx(-52429.1).margin(0.05));
CHECK(Earth_B_4.getX(gCS) / 1_nT == Approx(6261.8).margin(0.05));
CHECK(Earth_B_4.getY(gCS) / 1_nT == Approx(185.5).margin(0.05));
CHECK(Earth_B_4.getZ(gCS) / 1_nT == Approx(-52429.1).margin(0.05));
} }
{ {
GeomagneticModel igrf(gOrigin, "GeoMag/IGRF13.COF"); GeomagneticModel igrf(gOrigin, corsika_data("GeoMag/IGRF13.COF"));
// create earth magnetic field vector // create earth magnetic field vector
MagneticFieldVector Earth_B_1 = igrf.getField(2022.5, 100_km, -80, -120); MagneticFieldVector Earth_B_1 = igrf.getField(2022.5, 100_km, -80, -120);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment