LIBINT 2.9.0
sto3g_atomic_density.h
1/*
2 * Copyright (C) 2004-2024 Edward F. Valeev
3 *
4 * This file is part of Libint library.
5 *
6 * Libint library is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * Libint library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with Libint library. If not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20
21#ifndef INCLUDE_LIBINT2_CHEMISTRY_STO3GATOMICDENSITY_H_
22#define INCLUDE_LIBINT2_CHEMISTRY_STO3GATOMICDENSITY_H_
23
24#include <algorithm>
25#include <stdexcept>
26#include <vector>
27
28namespace libint2 {
29
30namespace detail {
31
40template <typename Real>
41void subshell_occvec(Real*& occvec, size_t size, size_t& ne) {
42 const auto ne_alloc = (ne > 2 * size) ? 2 * size : ne;
43 ne -= ne_alloc;
44 // # of electrons / orbital compute as precisely as possible
45 const double ne_per_orb = (ne_alloc % size == 0)
46 ? static_cast<Real>(ne_alloc / size)
47 : (static_cast<Real>(ne_alloc)) / size;
48 for (size_t f = 0; f != size; ++f) occvec[f] = ne_per_orb;
49 occvec += size;
50}
51
52} // namespace detail
53
57inline size_t sto3g_num_ao(size_t Z) {
58 size_t nao;
59 if (Z == 1 || Z == 2) // H, He
60 nao = 1;
61 else if (Z <= 10) // Li - Ne
62 nao = 5; // 2p is included even for Li and Be
63 else if (Z <= 18) // Na - Ar
64 nao = 9; // 3p is included even for Na and Mg
65 else if (Z <= 20) // K, Ca
66 nao = 13; // 4p is included
67 else if (Z <= 36) // Sc - Kr
68 nao = 18;
69 else if (Z <= 38) // Rb, Sr
70 nao = 22; // 5p is included
71 else if (Z <= 53) // Y - I
72 nao = 27;
73 else
74 throw std::invalid_argument{
75 "STO-3G basis is not defined for elements with Z > 53"};
76 return nao;
77}
78
85template <typename Real = double>
86const std::vector<Real>& sto3g_ao_occupation_vector(size_t Z) {
87 static std::vector<Real> occvec(27, 0.0);
88
90
91 occvec.resize(sto3g_num_ao(Z));
92 auto* occs_ptr = &occvec[0];
93 auto& occs = occs_ptr;
94
95 size_t num_of_electrons = Z; // # of electrons to allocate
96
97 // neutral atom electronic configurations from NIST:
98 // http://www.nist.gov/pml/data/images/illo_for_2014_PT_1.PNG
99 subshell_occvec(occs, 1, num_of_electrons); // 1s
100 if (Z > 2) { // Li+
101 subshell_occvec(occs, 1, num_of_electrons); // 2s
102 subshell_occvec(occs, 3, num_of_electrons); // 2p
103 }
104 if (Z > 10) { // Na+
105 subshell_occvec(occs, 1, num_of_electrons); // 3s
106 subshell_occvec(occs, 3, num_of_electrons); // 3p
107 }
108 if (18 < Z && Z <= 36) { // K .. Kr
109 // NB 4s is singly occupied in K, Cr, and Cu
110 size_t num_of_4s_electrons = (Z == 19 || Z == 24 || Z == 29) ? 1 : 2;
111 num_of_electrons -= num_of_4s_electrons;
112 subshell_occvec(occs, 1, num_of_4s_electrons); // 4s
113
114 size_t num_of_4p_electrons =
115 std::min(static_cast<decltype(Z)>(6), (Z > 30) ? Z - 30 : 0);
116 num_of_electrons -= num_of_4p_electrons;
117 subshell_occvec(occs, 3, num_of_4p_electrons); // 4p
118
119 subshell_occvec(occs, 5, num_of_electrons); // 3d
120 }
121 if (36 < Z && Z <= 53) { // Rb .. I
122 // 3d4s4p are fully occupied ...
123 subshell_occvec(occs, 1, num_of_electrons); // 4s
124 subshell_occvec(occs, 3, num_of_electrons); // 4p
125
126 // NB 5s is singly occupied in Rb, Nb, Mo, Ru, Rh, and Ag
127 size_t num_of_5s_electrons =
128 (Z == 37 || Z == 41 || Z == 42 || Z == 44 || Z == 45 || Z == 47) ? 1
129 : 2;
130 num_of_electrons -= num_of_5s_electrons;
131 subshell_occvec(occs, 1, num_of_5s_electrons); // 5s
132
133 size_t num_of_5p_electrons =
134 std::min(static_cast<decltype(Z)>(6), (Z > 48) ? Z - 48 : 0);
135 num_of_electrons -= num_of_5p_electrons;
136 subshell_occvec(occs, 3, num_of_5p_electrons); // 5p
137
138 subshell_occvec(occs, 5, num_of_electrons); // 3d
139 subshell_occvec(occs, 5, num_of_electrons); // 4d
140 }
141
142 return occvec;
143}
144
145} // namespace libint2
146
147#endif // INCLUDE_LIBINT2_CHEMISTRY_STO3GATOMICDENSITY_H_
void subshell_occvec(Real *&occvec, size_t size, size_t &ne)
computes orbital occupation numbers for a subshell of size size created by smearing no more than ne e...
Definition sto3g_atomic_density.h:41
Defaults definitions for various parameters assumed by Libint.
Definition algebra.cc:24
const std::vector< Real > & sto3g_ao_occupation_vector(size_t Z)
computes average orbital occupancies in the ground state of a neutral atoms
Definition sto3g_atomic_density.h:86
size_t sto3g_num_ao(size_t Z)
Definition sto3g_atomic_density.h:57