//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//             LOW ENERGY MUON SPIN RELAXATION, ROTATION, RADIATION 
//
//  ID    : LEMuSRAtRestSpinRotation.hh , v 1.3
//  AUTHOR: Taofiq PARAISO
//  DATE  : 2006-01-19 16:15
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//
//  &           &&&&&&&&&&                            &&&&&&&         &&&&&&&&
//  &           &                                   &&      &&       &       &&
//  &           &                   &      &       &                &       &&
//  &           &&&&&&&            &      &         &&&&&&         &&&&&&&&  
//  &           &                 &      &&                &      &      &&
//  &           &                &&     &  &     &&      &&      &        &
//  &&&&&&&&&&  &&&&&&&&&&      &  &&&&&    &&    &&&&&&&       &        &&   
//                             &
//                            &
//                           &
//                         &  
//                               AT REST SPIN ROTATION   
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$



/**
 *The LEMuSRAtRestSpinRotation class contains the implementation of the muon spin 
 *precession in a magnetic field when the muon is at rest.
 *
 *To implement a process one should create a particle change object.
 *
 *Indeed, in Geant4, a process is simply the change of an old particle to a new
 *one. Hence, this spin rotation process will just replace the muon by another
 *one with spin rotated, but same parameters of time, position, etc.
 *
 *The particle change object registers all the parameters of the new particle, 
 *like the change in time, the momentum direction, the position, the polarization but also
 *the type of the particle, which can be changed also as in the muonium formation
 *process (cf.LEMuSRMUONIUM ).
 *
 *At each step of a track Geant4 we check the list possible processes to excecute
 *(cf. LEMuSRPhysicsList) and will select them according to the priority which was
 *given by the user and to the state of the particle. Indeed, the user should
 *indicate if the process should be ran at rest, before and/or after the step.
 *
 *
 *Some processes can be implemented such that the behaviour in different in those
 *three different cases.
 *
 *Hence the class G4VProcess contains three important virtual methods:
 * -# PreStepDoIt()
 * -# PostStepDoIt()
 * -# AtRestDoIt()
 * . 
 *In the present implementation, we only use the  AtRestDoIt() method.
*/


#ifndef LEMUSRATRESTSPINROTATION_H
#define LEMUSRATRESTSPINROTATION_H 1


#include "G4VRestProcess.hh"
#include "G4DynamicParticle.hh"
#include "G4MagneticField.hh"
#include "G4ParticleTypes.hh"
#include "globals.hh"
#include "G4VParticleChange.hh"
#include "G4ios.hh"
#include "G4ForceCondition.hh"
#include "G4ParticleChangeForTransport.hh"
#include "LEMuSRParticleChangeForSR.hh"


/*!
 * This class is a public class of the G4VRestProcess class, 
 * which contains virtual methods to execute a process when a particle
 * is at rest.
 */
class LEMuSRAtRestSpinRotation : public G4VRestProcess
{


public:
  
//! The constructor specifies the process name.
  LEMuSRAtRestSpinRotation(const G4String& processName =  "SpinRotationAtRest" );
  LEMuSRAtRestSpinRotation(G4VRestProcess& );
  
  virtual ~LEMuSRAtRestSpinRotation();
 
  //! Method to return a pointer to the spin rotation process instance. 
  static LEMuSRAtRestSpinRotation* GetInstance();

  
private: 
  
//! The pointer to the process
  /**
      One can use it to communicate with the process and get information about different parameters
    */ 
  static LEMuSRAtRestSpinRotation* pointer;
  
  
public:


  //!The main method to execute the spin precession process.
  G4VParticleChange* AtRestDoIt(const G4Track& theTrack, const G4Step& theStep);
  
  
  G4double
  //! The muon position-time is given to the method GetFieldValue in order to get the magnetic field vector.
  point[4];
  G4double 
  //! The magnetic field vector at the point[4] position.
  B[3], 
  //! The spin rotation angle computed in the RotateSpin method
  rotation_angle;
  G4double 
  //! The initial time. 
  itime, 
  //! The final time.
  ftime, 
  //! The time variation. 
  deltatime;
  G4ThreeVector SpinDirection;

  //! The particle change object which stores all the proposed modification of the particle's state.
  LEMuSRParticleChangeForSR theParticleChange;
  

  const G4Field *mfield;



  void  RotateSpin(const G4Step&, G4ThreeVector, G4double);

  
  inline G4double GetMeanLifeTime(const G4Track&, G4ForceCondition* condition)
  {
    *condition = Forced;
    return DBL_MAX;
  }
  
  /*! The particle's polarization vector.*/ 
  G4ThreeVector polar;  
  
  
  
};
#endif
