Google

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

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