/**
 *      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;

}
Example #2
0
/*
 *      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);
    }
Example #3
0
/*!

  Compute the interaction matrix related to the set of visual features.

  \return Ls
*/
vpMatrix
vpServo::computeInteractionMatrix()
{

  try {

    switch (interactionMatrixType)
      {
      case CURRENT:
	{
	  try
	    {
	      computeInteractionMatrixFromList(this ->featureList,
					       this ->featureSelectionList,
					       L);
	      dim_task = L.getRows() ;
	      interactionMatrixComputed = true ;
	    }

	  catch(vpException me)
	    {
	      vpERROR_TRACE("Error caught") ;
	      throw ;
	    }
	}
	break ;
      case DESIRED:
	{
	  try
	    {
              if (interactionMatrixComputed == false || forceInteractionMatrixComputation == true)
              {
	        computeInteractionMatrixFromList(this ->desiredFeatureList,
		  			      this ->featureSelectionList, L);

	        dim_task = L.getRows() ;
	        interactionMatrixComputed = true ;
              }

	    }
	  catch(vpException me)
	    {
	      vpERROR_TRACE("Error caught") ;
	      throw ;
	    }
	}
	break ;
      case MEAN:
	{
	  vpMatrix Lstar (L.getRows(), L.getCols());
	  try
	    {
	      computeInteractionMatrixFromList(this ->featureList,
					      this ->featureSelectionList, L);
	      computeInteractionMatrixFromList(this ->desiredFeatureList,
					      this ->featureSelectionList, Lstar);
	    }
	  catch(vpException me)
	    {
	      vpERROR_TRACE("Error caught") ;
	      throw ;
	    }
	  L = (L+Lstar)/2;

	  dim_task = L.getRows() ;
	  interactionMatrixComputed = true ;
	}
	break ;
      case USER_DEFINED:
	// dim_task = L.getRows() ;
	interactionMatrixComputed = false ;
	break;
      }

  }
  catch(vpException me)
    {
      vpERROR_TRACE("Error caught") ;
      throw ;
    }
  return L ;
}
// This file should be identical to DogSolveRK_Unst, with the exception that all
// output printing statements are silenced.
//
// Advance the solution qold to qnew over time interval tstart to tend.
//
// All local information is allocated within this function.  The only part
// that gets shared are time values passed through dogStateUnst2.  This class
// should be modified to accept the state variable, q and aux in place of only
// containing time information as is currently the case.  (-DS)
double DogSolveRK_Unst_Quiet(
    const dTensor2* vel_vec,
    const mesh& Mesh, const edge_data_Unst& EdgeData,
    dTensor3& aux, dTensor3& qold, dTensor3& qnew, 
    const double tstart, const double tend, DogStateUnst2& dogStateUnst2)
{

    const int mx   = qnew.getsize(1);
    const int meqn = qnew.getsize(2);
    const int kmax = qnew.getsize(3);
    const int maux = aux.getsize(2);
    const double* cflv = dogParams.get_cflv();
    const int nv   = dogParams.get_nv();

    RKinfo rk;
    SetRKinfo(dogParams.get_time_order(),rk);

    // define local variables
    int n_step = 0;
    double t  = tstart;
    double dt = dogStateUnst2.get_initial_dt();

    const double CFL_max    = cflv[1];
    const double CFL_target = cflv[2];
    double cfl   = 0.0;
    double dtmin = dt;
    double dtmax = dt;

    const int NumElems = Mesh.get_NumElems(); // Number of total elements in mesh
    const int NumNodes = Mesh.get_NumNodes(); // Number of nodes in mesh
    const int NumEdges = Mesh.get_NumEdges(); // Number of edges in mesh 

    dTensor3   qstar(NumElems,meqn,kmax);
    dTensor3      q1(NumElems,meqn,kmax);
    dTensor3      q2(NumElems,meqn,kmax);
    dTensor3 auxstar(NumElems,maux,kmax);
    dTensor3   Lstar(NumElems,meqn,kmax);
    dTensor3    Lold(NumElems,meqn,kmax);
    dTensor3  auxold(NumElems,maux,kmax);
    dTensor1    smax(NumEdges);

    void L2Project_Unst( 
        const dTensor2* vel_vec, 
        const int istart, const int iend,
        const int QuadOrder, const int BasisOrder_qin, const int BasisOrder_auxin, const
        int BasisOrder_fout, const mesh& Mesh, const dTensor3* qin, const dTensor3*
        auxin, dTensor3* fout, void (*Func)(const dTensor2* vel_vec, const
        dTensor2&,const dTensor2&, const dTensor2&,dTensor2&));

    // JUNK here:
    void AuxFuncWrapper(
        const dTensor2* vel_vec,
        const dTensor2& xpts,
        const dTensor2& NOT_USED_1,
        const dTensor2& NOT_USED_2,
        dTensor2& auxvals);
    const int space_order = dogParams.get_space_order();
    if( maux > 0 )
    { 
        printf("WARNING: maux = %d should be zero for Vlasov routines.", maux);
        printf("    Modify parameters.ini to remove this warning\n" );
        L2Project_Unst(vel_vec,1,NumElems,
                space_order,space_order,space_order,space_order,		       
                Mesh,&qnew,&aux,&aux,&AuxFuncWrapper);  
    }

    // Set initialize qstar and auxstar values
    qstar.copyfrom(qold);
    auxstar.copyfrom(aux);

    // Runge-Kutta time stepping
    while (t<tend)
    {
        // initialize time step
        int m_accept = 0;      
        n_step = n_step + 1;

        // check if max number of time steps exceeded
        if( n_step > nv )
        {
            eprintf(" Error in DogSolveRK_Unst.cpp: "
                    " Exceeded allowed # of time steps \n"
                    "    n_step = %d\n"
                    "        nv = %d\n\n",
                    n_step, nv);
        }

        // copy qnew into qold
        qold.copyfrom(qnew);
        auxold.copyfrom(aux);

        // keep trying until we get a dt that does not violate CFL condition
        while (m_accept==0)
        {

            // set current time
            double told = t;
            if (told+dt > tend)
            { dt = tend - told; }
            t = told + dt;

            // TODO - this needs to be performed at the 'local' level
            dogStateUnst2.set_time ( told );
            dogStateUnst2.set_dt   ( dt   );

            // Set initial maximum wave speed to zero
            smax.setall(0.);

            // Take a full time step of size dt
            switch ( dogParams.get_time_order() )
            {

                case 1:  // First order in time (1-stage)


                    // -----------------------------------------------
                    // Stage #1 (the only one in this case)  
                    rk.mstage = 1;
                    BeforeStep_Unst(dt,Mesh,aux,qnew);
                    ConstructL_Unst(told, vel_vec,Mesh,EdgeData,aux,qnew,Lstar,smax);
                    UpdateSoln_Unst(rk.alpha1->get(rk.mstage),rk.alpha2->get(rk.mstage),
                            rk.beta->get(rk.mstage),dt,Mesh,aux, qnew, Lstar, qnew);
                    AfterStep_Unst(dt,Mesh,aux,qnew);
                    // -----------------------------------------------
                    break;
  
                case 2:  // Second order in time (2-stages)

                    // -----------------------------------------------
                    // Stage #1  	        
                    rk.mstage = 1;
                    dogStateUnst2.set_time(told);
                    BeforeStep_Unst(dt,Mesh,aux,qnew);
                    ConstructL_Unst(told,vel_vec,Mesh,EdgeData,aux,qnew,Lstar,smax);
                    UpdateSoln_Unst(
                        rk.alpha1->get(rk.mstage),rk.alpha2->get(rk.mstage),
                        rk.beta->get(rk.mstage), dt, Mesh, aux, qnew, Lstar, qstar);
                    AfterStep_Unst(dt, Mesh, auxstar, qstar);

                    // ------------------------------------------------
                    // Stage #2
                    rk.mstage = 2;
                    dogStateUnst2.set_time(told+dt);
                    BeforeStep_Unst(dt, Mesh, auxstar, qstar);
                    ConstructL_Unst(told+1.0*dt, vel_vec, Mesh, EdgeData, aux, qstar, Lstar, smax);
                    UpdateSoln_Unst(rk.alpha1->get(rk.mstage), rk.alpha2->get(rk.mstage), 
                            rk.beta->get(rk.mstage), dt, Mesh, auxstar, qstar, Lstar, qnew);
                    AfterStep_Unst(dt, Mesh, aux, qnew);
                    // ------------------------------------------------
                    break;

                case 3:  // Third order in time (3-stages)

//     qnew = alpha1 * qstar + alpha2 * qnew + beta * dt * L( qstar )

// alpha1 = 1.0
// alpha2 = 0.0
// beta   = 1.0

                    // ------------------------------------------------
                    // Stage #1
                    rk.mstage = 1;
                    dogStateUnst2.set_time(told);
                    BeforeStep_Unst(dt,Mesh,aux,qnew);	      
                    ConstructL_Unst(told, vel_vec,Mesh,EdgeData,aux,qnew,Lstar,smax);
                    Lold.copyfrom(Lstar);
                    UpdateSoln_Unst(rk.alpha1->get(rk.mstage),rk.alpha2->get(rk.mstage),
                            rk.beta->get(rk.mstage),dt,Mesh,aux,qnew,Lstar,qstar);
                    AfterStep_Unst(dt,Mesh,aux,qstar);
                    // -------------------------------------------------

// alpha1 = 0.75
// alpha2 = 0.25
// beta   = 0.25

                    // Stage #2
                    rk.mstage = 2;
                    dogStateUnst2.set_time(told+0.5*dt);
                    BeforeStep_Unst(dt,Mesh,aux,qstar);
                    ConstructL_Unst(told+dt,  vel_vec,Mesh,EdgeData,aux,qstar,Lstar,smax);
                    UpdateSoln_Unst(rk.alpha1->get(rk.mstage),rk.alpha2->get(rk.mstage),
                            rk.beta->get(rk.mstage),dt,Mesh,aux,qnew,Lstar,qstar);   
                    AfterStep_Unst(dt,Mesh,aux,qstar);
                    // --------------------------------------------------

// alpha1 = 2/3
// alpha2 = 1/3
// beta   = 2/3

                    // Stage #3
                    rk.mstage = 3;
                    dogStateUnst2.set_time(told+dt);
                    BeforeStep_Unst(dt,Mesh,auxstar,qstar);
                    ConstructL_Unst(told+0.5*dt,vel_vec,Mesh,EdgeData,auxstar,qstar,Lstar,smax);
                    UpdateSoln_Unst(rk.alpha1->get(rk.mstage),rk.alpha2->get(rk.mstage),
                            rk.beta->get(rk.mstage),dt,Mesh,aux,qstar,Lstar,qnew);   
                    AfterStep_Unst(dt,Mesh,aux,qnew);
                    // --------------------------------------------------   
                    break;


                default: unsupported_value_error(dogParams.get_time_order());

            }

            // compute cfl number
            cfl = GetCFL_Unst(dt,Mesh,aux,smax);

            // output time step information
//          if (dogParams.get_verbosity()>0) 
//          {
//              printf("    In DogSolveRK_Quiet: DogSolve2D ... Step %5d"
//                      "   CFL =%6.3f"
//                      "   dt =%11.3e"
//                      "   t =%11.3e\n",
//                      n_step, cfl, dt, t);
//          }

            // choose new time step
            if (cfl>0.0)
            {   
                dt = Min(dogParams.get_max_dt(), dt*CFL_target/cfl);
                dtmin = Min(dt,dtmin);
                dtmax = Max(dt,dtmax);
            }
            else
            {
                dt = dogParams.get_max_dt();
            }

            // see whether to accept or reject this step
            if (cfl<=CFL_max)
                // accept
            { 
                m_accept = 1; 
                dogStateUnst2.set_time(t);

                // do any extra work
//              AfterFullTimeStep_Unst(dogStateUnst2.get_dt(),Mesh,
//                      auxold,qold,Lold,aux,qnew);
            }
            else 
                //reject
            {   
                t = told;
                dogStateUnst2.set_time(told);
//              if( dogParams.get_verbosity() > 0 )
//              {
//                  printf("DogSolve2D rejecting step..."
//                          "CFL number too large\n");
//              }

                // copy qold into qnew
                qnew.copyfrom(qold);
                aux.copyfrom(auxold);

                // after reject function	      
//              AfterReject_Unst(Mesh,dt,aux,qnew);
            }      
        }

    }

//  printf("    Finished!  t = %2.3e and nsteps = %d\n", t, n_step );

    // set initial time step for next call to DogSolveRK
    dogStateUnst2.set_initial_dt(dt);

    void DeleteRKInfo(RKinfo& rk);
    DeleteRKInfo(rk);

    return cfl;

}
/*
 *      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;

}