/* Copyright (c) 2015  Gerald Knizia
 * 
 * This file is part of the IboView program (see: http://www.iboview.org)
 * 
 * IboView is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, version 3.
 * 
 * IboView is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with bfint (LICENSE). If not, see http://www.gnu.org/licenses/
 * 
 * Please see IboView documentation in README.txt for:
 * -- A list of included external software and their licenses. The included
 *    external software's copyright is not touched by this agreement.
 * -- Notes on re-distribution and contributions to/further development of
 *    the IboView software
 */

#ifndef CT_DFTI_H
#define CT_DFTI_H

#include "CxTypes.h"
#include "CxDefs.h"
#include "CtDftGrid.h"
#include "CtDft.h"
#include "CtIo.h"
#include "CtTiming.h"
#include "CtBasisSet.h"

namespace dfti {

enum FDftiFlags {
   DFTI_AuxiliaryExpand = 0x01,
   DFTI_MakeXc = 0x02,
   DFTI_MakeGradient = 0x04,
   DFTI_MakeGridGradient = 0x08, // in the case of a gradient computation, include the gradient of the integration grid.
   DFTI_MeasureTime = 0x10
};


struct FDftiArgs
{
   uint32_t
      Flags; // combination of DFTI_*.

   // energies, energy gradients, and triangular fock matrices (output) or Fock potential expansion coefficients.
   double *pDfuEnergies; double *pGradient; double *pFockC; double *pFockO;
   // triangular density matrices (input) in case of regular XC, expansion coefficients
   // in terms of auxiliary basis in other case.
   // if pDenO == 0, open-shell contributions are not evaluated.
   double *pDenC; double *pDenO;
   double *pOccOrbC; double *pOccOrbO;
   size_t nOccC; size_t nOccO;

   // basis over which the orbitals are expanded (regular) or auxiliary basis.
   ct::FRawBasis *pBasis;

   // the functional.
   ct::FXcFunctional *pXcFn;

   // integration grid.
   ct::FDftGrid const *pDftGrid;

   double ThrOrb; double LogThrOrb; // threshold for orbital-on-grid screening

   double *pTimings;
   double *pfElecTotal;
public:
   bool OpenShell() const { return pDenO != 0; };
   bool MakeGradient() const { return Flags & DFTI_MakeGradient; };
   bool MakeXc() const { return Flags & DFTI_MakeXc; };
   bool MakeGridGradient() const { return Flags & DFTI_MakeGridGradient; }
   bool UseAuxiliaryExpansion() const { return Flags & DFTI_AuxiliaryExpand; };
   bool MeasureTime() const { return Flags & DFTI_MeasureTime; }
   bool NeedTau() const { return pXcFn->NeedTau(); }
   bool NeedSigma() const { return pXcFn->NeedSigma(); }
   size_t nBf() const { return pBasis->nFn(); }; // number of basis functions in pBasis
   size_t nCenters() const { return pBasis->nCen(); }; // number of centers (required to determine gradient dimension)
   size_t nFockSize() const {
      size_t nBf_ = nBf();
      if (UseAuxiliaryExpansion())
         return nBf_;
      else
         return (nBf_*(nBf_+1))/2;
   }
};

void AccXc(FDftiArgs &Args, ct::FLog &Log, ct::FMemoryStack &Mem_);
void IrEvalBfn(double *pOrbValAo, size_t *pMap, size_t &nMap, double const *pGridPt, size_t iStGridPt, size_t nGridPt, uint nDiff, ct::FRawBasis const *pBasis, double ThrOrb, double LogThrOrb, ct::FMemoryStack &Mem);


} // namespace dfti


#endif // CT_DFTI_H
