/*
    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.
*/

/*-------------------------  Control  -----------------------------------*
 *                                                                       *
 * This class contains control criteria and data members for electronic  *
 * minimizations and others.  (member functions in  system.c)            *
 *                                                                       *
 *-----------------------------------------------------------------------*/

#ifndef DFT_CONTROL_H
#define DFT_CONTROL_H

class Control
{
  int converged;      // flag to indicate convergence of successive energy
                      // changes;  1 =  converged.

  // Auxiliary variables helping the minimization procedures
  real Etot;
  real Etot_old;
  real Etot_old_old;

public:

  // flags telling us what the overall task of the run is
  int electronic_minimization_flag,
    calculate_forces_flag,
    ionic_dynamics_flag,
    ionic_relaxation_flag,
    band_structure_flag,
    dump_bands_flag,
    spinorbit_flag,
    finite_diff_test_flag;
  
  // flag indicating whether we have to calculate PAW projectors
  int projector_flag;

  
  real E_tolerance;     // Tolerance level of energy convergence.
  real force_tolerance; // Tolerance on forces for ion relaxation
  real force_diff_tolerance; // Tolerance on successive changes in the
                             // ionic force during an electronic minimization

  // check for force_diff_convergence every (this) 
  // many iterations. if zero, don't bother with force_diffs
  int force_diff_check; 

  // If set, the optimal stepsize in line-minimization                        
  // is used the next time around
  int update_stepsize;   
			    
  real stepsize_min;  // minimum size of an electronic minimization step 
  real nel_fermi_tol; // tolerance of number of electrons when calculating
                      // Fermi fillings

  int dump_n;    // if set, dump charge density at each step of ion dynamics
  int algorithm; // minimization algorithm to use on electrons 
  int max_elecs_steps; // max number of steps during electronic minim 
  real elec_stepsize;  // initial electronic stepsize. 

  // how to do line minimization for the electrons.
  // currently accepted values: QUAD, LIN
  int linmin_method;   
                       

  // Whether number of bands is computed automatically or not
  int auto_n_bands;

  real lattscale[3];

  /* constructor */
  Control()
    {
      converged = 0;
      Etot = Etot_old = Etot_old_old = 0.0;
      
      electronic_minimization_flag = calculate_forces_flag = 
        ionic_dynamics_flag = ionic_relaxation_flag =
        band_structure_flag = FALSE;
      projector_flag = FALSE;
      spinorbit_flag = FALSE;
      finite_diff_test_flag = FALSE;
      E_tolerance = force_tolerance = 0.0;
      force_diff_check = 0;
      force_diff_tolerance = 0.0;
      update_stepsize = 0;
      dump_bands_flag = 0;
      stepsize_min = nel_fermi_tol = 0.0;
      dump_n = algorithm = max_elecs_steps = 0;
      lattscale[0] = lattscale[1] = lattscale[2] = 1;
      elec_stepsize = 0.0;
      auto_n_bands = 0;
      linmin_method = QUAD;
    }

  int if_e_converged(real E);
  int if_force_diff_converged(Everything &e);
  void reset_converge();
  void print(int iter);
};

#endif // DFT_CONTROL_H
