Esempio n. 1
0
/**
 *  \brief
 *      Computes Spherical Linear Interpolation (SLERP) between two unit vectors.
 *  \details
 *      Spherical linear interpolation (or slerping) is a method for smoothly
 *      interpolating points on a sphere (its a spherical geometry version of
 *      linear interpolation).  Let \f$\hat{a}\f$ and \f$\hat{b}\f$ be units
 *      vectors and \f$\phi\f$ be the angle between them. We can interpolate to
 *      a fraction alpha through the rotation between them using the formula;
 *
 *          \f[ \hat{z} = { \sin((1-\alpha)\phi)\over\sin(\phi)} \hat{a} + {
 *                                \sin(\alpha\phi)\over\sin(\phi)} \hat{b} \f]
 *
 *      The routine Lgm_InitSlerp() finds \f$\sin(\phi)\f$ and \f$\phi\f$ given
 *      the unbit vectors \f$\hat{a}\f$ and \f$\hat{b}\f$. Note that for small
 *      values of \f$\phi\f$, the routine uses the approximation;
 *
 *          \f[ \hat{z} =  (1-\alpha) \hat{a} + \alpha \hat{b} \f].
 *
 *
 * 
 *          \param[in]  a: initial unit vector.
 *          \param[in]  b: final unit vector.
 *          \param[in]  z: interpolated unit vector.
 *          \param[in]  alpha: fraction of the angle phi to rotate to.
 *          \param[in]  si: Lgm_SlerpInfo structure.
 */
void Lgm_Slerp( Lgm_Vector *a, Lgm_Vector *b, Lgm_Vector *z, double alpha, Lgm_SlerpInfo *si ) {

    Lgm_Vector  w1, w2;

    /*
     * Check to see that Phi is small. If it is, use approximation.
     */
    if ( si->Phi < 1e-9 ) {
        w1 = *a; Lgm_ScaleVector( &w1, (1.0-alpha) );
        w2 = *b; Lgm_ScaleVector( &w2, alpha );
    } else {
        w1 = *a; Lgm_ScaleVector( &w1, sin( (1.0-alpha)*si->Phi )/ si->SinPhi );
        w2 = *b; Lgm_ScaleVector( &w2, sin( alpha*si->Phi )/ si->SinPhi );
    }

    Lgm_VecAdd( z, &w1, &w2 ); 


}
Esempio n. 2
0
/**
 *  \brief
 *      Compute the instantaneous gradient and curvature drift velocity of the guiding center.
 *
 *
 *
 *  \details
 *      The gradient and curvature drift velocity of the guiding center is given by;
 *          \f[
 *              V_s = {mv^2\over qB^2}\left(\left(1-{B\over
 *              2B_m}\right){\vec{B}\times\nabla B\over B} + \left(1-{B\over
 *              B_m}\right){(\nabla\times \vec{B})_perp} \right)
 *          \f]
 *      (e.g. see Sukhtina, M.A., "One the calculation of the magnetic srift
 *      velocity of particles with arbitrary pitch angles, Planet Space Sci.
 *      41, 327--331, 1993.) With \f$\eta = T/E_0\f$, where \f$T\f$ is the
 *      particle's kinetic energy, and \f$E_0\f$ its rest energy, this can be
 *      rewritten as,
 *          \f[
 *              V_s = {\eta (2+\eta)\over (1+\eta)}{E_0\over qB^2}\left(\left(1-{B\over
 *              2B_m}\right){\vec{B}\times\nabla B\over B} + \left(1-{B\over
 *              B_m}\right){(\nabla\times \vec{B})_perp} \right)
 *          \f]
 *
 *
 *      \param[in]      u0          Position (in GSM) to use. [Re]
 *      \param[out]     Vel         The computed drift velocity in GSM coords. [km/s]
 *      \param[in]      q           Charge of the particle. [C]
 *      \param[in]      T           Kinetic energy of the particle. [MeV]
 *      \param[in]      E0          Rest energy of the particle. [MeV]
 *      \param[in]      Bm          Magnitude of B-field at mirror point for particle. [nT]
 *      \param[in]      DerivScheme Derivative scheme to use (can be one of LGM_DERIV_SIX_POINT, LGM_DERIV_FOUR_POINT, or LGM_DERIV_TWO_POINT).
 *      \param[in]      h           The delta (in Re) to use for grid spacing in the derivative scheme.
 *      \param[in,out]  m           A properly initialized and configured Lgm_MagModelInfo structure.
 *
 *
 *      \author         Mike Henderson
 *      \date           2011
 *
 */
int Lgm_GradAndCurvDriftVel( Lgm_Vector *u0, Lgm_Vector *Vel, Lgm_MagModelInfo *m ) {

    double      B, BoverBm, g, eta, h, Beta, Beta2, Gamma;
    double      q, T, E0, Bm;
    int         DerivScheme;
    Lgm_Vector  CurlB, CurlB_para, CurlB_perp, GradB, Bvec, Q, R, S, W, Z;
    Lgm_Vector  B_Cross_GradB;

    q           = m->Lgm_VelStep_q;
    T           = m->Lgm_VelStep_T;
    E0          = m->Lgm_VelStep_E0;
    Bm          = m->Lgm_VelStep_Bm;
    h           = m->Lgm_VelStep_h;
    DerivScheme = m->Lgm_VelStep_DerivScheme;

//printf("Lgm_GradAndCurvDriftVel: u0 = %g %g %g\n", u0->x, u0->y, u0->z);
    m->Bfield( u0, &Bvec, m );
    B = Lgm_Magnitude( &Bvec );
    BoverBm = B/Bm;
//printf("BoverBm = %g\n", BoverBm);


    /*
     * Compute B cross GradB  [nT/Re]
     */
    Lgm_GradB( u0, &GradB, DerivScheme, h, m );
    Lgm_CrossProduct( &Bvec, &GradB, &B_Cross_GradB );


    /*
     * Compute (curl B)_perp [nT/Re]
     */
    Lgm_CurlB2( u0, &CurlB, &CurlB_para, &CurlB_perp, DerivScheme, h, m );


    /*
     * Compute instantaneous gradient/curv drift Velocity.
     */
    Q = B_Cross_GradB;
    g = (1.0-0.5*BoverBm)/B;
//printf("g1 = %g\n", g);
    Lgm_ScaleVector( &Q, g ); // [nT/Re]

    R = CurlB_perp;
    g = 1.0-BoverBm;
//printf("g2 = %g\n", g);
    Lgm_ScaleVector( &R, g ); // [nT/Re]

    Lgm_VecAdd( &S, &Q, &R ); // [nT/Re]
    eta = T/E0; // kinetic energy over rest energy
    Gamma = eta + 1.0;
    Beta2 = 1.0 - 1.0/(Gamma*Gamma);
    Beta  = sqrt( Beta2 );
    g = Gamma*Beta2*E0*1e6*Joules_Per_eV/(q*B*B); // [ N m / (A s nT^2) ]  
    // gS would have units of [ N m / (A s nT Re) ], so convert nT and Re to SI
    // to get a final answer in m/s. Then convert to km/s.
    g *= 1e9/(Re*1e6);        
    g /= Re;        
//Re/s
//printf("g3 = %g\n", g);
    Lgm_ScaleVector( &S, g ); // [ N m / (A s T m) ] = [ N m / (A s (N/(A m) m) ] = [ m/s ]
// now its Re/s


    // Add in parallel velocity (Note that v = c*Beta)
    if (BoverBm >= 1.0) {
        g = 0.0;
    } else {
        g = -LGM_c/(1000.0*Re)*Beta*sqrt(1.0-BoverBm)/B;
    }
//printf("T = %g, Beta = %g g = %g\n", T, Beta, g);
    W = Bvec;
    Lgm_ScaleVector( &W, g );
//printf("W = %g %g %g\n", W.x, W.y, W.z);

    Lgm_VecAdd( &Z, &S, &W );
    

    *Vel = Z;


    return(1);

}