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_BOUNDS
00036 #undef SCF_DONT_USE_BOUNDS
00037 
00038 #include <chemistry/qc/scf/gbuild.h>
00039 
00040 template<class T>
00041 class LocalGBuild : public GBuild<T> {
00042   public:
00043     double tnint;
00044     
00045   protected:
00046     MessageGrp *grp_;
00047     TwoBodyInt *tbi_;
00048     GaussianBasisSet *gbs_;
00049     PetiteList *rpl_;
00050 
00051     signed char *pmax;
00052     int threadno_;
00053     int nthread_;
00054     double accuracy_;
00055     
00056   public:
00057     LocalGBuild(T& t, const Ref<TwoBodyInt>& tbi, const Ref<PetiteList>& rpl,
00058                 const Ref<GaussianBasisSet>& bs, const Ref<MessageGrp>& g,
00059                 signed char *pm, double acc, int nt=1, int tn=0) :
00060       GBuild<T>(t),
00061       pmax(pm), nthread_(nt), threadno_(tn), accuracy_(acc)
00062     {
00063       grp_ = g.pointer();
00064       tbi_ = tbi.pointer();
00065       rpl_ = rpl.pointer();
00066       gbs_ = bs.pointer();
00067     }
00068     ~LocalGBuild() {}
00069 
00070     void run() {
00071       int tol = (int) (log(accuracy_)/log(2.0));
00072       int me=grp_->me();
00073       int nproc = grp_->n();
00074   
00075       // grab references for speed
00076       GaussianBasisSet& gbs = *gbs_;
00077       PetiteList& pl = *rpl_;
00078       TwoBodyInt& tbi = *tbi_;
00079 
00080       tbi.set_redundant(0);
00081       const double *intbuf = tbi.buffer();
00082 
00083       tnint=0;
00084       sc_int_least64_t threadind=0;
00085       sc_int_least64_t ijklind=0;
00086 
00087       for (int i=0; i < gbs.nshell(); i++) {
00088         if (!pl.in_p1(i))
00089           continue;
00090 
00091         int fi=gbs.shell_to_function(i);
00092         int ni=gbs(i).nfunction();
00093         
00094         for (int j=0; j <= i; j++) {
00095           int oij = i_offset(i)+j;
00096           
00097           if (!pl.in_p2(oij))
00098             continue;
00099 
00100           int fj=gbs.shell_to_function(j);
00101           int nj=gbs(j).nfunction();
00102           int pmaxij = pmax[oij];
00103 
00104           for (int k=0; k <= i; k++, ijklind++) {
00105             if (ijklind%nproc != me)
00106               continue;
00107 
00108             threadind++;
00109             if (threadind % nthread_ != threadno_)
00110               continue;
00111             
00112             int fk=gbs.shell_to_function(k);
00113             int nk=gbs(k).nfunction();
00114 
00115             int pmaxijk=pmaxij, ptmp;
00116             if ((ptmp=pmax[i_offset(i)+k]-1) > pmaxijk) pmaxijk=ptmp;
00117             if ((ptmp=pmax[ij_offset(j,k)]-1) > pmaxijk) pmaxijk=ptmp;
00118         
00119             int okl = i_offset(k);
00120             for (int l=0; l <= (k==i?j:k); l++,okl++) {
00121               int pmaxijkl = pmaxijk;
00122               if ((ptmp=pmax[okl]) > pmaxijkl) pmaxijkl=ptmp;
00123               if ((ptmp=pmax[i_offset(i)+l]-1) > pmaxijkl) pmaxijkl=ptmp;
00124               if ((ptmp=pmax[ij_offset(j,l)]-1) > pmaxijkl) pmaxijkl=ptmp;
00125 
00126               int qijkl = pl.in_p4(oij,okl,i,j,k,l);
00127               if (!qijkl)
00128                 continue;
00129 
00130 #ifdef SCF_CHECK_BOUNDS
00131               double intbound = pow(2.0,double(tbi.log2_shell_bound(i,j,k,l)));
00132               double pbound   = pow(2.0,double(pmaxijkl));
00133               intbound *= qijkl;
00134               GBuild<T>::contribution.set_bound(intbound, pbound);
00135 #else
00136 #  ifndef SCF_DONT_USE_BOUNDS
00137               if (tbi.log2_shell_bound(i,j,k,l)+pmaxijkl < tol)
00138                 continue;
00139 #  endif
00140 #endif
00141 
00142               //tim_enter_default();
00143               tbi.compute_shell(i,j,k,l);
00144               //tim_exit_default();
00145 
00146               int e12 = (i==j);
00147               int e34 = (k==l);
00148               int e13e24 = (i==k) && (j==l);
00149               int e_any = e12||e34||e13e24;
00150     
00151               int fl=gbs.shell_to_function(l);
00152               int nl=gbs(l).nfunction();
00153      
00154               int ii,jj,kk,ll;
00155               int I,J,K,L;
00156               int index=0;
00157 
00158               for (I=0, ii=fi; I < ni; I++, ii++) {
00159                 for (J=0, jj=fj; J <= (e12 ? I : nj-1); J++, jj++) {
00160                   for (K=0, kk=fk; K <= (e13e24 ? I : nk-1); K++, kk++) {
00161                     int lend = (e34 ? ((e13e24)&&(K==I) ? J : K)
00162                                 : ((e13e24)&&(K==I)) ? J : nl-1);
00163 
00164                     for (L=0, ll=fl; L <= lend; L++, ll++, index++) {
00165 
00166                       if (fabs(intbuf[index]) < 1.0e-15)
00167                         continue;
00168 
00169                       double pki_int = intbuf[index];
00170 
00171                       if (isnan(pki_int))
00172                         abort();
00173                       
00174                       if (qijkl > 1)
00175                         pki_int *= qijkl;
00176 
00177       if (e_any) {
00178         int ij,kl;
00179         double val;
00180 
00181         if (jj == kk) {
00182           /*
00183            * if i=j=k or j=k=l, then this integral contributes
00184            * to J, K1, and K2 of G(ij), so
00185            * pkval = (ijkl) - 0.25 * ((ikjl)-(ilkj))
00186            *       = 0.5 * (ijkl)
00187            */
00188           if (ii == jj || kk == ll) {
00189             ij = i_offset(ii)+jj;
00190             kl = i_offset(kk)+ll;
00191             val = (ij==kl) ? 0.5*pki_int : pki_int;
00192 
00193             GBuild<T>::contribution.cont5(ij,kl,val);
00194 
00195           } else {
00196             /*
00197              * if j=k, then this integral contributes
00198              * to J and K1 of G(ij)
00199              *
00200              * pkval = (ijkl) - 0.25 * (ikjl)
00201              *       = 0.75 * (ijkl)
00202              */
00203             ij = i_offset(ii)+jj;
00204             kl = i_offset(kk)+ll;
00205             val = (ij==kl) ? 0.5*pki_int : pki_int;
00206             
00207             GBuild<T>::contribution.cont4(ij,kl,val);
00208 
00209             /*
00210              * this integral also contributes to K1 and K2 of
00211              * G(il)
00212              *
00213              * pkval = -0.25 * ((ijkl)+(ikjl))
00214              *       = -0.5 * (ijkl)
00215              */
00216             ij = ij_offset(ii,ll);
00217             kl = ij_offset(kk,jj);
00218             val = (ij==kl) ? 0.5*pki_int : pki_int;
00219             
00220             GBuild<T>::contribution.cont3(ij,kl,val);
00221           }
00222         } else if (ii == kk || jj == ll) {
00223           /*
00224            * if i=k or j=l, then this integral contributes
00225            * to J and K2 of G(ij)
00226            *
00227            * pkval = (ijkl) - 0.25 * (ilkj)
00228            *       = 0.75 * (ijkl)
00229            */
00230           ij = i_offset(ii)+jj;
00231           kl = i_offset(kk)+ll;
00232           val = (ij==kl) ? 0.5*pki_int : pki_int;
00233 
00234           GBuild<T>::contribution.cont4(ij,kl,val);
00235 
00236           /*
00237            * this integral also contributes to K1 and K2 of
00238            * G(ik)
00239            *
00240            * pkval = -0.25 * ((ijkl)+(ilkj))
00241            *       = -0.5 * (ijkl)
00242            */
00243           ij = ij_offset(ii,kk);
00244           kl = ij_offset(jj,ll);
00245           val = (ij==kl) ? 0.5*pki_int : pki_int;
00246 
00247           GBuild<T>::contribution.cont3(ij,kl,val);
00248 
00249         } else {
00250           /*
00251            * This integral contributes to J of G(ij)
00252            *
00253            * pkval = (ijkl)
00254            */
00255           ij = i_offset(ii)+jj;
00256           kl = i_offset(kk)+ll;
00257           val = (ij==kl) ? 0.5*pki_int : pki_int;
00258 
00259           GBuild<T>::contribution.cont1(ij,kl,val);
00260 
00261           /*
00262            * and to K1 of G(ik)
00263            *
00264            * pkval = -0.25 * (ijkl)
00265            */
00266           ij = ij_offset(ii,kk);
00267           kl = ij_offset(jj,ll);
00268           val = (ij==kl) ? 0.5*pki_int : pki_int;
00269 
00270           GBuild<T>::contribution.cont2(ij,kl,val);
00271 
00272           if ((ii != jj) && (kk != ll)) {
00273             /*
00274              * if i!=j and k!=l, then this integral also
00275              * contributes to K2 of G(il)
00276              *
00277              * pkval = -0.25 * (ijkl)
00278              *
00279              * note: if we get here, then ik can't equal jl,
00280              * so pkval wasn't multiplied by 0.5 above.
00281              */
00282             ij = ij_offset(ii,ll);
00283             kl = ij_offset(kk,jj);
00284 
00285             GBuild<T>::contribution.cont2(ij,kl,val);
00286           }
00287         }
00288       } else { // !e_any
00289         if (jj == kk) {
00290           /*
00291            * if j=k, then this integral contributes
00292            * to J and K1 of G(ij)
00293            *
00294            * pkval = (ijkl) - 0.25 * (ikjl)
00295            *       = 0.75 * (ijkl)
00296            */
00297           GBuild<T>::contribution.cont4(i_offset(ii)+jj,i_offset(kk)+ll,pki_int);
00298 
00299           /*
00300            * this integral also contributes to K1 and K2 of
00301            * G(il)
00302            *
00303            * pkval = -0.25 * ((ijkl)+(ikjl))
00304            *       = -0.5 * (ijkl)
00305            */
00306           GBuild<T>::contribution.cont3(ij_offset(ii,ll),ij_offset(kk,jj),pki_int);
00307 
00308         } else if (ii == kk || jj == ll) {
00309           /*
00310            * if i=k or j=l, then this integral contributes
00311            * to J and K2 of G(ij)
00312            *
00313            * pkval = (ijkl) - 0.25 * (ilkj)
00314            *       = 0.75 * (ijkl)
00315            */
00316           GBuild<T>::contribution.cont4(i_offset(ii)+jj,i_offset(kk)+ll,pki_int);
00317 
00318           /*
00319            * this integral also contributes to K1 and K2 of
00320            * G(ik)
00321            *
00322            * pkval = -0.25 * ((ijkl)+(ilkj))
00323            *       = -0.5 * (ijkl)
00324            */
00325           GBuild<T>::contribution.cont3(ij_offset(ii,kk),ij_offset(jj,ll),pki_int);
00326 
00327         } else {
00328           /*
00329            * This integral contributes to J of G(ij)
00330            *
00331            * pkval = (ijkl)
00332            */
00333           GBuild<T>::contribution.cont1(i_offset(ii)+jj,i_offset(kk)+ll,pki_int);
00334 
00335           /*
00336            * and to K1 of G(ik)
00337            *
00338            * pkval = -0.25 * (ijkl)
00339            */
00340           GBuild<T>::contribution.cont2(ij_offset(ii,kk),ij_offset(jj,ll),pki_int);
00341 
00342           /*
00343            * and to K2 of G(il)
00344            *
00345            * pkval = -0.25 * (ijkl)
00346            */
00347           GBuild<T>::contribution.cont2(ij_offset(ii,ll),ij_offset(kk,jj),pki_int);
00348         }
00349       }
00350                     }
00351                   }
00352                 }
00353               }
00354 
00355               tnint += (double) ni*nj*nk*nl;
00356             }
00357           }
00358         }
00359       }
00360     }
00361 };
00362 
00363 #endif
00364 
00365 // Local Variables:
00366 // mode: c++
00367 // c-file-style: "ETS"
00368 // End:

Generated at Thu Oct 4 18:08:45 2001 for MPQC 2.0.0 using the documentation package Doxygen 1.2.5.