Annotation of /home/cljanss/src/SC/src/lib/chemistry/qc/basis/obint.cc for ./mpqc.vmon.0018
1 //
2 // obint.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 #ifdef __GNUC__
29 #pragma implementation
30 #endif
31
32 #include <util/misc/formio.h>
33
34 #include <math/scmat/block.h>
35 #include <math/scmat/blkiter.h>
36 #include <math/scmat/offset.h>
37
38 #include <chemistry/qc/basis/obint.h>
39 #include <chemistry/qc/basis/basis.h>
40
41 ///////////////////////////////////////////////////////////////////////
42
43 void
44 EfieldDotVectorData::set_position(double*p)
45 {
46 position[0] = p[0];
47 position[1] = p[1];
48 position[2] = p[2];
49 }
50
51 void
52 EfieldDotVectorData::set_vector(double*v)
53 {
54 vector[0] = v[0];
55 vector[1] = v[1];
56 vector[2] = v[2];
57 }
58
59 ///////////////////////////////////////////////////////////////////////
60
61 void
62 DipoleData::set_origin(double*o)
63 {
64 origin[0] = o[0];
65 origin[1] = o[1];
66 origin[2] = o[2];
67 }
68
69 ///////////////////////////////////////////////////////////////////////
70
71 PointChargeData::PointChargeData(int ncharges,
72 const double *const*positions,
73 const double *charges,
74 int copy_data)
75 {
76 ncharges_ = ncharges;
77 if (copy_data) {
78 alloced_positions_ = new double*[ncharges];
79 alloced_charges_ = new double[ncharges];
80 memcpy(alloced_charges_, charges, sizeof(double)*ncharges);
81 double *tmp = new double[ncharges*3];
82 for (int i=0; i<ncharges; i++) {
83 alloced_positions_[i] = tmp;
84 for (int j=0; j<3; j++) {
85 *tmp++ = positions[i][j];
86 }
87 }
88 positions_ = alloced_positions_;
89 charges_ = alloced_charges_;
90 }
91 else {
92 charges_ = charges;
93 alloced_charges_ = 0;
94 alloced_positions_ = 0;
95 charges_ = charges;
96 positions_ = positions;
97 }
98 }
99
100 PointChargeData::~PointChargeData()
101 {
102 if (alloced_positions_) {
103 delete[] alloced_positions_[0];
104 delete[] alloced_positions_;
105 }
106 delete[] alloced_charges_;
107 }
108
109 ///////////////////////////////////////////////////////////////////////
110
111 OneBodyInt::OneBodyInt(Integral* integral,
112 const Ref<GaussianBasisSet>&bs1,
113 const Ref<GaussianBasisSet>&bs2) :
114 integral_(integral),
115 bs1_(bs1), bs2_(bs2)
116 {
117 buffer_ = 0;
118 }
119
120 OneBodyInt::~OneBodyInt()
121 {
122 }
123
124 int
125 OneBodyInt::nbasis() const
126 {
127 return bs1_->nbasis();
128 }
129
130 int
131 OneBodyInt::nbasis1() const
132 {
133 return bs1_->nbasis();
134 }
135
136 int
137 OneBodyInt::nbasis2() const
138 {
139 return bs2_->nbasis();
140 }
141
142 int
143 OneBodyInt::nshell() const
144 {
145 return bs1_->nshell();
146 }
147
148 int
149 OneBodyInt::nshell1() const
150 {
151 return bs1_->nshell();
152 }
153
154 int
155 OneBodyInt::nshell2() const
156 {
157 return bs2_->nshell();
158 }
159
160 Ref<GaussianBasisSet>
161 OneBodyInt::basis()
162 {
163 return bs1_;
164 }
165
166 Ref<GaussianBasisSet>
167 OneBodyInt::basis1()
168 3 0 2 0 0 0 0 0 0 0 {
169 return bs1_;
170 }
171
172 Ref<GaussianBasisSet>
173 OneBodyInt::basis2()
174 1 0 0 0 0 0 0 0 0 0 {
175 return bs2_;
176 }
177
178 const double *
179 OneBodyInt::buffer() const
180 {
181 return buffer_;
182 }
183
184 void
185 OneBodyInt::reinitialize()
186 {
187 }
188
189 ///////////////////////////////////////////////////////////////////////
190
191 ShellPairIter::ShellPairIter()
192 {
193 }
194
195 ShellPairIter::~ShellPairIter()
196 {
197 }
198
199 void
200 ShellPairIter::init(const double * b, int ishell, int jshell,
201 int fi, int fj, int ni, int nj,
202 int red, double scl)
203 1 0 0 0 0 0 0 0 0 0 {
204 1 0 0 0 0 1 0 0 0 0 e12 = ((ishell==jshell) && red);
205
206 ioffset=fi;
207 joffset=fj;
208
209 iend=ni;
210 jend=nj;
211
212 1 0 0 0 0 0 0 0 0 0 buf=b;
213 scale_=scl;
214 }
215
216 ///////////////////////////////////////////////////////////////////////
217
218 OneBodyIntIter::OneBodyIntIter()
219 {
220 }
221
222 OneBodyIntIter::OneBodyIntIter(const Ref<OneBodyInt>& o) :
223 obi(o)
224 {
225 }
226
227 OneBodyIntIter::~OneBodyIntIter()
228 {
229 }
230
231 void
232 OneBodyIntIter::start(int ist, int jst, int ien, int jen)
233 4 0 3 0 1 0 0 0 0 0 {
234 istart=ist;
235 jstart=jst;
236 iend=ien;
237 1 0 0 0 0 0 0 0 0 0 jend=jen;
238
239 icur=istart;
240 jcur=jstart;
241
242 if (!iend) {
243 iend=obi->nshell1();
244 jend=obi->nshell2();
245 }
246
247 1 0 1 0 0 0 0 0 0 0 ij = (icur*(icur+1)>>1) + jcur;
248 }
249
250 static inline int
251 min(int i, int j)
252 0 0 1 0 1 0 0 0 0 0 {
253 return (i<j) ? i : j;
254 }
255
256 void
257 OneBodyIntIter::next()
258 1 0 0 0 0 1 0 0 0 0 {
259 1 0 0 0 0 0 0 0 0 0 int jlast = (redund) ? min(icur,jend-1) : jend-1;
260
261 if (jcur < jlast) {
262 jcur++;
263 ij++;
264 return;
265 }
266
267 jcur=jstart;
268 icur++;
269
270 1 0 0 0 0 0 0 0 0 0 ij = (icur*(icur+1)>>1) + jcur;
271 1 0 0 0 0 0 0 0 0 0 }
272
273 double
274 OneBodyIntIter::scale() const
275 {
276 return 1.0;
277 }
278
279 ShellPairIter&
280 OneBodyIntIter::current_pair()
281 {
282 obi->compute_shell(icur,jcur);
283 spi.init(obi->buffer(), icur, jcur,
284 obi->basis1()->shell_to_function(icur),
285 obi->basis2()->shell_to_function(jcur),
286 obi->basis1()->operator()(icur).nfunction(),
287 obi->basis2()->operator()(jcur).nfunction(),
288 redund, scale()
289 );
290
291 return spi;
292 0 0 0 0 1 0 0 0 0 0 }
293
294 ///////////////////////////////////////////////////////////////////////
295
296 OneBodyIntOp::OneBodyIntOp(const Ref<OneBodyInt>& it)
297 {
298 iter = new OneBodyIntIter(it);
299 }
300
301 OneBodyIntOp::OneBodyIntOp(const Ref<OneBodyIntIter>& it) :
302 iter(it)
303 {
304 }
305
306 OneBodyIntOp::~OneBodyIntOp()
307 {
308 }
309
310 void
311 OneBodyIntOp::process(SCMatrixBlockIter& b)
312 {
313 ExEnv::err() << node0 << indent
314 << "OneBodyIntOp::process: cannot handle generic case\n";
315 abort();
316 }
317
318 void
319 OneBodyIntOp::process_spec_rect(SCMatrixRectBlock* b)
320 {
321 Ref<GaussianBasisSet> bs1 = iter->one_body_int()->basis1();
322 Ref<GaussianBasisSet> bs2 = iter->one_body_int()->basis2();
323
324 // convert basis function indices into shell indices
325 int ishstart = bs1->function_to_shell(b->istart);
326 int jshstart = bs2->function_to_shell(b->jstart);
327
328 int b1end = b->iend;
329 int ishend = (b1end?bs1->function_to_shell(b1end-1) + 1 : 0);
330
331 int b2end = b->jend;
332 int jshend = (b2end?bs2->function_to_shell(b2end-1) + 1 : 0);
333
334 int njdata = b->jend - b->jstart;
335
336 iter->set_redundant(0);
337
338 for (iter->start(ishstart,jshstart,ishend,jshend);
339 iter->ready(); iter->next()) {
340 ShellPairIter& spi = iter->current_pair();
341
342 for (spi.start(); spi.ready(); spi.next()) {
343 int ifn = spi.i();
344 int jfn = spi.j();
345
346 if (ifn < b->istart || ifn >= b->iend ||
347 jfn < b->jstart || jfn >= b->jend)
348 continue;
349
350 int data_index = (ifn - b->istart)*njdata + jfn - b->jstart;
351 b->data[data_index] += spi.val();
352 }
353 }
354 }
355
356 void
357 OneBodyIntOp::process_spec_ltri(SCMatrixLTriBlock* b)
358 {
359 Ref<GaussianBasisSet> bs1 = iter->one_body_int()->basis1();
360
361 // convert basis function indices into shell indices
362 int fnstart = b->start;
363 int fnend = b->end;
364 int shstart = bs1->function_to_shell(fnstart);
365 int shend = (fnend?bs1->function_to_shell(fnend - 1) + 1 : 0);
366
367 iter->set_redundant(1);
368
369 // loop over all needed shells
370 for (iter->start(shstart,shstart,shend,shend); iter->ready(); iter->next()) {
371 ShellPairIter& spi = iter->current_pair();
372
373 // compute a set of shell integrals
374 for (spi.start(); spi.ready(); spi.next()) {
375 int ifn = spi.i();
376 int jfn = spi.j();
377
378 if (ifn < fnstart || ifn >= fnend)
379 continue;
380
381 int ioff = ifn-fnstart;
382 int joff = jfn-fnstart;
383
384 int data_index = i_offset(ioff)+joff;
385
386 b->data[data_index] += spi.val();
387 }
388 }
389 }
390
391 void
392 OneBodyIntOp::process_spec_rectsub(SCMatrixRectSubBlock* b)
393 {
394 Ref<GaussianBasisSet> bs1 = iter->one_body_int()->basis1();
395 Ref<GaussianBasisSet> bs2 = iter->one_body_int()->basis2();
396
397 // convert basis function indices into shell indices
398 int istart = b->istart;
399 int jstart = b->jstart;
400 int iend = b->iend;
401 int jend = b->jend;
402
403 int ishstart = bs1->function_to_shell(istart);
404 int jshstart = bs2->function_to_shell(jstart);
405
406 int ishend = (iend ? bs1->function_to_shell(iend-1) + 1 : 0);
407 int jshend = (jend ? bs2->function_to_shell(jend-1) + 1 : 0);
408
409 int njdata = b->istride;
410
411 iter->set_redundant(0);
412
413 for (iter->start(ishstart,jshstart,ishend,jshend);
414 iter->ready(); iter->next()) {
415 ShellPairIter& spi = iter->current_pair();
416
417 for (spi.start(); spi.ready(); spi.next()) {
418 int ifn = spi.i();
419 int jfn = spi.j();
420
421 if (ifn < istart || ifn >= iend || jfn < jstart || jfn >= jend)
422 continue;
423
424 int data_index = ifn*njdata + jfn;
425 b->data[data_index] += spi.val();
426 }
427 }
428 }
429
430 void
431 OneBodyIntOp::process_spec_ltrisub(SCMatrixLTriSubBlock* b)
432 1 0 0 0 0 0 0 0 0 0 {
433 Ref<GaussianBasisSet> bs1 = iter->one_body_int()->basis1();
434
435 // convert basis function indices into shell indices
436 int istart = b->istart;
437 1 0 1 0 0 0 0 0 0 0 int iend = b->iend;
438
439 int jstart = b->jstart;
440 0 0 0 0 1 0 0 0 0 0 int jend = b->jend;
441
442 int ishstart = bs1->function_to_shell(istart);
443 int jshstart = bs1->function_to_shell(jstart);
444
445 int ishend = (iend ? bs1->function_to_shell(iend-1) + 1 : 0);
446 1 0 0 0 1 0 0 0 0 0 int jshend = (jend ? bs1->function_to_shell(jend-1) + 1 : 0);
447
448 iter->set_redundant(1);
449
450 // loop over all needed shells
451 for (iter->start(ishstart,jshstart,ishend,jshend);
452 iter->ready(); iter->next()) {
453 ShellPairIter& spi = iter->current_pair();
454
455 // compute a set of shell integrals
456 for (spi.start(); spi.ready(); spi.next()) {
457 int ifn = spi.i();
458 int jfn = spi.j();
459
460 0 0 2 1 1 1 0 0 0 0 if (ifn < istart || ifn >= iend || jfn < jstart || jfn >= jend)
461 continue;
462
463 3 0 0 0 1 0 0 0 0 0 int data_index = i_offset(ifn)+jfn;
464 0 0 0 1 0 0 0 0 0 0 b->data[data_index] += spi.val();
465 }
466 }
467 }
468
469 int
470 OneBodyIntOp::has_side_effects()
471 {
472 return 1;
473 }
474
475 ///////////////////////////////////////////////////////////////////////
476
477 OneBody3IntOp::OneBody3IntOp(const Ref<OneBodyInt>& it)
478 {
479 iter = new OneBodyIntIter(it);
480 }
481
482 OneBody3IntOp::OneBody3IntOp(const Ref<OneBodyIntIter>& it) :
483 iter(it)
484 {
485 }
486
487 OneBody3IntOp::~OneBody3IntOp()
488 {
489 }
490
491 void
492 OneBody3IntOp::process(SCMatrixBlockIter&,
493 SCMatrixBlockIter&,
494 SCMatrixBlockIter&)
495 {
496 ExEnv::err() << node0 << indent
497 << "OneBody3IntOp::process(SCMatrixBlockIter&): "
498 << "cannot handle generic case\n";
499 abort();
500 }
501
502 void
503 OneBody3IntOp::process_spec_rect(SCMatrixRectBlock* a,
504 SCMatrixRectBlock* b,
505 SCMatrixRectBlock* c)
506 {
507 Ref<GaussianBasisSet> bs1 = iter->one_body_int()->basis1();
508 Ref<GaussianBasisSet> bs2 = iter->one_body_int()->basis2();
509
510 // convert basis function indices into shell indices
511 int ishstart = bs1->function_to_shell(b->istart);
512 int jshstart = bs2->function_to_shell(b->jstart);
513
514 int ishend = bs1->function_to_shell(b->iend);
515 int jshend = bs2->function_to_shell(b->jend);
516
517 iter->set_redundant(0);
518
519 for (iter->start(ishstart,jshstart,ishend,jshend);
520 iter->ready(); iter->next()) {
521 // compute a set of shell integrals
522 ShellPairIter& spi = iter->current_pair();
523
524 for (spi.start(); spi.ready(); spi.next()) {
525 int ifn = spi.i();
526 int jfn = spi.j();
527
528 if (ifn < b->istart || ifn >= b->iend ||
529 jfn < b->jstart || jfn >= b->jend)
530 continue;
531
532 #if 0
533 for (int i=0; i<nish; i++,ifn++) {
534 if (ifn < b->istart || ifn >= b->iend) {
535 tmp += njsh * 3;
536 }
537 else {
538 int jfn = jfnsave;
539 int data_index = (ifn - b->istart)*njdata + jfn - b->jstart;
540 for (int j=0; j<njsh; j++,jfn++) {
541 if (jfn >= b->jstart && jfn < b->jend) {
542 a->data[data_index] += tmp[0] * scale;
543 b->data[data_index] += tmp[1] * scale;
544 c->data[data_index] += tmp[2] * scale;
545 data_index++;
546 }
547 tmp += 3;
548 }
549 }
550 }
551 #endif
552 }
553 }
554 }
555
556 void
557 OneBody3IntOp::process_spec_ltri(SCMatrixLTriBlock* a,
558 SCMatrixLTriBlock* b,
559 SCMatrixLTriBlock* c)
560 {
561 #if 0
562 Ref<GaussianBasisSet> bs1 = iter->one_body_int()->basis1();
563
564 // convert basis function indices into shell indices
565 int fnstart = b->start;
566 int fnend = b->end;
567 int shstart = bs1->function_to_shell(fnstart);
568 int shend = (fnend?bs1->function_to_shell(fnend - 1) + 1 : 0);
569
570 // loop over all needed shells
571 iter->reset(shstart, shend, 0, 0);
572 for (iter->start_ltri(); iter->ready_ltri(); iter->next_ltri()) {
573 int ish=iter->ishell();
574 int jsh=iter->jshell();
575
576 int nish = bs1->operator[](ish).nfunction();
577 int njsh = bs1->operator[](jsh).nfunction();
578
579 double scale = iter->scale();
580
581 // compute a set of shell integrals
582 compute_shell(ish,jsh,buffer_);
583
584 // take the integrals from buffer and put them into the LTri block
585 double*tmp = buffer_;
586 int ifn = bs1->shell_to_function(ish);
587 int jfnsave = bs1->shell_to_function(jsh);
588 for (int i=0; i<nish; i++,ifn++) {
589 // skip over basis functions that are not needed
590 if (ifn < fnstart || ifn >= fnend) {
591 tmp += njsh * 3;
592 }
593 else {
594 int jfn = jfnsave;
595 int irelfn = ifn - fnstart;
596 int data_index = ((irelfn+1)*irelfn>>1) + jfn - fnstart;
597 for (int j=0; j<njsh; j++,jfn++) {
598 // skip over basis functions that are not needed
599 if (jfn <= ifn && jfn >= fnstart) {
600 a->data[data_index] += tmp[0] * scale;
601 b->data[data_index] += tmp[1] * scale;
602 c->data[data_index] += tmp[2] * scale;
603 data_index++;
604 }
605 tmp += 3;
606 }
607 }
608 }
609 }
610 #endif
611 }
612
613 int
614 OneBody3IntOp::has_side_effects()
615 {
616 return 1;
617 }
618
619 int
620 OneBody3IntOp::has_side_effects_in_arg1()
621 {
622 return 1;
623 }
624
625 int
626 OneBody3IntOp::has_side_effects_in_arg2()
627 {
628 return 1;
629 }
630
631 ///////////////////////////////////////////////////////////////////////
632
633 OneBodyDerivInt::OneBodyDerivInt(Integral *integral,
634 const Ref<GaussianBasisSet>&b) :
635 integral_(integral),
636 bs1(b), bs2(b)
637 {
638 // allocate a buffer
639 int biggest_shell = b->max_nfunction_in_shell();
640 biggest_shell *= biggest_shell * 3;
641
642 if (biggest_shell) {
643 buffer_ = new double[biggest_shell];
644 } else {
645 buffer_ = 0;
646 }
647 }
648
649 OneBodyDerivInt::OneBodyDerivInt(Integral *integral,
650 const Ref<GaussianBasisSet>&b1,
651 const Ref<GaussianBasisSet>&b2) :
652 integral_(integral),
653 bs1(b1), bs2(b2)
654 {
655 buffer_ = 0;
656 }
657
658 OneBodyDerivInt::~OneBodyDerivInt()
659 {
660 }
661
662 int
663 OneBodyDerivInt::nbasis() const
664 {
665 return bs1->nbasis();
666 }
667
668 int
669 OneBodyDerivInt::nbasis1() const
670 {
671 return bs1->nbasis();
672 }
673
674 int
675 OneBodyDerivInt::nbasis2() const
676 {
677 return bs2->nbasis();
678 }
679
680 int
681 OneBodyDerivInt::nshell() const
682 {
683 return bs1->nshell();
684 }
685
686 int
687 OneBodyDerivInt::nshell1() const
688 {
689 return bs1->nshell();
690 }
691
692 int
693 OneBodyDerivInt::nshell2() const
694 {
695 return bs2->nshell();
696 }
697
698 Ref<GaussianBasisSet>
699 OneBodyDerivInt::basis()
700 {
701 return bs1;
702 }
703
704 Ref<GaussianBasisSet>
705 OneBodyDerivInt::basis1()
706 {
707 return bs1;
708 }
709
710 Ref<GaussianBasisSet>
711 OneBodyDerivInt::basis2()
712 {
713 return bs2;
714 }
715
716 const double *
717 OneBodyDerivInt::buffer() const
718 {
719 return buffer_;
720 }
721
722 /////////////////////////////////////////////////////////////////////////////
723
724 // Local Variables:
725 // mode: c++
726 // c-file-style: "ETS"
727 // End:
728