/*
 * Copyright University of Reims Champagne-Ardenne
 * Authors and Contributors: Akilan RAJAMANI, Corentin LEFEBVRE, Johanna KLEIN,
 *                           Emmanuel PLUOT, Gaetan RUBEZ, Hassan KHARTABIL,
 *                           Jean-Charles BOISSON and Eric HENON
 * (24/07/2017)
 * jean-charles.boisson@univ-reims.fr, eric.henon@univ-reims.fr
 *
 * This software is a computer program whose purpose is to
 * detect and quantify interactions from electron density
 * obtained either internally from promolecular density or
 * calculated from an input wave function input file. It also
 * prepares for the visualization of isosurfaces representing
 * several descriptors (dg) coming from the IGM methodology.
 *
 * This software is governed by the CeCILL-C license under French law and
 * abiding by the rules of distribution of free software.  You can  use,
 * modify and/ or redistribute the software under the terms of the CeCILL-C
 * license as circulated by CEA, CNRS and INRIA at the following URL
 * "http://www.cecill.info".
 *
 * As a counterpart to the access to the source code and  rights to copy,
 * modify and redistribute granted by the license, users are provided only
 * with a limited warranty  and the software's author,  the holder of the
 * economic rights,  and the successive licensors  have only  limited
 * liability.
 *
 * In this respect, the user's attention is drawn to the risks associated
 * with loading,  using,  modifying and/or developing or reproducing the
 * software by the user in light of its specific status of free software,
 * that may mean  that it is complicated to manipulate,  and  that  also
 * therefore means  that it is reserved for developers  and  experienced
 * professionals having in-depth computer knowledge. Users are therefore
 * encouraged to load and test the software's suitability as regards their
 * requirements in conditions enabling the security of their systems and/or
 * data to be ensured and,  more generally, to use and operate it in the
 * same conditions as regards security.
 *
 * The fact that you are presently reading this means that you have had
 * knowledge of the CeCILL-C license and that you accept its terms.
 *
 * */

/**
 * @file LocalData.h
 * @brief Class designed to store Gradient related values and provide some utilities concerning those
 * @warning No copy constructor defined, careful when trying to pass this by value
 * @author Emmanuel */

#ifndef _LOCAL_DATA_H_
#define _LOCAL_DATA_H_

// Local
//#include <eig3.h>
#include <toolbox.h>

/**
 * @brief Class designed to store Gradient related values and provide some utilities concerning those
 * @warning No copy constructor defined, careful when trying to pass this by value */
class LocalData
{
  
 private :
  
  //  Non Gradient related values
  
  //! Number of atom in the first molecule
  int nbAtomInMolA;
  //! Number of atoms
  int nbAtom;
		
  // Gradient values

  //! ED Gradient values
  double grad[3];

  //! ED Gradient IGM values
  double gradIGM[3];

  //! Contribution ED gradient inside molecule A
  double contributionInsideMoleculeA[3];

  //! Contribution ED gradient inside molecule B
  double contributionInsideMoleculeB[3];

  //! Contribution ED gradient for focused atom alone or all
  axis_t * contributionAtomicAlone;
		
  // Unique initialization gradient values

  //! Axis values for IGM Inter
  double gradIGMInter[3];

  //! Axis values for IGM Inter ( | molA + Atom | )
  double gradIGMAbsOut[3];

  //! Axis values for IGM Inter ( | molA | + | atom | )
  double gradIGMAbsIn[3];
		
  // Vectors' norms' values

  //! Gradient's vector's norm
  double normGrad;

  //! Gradient IGM's vector's norm
  double normGradIGM;

  //! Gradient IGM inter's vector's norm
  double normGradIGMInter;

  //! Gradient IGM inter's vector's norm (| molA + Atom |)
  double normGradIGMInterAbsOut;

  //! Gradient IGM inter's vector's norm (|molA| + |Atom|)
  double normGradIGMInterAbsIn; 
		
 public :
	
  /**
   * @fn LocalData(int nbAtomInMolAParam, int nbAtomParam, Focusor &focParam)
   * @brief Constructor
   * @param nbAtomInMolAParam the number of atom in the first molecule
   * @param nbAtomParam the number of atom */
  LocalData(int nbAtomInMolAParam, int nbAtomParam);
		
  /**
   * @fn ~LocalData()
   * @brief Destructor that frees space for the atom's contribution */
  ~LocalData();
		 
  /**
   * @fn void init()
   * @brief Function used to initialize values to 0 */
  void init();
		 
  /**
   * @fn void reinit()
   * @brief Function used to reinitialize values to 0 */
  void reinit();
		
  /**
   * @fn void updateGrad( int i, axis_t partialGrad )
   * @brief Function used to update the values using index and partial gradients passed as arguments
   * @param i Index value
   * @param partialGrad Partial Gradient for all three axis */
  void updateGrad( int i, axis_t partialGrad );
					
  /**
   * @fn void updateIGMInter()
   * @brief Updates the IGM inter */
  void updateIGMInter();
				
  /**
   * @fn void updateIGMAbsOut(int atomIndex)
   * @brief Updates the IGM with the absolute value of the interaction of molecule A and the atom alone summed up
   * @param atomIndex : the index of the atom relevant to the update */
  void updateIGMAbsOut(int atomIndex);
				
  /**
   * @fn void updateIGMAbsIn(int atomIndex)
   * @brief Updates the IGM with the sum of the absolute value of the molecule A and the absolute value of the atom
   * @param atomIndex : the index of the atom relevant to the update */
  void updateIGMAbsIn(int atomIndex);
				
  /**
   * @fn double getNormGrad()
   * @brief GEts the vector's norm for gradient
   * @return vector's norm */
  double getNormGrad();
		
  /**
   * @fn void processNormGrad()
   * @brief Process the vector's norm for gradient */
  void processNormGrad();
		
  /**
   * @fn double getNormGradIGM()
   * @brief Gets the vector's norm for gradient IGM
   * @return vector's norm */
  double getNormGradIGM();
		
  /**
   * @fn void processNormGradIGM()
   * @brief Process the vector's norm for gradient IGM */
  void processNormGradIGM();
		
  /**
   * @fn double getNormGradIGMInter()
   * @brief Gets the vector's norm for gradient inter
   * @return vector's norm */
  double getNormGradIGMInter();
		
  /**
   * @fn void processNormGradIGMInter()
   * @brief Process the vector's norm for gradient inter */
  void processNormGradIGMInter();
		
  /**
   * @fn double getNormGradIGMAbsOut()
   * @brief GEts the vector's norm for gradient inter with absolute value of the sum of molecule A's interactions and the atom alone's interactions
   * @warning Please note that this function directly depend on the atom given during the process
   * @return vector's norm */
  double getNormGradIGMAbsOut();
		
  /**
   * @fn void processNormGradIGMAbsOut(int i)
   * @brief Process the vector's norm for gradient inter with absolute value of the sum of molecule A's interactions and the atom alone's interactions
   * @param i the atom's index */
  void processNormGradIGMAbsOut(int i);
		
  /**
   * @fn double getNormGradIGMAbsIn()
   * @brief Gets the vector's norm for gradient inter with the sum of the absolute value of molecule A's interactions and the absolute value of the atom alone's interactions
   * @warning Please note that this function directly depend on the atom given during the process
   * @return vector's norm */
  double getNormGradIGMAbsIn();
		
  /**
   * @fn void processNormGradIGMAbsIn(int i)
   * @brief Process the vector's norm for gradient inter with the sum of the absolute value of molecule A's interactions and the absolute value of the atom alone's interactions
   * @param i the atom's index */
  void processNormGradIGMAbsIn(int i);		
		
		
  /********************************************************************/
  /**************************OUTPUT UTILITIES**************************/
  /********************************************************************/
		
  /**
   * @fn double getGradVal(int index)
   * @brief Gets the gradient value at the index given
   * @param index : the index value
   * @return the current gradient value at the given index */
  double getGradVal(int index);
		
  /**
   * @fn void setGradNull()
   * @brief Sets the gradient values to 0 */
  void setGradNull();	

}; // end of class LocalData

#endif
