/*
    DFT++ is a density functional package developed by the research group
    of Professor Tomas Arias

    Copyright 1996-2003 Sohrab Ismail-Beigi

    This file is part of DFT++.

    DFT++ 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; either version 2 of the License, or
    (at your option) any later version.

    DFT++ 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 more details.

    You should have received a copy of the GNU General Public License
    along with DFT++; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

    Please see the file CREDITS for a list of authors.

    For academic users, we request that publications using results obtained with
    this software reference

    "New algebraic formulation of density functional calculation," by Sohrab Ismail-Beigi
    and T.A. Arias, Computer Physics Communications 128:1-2, 1-45 (June 2000).

    and, if using the wavelet basis, further reference

    "Multiresolution analysis of electronic structure: semicardinal and wavelet bases,"
    T.A. Arias, Reviews of Modern Physics 71:1, 267-311 (January 1999).

    and 

    "Robust ab initio calculation of condensed matter: transparent convergence through
    semicardinal multiresolution analysis,'' I.P. Daykov, T.A. Arias, and
    Torkel D. Engeness, Physical Review Letters, 90:21, 216402 (May 2003).

    For your convenience, preprints of the above articles may be obtained from
    http://arXiv.org/abs/cond-mat/9909130, 9805262, and 0204411, respectively.
*/

/*------------------------  Elecvars  -----------------------------------*
 *                                                                       *
 * Structure containing the electronic variables                         *
 *                                                                       *
 *-----------------------------------------------------------------------*/
#ifndef DFT_ELECVARS_H
#define DFT_ELECVARS_H

class QuantumNumber
{
 public:
  vector3 kvec; // the k point 
  int spin;     // possible spin orientation. up=1, down=-1, none=0 
  int offset;   // for FREESPIN mode, this is the offset to the spindown part
                //  of the state 

  QuantumNumber() {spin = 0;}            // Default constructor
  QuantumNumber(const QuantumNumber &qn) // copy constructor
    {kvec = qn.kvec; spin = qn.spin;}
};

class BlochState
{
 public:
  ColumnBundle Y;          // unconstrained electronic wavefunctions
  ComplexMatrix U;                // U[k] = Y[k]^O(Y[k])
  ComplexMatrix W; real *mu;      // U[k] = W[k]*mu[k]*W[k]^ , 
                           //       mu is array of eigenvalues
  ComplexMatrix Umhalf;           // Uhmalf[k] = U[k]^(-1/2) 
  ColumnBundle C;          // C[k] = Y[k]*U[k]: orthonormal wavefuncs 
  ComplexMatrix Hsub;             // Subspace Hamiltonian:  Hsub[k]=C[k]^H*C[k] 
  ComplexMatrix Hsub_evecs;       // eigen-vectors of Hsub[k] (in cols) 
  real *Hsub_eigs;         //       values of Hsub[k] 
  diag_matrix F;           // the fillings for this state 

  /* The below are for the subspace rotation variables */
  ComplexMatrix B,V;              // V = exp(iB): C = Y*U^(-1/2)*Vdag; 
  ComplexMatrix Z; real *beta;    // B = Z*beta*Zdag (eigen decomposition of B) 
  
  real w;                  // weight of this state in the BZ sum
  QuantumNumber qnum;      // QuantumNumbers describing this Bloch State
  Basis basis;             // Basis describing this Bloch State

  // just a pointer to the appropriate Vscloc for this quantum state
  // it's set once and forever at the initialization part
  // i wonder if reference may be equivalent, but with nicer syntax
  CoeffSpaceScalarFieldColumn *Vscloc;
};

class Elecvars
{
 public:

  int nstates;            // copy from Elecinfo
  BlochState *states;     // array of wavefunctions and auxiliary dynamic data
                          // state[q] 

  // Arrays of pointers to the corresponding objects in BlochStates
  // just a different way to loop over them
  ColumnBundle **Y;
  ColumnBundle **C;
  Matrix **B;
  //these may be objectionable... put them for now and will see later
//  ColumnBundle **grad; 
//  ColumnBundle **dir;

      
  Basis basis;            // basis for the scalar fields above

  RealSpaceScalarFieldColumn n;      // electron density on real space grid
  RealSpaceScalarFieldColumn n_dn;   // down spin density, if we have it 
  RealSpaceScalarFieldColumn n_up;   // up spin density, if we have it
  RealSpaceScalarFieldColumn n_ud;   // up-down component of elec density, for FREESPIN
  RealSpaceScalarFieldColumn n_du;   // down-up component of elec density, for FREESPIN
  CoeffSpaceScalarFieldColumn d;       // electrostatic potential
  CoeffSpaceScalarFieldColumn Vlocpot; // Local (pseudo)potential 
  RealSpaceScalarFieldColumn Vscloc;   // Local part of self-consistent potential
  RealSpaceScalarFieldColumn Vscloc_up;// Local part of spin up self-consistent potential
  RealSpaceScalarFieldColumn Vscloc_dn;// Local part of spin down self-consistent potential


  void setup_initial_fillings(Elecinfo &einfo);
  void print_status(Elecinfo &einfo);
  void print_fillings(Output *out);

  void read_bloch_states_array(Elecinfo &einfo);
  void write_bloch_states_array(Elecinfo &einfo);

  Elecvars();
  void setup(Everything &everything);
};

#endif // DFT_ELECVARS_H
