/*
 * 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 general.h
 * @brief all data types and constant data needed by the rest of the program
 * @author Emmanuel */

#ifndef _GENERAL_H_
#define _GENERAL_H_

// STL
#include <cmath>
#include<string>
#include <set>
#include <sstream>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <fstream>
#include <cstdlib>
#include <vector>


//! Threshold for considering PAuli repulsion in TOPELF treatment
//const double  PauliThresh = 1.0E-20; // kcal/mol/bohr^3
const double  PauliThresh = 0.0;

//! accuracy for primitive calculation according to the J. Pilme procedure 
const double  maxElecAccurlev1 = 0.999999;    // default value is 0.999999for ELF, SELF, IGM
const double  maxElecAccurlev2 = 0.9999999;  // value for IBSI   calculations 
const double  maxElecAccurlev3 = 0.999999999; // value for CRITIC calculations 
const double  maxElecAccurlev4 = 0.9999999999999999999; // full accuracy mode              

// epsilon in dgscaled = dg/(rho + epsilon)
const double epsrhodgscaled = 0.0005;

// dg Threshold used to calculate dg/rho. Only
// those points for which dg > dgThresholdForDGSCALED will be used
// in dg/rho calculations (inter and intra) and then in Pauli calculations also
// to avoid numerical inaccuracy in building dg/rho isosurfaces
//const double dgThresholdForDGSCALED =0.0001; 
const double dgThresholdForDGSCALED =0.00001; 

// Rho Threshold used to calculate dg/rho. Only
// those points for which rho > rhoThresholdForDGSCALED will be used
// in dg/rho calculations (inter and intra) and then To project steric repulsion regions 
// to avoid numerical inaccuracy in building dg/rho isosurfaces
const double rhoThresholdForDGSCALED =0.000001; 


// isovalue for dg/rho isovalues
// Dividing by rho makes the dg/rho scale 
// in the range [0-2.5] (observed so far)
// over the all spectrum of interactions ! (strong or weak) 
const double dgSCALEDisovalue = 0.8;

// ED threshold for calculating Pauli repulsion
const double PauliRhoThresh = 1E-5;

// Local AO overlap (chi_a x chi_b) threshold for calculating Pauli repulsion
const double OV_thresh = 1E-5;

// Local AO (chi_a) threshold for calculating Pauli repulsion
const double chi_thresh = 1E-5;


// range for Pauli exchange repulsion (G - GW)
// so far observed
const double pauliMIN = 0.0;
const double pauliMAX = 2.5;

// conversion from Ekin in a.u to kcal/mol
const double ekin2kcal = 627.51;


// threshold in dg/rho descriptor to integrate pauli repulsion
const double pauliDgOverRhoThreshold = 0.1;

// ELF isovalue to draw ELF isosurfaces (default) with VMD
const double elfIsovalue = 0.83;

// threshold used to know if the GTO is zero or not
// based on the value of the exponent of the GTO
// -40 is the original value
const double exponThreshold = -40.0;

// pda epsilon for cylinder
const double epsCyl = 0.0001;

//! Value to transform to Bohr to Anstgrom
const double BOHRTOA = 0.52917720859;

// MEDIUM grid increments used in the search of critical points with seeds
// found from a promolecular IGM analysis:
const double incrCRITICMEDIUMx = 0.15*BOHRTOA; // in angstroms
const double incrCRITICMEDIUMy = 0.14*BOHRTOA; // no symetrical values are chosen on purpose 
const double incrCRITICMEDIUMz = 0.12*BOHRTOA; // to avoid any problem during the search of qg max values in the grid

// FINE grid increments used in the search of critical points with seeds
// found from a promolecular IGM analysis (will take about 4 more times)
const double incrCRITICFINEx = incrCRITICMEDIUMx/1.5874; // in angstroms
const double incrCRITICFINEy = incrCRITICMEDIUMy/1.5874; // no symetrical values are chosen on purpose 
const double incrCRITICFINEz = incrCRITICMEDIUMz/1.5874; // to avoid any problem during the search of qg max values in the grid

// ULTRAFINE grid increments used in the search of critical points with seeds
// found from a promolecular IGM analysis (will take about 10 more times)
const double incrCRITICULTRAFINEx = incrCRITICMEDIUMx/2.15443; // in angstroms
const double incrCRITICULTRAFINEy = incrCRITICMEDIUMy/2.15443; // no symetrical values are chosen on purpose 
const double incrCRITICULTRAFINEz = incrCRITICMEDIUMz/2.15443; // to avoid any problem during the search of qg max values in the grid


// threshold used to filter undesired drifted points during Newton-Raphson procedure for 
// critical points
const double qgThreshNR = 1.3;

// lower distance threshold allowed between two critical points
//const double cpSeparationThresh = 0.01;  // in bohr
//MODIF ERIC: 16081023
const double cpSeparationThresh = 0.01;  // in bohr

// ED gradient threshold for Newton-Raphson convergence
// MODIF ERIC 16082023
//const double gradThresholdNR = 0.0001;
const double gradThresholdNR = 0.000007;

// Displacement threshold for Newton-Raphson convergence
//const double normdisplactThreshNR  = 0.0001;
// MODIF ERIC 16082023
//const double normdisplactThreshNR  = 0.0000001;
const double normdisplactThreshNR  = 0.00000007;

// Maximum iteration number allowed for Newton-Raphson convergence
const int niterThreshNR=50;

// Epsilon value to perturb a little bit the current position during the Newton-Raphson search
// of critical points of the ED
const double epsXNR = 0.003;
const double epsYNR = 0.006;
const double epsZNR = 0.009;

// Threshold for every ED Hessian eigenvalue
const double EVthreshCP=0.00008;

// threshold to select those primitive to be used
const double cutoff_pri=1.0e-10; // original value from NCIPlot, save about 30%-40% CPU time

// threshold to select those primitive gradient sufficently large 
// to calculate cpsi in IBSI calculations
const double cutoff_gradpri=1.0e-12;

// ratio used to determine the isovalue selected to build 3D isosurface
// The isovalue is defined as 40% of the maximum peak height of the signature:
const double ratioPeak = 0.4; 

// a threshold value for extracting peaks from dg signatures
const double qgThresh = 1.3;

// a threshold to filter peaks in the analysis of dg for the ncc part
const double qgRhoThresh = -0.09;

// an espilon value to apply to the qgRhoThresh to estimate the influence of 
// qgRhoThresh on dgAt contribution to NCC
const double EDepsilon = 0.01;

// a constant indicating that no CHARGE keyword has been supplied in the param.igm input file
const int NOCHARGE = -99999;


// upper limit for allowed atomic number for separating core from valence e- 
const int COREAtomLimit= 53; // 0-based numbering -> calculation allowed up to Z=54 (including Xenon)

// upper limit for allowed atomic number for HIRSHFELD treatment
const int HIRSHAtomLimit = 17; // 0-based numbering -> calculation allowed up to Z=18 (including Argon)

// upper limit to allow critical point search treatment         
const int CRITICPROMOLAtomLimit = 35; // 0-based numbering -> determination of seeds by promol IGM allowed up to Z=36


// Lower IBSI limit to consider BDA calculation; above this threshold,
// BDA value are considered uncertained (too small covalent character)
const double IBSILimitForBDA = 0.15;

// For the BDA calculation the number of core orbital for each atom
// is saved in the ATOM_COREORB array, but fobidden for atoms of periods
// after 5 ==> the constant MAXCORE has been used in the ATOM_COREORB array
// to specify those atoms unallowed
const unsigned int MAXCORE = 1000000000;

//! in the Cylindrical version of IGMPLOT, a Bond Strngth Index is computed
//  based on dgpair integration.  In order for this IBSI index to match 1 for H2, Normation
//  coefficient has been computed :
//  (1) for the GTO level at the M062X 6-31G** level of theory
// and with the cylinder increments: Pz=100, Pr=100, Ptheta=50; 
// dist HH        = 0.737309086727
// dg pair (gross)= 0.390519702115
// dg/d^2         = 0.7183627045
const double NormCoeff_deltagd2GTO = 0.7183627045;// (=int_dg/d^2) in the case of H2
//  (2) for the STO level at the M062X/TZP  level of theory (ADF)
// and with the cylinder increments: Pz=100, Pr=100, Ptheta=50; 
// dist HH        = 0.739598965    
// dg pair (gross)= 0.34644146941713405141
// dg/d^2         = 0.63334692753492960460
const double NormCoeff_deltagd2STO = 0.63334692753492960460;// (=int_dg/d^2) in the case of H2



// name of the file containing timing informations 
const std::string runinfo="runinfo";


// cylindrical grid steps default:
const unsigned int cylPz     = 100;
const unsigned int cylPr     = 100;
const unsigned int cylPtheta =  50; // must be an even number !


// BDA detection threshold
const double pdaThreshold = 0.005;

//! dgInter threshold used to limit the integration 
const double scoredgThresh = 0.0001;

//! other threshold used to limit the integration
const double scoredg_over_rhoThresh = 0.0010; // sensible parameter

//! threshold used to limit the integration for estimating internal non-cov interactions
const double ratioIGMthresholdPRO = 2.0;
const double EDthreshold          = 0.07;
//const double gradrho_over_dgThreshWFN = 3.0;
//const double gradrho_over_dgThreshPRO = 2.0;
//const double gradrho_over_dgInterThreshPRO = 50.0;


//! intermolecular detection threshold (for the sum of dgInter)
const double   interacThreshold         = 0.00005;

//! TO DOCUMENT
const unsigned int 	NB_KNW_ATMS	= 54;

//! TO DOCUMENT
const double 	ALPHA 			= 0.16162045967;

//! Value of 1/3
const double 	ONE_THIRD 		= 0.33333333333333;

//! Value of 4/3
const double 	FOUR_THIRD 		= 1.33333333333333;

//! Value of 5/3
const double    FIVE_THIRD              = 1.66666666666666;

//! cylinder diameter (in bohr)
const double R_MAX              = 20.0;

// the threshold used to test if an atom is exactly located on a grid node (in bohr)
const double 	R_TRESHOLD		= 0.0000001;

//! TO DOCUMENT
const double 	DEFAULT_CUTOFF 	= 0.2;

//! TO DOCUMENT
const double 	LN_2			= 0.69314718056;

//! TO DOCUMENT
const double 	NaN 			= 0.0;

//! Value of PI
const double 	PI			= 3.141592653589793;

// constant used to obtain the RDG descriptor
//const double constValue = 2.0*std::pow((3.0*std::pow(PI,2)),(ONE_THIRD));
const double constValue = 6.187335452560202;


//! 2pi rad to go around the cylind
const double   THETA_MAX    = 2*PI;

//! Constant for getRotationMatrix
const double EPSILON_RAD = 0.00055*PI;

//! Value of 2*PI
const double 	PI_2			= 6.28318530718;

//! Value of 4*PI
const double 	PI_4			= 12.5663706144;

//! Value of PI**2 
const double PI_squared                 = 9.86960440108936;

//! ELF constant (denominator)  (3/10) * (3*PI_squared)^(2/3) = Thomas-Fermi cte
const double ELF_const                  = 2.871234000188192;// A. Savin, B. Silvi, F. Colonna Can. J. Chem. 74 (1996) 1088-1096 equation [5] independent on the spin.
// equivalent to Thomas Fermi formula : C_F = (3/10)(3pi^2)^2/3 [h/(2pi)]^2 / me

// The cte  in front of the expression of the ED "slater", no unit               
const double 	A1[NB_KNW_ATMS] = { //[1:2]   1s 
                                    0.2815, 2.437,                                                                            
                                    //[3:10]  2s 2p
				    11.84, 31.34, 67.82, 120.2,190.9, 289.5, 406.3, 561.3,
                                    //[11:18] 3s 3p
				    760.8, 1016., 1319., 1658., 2042., 2501., 3024., 3625.,
                                    //[19:20] 4s
				    422.685, 328.056,
                                    //[21:30] 3d
				    369.212, 294.479, 525.536, 434.298, 9346.12, 579.606, 665.791, 793.8, 897.784, 1857.03,
                                    //[31:36] 4p
				    898.009, 1001.24, 1101.35, 1272.92, 1333.8, 1459.53, 
                                    //[37:51] 5s NOT AVAILABLE
                                    0.0, 0.0,
                                    //4d NOT AVAILABLE
                                    0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
                                    //[52:54] 5p
                                    0.0, 0.0, 0.0, 457.406, 3.23589, 643.098
};


// The cte  in front of the expression of the ED "slater", no unit
const double 	A2[NB_KNW_ATMS] = { //[1:2]   1s
                                    0.0, 0.0,                                                                               
                                    //[3:10]  2s 2p
				    0.06332, 0.3694, 0.8527, 1.172, 2.247, 2.879, 3.049, 6.984,
                                    //[11:18] 3s 3p
				    22.42, 37.17, 57.95, 87.16, 115.7, 158.0, 205.5, 260.0,
                                    //[19:20] 4s
				    104.678, 48.1693,
                                    //[21:30] 3d
				    66.7813, 64.3627, 97.5552, 37.8524, 166.393, 50.2383, 51.7033, 60.5725, 58.8879, 135.027,
                                    //[31:36] 4p
				    1.10777, 0.855815, 901.893, 1.20778, 1.0722, 1.95028,
                                    //[37:51] 5s NOT AVAILABLE
                                    0.0, 0.0,
                                    //4d NOT AVAILABLE
                                    0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
                                    //[52:54] 5p
                                    0.0, 0.0, 0.0, 0.0648533, 4.1956, 0.133996
};

// The cte  in front of the expression of the ED "slater", no unit
const double 	A3[NB_KNW_ATMS] = { //1s
                                    0.0, 0.0,                                                                                
                                    //2s 2p
				    0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
                                    //3s 3p
				    0.06358, 0.3331, 0.8878, 0.7888, 1.465, 2.170, 3.369, 5.211,
                                    //4s
				    0.0305251, 0.137293,
                                    //3d
				    0.217304, 0.312378, 0.288164, 0.216041, 0.428442, 0.301226, 0.358959, 0.384414, 0.446463, 0.664027,
                                    //4p
				    0.178217, 0.271045, 1.43271, 0.548474, 1.52238, 3.12305,
                                    //5s NOT AVAILABLE
                                    0.0, 0.0,
                                    //4d NOT AVAILABLE
                                    0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
                                    //5p
                                    0.0, 0.0, 0.0, 0.0273883, 0.0347855, 0.0499776
};

// exponent in the expression of the ED "slater", given in bohr^-1 (to be multiplied by the distance 
// between the current grid node and the considered atom --> the distance hs to be expressed in bohr)
const double 	B1[NB_KNW_ATMS] = { //1s
                                    1.8910741301059, 2.95945546019532,                                                                                 
                                    //2s 2p
				    5.23012552301255, 7.19424460431655, 9.44287063267233, 11.3122171945701, 13.0378096479791, 14.9476831091181, 16.4473684210526, 18.2149362477231,  
                                    //3s 3p
				    20.1612903225806, 22.271714922049,  24.330900243309, 26.1780104712042, 27.9329608938547, 29.8507462686567, 31.7460317460318, 33.7837837837838,
                                    //4s
				    61.3085, 13.6033,
                                    //3d
				    15.1828, 8.87333, 18.4925, 12.2138, 47.0758, 13.6638, 14.1117, 15.1832, 15.4177, 23.5312,
                                    //4p
				    12.4217, 12.8073, 13.0865, 13.8734, 13.8227, 14.1814,
                                    //5s NOT AVAILABLE
                                    0.0, 0.0,
                                    //4d NOT AVAILABLE
                                    0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
                                    //5p
                                    0.0, 0.0, 0.0, 3.82753, 23.9761, 4.10166 
};

// exponent in the expression of the ED "slater", given in bohr^-1 (to be multiplied by the distance 
// between the current grid node and the considered atom --> the distance hs to be expressed in bohr)
const double 	B2[NB_KNW_ATMS] = { //1s
                                    1.000000, 1.000000, 
                                    //2s 2p
				    1.00080064051241, 1.43988480921526, 1.88679245283019, 1.82481751824818, 2.20653133274492, 2.51635631605435, 2.50375563345018, 2.90107339715695,  
                                    //3s 3p
				    3.98247710075667, 4.65116279069767, 5.33617929562433, 6.0459492140266, 6.62690523525514, 7.30460189919649, 7.9428117553614, 8.56164383561644,
                                    //4s
				    3.81272, 3.94253,
                                    //3d
				    4.24199, 4.33369, 4.58656, 3.81061, 5.07878, 4.09039, 4.17018, 4.30955, 4.35337, 5.19033,
                                    //4p
				    2.00145, 1.85496, 7.70162, 1.88584, 2.12925, 2.35537,
                                    //5s NOT AVAILABLE
                                    0.0, 0.0,
                                    //4d NOT AVAILABLE
                                    0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
                                    //5p
                                    0.0, 0.0, 0.0, 1.19985, 2.24851, 1.25439 
};

// exponent in the expression of the ED "slater", given in bohr^-1 (to be multiplied by the distance 
// between the current grid node and the considered atom --> the distance hs to be expressed in bohr)
const double 	B3[NB_KNW_ATMS] = { //1s
                                    1.000000, 1.000000, 
                                    //2s 2p
				    1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 
                                    //3s 3p
				    0.9769441187964, 1.28982329420869, 1.67728950016773, 1.42959256611866, 1.70910955392241, 1.94212468440474, 2.01045436268597, 2.26654578422484,
                                    //4s
				    0.760211, 0.972271,
                                    //3d
				    1.08807, 1.18612, 1.19053, 1.22212, 1.3246, 1.32999, 1.38735, 1.42114, 1.48338, 1.54071,
                                    //4p
				    1.19489, 1.31783, 1.64735, 1.57665, 1.79153, 1.99148,
                                    //5s NOT AVAILABLE
                                    0.0, 0.0,
                                    //4d NOT AVAILABLE
                                    0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
                                    //5p
                                    0.0, 0.0, 0.0, 0.906738, 0.856995, 1.02511   
};

//! TO DOCUMENT
//const double vdW_VALUES[NB_KNW_ATMS]	= { 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 };

//! The parameters' types (KEYWORDS in file param.igm)
typedef enum PARAM_TYPES
  {
    TYPE_INCREMENTS,
    TYPE_INTERMOLECULAR,
    TYPE_RADIUS,
    TYPE_OUTPUT_NAME,
    TYPE_CUBE,
    TYPE_CUTOFFS,
    TYPE_CUTPLOT,
    TYPE_CUTPLOT_IGM,
    TYPE_VMD_COLRANG_IGM,
    TYPE_LIGAND,
    TYPE_OUTPUT,
    FRAG1,
    FRAG2,
    BONDS,
    IBSI,
    CUBEFRAG,
    //CHARGE,
    HIRSH,
    CRITIC,
    CRITICFINE,
    CRITICULTRAFINE, 
    CRITICaddSEEDS,
    TYPE_PEAKFOCUSINTRA,
    TYPE_PEAKFOCUSINTER,
    ELF, 
    DGSCALED,
    PARSERKF,
    SELF,
    SELFATOMIC,
    FULLAOACC,
    PROSELF,   
    TOPELF,
    SIZE_PARAM
  } param_types_t;

//! The parameters' KEYWORDS names
//! Every change in the param_types_t strct (above)
//! must be transmitted to this structure as well. 
const std::string PARAM_NAMES [] =
  {
    "INCREMENTS",
    "INTERMOLECULAR",
    "RADIUS",
    "ONAME",
    "CUBE",
    "CUTOFFS",
    "CUTPLOT",
    "CUTPLOT_IGM",
    "VMD_COLRANG_IGM",
    "LIGAND",
    "OUTPUT",
    "FRAG1",
    "FRAG2",
    "BONDS",
    "IBSI",
    "CUBEFRAG",
    //"CHARGE",
    "HIRSH",
    "CRITIC",
    "CRITICFINE",
    "CRITICULTRAFINE",
    "CRITICADDSEEDS",
    "PEAKFOCUSINTRA",
    "PEAKFOCUSINTER",
    "ELF",
    "DGSCALED",
    "PARSERKF",
    "SELF",
    "SELFATOMIC",
    "FULLAOACC",
    "PROSELF",
    "TOPELF"
  };

								
//! Structure used for the storage of all vectors' norms for the gradients (PROMOL treatment)
typedef struct
{
  //! TO DOCUMENT
  double grad;
  
  //! TO DOCUMENT
  double gradIGM;

  //! TO DOCUMENT
  double gradIGMInter;

  //! TO DOCUMENT
  double gradIGMInter2;

  //! TO DOCUMENT
  double gradIGMInter3;
}norms_t;

/**
 * @brief Structure used for the storage of the parameters read from the parameter file param.igm */
typedef struct
{
  //! The name of the files of the molecule A
  std::string molAFileName;

  //! The name of the files of the molecule B
  std::string molBFileName;

  //! The output name
  std::string outputName;

  //! The radius around the molecule (in angstrom)
  double radiusRoundLigand;

  //! The intermolecular value
  double intermolecular;

  //! The number of the molecule
  int numLigand;

  //! The number of files
  int nbFiles;

  //! The type of the option OUTPUT
  int outputType;

  //! The arguments of the option RADIUS
  double radius[4];

  //! The arguments of the option CUTOFFS
  double cutoffs[2];
  
  //! The arguments of the option CUTLOT
  double cutplot[2];

  //! The arguments of the option CUTPLOT_IGM
  double cutplotIGM[2];

  //! The arguments of the option VMD_COLRANG_IGM
  double vmdcolrangIGM[2];

  //! The argument of the option CUBE
  double cube[6];

  //! The increments for xyz dimensions
  double increments[3];

  //! True if CUBE has been used
  bool cubeUsed;

  //! True if RADIUS has beed used
  bool radiusUsed;
 
  //! True if CUBEFRAG has been used
  bool cubefrag;

  //! Bond environement cutoff (primitive cutoff) used for IBSI
  double bondcut;

  //! Array used to know which parameters were given */
  bool paramFound[SIZE_PARAM];

  //! Number of core Molecular Orbitals excluded from BDA calculations
  unsigned int coremo;

  //! The CHARGE (>0 <-> CATION or <0 <-> ANION) of the system studied
  int CHARGE;

  //! The arguments of the option PEAKFOCUS
  double cutpeakIntra[2];
  double cutpeakInter[2];

}param_t;

//! The cubes' types
typedef enum CUBE_TYPES
  {
    TYPE_DELTA_G_INTRA,
    TYPE_DELTA_G_INTER,
    SIZE_CUBE_DELTA,
    TYPE_RHO,
    TYPE_RDG,
    TYPE_DELTA_G_INTRAFC,
    TYPE_DELTA_G_INTERFC
  }cube_types_t;

//! The outputs' types
typedef enum OUTPUT_TYPES
  {
    OUTPUT_NONE,
    OUTPUT_DAT,
    OUTPUT_RHO_RDG,
    OUTPUT_DELTA,
    OUTPUT_PERCENT,
    OUTPUT_ALL
  }output_types_t;

//! Structure describing studied bond (QM treatment)
typedef struct
{

  //! atom indexes
  std::pair< unsigned int,  unsigned int> atomPair;

  //! bond length  
  double length; // in bohr

  //! IBSI value 
  double ibsi;  // no unit

  //! baf value   
  double baf;  // unit of ED gradient

  //! AB vector from first to second atom
  double ABx,ABy,ABz;

}bond_t;

//! Structure describing one 3D position
typedef struct
{
  //! TO DOCUMENT  
  double x;

  //! TO DOCUMENT
  double y;

  //! TO DOCUMENT
  double z;	
}position_t;

/* JC: the definition of axis_t and position_t are similar 
 * but have different documentation ...*/
//! Structure describing one axis
typedef struct
{
  //! TO DOCUMENT
  double x;
  //! TO DOCUMENT
  double y;
  //! TO DOCUMENT
  double z;	
}axis_t;

//! Structure containing a serie of 3D position
typedef struct
{
  //! X value of each position
  double * __restrict xValues;

  //! Y value of each position
  double * __restrict yValues;

  //! Z value of each position
  double * __restrict zValues;
}positions_t;

//! structure to save critical points
typedef struct criticalpoint
  {
      double pos[3], L123[3]; // array containing coordinates of found critical points and ED hessian eigenval.
      double H, V, G, laplac, RHO, GRADRHO;  // and local energy density and kinetic energy density and ED and and ED gradient magn. and laplacian
      double dg, qg; // local dg and qd descriptors
      int type; // -3=NCP, -1=BCP, 1=RCP, 3=CCP

  } criticalpoint;


#endif
