votca 2026-dev
Loading...
Searching...
No Matches
podcoupling.h
Go to the documentation of this file.
1/*
2 * Copyright 2009-2026 The VOTCA Development Team
3 * (http://www.votca.org)
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License")
6 *
7 * You may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 */
19
20#pragma once
21#ifndef VOTCA_XTP_PODCOUPLING_H
22#define VOTCA_XTP_PODCOUPLING_H
23
24#include "logger.h"
25#include "votca/xtp/orbitals.h"
26#include <votca/tools/types.h>
27#include <votca/xtp/aobasis.h>
28
29namespace votca {
30namespace xtp {
31
32// Returns the AO indices of the given atoms, concatenated in the order
33// the atoms are given (not sorted). Fragment atoms need not be a
34// contiguous range; the AOs of each single atom are contiguous, those
35// of a fragment in general are not.
36//
37// func_per_atom is AOBasis::getFuncPerAtom(); taking it instead of an
38// AOBasis keeps the function testable without a basis set.
39std::vector<Index> MapAtomsToAOIndices(const std::vector<Index>& atom_indices,
40 const std::vector<Index>& func_per_atom);
41
42// Projection Operator Diabatization, POD2 variant (Ghan et al.), which
43// avoids the global Lowdin orthogonalization of the original POD that
44// makes results basis-set dependent (comparison of POD, FODFT and CDFT:
45// arXiv:1512.00200, "Critical analysis of fragment-orbital DFT schemes
46// for the calculation of electronic coupling values").
47//
48// Input is a single converged, unconstrained ground-state DFT calculation
49// of the intact supermolecule; unlike FODFT, covalent bonds across the
50// fragment boundary are therefore allowed. The donor and acceptor AO
51// blocks of the Fock matrix are diagonalized separately in the original
52// AO basis, giving fragment-localized diabatic orbitals; the coupling is
53// the off-diagonal Fock block transformed into these orbitals.
55 public:
56 PODCoupling(Orbitals& orbitals, Logger* log,
57 std::vector<Index> fragment_A_atoms,
58 std::vector<Index> fragment_B_atoms);
59
60 // Computes the couplings between all pairs of orbitals in the ranges
61 // of fragments A and B, occupied and virtual, with the conventions of
62 // DFTcoupling. numberofstates = N selects {HOMO-N+1, ..., HOMO, LUMO,
63 // ..., LUMO+N-1} (as DFTcoupling::DetermineRangeOfStates); N=1 gives
64 // {HOMO, LUMO}.
65 void CalculateCouplings(Index numberofstatesA, Index numberofstatesB);
66
67 // Coupling [Hartree] between orbitals levelA of fragment A and levelB
68 // of fragment B. Levels are absolute indices into the fragment's
69 // eigendecomposition (e.g. getFragmentAHomoIndex()), not relative to
70 // the computed range, as in DFTcoupling::getCouplingElement. Throws if
71 // outside the range of the last CalculateCouplings call.
72 double getCouplingElement(Index levelA, Index levelB) const;
73
74 // HOMO/LUMO index of each fragment in the index space of
75 // getCouplingElement. Available after construction, since they depend
76 // only on the fragment's nuclear charge (CountFragmentElectrons in
77 // podcoupling.cc).
78 Index getFragmentAHomoIndex() const { return nocc_A_ - 1; }
80 Index getFragmentBHomoIndex() const { return nocc_B_ - 1; }
82
83 // Orbital level (absolute index, as in getCouplingElement) of fragment
84 // A (fragment_A true) or B, embedded in the full-molecule AO basis with
85 // zero coefficients outside the fragment, e.g. for cube files. Throws
86 // if outside the range of the last CalculateCouplings call.
87 Eigen::VectorXd GetFragmentOrbital(bool fragment_A, Index level) const;
88
89 // Lists the top_n AOs with the largest |Mulliken population| in a
90 // fragment orbital, with atom index, element and shell type. Useful to
91 // identify which AO of the fragment causes density in the region of the
92 // other fragment (diffuse tails; coefficients on the other fragment's
93 // AOs are zero by construction).
94 //
95 // Ranked by Mulliken population c_i*(S*c)_i rather than |c_i|: in a
96 // non-orthogonal basis, strongly overlapping AOs (e.g. several
97 // contracted s shells on nearby atoms) can have large, mutually
98 // cancelling coefficients that contribute little to the orbital.
99 std::string DescribeFragmentOrbitalComposition(bool fragment_A, Index level,
100 Index top_n = 5) const;
101
102 private:
105 std::vector<Index> fragment_A_atoms_;
106 std::vector<Index> fragment_B_atoms_;
107
108 // Estimated number of occupied orbitals per fragment, set in the
109 // constructor (see CountFragmentElectrons in podcoupling.cc).
112
113 // (start, size) of the computed orbital range, in absolute fragment
114 // orbital indices; set by CalculateCouplings. As in DFTcoupling.
115 std::pair<Index, Index> Range_orbA_;
116 std::pair<Index, Index> Range_orbB_;
117
118 // Coupling matrix [Hartree], set by CalculateCouplings: JAB_(i,j)
119 // couples orbital Range_orbA_.first + i of A with Range_orbB_.first + j
120 // of B. Unlike DFTcoupling's JAB, only the A-B block is stored.
121 Eigen::MatrixXd JAB_;
122
123 // Set by CalculateCouplings for GetFragmentOrbital: fragment
124 // eigenvectors (all orbitals), fragment AO indices in the full basis,
125 // and the full AO count.
128 std::vector<Index> ao_indices_A_;
129 std::vector<Index> ao_indices_B_;
131
132 // Fragment AO overlap blocks, kept for the Mulliken populations in
133 // DescribeFragmentOrbitalComposition.
134 Eigen::MatrixXd S_AA_;
135 Eigen::MatrixXd S_BB_;
136};
137
138} // namespace xtp
139} // namespace votca
140
141#endif // VOTCA_XTP_PODCOUPLING_H
Logger is used for thread-safe output of messages.
Definition logger.h:164
Container for molecular orbitals and derived one-particle data.
Definition orbitals.h:47
Eigen::MatrixXd JAB_
Index getFragmentAHomoIndex() const
Definition podcoupling.h:78
std::pair< Index, Index > Range_orbA_
std::vector< Index > ao_indices_A_
std::pair< Index, Index > Range_orbB_
void CalculateCouplings(Index numberofstatesA, Index numberofstatesB)
double getCouplingElement(Index levelA, Index levelB) const
Eigen::MatrixXd fragment_B_eigenvectors_
Eigen::VectorXd GetFragmentOrbital(bool fragment_A, Index level) const
std::vector< Index > ao_indices_B_
std::vector< Index > fragment_B_atoms_
Eigen::MatrixXd fragment_A_eigenvectors_
std::vector< Index > fragment_A_atoms_
Index getFragmentBLumoIndex() const
Definition podcoupling.h:81
Index getFragmentALumoIndex() const
Definition podcoupling.h:79
Index getFragmentBHomoIndex() const
Definition podcoupling.h:80
Eigen::MatrixXd S_BB_
std::string DescribeFragmentOrbitalComposition(bool fragment_A, Index level, Index top_n=5) const
Eigen::MatrixXd S_AA_
PODCoupling(Orbitals &orbitals, Logger *log, std::vector< Index > fragment_A_atoms, std::vector< Index > fragment_B_atoms)
std::vector< Index > MapAtomsToAOIndices(const std::vector< Index > &atom_indices, const std::vector< Index > &func_per_atom)
Provides a means for comparing floating point numbers.
Definition basebead.h:33
Eigen::Index Index
Definition types.h:26