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