/* 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_RHF_H
#define CT_RHF_H

#include <string>
#include "CtBasisSet.h"
#include "CtAtomSet.h"
#include "CtMatrix.h"
// #include "CtDma.h"
#include "CtDftGrid.h" // for grid params.
#include "CtFockBuild.h"
#include "CtRhfOptions.h"
#include "CtIo.h"
#include "CxPodArray.h"

namespace ct {



// Stores stuff which came out of a calculation. Can also be used for initial
// guesses of later calculations.
struct FHfResult : public FIntrusivePtrDest
{
   FHeapMatrix
      Orb,
      Occ,
      Ew;
   FBasisSetPtr
      pOrbBasis;
   double
      Energy;
   FAtomSet const
      *pAtoms;

   ~FHfResult();
};
typedef boost::intrusive_ptr<FHfResult>
   FHfResultPtr;


struct FHfMethod
{
   FHfOptions
      Options;
   FWfDecl
      WfDecl;

   FHfMethod(FHfResult *pResult_, FHfResult *pStartingGuess_, FLog &Log_, FWfDecl const &WfDecl_, FAtomSet const &Atoms_, FHfOptions const &Options_, FMemoryStack &Mem, bool FreeObjects=true);
protected:
   FHfResult
      *m_pResult;
   FLog
      &Log;

   FAtomSet const
      // Geometry & environment we are calculating:
      // required to instantiate basis sets and 1e integrals
      *pAtoms;
   FBasisSetPtr
      pOrbBasis, pFitBasis, pMinBasis;
   size_t
      nAo, nFit;
   FMatrixView
      Ew,      // fock matrix eigenvalues.
      Overlap, // S := <mu|nu> of orbital basis
      Smh,     // S^-{1/2}. FIXME: Do I still need this?
      Scd,     // Cholesky decomposition of S
//       Jcd,     // Choleksy decomposition of fitting metric matx (A|B).  // FIXME: is this still valid? seems to be moved to Fock builder.
      CoreH,   // 1e Hamiltonian
      Fock,    // Fock matrix
      ExchO;   // open-shell exchange.
   FMatrixView
      Orb;     // Orbital matrix
   FTimerSet
      m_Timers;
   FTimer
      m_tTotal;
   double
      m_Energy; // total energy of result.
   bool
      // set once we have a set of orbitals which is reasonably consistent with
      // the current Fock matrix, as computed with a RHF coupling pattern. This is
      // not the case if (a) we are in the 1st iteration, and (b) we used anything
      // except for a previous orbital set as initial guess.
      m_HaveOrbitals;

   FFockComponentBuilderList
      m_FockComponentBuilders;

   void Init(FHfResult *pStartingGuess, FMemoryStack &Mem);
   void Run(FMemoryStack &Mem);
   void UpdateOrbitals(FMatrixView &Orb, FMatrixView &COccC, FMatrixView &COccO, FMatrixView &DenC, FMatrixView &DenO,
      FMatrixView const Fock, FMatrixView const &ExchO, FMatrixView &T1, FMemoryStack &Mem);
   void MakeInitialGuess(FMemoryStack &Mem);
   // output: 3 x pAtoms->size() array.
   void MakeGradient(double *pOut, FMemoryStack &Mem);
   void PrintGradient(double *pGrad);
//    void EvalDma(FDmaDescPtr &pDmaResult, FMemoryStack &Mem);
};

} // namespace ct

#endif // CT_RHF_H
