00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifdef __GNUG__
00029 #pragma interface
00030 #endif
00031
00032 #ifndef _chemistry_qc_libint2_boundstimpl_h
00033 #define _chemistry_qc_libint2_boundstimpl_h
00034
00035 #include <vector>
00036 #include <cmath>
00037 #include <algorithm>
00038 #include <util/class/scexception.h>
00039 #include <chemistry/qc/libint2/int2e.h>
00040
00041 namespace libint2 {
00042 template <typename T>
00043 struct abssqrt : public std::unary_function<const T&,T> {
00044 T operator()(const T& x) {
00045 if (x < 0) return std::sqrt(std::negate<T>()(x));
00046 else return std::sqrt(x);
00047 }
00048 };
00049 }
00050
00051 namespace sc {
00052
00053 template <class Int2e>
00054 BoundsLibint2<Int2e>::BoundsLibint2(Integral*integral,
00055 const Ref<GaussianBasisSet>& b1,
00056 const Ref<GaussianBasisSet>& b2,
00057 const Ref<GaussianBasisSet>& b3,
00058 const Ref<GaussianBasisSet>& b4,
00059 size_t storage,
00060 const Ref<IntParams>& params) :
00061 nsh2_(b2->nshell()), nsh4_(b4->nshell())
00062 {
00063 equiv_12_34_ = b1->equiv(b3) && b2->equiv(b4);
00064 equiv_12_43_ = b1->equiv(b4) && b2->equiv(b3);
00065 equiv_1_2_ = b1->equiv(b2);
00066 equiv_3_4_ = b3->equiv(b4);
00067
00068 Ref<MessageGrp> msg = integral->messagegrp();
00069 const int ntasks = msg->n();
00070 const int me = msg->me();
00071
00072 const int nsh1 = b1->nshell();
00073 const int nsh2 = b2->nshell();
00074 const int n12 = nsh1*nsh2;
00075 {
00076 Ref<Int2e> int12 = libint2::create_int2e<Int2e>(integral,b1,b2,b1,b2,storage,params);
00077 Q12_.resize(n12); for(int i=0; i<n12; ++i) Q12_[i] = (int_bound_t)0;
00078 double* buf = int12->buffer(0);
00079 int f12 = 0;
00080 for(int s1=0; s1<nsh1; ++s1) {
00081 const int nf1 = b1->shell(s1).nfunction();
00082 for(int s2=0; s2<nsh2; ++s2, ++f12) {
00083 const int nf2 = b2->shell(s2).nfunction();
00084 const int nf = nf1*nf2*nf1*nf2;
00085
00086 if (f12%ntasks != me)
00087 continue;
00088
00089 int12->compute_quartet(&s1,&s2,&s1,&s2);
00090
00091 std::transform(buf,buf+nf,buf,::libint2::abssqrt<double>());
00092 const double max_elem = *(std::max_element(buf,buf+nf));
00093 Q12_[f12] = Log2Bounds::bound_cast(max_elem);
00094 }
00095 }
00096 }
00097
00098 {
00099 int_bound_t* q12 = new int_bound_t[n12];
00100 std::copy(Q12_.begin(),Q12_.end(),q12);
00101 msg->sum(q12,n12);
00102 std::copy(q12,q12+n12,Q12_.begin());
00103 }
00104
00105 if (!equiv_12_34_ && !equiv_12_43_) {
00106
00107 const int nsh3 = b3->nshell();
00108 const int nsh4 = b4->nshell();
00109 const int n34 = nsh3*nsh4;
00110 {
00111 Ref<Int2e> int34 = libint2::create_int2e<Int2e>(integral,b3,b4,b3,b4,storage,params);
00112 Q34_.resize(n34); for(int i=0; i<n34; ++i) Q34_[i] = (int_bound_t)0;
00113 double* buf = int34->buffer(0);
00114 int f34 = 0;
00115 for(int s3=0; s3<nsh3; ++s3) {
00116 const int nf3 = b3->shell(s3).nfunction();
00117 for(int s4=0; s4<nsh4; ++s4, ++f34) {
00118 const int nf4 = b4->shell(s4).nfunction();
00119 const int nf = nf3*nf4*nf3*nf4;
00120
00121 if (f34%ntasks != me)
00122 continue;
00123
00124 int34->compute_quartet(&s3,&s4,&s3,&s4);
00125
00126 std::transform(buf,buf+nf,buf,::libint2::abssqrt<double>());
00127 const double max_elem = *(std::max_element(buf,buf+nf));
00128 Q34_[f34] = Log2Bounds::bound_cast(max_elem);
00129 }
00130 }
00131 }
00132
00133 {
00134 int_bound_t* q34 = new int_bound_t[n34];
00135 std::copy(Q34_.begin(),Q34_.end(),q34);
00136 msg->sum(q34,n34);
00137 std::copy(q34,q34+n34,Q34_.begin());
00138 }
00139
00140 }
00141 else {
00142 if (equiv_12_34_) {
00143 Q34_ = Q12_;
00144 }
00145 else if (equiv_12_43_) {
00146 Q34_.resize(n12);
00147 int f12 = 0;
00148 for(int s2=0; s2<nsh2; ++s2) {
00149 for(int s1=0; s1<nsh1; ++s1, ++f12) {
00150 Q34_[f12] = Q12_[s1*nsh2 + s2];
00151 }
00152 }
00153 }
00154 }
00155
00156 if (debugclass_ > 1) {
00157 ExEnv::out0() << indent << "BoundsLibint2::Q12 :" << std::endl;
00158 for(int s1=0; s1<nsh1; ++s1) {
00159 const int s2max = equiv_1_2_ ? s1 : nsh2-1;
00160 for(int s2=0; s2<=s2max; ++s2) {
00161 const int f12 = s1*nsh2 + s2;
00162 ExEnv::out0() << indent << s1 << " " << s2 << " "
00163 << int(Q12_[f12]) << std::endl;
00164 }
00165 }
00166 }
00167 }
00168
00169 template <class Int2e>
00170 BoundsLibint2<Int2e>::~BoundsLibint2()
00171 {
00172 }
00173
00174 template <class Int2e>
00175 int
00176 BoundsLibint2<Int2e>::log2_bound(int sh1, int sh2, int sh3, int sh4) const
00177 {
00178 return Q12_[nsh2_*sh1 + sh2] + Q34_[nsh4_*sh3 + sh4];
00179 }
00180 }
00181
00182 #endif // header guard
00183
00184
00185
00186
00187