/*
* Copyright 2009-2019 The VOTCA Development Team
* (http://www.votca.org)
*
* Licensed under the Apache License, Version 2.0 (the "License")
*
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#pragma once
#ifndef VOTCA_XTP_ORBITALS_H
#define VOTCA_XTP_ORBITALS_H
#include "aobasis.h"
#include <votca/tools/globals.h>
#include <votca/tools/property.h>
#include <votca/xtp/checkpoint.h>
#include <votca/xtp/classicalsegment.h>
#include <votca/xtp/eigen.h>
#include <votca/xtp/qmmolecule.h>
#include <votca/xtp/qmstate.h>
namespace votca {
namespace xtp {
/**
* \brief container for molecular orbitals
*
* The Orbitals class stores orbital id, energy, MO coefficients, basis set
*
*/
class Orbitals {
public:
Orbitals();
bool hasBasisSetSize() const { return (_basis_set_size > 0) ? true : false; }
Index getBasisSetSize() const { return _basis_set_size; }
void setBasisSetSize(Index basis_set_size) {
_basis_set_size = basis_set_size;
}
Index getLumo() const { return _occupied_levels; }
Index getHomo() const { return _occupied_levels - 1; }
// access to DFT number of levels, new, tested
bool hasNumberOfLevels() const {
return ((_occupied_levels > 0) ? true : false);
}
void setNumberOfOccupiedLevels(Index occupied_levels) {
_occupied_levels = occupied_levels;
}
// access to DFT number of electrons, new, tested
bool hasNumberOfAlphaElectrons() const {
return (_number_alpha_electrons > 0) ? true : false;
}
Index getNumberOfAlphaElectrons() const { return _number_alpha_electrons; };
void setNumberOfAlphaElectrons(Index electrons) {
_number_alpha_electrons = electrons;
}
bool hasECPName() const { return (_ECP != "") ? true : false; }
const std::string &getECPName() const { return _ECP; };
void setECPName(const std::string &ECP) { _ECP = ECP; };
// access to QM package name, new, tested
bool hasQMpackage() const { return (!_qm_package.empty()); }
const std::string &getQMpackage() const { return _qm_package; }
void setQMpackage(const std::string &qmpackage) { _qm_package = qmpackage; }
// access to DFT molecular orbital energies, new, tested
bool hasMOs() const { return (_mos.eigenvalues().size() > 0) ? true : false; }
const tools::EigenSystem &MOs() const { return _mos; }
tools::EigenSystem &MOs() { return _mos; }
// access to DFT molecular orbital energy of a specific level
double getMOEnergy(Index level) const {
if (level < _mos.eigenvalues().size()) {
return _mos.eigenvalues()[level];
} else {
throw std::runtime_error("Level index is outside array range");
}
return 0;
}
// determine (pseudo-)degeneracy of a DFT molecular orbital
std::vector<Index> CheckDegeneracy(Index level,
double energy_difference) const;
Index NumberofStates(QMStateType type) const {
switch (type.Type()) {
case QMStateType::Singlet:
return Index(_BSE_singlet.eigenvalues().size());
break;
case QMStateType::Triplet:
return Index(_BSE_triplet.eigenvalues().size());
break;
case QMStateType::KSstate:
return Index(_mos.eigenvalues().size());
break;
case QMStateType::PQPstate:
return Index(_QPpert_energies.size());
break;
case QMStateType::DQPstate:
return Index(_QPdiag.eigenvalues().size());
break;
default:
return 1;
break;
}
}
bool hasQMAtoms() const { return (_atoms.size() > 0) ? true : false; }
const QMMolecule &QMAtoms() const { return _atoms; }
QMMolecule &QMAtoms() { return _atoms; }
void setXCFunctionalName(std::string functionalname) {
_functionalname = functionalname;
}
const std::string &getXCFunctionalName() const { return _functionalname; }
// access to QM total energy, new, tested
bool hasQMEnergy() const { return (_qm_energy != 0.0) ? true : false; }
double getDFTTotalEnergy() const { return _qm_energy; }
void setQMEnergy(double qmenergy) { _qm_energy = qmenergy; }
// access to DFT basis set name
bool hasDFTbasisName() const { return (!_dftbasis.empty()) ? true : false; }
void setDFTbasisName(const std::string basis) { _dftbasis = basis; }
const std::string &getDFTbasisName() const { return _dftbasis; }
AOBasis SetupDftBasis() const { return SetupBasis<true>(); }
AOBasis SetupAuxBasis() const { return SetupBasis<false>(); }
/*
* ======= GW-BSE related functions =======
*/
// access to auxiliary basis set name
bool hasAuxbasisName() const { return (!_auxbasis.empty()) ? true : false; }
void setAuxbasisName(std::string basis) { _auxbasis = basis; }
const std::string &getAuxbasisName() const { return _auxbasis; }
// access to list of indices used in GWA
bool hasGWAindices() const { return (_qpmax > 0) ? true : false; }
void setGWindices(Index qpmin, Index qpmax) {
_qpmin = qpmin;
_qpmax = qpmax;
}
Index getGWAmin() const { return _qpmin; }
Index getGWAmax() const { return _qpmax; }
// access to list of indices used in RPA
bool hasRPAindices() const { return (_rpamax > 0) ? true : false; }
void setRPAindices(Index rpamin, Index rpamax) {
_rpamin = rpamin;
_rpamax = rpamax;
}
Index getRPAmin() const { return _rpamin; }
Index getRPAmax() const { return _rpamax; }
// access to list of indices used in BSE
void setTDAApprox(bool usedTDA) { _useTDA = usedTDA; }
bool getTDAApprox() const { return _useTDA; }
bool hasBSEindices() const { return (_bse_cmax > 0) ? true : false; }
void setBSEindices(Index vmin, Index cmax) {
_bse_vmin = vmin;
_bse_vmax = getHomo();
_bse_cmin = getLumo();
_bse_cmax = cmax;
_bse_vtotal = _bse_vmax - _bse_vmin + 1;
_bse_ctotal = _bse_cmax - _bse_cmin + 1;
_bse_size = _bse_vtotal * _bse_ctotal;
return;
}
Index getBSEvmin() const { return _bse_vmin; }
Index getBSEvmax() const { return _bse_vmax; }
Index getBSEcmin() const { return _bse_cmin; }
Index getBSEcmax() const { return _bse_cmax; }
double getScaHFX() const { return _ScaHFX; }
void setScaHFX(double ScaHFX) { _ScaHFX = ScaHFX; }
// access to perturbative QP energies
bool hasQPpert() const {
return (_QPpert_energies.size() > 0) ? true : false;
}
const Eigen::VectorXd &QPpertEnergies() const { return _QPpert_energies; }
Eigen::VectorXd &QPpertEnergies() { return _QPpert_energies; }
// access to diagonalized QP energies and wavefunctions
bool hasQPdiag() const {
return (_QPdiag.eigenvalues().size() > 0) ? true : false;
}
const tools::EigenSystem &QPdiag() const { return _QPdiag; }
tools::EigenSystem &QPdiag() { return _QPdiag; }
bool hasBSETriplets() const {
return (_BSE_triplet.eigenvectors().cols() > 0) ? true : false;
}
const tools::EigenSystem &BSETriplets() const { return _BSE_triplet; }
tools::EigenSystem &BSETriplets() { return _BSE_triplet; }
// access to singlet energies and wave function coefficients
bool hasBSESinglets() const {
return (_BSE_singlet.eigenvectors().cols() > 0) ? true : false;
}
const tools::EigenSystem &BSESinglets() const { return _BSE_singlet; }
tools::EigenSystem &BSESinglets() { return _BSE_singlet; }
// access to transition dipole moments
bool hasTransitionDipoles() const {
return (_transition_dipoles.size() > 0) ? true : false;
}
const std::vector<Eigen::Vector3d> &TransitionDipoles() const {
return _transition_dipoles;
}
Eigen::VectorXd Oscillatorstrengths() const;
Eigen::Vector3d CalcElDipole(const QMState &state) const;
// Calculates full electron density for state or transition density, if you
// want to calculate only the density contribution of hole or electron use
// DensityMatrixExcitedState
Eigen::MatrixXd DensityMatrixFull(const QMState &state) const;
// functions for calculating density matrices
Eigen::MatrixXd DensityMatrixGroundState() const;
std::array<Eigen::MatrixXd, 2> DensityMatrixExcitedState(
const QMState &state) const;
Eigen::MatrixXd DensityMatrixQuasiParticle(const QMState &state) const;
Eigen::MatrixXd CalculateQParticleAORepresentation() const;
double getTotalStateEnergy(const QMState &state) const; // Hartree
double getExcitedStateEnergy(const QMState &state) const; // Hartree
void OrderMOsbyEnergy();
void PrepareDimerGuess(const Orbitals &orbitalsA, const Orbitals &orbitalsB);
void CalcCoupledTransition_Dipoles();
void WriteToCpt(const std::string &filename) const;
void ReadFromCpt(const std::string &filename);
void WriteToCpt(CheckpointWriter w) const;
void ReadFromCpt(CheckpointReader parent);
private:
std::array<Eigen::MatrixXd, 3> CalcFreeTransition_Dipoles() const;
// returns indeces of a re-sorted vector of energies from lowest to highest
std::vector<Index> SortEnergies();
template <bool dftbasis>
AOBasis SetupBasis() const {
BasisSet bs;
if (dftbasis) {
bs.Load(this->getDFTbasisName());
} else {
bs.Load(this->getAuxbasisName());
}
AOBasis basis;
basis.Fill(bs, this->QMAtoms());
return basis;
}
void WriteToCpt(CheckpointFile f) const;
void ReadFromCpt(CheckpointFile f);
Eigen::MatrixXd TransitionDensityMatrix(const QMState &state) const;
std::array<Eigen::MatrixXd, 2> DensityMatrixExcitedState_R(
const QMState &state) const;
std::array<Eigen::MatrixXd, 2> DensityMatrixExcitedState_AR(
const QMState &state) const;
Eigen::MatrixXd CalcAuxMat_cc(const Eigen::VectorXd &coeffs) const;
Eigen::MatrixXd CalcAuxMat_vv(const Eigen::VectorXd &coeffs) const;
Index _basis_set_size;
Index _occupied_levels;
Index _number_alpha_electrons;
std::string _ECP = "";
bool _useTDA;
tools::EigenSystem _mos;
QMMolecule _atoms;
double _qm_energy = 0;
// new variables for GW-BSE storage
Index _rpamin = 0;
Index _rpamax = 0;
Index _qpmin = 0;
Index _qpmax = 0;
Index _bse_vmin = 0;
Index _bse_vmax = 0;
Index _bse_cmin = 0;
Index _bse_cmax = 0;
Index _bse_size = 0;
Index _bse_vtotal = 0;
Index _bse_ctotal = 0;
double _ScaHFX = 0;
std::string _dftbasis = "";
std::string _auxbasis = "";
std::string _functionalname = "";
std::string _qm_package = "";
// perturbative quasiparticle energies
Eigen::VectorXd _QPpert_energies;
// quasiparticle energies and coefficients after diagonalization
tools::EigenSystem _QPdiag;
tools::EigenSystem _BSE_singlet;
std::vector<Eigen::Vector3d> _transition_dipoles;
tools::EigenSystem _BSE_triplet;
};
} // namespace xtp
} // namespace votca
#endif // VOTCA_XTP_ORBITALS_H