1 /*
2 * This source code is part of
3 *
4 * E R K A L E
5 * -
6 * HF/DFT from Hel
7 *
8 * Written by Susi Lehtola, 2010-2014
9 * Copyright (c) 2010-2014, Susi Lehtola
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
15 */
16
17 /**
18 * This file contains routines for the automatical formation of
19 * application-specific basis sets.
20 *
21 * The algorithm performs completeness-optimization that was introduced in
22 *
23 * P. Manninen and J. Vaara, "Systematic Gaussian Basis-Set Limit
24 * Using Completeness-Optimized Primitive Sets. A Case for Magnetic
25 * Properties", J. Comp. Chem. 27, 434 (2006).
26 *
27 *
28 * The automatic algorithm for generating primitive basis sets was
29 * introduced in
30 *
31 * J. Lehtola, P. Manninen, M. Hakala, and K. Hämäläinen,
32 * "Completeness-optimized basis sets: Application to ground-state
33 * electron momentum densities", J. Chem. Phys. 137, 104105 (2012).
34 *
35 * and it was generalized to contracted basis sets in
36 *
37 * S. Lehtola, P. Manninen, M. Hakala, and K. Hämäläinen, "Contraction
38 * of completeness-optimized basis sets: Application to ground-state
39 * electron momentum densities", J. Chem. Phys. 138, 044109 (2013).
40 */
41
42 #include "co-opt.h"
43 #include "elements.h"
44
maxam(const std::vector<coprof_t> & cpl)45 int maxam(const std::vector<coprof_t> & cpl) {
46 for(size_t i=cpl.size()-1;i<cpl.size();i--)
47 if(cpl[i].exps.size()>0)
48 return (int) i;
49
50 // Dummy statement
51 return -1;
52 }
53
get_nfuncs(const std::vector<coprof_t> & cpl)54 int get_nfuncs(const std::vector<coprof_t> & cpl) {
55 int n=0;
56 for(int am=0;am<=maxam(cpl);am++)
57 n+=(2*am+1)*cpl[am].exps.size();
58 return n;
59 }
60
print_limits(const std::vector<coprof_t> & cpl,const char * msg)61 void print_limits(const std::vector<coprof_t> & cpl, const char *msg) {
62 if(msg)
63 printf("%s\n",msg);
64 for(int am=0;am<=maxam(cpl);am++)
65 printf("%c % .3f % .3f %e %2i\n",shell_types[am],cpl[am].start,cpl[am].end,cpl[am].tol,(int) cpl[am].exps.size());
66 printf("Totaling %i functions.\n\n",get_nfuncs(cpl));
67 fflush(stdout);
68 }
69
print_scheme(const BasisSetLibrary & baslib,int len)70 void print_scheme(const BasisSetLibrary & baslib, int len) {
71 // Get contraction scheme
72 ElementBasisSet el=baslib.get_elements()[0];
73
74 // Number of exponents and contractions
75 std::vector<int> nc, nx;
76
77 for(int am=0;am<=el.get_max_am();am++) {
78 arma::vec exps;
79 arma::mat coeffs;
80 el.get_primitives(exps,coeffs,am);
81 nx.push_back(coeffs.n_rows);
82 nc.push_back(coeffs.n_cols);
83 }
84
85 // Is the set contracted?
86 bool contr=false;
87 for(size_t i=0;i<nx.size();i++)
88 if(nx[i]!=nc[i])
89 contr=true;
90
91 std::string out;
92 char tmp[180];
93
94 if(contr) {
95 out="[";
96 for(int l=0;l<=el.get_max_am();l++) {
97 sprintf(tmp,"%i%c",nx[l],tolower(shell_types[l]));
98 out+=std::string(tmp);
99 }
100 out+="|";
101 for(int l=0;l<=el.get_max_am();l++)
102 if(nc[l]!=nx[l]) {
103 sprintf(tmp,"%i%c",nc[l],tolower(shell_types[l]));
104 out+=std::string(tmp);
105 }
106 out+="]";
107 } else {
108 out="(";
109 for(int l=0;l<=el.get_max_am();l++) {
110 sprintf(tmp,"%i%c",nx[l],tolower(shell_types[l]));
111 out+=std::string(tmp);
112 }
113 out+=")";
114 }
115
116 if(len==0)
117 printf("%s",out.c_str());
118 else {
119 // Format specifier
120 sprintf(tmp,"%%-%is",len);
121 printf(tmp,out.c_str());
122 }
123 }
124
maxwidth_exps_table(int am,double tol,size_t nexp,double & width,int n)125 arma::vec maxwidth_exps_table(int am, double tol, size_t nexp, double & width, int n) {
126
127 // Optimized exponents
128 static std::vector<co_exps_t> opt(max_am+1);
129
130 // Check if we already have the exponents in store
131 if(opt[am].tol!=tol || opt[am].exps.size()!=nexp) {
132 opt[am].tol=tol;
133 opt[am].exps=maxwidth_exps(am,tol,nexp,opt[am].w,n);
134 }
135
136 width=opt[am].w;
137
138 if(opt[am].exps.size() != nexp) {
139 std::ostringstream oss;
140 oss << "Required " << nexp << " completeness-optimized primitives but got " << opt[am].exps.size() << "!\n";
141 throw std::runtime_error(oss.str());
142 }
143
144 return opt[am].exps;
145 }
146
span_width(int am,double tol,double & width,int nx,int n)147 arma::vec span_width(int am, double tol, double & width, int nx, int n) {
148 // Check starting point
149 if(nx<0)
150 nx=0;
151
152 // Determine necessary amount of exponents
153 arma::vec exps;
154 double w=0.0;
155
156 for(nx++;nx<=NFMAX;nx++) {
157 exps=maxwidth_exps_table(am,tol,nx,w,n);
158 if(w>=width)
159 break;
160 }
161
162 // Store real width
163 width=w;
164
165 // Return exponents
166 return exps;
167 }
168
get_element_library(const std::string & el,const std::vector<coprof_t> & cpl)169 ElementBasisSet get_element_library(const std::string & el, const std::vector<coprof_t> & cpl) {
170 ElementBasisSet elbas(el);
171 for(size_t am=0;am<cpl.size();am++)
172 for(size_t ish=0;ish<cpl[am].exps.size();ish++) {
173 FunctionShell sh(am);
174 sh.add_exponent(1.0,cpl[am].exps[ish]);
175 elbas.add_function(sh);
176 }
177 elbas.sort();
178
179 return elbas;
180 }
181
augment_basis(const std::vector<coprof_t> & cplo,int ndiffuse,int ntight,int n_tau)182 std::vector<coprof_t> augment_basis(const std::vector<coprof_t> & cplo, int ndiffuse, int ntight, int n_tau) {
183 // New profile
184 std::vector<coprof_t> cpl(cplo);
185 if(ndiffuse==0 && ntight==0)
186 // Nothing to do
187 return cpl;
188
189 for(int am=0;am<=maxam(cpl);am++) {
190 // Require at least two exponents per augmented shell.
191 if(cpl[am].exps.size()<2)
192 continue;
193
194 // Current width
195 double width=cpl[am].end-cpl[am].start;
196
197 // New width and exponents
198 double w;
199 arma::vec exps=maxwidth_exps_table(am,cpl[am].tol,cpl[am].exps.size()+ndiffuse+ntight,w,n_tau);
200
201 // Additional width is
202 double dw=w-width;
203
204 // Update
205 cpl[am].start -= ndiffuse*dw/(ndiffuse+ntight);
206 cpl[am].end += ntight*dw/(ndiffuse+ntight);
207 cpl[am].exps=move_exps(exps,cpl[am].start);
208 }
209
210 return cpl;
211 }
212
213
get_library(const std::vector<coprof_t> & cpl)214 BasisSetLibrary get_library(const std::vector<coprof_t> & cpl) {
215 // Construct the basis set library
216 BasisSetLibrary baslib;
217 for(int Z=1;Z<=maxZ;Z++)
218 baslib.add_element(get_element_library(element_symbols[Z],cpl));
219
220 return baslib;
221 }
222