/*
 *  Note: The variables that save our state in this (and other fundtions) are
 *  not local static variables, but are contained in the Lgm_MagModelInfo
 *  structure that the user passes to it. This allows the function to be
 *  thread-safe and re-entrant. 
 */
double I_integrand( double s, _qpInfo *qpInfo ) {


    Lgm_Vector 		    Bvec;
    int			        reset=1, done, Count;
    double		        f, g, Hremaining, Hdone, H, Htry, Hdid, Hnext, sgn=1.0, sdid, B, dS;
    Lgm_MagModelInfo    *mInfo;



    /*
     *  Get pointer to our auxilliary data structure.
     */
    mInfo = (Lgm_MagModelInfo *)qpInfo;

	mInfo->Lgm_I_integrand_u_scale.x =  10.0;  mInfo->Lgm_I_integrand_u_scale.y = 1.0; mInfo->Lgm_I_integrand_u_scale.z = 10.0;



    if ( mInfo->Lgm_I_integrand_JumpMethod == LGM_RELATIVE_JUMP_METHOD ) {

        /*
         *  Set starting point.  If this is the first call for this integral,
         *  set point to the lower limit. 
         */
        if ( mInfo->Lgm_I_integrand_FirstCall  == TRUE ) {
	        mInfo->Lgm_I_integrand_FirstCall = FALSE;
            mInfo->Lgm_I_integrand_P = mInfo->Pm_South;
	        mInfo->Lgm_I_integrand_S = 0.0;
	        dS = s;
        } else {
	        dS = s - mInfo->Lgm_I_integrand_S;
        }

        if (dS < 0.0) {
            H = -dS; sgn = -1.0; // H is a positive qnty
        } else {
            H = dS; sgn = 1.0;
        }

    } else if ( mInfo->Lgm_I_integrand_JumpMethod == LGM_ABSOLUTE_JUMP_METHOD ) {

	    /*
         *  This strategy starts at start each time.  Slower(?), but seems to
         *  limit roundoff error from accumulating? The speed increase of the
         *  relative method really depends on how far apart the s points are
         *  that the integrator is picking. If they are bouncing all over the
         *  place the relative method still does alot of tracing.
	     */
        if ( mInfo->Lgm_I_integrand_FirstCall == TRUE ) {
	        mInfo->Lgm_I_integrand_FirstCall = FALSE;
        } 
	    mInfo->Lgm_I_integrand_P = mInfo->Pm_South;
        mInfo->Lgm_I_integrand_S = 0.0;
	    H = s; sgn = 1.0; // H is a positive qnty
 
    } else {

        printf("I_integrand: Error, unknown Jump Method ( Lgm_I_integrand_JumpMethod = %d\n", mInfo->Lgm_I_integrand_JumpMethod );
        exit(-1);

    }


    /*
     *  Get B-field at the given value of s.  Need to advance along field line
     *  by an amount H. May need to do more than one call to get there...
     *  Setting Htry to be H is an attempt to make the full jump in one call to
     *  MagStep. For very precise calculations, the number of jumps we do here
     *  seems to be fairly critical. Making two jumps (i.e. Htry = H/2) and
     *  limiting Hmax to 0.5 Re seems to work pretty well (perhaps its because
     *  symetry between mirror points?). Could still play with the max step
     *  size of 0.5 -- maybe something a bit higher would work just as well and
     *  be more efficient?
     */
    done = FALSE; Count = 0; Htry = 0.5*H; Hdone = 0.0; reset = TRUE;
    if (Htry > 0.5) Htry = 0.5;
    if ( fabs(mInfo->Lgm_I_integrand_S-s) < 1e-12 ) done = TRUE;

    while ( !done ) {

        Lgm_MagStep( &mInfo->Lgm_I_integrand_P, &mInfo->Lgm_I_integrand_u_scale, Htry, &Hdid, &Hnext, sgn, &sdid, &reset, mInfo->Bfield, mInfo );
        Hdone += Hdid; // positive qnty

        mInfo->Lgm_I_integrand_S += sgn*Hdid;
        Hremaining = H - Hdone;
	    if ( Count > 1000 ) {
            printf("I_integrand: Warning, early return because Count > 1000. Ill-conditioned integrand?\n");
	        done = TRUE;
        } else if ( fabs(mInfo->Lgm_I_integrand_S-s) < 1e-12 ){
	        done = TRUE;
	    } else {
            if ( Htry > Hremaining ) Htry = Hremaining;
	    }
	    ++Count;
    }

    mInfo->Bfield( &mInfo->Lgm_I_integrand_P, &Bvec, mInfo );
    B = Lgm_Magnitude( &Bvec );

    /*
     * Compute integrand, ( 1 - B/Bm ) ^ (1/2) Make sure 1-B/Bm is not
     * negative. If it is, assume its zero. (Note that sometimes (due to
     * round-off error) it could be very slightly negative).
     */
    g = 1.0 - B/mInfo->Bm;
    f = (g > 0.0) ? sqrt( g ) : 0.0;

    ++mInfo->Lgm_n_I_integrand_Calls;

    return( f );

}
Example #2
0
int main(){


    long int            Date;
    double              UTC;
    Lgm_Vector          u, B, CurlB;
    Lgm_MagModelInfo    *mInfo;
    int                 i, j;


    Date = 20050831;
    UTC  = 9.0;

    mInfo = Lgm_InitMagInfo( );
    Lgm_Set_Coord_Transforms( Date, UTC, mInfo->c );

   mInfo->Bfield = Lgm_B_TS04;
//mInfo->Bfield = Lgm_B_OP77;
//mInfo->Bfield = Lgm_B_T89;
    mInfo->Bfield = Lgm_B_TS04;
    mInfo->Bfield = Lgm_B_igrf;
    mInfo->Bfield = Lgm_B_cdip;
    mInfo->Bfield = Lgm_B_edip;
    mInfo->Bfield = Lgm_B_T89;
    mInfo->P      = 4.1011111111111118;
    mInfo->Dst    = 7.7777777777777777;
    mInfo->By     = 3.7244444444444444;
    mInfo->Bz     = -0.12666666666666665;
    mInfo->W[0]   = 0.12244444444444445;
    mInfo->W[1]   = 0.2514;
    mInfo->W[2]   = 0.089266666666666661;
    mInfo->W[3]   = 0.047866666666666668;
    mInfo->W[4]   = 0.22586666666666666;
    mInfo->W[5]   = 1.0461333333333334;


    printf("%13s", "Kp");
    printf(" %13s", "Ux (Re)");
    printf(" %13s", "Uy (Re)");
    printf(" %13s", "Uz (Re)");
    printf(" %13s", "Bx (nT)");
    printf(" %13s", "By (nT)");
    printf(" %13s", "Bz (nT)");
    printf(" %13s", "Bmag (nT)");
    printf(" %16s", "CurlB_x (nT/Re)");
    printf(" %16s", "CurlB_y (nT/Re)");
    printf(" %16s", "CurlB_z (nT/Re)\n");


    for (i=0; i<=5; i++) {
        mInfo->Kp = i;
        u.x = -6.6; u.y =  0.0;  u.z =  0.0;
        mInfo->Bfield( &u, &B, mInfo );
        Lgm_CurlB( &u, &CurlB, LGM_DERIV_SIX_POINT, 1e-3, mInfo );
        printf( "%13i", mInfo->Kp);
        printf( " %13g %13g %13g", u.x, u.y, u.z );
        printf( " %13g %13g %13g", B.x, B.y, B.z );
        printf( " %13g", Lgm_Magnitude( &B ) );
        printf( " %16g %16g %16g \n", CurlB.x, CurlB.y, CurlB.z );
    }

    for (j=0; j<100; j++){
        mInfo->Kp = 3;
        for (i=0; i<13; i++) {
            u.x = -1. - (double)i * 0.5;
            u.y =  1.0;  u.z =  -1.0;
            mInfo->Bfield( &u, &B, mInfo );
            Lgm_CurlB( &u, &CurlB, LGM_DERIV_SIX_POINT, 1e-3, mInfo );
            printf( "%13i", mInfo->Kp);
            printf( " %13g %13g %13g", u.x, u.y, u.z );
            printf( " %13g %13g %13g", B.x, B.y, B.z );
            printf( " %13g", Lgm_Magnitude( &B ) );
            printf( " %16g %16g %16g \n", CurlB.x, CurlB.y, CurlB.z );
        }
    }



    {
      Lgm_Vector v;

      mInfo->Lgm_VelStep_T = 100e-3; // 100keV
      mInfo->Lgm_VelStep_q = -LGM_e; // electron change
      mInfo->Lgm_VelStep_E0 = LGM_Ee0; // electron mass
      mInfo->Lgm_VelStep_Bm = sqrt(B.x*B.x + B.y*B.y + B.z*B.z);  // b mirror [nT]
      mInfo->Lgm_VelStep_h = 1e-3;  // step size in Re
      mInfo->Lgm_VelStep_DerivScheme = LGM_DERIV_FOUR_POINT;

      printf("\nT=%lf q=%lf E0=%lf Bm=%lf h=%lf DerivScheme=%d\n", 
	     mInfo->Lgm_VelStep_T, 
	     mInfo->Lgm_VelStep_q, mInfo->Lgm_VelStep_E0, mInfo->Lgm_VelStep_Bm, mInfo->Lgm_VelStep_h, 
	     mInfo->Lgm_VelStep_DerivScheme );


      Lgm_GradAndCurvDriftVel(&u, &v, mInfo);
      printf("\nThe drift velocity [km/s in GSM] for a locally mirroring 100 keV electron is:\n");
      Lgm_PrintVector(&v);
    }


    Lgm_FreeMagInfo( mInfo );


    exit(0);
}