Google

Main Page   Class Hierarchy   Compound List   File List   Compound Members   Related Pages  

lgbuild.h

00001 //
00002 // lgbuild.h --- definition of the local G matrix builder
00003 //
00004 // Copyright (C) 1996 Limit Point Systems, Inc.
00005 //
00006 // Author: Edward Seidl <seidl@janed.com>
00007 // Maintainer: LPS
00008 //
00009 // This file is part of the SC Toolkit.
00010 //
00011 // The SC Toolkit is free software; you can redistribute it and/or modify
00012 // it under the terms of the GNU Library General Public License as published by
00013 // the Free Software Foundation; either version 2, or (at your option)
00014 // any later version.
00015 //
00016 // The SC Toolkit is distributed in the hope that it will be useful,
00017 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019 // GNU Library General Public License for more details.
00020 //
00021 // You should have received a copy of the GNU Library General Public License
00022 // along with the SC Toolkit; see the file COPYING.LIB.  If not, write to
00023 // the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
00024 //
00025 // The U.S. Government is granted a limited license as per AL 91-7.
00026 //
00027 
00028 #ifndef _chemistry_qc_scf_lgbuild_h
00029 #define _chemistry_qc_scf_lgbuild_h
00030 
00031 #ifdef __GNUC__
00032 #pragma interface
00033 #endif
00034 
00035 #undef SCF_CHECK_INTS
00036 #undef SCF_CHECK_BOUNDS
00037 #undef SCF_DONT_USE_BOUNDS
00038 
00039 #include <chemistry/qc/scf/gbuild.h>
00040 
00041 namespace sc {
00042 
00043 template<class T>
00044 class LocalGBuild : public GBuild<T> {
00045   public:
00046     double tnint;
00047     
00048   protected:
00049     MessageGrp *grp_;
00050     TwoBodyInt *tbi_;
00051     GaussianBasisSet *gbs_;
00052     PetiteList *rpl_;
00053 
00054     signed char *pmax;
00055     int threadno_;
00056     int nthread_;
00057     double accuracy_;
00058     
00059   public:
00060     LocalGBuild(T& t, const Ref<TwoBodyInt>& tbi, const Ref<PetiteList>& rpl,
00061                 const Ref<GaussianBasisSet>& bs, const Ref<MessageGrp>& g,
00062                 signed char *pm, double acc, int nt=1, int tn=0) :
00063       GBuild<T>(t),
00064       pmax(pm), nthread_(nt), threadno_(tn), accuracy_(acc)
00065     {
00066       grp_ = g.pointer();
00067       tbi_ = tbi.pointer();
00068       rpl_ = rpl.pointer();
00069       gbs_ = bs.pointer();
00070     }
00071     ~LocalGBuild() {}
00072 
00073     void run() {
00074       int tol = (int) (log(accuracy_)/log(2.0));
00075       int me=grp_->me();
00076       int nproc = grp_->n();
00077   
00078       // grab references for speed
00079       GaussianBasisSet& gbs = *gbs_;
00080       PetiteList& pl = *rpl_;
00081       TwoBodyInt& tbi = *tbi_;
00082 
00083       tbi.set_redundant(0);
00084       const double *intbuf = tbi.buffer();
00085 
00086       tnint=0;
00087       sc_int_least64_t threadind=0;
00088       sc_int_least64_t ijklind=0;
00089 
00090       for (int i=0; i < gbs.nshell(); i++) {
00091         if (!pl.in_p1(i))
00092           continue;
00093 
00094         int fi=gbs.shell_to_function(i);
00095         int ni=gbs(i).nfunction();
00096         
00097         for (int j=0; j <= i; j++) {
00098           int oij = i_offset(i)+j;
00099           
00100           if (!pl.in_p2(oij))
00101             continue;
00102 
00103           int fj=gbs.shell_to_function(j);
00104           int nj=gbs(j).nfunction();
00105           int pmaxij = pmax[oij];
00106 
00107           for (int k=0; k <= i; k++, ijklind++) {
00108             if (ijklind%nproc != me)
00109               continue;
00110 
00111             threadind++;
00112             if (threadind % nthread_ != threadno_)
00113               continue;
00114             
00115             int fk=gbs.shell_to_function(k);
00116             int nk=gbs(k).nfunction();
00117 
00118             int pmaxijk=pmaxij, ptmp;
00119             if ((ptmp=pmax[i_offset(i)+k]-1) > pmaxijk) pmaxijk=ptmp;
00120             if ((ptmp=pmax[ij_offset(j,k)]-1) > pmaxijk) pmaxijk=ptmp;
00121         
00122             int okl = i_offset(k);
00123             for (int l=0; l <= (k==i?j:k); l++,okl++) {
00124               int pmaxijkl = pmaxijk;
00125               if ((ptmp=pmax[okl]) > pmaxijkl) pmaxijkl=ptmp;
00126               if ((ptmp=pmax[i_offset(i)+l]-1) > pmaxijkl) pmaxijkl=ptmp;
00127               if ((ptmp=pmax[ij_offset(j,l)]-1) > pmaxijkl) pmaxijkl=ptmp;
00128 
00129               int qijkl = pl.in_p4(oij,okl,i,j,k,l);
00130               if (!qijkl)
00131                 continue;
00132 
00133 #ifdef SCF_CHECK_BOUNDS
00134               double intbound = pow(2.0,double(tbi.log2_shell_bound(i,j,k,l)));
00135               double pbound   = pow(2.0,double(pmaxijkl));
00136               intbound *= qijkl;
00137               GBuild<T>::contribution.set_bound(intbound, pbound);
00138 #else
00139 #  ifndef SCF_DONT_USE_BOUNDS
00140               if (tbi.log2_shell_bound(i,j,k,l)+pmaxijkl < tol)
00141                 continue;
00142 #  endif
00143 #endif
00144 
00145               //tim_enter_default();
00146               tbi.compute_shell(i,j,k,l);
00147               //tim_exit_default();
00148 
00149               int e12 = (i==j);
00150               int e34 = (k==l);
00151               int e13e24 = (i==k) && (j==l);
00152               int e_any = e12||e34||e13e24;
00153     
00154               int fl=gbs.shell_to_function(l);
00155               int nl=gbs(l).nfunction();
00156      
00157               int ii,jj,kk,ll;
00158               int I,J,K,L;
00159               int index=0;
00160 
00161               for (I=0, ii=fi; I < ni; I++, ii++) {
00162                 for (J=0, jj=fj; J <= (e12 ? I : nj-1); J++, jj++) {
00163                   for (K=0, kk=fk; K <= (e13e24 ? I : nk-1); K++, kk++) {
00164                     int lend = (e34 ? ((e13e24)&&(K==I) ? J : K)
00165                                 : ((e13e24)&&(K==I)) ? J : nl-1);
00166 
00167                     for (L=0, ll=fl; L <= lend; L++, ll++, index++) {
00168 
00169                       double pki_int = intbuf[index];
00170 
00171                       if ((pki_int>0?pki_int:-pki_int) < 1.0e-15)
00172                         continue;
00173 
00174 #ifdef SCF_CHECK_INTS
00175                       if (isnan(pki_int))
00176                         abort();
00177 #endif
00178                       
00179                       if (qijkl > 1)
00180                         pki_int *= qijkl;
00181 
00182       if (e_any) {
00183         int ij,kl;
00184         double val;
00185 
00186         if (jj == kk) {
00187           /*
00188            * if i=j=k or j=k=l, then this integral contributes
00189            * to J, K1, and K2 of G(ij), so
00190            * pkval = (ijkl) - 0.25 * ((ikjl)-(ilkj))
00191            *       = 0.5 * (ijkl)
00192            */
00193           if (ii == jj || kk == ll) {
00194             ij = i_offset(ii)+jj;
00195             kl = i_offset(kk)+ll;
00196             val = (ij==kl) ? 0.5*pki_int : pki_int;
00197 
00198             GBuild<T>::contribution.cont5(ij,kl,val);
00199 
00200           } else {
00201             /*
00202              * if j=k, then this integral contributes
00203              * to J and K1 of G(ij)
00204              *
00205              * pkval = (ijkl) - 0.25 * (ikjl)
00206              *       = 0.75 * (ijkl)
00207              */
00208             ij = i_offset(ii)+jj;
00209             kl = i_offset(kk)+ll;
00210             val = (ij==kl) ? 0.5*pki_int : pki_int;
00211             
00212             GBuild<T>::contribution.cont4(ij,kl,val);
00213 
00214             /*
00215              * this integral also contributes to K1 and K2 of
00216              * G(il)
00217              *
00218              * pkval = -0.25 * ((ijkl)+(ikjl))
00219              *       = -0.5 * (ijkl)
00220              */
00221             ij = ij_offset(ii,ll);
00222             kl = ij_offset(kk,jj);
00223             val = (ij==kl) ? 0.5*pki_int : pki_int;
00224             
00225             GBuild<T>::contribution.cont3(ij,kl,val);
00226           }
00227         } else if (ii == kk || jj == ll) {
00228           /*
00229            * if i=k or j=l, then this integral contributes
00230            * to J and K2 of G(ij)
00231            *
00232            * pkval = (ijkl) - 0.25 * (ilkj)
00233            *       = 0.75 * (ijkl)
00234            */
00235           ij = i_offset(ii)+jj;
00236           kl = i_offset(kk)+ll;
00237           val = (ij==kl) ? 0.5*pki_int : pki_int;
00238 
00239           GBuild<T>::contribution.cont4(ij,kl,val);
00240 
00241           /*
00242            * this integral also contributes to K1 and K2 of
00243            * G(ik)
00244            *
00245            * pkval = -0.25 * ((ijkl)+(ilkj))
00246            *       = -0.5 * (ijkl)
00247            */
00248           ij = ij_offset(ii,kk);
00249           kl = ij_offset(jj,ll);
00250           val = (ij==kl) ? 0.5*pki_int : pki_int;
00251 
00252           GBuild<T>::contribution.cont3(ij,kl,val);
00253 
00254         } else {
00255           /*
00256            * This integral contributes to J of G(ij)
00257            *
00258            * pkval = (ijkl)
00259            */
00260           ij = i_offset(ii)+jj;
00261           kl = i_offset(kk)+ll;
00262           val = (ij==kl) ? 0.5*pki_int : pki_int;
00263 
00264           GBuild<T>::contribution.cont1(ij,kl,val);
00265 
00266           /*
00267            * and to K1 of G(ik)
00268            *
00269            * pkval = -0.25 * (ijkl)
00270            */
00271           ij = ij_offset(ii,kk);
00272           kl = ij_offset(jj,ll);
00273           val = (ij==kl) ? 0.5*pki_int : pki_int;
00274 
00275           GBuild<T>::contribution.cont2(ij,kl,val);
00276 
00277           if ((ii != jj) && (kk != ll)) {
00278             /*
00279              * if i!=j and k!=l, then this integral also
00280              * contributes to K2 of G(il)
00281              *
00282              * pkval = -0.25 * (ijkl)
00283              *
00284              * note: if we get here, then ik can't equal jl,
00285              * so pkval wasn't multiplied by 0.5 above.
00286              */
00287             ij = ij_offset(ii,ll);
00288             kl = ij_offset(kk,jj);
00289 
00290             GBuild<T>::contribution.cont2(ij,kl,val);
00291           }
00292         }
00293       } else { // !e_any
00294         if (jj == kk) {
00295           /*
00296            * if j=k, then this integral contributes
00297            * to J and K1 of G(ij)
00298            *
00299            * pkval = (ijkl) - 0.25 * (ikjl)
00300            *       = 0.75 * (ijkl)
00301            */
00302           GBuild<T>::contribution.cont4(i_offset(ii)+jj,i_offset(kk)+ll,pki_int);
00303 
00304           /*
00305            * this integral also contributes to K1 and K2 of
00306            * G(il)
00307            *
00308            * pkval = -0.25 * ((ijkl)+(ikjl))
00309            *       = -0.5 * (ijkl)
00310            */
00311           GBuild<T>::contribution.cont3(ij_offset(ii,ll),ij_offset(kk,jj),pki_int);
00312 
00313         } else if (ii == kk || jj == ll) {
00314           /*
00315            * if i=k or j=l, then this integral contributes
00316            * to J and K2 of G(ij)
00317            *
00318            * pkval = (ijkl) - 0.25 * (ilkj)
00319            *       = 0.75 * (ijkl)
00320            */
00321           GBuild<T>::contribution.cont4(i_offset(ii)+jj,i_offset(kk)+ll,pki_int);
00322 
00323           /*
00324            * this integral also contributes to K1 and K2 of
00325            * G(ik)
00326            *
00327            * pkval = -0.25 * ((ijkl)+(ilkj))
00328            *       = -0.5 * (ijkl)
00329            */
00330           GBuild<T>::contribution.cont3(ij_offset(ii,kk),ij_offset(jj,ll),pki_int);
00331 
00332         } else {
00333           /*
00334            * This integral contributes to J of G(ij)
00335            *
00336            * pkval = (ijkl)
00337            */
00338           GBuild<T>::contribution.cont1(i_offset(ii)+jj,i_offset(kk)+ll,pki_int);
00339 
00340           /*
00341            * and to K1 of G(ik)
00342            *
00343            * pkval = -0.25 * (ijkl)
00344            */
00345           GBuild<T>::contribution.cont2(ij_offset(ii,kk),ij_offset(jj,ll),pki_int);
00346 
00347           /*
00348            * and to K2 of G(il)
00349            *
00350            * pkval = -0.25 * (ijkl)
00351            */
00352           GBuild<T>::contribution.cont2(ij_offset(ii,ll),ij_offset(kk,jj),pki_int);
00353         }
00354       }
00355                     }
00356                   }
00357                 }
00358               }
00359 
00360               tnint += (double) ni*nj*nk*nl;
00361             }
00362           }
00363         }
00364       }
00365     }
00366 };
00367 
00368 }
00369 
00370 #endif
00371 
00372 // Local Variables:
00373 // mode: c++
00374 // c-file-style: "ETS"
00375 // End:

Generated at Fri Jan 10 08:14:09 2003 for MPQC 2.1.3 using the documentation package Doxygen 1.2.14.