|
lbgbuild.h00001 // 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. |