//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$//*
//             LOW ENERGY MUON SPIN RELAXATION, ROTATION, RADIATION 
// 
//  ID    :LEMuSRElMag_SpinEqRhs.cc , v 1.3
//  AUTHOR: Taofiq PARAISO
//  DATE  : 2004-09-17 10:20
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$//
//
//  &           &&&&&&&&&&                            &&&&&&&         &&&&&&&&
//  &           &                                   &&      &&       &       &&
//  &           &                   &      &       &                &       &&
//  &           &&&&&&&            &      &         &&&&&&         &&&&&&&&  
//  &           &                 &      &&                &      &      &&
//  &           &                &&     &  &     &&      &&      &        &
//  &&&&&&&&&&  &&&&&&&&&&      &  &&&&&    &&    &&&&&&&       &        &&   
//                             &
//                            &
//                           &
//                         &  
//                               ElectroMagnetic Spin Equation   
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$//


#include "LEMuSRElMag_SpinEqRhs.hh"
#include "G4MagneticField.hh"
#include "G4ThreeVector.hh"
#include "G4ios.hh"
#include "G4UnitsTable.hh"
#include "globals.hh"

LEMuSRElMag_SpinEqRhs::LEMuSRElMag_SpinEqRhs( G4MagneticField* MagField )
  : G4Mag_EqRhs( MagField ) {
}

LEMuSRElMag_SpinEqRhs::~LEMuSRElMag_SpinEqRhs() {}


void LEMuSRElMag_SpinEqRhs::SetChargeMomentumMass(G4double particleCharge, // in e+ units
                                       G4double MomentumXc,
                                       G4double mass)
{
   //  To set fCof_val 
   G4Mag_EqRhs::SetChargeMomentumMass(particleCharge, MomentumXc, mass);

   /*   theTrackingAction= LEMuSRTrackingAction::GetInstance();
   G4double gratio=theTrackingAction->GyroMagRatio;
   G4cout <<"g ratio [MHz]/[T]"<<gratio<<G4endl;
   */

   // Get the gyromagnetic ratio via the event manager
   G4EventManager* evtMgr = G4EventManager::GetEventManager();
   G4Track* theTrack = evtMgr->GetTrackingManager()->GetTrack();
   G4double gratio= theTrack->GetDefinition()->GetGyromagneticRatio();
   //   G4cout <<"g ratio [MHz]/[T]"<<gratio<<G4endl;
   
   omegac =gratio;// 0.105658387*GeV/mass * 2.837374841e-3*(rad/cm/kilogauss);


#ifdef DEBUG
   anomaly =1.165923e-3;
   oldomegac= 0.105658387*GeV/mass * 2.837374841e-3*(rad/cm/kilogauss);
   //G4cout<< "Old FrequencyG: " << G4BestUnit(oldomegac*gauss/(2*M_PI*rad)*cm,"Frequency") <<G4endl;
#endif
   //G4cout<< "FrequencyG: " << G4BestUnit(gratio*gauss,"Frequency") <<G4endl;

   ParticleCharge = particleCharge;

   E = sqrt(sqr(MomentumXc)+sqr(mass));
   beta  = MomentumXc/E;
   gamma = E/mass;
   m_mass=mass;

  cst = particleCharge*eplus*m_mass;

}


void LEMuSRElMag_SpinEqRhs::EvaluateRhsGivenB( const G4double y[],
			            const G4double B[6],
				    G4double dydx[] ) const
{
  G4double momentum_square = y[3]*y[3] + y[4]*y[4] + y[5]*y[5];
  G4double inv_momentum_magnitude = 1.0 / sqrt( momentum_square );

  G4double cof = FCof()*inv_momentum_magnitude;
  G4double cofe = cst*inv_momentum_magnitude;

   dydx[0] = y[3] * inv_momentum_magnitude;       //  (d/ds)x = Vx/V
   dydx[1] = y[4] * inv_momentum_magnitude;       //  (d/ds)y = Vy/V
   dydx[2] = y[5] * inv_momentum_magnitude;       //  (d/ds)z = Vz/V

   dydx[3] = cofe*B[3] + cof*(y[4]*B[2] - y[5]*B[1]) ;   // Ax = a*(Ex+Vy*Bz - Vz*By)
   dydx[4] = cofe*B[4] + cof*(y[5]*B[0] - y[3]*B[2]) ;   // Ay = a*(Ey+Vz*Bx - Vx*Bz)
   dydx[5] = cofe*B[5] + cof*(y[3]*B[1] - y[4]*B[0]) ;   // Az = a*(Ez+Vx*By - Vy*Bx)
   
   
   G4ThreeVector u(y[3], y[4], y[5]);
   u *= inv_momentum_magnitude; 
   
   G4ThreeVector BField(B[0],B[1],B[2]);


   // Initialise the values of dydx that we do not update.
   dydx[6] =  dydx[8] = 0.0;

   //unit of momentum is mev/c in this case
   G4double velocity=(sqrt(momentum_square)/m_mass)*c_light;

   dydx[7]=1./velocity;  //dt/ds
   //G4cout <<"\nmass"<<m_mass/MeV;  


   G4ThreeVector Spin(y[9],y[10],y[11]);
   G4ThreeVector dSpin;

#ifdef DEBUG   
   G4double udb = anomaly*beta*gamma/(1.+gamma) * (BField * u); 
   G4double ucb = (anomaly+1./gamma)/beta;
   dSpin = ParticleCharge*oldomegac*(ucb*(Spin.cross(BField))-udb*(Spin.cross(u)));
   G4cout<<"Old dSpin" << dSpin<<G4endl;
#endif
   
   // Calculation of dSpin according to theory for ex. Cohen-Tannoudji I p449
   // dSpin/dt=gyromag_ratio*S^B
   // dVar/ds=dVar/dt*mass/|mom|
   //
   
   dSpin =(Spin.cross(BField))*1./velocity*omegac;//multiply by gyromag ratio
#ifdef DEBUG
   G4cout<<"New dSpin" << dSpin<<G4endl;
#endif
   
   
   dydx[ 9] = dSpin.x();
   dydx[10] = dSpin.y();
   dydx[11] = dSpin.z();
   
   /*        G4cout<<"LEMuSRMAg_SpinEqRhs :: dydx \n"  
	     << dydx[0] <<"    " << dydx[1] <<"    "<< dydx[2] <<"    "<<"\n"
	     << dydx[3] <<"    " << dydx[4] <<"    "<< dydx[5] <<"    "<<"\n"
	     << dydx[6] <<"    " << dydx[7] <<"    "<< dydx[8] <<"    "<<"\n"
	     << dydx[9] <<"    " << dydx[10] <<"    "<< dydx[11] <<"     "<<"\n";
   */
   
   return ;
}

  
