////////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2008 The Regents of the University of California
//
// This file is part of Qbox
//
// Qbox is distributed 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.
// See the file COPYING in the root directory of this distribution
// or .
//
////////////////////////////////////////////////////////////////////////////////
//
// XCOperator.C
//
////////////////////////////////////////////////////////////////////////////////
#include "XCOperator.h"
#include "ChargeDensity.h"
#include "XCPotential.h"
#include "ExchangeOperator.h"
using namespace std;
////////////////////////////////////////////////////////////////////////////////
XCOperator::XCOperator(Sample& s, const ChargeDensity& cd) :cd_(cd)
{
// set initial values
xcp_ = 0;
xop_ = 0;
exc_ = 0.0 ;
dxc_ = 0.0 ;
sigma_exc_.resize(6);
string functional_name = s.ctrl.xc;
// check the name of the functional
if ( ( functional_name == "LDA" ) ||
( functional_name == "VWN" ) ||
( functional_name == "PBE" ) ||
( functional_name == "BLYP" ) )
{
// create only an xc potential
xcp_ = new XCPotential(cd, functional_name, s.ctrl);
hasPotential_ = true;
hasGGA_ = xcp_->isGGA();
hasHF_ = false;
HFmixCoeff_ = 0.0;
}
else if ( functional_name == "HF" )
{
// create exchange operator with mixing coeff=1
xop_ = new ExchangeOperator(s, 1.0);
hasPotential_ = false;
hasGGA_ = false;
hasHF_ = true;
HFmixCoeff_ = 1.0;
}
else if ( functional_name == "PBE0" )
{
// create an exchange potential
xcp_ = new XCPotential(cd, functional_name, s.ctrl);
// create the exchange operator with mixing coeff=0.25
xop_ = new ExchangeOperator(s, s.ctrl.alpha_PBE0);
hasPotential_ = true;
hasGGA_ = xcp_->isGGA();
hasHF_ = true;
HFmixCoeff_ = s.ctrl.alpha_PBE0;;
}
else if ( functional_name == "B3LYP" )
{
// create an exchange potential
xcp_ = new XCPotential(cd, functional_name, s.ctrl);
// create the exchange operator with mixing coeff=0.20
xop_ = new ExchangeOperator(s, 0.20);
hasPotential_ = true;
hasGGA_ = xcp_->isGGA();
hasHF_ = true;
HFmixCoeff_ = 0.20;
}
else
{
throw XCOperatorException(
"unknown functional name during exchange operator construction");
}
}
XCOperator::~XCOperator()
{
delete xcp_;
delete xop_;
}
////////////////////////////////////////////////////////////////////////////////
void XCOperator::update(std::vector >& vr, bool compute_stress)
{
// update xc potential and self-energy
// used whenever the charge density and/or wave functions have changed
// compute vxc potential and energy
if ( hasPotential_ )
{
// update LDA/GGA xc potential
xcp_->update( vr );
// LDA/GGA exchange energy
exc_ = xcp_->exc();
dxc_ = xcp_->dxc();
if ( compute_stress )
xcp_->compute_stress(sigma_exc_);
}
else
{
exc_ = 0.0;
dxc_ = 0.0;
sigma_exc_ = 0.0;
}
if ( hasHF() )
{
double ex_hf = xop_->update_operator(compute_stress);
exc_ += ex_hf;
dxc_ -= ex_hf;
if ( compute_stress )
xop_->add_stress(sigma_exc_);
}
}
////////////////////////////////////////////////////////////////////////////////
void XCOperator::apply_self_energy(Wavefunction &dwf)
{
if ( hasHF() )
xop_->apply_operator(dwf);
}
////////////////////////////////////////////////////////////////////////////////
void XCOperator::compute_stress(std::valarray& sigma)
{
sigma = sigma_exc_;
}
////////////////////////////////////////////////////////////////////////////////
void XCOperator::cell_moved(void)
{
if ( hasHF() )
xop_->cell_moved();
}