LIBINT  2.6.0
sto3g_atomic_density.h
1 /*
2  * Copyright (C) 2004-2019 Edward F. Valeev
3  *
4  * This file is part of Libint.
5  *
6  * Libint 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 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. 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 <vector>
26 
27 namespace libint2 {
28 
29 namespace detail {
30 
39 template <typename Real>
40 void subshell_occvec(Real*& occvec, size_t size, size_t& ne) {
41  const auto ne_alloc = (ne > 2 * size) ? 2 * size : ne;
42  ne -= ne_alloc;
43  // # of electrons / orbital compute as precisely as possible
44  const double ne_per_orb = (ne_alloc % size == 0)
45  ? static_cast<Real>(ne_alloc / size)
46  : (static_cast<Real>(ne_alloc)) / size;
47  for (size_t f = 0; f != size; ++f) occvec[f] = ne_per_orb;
48  occvec += size;
49 }
50 
51 } // namespace detail
52 
56 inline size_t sto3g_num_ao(size_t Z) {
57  size_t nao;
58  if (Z == 1 || Z == 2) // H, He
59  nao = 1;
60  else if (Z <= 10) // Li - Ne
61  nao = 5; // 2p is included even for Li and Be
62  else if (Z <= 18) // Na - Ar
63  nao = 9; // 3p is included even for Na and Mg
64  else if (Z <= 20) // K, Ca
65  nao = 13; // 4p is included
66  else if (Z <= 36) // Sc - Kr
67  nao = 18;
68  else if (Z <= 38) // Rb, Sr
69  nao = 22; // 5p is included
70  else if (Z <= 53) // Y - I
71  nao = 27;
72  else
73  throw "STO-3G basis is not defined for elements with Z > 53";
74  return nao;
75 }
76 
83 template <typename Real = double>
84 const std::vector<Real>& sto3g_ao_occupation_vector(size_t Z) {
85  static std::vector<Real> occvec(27, 0.0);
86 
88 
89  occvec.resize(sto3g_num_ao(Z));
90  auto* occs_ptr = &occvec[0];
91  auto& occs = occs_ptr;
92 
93  size_t num_of_electrons = Z; // # of electrons to allocate
94 
95  // neutral atom electronic configurations from NIST:
96  // http://www.nist.gov/pml/data/images/illo_for_2014_PT_1.PNG
97  subshell_occvec(occs, 1, num_of_electrons); // 1s
98  if (Z > 2) { // Li+
99  subshell_occvec(occs, 1, num_of_electrons); // 2s
100  subshell_occvec(occs, 3, num_of_electrons); // 2p
101  }
102  if (Z > 10) { // Na+
103  subshell_occvec(occs, 1, num_of_electrons); // 3s
104  subshell_occvec(occs, 3, num_of_electrons); // 3p
105  }
106  if (18 < Z && Z <= 36) { // K .. Kr
107  // NB 4s is singly occupied in K, Cr, and Cu
108  size_t num_of_4s_electrons = (Z == 19 || Z == 24 || Z == 29) ? 1 : 2;
109  num_of_electrons -= num_of_4s_electrons;
110  subshell_occvec(occs, 1, num_of_4s_electrons); // 4s
111 
112  size_t num_of_4p_electrons =
113  std::min(static_cast<decltype(Z)>(6), (Z > 30) ? Z - 30 : 0);
114  num_of_electrons -= num_of_4p_electrons;
115  subshell_occvec(occs, 3, num_of_4p_electrons); // 4p
116 
117  subshell_occvec(occs, 5, num_of_electrons); // 3d
118  }
119  if (36 < Z && Z <= 53) { // Rb .. I
120  // 3d4s4p are fully occupied ...
121  subshell_occvec(occs, 1, num_of_electrons); // 4s
122  subshell_occvec(occs, 3, num_of_electrons); // 4p
123 
124  // NB 5s is singly occupied in Rb, Nb, Mo, Ru, Rh, and Ag
125  size_t num_of_5s_electrons =
126  (Z == 37 || Z == 41 || Z == 42 || Z == 44 || Z == 45 || Z == 47) ? 1
127  : 2;
128  num_of_electrons -= num_of_5s_electrons;
129  subshell_occvec(occs, 1, num_of_5s_electrons); // 5s
130 
131  size_t num_of_5p_electrons =
132  std::min(static_cast<decltype(Z)>(6), (Z > 48) ? Z - 48 : 0);
133  num_of_electrons -= num_of_5p_electrons;
134  subshell_occvec(occs, 3, num_of_5p_electrons); // 5p
135 
136  subshell_occvec(occs, 5, num_of_electrons); // 3d
137  subshell_occvec(occs, 5, num_of_electrons); // 4d
138  }
139 
140  return occvec;
141 }
142 
143 } // namespace libint2
144 
145 
146 
147 #endif // INCLUDE_LIBINT2_CHEMISTRY_STO3GATOMICDENSITY_H_
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:84
size_t sto3g_num_ao(size_t Z)
Definition: sto3g_atomic_density.h:56
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:40