/* * LogicalDataType.hh * @brief is a complement of ParamData.hh, contain mathematics function between ParamData element * @see paramData.hh * Created on: Dec 21, 2012 * Author: f.casimir */ #ifndef LOGICALDATATYPE_HH_ #define LOGICALDATATYPE_HH_ #define MU_0 1.25664e-06 #define RE 6.3712e+06 #include #include #include #include "ParamData.hh" #include "AMDA_constants.hh" inline AMDA::Parameters::LogicalData castToLogicalData(int a) { if (isNAN(a)) { return AMDA::Parameters::LogicalData::NaN; } return (a >= 1) ? AMDA::Parameters::LogicalData::True : AMDA::Parameters::LogicalData::False; } inline AMDA::Parameters::LogicalData castToLogicalData(AMDA::Parameters::LogicalData a) { return a; } /** * @brief Operator And (&&) between LogicalData */ template inline AMDA::Parameters::LogicalData And(Type1 a, Type2 b) { AMDA::Parameters::LogicalData aa = castToLogicalData(a); AMDA::Parameters::LogicalData bb = castToLogicalData(b); AMDA::Parameters::LogicalData res = AMDA::Parameters::LogicalData::NaN; if (aa != AMDA::Parameters::LogicalData::NaN && bb != AMDA::Parameters::LogicalData::NaN) { res = ((aa == AMDA::Parameters::LogicalData::True) && (bb == AMDA::Parameters::LogicalData::True)) ? AMDA::Parameters::LogicalData::True : AMDA::Parameters::LogicalData::False; } return res; } /** * @brief Operator Or (||) between LogicalData */ template inline AMDA::Parameters::LogicalData Or(Type1 a, Type2 b) { AMDA::Parameters::LogicalData aa = castToLogicalData(a); AMDA::Parameters::LogicalData bb = castToLogicalData(b); AMDA::Parameters::LogicalData res = AMDA::Parameters::LogicalData::NaN; if (aa != AMDA::Parameters::LogicalData::NaN && bb != AMDA::Parameters::LogicalData::NaN) { res = ((aa == AMDA::Parameters::LogicalData::True) || (bb == AMDA::Parameters::LogicalData::True)) ? AMDA::Parameters::LogicalData::True : AMDA::Parameters::LogicalData::False; } return res; } /** * @brief Operator greater_than (>) between LogicalData */ template AMDA::Parameters::LogicalData greater_than(Type1 a, Type2 b) { AMDA::Parameters::LogicalData res = AMDA::Parameters::LogicalData::True; if (std::isfinite(a) && std::isfinite(b)) { res = (a > b) ? AMDA::Parameters::LogicalData::True : AMDA::Parameters::LogicalData::False; } else { res = AMDA::Parameters::LogicalData::NaN; } return res; } /** * @brief Operator greater_than (>) between table of LogicalData */ template std::vector greater_than(std::vector a, std::vector b) { std::vector r; if (a.size() != b.size()) { BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Logical comparison between two vector of different size")); } for (unsigned int i = 0; i < a.size(); ++i) { r.push_back(greater_than(a[i], b[i])); } return r; } /** * @brief Operator lower_than (<) between table of LogicalData */ template AMDA::Parameters::LogicalData lower_than(Type1 a, Type2 b) { AMDA::Parameters::LogicalData res = AMDA::Parameters::LogicalData::True; if (std::isfinite(a) && std::isfinite(b)) { res = (a < b) ? AMDA::Parameters::LogicalData::True : AMDA::Parameters::LogicalData::False; } else { res = AMDA::Parameters::LogicalData::NaN; } return res; } /** * @brief Operator lower_than (<) between table of LogicalData */ template std::vector lower_than(std::vector a, std::vector b) { std::vector r; if (a.size() != b.size()) { BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Logical comparison between two vector of different size")); } for (unsigned int i = 0; i < a.size(); ++i) { r.push_back(lower_than(a[i], b[i])); } return r; } /** * @brief Operator * between two scalars, one is LogicalData */ template Type operator*(Type a, AMDA::Parameters::LogicalData b) { Type r; r << NotANumber(); if (isNAN(a) || isNAN(b)) { return r; } r = a * (Type) b; return r; } template Type operator*(AMDA::Parameters::LogicalData a, Type b) { return b * a; } /** * @brief Operator / between two scalars, one is LogicalData */ template Type operator/(Type a, AMDA::Parameters::LogicalData b) { Type r; r << NotANumber(); if (isNAN(a) || isNAN(b) || (b == AMDA::Parameters::LogicalData::False)) { return r; } r = a / (Type) b; return r; } template Type operator/(AMDA::Parameters::LogicalData a, Type b) { Type r; r << NotANumber(); if (isNAN(a) || isNAN(b) || (b == 0)) { return r; } r = (Type) a / b; return r; } /** * @brief Operator + between two scalars, one is LogicalData */ template Type operator+(Type a, AMDA::Parameters::LogicalData b) { Type r; r << NotANumber(); if (isNAN(a) || isNAN(b)) { return r; } r = a + (Type) b; return r; } template Type operator+(AMDA::Parameters::LogicalData a, Type b) { return b + a; } /** * @brief Operator - between two scalars, one is LogicalData */ template Type operator-(Type a, AMDA::Parameters::LogicalData b) { Type r; r << NotANumber(); if (isNAN(a) || isNAN(b)) { return r; } r = a - (Type) b; return r; } template Type operator-(AMDA::Parameters::LogicalData a, Type b) { Type r; r << NotANumber(); if (isNAN(a) || isNAN(b)) { return r; } r = (Type) a - b; return r; } /** * @brief Operator addition between two vector * @details * r[0] = a[0] + b[0] * r[1] = a[1] + b[1] * r[2] = a[2] + b[2] * @return r */ template std::vector operator+(std::vector a, std::vector b) { std::vector r; if (a.size() != b.size()) { BOOST_THROW_EXCEPTION(AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Add two vector of different size")); } for (unsigned int i = 0; i < a.size(); ++i) { r.push_back((Type1) (a[i] + b[i])); } return r; } /** * @brief Operator subtraction between two vector * @details * r[0] = a[0] - b[0] * r[1] = a[1] - b[1] * r[2] = a[2] - b[2] * @return r */ template std::vector operator-(std::vector a, std::vector b) { std::vector r; if (a.size() != b.size()) { BOOST_THROW_EXCEPTION(AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Subtract two vector of different size")); } for (unsigned int i = 0; i < a.size(); ++i) { r.push_back(a[i] - b[i]); } return r; } /** * @brief Operator dot product between two vector * @details * r = a[0]*b[0] + a[1]*b[1] + a[2]+b[2] * @return the scalar r */ template Type1 operator*(std::vector a, std::vector b) { Type1 r = 0; if (a.size() != b.size()) { BOOST_THROW_EXCEPTION(AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Multiply two vector of different size")); } for (unsigned int i = 0; i < a.size(); ++i) { r += a[i] * b[i]; } return r; } /** * @brief Function dot between two vectors can be used for dot product */ template Type1 dot(std::vector a, std::vector b) { return a*b; } template Type magnitude(std::vector a) { Type mag = 0; for (unsigned int i = 0; i < a.size(); ++i) mag += a[i] * a[i]; return std::sqrt(mag); } template Type1 angle(std::vector a, std::vector b) { if (magnitude(a) == 0 || magnitude(b) == 0) { BOOST_THROW_EXCEPTION(AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("One of the two vectors is NULL")); } Type1 res; if (dot(a, b) / magnitude(a) / magnitude(b) > 0.99999) { res = 0; } else { res = std::acos(dot(a, b) / magnitude(a) / magnitude(b)); } return res; } /** * @brief alfvenVelocity : args magnetic field magnitude and density * @details * * standard : V (m/s) = mag (T) / std::sqrt(MU_0 * density ( kg/m^3)) * our : V (km/s) = K * mag (nT) / sqrt(density ( 1/cm^3)) assuming mass of proton */ template Type1 alfvenVelocity(Type1 density, Type2 mag) { Type1 val; if (density <= 0) { val << NotANumber(); } else { val = 21.83 * mag / std::sqrt(density); } return val; } /** * @brief FAIRFIELD 1970 model of neutral sheet position * @details * z_sm-std::sqrt(pow(11.0, 2.0) - pow(11.0, 2.0) / pow(15.0, 2.0) * pow(y_sm, 2.0)) * std::sin(x_ss); * where y_sm and z_sm are the solar magnetospheric coordinates of the spacecraft and x_ss is geomagnetic latitude of the sun (tilt angle) template Type1 fairfield70(Type1 y_sm, Type2 z_sm,Type3 x_ss) { Type1 val = z_sm-std::sqrt(pow(11.0, 2.0) - pow(11.0, 2.0) / pow(15.0, 2.0) * pow(y_sm, 2.0)) * std::sin(x_ss); return val; } * */ /** * @brief FAIRFIELD 1970 model of neutral sheet position : ..sqrt(11^2 - 11^2/15^2*y^2)... * @param xyz_sm SM coordinates of the sat * @param x_ss tilt Angle ( deg ) * @return delta Z */ template Type1 fairfield70(std::vector xyz_sm, Type2 x_ss) { Type1 val = xyz_sm[2] - std::sqrt(121.0 - 0.537778 * pow(xyz_sm[1], 2.0)) * std::sin(x_ss * DEG2RAD); return val; } /** * @brief FAIRFIELD 1980 model of neutral sheet position * @param xyz_sm SM coordinates of the sat * @param x_ss tilt Angle * @return delta Z */ template Type1 fairfield80(std::vector xyz_sm, Type2 x_ss) { Type1 val = xyz_sm[2] - 10.5 * std::sqrt(1.0 - pow(xyz_sm[1], 2.0) / 289.0) * std::sin(x_ss * DEG2RAD); return val; } /** * @brief Perrault and Akasofu 1978 geomagnetic storms * @details * u(t) = E_mag(t)*B_mag(t)/4pi(7RE sin²(theta_p(t)/2))² * where u(t) is total energy dissipation * E_mag(t) The magnitude of the solar-wind electric field * theta_p is a measure of the angle between the geomagnetic field vector and the IMF vector at the front of the * B_mag(t) The magnitude of the IMF magnetosphere in the equatorial plane. theta_p = pi/2 -theta where theta * denotes the latitudinal angle of the IMF vector measured from the solar equatorial plane. */ template Type1 perreault78(Type1 E_mag, Type2 B_mag, Type3 theta_p) { Type1 val = E_mag * B_mag / (4 * std::atan(1)*4) * std::pow((7 * RE * std::pow(sin(theta_p / 2), 2)), 2); return val; } /** * @brief NEWELL et al 2007 solar wind-magnetosphere coupling function * @details d_phi/d_t = mu^4/3*Bt^2/3*sin(theta/2)^8/3 * where mu is rate IMF field lines approach the magnetopause * B_mag interplanetary field magnitude, * theta IMF clock angle arctan(By/Bz) */ template Type1 newell2007(Type1 mu, std::vector Bxyz) { Type2 B_mag = std::sqrt(Bxyz[0] * Bxyz[0] + Bxyz[1] * Bxyz[1] + Bxyz[2] * Bxyz[2]); Type2 theta = std::atan2(Bxyz[1] / Bxyz[2]); Type1 val = std::pow(mu, 4.0 / 3.0) * std::pow(B_mag, 2.0 / 3.0) * pow(std::sin(theta / 2), 8.0 / 3.0); return val; } /** * @brief Lopez 1990 model of magnetic latitude of the neutral sheet * @details *MLAT = -(0.14*Kp+0.69)*std::pow(phi, 1.0/3.0)*(0.065*R-0.16)*DTA; * where Kp is the 3-hour magnetic index, phi the magnetic local time in degrees (phi = 0° at midnight) * R is the radial distance in RE and DTA is the dipole tilt angle */ template Type1 lopez90(Type1 Kp, Type2 phi, Type3 R, Type4 DTA) { Type1 val = -(0.14 * Kp + 0.69) * std::pow(phi, 0.3333)*(0.065 * R - 0.16) * DTA*DEG2RAD; return val; } template Type1 pv_ionos_te(Type1 alt, Type2 sza) { Type1 te; if (alt > 3000 || alt < 150) { te << NotANumber(); return te; } else { std::vector pb; pb.resize(4); // 0 was added to fdsmodt in order to keep indexes as in fortran original source const std::vector< double> fdsmodt{0, 3.567296, 1.3836078e-02, 1.5086544e-02, 6.0729804e-03, 4.0306677e-03, -1.3217842e-02, 7.8089219e-03, -2775.023, -123.7310, 8.828382, -96.94563, 15.84634, 138.9812, -139.7511, -84.03277, 0.2649297, -1.444215, 0.6347786, -2.192531, -0.5396207, 0.6054179, 1.0569388e-04, -8.0908003e-06, 1.3877957e-05, -1.2327257e-05, -1.1256760e-05, 1.3830228e-05, -1.4350858e-05}; double s = std::sin(sza); double c = std::cos(sza); double s2 = std::sin(2 * sza); double c2 = std::cos(2 * sza); double s3 = std::sin(3 * sza); double c3 = std::cos(3 * sza); for (int j = 1; j < 5; j++) { int k = 7 * j; pb[j - 1] = fdsmodt[k - 6] + fdsmodt[k - 5] * s + fdsmodt[k - 4] * c + fdsmodt[k - 3] * s2 + fdsmodt[k - 2] * c2 + fdsmodt[k - 1] * s3 + fdsmodt[k] * c3; } te = (Type1) pb[0] + pb[1] / ((alt + pb[2])*(alt + pb[2])) + pb[3] * alt; return te; } } template Type1 pv_ionos_dn(Type1 alt, Type2 sza) { Type1 dn; if (alt > 3000 || alt < 150) { dn << NotANumber(); return dn; } else { std::vector bp; bp.resize(4); // 0 was added to fdsmodde in order to keep indexes as in fortran original source const std::vector fdsmodde{0, 5.334022, 252.5587, 120.4444, 9.1163822E-02, -6.195264, 37.38898, 3.331818, 245.5529, 0.7587564, 0.1453792, -0.9461438, 127.1485, -0.3391595, 2.4936652E-02, 0.1879423, -5.3126566E-02, 2.9439656E-02, 1.654282, 415.7859, 2.6281483E-02, 145.3951, 2.045347, 0.4421963, 3.036170, 9.1009791E-04, 141.5824}; double s2 = std::sin(sza) * std::sin(sza); double szap = sza * (1. - fdsmodde[23] * s2 * std::exp(-fdsmodde[24] * s2 - fdsmodde[25]*(alt - fdsmodde[26])*(alt - fdsmodde[26]))); double sinz = std::sin(fdsmodde[18] + szap); double s = fdsmodde[1] + fdsmodde[2] / (alt - fdsmodde[3]) + sinz * fdsmodde[13] + fdsmodde[19] * std::exp(-fdsmodde[20]*((alt - fdsmodde[21])*(alt - fdsmodde[21])) - fdsmodde[22] * szap * szap); double o = fdsmodde[4] + fdsmodde[5] / (alt - fdsmodde[6]) + sinz * fdsmodde[14]; double c = fdsmodde[7] + fdsmodde[8] / (alt - fdsmodde[9]) + sinz * fdsmodde[15]; double m = fdsmodde[10] + fdsmodde[11] / (alt - fdsmodde[12]) + sinz * fdsmodde[16]; double ss = s * cos(fdsmodde[17] + szap); double calc = (1.77245 * ss * erfc(-ss) + std::exp(-ss * ss) + o); if (calc <= 0) calc = 0.00001; dn = (Type1) c + m * log(calc); return dn; } } /** * @brief Operator cross product between two vector * @details * r[0] = a[1]*b[2] - a[2]*b[1] * r[1] = a[2]*b[0] - a[0]*b[2] * r[2] = a[0]*b[1] - a[1]*b[0] * @return r */ template std::vector operator ^(std::vector a, std::vector b) { std::vector r; if (a.size() != b.size() || b.size() != 3) { BOOST_THROW_EXCEPTION(AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Vector product on two vector of different size")); } r.push_back(a[1] * b[2] - a[2] * b[1]); r.push_back(a[2] * b[0] - a[0] * b[2]); r.push_back(a[0] * b[1] - a[1] * b[0]); return r; } /** * @brief Function cross between two vectors can be used for cross product */ template std::vector cross(std::vector a, std::vector b) { return a^b; } /** * @brief div each coordinate one to one * @details * r[0] = a[0] / b[0] * r[1] = a[1] / b[1] * r[2] = a[2] / b[2] */ template std::vector div(std::vector a, std::vector b) { std::vector r; if (a.size() != b.size()) { BOOST_THROW_EXCEPTION(AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Vector div on two vector of different size")); } for (unsigned int i = 0; i < a.size(); ++i) { r.push_back(a[i] / b[i]); } return r; } // //Idea but more complex: template //auto operator ^(std::vector a, std::vector b) -> std::vector { // std::vector r; // Idea but more complex: template // double operator ^(Type1 a, Type2 b) { // return pow(a, b); // } // class Integer { // public: // Integer(int i) : _i(i) {}; // int _i; // }; // // inline double operator ^(double a, Integer b) { // return pow(a, b._i); // } // // // class Double { // public: // Double(double i) : _i(i) {}; // double _i; // }; // inline double operator ^(double a, Double b) { // return pow(a, b._i); // } // vector with scalar operation /** * @brief Operator division between a vector and a scalar * @details all member of vector are divided by the scalar */ template std::vector operator/(std::vector a, Type2 b) { std::vector r; for (typename std::vector::iterator it = a.begin(); it != a.end(); ++it) { r.push_back((Type1) (*it / b)); } return r; } /** * @brief Operator division between a scalar and a vector * @details apply the division on each vector component */ template std::vector operator/(Type1 a, std::vector b) { std::vector r; for (typename std::vector::iterator it = b.begin(); it != b.end(); ++it) { r.push_back((Type2) (a / *it)); } return r; } /** * @brief Operator addition between a vector and a scalar * @details all member of vector are added with the scalar */ template std::vector operator+(std::vector a, Type2 b) { std::vector r; for (typename std::vector::iterator it = a.begin(); it != a.end(); ++it) { r.push_back((Type1) (*it + b)); } return r; } /** * @brief Operator addition between a scalar and a vector * @details all member of vector are added with the scalar */ template std::vector operator+(Type1 a, std::vector b) { std::vector r; for (typename std::vector::iterator it = b.begin(); it != b.end(); ++it) { r.push_back((Type2) (a + *it)); } return r; } /** * @brief Operator subtraction between a vector and a scalar * @details scalar is substracted to all vector components */ template std::vector operator-(std::vector a, Type2 b) { std::vector r; for (typename std::vector::iterator it = a.begin(); it != a.end(); ++it) { r.push_back((Type1) (*it - b)); } return r; } /** * @brief Operator subtraction between a scalar and a vector * @details all member of vector are subtracted with the scalar */ template std::vector operator-(Type1 a, std::vector b) { std::vector r; for (typename std::vector::iterator it = b.begin(); it != b.end(); ++it) { r.push_back((Type2) (a - *it)); } return r; } /** * @brief Operator product between a vector and a scalar * @details product applied in all member of vector */ template std::vector operator*(std::vector a, Type2 b) { std::vector r; for (typename std::vector::iterator it = a.begin(); it != a.end(); ++it) { r.push_back((Type1) ((*it) * b)); } return r; } /** * @brief Operator product between a scalar and a vector * @details all member of vector are added by the scalar */ template std::vector operator*(Type1 a, std::vector b) { std::vector r; for (typename std::vector::iterator it = b.begin(); it != b.end(); ++it) { r.push_back((Type2) (a * (*it))); } return r; } /** * @return false if val is NaN or inf or -inf */ template inline bool isFinite(Type val) { return std::isfinite(val); } inline bool isFinite(AMDA::Parameters::LogicalData val) { return !isNAN(val); } /** * @return false if elem of val is NaN or inf or -inf */ template inline bool isFinite(std::vector val) { bool ret = false; auto it = val.begin(); while (it != val.end() && !ret) { ret &= std::isfinite(*it); ++it; } return ret; } /** * @return false if elem of val is NaN or inf or -inf */ template inline bool isFinite(const AMDA::Parameters::Tab2DData& val) { bool ret = false; for (int i = 0; i < val.getDim1Size(); ++i) for (int j = 0; j < val.getDim2Size(); ++j) ret &= std::isfinite(val[i][j]); return ret; } /** * @return the average of std::list */ template inline Type average(std::list tab, int /*dim1*/, int /*dim2*/) { Type mean; if (tab.empty()) { mean << NotANumber(); } else { mean << ElemNull(); auto it = tab.begin(); if (it != tab.end()) { unsigned int nbNan = 0; Type sum; sum << NotANumber(); for (; it != tab.end(); ++it) { if (isFinite(*it) && !isNAN(*it)) { if (isNAN(sum)) sum = *it; else sum = sum + *it; } else { ++nbNan; } } if ((tab.size() - nbNan == 0) || isNAN(sum)) { mean << NotANumber(); } else { mean = sum / (int) (tab.size() - nbNan); } } else { mean << NotANumber(); } } return mean; } inline AMDA::Parameters::LogicalData average(std::list /*tab*/, int /*dim1*/, int /*dim2*/) { AMDA::Parameters::LogicalData mean; mean << NotANumber(); return mean; } template inline AMDA::Parameters::Tab2DData average(std::list > tab, int dim1, int dim2) { AMDA::Parameters::Tab2DData mean(dim1, dim2); AMDA::Parameters::Tab2DData nbNan(dim1, dim2); AMDA::Parameters::Tab2DData sum(dim1, dim2); if (tab.empty()) { mean << NotANumber(); return mean; } for (int index1 = 0; index1 < dim1; ++index1) { for (int index2 = 0; index2 < dim2; ++index2) { nbNan[index1][index2] = 0; } } sum << NotANumber(); for (auto it = tab.begin(); it != tab.end(); ++it) { for (int index1 = 0; index1 < dim1; ++index1) { for (int index2 = 0; index2 < dim2; ++index2) { Type val = (*it)[index1][index2]; if (std::isfinite(val) && !isNAN(val)) { if (isNAN(sum[index1][index2])) sum[index1][index2] = val; else sum[index1][index2] += val; } else { ++(nbNan[index1][index2]); } } } } for (int index1 = 0; index1 < dim1; ++index1) { for (int index2 = 0; index2 < dim2; ++index2) { if (tab.size() - nbNan[index1][index2] == 0) { mean[index1][index2] << NotANumber(); } else { mean[index1][index2] = sum[index1][index2] / (int) (tab.size() - nbNan[index1][index2]); } } } return mean; } inline AMDA::Parameters::Tab2DData average(std::list> /*tab*/, int dim1, int dim2) { AMDA::Parameters::Tab2DData mean(dim1, dim2); mean << NotANumber(); return mean; } /** * @return the average of std::list */ template inline std::vector average(std::list > tab, int dim1, int /*dim2*/) { std::vector mean; mean.resize(dim1); std::vectornbNan; nbNan.resize(dim1); std::vector sum; sum.resize(dim1); if (tab.empty()) { mean << NotANumber(); return mean; } for (unsigned int index = 0; index < tab.begin()->size(); ++index) { nbNan[index] = 0; } sum << NotANumber(); for (auto it = tab.begin(); it != tab.end(); ++it) { for (unsigned int index = 0; index < it->size(); ++index) { Type val = it->at(index); if (std::isfinite(val) && !isNAN(val)) { if (isNAN(sum[index])) sum[index] = val; else sum[index] += val; } else { ++(nbNan[index]); } } } for (unsigned int index = 0; index < tab.begin()->size(); ++index) { if (tab.size() - nbNan[index] == 0) { mean[index] << NotANumber(); } else { mean[index] = sum[index] / (int) (tab.size() - nbNan[index]); } } return mean; } inline std::vector average(std::list> /*tab*/, int dim1, int /*dim2*/) { std::vector mean; mean.resize(dim1); mean << NotANumber(); return mean; } /** * */ template inline Type interpolation(const Type& leftVal, const Type& rightVal, double coef, int /*dim1*/, int /*dim2*/) { Type val; val << NotANumber(); if (isNAN(leftVal) || isNAN(rightVal) || coef < 0. || coef > 1.) return val; val = leftVal + (rightVal - leftVal) * coef; return val; } inline AMDA::Parameters::LogicalData interpolation(const AMDA::Parameters::LogicalData& leftVal, const AMDA::Parameters::LogicalData& rightVal, double /*coef*/, int /*dim1*/, int /*dim2*/) { AMDA::Parameters::LogicalData val; if (leftVal == rightVal) { val = leftVal; } else { val << NotANumber(); } return val; } /** * */ template inline AMDA::Parameters::Tab2DData interpolation(const AMDA::Parameters::Tab2DData& leftVal, const AMDA::Parameters::Tab2DData& rightVal, double coef, int dim1, int dim2) { AMDA::Parameters::Tab2DData val(dim1, dim2); val << NotANumber(); for (int index1 = 0; index1 < dim1; ++index1) { for (int index2 = 0; index2 < dim2; ++index2) { Type leftValComp = leftVal[index1][index2]; Type rightValComp = rightVal[index1][index2]; val[index1][index2] = interpolation(leftValComp, rightValComp, coef, 1, 1); } } return val; } template inline std::vector interpolation(const std::vector& leftVal, const std::vector& rightVal, double coef, int dim1, int /*dim2*/) { std::vector val; val.resize(dim1); val << NotANumber(); for (int index = 0; index < dim1; ++index) { Type leftValComp = leftVal[index]; Type rightValComp = rightVal[index]; val[index] = interpolation(leftValComp, rightValComp, coef, 1, 1); } return val; } /** * @brief Operator + between Tab2D and scalar */ template AMDA::Parameters::Tab2DData operator+(const AMDA::Parameters::Tab2DData& a, Type2 b) { AMDA::Parameters::Tab2DData r(a); if (isNAN(b)) { r << NotANumber(); return r; } for (int i = 0; i < r.getDim1Size(); ++i) for (int j = 0; j < r.getDim2Size(); ++j) { if (!isNAN(r[i][j])) r[i][j] += b; } return r; } template AMDA::Parameters::Tab2DData operator+(Type1 a, const AMDA::Parameters::Tab2DData& b) { return (b + a); } /** * @brief Operator - between Tab2D and scalar */ template AMDA::Parameters::Tab2DData operator-(const AMDA::Parameters::Tab2DData& a, Type2 b) { return (a + (-b)); } template AMDA::Parameters::Tab2DData operator-(Type1 a, const AMDA::Parameters::Tab2DData& b) { AMDA::Parameters::Tab2DData r(b); if (isNAN(a)) { r << NotANumber(); return r; } for (int i = 0; i < r.getDim1Size(); ++i) for (int j = 0; j < r.getDim2Size(); ++j) { if (!isNAN(r[i][j])) r[i][j] = a - r[i][j]; } return r; } /** * @brief Operator * between Tab2D and scalar */ template AMDA::Parameters::Tab2DData operator*(const AMDA::Parameters::Tab2DData& a, Type2 b) { AMDA::Parameters::Tab2DData r(a); if (isNAN(b)) { r << NotANumber(); return r; } for (int i = 0; i < r.getDim1Size(); ++i) for (int j = 0; j < r.getDim2Size(); ++j) { if (!isNAN(r[i][j])) r[i][j] *= b; } return r; } template AMDA::Parameters::Tab2DData operator*(Type1 a, const AMDA::Parameters::Tab2DData& b) { return (b * a); } /** * @brief Operator / between Tab2D and scalar */ template AMDA::Parameters::Tab2DData operator/(const AMDA::Parameters::Tab2DData& a, Type2 b) { if (b == 0) { AMDA::Parameters::Tab2DData r(a); r << NotANumber(); return r; } return (a * (1. / b)); } template AMDA::Parameters::Tab2DData operator/(Type1 a, const AMDA::Parameters::Tab2DData& b) { AMDA::Parameters::Tab2DData r(b); if (isNAN(a)) { r << NotANumber(); return r; } for (int i = 0; i < r.getDim1Size(); ++i) for (int j = 0; j < r.getDim2Size(); ++j) { if (isNAN(r[i][j]) || (r[i][j] == 0)) r[i][j] << NotANumber(); else r[i][j] = a / r[i][j]; } return r; } /* * @brief Function add between a Tab2D and a vector */ template AMDA::Parameters::Tab2DData add(const AMDA::Parameters::Tab2DData& a, std::vector b, int mode) { AMDA::Parameters::Tab2DData r(a); switch (mode) { case 1: if (r.getDim1Size() != b.size()) { BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Operation not allowed due to incompatibility in data dimensions")); } for (int i = 0; i < r.getDim1Size(); ++i) for (int j = 0; j < r.getDim2Size(); ++j) { if (isNAN(r[i][j]) || isNAN(b[i])) r[i][j] << NotANumber(); else r[i][j] += b[i]; } break; case 2: if (r.getDim2Size() != b.size()) { BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Operation not allowed due to incompatibility in data dimensions")); } for (int i = 0; i < r.getDim1Size(); ++i) for (int j = 0; j < r.getDim2Size(); ++j) { if (isNAN(r[i][j]) || isNAN(b[j])) r[i][j] << NotANumber(); else r[i][j] += b[j]; } break; default: BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Operation not allowed due a not implemented mode")); } return r; } template AMDA::Parameters::Tab2DData add(std::vector a, const AMDA::Parameters::Tab2DData& b, int mode) { return add(b, a, mode); } /** * @brief Operator + between Tab2D and vector */ template AMDA::Parameters::Tab2DData operator+(const AMDA::Parameters::Tab2DData& a, std::vector b) { return add(a, b, 1); } template AMDA::Parameters::Tab2DData operator+(std::vector a, const AMDA::Parameters::Tab2DData& b) { return add(a, b, 1); } /** * @brief Function sub between Tab2D and vector */ template AMDA::Parameters::Tab2DData sub(const AMDA::Parameters::Tab2DData& a, std::vector b, int mode) { return add(a, (-1) * b, mode); } template AMDA::Parameters::Tab2DData sub(std::vector a, const AMDA::Parameters::Tab2DData& b, int mode) { AMDA::Parameters::Tab2DData r(b); switch (mode) { case 1: if (r.getDim1Size() != a.size()) { BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Operation not allowed due to incompatibility in data dimensions")); } for (int i = 0; i < r.getDim1Size(); ++i) for (int j = 0; j < r.getDim2Size(); ++j) { if (isNAN(r[i][j]) || isNAN(a[i])) r[i][j] << NotANumber(); else r[i][j] = a[i] - r[i][j]; } break; case 2: if (r.getDim2Size() != a.size()) { BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Operation not allowed due to incompatibility in data dimensions")); } for (int i = 0; i < r.getDim1Size(); ++i) for (int j = 0; j < r.getDim2Size(); ++j) { if (isNAN(r[i][j]) || isNAN(a[j])) r[i][j] << NotANumber(); else r[i][j] = a[j] - r[i][j]; } break; default: BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Operation not allowed due a not implemented mode")); } return r; } /** * @brief Operator - between Tab2D and vector */ template AMDA::Parameters::Tab2DData operator-(const AMDA::Parameters::Tab2DData& a, std::vector b) { return sub(a, b, 1); } template AMDA::Parameters::Tab2DData operator-(std::vector a, const AMDA::Parameters::Tab2DData& b) { return sub(a, b, 1); } /** * @brief Function mult between Tab2D and vector */ template AMDA::Parameters::Tab2DData mult(const AMDA::Parameters::Tab2DData& a, std::vector b, int mode) { AMDA::Parameters::Tab2DData r(a); switch (mode) { case 1: if (r.getDim1Size() != b.size()) { BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Operation not allowed due to incompatibility in data dimensions")); } for (int i = 0; i < r.getDim1Size(); ++i) for (int j = 0; j < r.getDim2Size(); ++j) { if (isNAN(r[i][j]) || isNAN(b[i])) r[i][j] << NotANumber(); else r[i][j] *= b[i]; } break; case 2: if (r.getDim2Size() != b.size()) { BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Operation not allowed due to incompatibility in data dimensions")); } for (int i = 0; i < r.getDim1Size(); ++i) for (int j = 0; j < r.getDim2Size(); ++j) { if (isNAN(r[i][j]) || isNAN(b[j])) r[i][j] << NotANumber(); else r[i][j] *= b[j]; } break; default: BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Operation not allowed due a not implemented mode")); } return r; } template AMDA::Parameters::Tab2DData mult(std::vector a, const AMDA::Parameters::Tab2DData& b, int mode) { return mult(b, a, mode); } /** * @brief Operator * between Tab2D and vector */ template AMDA::Parameters::Tab2DData operator*(const AMDA::Parameters::Tab2DData& a, std::vector b) { return mult(a, b, 1); } template AMDA::Parameters::Tab2DData operator*(std::vector a, const AMDA::Parameters::Tab2DData& b) { return mult(b, a, 1); } /** * @brief Function div between Tab2D and vector */ template AMDA::Parameters::Tab2DData div(const AMDA::Parameters::Tab2DData& a, std::vector b, int mode) { AMDA::Parameters::Tab2DData r(a); switch (mode) { case 1: if (r.getDim1Size() != b.size()) { BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Operation not allowed due to incompatibility in data dimensions")); } for (int i = 0; i < r.getDim1Size(); ++i) for (int j = 0; j < r.getDim2Size(); ++j) { if (isNAN(r[i][j]) || isNAN(b[i]) || (b[i] == 0)) r[i][j] << NotANumber(); else r[i][j] = r[i][j] / b[i]; } break; case 2: if (r.getDim2Size() != b.size()) { BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Operation not allowed due to incompatibility in data dimensions")); } for (int i = 0; i < r.getDim1Size(); ++i) for (int j = 0; j < r.getDim2Size(); ++j) { if (isNAN(r[i][j]) || isNAN(b[j]) || (b[j] == 0)) r[i][j] << NotANumber(); else r[i][j] = r[i][j] / b[j]; } break; default: BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Operation not allowed due a not implemented mode")); } return r; } template AMDA::Parameters::Tab2DData div(std::vector a, const AMDA::Parameters::Tab2DData& b, int mode) { AMDA::Parameters::Tab2DData r(b); switch (mode) { case 1: if (r.getDim1Size() != a.size()) { BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Operation not allowed due to incompatibility in data dimensions")); } for (int i = 0; i < r.getDim1Size(); ++i) for (int j = 0; j < r.getDim2Size(); ++j) { if (isNAN(r[i][j]) || isNAN(a[i]) || (r[i][j] == 0)) r[i][j] << NotANumber(); else r[i][j] = a[i] / r[i][j]; } break; case 2: if (r.getDim2Size() != a.size()) { BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Operation not allowed due to incompatibility in data dimensions")); } for (int i = 0; i < r.getDim1Size(); ++i) for (int j = 0; j < r.getDim2Size(); ++j) { if (isNAN(r[i][j]) || isNAN(a[j]) || (r[i][j] == 0)) r[i][j] << NotANumber(); else r[i][j] = a[j] / r[i][j]; } break; default: BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Operation not allowed due a not implemented mode")); } return r; } /** * @brief Operator / between Tab2D and vector */ template AMDA::Parameters::Tab2DData operator/(const AMDA::Parameters::Tab2DData& a, std::vector b) { return div(a, b, 1); } template AMDA::Parameters::Tab2DData operator/(std::vector a, const AMDA::Parameters::Tab2DData& b) { return div(b, a, 1); } /** * @brief Operator + between two Tab2D */ template AMDA::Parameters::Tab2DData operator+(const AMDA::Parameters::Tab2DData& a, const AMDA::Parameters::Tab2DData& b) { if ((a.getDim1Size() != b.getDim1Size()) || (a.getDim2Size() != b.getDim2Size())) { BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Operation not allowed due to incompatibility in data dimensions")); } AMDA::Parameters::Tab2DData r(a); for (int i = 0; i < r.getDim1Size(); ++i) for (int j = 0; j < r.getDim2Size(); ++j) { if (isNAN(a[i][j]) || isNAN(b[i][j])) r[i][j] << NotANumber(); else r[i][j] = a[i][j] + b[i][j]; } return r; } /** * @brief Operator - between two Tab2D */ template AMDA::Parameters::Tab2DData operator-(const AMDA::Parameters::Tab2DData& a, const AMDA::Parameters::Tab2DData& b) { if ((a.getDim1Size() != b.getDim1Size()) || (a.getDim2Size() != b.getDim2Size())) { BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Operation not allowed due to incompatibility in data dimensions")); } AMDA::Parameters::Tab2DData r(a); for (int i = 0; i < r.getDim1Size(); ++i) for (int j = 0; j < r.getDim2Size(); ++j) { if (isNAN(a[i][j]) || isNAN(b[i][j])) r[i][j] << NotANumber(); else r[i][j] = a[i][j] - b[i][j]; } return r; } /** * @brief Operator * between two Tab2D */ template AMDA::Parameters::Tab2DData operator*(const AMDA::Parameters::Tab2DData& a, const AMDA::Parameters::Tab2DData& b) { if ((a.getDim1Size() != b.getDim1Size()) || (a.getDim2Size() != b.getDim2Size())) { BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Operation not allowed due to incompatibility in data dimensions")); } AMDA::Parameters::Tab2DData r(a); for (int i = 0; i < r.getDim1Size(); ++i) for (int j = 0; j < r.getDim2Size(); ++j) { if (isNAN(a[i][j]) || isNAN(b[i][j])) r[i][j] << NotANumber(); else r[i][j] = a[i][j] * b[i][j]; } return r; } /** * @brief Operator + between two Tab2D */ template AMDA::Parameters::Tab2DData operator/(const AMDA::Parameters::Tab2DData& a, const AMDA::Parameters::Tab2DData& b) { if ((a.getDim1Size() != b.getDim1Size()) || (a.getDim2Size() != b.getDim2Size())) { BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Operation not allowed due to incompatibility in data dimensions")); } AMDA::Parameters::Tab2DData r(a); for (int i = 0; i < r.getDim1Size(); ++i) for (int j = 0; j < r.getDim2Size(); ++j) { if (isNAN(a[i][j]) || isNAN(b[i][j]) || (b[i][j] == 0)) r[i][j] << NotANumber(); else r[i][j] = a[i][j] / b[i][j]; } return r; } /** * @brief Function total on all components of a vector => result is a scalar */ template Type total(const std::vector& a) { Type sum; sum << NotANumber(); for (int j = 0; j < a.size(); ++j) { if (isFinite(a[j])) { if (isNAN(sum)) sum = a[j]; else sum += a[j]; } } return sum; } /** * @brief Function total on all components of a Tab2D => result is a scalar */ template Type total(const AMDA::Parameters::Tab2DData& a) { Type sum; sum << NotANumber(); for (int i = 0; i < a.getDim1Size(); ++i) for (int j = 0; j < a.getDim2Size(); ++j) { if (isFinite(a[i][j])) { if (isNAN(sum)) sum = a[i][j]; else sum += a[i][j]; } } return sum; } /** * @brief Function total on lines or columns of a Tab2D => result is a vector * mode = 1 => sum on lines * mode = 2 => sum on columns */ template std::vector total(const AMDA::Parameters::Tab2DData& a, int mode) { std::vector sum; switch (mode) { case 1: for (int j = 0; j < a.getDim2Size(); ++j) { Type elem; elem << NotANumber(); for (int i = 0; i < a.getDim1Size(); ++i) { if (isFinite(a[i][j])) { if (isNAN(elem)) elem = a[i][j]; else elem += a[i][j]; } } sum.push_back(elem); } break; case 2: for (int i = 0; i < a.getDim1Size(); ++i) { Type elem; elem << NotANumber(); for (int j = 0; j < a.getDim2Size(); ++j) { if (isFinite(a[i][j])) { if (isNAN(elem)) elem = a[i][j]; else elem += a[i][j]; } } sum.push_back(elem); } break; default: BOOST_THROW_EXCEPTION( AMDA::AMDA_exception() << AMDA::errno_code(AMDA_OPER_NOT_ALLOWED) << AMDA::ex_msg("Operation not allowed due a not implemented mode")); } return sum; } // Reshape a Tab2D to a vector template std::vector reshapeToVector(const AMDA::Parameters::Tab2DData& a) { std::vector v; v.resize(a.getDim1Size() * a.getDim2Size()); for (int r = 0; r < a.getDim1Size(); ++r) { for (int c = 0; c < a.getDim2Size(); ++c) { v[r * a.getDim2Size() + c] = a[r][c]; } } return v; } /* * Evaluation of SuperMAG auroral electrojet indices as indicators * of substorms and auroral power * JOURNAL OF GEOPHYSICAL RESEARCH, VOL. 116, A12211, doi:10.1029/2011JA016779, 2011 */ template Type newell2011(Type a) { return 0.048 * a + 0.241 * std::sqrt(a); } template std::vector operator+(AMDA::Parameters::TabRow a, AMDA::Parameters::TabRow b) { std::vector av(a); std::vector bv(b); return av + bv; } template std::vector operator+(std::vector a, AMDA::Parameters::TabRow b) { std::vector bv(b); return a + bv; } template std::vector operator+(AMDA::Parameters::TabRow a, std::vector b) { std::vector av(a); return av + b; } template std::vector operator*(AMDA::Parameters::TabRow a, AMDA::Parameters::TabRow b) { std::vector av(a); std::vector bv(b); return av*bv; } template std::vector operator*(std::vector a, AMDA::Parameters::TabRow b) { std::vector bv(b); return a*bv; } template std::vector operator*(AMDA::Parameters::TabRow a, std::vector b) { std::vector av(a); return av*b; } template std::vector operator-(AMDA::Parameters::TabRow a, AMDA::Parameters::TabRow b) { std::vector av(a); std::vector bv(b); return av - bv; } template std::vector operator-(std::vector a, AMDA::Parameters::TabRow b) { std::vector bv(b); return a - bv; } template std::vector operator-(AMDA::Parameters::TabRow a, std::vector b) { std::vector av(a); return av - b; } template std::vector operator/(AMDA::Parameters::TabRow a, AMDA::Parameters::TabRow b) { std::vector av(a); std::vector bv(b); return av / bv; } template std::vector operator/(std::vector a, AMDA::Parameters::TabRow b) { std::vector bv(b); return a / bv; } template std::vector operator/(AMDA::Parameters::TabRow a, std::vector b) { std::vector av(a); return av / b; } template bool isValid(const std::string& num) { bool flag = true; try { boost::lexical_cast(num); } catch (boost::bad_lexical_cast &e) { flag = false; } return flag; } template std::pair operator-(std::pair a, std::pair b) { std::pair c; c.first = a.first - b.firest; c.second = a.second - b.second; return c; } template std::pair operator+(std::pair a, std::pair b) { std::pair c; c.first = a.first + b.firest; c.second = a.second + b.second; return c; } template std::pair operator*(std::pair a, std::pair b) { std::pair c; c.first = a.first * b.firest; c.second = a.second * b.second; return c; } template std::pair operator/(std::pair a, Type2 b) { std::pair c; c.first = a.first / b; c.second = a.second / b; return c; } #endif /* LOGICALDATATYPE_HH_ */