7 #ifndef SPARROW_TDDFTBEIGENVALUESOLVER_H
8 #define SPARROW_TDDFTBEIGENVALUESOLVER_H
22 template<Utils::Reference restrictedness>
23 class TDDFTBEigenvalueSolver {
25 TDDFTBEigenvalueSolver(
const Utils::Settings& settings, std::shared_ptr<Eigen::MatrixXd> gammaMatrix,
26 std::shared_ptr<Eigen::VectorXd> spinConstants,
const OrderedInput<restrictedness>& orderedInput,
27 std::shared_ptr<Utils::DipoleMatrix> dipoleMatrixMO, Core::Log& log)
28 : settings_(settings),
29 gammaMatrix_(std::move(gammaMatrix)),
30 spinConstants_(std::move(spinConstants)),
31 dipoleMatrix_(std::move(dipoleMatrixMO)),
44 auto solve(
int numberOfEnergyLevels,
int initialSubspaceDimension,
45 Utils::SpinTransition spinBlock = Utils::SpinTransition::Singlet) -> Utils::ElectronicTransitionResult;
47 auto solveDftb0(
int numberOfRoots)
const -> Utils::ElectronicTransitionResult;
49 void setGuess(std::shared_ptr<LinearResponseCalculator::GuessSpecifier> guess) {
50 guess_ = std::move(guess);
54 void checkAndCorrectNumberOfRoots(
int& numberOfEnergyLevels,
int& initialSubspaceDimension,
int nConfigurations);
55 void generateTransitionDipoleMoments(Utils::ElectronicTransitionResult& excitedStatesResults,
56 Utils::SpinTransition spinBlock)
const;
73 Utils::ElectronicTransitionResult formExcitedStatesResults(
const Utils::EigenContainer& resultsFromDavidson,
74 Utils::SpinTransition spinBlock)
const;
76 auto generateGuess(
int nConfigurations, Utils::SpinTransition spinBlock = Utils::SpinTransition::Singlet)
77 -> boost::optional<Eigen::MatrixXd>;
78 const Utils::Settings& settings_;
79 std::shared_ptr<Eigen::MatrixXd> gammaMatrix_;
80 std::shared_ptr<Eigen::VectorXd> spinConstants_;
81 std::shared_ptr<Utils::DipoleMatrix> dipoleMatrix_;
82 std::shared_ptr<LinearResponseCalculator::GuessSpecifier> guess_;
83 OrderedInput<restrictedness> input_;
87 template<Utils::Reference restrictedness>
89 int initialSubspaceDimension,
90 Utils::SpinTransition spinBlock) {
91 const int nConfigurations = input_.energyDifferences().size();
92 TDDFTBType type = settings_.getBool(
"tda") ? TDDFTBType::TDA : TDDFTBType::TDDFTB;
94 checkAndCorrectNumberOfRoots(numberOfEnergyLevels, initialSubspaceDimension, nConfigurations);
97 diagonalizer.
settings().modifyInt(Utils::initialGuessDimensionOption, initialSubspaceDimension);
98 diagonalizer.
settings().modifyDouble(Utils::residualNormToleranceOption, settings_.getDouble(convergence));
99 diagonalizer.
settings().modifyString(
"gep_algo", settings_.getString(
"gep_algo"));
100 if (settings_.getInt(Utils::SettingsNames::maxDavidsonIterations) != 0) {
101 diagonalizer.
settings().modifyInt(Utils::SettingsNames::maxDavidsonIterations,
102 settings_.getInt(Utils::SettingsNames::maxDavidsonIterations));
105 diagonalizer.
setGuess(generateGuess(nConfigurations, spinBlock));
112 auto eigenvalueProblemResult = diagonalizer.
solve(log_);
114 auto excitedStates = formExcitedStatesResults(eigenvalueProblemResult, spinBlock);
116 return excitedStates;
119 template<Utils::Reference restrictedness>
121 const int nRoots = std::min(numberOfEnergyLevels,
int(input_.energyDifferences().size()));
124 result.eigenStates.eigenValues = input_.energyDifferences().head(nRoots);
125 result.eigenStates.eigenVectors = Eigen::MatrixXd::Identity(input_.energyDifferences().size(), nRoots);
129 generateTransitionDipoleMoments(result, Utils::SpinTransition::Singlet);
134 template<Utils::Reference restrictedness>
135 void TDDFTBEigenvalueSolver<restrictedness>::checkAndCorrectNumberOfRoots(
int& numberOfEnergyLevels,
136 int& initialSubspaceDimension,
int nConfigurations) {
138 if (numberOfEnergyLevels == 0 || numberOfEnergyLevels > nConfigurations) {
139 numberOfEnergyLevels = nConfigurations;
141 if (initialSubspaceDimension == 0 || initialSubspaceDimension < numberOfEnergyLevels) {
142 initialSubspaceDimension = numberOfEnergyLevels;
144 if (initialSubspaceDimension > nConfigurations) {
145 initialSubspaceDimension = nConfigurations;
149 template<Utils::Reference restrictedness>
150 Utils::ElectronicTransitionResult
151 TDDFTBEigenvalueSolver<restrictedness>::formExcitedStatesResults(
const Utils::EigenContainer& resultsFromDavidson,
152 Utils::SpinTransition spinBlock)
const {
153 Utils::ElectronicTransitionResult excitedStates;
155 if (settings_.getBool(
"tda")) {
156 excitedStates.eigenStates.eigenVectors = resultsFromDavidson.eigenVectors;
157 excitedStates.eigenStates.eigenValues = resultsFromDavidson.eigenValues;
161 excitedStates.eigenStates.eigenVectors.resize(resultsFromDavidson.eigenVectors.rows(),
162 resultsFromDavidson.eigenVectors.cols());
163 excitedStates.eigenStates.eigenVectors.colwise() = input_.energyDifferences();
169 for (
int row = 0; row < int(excitedStates.eigenStates.eigenVectors.rows()); ++row) {
170 excitedStates.eigenStates.eigenVectors.row(row).array() /= resultsFromDavidson.eigenValues.array().transpose().sqrt();
172 excitedStates.eigenStates.eigenVectors = excitedStates.eigenStates.eigenVectors.array().sqrt();
173 excitedStates.eigenStates.eigenVectors.array() *= resultsFromDavidson.eigenVectors.array();
180 Eigen::MatrixXd temp = resultsFromDavidson.eigenValues.cwiseSqrt();
181 excitedStates.eigenStates.eigenValues = std::move(temp);
184 generateTransitionDipoleMoments(excitedStates, spinBlock);
188 Eigen::MatrixXd sign =
189 Eigen::MatrixXd::Ones(excitedStates.eigenStates.eigenVectors.rows(), excitedStates.eigenStates.eigenVectors.cols());
190 sign = (sign.array() > 0).select(sign, -sign);
193 excitedStates.eigenStates.eigenVectors =
194 excitedStates.eigenStates.eigenVectors.array().square().matrix().cwiseProduct(sign).colwise().normalized();
196 return excitedStates;
199 template<Utils::Reference restrictedness>
200 void TDDFTBEigenvalueSolver<restrictedness>::generateTransitionDipoleMoments(Utils::ElectronicTransitionResult& excitedStatesResults,
201 Utils::SpinTransition spinBlock)
const {
204 if (!dipoleMatrix_ || spinBlock == Utils::SpinTransition::Triplet) {
205 excitedStatesResults.transitionDipoles = Eigen::Matrix3Xd::Zero(3, excitedStatesResults.eigenStates.eigenValues.size());
208 excitedStatesResults.transitionDipoles = Utils::TransitionDipoleCalculator::calculate<restrictedness>(
209 *dipoleMatrix_, excitedStatesResults.eigenStates.eigenVectors, input_.excitations());
214 inline auto TDDFTBEigenvalueSolver<Utils::Reference::Restricted>::generateGuess(
int nConfigurations, Utils::SpinTransition spinBlock)
215 -> boost::optional<Eigen::MatrixXd> {
217 if (spinBlock == Utils::SpinTransition::Singlet) {
218 if (guess_->singlet.rows() != nConfigurations) {
219 throw std::runtime_error(
"Number of configurations is not the same as the row dimention of the initial guess.");
221 return guess_->singlet;
224 if (guess_->triplet.rows() != nConfigurations) {
225 throw std::runtime_error(
"Number of configurations is not the same as the row dimention of the initial guess.");
227 return guess_->triplet;
233 inline auto TDDFTBEigenvalueSolver<Utils::Reference::Unrestricted>::generateGuess(
int nConfigurations,
234 Utils::SpinTransition )
235 -> boost::optional<Eigen::MatrixXd> {
237 if (guess_->unrestricted.rows() != nConfigurations) {
238 throw std::runtime_error(
"Number of configurations is not the same as the row dimention of the initial guess.");
240 return guess_->unrestricted;
246 #endif // SPARROW_TDDFTBEIGENVALUESOLVER_H
void setGuess(boost::optional< Eigen::MatrixXd > guessVectors)
void setPreconditionerEvaluator(std::shared_ptr< PreconditionerEvaluator > evaluator)
Definition: TDDFTBSigmaVectorEvaluator.h:49
auto solve(Core::Log &log) -> const EigenContainer &
Definition: TDDFTBCalculator.h:42
auto settings() const -> const Settings &
void setSigmaVectorEvaluator(std::shared_ptr< SigmaVectorEvaluator > evaluator)
auto solve(int numberOfEnergyLevels, int initialSubspaceDimension, Utils::SpinTransition spinBlock=Utils::SpinTransition::Singlet) -> Utils::ElectronicTransitionResult
Solves the first roots of the TDDFTB Matrix without any pruning.
Definition: TDDFTBEigenvalueSolver.h:88