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

lbgbuild.h

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

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