MPQC 3.0.0-alpha
Loading...
Searching...
No Matches
lgbuild.h
1//
2// lgbuild.h --- definition of the local G matrix builder
3//
4// Copyright (C) 1996 Limit Point Systems, Inc.
5//
6// Author: Edward Seidl <seidl@janed.com>
7// Maintainer: LPS
8//
9// This file is part of the SC Toolkit.
10//
11// The SC Toolkit is free software; you can redistribute it and/or modify
12// it under the terms of the GNU Library General Public License as published by
13// the Free Software Foundation; either version 2, or (at your option)
14// any later version.
15//
16// The SC Toolkit is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19// GNU Library General Public License for more details.
20//
21// You should have received a copy of the GNU Library General Public License
22// along with the SC Toolkit; see the file COPYING.LIB. If not, write to
23// the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24//
25// The U.S. Government is granted a limited license as per AL 91-7.
26//
27
28#ifndef _chemistry_qc_scf_lgbuild_h
29#define _chemistry_qc_scf_lgbuild_h
30
31#undef SCF_CHECK_INTS
32#undef SCF_CHECK_BOUNDS
33#undef SCF_DONT_USE_BOUNDS
34
35#include <mpqc_config.h>
36#include <chemistry/qc/scf/gbuild.h>
37
38namespace sc {
39
40template<class T>
41class LocalGBuild : public GBuild<T> {
42 public:
43 double tnint;
44 double tinttime;
45
46 protected:
47 MessageGrp *grp_;
48 TwoBodyInt *tbi_;
49 GaussianBasisSet *gbs_;
50 PetiteList *rpl_;
51
52 signed char * RESTRICT pmax;
53 int threadno_;
54 int nthread_;
55 double accuracy_;
56
57 public:
58 LocalGBuild(T& t, const Ref<TwoBodyInt>& tbi, const Ref<PetiteList>& rpl,
59 const Ref<GaussianBasisSet>& bs, const Ref<MessageGrp>& g,
60 signed char *pm, double acc, int nt=1, int tn=0) :
61 GBuild<T>(t),
62 pmax(pm), threadno_(tn), nthread_(nt), accuracy_(acc)
63 {
64 grp_ = g.pointer();
65 tbi_ = tbi.pointer();
66 rpl_ = rpl.pointer();
67 gbs_ = bs.pointer();
68 }
69 ~LocalGBuild() {}
70
71 void run() {
72 int tol = (int) (log(accuracy_)/log(2.0));
73 int me=grp_->me();
74 int nproc = grp_->n();
75
76 // grab references for speed
77 GaussianBasisSet& gbs = *gbs_;
78 PetiteList& pl = *rpl_;
79 TwoBodyInt& tbi = *tbi_;
80
81 tbi.set_redundant(0);
82 const double *intbuf = tbi.buffer();
83
84 tnint=0;
85 tinttime=0.0;
86 sc_int_least64_t threadind=0;
87 sc_int_least64_t ijklind=0;
88
89 for (int i=0; i < gbs.nshell(); i++) {
90 if (!pl.in_p1(i))
91 continue;
92
93 int fi=gbs.shell_to_function(i);
94 int ni=gbs(i).nfunction();
95
96 for (int j=0; j <= i; j++) {
97 int oij = i_offset(i)+j;
98
99 if (!pl.in_p2(oij))
100 continue;
101
102 int fj=gbs.shell_to_function(j);
103 int nj=gbs(j).nfunction();
104 int pmaxij = pmax[oij];
105
106 for (int k=0; k <= i; k++, ijklind++) {
107 if (ijklind%nproc != me)
108 continue;
109
110 threadind++;
111 if (threadind % nthread_ != threadno_)
112 continue;
113
114 int fk=gbs.shell_to_function(k);
115 int nk=gbs(k).nfunction();
116
117 int pmaxijk=pmaxij, ptmp;
118 if ((ptmp=pmax[i_offset(i)+k]-1) > pmaxijk) pmaxijk=ptmp;
119 if ((ptmp=pmax[ij_offset(j,k)]-1) > pmaxijk) pmaxijk=ptmp;
120
121 int okl = i_offset(k);
122 for (int l=0; l <= (k==i?j:k); l++,okl++) {
123 int pmaxijkl = pmaxijk;
124 if ((ptmp=pmax[okl]) > pmaxijkl) pmaxijkl=ptmp;
125 if ((ptmp=pmax[i_offset(i)+l]-1) > pmaxijkl) pmaxijkl=ptmp;
126 if ((ptmp=pmax[ij_offset(j,l)]-1) > pmaxijkl) pmaxijkl=ptmp;
127
128 int qijkl = pl.in_p4(oij,okl,i,j,k,l);
129 if (!qijkl)
130 continue;
131
132#ifdef SCF_CHECK_BOUNDS
133 double intbound = pow(2.0,double(tbi.log2_shell_bound(i,j,k,l)));
134 double pbound = pow(2.0,double(pmaxijkl));
135 intbound *= qijkl;
136 GBuild<T>::contribution.set_bound(intbound, pbound);
137#else
138# ifndef SCF_DONT_USE_BOUNDS
139 if (tbi.log2_shell_bound(i,j,k,l)+pmaxijkl < tol)
140 continue;
141# endif
142#endif
143
144#ifdef MPQC_NEW_FEATURES
145 const auto tstart = sc::RegionTimer::get_time_point();
146#endif
147 tbi.compute_shell(i,j,k,l);
148#ifdef MPQC_NEW_FEATURES
149 const auto tstop = RegionTimer::get_time_point();
150 const std::chrono::duration<double> time_elapsed = tstop - tstart;
151 tinttime += time_elapsed.count();
152#endif
153
154 int e12 = (i==j);
155 int e34 = (k==l);
156 int e13e24 = (i==k) && (j==l);
157 int e_any = e12||e34||e13e24;
158
159 int fl=gbs.shell_to_function(l);
160 int nl=gbs(l).nfunction();
161
162 int ii,jj,kk,ll;
163 int I,J,K,L;
164 int index=0;
165
166 for (I=0, ii=fi; I < ni; I++, ii++) {
167 for (J=0, jj=fj; J <= (e12 ? I : nj-1); J++, jj++) {
168 for (K=0, kk=fk; K <= (e13e24 ? I : nk-1); K++, kk++) {
169 int lend = (e34 ? ((e13e24)&&(K==I) ? J : K)
170 : ((e13e24)&&(K==I)) ? J : nl-1);
171
172 for (L=0, ll=fl; L <= lend; L++, ll++, index++) {
173
174 double pki_int = intbuf[index];
175
176 if ((pki_int>0?pki_int:-pki_int) < 1.0e-15)
177 continue;
178
179#ifdef SCF_CHECK_INTS
180#ifdef HAVE_ISNAN
181 if (isnan(pki_int))
182 abort();
183#endif
184#endif
185
186 if (qijkl > 1)
187 pki_int *= qijkl;
188
189 if (e_any) {
190 int ij,kl;
191 double val;
192
193 if (jj == kk) {
194 /*
195 * if i=j=k or j=k=l, then this integral contributes
196 * to J, K1, and K2 of G(ij), so
197 * pkval = (ijkl) - 0.25 * ((ikjl)-(ilkj))
198 * = 0.5 * (ijkl)
199 */
200 if (ii == jj || kk == ll) {
201 ij = i_offset(ii)+jj;
202 kl = i_offset(kk)+ll;
203 val = (ij==kl) ? 0.5*pki_int : pki_int;
204
205 GBuild<T>::contribution.cont5(ij,kl,val);
206
207 } else {
208 /*
209 * if j=k, then this integral contributes
210 * to J and K1 of G(ij)
211 *
212 * pkval = (ijkl) - 0.25 * (ikjl)
213 * = 0.75 * (ijkl)
214 */
215 ij = i_offset(ii)+jj;
216 kl = i_offset(kk)+ll;
217 val = (ij==kl) ? 0.5*pki_int : pki_int;
218
219 GBuild<T>::contribution.cont4(ij,kl,val);
220
221 /*
222 * this integral also contributes to K1 and K2 of
223 * G(il)
224 *
225 * pkval = -0.25 * ((ijkl)+(ikjl))
226 * = -0.5 * (ijkl)
227 */
228 ij = ij_offset(ii,ll);
229 kl = ij_offset(kk,jj);
230 val = (ij==kl) ? 0.5*pki_int : pki_int;
231
232 GBuild<T>::contribution.cont3(ij,kl,val);
233 }
234 } else if (ii == kk || jj == ll) {
235 /*
236 * if i=k or j=l, then this integral contributes
237 * to J and K2 of G(ij)
238 *
239 * pkval = (ijkl) - 0.25 * (ilkj)
240 * = 0.75 * (ijkl)
241 */
242 ij = i_offset(ii)+jj;
243 kl = i_offset(kk)+ll;
244 val = (ij==kl) ? 0.5*pki_int : pki_int;
245
246 GBuild<T>::contribution.cont4(ij,kl,val);
247
248 /*
249 * this integral also contributes to K1 and K2 of
250 * G(ik)
251 *
252 * pkval = -0.25 * ((ijkl)+(ilkj))
253 * = -0.5 * (ijkl)
254 */
255 ij = ij_offset(ii,kk);
256 kl = ij_offset(jj,ll);
257 val = (ij==kl) ? 0.5*pki_int : pki_int;
258
259 GBuild<T>::contribution.cont3(ij,kl,val);
260
261 } else {
262 /*
263 * This integral contributes to J of G(ij)
264 *
265 * pkval = (ijkl)
266 */
267 ij = i_offset(ii)+jj;
268 kl = i_offset(kk)+ll;
269 val = (ij==kl) ? 0.5*pki_int : pki_int;
270
271 GBuild<T>::contribution.cont1(ij,kl,val);
272
273 /*
274 * and to K1 of G(ik)
275 *
276 * pkval = -0.25 * (ijkl)
277 */
278 ij = ij_offset(ii,kk);
279 kl = ij_offset(jj,ll);
280 val = (ij==kl) ? 0.5*pki_int : pki_int;
281
282 GBuild<T>::contribution.cont2(ij,kl,val);
283
284 if ((ii != jj) && (kk != ll)) {
285 /*
286 * if i!=j and k!=l, then this integral also
287 * contributes to K2 of G(il)
288 *
289 * pkval = -0.25 * (ijkl)
290 *
291 * note: if we get here, then ik can't equal jl,
292 * so pkval wasn't multiplied by 0.5 above.
293 */
294 ij = ij_offset(ii,ll);
295 kl = ij_offset(kk,jj);
296
297 GBuild<T>::contribution.cont2(ij,kl,val);
298 }
299 }
300 } else { // !e_any
301 if (jj == kk) {
302 /*
303 * if j=k, then this integral contributes
304 * to J and K1 of G(ij)
305 *
306 * pkval = (ijkl) - 0.25 * (ikjl)
307 * = 0.75 * (ijkl)
308 */
309 GBuild<T>::contribution.cont4(i_offset(ii)+jj,i_offset(kk)+ll,pki_int);
310
311 /*
312 * this integral also contributes to K1 and K2 of
313 * G(il)
314 *
315 * pkval = -0.25 * ((ijkl)+(ikjl))
316 * = -0.5 * (ijkl)
317 */
318 GBuild<T>::contribution.cont3(ij_offset(ii,ll),ij_offset(kk,jj),pki_int);
319
320 } else if (ii == kk || jj == ll) {
321 /*
322 * if i=k or j=l, then this integral contributes
323 * to J and K2 of G(ij)
324 *
325 * pkval = (ijkl) - 0.25 * (ilkj)
326 * = 0.75 * (ijkl)
327 */
328 GBuild<T>::contribution.cont4(i_offset(ii)+jj,i_offset(kk)+ll,pki_int);
329
330 /*
331 * this integral also contributes to K1 and K2 of
332 * G(ik)
333 *
334 * pkval = -0.25 * ((ijkl)+(ilkj))
335 * = -0.5 * (ijkl)
336 */
337 GBuild<T>::contribution.cont3(ij_offset(ii,kk),ij_offset(jj,ll),pki_int);
338
339 } else {
340 /*
341 * This integral contributes to J of G(ij)
342 *
343 * pkval = (ijkl)
344 */
345 GBuild<T>::contribution.cont1(i_offset(ii)+jj,i_offset(kk)+ll,pki_int);
346
347 /*
348 * and to K1 of G(ik)
349 *
350 * pkval = -0.25 * (ijkl)
351 */
352 GBuild<T>::contribution.cont2(ij_offset(ii,kk),ij_offset(jj,ll),pki_int);
353
354 /*
355 * and to K2 of G(il)
356 *
357 * pkval = -0.25 * (ijkl)
358 */
359 GBuild<T>::contribution.cont2(ij_offset(ii,ll),ij_offset(kk,jj),pki_int);
360 }
361 }
362 }
363 }
364 }
365 }
366
367 tnint += (double) ni*nj*nk*nl;
368 }
369 }
370 }
371 }
372 }
373};
374
375}
376
377#endif
378
379// Local Variables:
380// mode: c++
381// c-file-style: "ETS"
382// End:
Definition gbuild.h:37
The GaussianBasisSet class is used describe a basis set composed of atomic gaussian orbitals.
Definition gaussbas.h:145
unsigned int nshell() const
Return the number of shells.
Definition gaussbas.h:500
int shell_to_function(int i) const
Return the number of the first function in the given shell.
Definition gaussbas.h:540
Definition lgbuild.h:41
double tnint
total # of integrals computed in this thread
Definition lgbuild.h:43
double tinttime
total user time spent computing integrals
Definition lgbuild.h:44
void run()
This is called with the Thread is run from a ThreadGrp.
Definition lgbuild.h:71
The MessageGrp abstract class provides a mechanism for moving data and objects between nodes in a par...
Definition message.h:120
int me()
Returns my processor number. In the range [0,n()).
Definition message.h:194
int n()
Returns the number of processors.
Definition message.h:192
PetiteList is a petite list (see Dupuis & King, IJQC 11,613,(1977) ) that can be used for constructin...
Definition petite.h:120
A template class that maintains references counts.
Definition ref.h:361
T * pointer() const
Returns a pointer the reference counted object.
Definition ref.h:413
This is an abstract base type for classes that compute integrals involving two electrons and 2 functi...
Definition tbint.h:61
virtual int log2_shell_bound(int=-1, int=-1, int=-1, int=-1)=0
Return log base 2 of the maximum magnitude of any integral in a shell block obtained from compute_she...
virtual void set_redundant(int i)
See redundant().
Definition tbint.h:168
virtual void compute_shell(int, int, int, int)=0
Given four shell indices, integrals will be computed and placed in the buffer.
virtual const double * buffer(TwoBodyOper::type type=TwoBodyOper::eri) const
The computed shell integrals will be put in the buffer returned by this member.
Contains all MPQC code up to version 3.
Definition mpqcin.h:14

Generated at Wed Sep 25 2024 02:45:30 for MPQC 3.0.0-alpha using the documentation package Doxygen 1.12.0.