Difference between revisions of "RDYNLAB Code"
Jump to navigation
Jump to search
(New page: The following files constitute the source code for RDYNLAB. They can be compiled with any source code intended to use the library functions or (preferably) compiled as a shared object ...) |
|||
Line 301: | Line 301: | ||
<pre><nowiki> | <pre><nowiki> | ||
+ | /* RDLparticle.cpp: defines class for a particle */ | ||
+ | |||
+ | #include <rdynlab.h> | ||
+ | #include <math.h> | ||
+ | |||
+ | RDL_Particle::RDL_Particle(double qin, double min, const RDL_Vector &xin, const RDL_Vector &vin) | ||
+ | { | ||
+ | q=qin; | ||
+ | m=min; | ||
+ | x=xin; | ||
+ | v=vin; | ||
+ | } | ||
+ | |||
+ | RDL_Particle RDL_Particle::operator=(const RDL_Particle ¶m) | ||
+ | { | ||
+ | q=param.q; | ||
+ | m=param.m; | ||
+ | x=param.x; | ||
+ | v=param.v; | ||
+ | return *this; | ||
+ | } | ||
+ | |||
+ | double RDL_Particle::gamma(void) | ||
+ | { | ||
+ | double s=length(v); | ||
+ | return 1./sqrt(1.-s*s/(RDL_CLIGHT*RDL_CLIGHT)); | ||
+ | } | ||
+ | |||
+ | double RDL_Particle::energy(void) | ||
+ | { | ||
+ | return gamma()*m*RDL_CLIGHT*RDL_CLIGHT; | ||
+ | } | ||
+ | |||
+ | double RDL_Particle::kinetic_energy(void) | ||
+ | { | ||
+ | return (gamma()-1.0)*m*RDL_CLIGHT*RDL_CLIGHT; | ||
+ | } | ||
+ | |||
+ | double RDL_Particle::rest_energy(void) | ||
+ | { | ||
+ | return m*RDL_CLIGHT*RDL_CLIGHT; | ||
+ | } | ||
+ | |||
+ | RDL_Vector RDL_Particle::momentum(void) | ||
+ | { | ||
+ | return v*gamma()*m; | ||
+ | } | ||
+ | |||
+ | ostream &operator<<(ostream &out, const RDL_Particle &p) | ||
+ | { | ||
+ | out << "Current state of particle:\n"; | ||
+ | out << " mass: " << p.m << "\n"; | ||
+ | out << " charge: " << p.q << "\n"; | ||
+ | out << " position: " << p.x << "\n"; | ||
+ | out << " velocity: " << p.v << "\n"; | ||
+ | return out; | ||
+ | } | ||
</nowiki></pre> | </nowiki></pre> | ||
Line 310: | Line 367: | ||
<pre><nowiki> | <pre><nowiki> | ||
+ | |||
+ | /* RDLsolver.cpp: The main solver routine for the RDYNLAB package */ | ||
+ | |||
+ | #include <rdynlab.h> | ||
+ | #include <gsl/gsl_odeiv.h> | ||
+ | #include <gsl/gsl_errno.h> | ||
+ | #include <gsl/gsl_math.h> | ||
+ | #include <gsl/gsl_diff.h> | ||
+ | #include <math.h> | ||
+ | #include <iostream> | ||
+ | #include <iomanip> | ||
+ | |||
+ | int RDL_solver(RDL_Particle &p, | ||
+ | RDL_Vector (*force) (const RDL_Particle&, double), | ||
+ | double ti, | ||
+ | double dt, | ||
+ | int (*stopping_conditions) (const RDL_Particle&, double, int), | ||
+ | ostream &out) | ||
+ | { | ||
+ | double y[6]; | ||
+ | double t; | ||
+ | int status,iter,retval; | ||
+ | struct RDL_solver_parameters pars; | ||
+ | |||
+ | /* Initialize the parameters struct */ | ||
+ | |||
+ | pars.p=p; | ||
+ | pars.t=ti; | ||
+ | pars.f=force; | ||
+ | |||
+ | /* Write information to ostream... */ | ||
+ | |||
+ | out << scientific; | ||
+ | out << setprecision(3); | ||
+ | out << setfill(' '); | ||
+ | out << "# Beginning solver iterations. Output columns are as follows\n"; | ||
+ | out << "# (1) Time, in seconds\n"; | ||
+ | out << "# (2) X position of particle, in meters\n"; | ||
+ | out << "# (3) Y position of particle, in meters\n"; | ||
+ | out << "# (4) Z position of particle, in meters\n"; | ||
+ | out << "# (5) X component of velocity, in m/s\n"; | ||
+ | out << "# (6) Y component of velocity, in m/s\n"; | ||
+ | out << "# (7) Z component of velocity, in m/s\n"; | ||
+ | |||
+ | /* Set up GSL ODE solver system */ | ||
+ | |||
+ | const gsl_odeiv_step_type *T=gsl_odeiv_step_rk8pd; | ||
+ | |||
+ | gsl_odeiv_step *s=gsl_odeiv_step_alloc(T,6); | ||
+ | gsl_odeiv_control *c=gsl_odeiv_control_y_new(RDL_TINY,0.0); | ||
+ | gsl_odeiv_evolve *e=gsl_odeiv_evolve_alloc(6); | ||
+ | gsl_odeiv_system sys={RDL_solver_func,NULL,6,&pars}; | ||
+ | |||
+ | /* Initialize variable array */ | ||
+ | |||
+ | y[0]=p.x.x; | ||
+ | y[1]=p.x.y; | ||
+ | y[2]=p.x.z; | ||
+ | y[3]=p.v.x; | ||
+ | y[4]=p.v.y; | ||
+ | y[5]=p.v.z; | ||
+ | |||
+ | /* Print out initial position */ | ||
+ | |||
+ | out << setw(10) << ti << " "; | ||
+ | out << setw(10) << y[0] << " "; | ||
+ | out << setw(10) << y[1] << " "; | ||
+ | out << setw(10) << y[2] << " "; | ||
+ | out << setw(10) << y[3] << " "; | ||
+ | out << setw(10) << y[4] << " "; | ||
+ | out << setw(10) << y[5] << "\n"; | ||
+ | |||
+ | /* Solver loop */ | ||
+ | |||
+ | t=ti; | ||
+ | status=GSL_SUCCESS; | ||
+ | iter=1; | ||
+ | |||
+ | while (t<(RDL_TMAX+ti)) | ||
+ | { | ||
+ | pars.p=p; | ||
+ | pars.t=t; | ||
+ | status=gsl_odeiv_evolve_apply(e,c,s,&sys,&t,(RDL_TMAX+ti),&dt,y); | ||
+ | out << setw(10) << t << " "; | ||
+ | out << setw(10) << y[0] << " "; | ||
+ | out << setw(10) << y[1] << " "; | ||
+ | out << setw(10) << y[2] << " "; | ||
+ | out << setw(10) << y[3] << " "; | ||
+ | out << setw(10) << y[4] << " "; | ||
+ | out << setw(10) << y[5] << "\n"; | ||
+ | /* Update the particle and the struct that carries the info */ | ||
+ | p.x.x=y[0]; | ||
+ | p.x.y=y[1]; | ||
+ | p.x.z=y[2]; | ||
+ | p.v.x=y[3]; | ||
+ | p.v.y=y[4]; | ||
+ | p.v.z=y[5]; | ||
+ | /* Check break conditions */ | ||
+ | if(status!=GSL_SUCCESS) break; | ||
+ | retval=stopping_conditions(p,t,iter); | ||
+ | if(retval) break; | ||
+ | iter++; | ||
+ | } | ||
+ | |||
+ | /* Free memory allocated by GSL */ | ||
+ | |||
+ | gsl_odeiv_evolve_free(e); | ||
+ | gsl_odeiv_control_free(c); | ||
+ | gsl_odeiv_step_free(s); | ||
+ | |||
+ | /* Return */ | ||
+ | |||
+ | if(status!=GSL_SUCCESS) return 0; | ||
+ | else return retval; | ||
+ | |||
+ | } | ||
</nowiki></pre> | </nowiki></pre> | ||
Line 319: | Line 492: | ||
<pre><nowiki> | <pre><nowiki> | ||
+ | |||
+ | /* RDLsolver_func.cpp: This function is needed by the RDYNLAB main routine, and | ||
+ | * should net be called from user space */ | ||
+ | |||
+ | #include <rdynlab.h> | ||
+ | #include <gsl/gsl_odeiv.h> | ||
+ | #include <gsl/gsl_errno.h> | ||
+ | #include <gsl/gsl_math.h> | ||
+ | #include <gsl/gsl_diff.h> | ||
+ | #include <math.h> | ||
+ | #include <iostream> | ||
+ | #include <iomanip> | ||
+ | |||
+ | int RDL_solver_func(double t,const double y[],double f[], void *params) | ||
+ | { | ||
+ | /* Note: variables coming in array y are as follows: | ||
+ | * y[0]: x | ||
+ | * y[1]: y | ||
+ | * y[2]: z | ||
+ | * y[3]: vx | ||
+ | * y[4]: vy | ||
+ | * y[5]: vz */ | ||
+ | |||
+ | /* Extract the particle and force from the input parameters */ | ||
+ | |||
+ | RDL_solver_parameters *pars=(RDL_solver_parameters*)params; | ||
+ | RDL_Particle p=(pars->p); | ||
+ | RDL_Vector (*F)(const RDL_Particle&,const double)=pars->f; | ||
+ | |||
+ | /* Other variables we will need */ | ||
+ | |||
+ | RDL_Vector Fpar,Fperp; | ||
+ | RDL_Vector a; | ||
+ | double gm,g3m; | ||
+ | double dgdt,g; | ||
+ | |||
+ | /* Update position and velocity of the particle from the y array. If I | ||
+ | * don't do this, the solver has no way of testing the accuracy of a step! */ | ||
+ | |||
+ | p.x.x=y[0]; | ||
+ | p.x.y=y[1]; | ||
+ | p.x.z=y[2]; | ||
+ | p.v.x=y[3]; | ||
+ | p.v.y=y[4]; | ||
+ | p.v.z=y[5]; | ||
+ | |||
+ | /* Calculate gamma*m and gamma^3*m */ | ||
+ | |||
+ | g=p.gamma(); | ||
+ | gm=g*p.m; | ||
+ | g3m=g*g*gm; | ||
+ | |||
+ | |||
+ | /* Calculate the components of the force that are parallel and | ||
+ | * perpendicular to the velocity of the particle */ | ||
+ | |||
+ | if(length(p.v)>0.) | ||
+ | { | ||
+ | Fpar=unit(p.v)*(F(p,t)*p.v)/length(p.v); | ||
+ | Fperp=F(p,t)-Fpar; | ||
+ | } | ||
+ | else /* Velocity is zero, no component of force is parallel to velocity! */ | ||
+ | { | ||
+ | Fpar=p.v; | ||
+ | Fperp=F(p,t); | ||
+ | } | ||
+ | |||
+ | /* Calculate the acceleration w/o radiative losses (dv/dt) */ | ||
+ | |||
+ | a=Fperp/gm+Fpar/g3m; | ||
+ | |||
+ | /* Use this acceleration to calculate dgamma/dt, derived from the | ||
+ | * Lienard formula: dgdt = 1/(mc^2) dE/dt */ | ||
+ | |||
+ | dgdt=-RDL_MU0*p.q*p.q*g*g*g*g*g*g; | ||
+ | dgdt=dgdt/(6.*M_PI*p.m*RDL_CLIGHT*RDL_CLIGHT*RDL_CLIGHT); | ||
+ | dgdt=dgdt*(a*a-(p.v^a)*(p.v^a)/(RDL_CLIGHT*RDL_CLIGHT)); | ||
+ | |||
+ | /* Update acceleration with radiative losses */ | ||
+ | |||
+ | a=a+p.v*dgdt/g; | ||
+ | |||
+ | /* Put the time derivatives in the appropriate array */ | ||
+ | |||
+ | f[0]=y[3]; | ||
+ | f[1]=y[4]; | ||
+ | f[2]=y[5]; | ||
+ | f[3]=a.x; | ||
+ | f[4]=a.y; | ||
+ | f[5]=a.z; | ||
+ | |||
+ | /* return */ | ||
+ | |||
+ | return GSL_SUCCESS; | ||
+ | } | ||
</nowiki></pre> | </nowiki></pre> |
Latest revision as of 18:06, 18 June 2009
The following files constitute the source code for RDYNLAB. They can be compiled with any source code intended to use the library functions or (preferably) compiled as a shared object library using GNU autoconf, automake, and libtool. Compiling a shared object library is beyond the scope of this document. The package, with the appropriate configure scripts and makefiles, can be obtained by contacting the author (kelleyk@byui.edu).
It should be noted that the library is written in C++, and will probably only compile or work properly with other C++ codes.
***rdynlab.h***
/* RDYNLAB: Relativistic particle DYNamics in the LAB frame. */ #ifndef _RDYNLAB_H_ #define _RDYNLAB_H_ #include <iostream> using namespace std; /* Some global control parameters */ #define RDL_TINY 1.e+00 /* Required numerical accuracy */ #define RDL_TMAX 1.e+18 /* Maximum time we will ever be allowed to run to. * This number can be rediculously large, since the * stopping time will normally be provided by the * user. */ /* A few constants that we will need */ #define RDL_CLIGHT 2.99792458E8 /* Speed of light in vacuum */ #define RDL_MU0 1.25663706144E-6 /* Permeability of free space, needed for power * loss of charged particles */ /***************************** Vector Class **********************************/ class RDL_Vector { public: double x,y,z; /* The three components of a vector */ /* Construction and destruction operators */ RDL_Vector() {}; ~RDL_Vector() {}; RDL_Vector(double,double,double); /* Operators */ RDL_Vector operator+(const RDL_Vector&); /* Add vectors */ RDL_Vector operator+(void); /* "Positive" of a vector */ RDL_Vector operator-(const RDL_Vector&); /* Subtract vectors */ RDL_Vector operator-(void); /* "Negative" of a vector */ RDL_Vector operator*(double); /* Multiply vector by scalar */ double operator*(const RDL_Vector&); /* Vector dot product */ RDL_Vector operator/(double); /* Divide vector by scalar */ RDL_Vector operator^(const RDL_Vector&); /* Vector cross product */ bool operator==(const RDL_Vector&); /* Are vectors the same? */ /* Friends to this class */ friend ostream &operator<<(ostream &out,const RDL_Vector &V); friend RDL_Vector operator*(double a, const RDL_Vector &V); }; /* Define << operator for vectors */ ostream &operator<<(ostream &out, const RDL_Vector &V); /* Allows us to do scalar times vector */ RDL_Vector operator*(double a, const RDL_Vector &V); /* These return the length of a vector and a unit vector */ double length(const RDL_Vector &V); RDL_Vector unit(const RDL_Vector &V); /***************************** Particle Class ********************************/ class RDL_Particle { public: double q; /* Charge, in Coulombs */ double m; /* Mass, in kg */ RDL_Vector x; /* Position, in meters */ RDL_Vector v; /* Velocity, in m/s */ /* Construction and Destruction operators */ RDL_Particle() {}; ~RDL_Particle() {}; RDL_Particle(double, double, const RDL_Vector&, const RDL_Vector&); /* Init with q,m,x,v */ /* We need to define the = operator */ RDL_Particle operator=(const RDL_Particle&); /* Allow the << operator access... */ friend ostream &operator<<(ostream &out, const RDL_Particle &p); /* Return particle properties */ double gamma(void); /* Returns relativistic factor gamma */ double energy(void); /* Returns total energy */ double kinetic_energy(void); /* Returns kinetic energy */ double rest_energy(void); /* Returns rest energy */ RDL_Vector momentum(void); /* Returns momentum vector */ }; /* Overload << operator for particles */ ostream &operator<<(ostream &out, const RDL_Particle &p); /******************* Struct for passing information to GSL ********************/ struct RDL_solver_parameters { RDL_Particle p; /* The particle */ double t; /* The time */ RDL_Vector (*f)(const RDL_Particle&,double); /* Function returning force */ }; /******************** Declaration of main solver routine **********************/ /* This is the main solver routine. Input parameters are the particle, * a function that returns the force, the initial time, the initial time step, * a function that determines if the simulation should stop, and an ostream for * writing output. * * The force function takes arguments of a particle (which will include position * and velocity) and time. The stopping condition function takes arguments of a * particle (which has the particle's position and velocity), the time, and the * number of iterations the solver has completed. */ int RDL_solver(RDL_Particle&, RDL_Vector (*)(const RDL_Particle&,double), double, double, int (*)(const RDL_Particle&,double,int), ostream&); /* This function is required by the solver routine, and will probably never * need to be called from user space. */ int RDL_solver_func(double t, const double y[], double f[], void *params); #endif
***RDLvector.cpp***
/* RDLvector.c: 3-D vectors and functions */ #include <rdynlab.h> #include <math.h> using namespace std; /* Constructor */ RDL_Vector::RDL_Vector (double xin, double yin, double zin) { x = xin; y = yin; z = zin; } /* Operators */ RDL_Vector RDL_Vector::operator+(const RDL_Vector ¶m) { RDL_Vector temp; temp.x = x + param.x; temp.y = y + param.y; temp.z = z + param.z; return temp; } RDL_Vector RDL_Vector::operator+(void) { RDL_Vector temp; temp.x = x; temp.y = y; temp.z = z; return temp; } RDL_Vector RDL_Vector::operator-(const RDL_Vector ¶m) { RDL_Vector temp; temp.x = x - param.x; temp.y = y - param.y; temp.z = z - param.z; return temp; } RDL_Vector RDL_Vector::operator-(void) { RDL_Vector temp; temp.x = -x; temp.y = -y; temp.z = -z; return temp; } RDL_Vector RDL_Vector::operator*(double a) { RDL_Vector temp; temp.x = x*a; temp.y = y*a; temp.z = z*a; return temp; } double RDL_Vector::operator*(const RDL_Vector ¶m) { double temp; temp = (x * param.x) + (y * param.y) + (z * param.z); return temp; } RDL_Vector RDL_Vector::operator/(double a) { RDL_Vector temp; temp.x = x/a; temp.y = y/a; temp.z = z/a; return temp; } RDL_Vector RDL_Vector::operator^(const RDL_Vector ¶m) { RDL_Vector temp; temp.x = (y * param.z) - (z * param.y); temp.y = (z * param.x) - (x * param.z); temp.z = (x * param.y) - (y * param.x); return temp; } bool RDL_Vector::operator==(const RDL_Vector ¶m) { if(param.x==x && param.y==y && param.z==z) return true; else return false; } /* << operator */ ostream &operator<<(ostream &out, const RDL_Vector &V) { out << "<" << V.x << ", " << V.y << ", " << V.z << ">"; return out; } /* This one allows double*RDL_Vector */ RDL_Vector operator*(double a, const RDL_Vector &V) { RDL_Vector temp; temp.x = V.x*a; temp.y = V.y*a; temp.z = V.z*a; return (temp); } /* Return the length of a vector, unit vector */ double length(const RDL_Vector &V) { RDL_Vector temp=V; return sqrt(temp*temp); } RDL_Vector unit(const RDL_Vector &V) { RDL_Vector temp=V; double s=length(temp); /* Return zero if the length is zero */ if(s>0) return temp/s; else return temp; }
***RDLparticle.cpp***
/* RDLparticle.cpp: defines class for a particle */ #include <rdynlab.h> #include <math.h> RDL_Particle::RDL_Particle(double qin, double min, const RDL_Vector &xin, const RDL_Vector &vin) { q=qin; m=min; x=xin; v=vin; } RDL_Particle RDL_Particle::operator=(const RDL_Particle ¶m) { q=param.q; m=param.m; x=param.x; v=param.v; return *this; } double RDL_Particle::gamma(void) { double s=length(v); return 1./sqrt(1.-s*s/(RDL_CLIGHT*RDL_CLIGHT)); } double RDL_Particle::energy(void) { return gamma()*m*RDL_CLIGHT*RDL_CLIGHT; } double RDL_Particle::kinetic_energy(void) { return (gamma()-1.0)*m*RDL_CLIGHT*RDL_CLIGHT; } double RDL_Particle::rest_energy(void) { return m*RDL_CLIGHT*RDL_CLIGHT; } RDL_Vector RDL_Particle::momentum(void) { return v*gamma()*m; } ostream &operator<<(ostream &out, const RDL_Particle &p) { out << "Current state of particle:\n"; out << " mass: " << p.m << "\n"; out << " charge: " << p.q << "\n"; out << " position: " << p.x << "\n"; out << " velocity: " << p.v << "\n"; return out; }
***RDLsolver.cpp***
/* RDLsolver.cpp: The main solver routine for the RDYNLAB package */ #include <rdynlab.h> #include <gsl/gsl_odeiv.h> #include <gsl/gsl_errno.h> #include <gsl/gsl_math.h> #include <gsl/gsl_diff.h> #include <math.h> #include <iostream> #include <iomanip> int RDL_solver(RDL_Particle &p, RDL_Vector (*force) (const RDL_Particle&, double), double ti, double dt, int (*stopping_conditions) (const RDL_Particle&, double, int), ostream &out) { double y[6]; double t; int status,iter,retval; struct RDL_solver_parameters pars; /* Initialize the parameters struct */ pars.p=p; pars.t=ti; pars.f=force; /* Write information to ostream... */ out << scientific; out << setprecision(3); out << setfill(' '); out << "# Beginning solver iterations. Output columns are as follows\n"; out << "# (1) Time, in seconds\n"; out << "# (2) X position of particle, in meters\n"; out << "# (3) Y position of particle, in meters\n"; out << "# (4) Z position of particle, in meters\n"; out << "# (5) X component of velocity, in m/s\n"; out << "# (6) Y component of velocity, in m/s\n"; out << "# (7) Z component of velocity, in m/s\n"; /* Set up GSL ODE solver system */ const gsl_odeiv_step_type *T=gsl_odeiv_step_rk8pd; gsl_odeiv_step *s=gsl_odeiv_step_alloc(T,6); gsl_odeiv_control *c=gsl_odeiv_control_y_new(RDL_TINY,0.0); gsl_odeiv_evolve *e=gsl_odeiv_evolve_alloc(6); gsl_odeiv_system sys={RDL_solver_func,NULL,6,&pars}; /* Initialize variable array */ y[0]=p.x.x; y[1]=p.x.y; y[2]=p.x.z; y[3]=p.v.x; y[4]=p.v.y; y[5]=p.v.z; /* Print out initial position */ out << setw(10) << ti << " "; out << setw(10) << y[0] << " "; out << setw(10) << y[1] << " "; out << setw(10) << y[2] << " "; out << setw(10) << y[3] << " "; out << setw(10) << y[4] << " "; out << setw(10) << y[5] << "\n"; /* Solver loop */ t=ti; status=GSL_SUCCESS; iter=1; while (t<(RDL_TMAX+ti)) { pars.p=p; pars.t=t; status=gsl_odeiv_evolve_apply(e,c,s,&sys,&t,(RDL_TMAX+ti),&dt,y); out << setw(10) << t << " "; out << setw(10) << y[0] << " "; out << setw(10) << y[1] << " "; out << setw(10) << y[2] << " "; out << setw(10) << y[3] << " "; out << setw(10) << y[4] << " "; out << setw(10) << y[5] << "\n"; /* Update the particle and the struct that carries the info */ p.x.x=y[0]; p.x.y=y[1]; p.x.z=y[2]; p.v.x=y[3]; p.v.y=y[4]; p.v.z=y[5]; /* Check break conditions */ if(status!=GSL_SUCCESS) break; retval=stopping_conditions(p,t,iter); if(retval) break; iter++; } /* Free memory allocated by GSL */ gsl_odeiv_evolve_free(e); gsl_odeiv_control_free(c); gsl_odeiv_step_free(s); /* Return */ if(status!=GSL_SUCCESS) return 0; else return retval; }
***RDLsolver_func.cpp***
/* RDLsolver_func.cpp: This function is needed by the RDYNLAB main routine, and * should net be called from user space */ #include <rdynlab.h> #include <gsl/gsl_odeiv.h> #include <gsl/gsl_errno.h> #include <gsl/gsl_math.h> #include <gsl/gsl_diff.h> #include <math.h> #include <iostream> #include <iomanip> int RDL_solver_func(double t,const double y[],double f[], void *params) { /* Note: variables coming in array y are as follows: * y[0]: x * y[1]: y * y[2]: z * y[3]: vx * y[4]: vy * y[5]: vz */ /* Extract the particle and force from the input parameters */ RDL_solver_parameters *pars=(RDL_solver_parameters*)params; RDL_Particle p=(pars->p); RDL_Vector (*F)(const RDL_Particle&,const double)=pars->f; /* Other variables we will need */ RDL_Vector Fpar,Fperp; RDL_Vector a; double gm,g3m; double dgdt,g; /* Update position and velocity of the particle from the y array. If I * don't do this, the solver has no way of testing the accuracy of a step! */ p.x.x=y[0]; p.x.y=y[1]; p.x.z=y[2]; p.v.x=y[3]; p.v.y=y[4]; p.v.z=y[5]; /* Calculate gamma*m and gamma^3*m */ g=p.gamma(); gm=g*p.m; g3m=g*g*gm; /* Calculate the components of the force that are parallel and * perpendicular to the velocity of the particle */ if(length(p.v)>0.) { Fpar=unit(p.v)*(F(p,t)*p.v)/length(p.v); Fperp=F(p,t)-Fpar; } else /* Velocity is zero, no component of force is parallel to velocity! */ { Fpar=p.v; Fperp=F(p,t); } /* Calculate the acceleration w/o radiative losses (dv/dt) */ a=Fperp/gm+Fpar/g3m; /* Use this acceleration to calculate dgamma/dt, derived from the * Lienard formula: dgdt = 1/(mc^2) dE/dt */ dgdt=-RDL_MU0*p.q*p.q*g*g*g*g*g*g; dgdt=dgdt/(6.*M_PI*p.m*RDL_CLIGHT*RDL_CLIGHT*RDL_CLIGHT); dgdt=dgdt*(a*a-(p.v^a)*(p.v^a)/(RDL_CLIGHT*RDL_CLIGHT)); /* Update acceleration with radiative losses */ a=a+p.v*dgdt/g; /* Put the time derivatives in the appropriate array */ f[0]=y[3]; f[1]=y[4]; f[2]=y[5]; f[3]=a.x; f[4]=a.y; f[5]=a.z; /* return */ return GSL_SUCCESS; }