GeopackWrapper.hh 6.92 KB
#include "geopack.hh"


namespace AMDA {
    namespace Parameters {
        namespace Tsyganenko96 {
            namespace geopack {

#define LMAX_VAL 2000

                class GeopackWrapper {
                public:

                    static void initInGSM(int iyr, int iday, int ihour, int min, int isec) {
                        // We use GSM coordinate frames
                                            float v_default_x = -400.0;
                    float v_default_y = 0.0;
                    float v_default_z = 0.0;

                        recalc_08_(&iyr, &iday, &ihour, &min, &isec, &v_default_x, &v_default_y, &v_default_z);
                    }

                    static bool isInMagnetopause(float Pdyn_i, float sat_pos_X_GSM, float sat_pos_Y_GSM, float sat_pos_Z_GSM) {
                        // We use dynamic pressure Pdyn
                        float vel_mgnp = -1.0;

                        float x_mgnp = 0.;
                        float y_mgnp = 0.;
                        float z_mgnp = 0.;
                        float DIST_MGNP = 0.;
                        int ID_MGNP = 0;

                        t96_mgnp_08_(&Pdyn_i, &vel_mgnp, &sat_pos_X_GSM, &sat_pos_Y_GSM, &sat_pos_Z_GSM,
                                &x_mgnp, &y_mgnp, &z_mgnp, &DIST_MGNP, &ID_MGNP);

                        return (ID_MGNP == 1);
                    }

                    static bool computeGeomagneticFieldInGSM(float sat_pos_X_GSM, float sat_pos_Y_GSM, float sat_pos_Z_GSM,
                            float Pdyn, float Dst, float B_Y_GSM, float B_Z_GSM,
                            float &B_X_GSM_RES, float& B_Y_GSM_RES, float& B_Z_GSM_RES) {

                        // COMPUTES T96 GEOMAGNETIC FIELD MODEL
                        int IOPT = 0;
                        float PARMOD[10];
                        memset(PARMOD, 0, 10 * sizeof (float));
                        PARMOD[0] = Pdyn;
                        PARMOD[1] = Dst;
                        PARMOD[2] = B_Y_GSM;
                        PARMOD[3] = B_Z_GSM;

                        float BX = 0;
                        float BY = 0;
                        float BZ = 0;
                        t96_01_modified_(&IOPT, PARMOD, &sat_pos_X_GSM, &sat_pos_Y_GSM,
                                &sat_pos_Z_GSM, &BX, &BY, &BZ);

                        // COMPUTES GEODIPOLE MAGNETIC field
                        float HX = 0.;
                        float HY = 0.;
                        float HZ = 0.;
                        igrf_gsw_08_(&sat_pos_X_GSM, &sat_pos_Y_GSM, &sat_pos_Z_GSM, &HX, &HY, &HZ);

                        B_X_GSM_RES = BX + HX;
                        B_Y_GSM_RES = BY + HY;
                        B_Z_GSM_RES = BZ + HZ;

                        return true;
                    }

                    static bool computeGeomagneticFieldInGSE(float sat_pos_X_GSM, float sat_pos_Y_GSM, float sat_pos_Z_GSM,
                            float Pdyn, float Dst, float B_Y_GSM, float B_Z_GSM,
                            float &B_X_GSE_RES, float& B_Y_GSE_RES, float& B_Z_GSE_RES) {
                        float B_X_GSM_RES, B_Y_GSM_RES, B_Z_GSM_RES;
                        // COMPUTE GEOMAGNETIC FIELD IN GSM
                        if (!GeopackWrapper::computeGeomagneticFieldInGSM(sat_pos_X_GSM, sat_pos_Y_GSM, sat_pos_Z_GSM, Pdyn, Dst, B_Y_GSM, B_Z_GSM, B_X_GSM_RES, B_Y_GSM_RES, B_Z_GSM_RES)) {
                            return false;
                        }
                        // APPLY TRANSFORMATION FROM GSM TO GSE
                        int transform_flag = 1;
                        gswgse_08_(&B_X_GSM_RES, &B_Y_GSM_RES, &B_Z_GSM_RES, &B_X_GSE_RES, &B_Y_GSE_RES, &B_Z_GSE_RES, &transform_flag);
                        return true;
                    }

                    static bool computeFootprint(bool south, float altitude, float sat_pos_X_GSM, float sat_pos_Y_GSM, float sat_pos_Z_GSM,
                            float Pdyn, float Dst, float B_Y_GSM, float B_Z_GSM, float& FP_X_GSM, float& FP_Y_GSM, float& FP_Z_GSM) {

                        float DIR = south ? 1.0 : -1.0;
                        float DSMAX = 0.5; // Upper limit of the stepsize
                        float ERR = 0.0001; // Permissible step error
                        float RLIM = 50.0; // Outter boundary radii
                        float R0 = 1. + altitude; // Inner boundary radii
                        int IOPT = 0; // Model index

                        float PARMOD[10];
                        memset(PARMOD, 0, 10 * sizeof (float));
                        PARMOD[0] = Pdyn;
                        PARMOD[1] = Dst;
                        PARMOD[2] = B_Y_GSM;
                        PARMOD[3] = B_Z_GSM;

                        int LMAX = LMAX_VAL;

                        float XX[LMAX_VAL];
                        float YY[LMAX_VAL];
                        float ZZ[LMAX_VAL];

                        memset(XX, 0, LMAX * sizeof (float));
                        memset(YY, 0, LMAX * sizeof (float));
                        memset(ZZ, 0, LMAX * sizeof (float));

                        int L = 0;

                        trace_08_modified_(&sat_pos_X_GSM, &sat_pos_Y_GSM, &sat_pos_Z_GSM, &DIR,
                                &DSMAX, &ERR, &RLIM, &R0, &IOPT, PARMOD,
                                &FP_X_GSM, &FP_Y_GSM, &FP_Z_GSM, XX, YY, ZZ, &L, &LMAX);

                        return true;
                    }

                    static void toRLatLong(float FP_X_GSM, float FP_Y_GSM, float FP_Z_GSM, float& r, float& lat, float& lon) {
                        int transform_flag = -1;

                        float FP_GEO_X_i = 0.;
                        float FP_GEO_Y_i = 0.;
                        float FP_GEO_Z_i = 0.;

                        geogsw_08_(&FP_GEO_X_i, &FP_GEO_Y_i, &FP_GEO_Z_i,
                                &FP_X_GSM, &FP_Y_GSM, &FP_Z_GSM,
                                &transform_flag);

                        float SQ = 0.;
                        SQ = FP_GEO_X_i * FP_GEO_X_i + FP_GEO_Y_i*FP_GEO_Y_i;
                        r = sqrt(SQ + FP_GEO_Z_i * FP_GEO_Z_i);
                        SQ = sqrt(SQ);
                        lon = atan2(FP_GEO_Y_i, FP_GEO_X_i);
                        lat = atan2(FP_GEO_Z_i, SQ);

                        if (lon < 0.) {
                            lon += 2. * M_PI;
                        }

                        lon *= (180. / M_PI);
                        lat *= (180. / M_PI);
                    }

                    static void computeTiltAngle(int iyr, int iday, int ihour, int min, int isec, float * tiltAngle) {
                                            float v_default_x = -400.0;
                    float v_default_y = 0.0;
                    float v_default_z = 0.0;
                        recalc_08_modified_(&iyr, &iday, &ihour, &min, &isec, &v_default_x, &v_default_y, &v_default_z, tiltAngle);
                    }

                };

            } /* geopack */
        } /* Tsyganenko96 */
    } /* Parameters */
} /* AMDA */