From 7b4250412210bdcc9fa18b17055ee0fdcf58ec17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Schmidt?= <upwli@student.kit.edu> Date: Wed, 1 Dec 2021 15:33:43 +0000 Subject: [PATCH] Update WMM.hpp --- corsika/media/WMM.hpp | 145 ++++++------------------------------------ 1 file changed, 19 insertions(+), 126 deletions(-) diff --git a/corsika/media/WMM.hpp b/corsika/media/WMM.hpp index 1fa713406..a1f84351a 100644 --- a/corsika/media/WMM.hpp +++ b/corsika/media/WMM.hpp @@ -1,4 +1,3 @@ -<<<<<<< Updated upstream /* * (c) Copyright 2020 CORSIKA Project, corsika-project@lists.kit.edu * @@ -17,129 +16,23 @@ #include <fstream> namespace corsika { - MagneticFieldVector get_wmm(const CoordinateSystemPtr Cs, const double year, const LengthType altitude, const double latitude, const double longitude) { - if (year < 2020 || year > 2025) { - CORSIKA_LOG_ERROR("Year has to be between 2020 and 2025."); - abort(); - } - if (altitude < -1_km || altitude > 850_km) { - CORSIKA_LOG_WARN("Altitude should be between -1_km and 850_km."); - } - if (latitude < -90 || latitude > 90) { - CORSIKA_LOG_ERROR("Latitude has to be between -90 and 90 degree."); - abort(); - } else if (latitude < -89.992 || latitude > 89.992) { - CORSIKA_LOG_WARN("Latitude is close to the poles."); - } - if (longitude < -180 || longitude > 180) { - CORSIKA_LOG_ERROR("Longitude has to be between -180 and 180 degree."); - abort(); - } - - const double lat_geo = latitude * constants::pi / 180; - const double lon = longitude * constants::pi / 180; - - // Transform into spherical coordinates - const double f = 1 / 298.257223563; - const double e_squared = f * (2 - f); - LengthType R_c = constants::EarthRadius::Equatorial / sqrt(1 - e_squared * pow(sin(lat_geo), 2)); - LengthType p = (R_c + altitude) * cos(lat_geo); - LengthType z = sin(lat_geo) * (altitude + R_c * (1 - e_squared)); - LengthType r = sqrt(p * p + z * z); - double lat_sph = asin(z / r); - - const int length = 90; - double epoch, g[length], h[length], g_dot[length], h_dot[length]; - std::string model_name; - std::string release_date; - int n[length], m[length]; - - // Read in coefficients - boost::filesystem::path const path = corsika::corsika_data("GeoMag/WMM.COF"); - boost::filesystem::ifstream file(path, std::ios::in); - // Exit if file opening failed - if (!file.is_open()){ - CORSIKA_LOG_ERROR("Failed opening WMM.COF."); - abort(); - } - - file >> epoch >> model_name >> release_date; - for (int i = 0; i < length; i++) { - file >> n[i] >> m[i] >> g[i] >> h[i] >> g_dot[i] >> h_dot[i]; - // Time interpolation - g[i] = g[i] + (year - epoch) * g_dot[i]; - h[i] = h[i] + (year - epoch) * h_dot[i]; - } - file.close(); - - double legendre, next_legendre, derivate_legendre; - double magneticfield[3] = {0, 0, 0}; - - for (int j = 0; j < length; j++) { - legendre = boost::math::legendre_p(n[j], m[j], sin(lat_sph)); - next_legendre = boost::math::legendre_p(n[j] + 1, m[j], sin(lat_sph)); - - // Schmidt semi-normalization and Condon-Shortley phase term - if (m[j] > 0) { - legendre *= sqrt(2 * boost::math::factorial<double>(n[j] - m[j]) / boost::math::factorial<double>(n[j] + m[j])) * pow(-1, m[j]); - next_legendre *= sqrt(2 * boost::math::factorial<double>(n[j] + 1 - m[j]) / boost::math::factorial<double>(n[j] + 1 + m[j])) * pow(-1, m[j]); - } - derivate_legendre = (n[j] + 1) * tan(lat_sph) * legendre - sqrt(pow(n[j] + 1, 2) - pow(m[j], 2)) / cos(lat_sph) * next_legendre; - - magneticfield[0] += pow(constants::EarthRadius::Geomagnetic_reference / r, n[j] + 2) * (g[j] * cos(m[j] * lon) + h[j] * sin(m[j] * lon)) * derivate_legendre; - magneticfield[1] += pow(constants::EarthRadius::Geomagnetic_reference / r, n[j] + 2) * m[j] * (g[j] * sin(m[j] * lon) - h[j] * cos(m[j] * lon)) * legendre; - magneticfield[2] += (n[j] + 1) * pow(constants::EarthRadius::Geomagnetic_reference / r, n[j] + 2) * (g[j] * cos(m[j] * lon) + h[j] * sin(m[j] * lon)) * legendre; - } - magneticfield[0] *= -1; - magneticfield[1] /= cos(lat_sph); - magneticfield[2] *= -1; - - // Transform back into geodetic coordinates - double magneticfield_geo[3]; - magneticfield_geo[0] = magneticfield[0] * cos(lat_sph - lat_geo) - magneticfield[2] * sin(lat_sph - lat_geo); - magneticfield_geo[1] = magneticfield[1]; - magneticfield_geo[2] = magneticfield[0] * sin(lat_sph - lat_geo) + magneticfield[2] * cos(lat_sph - lat_geo); - - return MagneticFieldVector{Cs, magneticfield_geo[0] * 1_nT, magneticfield_geo[1] * 1_nT, magneticfield_geo[2] * -1_nT}; - } -} -======= -/* - * (c) Copyright 2020 CORSIKA Project, corsika-project@lists.kit.edu - * - * This software is distributed under the terms of the GNU General Public - * Licence version 3 (GPL Version 3). See file LICENSE for a full version of - * the license. - */ - -#include <boost/filesystem.hpp> -#include <boost/math/special_functions/factorials.hpp> -#include <boost/math/special_functions/legendre.hpp> - -#include <cmath> -#include <corsika/framework/core/Logging.hpp> -#include <corsika/framework/utility/CorsikaData.hpp> -#include <fstream> - -namespace corsika { - /** - * A magnetic field calculated with the WMM model - * - * @param year Year of the evaluation, between 2020 and 2025. - * @param altitude Height of the location to evaluate the field at, - in km between -1 and 850. - * @param latitude Latitude of the location to evaluate the field at, - in degrees between -90 and 90 (negative for southern hemisphere). - * @param longitute Longitude of the location to evaluate the field at, - in degrees between -180 and 180 (negative for western hemisphere). - * - * @returns The magnetic field vector in nT. - * - */ - - inline MagneticFieldVector get_wmm(const CoordinateSystemPtr Cs, const double year, - const LengthType altitude, const double latitude, const double longitude); -} // namespace corsika - + /** + * A magnetic field calculated with the WMM model + * + * @param year Year of the evaluation, between 2020 and 2025. + * @param altitude Height of the location to evaluate the field at, + in km between -1 and 850. + * @param latitude Latitude of the location to evaluate the field at, + in degrees between -90 and 90 (negative for southern hemisphere). + * @param longitute Longitude of the location to evaluate the field at, + in degrees between -180 and 180 (negative for western hemisphere). + * + * @returns The magnetic field vector in nT. + * + */ + + inline MagneticFieldVector get_wmm(const CoordinateSystemPtr Cs, const double year, + const LengthType altitude, const double latitude, const double longitude); +} // namespace corsika + #include <corsika/detail/media/WMM.inl> ->>>>>>> Stashed changes -- GitLab