コード例 #1
0
ファイル: McIlwain_L.c プロジェクト: balarsen/LANLGeoMag
int main(){
    long int             Date;
    double               L, I, Bm, M, a, UTC, Ltarget;
    Lgm_Vector           u, v;
    Lgm_MagModelInfo    *mInfo = Lgm_InitMagInfo();
    Lgm_CTrans          *c = Lgm_init_ctrans( 0 );
    Lgm_ElapsedTimeInfo  tInfo;

    Lgm_ElapsedTimeInit( &tInfo, 255, 95, 0 );

    for (Ltarget=1.5; Ltarget<16.0; Ltarget += 0.1){
        //Ltarget = 5.0;
    
        Date = 20100101;
        UTC = 0.0;
        Lgm_Set_Coord_Transforms( Date, UTC, c );
        u.x = -Ltarget; u.y = 0.0; u.z = 0.0; // SM
        Lgm_Convert_Coords( &u, &v, SM_TO_GSM, c );
        
        
        mInfo->Bfield = Lgm_B_cdip;
        
        for (a=5.0; a<=90.0; a+= 5.0){
            L = Lgm_McIlwain_L( Date, UTC, &v, a, 0, &I, &Bm, &M, mInfo );
            printf("Pitch Angle: %g    McIlwain L  = %.10g   ( I, Bm, M = %g %g %g )   Delta = %g\n", a, L, I, Bm, M, Ltarget-L);
        }
    }



    Lgm_PrintElapsedTime( &tInfo );
    Lgm_FreeMagInfo(mInfo);
    Lgm_free_ctrans(c);
    return(0);
}
コード例 #2
0
/**
 *      Input Variables:
 *
 *                      Date:
 *                       UTC:
 *                         u:  Input position vector in GSM
 *                    nAlpha:  Number of Pitch Angles to compute
 *                     Alpha:  Pitch Angles to compute
 *
 *      Input/OutPut Variables:
 *
 *              MagEphemInfo:  Structure used to input and output parameters/settings/results to/from routine.
 *
 */
void Lgm_ComputeLstarVersusPA( long int Date, double UTC, Lgm_Vector *u, int nAlpha, double *Alpha, int Colorize, Lgm_MagEphemInfo *MagEphemInfo ) {

    Lgm_LstarInfo 	*LstarInfo, *LstarInfo2, *LstarInfo3;
    Lgm_Vector      v1, v2, v3, vv1, Bvec;
    double          sa, sa2, Blocal;
    double          Lam, CosLam, LSimple;
    int             i, k, LS_Flag, nn, tk, TraceFlag;
    char            *PreStr, *PostStr;

    /* These should be set by the user in the setup up MagEphemInfo no in here */
    //MagEphemInfo->LstarInfo->SaveShellLines = FALSE;
    //MagEphemInfo->LstarInfo->FindShellPmin  = FALSE;
    //MagEphemInfo->LstarInfo->ComputeVgc     = FALSE;
    //MagEphemInfo->LstarInfo->ComputeVgc     = FALSE;
    LstarInfo = MagEphemInfo->LstarInfo;

    // Save Date, UTC to MagEphemInfo structure
    MagEphemInfo->Date   = Date;
    MagEphemInfo->UTC    = UTC;

    // Save nAlpha, and Alpha array to MagEphemInfo structure
    MagEphemInfo->nAlpha = nAlpha;
    for (i=0; i<MagEphemInfo->nAlpha; i++) MagEphemInfo->Alpha[i] = Alpha[i];

    // Set Tolerances
    Lgm_SetLstarTolerances( MagEphemInfo->LstarQuality, MagEphemInfo->nFLsInDriftShell, LstarInfo );


    // set coord transformation
    Lgm_Set_Coord_Transforms( Date, UTC, LstarInfo->mInfo->c );

    /*
     *  Blocal at sat location.
     */
    MagEphemInfo->P = *u;
    LstarInfo->mInfo->Bfield( u, &Bvec, LstarInfo->mInfo );
    Blocal = Lgm_Magnitude( &Bvec );
    MagEphemInfo->B = Blocal;
//printf("Blocal = %g\n", Blocal);

    for ( i=0; i<MagEphemInfo->nAlpha; i++ ){
        sa = sin( MagEphemInfo->Alpha[i]*RadPerDeg ); sa2 = sa*sa;
        MagEphemInfo->Bm[i] = Blocal/sa2;
//printf("Bm[%d] = %g\n", i, MagEphemInfo->Bm[i] );
    }




    /*
     *  Compute Field-related quantities for each Pitch Angle.
     *
     *
     *  First do a trace to identify the FL type and some of its critical points.
     *
     */
    TraceFlag = Lgm_Trace( u, &v1, &v2, &v3, LstarInfo->mInfo->Lgm_LossConeHeight, TRACE_TOL, TRACE_TOL2, LstarInfo->mInfo );
    MagEphemInfo->FieldLineType = TraceFlag;
//printf("P = %g %g %g   Blocal = %lf Bmin = %lf \n",  u->x, u->y, u->z, Blocal, MagEphemInfo->Bmin );
    if ( TraceFlag > 0 ) {
        MagEphemInfo->Ellipsoid_Footprint_Ps  = v1;
        MagEphemInfo->Ellipsoid_Footprint_Pn  = v2;
        MagEphemInfo->Pmin          = v3;
        MagEphemInfo->Snorth        = LstarInfo->mInfo->Snorth;
        MagEphemInfo->Ssouth        = LstarInfo->mInfo->Ssouth;
        MagEphemInfo->Smin          = LstarInfo->mInfo->Smin;
        MagEphemInfo->Bmin          = LstarInfo->mInfo->Bmin;
//printf("P = %g %g %g   Blocal = %lf Bmin = %lf \n",  u->x, u->y, u->z, Blocal, MagEphemInfo->Bmin );
        //MagEphemInfo->Mref          = LstarInfo->mInfo->c->M_cd_McIllwain;
        MagEphemInfo->Mref          = LstarInfo->mInfo->c->M_cd_2010;
        MagEphemInfo->Mcurr         = LstarInfo->mInfo->c->M_cd;
        MagEphemInfo->Mused         = MagEphemInfo->Mref;
    }
    if ( TraceFlag != 1 ) {
        /*
         * FL not closed.
         */
        for ( i=0; i<MagEphemInfo->nAlpha; i++ ){
            MagEphemInfo->Lstar[i] = LGM_FILL_VALUE;
            MagEphemInfo->I[i]     = LGM_FILL_VALUE;
            MagEphemInfo->K[i]     = LGM_FILL_VALUE;
            MagEphemInfo->Sb[i]    = LGM_FILL_VALUE;
        }
        MagEphemInfo->Sb0     = LGM_FILL_VALUE;
        MagEphemInfo->d2B_ds2 = LGM_FILL_VALUE;
        MagEphemInfo->RofC    = LGM_FILL_VALUE;
    }
    if ( TraceFlag == 1 ) {

           MagEphemInfo->Sb0     = LstarInfo->mInfo->Sb0;     // Sb Integral for equatorially mirroring particles.
           MagEphemInfo->d2B_ds2 = LstarInfo->mInfo->d2B_ds2; // second deriv of B wrt s at equator.
           MagEphemInfo->RofC    = LstarInfo->mInfo->RofC;    // radius of curvature at Bmin point.

            /*
             *  Get a simple measure of how big L is
             */
            Lgm_Convert_Coords( &v1, &vv1, GSM_TO_SM, LstarInfo->mInfo->c );
            Lam = asin( vv1.z/Lgm_Magnitude( &vv1 ) );
            CosLam = cos( Lam );
            //LSimple = (1.0+LstarInfo->mInfo->Lgm_LossConeHeight/WGS84_A)/( CosLam*CosLam );
            LSimple = Lgm_Magnitude( &LstarInfo->mInfo->Pmin );

            { // ***** BEGIN PARALLEL EXECUTION *****

            /*
             *  Do all of the PAs in parallel. To control how many threads get run
             *  use the enironment variable OMP_NUM_THREADS. For example,
             *          setenv OMP_NUM_THREADS 8
             *  will use 8 threads to do the loop in parallel. Be very careful what gets
             *  set private here -- the threads must not interfere with each other.
             */
#if USE_OPENMP
            #pragma omp parallel private(LstarInfo2,LstarInfo3,sa,sa2,LS_Flag,nn,tk,PreStr,PostStr)
            #pragma omp for schedule(dynamic, 1)
#endif
            for ( i=0; i<MagEphemInfo->nAlpha; i++ ){  // LOOP OVER PITCH ANGLES

                /*
                 * make a local copy of LstarInfo structure -- needed for multi-threading
                 */
                LstarInfo3 = Lgm_CopyLstarInfo( LstarInfo );

                /*
                 * colorize the diagnostic messages.
                 */
                if ( Colorize ){
                    sprintf( LstarInfo3->PreStr, "\033[38;5;%dm", Colors[i%9]); sprintf( LstarInfo3->PostStr, "\033[0m");
                } else {
                    LstarInfo3->PreStr[0] = '\0'; LstarInfo3->PostStr[0] = '\0';
                }
                PreStr = LstarInfo3->PreStr; PostStr = LstarInfo3->PostStr;

                /*
                 *  Set Bmirror
                 */
                LstarInfo3->mInfo->Bm = MagEphemInfo->Bm[i];
                NewTimeLstarInfo( Date, UTC, MagEphemInfo->Alpha[i], LstarInfo3->mInfo->Bfield, LstarInfo3 );

                /*
                 *  Compute L*
                 */
                if ( LSimple < LstarInfo3->LSimpleMax ){

                    LstarInfo2 = Lgm_CopyLstarInfo( LstarInfo3 );

                    LstarInfo2->mInfo->Bm = LstarInfo3->mInfo->Bm;
                    if (LstarInfo3->VerbosityLevel >= 2 ) {
                        printf("\n\n\t\t%sComputing L* for: UTC = %g  (Local) PA = %d  (%g)%s\n", PreStr, UTC, i, MagEphemInfo->Alpha[i], PostStr );
                        //printf("    \t\t%s                  I   = %g PA = %d  (%g)%s\n", PreStr, MagEphemInfo->I[i], i, MagEphemInfo->Alpha[i], PostStr );
                    }
//////////////////////////////NOTE
//////////////////////////////NOTE   We are giving Lstar the Min B point ALREADY!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//////////////////////////////NOTE
//////////////////////////////NOTE
//////////////////////////////NOTE

//printf("LstarInfo2->mInfo->Bm = %g\n", LstarInfo2->mInfo->Bm);
                    LS_Flag = Lstar( &v3, LstarInfo2);

                    if (LstarInfo3->VerbosityLevel >= 2 ) {
                        printf("\t\t%sUTC, L*          = %g %g%s\n", PreStr, UTC, LstarInfo2->LS, PostStr );
                        printf("\t\t%sUTC, L*_McIlwain = %g %g%s\n", PreStr, UTC, LstarInfo2->LS_McIlwain_M, PostStr );
                        printf("\t\t%sUTC, LSimple     = %g %g%s\n\n\n", PreStr, UTC, LSimple, PostStr );
                    }
                    MagEphemInfo->Lstar[i] = ( LS_Flag >= 0 ) ? LstarInfo2->LS : LGM_FILL_VALUE;
                    MagEphemInfo->I[i]  = LstarInfo2->I[0]; // I[0] is I for the FL that the sat is on.
                    MagEphemInfo->K[i]  = LstarInfo2->I[0]*sqrt(MagEphemInfo->Bm[i]*1e-5); // Second invariant
                    MagEphemInfo->Sb[i] = LstarInfo2->SbIntegral0; // SbIntegral0 is Sb for the FL that the sat is on.
                    /*
                     *  Determine the type of the orbit
                     */
                    if ( LS_Flag >= 0 )  {
                        LstarInfo2->DriftOrbitType = LGM_DRIFT_ORBIT_CLOSED;
                        for ( k=0; k<LstarInfo2->nMinMax; ++k ) {
                            if ( LstarInfo2->nMinima[k] > 1 ) LstarInfo2->DriftOrbitType = LGM_DRIFT_ORBIT_CLOSED_SHABANSKY;
                        }
                    } else {
                        LstarInfo2->DriftOrbitType = LGM_DRIFT_ORBIT_OPEN;
                        for ( k=0; k<LstarInfo2->nMinMax; ++k ) {
                            if ( LstarInfo2->nMinima[k] > 1 ) LstarInfo2->DriftOrbitType = LGM_DRIFT_ORBIT_OPEN_SHABANSKY;
                        }
                    }
                    MagEphemInfo->DriftOrbitType[i] = LstarInfo2->DriftOrbitType;


                    //printf("\t    %sL* [ %g Deg. ]: Date: %ld   UTC: %g   Lsimple:%g   L*:%.15g%s\n", PreStr, MagEphemInfo->Alpha[i], Date, UTC, LSimple, LstarInfo2->LS, PostStr );
                    if (LstarInfo3->VerbosityLevel > 0 ) {
		                printf("\t    %sL* [ %g\u00b0 ]: Date: %ld   UTC: %g   Lsimple:%g   L*:%.15g%s\n", PreStr, MagEphemInfo->Alpha[i], Date, UTC, LSimple, LstarInfo2->LS, PostStr );
		            }




                    /*
                     * Save detailed results to the MagEphemInfo structure.
                     */
                    MagEphemInfo->nShellPoints[i] = LstarInfo2->nPnts;
                    for (nn=0; nn<LstarInfo2->nPnts; nn++ ){
                        MagEphemInfo->Shell_Pmin[i][nn]  = LstarInfo2->Pmin[nn];
                        MagEphemInfo->Shell_Bmin[i][nn]  = LstarInfo2->Bmin[nn];
                        MagEphemInfo->Shell_GradI[i][nn] = LstarInfo2->GradI[nn];
                        MagEphemInfo->Shell_Vgc[i][nn]   = LstarInfo2->Vgc[nn];

                        MagEphemInfo->ShellI[i][nn] = LstarInfo2->I[nn];

                        MagEphemInfo->ShellSphericalFootprint_Pn[i][nn] = LstarInfo2->Spherical_Footprint_Pn[nn];
                        MagEphemInfo->ShellSphericalFootprint_Sn[i][nn] = LstarInfo2->Spherical_Footprint_Sn[nn];
                        MagEphemInfo->ShellSphericalFootprint_Bn[i][nn] = LstarInfo2->Spherical_Footprint_Bn[nn];
                        MagEphemInfo->ShellSphericalFootprint_Ps[i][nn] = LstarInfo2->Spherical_Footprint_Ps[nn];
                        MagEphemInfo->ShellSphericalFootprint_Ss[i][nn] = LstarInfo2->Spherical_Footprint_Ss[nn];
                        MagEphemInfo->ShellSphericalFootprint_Bs[i][nn] = LstarInfo2->Spherical_Footprint_Bs[nn];

                        MagEphemInfo->ShellEllipsoidFootprint_Pn[i][nn] = LstarInfo2->Ellipsoid_Footprint_Pn[nn];
                        MagEphemInfo->ShellEllipsoidFootprint_Sn[i][nn] = LstarInfo2->Ellipsoid_Footprint_Sn[nn];
                        MagEphemInfo->ShellEllipsoidFootprint_Bn[i][nn] = LstarInfo2->Ellipsoid_Footprint_Bn[nn];
                        MagEphemInfo->ShellEllipsoidFootprint_Ps[i][nn] = LstarInfo2->Ellipsoid_Footprint_Ps[nn];
                        MagEphemInfo->ShellEllipsoidFootprint_Ss[i][nn] = LstarInfo2->Ellipsoid_Footprint_Ss[nn];
                        MagEphemInfo->ShellEllipsoidFootprint_Bs[i][nn] = LstarInfo2->Ellipsoid_Footprint_Bs[nn];


                        MagEphemInfo->ShellMirror_Pn[i][nn]    = LstarInfo2->Mirror_Pn[nn];
                        //MagEphemInfo->ShellMirror_Sn[i][nn]    = LstarInfo2->mInfo->Sm_North;
                        MagEphemInfo->ShellMirror_Sn[i][nn]    = LstarInfo2->Mirror_Sn[nn];

                        MagEphemInfo->ShellMirror_Ps[i][nn]    = LstarInfo2->Mirror_Ps[nn];
                        //MagEphemInfo->ShellMirror_Ss[i][nn]    = LstarInfo2->mInfo->Sm_South;
                        MagEphemInfo->ShellMirror_Ss[i][nn]    = LstarInfo2->Mirror_Ss[nn];

                        /*
                         *  Save all of the drift shell FLs in MagEphemInfo structure
                         */
                        MagEphemInfo->nFieldPnts[i][nn] = LstarInfo2->nFieldPnts[nn];
                        for (tk=0; tk<LstarInfo2->nFieldPnts[nn]; tk++){    // loop over points in a FL
                            MagEphemInfo->s_gsm[i][nn][tk] = LstarInfo2->s_gsm[nn][tk];
                            MagEphemInfo->Bmag[i][nn][tk]  = LstarInfo2->Bmag[nn][tk];
                            MagEphemInfo->x_gsm[i][nn][tk] = LstarInfo2->x_gsm[nn][tk];
                            MagEphemInfo->y_gsm[i][nn][tk] = LstarInfo2->y_gsm[nn][tk];
                            MagEphemInfo->z_gsm[i][nn][tk] = LstarInfo2->z_gsm[nn][tk];
                        }
//printf("LstarInfo2->nFieldPnts[%d] = %d\n", nn, LstarInfo2->nFieldPnts[nn]);


                        MagEphemInfo->nMinima[i][nn] = LstarInfo2->nMinima[nn];
                        MagEphemInfo->nMaxima[i][nn] = LstarInfo2->nMaxima[nn];

                    }

                    FreeLstarInfo( LstarInfo2 );

                } else {
                    printf(" Lsimple >= %g  ( Not doing L* calculation )\n", LstarInfo3->LSimpleMax );
                    MagEphemInfo->Lstar[i] = LGM_FILL_VALUE;
//printf("Bm = %g\n", MagEphemInfo->Bm[i]);
                    MagEphemInfo->I[i]     = LGM_FILL_VALUE;
                    MagEphemInfo->K[i]     = LGM_FILL_VALUE;
                    MagEphemInfo->nShellPoints[i] = 0;

                }


                FreeLstarInfo( LstarInfo3 );
            }

        }
        // ***** END PARALLEL EXECUTION *****


    }


    return;

}
コード例 #3
0
ファイル: LCDS.c プロジェクト: balarsen/LANLGeoMag
/*
 *      Input Variables:
 *
 *                      Date: 
 *                       UTC: 
 *                     brac1:  Radial distance for inner edge of search bracket
 *                     brac2:  Radial distance for outer edge of search bracket
 *                     Alpha:  Equatorial pitch angle to compute 
 *                   Quality:  Quality factor (0-8)
 *
 *      Input/OutPut Variables:
 *                         K:  K value for LCDS at given alpha
 *                 LstarInfo:  LstarInfo structure to specify B-field model, store last valid Lstar, etc.
 *  
 */
int LCDS( long int Date, double UTC, double brac1, double brac2, double MLT, double Alpha, double tol, int Quality, double *K, Lgm_LstarInfo *LstarInfo ) {
    Lgm_LstarInfo   *LstarInfo_brac1, *LstarInfo_brac2, *LstarInfo_test;
    Lgm_Vector      v1, v2, v3, LCDSv3, Bvec, Ptest, PtestSM, Pinner, PinnerSM, Pouter, PouterSM;
    double          Blocal, Xtest, sa, sa2, LCDS;
    double          nTtoG = 1.0e-5;
    int             LS_Flag, nn, k, TFlag;
    int             maxIter = 50;

    //Start by creating necessary structures... need an Lstar info for each bracket, plus test point.
    LstarInfo_brac1 = Lgm_CopyLstarInfo( LstarInfo );
    LstarInfo_brac2 = Lgm_CopyLstarInfo( LstarInfo );
    LstarInfo_test = Lgm_CopyLstarInfo( LstarInfo );

    // Set Tolerances
    Lgm_SetLstarTolerances( Quality, 24, LstarInfo_brac1 );
    Lgm_SetLstarTolerances( Quality, 24, LstarInfo_brac2 );
    Lgm_SetLstarTolerances( Quality, 24, LstarInfo_test );

    // set coord transformation 
    Lgm_Set_Coord_Transforms( Date, UTC, LstarInfo_brac1->mInfo->c );
    Lgm_Set_Coord_Transforms( Date, UTC, LstarInfo_brac2->mInfo->c );
    Lgm_Set_Coord_Transforms( Date, UTC, LstarInfo_test->mInfo->c );

    //Check for closed drift shell at brackets
    PinnerSM.x = brac1*cos(MLT); PinnerSM.y = brac1*sin(MLT); PinnerSM.z = 0.0;
    Lgm_Convert_Coords( &PinnerSM, &Pinner, SM_TO_GSM, LstarInfo_test->mInfo->c );

    /*
     *  Test inner bracket location.
     */
    LstarInfo_brac1->mInfo->Bfield( &Pinner, &Bvec, LstarInfo_brac1->mInfo );
    Blocal = Lgm_Magnitude( &Bvec );
    sa = sin( LstarInfo->PitchAngle*RadPerDeg ); sa2 = sa*sa;

    //Trace to minimum-B
    if ( Lgm_Trace( &Pinner, &v1, &v2, &v3, 120.0, 0.01, TRACE_TOL, LstarInfo_brac1->mInfo ) == LGM_CLOSED ) {
        //Only continue if bracket 1 is closed FL
        //Get L*
        LstarInfo_brac1->mInfo->Bm = LstarInfo_brac1->mInfo->Bmin/sa2;
        LS_Flag = Lstar( &v3, LstarInfo_brac1);
        LCDS = LstarInfo_brac1->LS;
        *K = (LstarInfo_brac1->I0)*sqrt(Lgm_Magnitude(&LstarInfo_brac1->Bmin[0]));
        if (LstarInfo->VerbosityLevel > 1) printf("Found valid inner bracket. Pinner_GSM, Pmin_GSM = (%g, %g, %g), (%g, %g, %g)\n", Pinner.x, Pinner.y, Pinner.z, LstarInfo_brac1->mInfo->Pmin.x, LstarInfo_brac1->mInfo->Pmin.y, LstarInfo_brac1->mInfo->Pmin.z);
    } else {
        FreeLstarInfo( LstarInfo_brac1 );
        FreeLstarInfo( LstarInfo_brac2 );
        FreeLstarInfo( LstarInfo_test );
        return(-8); //Inner bracket is bad - bail
    }


    /*
     *  Test outer bracket location.
     */
    PouterSM.x = brac2*cos(MLT); PouterSM.y = brac2*sin(MLT); PouterSM.z = 0.0;
    Lgm_Convert_Coords( &PouterSM, &Pouter, SM_TO_GSM, LstarInfo_test->mInfo->c );

    LstarInfo_brac2->mInfo->Bfield( &Pouter, &Bvec, LstarInfo_brac2->mInfo );
    Blocal = Lgm_Magnitude( &Bvec );

    //Trace to minimum-B
    if ( Lgm_Trace( &Pouter, &v1, &v2, &v3, 120.0, 0.01, TRACE_TOL, LstarInfo_brac2->mInfo ) == LGM_CLOSED ) {
        //If bracket 2 is closed FL then check for undefined L*. If L* is defined, we have a problem
        //Get L*
        LstarInfo_brac2->mInfo->Bm = LstarInfo_brac2->mInfo->Bmin/sa2;
        LS_Flag = Lstar( &v3, LstarInfo_brac2);
        if (LstarInfo_brac2->LS != LGM_FILL_VALUE) {
            //move outer bracket out and try again
            PouterSM.x = 1.7*Lgm_Magnitude(&Pouter)*cos(MLT);
            PouterSM.y = 1.7*Lgm_Magnitude(&Pouter)*sin(MLT); PouterSM.z = 0.0;
            Lgm_Convert_Coords( &PouterSM, &Pouter, SM_TO_GSM, LstarInfo_test->mInfo->c );
            if ( Lgm_Trace( &Pouter, &v1, &v2, &v3, 120.0, 0.01, TRACE_TOL, LstarInfo_brac2->mInfo ) == LGM_CLOSED ) {
                LS_Flag = Lstar( &v3, LstarInfo_brac2);
                if (LstarInfo_brac2->LS != LGM_FILL_VALUE) {
                    FreeLstarInfo( LstarInfo_brac1 );
                    FreeLstarInfo( LstarInfo_brac2 );
                    FreeLstarInfo( LstarInfo_test );
                    return(-9); //Outer bracket is bad - bail
                }
            }
        }
    }
    if (LstarInfo->VerbosityLevel > 1) {
        printf("Found valid outer bracket. Pouter_GSM, Pmin_GSM = (%g, %g, %g), (%g, %g, %g)\n", Pouter.x, Pouter.y, Pouter.z, LstarInfo_brac2->mInfo->Pmin.x, LstarInfo_brac2->mInfo->Pmin.y, LstarInfo_brac2->mInfo->Pmin.z);
    }

    //if brackets are okay, we've moved on without changing anything except setting initial LCDS value as L* at inner bracket
    nn = 0;
    while (Lgm_Magnitude(&Pouter)-Lgm_Magnitude(&Pinner) > tol){
        if (LstarInfo->VerbosityLevel > 1) printf("Current LCDS iteration, bracket width = %d, %g\n", nn, Lgm_Magnitude(&Pouter)-Lgm_Magnitude(&Pinner));
        if (nn > maxIter) {
            printf("********* EXCEEDED MAXITER\n");
            //free structures before returning
            FreeLstarInfo( LstarInfo_brac1 );
            FreeLstarInfo( LstarInfo_brac2 );
            FreeLstarInfo( LstarInfo_test );
            return(-2); //reached max iterations without achieving tolerance - bail
        }
        Xtest = (Lgm_Magnitude(&Pinner) + (Lgm_Magnitude(&Pouter)-Lgm_Magnitude(&Pinner))/2.0);
        PtestSM.x = -1.0*Xtest*cos(MLT); PtestSM.y = -1.0*Xtest*sin(MLT); PtestSM.z = 0.0;
        Lgm_Convert_Coords( &PtestSM, &Ptest, SM_TO_GSM, LstarInfo_test->mInfo->c );

        LstarInfo_test->mInfo->Bfield( &Ptest, &Bvec, LstarInfo_test->mInfo );
        Blocal = Lgm_Magnitude( &Bvec );
        //Trace to minimum-B
        TFlag = Lgm_Trace( &Ptest, &v1, &v2, &v3, 120.0, 0.01, TRACE_TOL, LstarInfo_test->mInfo );
        if ( TFlag == LGM_CLOSED ) {
            //If test point is closed FL then check for undefined L*.
            //Get L*
            LstarInfo_test->mInfo->Bm = LstarInfo_test->mInfo->Bmin/sa2;
            LS_Flag = Lstar( &v3, LstarInfo_test);
            if ( (LS_Flag > 0) || (LstarInfo_test->LS != LGM_FILL_VALUE) ){
                //Drift shell defined
                Pinner = Ptest;
                LCDSv3 = v3;
                LCDS = LstarInfo_test->LS;
                *K = (LstarInfo_test->I0)*sqrt(LstarInfo_test->mInfo->Bm*nTtoG);

                //Determine the type of the orbit
                LstarInfo_test->DriftOrbitType = LGM_DRIFT_ORBIT_CLOSED;
                for ( k=0; k<LstarInfo_test->nMinMax; ++k ) {
                    if ( LstarInfo_test->nMinima[k] > 1 ) LstarInfo_test->DriftOrbitType = LGM_DRIFT_ORBIT_CLOSED_SHABANSKY;
                    if ( LstarInfo_test->nMinima[k] < 1 ) {printf("Less than one minimum defined on field line: Exit due to impossibility."); exit(-1); }
                }

                if (LstarInfo->VerbosityLevel > 1) printf("Current LCDS, K, PtestSM is %g, %g, (%g, %g, %g)\n", LCDS, *K, PtestSM.x, PtestSM.y, PtestSM.z);
                LstarInfo->mInfo->Bm = LstarInfo_test->mInfo->Bm;
                LstarInfo->DriftOrbitType = LstarInfo_test->DriftOrbitType;
            } else {
                Pouter = Ptest;
                Lgm_Convert_Coords( &Ptest, &PtestSM, GSM_TO_SM, LstarInfo_test->mInfo->c );
                printf("Failed DS trace at test point (%g %g %g GSM; %g %g %g SM; TFlag = %d), moving outer bracket to current location\n", 
                   Ptest.x, Ptest.y, Ptest.z, PtestSM.x, PtestSM.y, PtestSM.z, TFlag);
            }
        } else {
            //FL open -> drift shell open
            Lgm_Convert_Coords( &Ptest, &PtestSM, GSM_TO_SM, LstarInfo_test->mInfo->c );
            printf("Failed FL trace at test point (%g %g %g GSM; %g %g %g SM; TFlag = %d), moving outer bracket to current location\n", 
                   Ptest.x, Ptest.y, Ptest.z, PtestSM.x, PtestSM.y, PtestSM.z, TFlag);
            Pouter = Ptest;
        }

    nn++;
    }
if (LstarInfo->VerbosityLevel > 0) printf("Final LCDS, K is %g, %g. Eq. radius = %g \n", LCDS, *K, Lgm_Magnitude( &LCDSv3 ));
    LstarInfo->LS = LCDS;
    //free structures
    FreeLstarInfo( LstarInfo_brac1 );
    FreeLstarInfo( LstarInfo_brac2 );
    FreeLstarInfo( LstarInfo_test );
    return(0);
    }
コード例 #4
0
/*
 * This version traces FLs from the Earth at the given MLT/mlat instead of trying to find the Bm radially out first.
 */
double ComputeI_FromMltMlat2( double Bm, double MLT, double mlat, double *r, double I0, Lgm_LstarInfo *LstarInfo ) {

    int         reset=1, reset2, TraceFlag;

    double      Bmin, I, Phi, cl, sl, rat, SS1, SS2, SS, Sn, Ss, Htry, Hdid, Hnext, Bs, Be, s, sgn;
    Lgm_Vector  w, u, Pmirror1, Pmirror2, v1, v2, v3, Bvec, P, Ps, u_scale, Bvectmp, Ptmp;
    double      stmp, Btmp;



    /*
     *  First do a trace to identify the FL type and some of its critical points.
     */
    *r = 1.0 + 100.0/Re;
    Phi = 15.0*(MLT-12.0)*RadPerDeg;
    cl = cos( mlat * RadPerDeg ); sl = sin( mlat * RadPerDeg );
    w.x = (*r)*cl*cos(Phi); w.y = (*r)*cl*sin(Phi); w.z = (*r)*sl;
    Lgm_Convert_Coords( &w, &u, SM_TO_GSM, LstarInfo->mInfo->c );
printf("w = %g %g %g\n", w.x, w.y, w.z);
    TraceFlag = Lgm_Trace( &u, &v1, &v2, &v3, LstarInfo->mInfo->Lgm_LossConeHeight, 1e-6, 1e-8, LstarInfo->mInfo );
    LstarInfo->mInfo->Bfield( &v3, &Bvec, LstarInfo->mInfo );
    Bmin = Lgm_Magnitude( &Bvec );
printf("Got here\n");

    if ( TraceFlag != LGM_CLOSED ) {

        if (LstarInfo->VerbosityLevel > 1){ printf( "\t\t\t> Field Line not closed\n" ); }
        return( 9e99 );

    } else if ( Bmin <= Bm ) {

        /*
         * From the minimum B point, attempt to trace along the field to get the northern mirror point.
         */
        P = v3;
        SS1 = 0.0;
        if ( Lgm_TraceToMirrorPoint( &P, &Pmirror1, &SS1, LstarInfo->mInfo->Bm,  1.0, LstarInfo->mInfo->Lgm_TraceToMirrorPoint_Tol, LstarInfo->mInfo ) > 0 )  {

            SS2 = 0.0;
            if ( Lgm_TraceToMirrorPoint( &P, &Pmirror2, &SS2, LstarInfo->mInfo->Bm,  -1.0, LstarInfo->mInfo->Lgm_TraceToMirrorPoint_Tol, LstarInfo->mInfo ) > 0 )  {

            } else {
                if (LstarInfo->VerbosityLevel > 3){ printf( "\t\t\t> Unable to find southern mirror point\n" ); }
                return( 9e99 );
            }

            // total distance between mirror point.
            SS = SS1 + SS2;
            
            // If its really small, just return 0.0 for I
            if ( fabs(SS) < 1e-7) {
                if (LstarInfo->VerbosityLevel > 3){ printf( "\t\t\t> Distance between mirror points is < 1e-7Re, Assuming I=0\n" ); }
                return( 0.0 );
            }

        } else {
            if (LstarInfo->VerbosityLevel > 3){ printf( "\t\t\t> Unable to find northern mirror point\n" ); }
            return( 9e99 );
        }

        /*
         * OK, we have both mirror points. LEts compute I
         */
        I = 9e99;
        LstarInfo->mInfo->Hmax = 0.1;
        LstarInfo->mInfo->Hmax = SS/(double)LstarInfo->mInfo->nDivs;

        /*
         *  This little section is attempting to solve an annoying
         *  precision issue.  If the distance over which we are trying
         *  to trace is too small, too many sub-divisions (i.e. total
         *  steps) will lead to a step size that is too small.  We can
         *  end up with the gridded FL points computed in
         *  Lgm_TraceLine3() such that the distance, s of the final
         *  point is very slightly less than we expect.  This tries to
         *  reduce the number of divisions to avoid this in cases where
         *  the total distance to trace is very small.
         */
        int nDivs;
        if ( SS/LstarInfo->mInfo->nDivs < 1e-6 ) {
            nDivs = SS/1e-6;
            if (nDivs < 10) nDivs = 10;
        } else {
            nDivs = LstarInfo->mInfo->nDivs;
        }

         
        if ( Lgm_TraceLine3( &(LstarInfo->mInfo->Pm_South), SS, nDivs, 1.0, 1e-7, FALSE, LstarInfo->mInfo ) < 0 ) return( 9e99 );

        /*
         *  Set the limits of integration.
         */
        LstarInfo->mInfo->Sm_South = 0.0;
        LstarInfo->mInfo->Sm_North = SS;

        if ( InitSpline( LstarInfo->mInfo ) ) {

            /*
             *  Do I integral with interped integrand.
             */
             I = Iinv_interped( LstarInfo->mInfo );
             if (LstarInfo->VerbosityLevel > 1) {
                printf("\t\t%s  mlat: %13.6g   I: %13.6g   I0: %13.6g   I-I0: %13.6g    [Sa,Sb]: %.8g  %.8g  (nCalls = %d)%s\n",  LstarInfo->PreStr, mlat, I, I0, I-I0, LstarInfo->mInfo->Sm_South, LstarInfo->mInfo->Sm_North, LstarInfo->mInfo->Lgm_n_I_integrand_Calls, LstarInfo->PostStr );
             }
             FreeSpline( LstarInfo->mInfo );

        } else {
            I = 9e99;
        }


    } else {

        if (LstarInfo->VerbosityLevel > 1){ printf( "\t\t\t> Field line min-B is greater than Bm. Bm = %g Bmin = %g\n", Bm, Bmin ); }
        return( 9e99 );

    }


    return( I );
    

}
コード例 #5
0
int Lgm_TraceToYZPlane( Lgm_Vector *u, Lgm_Vector *v, double Xtarget, double sgn0, double tol, Lgm_MagModelInfo *Info ) {

    Lgm_Vector	u_scale;
    double	    Htry, Hdid, Hnext, Hmin, Hmax, s, sgn, fsgn0;
    double	    Sa, Sb, B, f, r2, z2, r3, L, R, hhh;
    double      Stotal;
    Lgm_Vector	Btmp;
    Lgm_Vector	Pa, Pb, P;
    int		    done, reset=TRUE, bracketed=FALSE;
    long int    Ntotal;

//printf("\n\n\n***************************************\n");
    Pb.x = Pb.y = Pb.z = 0.0;


    Hmax = 20.0;
    Hmin = 0.01;
    u_scale.x =  100.0;  u_scale.y = 100.0; u_scale.z = 100.0;


    /* 
     *  Set the start point, Pa 
     */
    Pa   = *u;
    f = Xtarget - Pa.x;
    fsgn0 = ( f<0.0) ? -1.0 : 1.0;
    Sa   = 0.0;
    Stotal = 0.0;
    Ntotal = 0;





    /*
     *  Choose a good step size to try.
     */
    Lgm_Convert_Coords( &Pa, &P, GSM_TO_SM, Info->c );
    R  = Lgm_Magnitude( &Pa );
    r2 = R*R;
    z2 = P.z*P.z;
    L  = 9e99;
    if ( fabs( r2 - z2 ) < 1e-2 ) {

        /*
         *  High  L
         */
        Htry = 2.0;

    } else {

        r3   = r2*R;
        L    = r3 / (r2 - z2);
        Htry = ( L < 4.5 ) ? 1.165*L : 4.5;

    }

    if ( Htry < 1e-4 ) Htry = 0.001;



//Htry = 0.01;


    /* 
     *   Now, bracket minimum. And do a bisection search for the minimum.
     */
    done = FALSE;
    sgn  = sgn0;
    P    = Pa;
    Sb   = -9e99;
//printf("Htry =%g   sgn = %g\n", Htry, sgn );
//printf("Xtarget = %g f = %g P = %g %g %g\n", Xtarget, f, P.x, P.y, P.z);
    while ( !done ) {

        //if ( Lgm_MagStep( &P, &u_scale, Htry, &Hdid, &Hnext, 1.0e-7, sgn, &s, &reset, Info->Bfield, Info ) < 0 ) return(-1);
        if ( Lgm_MagStep( &P, &u_scale, Htry, &Hdid, &Hnext, sgn, &s, &reset, Info->Bfield, Info ) < 0 ) return(-1);
        Stotal += Hdid;
        ++Ntotal;
        R  = Lgm_Magnitude( &P );
        r2 = R*R;
        r3   = r2*R;
        L    = r3 / (r2 - z2);

        f = Xtarget - P.x;
//printf("Xtarget = %g f = %g P = %g %g %g\n", Xtarget, f, P.x, P.y, P.z);

         if (   (P.x > Info->OpenLimit_xMax) || (P.x < Info->OpenLimit_xMin) || (P.y > Info->OpenLimit_yMax) || (P.y < Info->OpenLimit_yMin)
                || (P.z > Info->OpenLimit_zMax) || (P.z < Info->OpenLimit_zMin) || ( s > 1000.0 ) ) {
            /*
             *  Open FL!
             */
            //v->x = v->y = v->z = 0.0;
            *v = P;
//printf("OPEN!\n\n\n");
            return(0);

	    } else if ( r2 < 1.0 ) {

	        return( -1 );

        } else if ( (Stotal > 300.0) || ( Ntotal > 1500 ) ) {

            printf("Lgm_TraceToYZPlane: %s:%d Field line too long or too many iterations: Stotal / Ntotal:  %g / %ld\n", __FILE__, __LINE__, Stotal, Ntotal );

	        return( 0 );

	    } else if ( fabs( f ) < tol ){

	        done = TRUE;

        } else if ( fsgn0*f > 0.0 ){

            Pa    = P;
            Sa   += Hdid;
            sgn   = sgn0;
            if ( bracketed ) {
                Htry = fabs( Sb - Sa )/2.0;
            } else if ( L < 4.5 ) {
                hhh = 1.165*L+1.0 - R + 1.0;
                //if ( hhh > 1e-4 ) Htry = hhh;
                if ( hhh > R-1.0 ) {
                    hhh = (R-1.0)/2.0;
                }
                

	        }
	    /*
printf("A: Sa, Sb, P = %g %g    (%g, %g, %g)   Htry = %f\n", Sa, Sb, P.x, P.y, P.z, Htry);
*/

	    } else {

            Pb  = P;
            if ( bracketed ) Sb += sgn*sgn0*Hdid;
            else	     Sb  = Sa + Hdid;
            
            bracketed = TRUE;
            sgn  = -sgn0;
            Htry = fabs( Sb - Sa )/2.0;
	    /*
printf("B: Sa, Sb, P = %g %g    (%g, %g, %g)   Htry = %f\n", Sa, Sb, P.x, P.y, P.z, Htry);
*/

	    }

    }




    /*
     *  
     */
    *v = Pb;
//printf("B: Sa, Sb, P = %g %g    (%g, %g, %g)   Htry = %f\n", Sa, Sb, P.x, P.y, P.z, Htry);


//    if ( fabs( Xtarget - Pb.x ) >  2.0*tol ) return( -1 );

    return( 1 );

}
コード例 #6
0
int Lgm_TraceToSMEquat( Lgm_Vector *u, Lgm_Vector *v, double tol, Lgm_MagModelInfo *Info ) {

    Lgm_Vector	u_scale;
    double	    Htry, Hdid, Hnext, Hmin, Hmax, s, sgn, r2;
    double	    Sa=0.0, Sb=0.0, Sc=0.0, d1, d2;
    double	    Za, Zb, Zc, Z;
    Lgm_Vector	Ztmp;
    Lgm_Vector	Pa, Pb, Pc, P;
    int		    done, reset;



    Hmax = 20.0;
    Hmin = 0.001;
    u_scale.x =  100.0;  u_scale.y = 100.0; u_scale.z = 100.0;
    Za = Zb = Zc = 0.0;



    /*
     *  Bracket the minimum. We want to find two points along
     *  the field line such that the location of equatorial plane is
     *  gauranteed to lie between them. To do this, we need to find
     *  three points; Pa, Pb, and Pc such that;
     *
     *		     Pc > Pb > Pa
     *
     *		and  |z_sm( Pa )|   >   |z_sm( Pb )|
     *		and  |z_sm( Pc )|   >   |z_sm( Pb )|
     *
     *
     */


    /* 
     *  Set the start point, Pa and Za (the absolute value of the SM z coord).
     */
    Pa   = *u;
    Lgm_Convert_Coords( &Pa, &Ztmp, GSM_TO_SM, Info->c );
    Za   = fabs( Ztmp.z );
    Sa   = 0.0;




    /*
     *  If we are above the SM plane (i.e. in the northern hemisphere), lets 
     *  try tracing against the field direction.
     */
    sgn = ( Ztmp.z > 0.0 ) ? -1.0 : 1.0;



    /*
     *  Keep stepping along the field line until we have a |Zsm| less than the start point.
     */
    P    = Pa;
    done = FALSE;
    Htry = Za;
    while ( !done ) {

        //if ( Lgm_MagStep( &P, &u_scale, Htry, &Hdid, &Hnext, 1.0e-7, sgn, &s, &reset, Info->Bfield, Info ) < 0 ) return(-1);
        if ( Lgm_MagStep( &P, &u_scale, Htry, &Hdid, &Hnext, sgn, &s, &reset, Info->Bfield, Info ) < 0 ) return(-1);
        Lgm_Convert_Coords( &P, &Ztmp, GSM_TO_SM, Info->c );
        Z = fabs( Ztmp.z );
            if (   (P.x > Info->OpenLimit_xMax) || (P.x < Info->OpenLimit_xMin) || (P.y > Info->OpenLimit_yMax) || (P.y < Info->OpenLimit_yMin)
                || (P.z > Info->OpenLimit_zMax) || (P.z < Info->OpenLimit_zMin) ) {
	        /*
	         *  Open FL!
	         */
	        v->x = v->y = v->z = 0.0;
	        return(0);
	    } else if ( Z < Za ) {
	        done = TRUE;
	        Pb = P;
	        Zb = Z;
	        Sb += Hdid;
        } else {
            Pa = P;
            Za = Z;
            Sa = 0.0;
        }

	    Htry = Z;

    }



    /*
     *  Keep stepping along the field line until we complete the bracket triple.
     */
    done = FALSE;
    while (!done) {

	    P = Pb;
        //if ( Lgm_MagStep( &P, &u_scale, Htry, &Hdid, &Hnext, 1.0e-7, sgn, &s, &reset, Info->Bfield, Info ) < 0 ) return(-1);
        if ( Lgm_MagStep( &P, &u_scale, Htry, &Hdid, &Hnext, sgn, &s, &reset, Info->Bfield, Info ) < 0 ) return(-1);
        Lgm_Convert_Coords( &P, &Ztmp, GSM_TO_SM, Info->c );
        Z = fabs( Ztmp.z );
            if (   (P.x > Info->OpenLimit_xMax) || (P.x < Info->OpenLimit_xMin) || (P.y > Info->OpenLimit_yMax) || (P.y < Info->OpenLimit_yMin)
                || (P.z > Info->OpenLimit_zMax) || (P.z < Info->OpenLimit_zMin) ) {
	        /*
	         *  Open FL!
	         */
	        v->x = v->y = v->z = 0.0;
	        return(0);
	    } else if ( Z < Zb ) {
	        Pa = Pb; Za = Zb; Sa = 0.0;
	        Pb = P;  Zb = Z;  Sb = Hdid; 
            r2  = P.x*P.x + P.y*P.y + P.z*P.z;
            Htry = (Hnext < Hmax) ? ((Hnext > Hmin) ? Hnext : Hmin) : Hmax;
            if (Htry*Htry > r2) Htry = 0.25*sqrt(r2);
	    } else {
	        Pc = P;  Zc = Z; Sc = Sb + Hdid;
	        done = TRUE;
	    }


    }
	






    /*
     *  We have a bracket. Now go in for the kill.
     *  Use golden-section search to converge toward minimum.
     *  (Sa, Sb, Sc) are the distances of the triple points along
     *  the FL. For convenience, we maintain Sa = 0.0, so that
     *  Sb and Sc are always the distances relative to Pa. (And
     *  so Sc is always the width of the bracketed interval. So when
     *  Sc gets small enough we bail out and take Pb as the min).
     */
    done = FALSE;
    while (!done) {

	    d1 = Sb;
	    d2 = Sc - Sb;
	    if ( Sc < tol ) {
	        done = TRUE;
	    } else if ( d1 > d2 ) {

	        P = Pa; Htry = 0.381966011*d1;
            //if ( Lgm_MagStep( &P, &u_scale, Htry, &Hdid, &Hnext, 1.0e-7, sgn, &s, &reset, Info->Bfield, Info ) < 0 ) return(-1);
            if ( Lgm_MagStep( &P, &u_scale, Htry, &Hdid, &Hnext, sgn, &s, &reset, Info->Bfield, Info ) < 0 ) return(-1);
            Lgm_Convert_Coords( &P, &Ztmp, GSM_TO_SM, Info->c );
            Z = fabs( Ztmp.z );
	        if ( Z < Zb ) {
		        Pb = P; Zb = Z; Sb = Hdid;
	        } else {
		        Pa = P; Za = Z; Sb -= Hdid; Sc -= Hdid;
	        }
	    
	    } else {

	        P = Pb; Htry = 0.381966011*d2;
            //if ( Lgm_MagStep( &P, &u_scale, Htry, &Hdid, &Hnext, 1.0e-7, sgn, &s, &reset, Info->Bfield, Info ) < 0 ) return(-1);
            if ( Lgm_MagStep( &P, &u_scale, Htry, &Hdid, &Hnext, sgn, &s, &reset, Info->Bfield, Info ) < 0 ) return(-1);
            Lgm_Convert_Coords( &P, &Ztmp, GSM_TO_SM, Info->c );
            Z = fabs( Ztmp.z );
	        if ( Z < Zb ) {
		        Pb = P; Zb = Z; Sb += Hdid;
	        } else {
		        Pc = P; Zc = Z; Sc = Sb + Hdid;
	        }

	    }

    }


    *v = Pb;


    return( 1 );

}
コード例 #7
0
ファイル: LstarVersusPA.c プロジェクト: balarsen/LANLGeoMag
int main( int argc, char *argv[] ){

    double           UTC, Alpha[1000], a;
    long int         Date;
    int              nAlpha, Kp, i;
    Lgm_Vector       P, Pgsm;
    Lgm_CTrans       *c = Lgm_init_ctrans(0);
    Lgm_MagModelInfo *mmi = Lgm_InitMagInfo();
    Lgm_MagEphemInfo *MagEphemInfo = Lgm_InitMagEphemInfo(0, 20);
    FILE             *fp;

    mmi->Lgm_MagStep_Integrator = LGM_MAGSTEP_ODE_BS;

    // Date and UTC
    Date       = 20130327;
    Date       = 20000701;
    Date       = 20130101;
    Date       = 20130322;
    UTC        = 4.0 + 0.0/60.0 + 0.0/3600.0;
    UTC        = 0.0 + 0.0/60.0 + 0.0/3600.0;
    Lgm_Set_Coord_Transforms( Date, UTC, c );
    MagEphemInfo->LstarInfo->LSimpleMax = 35.0;
    MagEphemInfo->LstarInfo->mInfo->Lgm_MagStep_Integrator = LGM_MAGSTEP_ODE_BS;
    MagEphemInfo->LstarInfo->nFLsInDriftShell = 96;
    MagEphemInfo->nFLsInDriftShell = 96;

    //USER INPUT STUFF
    MagEphemInfo->LstarQuality   = 3;
Lgm_SetLstarTolerances( 3, 96, MagEphemInfo->LstarInfo );
    MagEphemInfo->SaveShellLines = TRUE;
    MagEphemInfo->LstarInfo->VerbosityLevel = 1;
    MagEphemInfo->LstarInfo->ISearchMethod = 2;
    MagEphemInfo->LstarInfo->mInfo->VerbosityLevel = 0;

    Kp = 2;
    MagEphemInfo->LstarInfo->mInfo->Bfield        = Lgm_B_cdip;
    MagEphemInfo->LstarInfo->mInfo->Bfield        = Lgm_B_T89;
    MagEphemInfo->LstarInfo->mInfo->Kp = ( Kp >= 0 ) ? Kp : KP_DEFAULT;
    if ( MagEphemInfo->LstarInfo->mInfo->Kp > 5 ) MagEphemInfo->LstarInfo->mInfo->Kp = 5;

    MagEphemInfo->LstarInfo->mInfo->Bfield        = Lgm_B_cdip;
    MagEphemInfo->LstarInfo->mInfo->Bfield        = Lgm_B_OP77;
    MagEphemInfo->LstarInfo->mInfo->InternalModel = LGM_IGRF;
    MagEphemInfo->LstarInfo->mInfo->InternalModel = LGM_CDIP;
    MagEphemInfo->LstarInfo->mInfo->Bfield        = Lgm_B_Dungey;
    MagEphemInfo->LstarInfo->mInfo->Bfield       = Lgm_B_T89c;
    MagEphemInfo->LstarInfo->mInfo->c->psi       = 0.0;


    FILE         *fpjunk;
    int          done;
    char         fname[1024];
    double       Ra, Rc, Fa, Fc, R, F, Phi, Lat, MLT, Fmax, Rmax;
    double       Kin = 1.5;

    sprintf(fname, "junk_K_v5_24.txt" );
    fpjunk = fopen(fname, "w");





    for (MLT=1.5; MLT<=1.5; MLT+=0.05){


        done = FALSE;

        Ra  = 5.0;   
        Phi = (MLT*15.0 - 180.0)*RadPerDeg; Lat = 0.0*RadPerDeg;
        P.x = Ra*cos( Phi )*cos(Lat); P.y = Ra*sin( Phi )*cos(Lat); P.z = Ra*sin(Lat);
        Lgm_Convert_Coords( &P, &Pgsm, SM_TO_GSM, c );
        Fa  =  LS(  Date, UTC, Kin, &Pgsm, MagEphemInfo  );
//    WriteMagEphemInfoStruct( "test.dat", 1, MagEphemInfo );
//exit(0);

        Rc  = 30.0;   
        Phi = (MLT*15.0 - 180.0)*RadPerDeg; Lat = 0.0*RadPerDeg;
        P.x = Rc*cos( Phi )*cos(Lat); P.y = Rc*sin( Phi )*cos(Lat); P.z = Rc*sin(Lat);
        Lgm_Convert_Coords( &P, &Pgsm, SM_TO_GSM, c );
        Fc  =  LS(  Date, UTC, Kin, &Pgsm, MagEphemInfo  );

        Fmax = -1.0;

        if ( (Fc < 0.0) && (Fa>0.0) ) {

            while (!done ) {

                R   = (Ra+Rc)/2.0;
printf("R = %g\n", R);
                Phi = (MLT*15.0 - 180.0)*RadPerDeg; Lat = 0.0*RadPerDeg;
                P.x = R*cos( Phi )*cos(Lat); P.y = R*sin( Phi )*cos(Lat); P.z = R*sin(Lat);
                Lgm_Convert_Coords( &P, &Pgsm, SM_TO_GSM, c );
                F  =  LS(  Date, UTC, Kin, &Pgsm, MagEphemInfo  );

                if ( F < 0.0 ) {
                    Rc = R;
                    Fc = F;
                } else {
                    if ( F > Fmax ) { Fmax = F; Rmax = R; };
                    Ra = R;
                    Fa = F;
                }

                if ( fabs(Rc-Ra) < 1e-3 ) done = TRUE;

            }

        } else {
            printf("No bracket!\n");
        }


if (Fmax > Fa) printf("************************* Fmax, Fa = %g %g\n", Fmax, Fa);
        fprintf( fpjunk, "%g %g\n", MLT, Fa );
        fflush(fpjunk);

    }

    fclose(fpjunk);



    MLT = 3.00;
    Phi = (MLT*15.0 - 180.0)*RadPerDeg; Lat = 0.0*RadPerDeg;
    P.x = Ra*cos( Phi )*cos(Lat); P.y = Ra*sin( Phi )*cos(Lat); P.z = Ra*sin(Lat);
    Lgm_Convert_Coords( &P, &Pgsm, SM_TO_GSM, c );
    F  =  LS(  Date, UTC, Kin, &Pgsm, MagEphemInfo  );
    WriteMagEphemInfoStruct( "test.dat", 1, MagEphemInfo );

    fp = fopen("Lstar.dat", "w");
    for ( i=0; i<nAlpha; ++i ) {
        fprintf( fp, "%g %.10lf\n", Alpha[i], MagEphemInfo->Lstar[i] );
    }
    fclose(fp);

    Lgm_free_ctrans( c );
    Lgm_FreeMagEphemInfo( MagEphemInfo );

    return(0);

}
コード例 #8
0
void ComputeZPSTransMatrix( Lgm_Vector *Rgeo, long int Date, double UT, double Agsm_to_ins[3][3], double Ains_to_gsm[3][3], double Qins_to_gsm[4], double Qgsm_to_ins[4] ) {

    double  Glon, Alpha, A, B, ca, sa, sum;
    Lgm_Vector  Xgeo, Ygeo, Zgeo, Xgsm, Ygsm, Zgsm;
    Lgm_Vector  Ngeo, Egeo, Ngsm, Egsm;
    Lgm_Vector  Xsc_geo,Ysc_geo, Zsc_geo;
    Lgm_Vector  Xsc_gsm,Ysc_gsm, Zsc_gsm;
    double  Agsm_to_sc[3][3], Asc_to_gsm[3][3], Asc_to_r3[3][3], Ar3_to_sc[3][3], Asc_to_dom[3][3], Adom_to_sc[3][3];  
    Lgm_Vector  X1, Y1, Z1;
    Lgm_Vector  X2, Y2, Z2;
    Lgm_Vector  X3, Y3, Z3;
    Lgm_Vector  X4, Y4, Z4;
    int     i, j, k;
    Lgm_CTrans  c;
    Lgm_Vector Xins, Yins, Zins, Xsc, Ysc, Zsc;
    Lgm_Vector Xins_new, Yins_new, Zins_new;
    double  Q1[4], Q2[4], Q3[4], QQ[4], QT1[4];



    Glon = atan2( Rgeo->y, Rgeo->x );



    /*
     *  Compute transformation matrix from dome coords to GSM
     *  Assume spacecraft is located at Rgeo.
     */
    
    
    /*
     * Nadir in GEO coords.
     */
    Ngeo.x = -Rgeo->x;
    Ngeo.y = -Rgeo->y;
    Ngeo.z = -Rgeo->z;
    Lgm_NormalizeVector( &Ngeo );
    

    
    /*
     *   East in GEO coords. Since, r = {cos(phi), sin(phi)}
     *   east direction will be dr/dphi which is;
     *
     *      east = {-sin(phi), cos(phi)}
     *  
     *   note that phi is just glon in GEO coords.
     *  
     */
    Egeo.x = -1.0*sin(Glon);
    Egeo.y = cos(Glon);
    Egeo.z = 0.0;


    /*
     * North in GEO coords.
     */
    Zgeo.x = 0.0;
    Zgeo.y = 0.0;
    Zgeo.z = 1.0;




    /*
     *  Define S/C coords as:
     *   X: East
     *   Y: South
     *   Z: Nadir
     */
    Xsc_geo = Egeo;
    Ysc_geo.x = -Zgeo.x; Ysc_geo.y = -Zgeo.y; Ysc_geo.z = -Zgeo.z;
    Zsc_geo = Ngeo;


    /*
     *  Convert to GSM
     */
    Lgm_Set_Coord_Transforms( Date, UT, &c );
    Lgm_Convert_Coords( &Xsc_geo, &Xsc_gsm, GEO_TO_GSM, &c );
    Lgm_Convert_Coords( &Ysc_geo, &Ysc_gsm, GEO_TO_GSM, &c );
    Lgm_Convert_Coords( &Zsc_geo, &Zsc_gsm, GEO_TO_GSM, &c );

Xsc_gsm = Xsc_geo;
Ysc_gsm = Ysc_geo;
Zsc_gsm = Zsc_geo;


    /*
     *  Construct Transformation Matrix from GSM to S/C
     */
    Agsm_to_sc[0][0] = Xsc_gsm.x, Agsm_to_sc[1][0] =  Xsc_gsm.y, Agsm_to_sc[2][0] = Xsc_gsm.z;
    Agsm_to_sc[0][1] = Ysc_gsm.x, Agsm_to_sc[1][1] =  Ysc_gsm.y, Agsm_to_sc[2][1] = Ysc_gsm.z;
    Agsm_to_sc[0][2] = Zsc_gsm.x, Agsm_to_sc[1][2] =  Zsc_gsm.y, Agsm_to_sc[2][2] = Zsc_gsm.z;

    Asc_to_gsm[0][0] = Xsc_gsm.x, Asc_to_gsm[1][0] =  Ysc_gsm.x, Asc_to_gsm[2][0] = Zsc_gsm.x;
    Asc_to_gsm[0][1] = Xsc_gsm.y, Asc_to_gsm[1][1] =  Ysc_gsm.y, Asc_to_gsm[2][1] = Zsc_gsm.y;
    Asc_to_gsm[0][2] = Xsc_gsm.z, Asc_to_gsm[1][2] =  Ysc_gsm.z, Asc_to_gsm[2][2] = Zsc_gsm.z;
printf("             ( %5g %5g %5g )\n", Asc_to_gsm[0][0],  Asc_to_gsm[1][0], Asc_to_gsm[2][0] );
printf("Asc_to_gsm = ( %5g %5g %5g )\n", Asc_to_gsm[0][1],  Asc_to_gsm[1][1], Asc_to_gsm[2][1] );
printf("             ( %5g %5g %5g )\n", Asc_to_gsm[0][2],  Asc_to_gsm[1][2], Asc_to_gsm[2][2] );




    /*
     *  Now construct trans matrix between S/C and INSTRUMENT
     *
     *  Lets define the instrument coord system to be as follows:
     *     Yins: parallel to instrument cylindrical symmetry axis.
     *     Zins: parallel to FOV of 
     */


    /*
     *  Here is the prescription to orient ZPS:
     *
     *      1. Start with Yins parallel to Ysc and Zins parallel to Zsc
     *      2. Rotate by -29 deg. about Zsc
     *      3. Then rotate by +45.5 deg. about Yins
     *      4. Then roate by +30.0 deg. about Zins
     * 
     * The easiest way to do this is to use Quaternions
     * 
     */
    
    // Step 1
    Xins = Xsc_gsm;
    Yins = Ysc_gsm;
    Zins = Zsc_gsm;

    // Step2
    //Lgm_AxisAngleToQuat( &Zins, -29.0, Q1 );
    Lgm_AxisAngleToQuat( &Zins, 0.0, Q1 );
    Lgm_QuatRotateVector( Q1, &Xins, &Xins_new ); Xins = Xins_new;
    Lgm_QuatRotateVector( Q1, &Yins, &Yins_new ); Yins = Yins_new;
    Lgm_QuatRotateVector( Q1, &Zins, &Zins_new ); Zins = Zins_new;

    // Step3
    //Lgm_AxisAngleToQuat( &Yins, 45.5, Q2 );
    Lgm_AxisAngleToQuat( &Yins, 0.0, Q2 );
    Lgm_QuatRotateVector( Q2, &Xins, &Xins_new ); Xins = Xins_new;
    Lgm_QuatRotateVector( Q2, &Yins, &Yins_new ); Yins = Yins_new;
    Lgm_QuatRotateVector( Q2, &Zins, &Zins_new ); Zins = Zins_new;
    
    // Step4
    //Lgm_AxisAngleToQuat( &Zins, 30.0, Q3 );
    Lgm_AxisAngleToQuat( &Zins, 0.0, Q3 );
    Lgm_QuatRotateVector( Q3, &Xins, &Xins_new ); Xins = Xins_new;
    Lgm_QuatRotateVector( Q3, &Yins, &Yins_new ); Yins = Yins_new;
    Lgm_QuatRotateVector( Q3, &Zins, &Zins_new ); Zins = Zins_new;

    /*
     *  Now, Xins, Yins, Zins will be oriented in their final positions.
     *  We can construct the sc -> ins trans matrix in one of two wyas now.
     *      1. combine all of the quats and then convert Q->matrix
     *  or  2. use the final unit vectors to manually construct the matri.
     *  Try both...
     */

    Lgm_QuatCombineQuats( Q1, Q2, QT1 );
    Lgm_QuatCombineQuats( QT1, Q3, QQ );
    for (i=0; i<4; i++) Qins_to_gsm[i] = QQ[i];

    Lgm_Quat_To_Matrix( QQ, Ains_to_gsm );

    for (i=0; i<3; ++i){ 
        for (j=0; j<3; ++j){ 
            Agsm_to_ins[i][j] = Ains_to_gsm[j][i];
        }
    }
    Lgm_MatrixToQuat( Agsm_to_ins, Qgsm_to_ins );

Lgm_MatrixToQuat( Agsm_to_sc, Qgsm_to_ins );
Lgm_MatrixToQuat( Asc_to_gsm, Qins_to_gsm );
}
コード例 #9
0
/*
 *      Input Variables:
 *
 *                      Date: 
 *                       UTC: 
 *                         u:  Input position vector in GSM
 *                    nAlpha:  Number of Pitch Angles to compute 
 *                     Alpha:  Pitch Angles to compute 
 *                   Quality:  Quality factor (0-8)
 *
 *      Input/OutPut Variables:
 *
 *              MagEphemInfo:  Structure used to input and output parameters/settings/results to/from routine.
 *  
 */
void ComputeLstarVersusPA( long int Date, double UTC, Lgm_Vector *u, int nAlpha, double *Alpha, int Quality, Lgm_MagEphemInfo *MagEphemInfo ) {

    Lgm_LstarInfo 	*LstarInfo, *LstarInfo2, *LstarInfo3;
    Lgm_Vector  v, v1, v2, v3, vv1, Bvec;
    double      sa, sa2, Blocal;
    double      Lam, CosLam, LSimple, dSa, dSb;
    int         i, LS_Flag, nn, tk, ci;
    double      Ival, Sbval, r, SS;
    int         Kp=KP_DEFAULT;
    char        Filename[128], *PreStr, *PostStr;
    FILE    *fpout;

    LstarInfo = MagEphemInfo->LstarInfo;

    // Save Date, UTC to MagEphemInfo structure
    MagEphemInfo->Date   = Date;
    MagEphemInfo->UTC    = UTC;

    // Save nAlpha, and Alpha array to MagEphemInfo structure
    MagEphemInfo->nAlpha = nAlpha;
    for (i=0; i<MagEphemInfo->nAlpha; i++) MagEphemInfo->Alpha[i] = Alpha[i];

    // Set Tolerances
    SetLstarTolerances( MagEphemInfo->LstarQuality, LstarInfo );

sprintf( Filename, "DipoleTest_1.05/results_%.0e.dat", LstarInfo->mInfo->Lgm_FindShellLine_I_Tol );
fpout = fopen(Filename, "w");


    // set coord transformation 
    Lgm_Set_Coord_Transforms( Date, UTC, LstarInfo->mInfo->c );


    /*
     *  Blocal at sat location.
     */
    MagEphemInfo->P_gsm = *u;
    LstarInfo->mInfo->Bfield( u, &Bvec, LstarInfo->mInfo );
    Blocal = Lgm_Magnitude( &Bvec );
    MagEphemInfo->B = Blocal;


    /*
     *  Compute Field-related quantities for each Pitch Angle.
     */
    if ( Lgm_Trace( u, &v1, &v2, &v3, 120.0, 0.01, TRACE_TOL, LstarInfo->mInfo ) == 1 ) {

        MagEphemInfo->Pmin_gsm = v3;
        MagEphemInfo->Bmin     = LstarInfo->mInfo->Bmin;


            /*
             *  Get a simple measure of how big L is
             */
            Lgm_Convert_Coords( &v1, &vv1, GSM_TO_SM, LstarInfo->mInfo->c );
            Lam = asin( vv1.z/Lgm_Magnitude( &vv1 ) );
            CosLam = cos( Lam );
            LSimple = (1.0+120.0/WGS84_A)/( CosLam*CosLam );



            { // ***** BEGIN PARALLEL EXECUTION *****

            /*
             *  Do all of the PAs in parallel. To control how many threads get run
             *  use the enironment variable OMP_NUM_THREADS. For example,
             *          setenv OMP_NUM_THREADS 8
             *  will use 8 threads to do the loop in parallel. Be very careful what gets 
             *  set private here -- the threads must not interfere with each other.
             */
            #pragma omp parallel private(LstarInfo2,LstarInfo3,sa,sa2,dSa,dSb,LS_Flag,Ival,Sbval,nn,tk)
            #pragma omp for schedule(dynamic, 1)
            for ( i=0; i<MagEphemInfo->nAlpha; i++ ){  // LOOP OVER PITCH ANGLES

                

                // make a local copy of LstarInfo structure -- needed for multi-threading
                LstarInfo3 = Lgm_CopyLstarInfo( LstarInfo );

                // colorize the diagnostic messages.
                sprintf( LstarInfo3->PreStr, "\033[38;5;%dm", Colors[i%9]); sprintf( LstarInfo3->PostStr, "\033[0m");
                PreStr = LstarInfo3->PreStr; PostStr = LstarInfo3->PostStr;

                /*
                 *  Set Pitch Angle, sin, sin^2, and Bmirror
                 */
                sa = sin( MagEphemInfo->Alpha[i]*RadPerDeg ); sa2 = sa*sa;
                printf("%sComputing L* for Pitch Angle: Alpha[%d] = %g Date: %ld   UTC: %g   Lsimple = %g%s\n", PreStr, i, MagEphemInfo->Alpha[i], Date, UTC, LSimple, PostStr );

                LstarInfo3->mInfo->Bm = Blocal/sa2; 
                NewTimeLstarInfo( Date, UTC, MagEphemInfo->Alpha[i], LstarInfo3->mInfo->Bfield, LstarInfo3 );
                MagEphemInfo->Bm[i] = LstarInfo3->mInfo->Bm;

                /*
                 *  Compute L* 
                 */
                LstarInfo2 = Lgm_CopyLstarInfo( LstarInfo3 );
                if ( LSimple < 10.0 ){
// USER SHOULD DECIDE THRESHOLD HERE

                    LstarInfo2->mInfo->Bm = LstarInfo3->mInfo->Bm;
                    if (LstarInfo3->VerbosityLevel >= 2 ) {
                        printf("\n\n\t%sComputing L* for: UTC = %g PA = %d  (%g)%s\n", PreStr, UTC, i, MagEphemInfo->Alpha[i], PostStr );
                        printf("    \t%s                  I   = %g PA = %d  (%g)%s\n", PreStr, MagEphemInfo->I[i], i, MagEphemInfo->Alpha[i], PostStr );
                    }
                    LS_Flag = Lstar( &v3, LstarInfo2);
                    if (LstarInfo3->VerbosityLevel >= 2 ) {
                        printf("\t%sUTC, L*          = %g %g%s\n", PreStr, UTC, LstarInfo2->LS, PostStr );
                        printf("\t%sUTC, L*_McIlwain = %g %g%s\n", PreStr, UTC, LstarInfo2->LS_McIlwain_M, PostStr );
                        printf("\t%sUTC, LSimple     = %g %g%s\n\n\n", PreStr, UTC, LSimple, PostStr );
                    }
                    MagEphemInfo->Lstar[i] = LstarInfo2->LS;


                    /*
                     * Save results to the MagEphemInfo structure.
                     */
                    MagEphemInfo->nShellPoints[i] = LstarInfo2->nPnts;
                    for (nn=0; nn<LstarInfo2->nPnts; nn++ ){
                        MagEphemInfo->ShellI[i][nn] = LstarInfo2->I[nn];
                        MagEphemInfo->ShellFootprint_Pn[i][nn] = LstarInfo2->Footprint_Pn[nn];
                        MagEphemInfo->ShellFootprint_Ps[i][nn] = LstarInfo2->Footprint_Ps[nn];
                        MagEphemInfo->ShellMirror_Pn[i][nn]    = LstarInfo2->Mirror_Pn[nn];
                        MagEphemInfo->ShellMirror_Ps[i][nn]    = LstarInfo2->Mirror_Ps[nn];
                        MagEphemInfo->ShellMirror_Ss[i][nn]    = LstarInfo2->mInfo->Sm_South;
                        MagEphemInfo->ShellMirror_Sn[i][nn]    = LstarInfo2->mInfo->Sm_North;

                        /*
                         *  Save all of the drift shell FLs in MagEphemInfo structure
                         */
                        MagEphemInfo->nFieldPnts[i][nn] = LstarInfo2->nFieldPnts[nn];
                        for (tk=0; tk<LstarInfo2->nFieldPnts[nn]; tk++){    // loop over points in a FL
                            MagEphemInfo->s_gsm[i][nn][tk] = LstarInfo2->s_gsm[nn][tk];
                            MagEphemInfo->Bmag[i][nn][tk]  = LstarInfo2->Bmag[nn][tk];
                            MagEphemInfo->x_gsm[i][nn][tk] = LstarInfo2->x_gsm[nn][tk];
                            MagEphemInfo->y_gsm[i][nn][tk] = LstarInfo2->y_gsm[nn][tk];
                            MagEphemInfo->z_gsm[i][nn][tk] = LstarInfo2->z_gsm[nn][tk];
                        }
                    }

                } else {
                    printf(" Lsimple >= 10.0  ( Not doing L* calculation )\n" );
                }
fprintf(fpout, "%.15lf %.15lf\n", MagEphemInfo->Alpha[i], (1.05-LstarInfo2->LS)/LstarInfo->mInfo->Lgm_FindShellLine_I_Tol );
fflush(fpout);

                FreeLstarInfo( LstarInfo2 );

                FreeLstarInfo( LstarInfo3 );
            }

        } 
        // ***** END PARALLEL EXECUTION *****

    }


//    FreeLstarInfo( LstarInfo );
    
    fclose(fpout);

    return;

}