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 |
|
---|
36 | using namespace std;
|
---|
37 | using namespace sc;
|
---|
38 |
|
---|
39 | #define COMPUTE_Q 1
|
---|
40 | #define COMPUTE_R 2
|
---|
41 |
|
---|
42 | /* find the biggest number in the buffer */
|
---|
43 | static double
|
---|
44 | find_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 |
|
---|
56 | void
|
---|
57 | Int2eV3::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 |
|
---|
80 | void
|
---|
81 | Int2eV3::init_bounds()
|
---|
82 | {
|
---|
83 | int_init_bounds_nocomp();
|
---|
84 | compute_bounds(&int_Q,int_Qvec,COMPUTE_Q);
|
---|
85 | }
|
---|
86 |
|
---|
87 | void
|
---|
88 | Int2eV3::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 |
|
---|
115 | void
|
---|
116 | Int2eV3::int_bounds_comp(int s1, int s2)
|
---|
117 | {
|
---|
118 | compute_bounds_shell(&int_Q,int_Qvec,COMPUTE_Q,s1,s2);
|
---|
119 | }
|
---|
120 |
|
---|
121 | void
|
---|
122 | Int2eV3::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 |
|
---|
128 | void
|
---|
129 | Int2eV3::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 |
|
---|
136 | void
|
---|
137 | Int2eV3::done_bounds()
|
---|
138 | {
|
---|
139 | if (int_Qvec) free(int_Qvec);
|
---|
140 | int_Qvec = 0;
|
---|
141 | }
|
---|
142 |
|
---|
143 | void
|
---|
144 | Int2eV3::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 |
|
---|
152 | int
|
---|
153 | Int2eV3::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 |
|
---|
174 | int
|
---|
175 | Int2eV3::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 |
|
---|
185 | int
|
---|
186 | Int2eV3::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 |
|
---|
194 | int
|
---|
195 | Int2eV3::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 |
|
---|
217 | int
|
---|
218 | Int2eV3::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. */
|
---|
266 | void
|
---|
267 | Int2eV3::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. */
|
---|
299 | void
|
---|
300 | Int2eV3::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. */
|
---|
391 | int
|
---|
392 | Int2eV3::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. */
|
---|
404 | double
|
---|
405 | Int2eV3::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:
|
---|