//
// ********************************************************************
// * License and Disclaimer                                           *
// *                                                                  *
// * The  Geant4 software  is  copyright of the Copyright Holders  of *
// * the Geant4 Collaboration.  It is provided  under  the terms  and *
// * conditions of the Geant4 Software License,  included in the file *
// * LICENSE and available at  http://cern.ch/geant4/license .  These *
// * include a list of copyright holders.                             *
// *                                                                  *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work  make  any representation or  warranty, express or implied, *
// * regarding  this  software system or assume any liability for its *
// * use.  Please see the license in the file  LICENSE  and URL above *
// * for the full disclaimer and the limitation of liability.         *
// *                                                                  *
// * This  code  implementation is the result of  the  scientific and *
// * technical work of the GEANT4 collaboration.                      *
// * By using,  copying,  modifying or  distributing the software (or *
// * any work based  on the software)  you  agree  to acknowledge its *
// * use  in  resulting  scientific  publications,  and indicate your *
// * acceptance of all terms of the Geant4 Software license.          *
// ********************************************************************
//
#ifndef G4RadioactiveDecay_h
#define G4RadioactiveDecay_h 1
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// MODULE:              G4RadioactiveDecay.hh
//
// Version:             0.b.4
// Date:                14/04/00
// Author:              F Lei & P R Truscott
// Organisation:        DERA UK
// Customer:            ESA/ESTEC, NOORDWIJK
// Contract:            12115/96/JG/NL Work Order No. 3
//
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
// CHANGE HISTORY
// --------------
//
// 29 February 2000, P R Truscott, DERA UK
// 0.b.3 release.
//
// 13 April 2000, F Lei, DERA UK
// 0.b.4 release. No change to this file     
//
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
////////////////////////////////////////////////////////////////////////////////
//
#include "G4ios.hh"
#include "globals.hh"
#include "G4VRestDiscreteProcess.hh"
#include "G4ParticleChangeForRadDecay.hh"
#include "G4RadioactiveDecaymessenger.hh"  

#include "G4NucleusLimits.hh"
#include "G4RadioactiveDecayRate.hh"
#include "G4RadioactiveDecayRateVector.hh"
#include "G4RIsotopeTable.hh"
#include <vector>

//class G4UserlimitsForRD;

////////////////////////////////////////////////////////////////////////////////
//
class G4RadioactiveDecaymessenger;

typedef std::vector<G4RadioactiveDecayRateVector> G4RadioactiveDecayRateTable;
typedef std::vector<G4RadioactiveDecayRate> G4RadioactiveDecayRates;

class G4RadioactiveDecay : public G4VRestDiscreteProcess 
{
  // class description
  
  // Implementation of nuclear radioactive decay process. 
  // It simulates the decays of radioactive nuclei, which is submitted to RDM in the form
  // of G4Ions. Half-liffe and decay schemes are hold in the Radioactivity database
  // All decay products are submitted back to the particle tracking process through 
  // the G4ParticleChangeForRadDecay object.

  // class description - end 
  
public: // with description

  G4RadioactiveDecay (const G4String& processName="RadioactiveDecay");
  ~G4RadioactiveDecay();
  // constructor and destructor
  //

  G4bool IsApplicable(const G4ParticleDefinition &);
  // Returns true if the specified isotope is
  //  1) defined as "nucleus" and
  //  2) it is within theNucleusLimit
  //
  G4bool IsLoaded (const G4ParticleDefinition &);
  // Returns true if the decay table of the specified nuclei is ready.
  //
  void SelectAVolume(const G4String aVolume);
  // Select a logical volume in which RDM applies.
  //
  void DeselectAVolume(const G4String aVolume);
  // remove a logical volume from the RDM applied list
  //
  void SelectAllVolumes();
  // Select all logical volumes for the application of RDM.
  //
  void DeselectAllVolumes();
  // Remove all logical volumes from RDM applications.
  //
  void SetDecayBias (G4String filename);
  //   Sets the decay biasing scheme using the data in "filename"
  //
  void SetHLThreshold (G4double hl) {halflifethreshold = hl;}
  // Set the half-life threshold for isomer production
  //
  void SetICM (G4bool icm) {applyICM = icm;}
  // Enable/disable ICM 
  //
  void SetARM (G4bool arm) {applyARM = arm;}
  // Enable/disable ARM
  // 
  void SetSourceTimeProfile (G4String filename) ;
  //  Sets source exposure function using histograms in "filename"
  //
  G4bool IsRateTableReady(const G4ParticleDefinition &);
  // Returns true if the coefficient and decay time table for all the
  // descendants of the specified isotope are ready.
  //
  // used in VR decay mode only 
  //
  void AddDecayRateTable(const G4ParticleDefinition &);
  // Calculates the coefficient and decay time table for all the descendants
  // of the specified isotope.  Adds the calculated table to the private data
  // member "theDecayRateTableVector".
  //
  //
  // used in VR decay mode only 
  //
  void GetDecayRateTable(const G4ParticleDefinition &);
  // Used to retrieve the coefficient and decay time table for all the
  // descendants of the specified isotope from "theDecayRateTableVector"
  // and place it in "theDecayRateTable".
  //
  //
  // used in VR decay mode only 
  //
  void SetDecayRate(G4int,G4int,G4double, G4int, std::vector<G4double>,
                    std::vector<G4double>);
  // Sets "theDecayRate" with data supplied in the arguements.
  //
  //  //
  // used in VR decay mode only 
  //

  G4DecayTable *LoadDecayTable (G4ParticleDefinition & theParentNucleus);
  // Load the decay data of isotope theParentNucleus.
  //
  inline void  SetVerboseLevel(G4int value) {verboseLevel = value;}
  // Sets the VerboseLevel which controls duggering display.
  //
  inline G4int GetVerboseLevel() const {return verboseLevel;}
  // Returns the VerboseLevel which controls level of debugging output.
  //
  inline void SetNucleusLimits(G4NucleusLimits theNucleusLimits1)
  {theNucleusLimits = theNucleusLimits1 ;}
  //  Sets theNucleusLimits which specifies the range of isotopes
  //  the G4RadioactiveDecay applies.
  //
  inline G4NucleusLimits GetNucleusLimits() const
  {return theNucleusLimits;}
  //  Returns theNucleusLimits which specifies the range of isotopes
  //  the G4RadioactiveDecay applies.
  //
  inline void SetAnalogueMonteCarlo (G4bool r ) { AnalogueMC  = r; }
  //   Controls whether G4RadioactiveDecay runs in analogue mode or
  //   variance reduction mode.
  inline void SetFBeta (G4bool r ) { FBeta  = r; }
  //   Controls whether G4RadioactiveDecay uses fast beta simulation mode
  //
  inline G4bool IsAnalogueMonteCarlo () {return AnalogueMC;}
  //   Returns true if the simulation is an analogue Monte Carlo, and false if
  //   any of the biassing schemes have been selected.
  //
  inline void SetBRBias (G4bool r ) { BRBias  = r;
  SetAnalogueMonteCarlo(0);}
  //   Sets whether branching ration bias scheme applies.
  //
  inline void SetSplitNuclei (G4int r) { NSplit = r; SetAnalogueMonteCarlo(0); }
  //  Sets the N number for the Nuclei spliting bias scheme
  //
  inline G4int GetSplitNuclei () {return NSplit;}
  //  Returns the N number used for the Nuclei spliting bias scheme
  //
public:
  
  void BuildPhysicsTable(const G4ParticleDefinition &);

protected:

  G4VParticleChange* DecayIt( const G4Track& theTrack,
                              const G4Step&  theStep);

  G4DecayProducts* DoDecay(G4ParticleDefinition& theParticleDef);

  G4double GetMeanFreePath(const G4Track& theTrack,
                           G4double previousStepSize,
                           G4ForceCondition* condition);

  G4double GetMeanLifeTime(const G4Track& theTrack,
                           G4ForceCondition* condition);

  G4double GetTaoTime(G4double,G4double);

  G4double GetDecayTime();

  G4int GetDecayTimeBin(const G4double aDecayTime);

private:

  G4RadioactiveDecay(const G4RadioactiveDecay &right);
  G4RadioactiveDecay & operator=(const G4RadioactiveDecay &right);

private:

  G4RadioactiveDecaymessenger  *theRadioactiveDecaymessenger;

  G4PhysicsTable               *aPhysicsTable;

  G4RIsotopeTable              *theIsotopeTable;

  G4NucleusLimits               theNucleusLimits;

  const G4double                HighestBinValue;
  const G4double                LowestBinValue;

  const G4int                   TotBin;

  G4bool                        AnalogueMC;
  G4bool                        BRBias;
  G4bool                        FBeta;
  G4int                         NSplit;

  G4double                      halflifethreshold;
  G4bool                        applyICM;
  G4bool                        applyARM;

  G4int                         NSourceBin;
  G4double                      SBin[99];
  G4double                      SProfile[99];

  G4int                         NDecayBin;
  G4double                      DBin[99];
  G4double                      DProfile[99];

  std::vector<G4String>         LoadedNuclei;
  std::vector<G4String>         ValidVolumes;

  G4RadioactiveDecayRate        theDecayRate;
  G4RadioactiveDecayRates       theDecayRateVector;
  G4RadioactiveDecayRateVector  theDecayRateTable;
  G4RadioactiveDecayRateTable   theDecayRateTableVector;

  static const G4double         levelTolerance;

  // Remainder of life time at rest
  G4double                      fRemainderLifeTime;

  G4int                         verboseLevel;


  // ParticleChange for decay process
  G4ParticleChangeForRadDecay   fParticleChangeForRadDecay;

  inline G4double AtRestGetPhysicalInteractionLength
    (const G4Track& track, G4ForceCondition* condition)
  {fRemainderLifeTime = G4VRestDiscreteProcess::
    AtRestGetPhysicalInteractionLength(track, condition );
  return fRemainderLifeTime;}

  inline G4VParticleChange* AtRestDoIt
    (const G4Track& theTrack, const G4Step& theStep)
  {return DecayIt(theTrack, theStep);}

  inline G4VParticleChange* PostStepDoIt
    (const G4Track& theTrack, const G4Step& theStep)
  {return DecayIt(theTrack, theStep);}

};
#endif







