source: ThirdParty/mpqc_open/src/lib/chemistry/qc/intv3/bounds.cc@ a844d8

Candidate_v1.6.1
Last change on this file since a844d8 was 860145, checked in by Frederik Heber <heber@…>, 8 years ago

Merge commit '0b990dfaa8c6007a996d030163a25f7f5fc8a7e7' as 'ThirdParty/mpqc_open'

  • Property mode set to 100644
File size: 10.1 KB
Line 
1//
2// bounds.cc
3//
4// Copyright (C) 1996 Limit Point Systems, Inc.
5//
6// Author: Curtis Janssen <cljanss@limitpt.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#include <stdlib.h>
29#include <math.h>
30
31#include <util/misc/formio.h>
32#include <chemistry/qc/intv3/types.h>
33#include <chemistry/qc/intv3/flags.h>
34#include <chemistry/qc/intv3/int2e.h>
35
36using namespace std;
37using namespace sc;
38
39#define COMPUTE_Q 1
40#define COMPUTE_R 2
41
42/* find the biggest number in the buffer */
43static double
44find_max(double *int_buffer,int nint)
45{
46 int i;
47 double max = 0.0;
48 for (i=0; i<nint; i++) {
49 double val = int_buffer[i];
50 if (val<0) val = -val;
51 if (val > max) max = val;
52 }
53 return max;
54 }
55
56void
57Int2eV3::int_init_bounds_nocomp()
58{
59 int i;
60 int nshell=bs1_->nshell();
61 int nsht=nshell*(nshell+1)/2;
62
63 if (int_Qvec) free(int_Qvec);
64
65 int_Qvec = (int_bound_t *) malloc(sizeof(int_bound_t)*nsht);
66 used_storage_ += sizeof(int_bound_t)*nsht;
67 if(int_Qvec==0) {
68 ExEnv::errn() << scprintf("int_init_bounds_nocomp: cannot malloc int_Qvec: %d",
69 nsht)
70 << endl;
71 exit(1);
72 }
73
74 int_Rvec = 0;
75
76 int_Q = int_bound_min;
77 for (i=0; i<nsht; i++) int_Qvec[i] = 0;
78}
79
80void
81Int2eV3::init_bounds()
82{
83 int_init_bounds_nocomp();
84 compute_bounds(&int_Q,int_Qvec,COMPUTE_Q);
85 }
86
87void
88Int2eV3::int_init_bounds_1der_nocomp()
89{
90 int i;
91 int nshell=bs1_->nshell();
92 int nsht=nshell*(nshell+1)/2;
93
94 if (!int_derivative_bounds) {
95 ExEnv::errn() << "requested der bounds but space not allocated" << endl;
96 exit(1);
97 }
98
99 if (int_Qvec) free(int_Qvec);
100 if (int_Rvec) free(int_Rvec);
101
102 int_Qvec = (int_bound_t *) malloc(sizeof(int_bound_t)*nsht);
103 int_Rvec = (int_bound_t *) malloc(sizeof(int_bound_t)*nsht);
104 used_storage_ += sizeof(int_bound_t)*nsht*2;
105 if((int_Qvec==0) || (int_Rvec==0)) {
106 ExEnv::errn() << scprintf("int_init_bounds_1der_nocomp: cannot malloc int_{R,Q}vec: %d",nsht) << endl;
107 exit(1);
108 }
109
110 int_Q = int_bound_min;
111 int_R = int_bound_min;
112 for (i=0; i<nsht; i++) int_Qvec[i] = int_Rvec[i] = 0;
113 }
114
115void
116Int2eV3::int_bounds_comp(int s1, int s2)
117{
118 compute_bounds_shell(&int_Q,int_Qvec,COMPUTE_Q,s1,s2);
119 }
120
121void
122Int2eV3::int_bounds_1der_comp(int s1, int s2)
123{
124 compute_bounds_shell(&int_Q,int_Qvec,COMPUTE_Q,s1,s2);
125 compute_bounds_shell(&int_R,int_Rvec,COMPUTE_R,s1,s2);
126 }
127
128void
129Int2eV3::init_bounds_1der()
130{
131 int_init_bounds_1der_nocomp();
132 compute_bounds(&int_Q,int_Qvec,COMPUTE_Q);
133 compute_bounds(&int_R,int_Rvec,COMPUTE_R);
134 }
135
136void
137Int2eV3::done_bounds()
138{
139 if (int_Qvec) free(int_Qvec);
140 int_Qvec = 0;
141 }
142
143void
144Int2eV3::done_bounds_1der()
145{
146 if (int_Qvec) free(int_Qvec);
147 if (int_Rvec) free(int_Rvec);
148 int_Qvec = 0;
149 int_Rvec = 0;
150 }
151
152int
153Int2eV3::erep_4bound(int s1, int s2, int s3, int s4)
154{
155 if (!int_Qvec)
156 return 256;
157
158 int Qij;
159 int Qkl;
160 if (s1 >= 0 && s2 >= 0) {
161 int ij=(s1>s2) ? ((s1*(s1+1))>>1)+s2 : ((s2*(s2+1))>>1)+s1;
162 Qij = int_Qvec[ij];
163 }
164 else Qij = int_Q;
165 if (s3 >=0 && s4 >= 0) {
166 int kl=(s3>s4) ? ((s3*(s3+1))>>1)+s4 : ((s4*(s4+1))>>1)+s3;
167 Qkl = int_Qvec[kl];
168 }
169 else Qkl = int_Q;
170
171 return Qij+Qkl;
172 }
173
174int
175Int2eV3::int_erep_2bound(int s1, int s2)
176{
177 if (!int_Qvec)
178 return int_bound_max;
179
180 int ij=(s1>s2) ? ((s1*(s1+1))>>1)+s2 : ((s2*(s2+1))>>1)+s1;
181
182 return((int) int_Qvec[ij]);
183 }
184
185int
186Int2eV3::int_erep_0bound_1der()
187{
188#if 0
189 ExEnv::outn() << scprintf("int_erep_0bound_1der(): Q: %4d R: %4d\n", int_Q,int_R);
190#endif
191 return 1 + int_Q + int_R;
192 }
193
194int
195Int2eV3::int_erep_2bound_1der(int s1, int s2)
196{
197 if (!int_Qvec || !int_Rvec)
198 return int_bound_max;
199
200 int ij=(s1>s2) ? ((s1*(s1+1))>>1)+s2 : ((s2*(s2+1))>>1)+s1;
201 int b1 = int_Qvec[ij] + int_R;
202 int b2 = int_Q + int_Rvec[ij];
203
204#if 0
205 ExEnv::outn() << scprintf("int_erep_2bound_1der(%d,%d): Q: %4d R: %4d\n",s1,s2,
206 int_Qvec[ij],int_Rvec[ij]);
207#endif
208
209 /* The actual bound is Qij R + Q Rij
210 * but since I'm using log base 2 I'll use
211 * 2 * max (Qij R, Q Rij) -> 1 + max (Qij + R, Q + Rij)
212 */
213
214 return 1 + ((b1>b2)? b1 : b2);
215 }
216
217int
218Int2eV3::erep_4bound_1der(int s1, int s2, int s3, int s4)
219{
220 if (!int_Qvec || !int_Rvec)
221 return 256;
222
223 int Qij, Qkl, Rij, Rkl;
224
225 if (s1 >= 0 && s2 >= 0) {
226 int ij=(s1>s2) ? ((s1*(s1+1))>>1)+s2 : ((s2*(s2+1))>>1)+s1;
227 Qij = int_Qvec[ij];
228 Rij = int_Rvec[ij];
229 }
230 else {
231 Qij = int_Q;
232 Rij = int_R;
233 }
234 if (s3 >= 0 && s4 >= 0) {
235 int kl=(s3>s4) ? ((s3*(s3+1))>>1)+s4 : ((s4*(s4+1))>>1)+s3;
236 Qkl = int_Qvec[kl];
237 Rkl = int_Rvec[kl];
238 }
239 else {
240 Qkl = int_Q;
241 Rkl = int_R;
242 }
243
244 int b1 = Qij + Rkl;
245 int b2 = Qkl + Rij;
246
247#if 0
248 ExEnv::outn() << scprintf("int_erep_4bound_1der(%d,%d,%d,%d): Q: %4d %4d R: %4d %4d\n",
249 s1,s2,s3,s4,
250 int_Qvec[ij],int_Qvec[kl],int_Rvec[ij],int_Rvec[kl]);
251#endif
252
253 /* The actual bound is Qij Rkl + Qkl Rij
254 * but since I'm using log base 2 I'll use
255 * 2 * max (Qij Rkl, Qkl Rij) -> 1 + max (Qij + Rkl, Qkl + Rij)
256 */
257
258 return 1 + ((b1>b2)? b1 : b2 );
259 }
260
261/* ripped off from clj's libintv2 */
262/* (add subsequently ripped back on from ets's libdmtscf) */
263
264/* Compute the partial bound arrays, either Q or R can be computed
265 * with appropiate choice of flag. */
266void
267Int2eV3::compute_bounds(int_bound_t *overall, int_bound_t *vec, int flag)
268{
269 int sh1,sh2;
270
271 if ((bs1_ != bs2_)&&(bs1_ != bs3_)&&(bs1_ != bs4_)) {
272 ExEnv::errn() << scprintf("bounds.compute_bounds: all centers must be the same")
273 << endl;
274 exit(1);
275 }
276
277 int nshell=bs1_->nshell();
278 int nsht=(nshell*(nshell+1))/2;
279
280 int me = grp_->me();
281 int n = grp_->n();
282
283 for (int i=0; i<nsht; i++) vec[i] = 0;
284
285 *overall = int_bound_min;
286 int sh12 = 0;
287 for(sh1=0; sh1 < bs1_->nshell() ; sh1++) {
288 for(sh2=0; sh2 <= sh1 ; sh2++,sh12++) {
289 if (sh12%n == me) compute_bounds_shell(overall,vec,flag,sh1,sh2);
290 }
291 }
292
293 grp_->sum(vec,nsht);
294 grp_->max(overall,1);
295 }
296
297/* Compute the partial bound arrays, either Q or R can be computed
298 * with appropiate choice of flag. */
299void
300Int2eV3::compute_bounds_shell(int_bound_t *overall, int_bound_t *vec,
301 int flag, int sh1, int sh2)
302{
303 int nint;
304 int shellij;
305 int shells[4],size[4];
306 double max;
307 double tol = pow(2.0,double(int_bound_min));
308 double loginv = 1.0/log(2.0);
309 int old_int_integral_storage = int_integral_storage;
310 int_integral_storage = 0;
311
312 int old_perm = permute();
313 set_permute(0);
314 int old_red = redundant();
315 set_redundant(1);
316
317 if ((bs1_ != bs2_)&&(bs1_ != bs3_)&&(bs1_ != bs4_)) {
318 ExEnv::errn() << scprintf("bounds.compute_bounds: all centers must be the same")
319 << endl;
320 exit(1);
321 }
322
323 if (sh1<sh2) {
324 int tmp = sh1;
325 sh1 = sh2;
326 sh2 = tmp;
327 }
328
329 shellij= ((sh1*(sh1+1))>>1) + sh2;
330 shells[0]=shells[2]=sh1;
331 shells[1]=shells[3]=sh2;
332
333 if (flag == COMPUTE_Q) {
334 erep(shells,size);
335 nint = size[0]*size[1]*size[0]*size[1];
336 max = find_max(int_buffer,nint);
337#if 0
338 ExEnv::outn() << scprintf("max for %d %d (size %d) is %15.11f\n", sh1, sh2, nint, max);
339#endif
340 }
341 else if (flag == COMPUTE_R) {
342 double max1,max2;
343 int_erep_bound1der(0,sh1,sh2,&nint);
344 max1 = find_max(int_buffer,nint);
345#if 0
346 ExEnv::outn() << scprintf("bound(%d) for (%d,%d) is %12.8f int_buffer =",
347 flag,sh1,sh2,max1);
348 for (i=0; (i<nint)&&(i<27); i++)
349 ExEnv::outn() << scprintf(" %12.8f",int_buffer[i]);
350 if (nint > 27) ExEnv::outn() << scprintf(" ...");
351 ExEnv::outn() << scprintf("\n");
352#endif
353 int_erep_bound1der(0,sh2,sh1,&nint);
354 max2 = find_max(int_buffer,nint);
355 max = (max1>max2)?max1:max2;
356 }
357 else {
358 ExEnv::outn() << scprintf("bad bound flag\n"); exit(1);
359 }
360
361 /* Compute the partial bound value. */
362 max = sqrt(max);
363 if (max>tol) {
364 vec[shellij] = (int_bound_t) ceil(log(max)*loginv);
365 }
366 else {
367 vec[shellij] = (int_bound_t) int_bound_min;
368 }
369
370 /* Multiply R contributions by a factor of two to account for
371 * fact that contributions from both centers must be accounted
372 * for. */
373 if (flag == COMPUTE_R) vec[shellij]++;
374 if (vec[shellij]>*overall) *overall = vec[shellij];
375#if 0
376 ExEnv::outn() << scprintf("bound(%d) for (%d,%d) is %4d int_buffer =",
377 flag,sh1,sh2,vec[shellij]);
378 for (i=0; (i<nint)&&(i<27); i++) ExEnv::outn() << scprintf(" %12.8f",int_buffer[i]);
379 if (nint > 27) ExEnv::outn() << scprintf(" ...");
380 ExEnv::outn() << scprintf("\n");
381#endif
382 int_integral_storage = old_int_integral_storage;
383
384 set_permute(old_perm);
385 set_redundant(old_red);
386
387 }
388
389/* This function is used to convert a double to its log base 2 rep
390 * for use in bound computations. */
391int
392Int2eV3::bound_to_logbound(double value)
393{
394 double tol = pow(2.0,double(int_bound_min));
395 double loginv = 1.0/log(2.0);
396 int_bound_t res;
397
398 if (value > tol) res = (int_bound_t) ceil(log(value)*loginv);
399 else res = int_bound_min;
400 return res;
401 }
402
403/* This function is used to convert a double from its log base 2 rep. */
404double
405Int2eV3::logbound_to_bound(int value)
406{
407 return pow(2.0,(double)value);
408 }
409
410/////////////////////////////////////////////////////////////////////////////
411
412// Local Variables:
413// mode: c++
414// c-file-style: "CLJ-CONDENSED"
415// End:
Note: See TracBrowser for help on using the repository browser.