21#ifndef INCLUDE_LIBINT2_LCAO_MOLDEN_H_
22#define INCLUDE_LIBINT2_LCAO_MOLDEN_H_
24#include <libint2/atom.h>
25#include <libint2/basis.h>
26#include <libint2/cgshell_ordering.h>
27#include <libint2/chemistry/elements.h>
28#include <libint2/shell.h>
29#include <libint2/shgshell_ordering.h>
37#pragma GCC diagnostic push
38#pragma GCC system_header
40#pragma GCC diagnostic pop
80 template <
typename ShellSequence,
typename Coeffs,
typename Occs,
81 typename Energies = Eigen::VectorXd>
83 const std::vector<Atom>& atoms,
const ShellSequence& basis,
84 const Coeffs& coefficients,
const Occs& occupancies,
85 const Energies& energies = Energies(),
86 const std::vector<std::string>& symmetry_labels =
87 std::vector<std::string>(),
88 const std::vector<bool>& spincases = std::vector<bool>(),
89 const double bohr_to_angstrom = constants::codata_2018::bohr_to_angstrom,
90 double coefficient_epsilon = 5e-11)
92 basis_(validate(basis)),
94 occupancies_(occupancies),
96 labels_(symmetry_labels),
98 bohr_to_angstrom_(bohr_to_angstrom),
99 coefficient_epsilon_(coefficient_epsilon) {
105 os <<
"[Molden Format]" << std::endl;
110 os <<
"[Atoms] AU" << std::endl;
113 os << std::fixed << std::setprecision(8);
115 for (
const auto& atom : atoms_) {
116 auto Z = atom.atomic_number;
118 << libint2::chemistry::get_element_info().at(Z - 1).symbol
119 << std::setw(6) << (iatom + 1) << std::setw(6) << Z << std::setw(14)
120 << atom.x << std::setw(14) << atom.y << std::setw(14) << atom.z
129 bool f_found =
false;
130 os <<
"[GTO]" << std::endl;
131 for (
size_t iatom = 0; iatom < atoms_.size(); ++iatom) {
132 os << std::setw(4) << (iatom + 1) << std::setw(4) << 0 << std::endl;
133 for (
auto ish : atom2shell_[iatom]) {
134 const Shell& sh = basis_.at(ish);
135 if (sh.
contr.size() == 1) {
136 const auto& contr = sh.
contr[0];
137 const auto l = contr.l;
139 if (l == 3) f_found =
true;
140 const auto nprim = contr.coeff.size();
142 << nprim << std::setw(6) <<
"1.00" << std::endl;
143 for (
int iprim = 0; iprim < nprim; ++iprim) {
144 os << std::scientific << std::uppercase << std::setprecision(10);
145 os << std::setw(20) << sh.
alpha[iprim] << std::setw(20)
161 if (dfg_is_cart_[0]) {
162 if (!dfg_is_cart_[1])
163 os <<
"[7F]" << std::endl;
165 if (!dfg_is_cart_[1]) {
166 os <<
"[5D7F]" << std::endl;
167 }
else if (f_found) {
168 os <<
"[5D10F]" << std::endl;
170 os <<
"[5D]" << std::endl;
173 if (!dfg_is_cart_[2])
174 os <<
"[9G]" << std::endl;
180 os <<
"[MO]" << std::endl;
181 for (
int imo = 0; imo < coefs_.cols(); ++imo) {
182 os << std::fixed << std::setprecision(10);
183 os << std::setw(8) <<
"Sym= " << (labels_.empty() ?
"A" : labels_.at(imo))
185 << std::setw(8) <<
"Ene= " << std::setw(16)
186 << (energies_.rows() == 0 ? 0.0 : energies_(imo)) << std::endl
187 << std::setw(8) <<
"Spin= "
188 << (spins_.empty() ?
"Alpha" : (spins_.at(imo) ?
"Alpha" :
"Beta"))
190 << std::setw(8) <<
"Occup= " << occupancies_(imo) << std::endl;
191 os << std::scientific << std::uppercase << std::setprecision(10);
192 for (
int iao = 0; iao < coefs_.rows(); ++iao) {
193 const auto C_ao_mo = coefs_(ao_map_[iao], imo);
194 if (std::abs(C_ao_mo) >= coefficient_epsilon_) {
195 os << std::setw(6) << (iao + 1) <<
" " << std::setw(16) << C_ao_mo
203 void write(std::ostream& os)
const {
211 void write(
const std::string& filename)
const {
212 std::ofstream os(filename);
219 double bohr_to_angstrom()
const {
return bohr_to_angstrom_; }
222 const std::vector<Atom>& atoms_;
223 const std::vector<Shell>& basis_;
224 Eigen::MatrixXd coefs_;
225 Eigen::VectorXd occupancies_;
226 Eigen::VectorXd energies_;
227 std::vector<std::string> labels_;
228 std::vector<bool> spins_;
229 double bohr_to_angstrom_;
230 double coefficient_epsilon_;
231 mutable bool dfg_is_cart_[3];
233 std::vector<std::vector<long>>
242 const std::vector<Shell>& validate(
const std::vector<Shell>& shells)
const {
243 bool dfg_found[] = {
false,
false,
false};
244 for (
int i = 0; i !=
sizeof(dfg_is_cart_) /
sizeof(
bool); ++i)
245 dfg_is_cart_[i] =
true;
246 for (
const auto& shell : shells) {
247 for (
const auto& contr : shell.contr) {
249 throw std::logic_error(
250 "molden::Export cannot handle shells with l > 4");
255 throw std::logic_error(
256 "molden::Export cannot handle solid harmonics p shells");
261 if (!dfg_found[contr.l - 2]) {
262 dfg_is_cart_[contr.l - 2] = !contr.pure;
263 dfg_found[contr.l - 2] =
true;
265 if (!contr.pure ^ dfg_is_cart_[contr.l - 2])
266 throw std::logic_error(
267 "molden::Export only supports all-Cartesian or "
268 "all-solid-harmonics d/f/g shells");
281 const std::vector<Shell>& validate(
const BasisSet& bs)
const {
282 return validate(bs.shells());
285 void initialize_bf_map() {
286 atom2shell_ = BasisSet::atom2shell(atoms_, basis_);
288 const auto nao = BasisSet::nbf(basis_);
290 assert(nao == coefs_.rows());
291 const auto shell2ao = BasisSet::compute_shell2bf(basis_);
293 for (
size_t iatom = 0; iatom < atoms_.size(); ++iatom) {
294 for (
auto ish : atom2shell_[iatom]) {
295 auto ao = shell2ao[ish];
296 const auto& shell = basis_[ish];
297 const auto ncontr = shell.contr.size();
298 for (
int c = 0; c != ncontr; ++c) {
299 const auto l = shell.contr[c].l;
300 const auto pure = shell.contr[c].pure;
303 FOR_SOLIDHARM_MOLDEN(l, m)
304 const auto ao_in_shell = libint2::INT_SOLIDHARMINDEX(l, m);
305 ao_map_[ao_molden] = ao + ao_in_shell;
307 END_FOR_SOLIDHARM_MOLDEN
311 FOR_CART_MOLDEN(i, j, k, l)
312 const auto ao_in_shell = INT_CARTINDEX(l, i, j);
313 ao_map_[ao_molden] = ao + ao_in_shell;
358 template <
typename Coeffs,
typename Occs,
typename Energies = Eigen::VectorXd>
360 const std::vector<Atom>& atoms,
361 const std::array<Eigen::Vector3d, 3>& cell_axes,
362 const std::vector<Shell>& basis,
const Coeffs& coefficients,
363 const Occs& occupancies,
int space_group,
364 const Energies& energies = Energies(),
365 const std::vector<std::string>& symmetry_labels =
366 std::vector<std::string>(),
367 const std::vector<bool>& spincases = std::vector<bool>(),
368 const double bohr_to_angstrom = constants::codata_2018::bohr_to_angstrom)
369 :
Export(atoms, basis, coefficients, occupancies, energies,
370 symmetry_labels, spincases, bohr_to_angstrom),
371 cell_axes_(cell_axes),
372 space_group_(space_group) {
378 os <<
"[SpaceGroup] (Number)" << std::endl;
379 os << space_group_ << std::endl;
384 os <<
"[Operators]" << std::endl;
385 os <<
"x, y, z" << std::endl;
392 os <<
"[Cell]" << std::endl;
395 const double a = cell_axes_[0].norm();
396 const double b = cell_axes_[1].norm();
397 const double c = cell_axes_[2].norm();
398 const double eps = std::sqrt(std::numeric_limits<double>::epsilon());
399 const bool nonzero_a = a >= eps;
400 const bool nonzero_b = b >= eps;
401 const bool nonzero_c = c >= eps;
402 static constexpr double right_angle = M_PI / 2;
404 nonzero_b && nonzero_c
405 ? std::acos(cell_axes_[1].dot(cell_axes_[2]) / (b * c))
408 nonzero_a && nonzero_c
409 ? std::acos(cell_axes_[0].dot(cell_axes_[2]) / (a * c))
412 nonzero_a && nonzero_b
413 ? std::acos(cell_axes_[0].dot(cell_axes_[1]) / (a * b))
415 const double radian_to_degree = 180 / M_PI;
416 os << std::setw(12) << a * bohr_to_angstrom() << std::setw(12)
417 << b * bohr_to_angstrom() << std::setw(12) << c * bohr_to_angstrom()
418 << std::setw(12) << alpha * radian_to_degree << std::setw(12)
419 << beta * radian_to_degree << std::setw(12) << gamma * radian_to_degree
424 void write(
const std::string& filename)
const {
425 std::ofstream os(filename);
436 std::array<Eigen::Vector3d, 3> cell_axes_;
Exports LCAO coefficients in Molden format.
Definition molden.h:47
void write_basis(std::ostream &os) const
writes the "[GTO]" section, as well as optional Cartesian/solid harmonics keywords,...
Definition molden.h:128
void write_atoms(std::ostream &os) const
writes the "[Atoms]" section to ostream os
Definition molden.h:109
void write_prologue(std::ostream &os) const
writes "[Molden Format]" to ostream os
Definition molden.h:104
void write(const std::string &filename) const
same as write(ostream), but creates new file named filename
Definition molden.h:211
Export(const std::vector< Atom > &atoms, const ShellSequence &basis, const Coeffs &coefficients, const Occs &occupancies, const Energies &energies=Energies(), const std::vector< std::string > &symmetry_labels=std::vector< std::string >(), const std::vector< bool > &spincases=std::vector< bool >(), const double bohr_to_angstrom=constants::codata_2018::bohr_to_angstrom, double coefficient_epsilon=5e-11)
Definition molden.h:82
void write_lcao(std::ostream &os) const
writes the "[MO]" section to ostream os
Definition molden.h:179
void write(std::ostream &os) const
writes "prologue", atoms, basis, and LCAOs to ostream os
Definition molden.h:203
Extension of the Molden exporter to support JMOL extensions for crystal orbitals (see https://sourcef...
Definition molden.h:328
void write_space_group(std::ostream &os) const
writes the "[SpaceGroup]" section to ostream os
Definition molden.h:377
PBCExport(const std::vector< Atom > &atoms, const std::array< Eigen::Vector3d, 3 > &cell_axes, const std::vector< Shell > &basis, const Coeffs &coefficients, const Occs &occupancies, int space_group, const Energies &energies=Energies(), const std::vector< std::string > &symmetry_labels=std::vector< std::string >(), const std::vector< bool > &spincases=std::vector< bool >(), const double bohr_to_angstrom=constants::codata_2018::bohr_to_angstrom)
Definition molden.h:359
void write_cell_axes(std::ostream &os) const
writes the "[Cell]" section to ostream os
Definition molden.h:389
void write_operators(std::ostream &os) const
writes the "[Operators]" section to ostream os
Definition molden.h:383
Defaults definitions for various parameters assumed by Libint.
Definition algebra.cc:24
generally-contracted Solid-Harmonic/Cartesion Gaussian Shell
Definition shell.h:720
svector< Contraction > contr
contractions
Definition shell.h:742
static char am_symbol(size_t l)
Definition shell.h:814
real_t coeff_normalized(size_t c, size_t p) const
Definition shell.h:915
svector< real_t > alpha
exponents
Definition shell.h:741