votca 2026-dev
Loading...
Searching...
No Matches
gaussianwriter.cc
Go to the documentation of this file.
1/*
2 * Copyright 2009-2021 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
21#include "votca/xtp/basisset.h"
22#include <boost/algorithm/string.hpp>
23#include <boost/format.hpp>
24#include <sstream>
26
27namespace votca {
28namespace xtp {
29
30/*
31 * This function converts VOTCA's L enum to the gaussian equivalent.
32 * Gaussian uses a minus sign to indicate spherical shells, but -1 for sp.
33 */
35 switch (l) {
36 case L::S:
37 return 0;
38 case L::P:
39 return 1;
40 default:
41 return -1 * static_cast<Index>(l);
42 }
43}
44
45Eigen::MatrixXd GaussianWriter::moCoefficients(const Orbitals& orbitals) const {
47 return orbitals.BSEOrbitals();
48 }
49 return orbitals.MOs().eigenvectors();
50}
51
52Eigen::VectorXd GaussianWriter::moEnergies(const Orbitals& orbitals) const {
53 Eigen::VectorXd energies = orbitals.MOs().eigenvalues();
54 if (use_bse_orbitals_ && orbitals.isQSGW() && orbitals.hasQPdiag()) {
55 const Index qpmin = orbitals.getGWAmin();
56 const Index qptotal = orbitals.QPdiag().eigenvalues().size();
57 energies.segment(qpmin, qptotal) = orbitals.QPdiag().eigenvalues();
58 }
59 return energies;
60}
61
63 const Orbitals& orbitals) const {
65 Eigen::MatrixXd moCoefficients = this->moCoefficients(orbitals);
66 reorder.reorderOrbitals(moCoefficients, orbitals.getDftBasis());
67
68 // put the reordered mos in a string
69 std::stringstream mos_string;
70
71 int temp_int = 1;
72 for (Index i = 0; i < moCoefficients.rows(); ++i) {
73 for (Index j = 0; j < moCoefficients.cols(); ++j) {
74 mos_string << boost::format("%16.8e") % moCoefficients(j, i);
75 if (temp_int % 5 == 0) {
76 mos_string << "\n";
77 }
78 temp_int++;
79 }
80 }
81 mos_string << ((temp_int - 1) % 5 == 0 ? "" : "\n");
82
83 return mos_string.str();
84}
85
87 const QMState& state,
88 bool diff2gs) const {
90
91 Eigen::MatrixXd density;
92 if (diff2gs) {
93 density = orbitals.DensityMatrixWithoutGS(state);
94 } else {
95 density = orbitals.DensityMatrixFull(state);
96 }
97
98 reorder.reorderOperator(density, orbitals.getDftBasis());
99
100 // put the reordered mos in a string
101 std::stringstream density_string;
102
103 int temp_int = 1;
104
105 for (Index i = 0; i < density.rows(); ++i) {
106 for (Index j = 0; j <= i; ++j) {
107 density_string << boost::format("%16.8e") % density(i, j);
108 if (temp_int % 5 == 0) {
109 density_string << "\n";
110 }
111 temp_int++;
112 }
113 }
114 density_string << ((temp_int - 1) % 5 == 0 ? "" : "\n");
115
116 return density_string.str();
117}
118
119void GaussianWriter::WriteFile(const std::string& basename,
120 const Orbitals& orbitals, const QMState state,
121 bool diff2gs) const {
122 if (!orbitals.hasDFTbasisName()) {
123 throw std::runtime_error(".orb file does not contain a basisset name");
124 }
125 if (orbitals.hasUnrestrictedOrbitals()) {
126 throw std::runtime_error(
127 "fchk writer supports restricted closed-shell orbitals only; "
128 "unrestricted (beta) orbitals would be silently dropped.");
129 }
130
131 AOBasis basis = orbitals.getDftBasis();
132
133 std::ofstream outFile(basename + ".fchk");
134
135 if (outFile.is_open()) {
137 << "Start writing to " << (basename + ".fchk") << std::flush;
138 int temp_int;
139 // job description
140 outFile << basename << ", fchk created by VOTCA-XTP\n";
141 // Gaussian fixed format (A10,A30,A30): readers take the method from
142 // column 11, its first letter (R/U/RO) decides restricted vs unrestricted
143 outFile << boost::format("%-10s%-30s%-30s\n") % "SP" % "RHF" %
144 orbitals.getDFTbasisName();
145
146 // clang-format off
147 outFile << boost::format("%-43s%-2s%15d\n") % "Number of atoms" % "I" % orbitals.QMAtoms().size();
148 outFile << boost::format("%-43s%-2s%15d\n") % "Charge" % "I" % orbitals.getCharge();
149 outFile << boost::format("%-43s%-2s%15d\n") % "Multiplicity" % "I" % orbitals.getSpin();
150 outFile << boost::format("%-43s%-2s%15d\n") % "Number of electrons" % "I" % (2*orbitals.getNumberOfAlphaElectrons());
151 outFile << boost::format("%-43s%-2s%15d\n") % "Number of alpha electrons" % "I" % orbitals.getNumberOfAlphaElectrons();
152 outFile << boost::format("%-43s%-2s%15d\n") % "Number of beta electrons" % "I" % orbitals.getNumberOfAlphaElectrons();
153 outFile << boost::format("%-43s%-2s%15d\n") % "Number of basis functions" % "I" % basis.AOBasisSize();
154 outFile << boost::format("%-43s%-2s%15d\n") % "Number of independent functions" % "I" % basis.AOBasisSize();
155 // clang-format on
156 // ATOMIC NUMBERS
157 outFile << boost::format("%-43s%-2s N= %10d\n") % "Atomic numbers" % "I" %
158 orbitals.QMAtoms().size();
159 temp_int = 1;
160 for (const auto& atom : orbitals.QMAtoms()) {
161 outFile << boost::format("%12d") % atom.getElementNumber();
162 if (temp_int % 6 == 0) {
163 outFile << "\n";
164 }
165 temp_int++;
166 }
167 outFile << ((temp_int - 1) % 6 == 0 ? "" : "\n");
168 // NUCLEAR CHARGES
169 outFile << boost::format("%-43s%-2s N= %10d\n") % "Nuclear charges" % "R" %
170 orbitals.QMAtoms().size();
171 temp_int = 1;
172 for (const auto& atom : orbitals.QMAtoms()) {
173 outFile << boost::format("%16.8e") % (double)atom.getNuccharge();
174 if (temp_int % 5 == 0) {
175 outFile << "\n";
176 }
177 temp_int++;
178 }
179 outFile << ((temp_int - 1) % 5 == 0 ? "" : "\n");
180 // CURRENT CARTESIAN COORDINATES
181 outFile << boost::format("%-43s%-2s N= %10d\n") %
182 "Current cartesian coordinates" % "R" %
183 (3 * orbitals.QMAtoms().size());
184 temp_int = 1;
185 for (const auto& atom : orbitals.QMAtoms()) {
186 for (int i = 0; i < 3; ++i) {
187 outFile << boost::format("%16.8e") % atom.getPos()(i);
188 if (temp_int % 5 == 0) {
189 outFile << "\n";
190 }
191 temp_int++;
192 }
193 }
194 outFile << ((temp_int - 1) % 5 == 0 ? "" : "\n");
195 // NUMBER OF PRIMITIVE SHELLS
196 outFile << boost::format("%-43s%-2s%15d\n") % "Number of primitive shells" %
197 "I" % basis.getNumberOfPrimitives();
198 // NUMBER OF CONTRACTED SHELLS
199 outFile << boost::format("%-43s%-2s%15d\n") %
200 "Number of contracted shells" % "I" % basis.getNumofShells();
201 // PURE/CARTESIAN D
202 outFile << boost::format("%-43s%-2s%15d\n") % "Pure/Cartesian d shells " %
203 "I" % 0;
204 // PURE/CARTESIAN F
205 outFile << boost::format("%-43s%-2s%15d\n") % "Pure/Cartesian f shells " %
206 "I" % 0;
207 // HIGHEST ANGULAR MOMENTUM
208 outFile << boost::format("%-43s%-2s%15d\n") % "Highest angular momentum " %
209 "I" % basis.getMaxL();
210 // HIGHEST ANGULAR MOMENTUM
211 outFile << boost::format("%-43s%-2s%15d\n") %
212 "Largest degree of contraction " % "I" % basis.getMaxNprim();
213 // SHELL TYPES
214 outFile << boost::format("%-43s%-2s N= %10d\n") % "Shell types" % "I" %
215 (basis.getNumofShells());
216 temp_int = 1;
217 for (const auto& shell : basis) {
218 outFile << boost::format("%12d") % toGaussianL(shell.getL());
219 if (temp_int % 6 == 0) {
220 outFile << "\n";
221 }
222 temp_int++;
223 }
224 outFile << ((temp_int - 1) % 6 == 0 ? "" : "\n");
225 // NR OF PRIMITIVES PER SHELL
226 outFile << boost::format("%-43s%-2s N= %10d\n") %
227 "Number of primitives per shell" % "I" %
228 (basis.getNumofShells());
229 temp_int = 1;
230 for (const AOShell& shell : basis) {
231 outFile << boost::format("%12d") % shell.getSize();
232 if (temp_int % 6 == 0) {
233 outFile << "\n";
234 }
235 temp_int++;
236 }
237 outFile << ((temp_int - 1) % 6 == 0 ? "" : "\n");
238 // SHELL TO ATOM MAP
239 outFile << boost::format("%-43s%-2s N= %10d\n") % "Shell to atom map" %
240 "I" % (basis.getNumofShells());
241 temp_int = 1;
242 for (const AOShell& shell : basis) {
243 // Gaussian indices start at 1, hence the + 1
244 outFile << boost::format("%12d") % (shell.getAtomIndex() + 1);
245 if (temp_int % 6 == 0) {
246 outFile << "\n";
247 }
248 temp_int++;
249 }
250 outFile << ((temp_int - 1) % 6 == 0 ? "" : "\n");
251 // PRIMITIVE EXPONENTS
252 outFile << boost::format("%-43s%-2s N= %10d\n") % "Primitive exponents" %
253 "R" % basis.getNumberOfPrimitives();
254 temp_int = 1;
255 for (const AOShell& shell : basis) {
256 for (const AOGaussianPrimitive& prim : shell) {
257 outFile << boost::format("%16.8e") % prim.getDecay();
258 if (temp_int % 5 == 0) {
259 outFile << "\n";
260 }
261 temp_int++;
262 }
263 }
264 outFile << ((temp_int - 1) % 5 == 0 ? "" : "\n");
265 // CONTRACTION COEFFICIENTS
266 outFile << boost::format("%-43s%-2s N= %10d\n") %
267 "Contraction coefficients" % "R" %
268 basis.getNumberOfPrimitives();
269 temp_int = 1;
270 for (const AOShell& shell : basis) {
271 for (const AOGaussianPrimitive& prim : shell) {
272 outFile << boost::format("%16.8e") % prim.getContraction();
273 if (temp_int % 5 == 0) {
274 outFile << "\n";
275 }
276 temp_int++;
277 }
278 }
279 outFile << ((temp_int - 1) % 5 == 0 ? "" : "\n");
280 // SHELL COORDINATES
281 outFile << boost::format("%-43s%-2s N= %10d\n") %
282 "Coordinates of each shell" % "R" %
283 (3 * basis.getNumofShells());
284 temp_int = 1;
285 for (const AOShell& shell : basis) {
286 for (int i = 0; i < 3; ++i) {
287 outFile << boost::format("%16.8e") % shell.getPos()(i);
288 if (temp_int % 5 == 0) {
289 outFile << "\n";
290 }
291 temp_int++;
292 }
293 }
294 outFile << ((temp_int - 1) % 5 == 0 ? "" : "\n");
295 // TOTAL ENERGY
296 outFile << boost::format("%-43s%-2s%22.15e\n") % "Total Energy" % "R" %
297 orbitals.getDFTTotalEnergy();
298 // ALPHA ORBITAL ENERGIES
299 outFile << boost::format("%-43s%-2s N= %10d\n") %
300 "Alpha Orbital Energies" % "R" %
301 orbitals.MOs().eigenvalues().size();
302 temp_int = 1;
303 const Eigen::VectorXd mo_energies = moEnergies(orbitals);
304 for (Index i = 0; i < mo_energies.size(); ++i) {
305 outFile << boost::format("%16.8e") % mo_energies[i];
306 if (temp_int % 5 == 0) {
307 outFile << "\n";
308 }
309 temp_int++;
310 }
311 outFile << ((temp_int - 1) % 5 == 0 ? "" : "\n");
312 // ALPHA MO COEFFICIENTS
313 outFile << boost::format("%-43s%-2s N= %10d\n") % "Alpha MO coefficients" %
314 "R" %
315 (orbitals.MOs().eigenvalues().size() *
316 orbitals.MOs().eigenvalues().size());
317 outFile << reorderedMOCoefficients(orbitals);
318 // DENSITY MATRIX
319 outFile << boost::format("%-43s%-2s N= %10d\n") % "Total SCF Density" %
320 "R" %
321 ((orbitals.MOs().eigenvalues().size() *
322 (orbitals.MOs().eigenvalues().size() - 1)) /
323 2 +
324 orbitals.MOs().eigenvalues().size());
325 outFile << densityMatrixToString(orbitals, state, diff2gs);
326
327 XTP_LOG(Log::error, log_) << "Done writing \n" << std::flush;
328 }
329}
330
331} // namespace xtp
332} // namespace votca
const Eigen::VectorXd & eigenvalues() const
Definition eigensystem.h:30
const Eigen::MatrixXd & eigenvectors() const
Definition eigensystem.h:33
Container to hold Basisfunctions for all atoms.
Definition aobasis.h:42
Index getMaxL() const
Definition aobasis.cc:29
Index AOBasisSize() const
Definition aobasis.h:46
Index getNumberOfPrimitives() const
Definition aobasis.h:58
Index getNumofShells() const
Definition aobasis.h:56
Index getMaxNprim() const
Definition aobasis.cc:37
std::array< Index, 49 > gaussianMultipliers
std::string densityMatrixToString(const Orbitals &orbitals, const QMState &state, bool diff2gs) const
std::array< Index, 49 > gaussianOrder
std::string reorderedMOCoefficients(const Orbitals &orbitals) const
Eigen::MatrixXd moCoefficients(const Orbitals &orbitals) const
void WriteFile(const std::string &basename, const Orbitals &orbitals, const QMState state=QMState(QMStateType::statetype::Gstate, 0, false), bool diff2gs=false) const
Eigen::VectorXd moEnergies(const Orbitals &orbitals) const
void reorderOrbitals(Eigen::MatrixXd &moCoefficients, const AOBasis &basis)
Definition orbreorder.cc:74
void reorderOperator(Eigen::MatrixXd &Matrixoperator, const AOBasis &basis)
Container for molecular orbitals and derived one-particle data.
Definition orbitals.h:47
bool hasQPdiag() const
Definition orbitals.h:478
Index getCharge() const
Return the stored total charge.
Definition orbitals.h:254
const tools::EigenSystem & QPdiag() const
Return read-only access to the diagonalized quasiparticle representation.
Definition orbitals.h:482
double getDFTTotalEnergy() const
Return the stored total DFT energy.
Definition orbitals.h:292
Index getSpin() const
Return the stored spin multiplicity.
Definition orbitals.h:252
bool hasUnrestrictedOrbitals() const
Report whether separate beta-spin orbitals are present.
Definition orbitals.h:718
Index getNumberOfAlphaElectrons() const
Return the stored number of alpha electrons.
Definition orbitals.h:159
bool isQSGW() const
Definition orbitals.h:685
Eigen::MatrixXd DensityMatrixWithoutGS(const QMState &state) const
Definition orbitals.cc:121
Eigen::MatrixXd DensityMatrixFull(const QMState &state) const
Definition orbitals.cc:150
Eigen::MatrixXd BSEOrbitals() const
Definition orbitals.cc:250
Index getGWAmin() const
Return the lower GW orbital index.
Definition orbitals.h:389
const tools::EigenSystem & MOs() const
Return read-only access to alpha/restricted molecular orbitals.
Definition orbitals.h:192
const QMMolecule & QMAtoms() const
Return read-only access to the molecular geometry.
Definition orbitals.h:262
bool hasDFTbasisName() const
Report whether a DFT basis-set name has been stored.
Definition orbitals.h:327
const std::string & getDFTbasisName() const
Return the DFT basis-set name.
Definition orbitals.h:332
const AOBasis & getDftBasis() const
Return the DFT AO basis, throwing if it has not been initialized.
Definition orbitals.h:342
Identifier for QMstates. Strings like S1 are converted into enum +zero indexed int.
Definition qmstate.h:135
#define XTP_LOG(level, log)
Definition logger.h:40
Charge transport classes.
Definition ERIs.h:28
Provides a means for comparing floating point numbers.
Definition basebead.h:33
Eigen::Index Index
Definition types.h:26