//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$//*
//             LOW ENERGY MUON SPIN RELAXATION, ROTATION, RADIATION 
// 
//  ID    :LEMuSRElectricField.hh , v 1.3
//  AUTHOR: Taofiq PARAISO
//  DATE  : 2004-09-17 10:20
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$//
//
//  &           &&&&&&&&&&                            &&&&&&&         &&&&&&&&
//  &           &                                   &&      &&       &       &&
//  &           &                   &      &       &                &       &&
//  &           &&&&&&&            &      &         &&&&&&         &&&&&&&&  
//  &           &                 &      &&                &      &      &&
//  &           &                &&     &  &     &&      &&      &        &
//  &&&&&&&&&&  &&&&&&&&&&      &  &&&&&    &&    &&&&&&&       &        &&   
//                             &
//                            &
//                           &
//                         &  
//                               Electric Field   
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$//

/**
 * The goal of the LEMuSRElectricField class is to read field maps generated by 
 * COMSOL Multiphysics. 
 * \image html field.gif Example of a field map generated using COMSOL.
 * Those field maps are shared into three ascii files, one per field component, 
 * in the format (x y z B_i). 
 * LEMuSRElectricField reads those files and store them in an array.
 * Some important parameters must be specified to read a field map:
 * -# <b> The number of points</b> along each axis which was  defined in COMSOL 
 * before exporting the maps. 
 *    - It is very important to check that the number of points do not 
 * exceed the size of the array defined in LEMuSRElectricField.hh
 * -# <b> The unit of the map</b>, which is an important parameter because the 
 * default distance unit in COMSOL is the meter. 
 *    - A different unit has an influence
 * on the coordinates reading, but also on the actual field value which has to
 * be scaled consequently.
 * -# The voltage to use because field maps are calculated for 1kV potential. 
 * The user should indicate the actual voltage to multiply the fields values.
 * -# The offset along z axis, in case the map is not centered on the actual
 * postition of the field. This is the case for the third lense field for example:
 * the map is centered on (0, 0, 0) and the center or the lens is at (0, 0, -567mm).
 * .
 * The field maps can be very heavy files and reading them can cost a lot of time.
 * For this reason, it is possible to write the field map array in a single file
 * after the first reading. 
 */

#ifndef LEMUSRELECTRICFIELD_H
#define LEMUSRELECTRICFIELD_H 1
 
#include"G4ElectricField.hh"
#include"G4ElectroMagneticField.hh"
#include "globals.hh"
#include "G4ios.hh"

#include <iomanip.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <cmath>
#include "CLHEP/Matrix/Vector.h"
#include "CLHEP/Matrix/Matrix.h"



class LEMuSRElectricField : public G4ElectricField
{
public:
 
  //! Constructor from three field maps
  LEMuSRElectricField(G4double fieldval,const char* Xfile, 
		      const char* Yfile,
		      const char* Zfile,G4String map_length_unit,
		      G4double Offset, G4double nx, G4double ny, G4double nz);//offset must be entered in millimeter
  
  //! Contructor from a single field map
  LEMuSRElectricField(G4double fieldval,const char* file,G4String map_length_unit,	
		      G4double Offset, G4double nx, G4double ny, G4double nz);
  
  
  ~LEMuSRElectricField();
  
  //! Returns the field value at Point[4] space-time coordinate.
  /*!
   * This method is in charge of returning the field value for a given position.
   * It scales the field array according to the unit and interpolates the field
   * value from the cube surrounding Point[4]. 
   */
  void GetFieldValue(const G4double Point[4], G4double *Bfield) const;

  //! Debugging test.  
  void Test();
  
public:
  //    std::vector< std::vector< std::vector< G4double > > > xField; // vector of 
  // vector of 
  // vector of G4doubles [[[a]i]j]k
 
  //    std::vector< std::vector< std::vector< G4double > > > yField;
  //    std::vector< std::vector< std::vector< G4double > > > zField;
 
  //! Bx, By, Bz, for all x positions
   G4double xField[90][90][201];
  //! Bx, By, Bz, for all y positions
   G4double yField[90][90][201];
  //! Bx, By, Bz, for all z positions
   G4double zField[90][90][201]; 

  //! The physical limits of the defined region
  G4double minx, maxx, miny, maxy, minz, maxz;
  
  G4double
    //! Number of divisions along axis.
    nx,ny,nz, 
    //! Offset along propagation axis 
    zOffset, 
    //! Actual voltage value.
    FieldVal;

  //! Unit of the field map.
  G4String map_unit;
};

#endif


