00001 #include <chemistry/qc/basis/integral.h>
00002 #include <chemistry/qc/basis/tbint.h>
00003 #include <Chemistry_QC_GaussianBasis_DescrInterface.hxx>
00004 #include <Chemistry_QC_GaussianBasis_CompositeDescrInterface.hxx>
00005 #include <Chemistry_QC_GaussianBasis_DerivCentersInterface.hxx>
00006 #include <Chemistry_QC_GaussianBasis_MolecularInterface.hxx>
00007 #include <ChemistryDescrCXX_CompositeDescr.hxx>
00008 #include <limits.h>
00009 #include <vector>
00010 #include <utility>
00011 #include <sidl_SIDLException.hxx>
00012
00013 namespace MpqcCca {
00014
00015 typedef Chemistry::QC::GaussianBasis::DescrInterface
00016 QC_IntegralDescr;
00017 typedef Chemistry::QC::GaussianBasis::DerivCentersInterface
00018 QC_DerivCenters;
00019 typedef Chemistry::QC::GaussianBasis::CompositeDescrInterface
00020 QC_CompIntegralDescr;
00021
00022 class onebody_onecenter_computer {
00023
00024 private:
00025 int sh1_;
00026
00027 public:
00028 onebody_onecenter_computer():
00029 sh1_(-1) { }
00030
00031 void set_shells( int sh1 )
00032 {
00033 sh1_=sh1;
00034 }
00035
00036
00037 void compute(
00038 sc::OneBodyOneCenterInt* eval,
00039 QC_DerivCenters* dc )
00040 {
00041 eval->compute_shell( sh1_ );
00042 }
00043
00044 double compute_bounds(
00045 sc::OneBodyOneCenterInt* eval )
00046 {
00047 sidl::SIDLException ex = sidl::SIDLException::_create();
00048 try {
00049 ex.setNote("MPQC doesn't support one body in bounds");
00050 ex.add(__FILE__, __LINE__,"");
00051 }
00052 catch(...) { }
00053 throw ex;
00054 }
00055
00056 };
00057
00058
00059 class onebody_onecenter_deriv_computer {
00060
00061 private:
00062 int sh1_;
00063
00064 public:
00065 onebody_onecenter_deriv_computer():
00066 sh1_(-1) { }
00067
00068 void set_shells( int sh1 )
00069 {
00070 sh1_=sh1;
00071 }
00072
00073
00074 void compute(
00075 sc::OneBodyOneCenterDerivInt* eval,
00076 QC_DerivCenters* dc )
00077 {
00078 }
00079
00080 double compute_bounds(
00081 sc::OneBodyOneCenterDerivInt* eval )
00082 {
00083 sidl::SIDLException ex = sidl::SIDLException::_create();
00084 try {
00085 ex.setNote("MPQC doesn't support one body int bounds");
00086 ex.add(__FILE__, __LINE__,"");
00087 }
00088 catch(...) { }
00089 throw ex;
00090 }
00091
00092 };
00093
00094
00095 class onebody_computer {
00096
00097 private:
00098 int sh1_, sh2_;
00099
00100 public:
00101 onebody_computer():
00102 sh1_(-1), sh2_(-1) { }
00103
00104 void set_shells( int sh1, int sh2 )
00105 {
00106 sh1_=sh1; sh2_=sh2;
00107 }
00108
00109 void compute( sc::OneBodyInt* eval, QC_DerivCenters* dc )
00110 {
00111 eval->compute_shell( sh1_, sh2_ );
00112 }
00113
00114 double compute_bounds( sc::OneBodyInt* eval )
00115 {
00116 sidl::SIDLException ex = sidl::SIDLException::_create();
00117 try {
00118 ex.setNote("MPQC doesn't support one body in bounds");
00119 ex.add(__FILE__, __LINE__,"");
00120 }
00121 catch(...) { }
00122 throw ex;
00123 }
00124 };
00125
00126
00127 class onebody_deriv_computer {
00128
00129 private:
00130 int sh1_, sh2_;
00131
00132 public:
00133 onebody_deriv_computer():
00134 sh1_(-1), sh2_(-1) { }
00135
00136 void set_shells( int sh1, int sh2 )
00137 {
00138 sh1_=sh1; sh2_=sh2;
00139 }
00140
00141
00142 void compute( sc::OneBodyDerivInt* eval, QC_DerivCenters* dc )
00143 {
00144 eval->compute_shell( sh1_, sh2_, dc->get_deriv_atom() );
00145 }
00146
00147 double compute_bounds( sc::OneBodyDerivInt* eval )
00148 {
00149 sidl::SIDLException ex = sidl::SIDLException::_create();
00150 try {
00151 ex.setNote("MPQC doesn't support one body int bounds");
00152 ex.add(__FILE__, __LINE__,"");
00153 }
00154 catch(...) { }
00155 throw ex;
00156 }
00157 };
00158
00159
00160 class twobody_threecenter_computer {
00161
00162 private:
00163 int sh1_, sh2_, sh3_;
00164
00165 public:
00166 twobody_threecenter_computer():
00167 sh1_(-1), sh2_(-1), sh3_(-1) { }
00168
00169 void set_shells( int sh1, int sh2, int sh3 )
00170 {
00171 sh1_=sh1; sh2_=sh2; sh3_=sh3;
00172 }
00173
00174
00175 void compute( sc::TwoBodyThreeCenterInt* eval, QC_DerivCenters* dc )
00176 {
00177 eval->compute_shell( sh1_, sh2_, sh3_ );
00178 }
00179
00180 double compute_bounds( sc::TwoBodyThreeCenterInt* eval )
00181 { return eval->shell_bound( sh1_, sh2_, sh3_); }
00182 };
00183
00184
00185 class twobody_threecenter_deriv_computer {
00186
00187 private:
00188 int sh1_, sh2_, sh3_;
00189
00190 public:
00191 twobody_threecenter_deriv_computer():
00192 sh1_(-1), sh2_(-1), sh3_(-1) { }
00193
00194 void set_shells( int sh1, int sh2, int sh3 )
00195 {
00196 sh1_=sh1; sh2_=sh2; sh3_=sh3;
00197 }
00198
00199 void compute( sc::TwoBodyThreeCenterDerivInt* eval, QC_DerivCenters* dc )
00200 {
00201 }
00202
00203 double compute_bounds( sc::TwoBodyThreeCenterDerivInt* eval )
00204 { return eval->shell_bound( sh1_, sh2_, sh3_); }
00205 };
00206
00207
00208 class twobody_computer {
00209
00210 private:
00211 int sh1_, sh2_, sh3_, sh4_;
00212
00213 public:
00214 twobody_computer():
00215 sh1_(-1), sh2_(-1), sh3_(-1), sh4_(-1) { }
00216
00217 void set_shells( int sh1, int sh2, int sh3, int sh4 )
00218 {
00219 sh1_=sh1; sh2_=sh2; sh3_=sh3; sh4_=sh4;
00220 }
00221
00222
00223 void compute( sc::TwoBodyInt* eval, QC_DerivCenters* dc )
00224 {
00225 eval->compute_shell( sh1_, sh2_, sh3_, sh4_ );
00226 }
00227
00228 double compute_bounds( sc::TwoBodyInt* eval )
00229 {
00230 return eval->shell_bound( sh1_, sh2_, sh3_, sh4_ );
00231 }
00232 };
00233
00234
00235 class twobody_deriv_computer {
00236
00237 private:
00238 int sh1_, sh2_, sh3_, sh4_;
00239
00240 public:
00241 sc::DerivCenters sc_dc_;
00242
00243 public:
00244 twobody_deriv_computer():
00245 sh1_(-1), sh2_(-1), sh3_(-1), sh4_(-1) { }
00246
00247 void set_shells( int sh1, int sh2, int sh3, int sh4 )
00248 {
00249 sh1_=sh1; sh2_=sh2; sh3_=sh3; sh4_=sh4;
00250 }
00251
00252 void compute( sc::TwoBodyDerivInt* eval, QC_DerivCenters* dc )
00253 {
00254 sc_dc_.clear();
00255 eval->compute_shell(sh1_,sh2_,sh3_,sh4_,sc_dc_);
00256
00257 dc->clear();
00258 if( sc_dc_.has_omitted_center() )
00259 dc->add_omitted(sc_dc_.omitted_center(),sc_dc_.omitted_atom());
00260 for( int i=0; i<sc_dc_.n(); ++i)
00261 dc->add_center(sc_dc_.center(i),sc_dc_.atom(i));
00262 }
00263
00264 double compute_bounds( sc::TwoBodyDerivInt* eval )
00265 {
00266 return eval->shell_bound( sh1_, sh2_, sh3_, sh4_ );
00267 }
00268 };
00269
00270
00271
00272
00273
00274 template< typename eval_type, typename computer_type >
00275 class IntegralEvaluator {
00276
00277 public:
00278
00279 IntegralEvaluator( ) { }
00280
00281 ~IntegralEvaluator( ) {
00282 }
00283
00284 private:
00285
00286 std::vector< std::pair<eval_type*,QC_IntegralDescr> > evals_;
00287 std::vector< QC_DerivCenters > dcs_;
00288 std::vector< int > deriv_lvls_;
00289 std::vector< std::string > types_;
00290 std::vector< double* > buffers_;
00291 sidl::array<double> sidl_buffer_;
00292
00293 public:
00294
00295 void add_evaluator ( void* eval, QC_IntegralDescr desc )
00296 {
00297 eval_type* eval_ptr;
00298 eval_ptr = static_cast<eval_type*>(eval);
00299 std::pair<eval_type*,QC_IntegralDescr> p(eval_ptr,desc);
00300 evals_.push_back( p );
00301 dcs_.push_back( p.second.get_deriv_centers() );
00302 deriv_lvls_.push_back( p.second.get_deriv_lvl() );
00303 types_.push_back( p.second.get_type() );
00304 buffers_.push_back( const_cast<double*>( p.first->buffer()) );
00305 }
00306
00307 double* get_buffer ( QC_IntegralDescr desc )
00308 {
00309 for( int i=0; i<evals_.size(); ++i)
00310 if( desc.get_type() == types_[i] &&
00311 desc.get_deriv_lvl() == deriv_lvls_[i] ) {
00312 return const_cast<double*>( buffers_[i] );
00313 }
00314 return NULL;
00315 }
00316
00317 sidl::array<double> get_array ( QC_IntegralDescr desc,
00318 int buffer_size )
00319 {
00320 for( int i=0; i<evals_.size(); ++i)
00321 if( desc.get_type() == types_[i] &&
00322 desc.get_deriv_lvl() == deriv_lvls_[i] ) {
00323
00324 int lower[1] = {0};
00325 int upper[1];
00326 upper[0] = buffer_size - 1;
00327 int stride[1] = {1};
00328
00329 sidl_buffer_.borrow( buffers_[i], 1, lower, upper, stride);
00330 return sidl_buffer_;
00331 }
00332 }
00333
00334 Chemistry::QC::GaussianBasis::CompositeDescrInterface
00335 get_descriptor ()
00336 {
00337 Chemistry::QC::GaussianBasis::CompositeDescrInterface cdesc =
00338 ChemistryDescrCXX::CompositeDescr::_create();
00339 for( int i=0; i<evals_.size(); ++i)
00340 cdesc.add_descr( evals_[i].second );
00341 return cdesc;
00342 }
00343
00344 void compute ( computer_type* computer )
00345 {
00346 for( int i=0; i<evals_.size(); ++i) {
00347 if( deriv_lvls_[i] == 0 )
00348 computer->compute( evals_[i].first, NULL );
00349 else
00350 computer->compute( evals_[i].first, &(dcs_[i]) );
00351 }
00352 }
00353
00354 double compute_bounds( computer_type* computer )
00355 {
00356 double bounds=0;
00357 if( evals_.size() )
00358 for( int i=0; i<evals_.size(); ++i)
00359 bounds = std::max( computer->compute_bounds(evals_[i].first),
00360 bounds );
00361
00362 return bounds;
00363 }
00364
00365
00366 sidl::array<double> compute_array ( computer_type* computer,
00367 std::string type,
00368 int deriv_lvl,
00369 int buffer_size )
00370 {
00371 int lower[1] = {0};
00372 int upper[1];
00373 upper[0] = buffer_size - 1;
00374 int stride[1] = {1};
00375
00376 for( int i=0; i<evals_.size(); ++i)
00377 if( types_[i] == type && deriv_lvls_[i] == deriv_lvl ) {
00378
00379 if( deriv_lvls_[i] == 0 )
00380 computer->compute( evals_[i].first, NULL );
00381 else
00382 computer->compute( evals_[i].first, &(dcs_[i]) );
00383
00384 sidl_buffer_.borrow( const_cast<double*>(buffers_[i]),
00385 1, lower, upper, stride);
00386 return sidl_buffer_;
00387 }
00388
00389 return NULL;
00390 }
00391
00392 };
00393
00394
00395
00396 template< typename eval_type, typename computer_type >
00397 class CompositeIntegralEvaluator {
00398
00399 public:
00400
00401 CompositeIntegralEvaluator( ):
00402 have_new_shells_(true), sh1_(-1), sh2_(-1), sh3_(-1), sh4_(-1) { }
00403
00404 ~CompositeIntegralEvaluator( ) {
00405 }
00406
00407 private:
00408
00409 std::vector< std::pair<eval_type*,QC_CompIntegralDescr> > evals_;
00410 std::vector< sidl::array<double> > sidl_buffers_;
00411 int sh1_, sh2_, sh3_, sh4_;
00412 bool have_new_shells_;
00413 std::vector< double* > buffers_;
00414 std::vector< std::string > types_;
00415 std::vector< int > deriv_lvls_;
00416
00417 public:
00418
00419 void set_shells( int sh1, int sh2, int sh3, int sh4 )
00420 {
00421 have_new_shells_ = false;
00422 if( sh1_ != sh1 ) {
00423 sh1_ = sh1;
00424 have_new_shells_ = true;
00425 }
00426 if( sh2 != -1 && sh2_ != sh2 ) {
00427 sh2_ = sh2;
00428 have_new_shells_ = true;
00429 }
00430 if( sh3 != -1 && sh3_ != sh3 ) {
00431 sh3_ = sh3;
00432 have_new_shells_ = true;
00433 }
00434 if( sh4 != -1 && sh4_ != sh4 ) {
00435 sh4_ = sh4;
00436 have_new_shells_ = true;
00437 }
00438 }
00439
00440 void add_evaluator ( void* eval, QC_CompIntegralDescr cdesc )
00441 {
00442 eval_type* eval_ptr;
00443 eval_ptr = static_cast<eval_type*>(eval);
00444 std::pair<eval_type*,QC_CompIntegralDescr> p(eval_ptr,cdesc);
00445 evals_.push_back( p );
00446 }
00447
00448 double* get_buffer ( QC_IntegralDescr desc,
00449 sc::TwoBodyInt::tbint_type tbt )
00450 {
00451 std::string type = desc.get_type();
00452 int deriv_lvl = desc.get_deriv_lvl();
00453 for( int i=0; i<evals_.size(); ++i)
00454 for( int j=0; i<evals_[i].second.get_n_descr(); ++ j)
00455 if( type == evals_[i].second.get_descr(j).get_type() &&
00456 deriv_lvl == evals_[i].second.get_descr(j).get_deriv_lvl() ) {
00457 const double *b = evals_[i].first->buffer( tbt );
00458 types_.push_back( type );
00459 deriv_lvls_.push_back( deriv_lvl );
00460 buffers_.push_back( const_cast<double*>( b ) );
00461 return buffers_.back();
00462 }
00463 return NULL;
00464 }
00465
00466 sidl::array<double> get_array ( QC_IntegralDescr desc,
00467 sc::TwoBodyInt::tbint_type tbt,
00468 int buffer_size )
00469 {
00470 std::string type = desc.get_type();
00471 int deriv_lvl = desc.get_deriv_lvl();
00472 for( int i=0; i<evals_.size(); ++i) {
00473 for( int j=0; j<evals_[i].second.get_n_descr(); ++ j) {
00474 if( type == evals_[i].second.get_descr(j).get_type() &&
00475 deriv_lvl == evals_[i].second.get_descr(j).get_deriv_lvl() ) {
00476 const double *b = evals_[i].first->buffer( tbt );
00477 types_.push_back( type );
00478 deriv_lvls_.push_back( deriv_lvl );
00479 buffers_.push_back( const_cast<double*>( b ) );
00480 }
00481 }
00482 }
00483
00484 int lower[1] = {0};
00485 int upper[1];
00486 upper[0] = buffer_size - 1;
00487 int stride[1] = {1};
00488
00489 for( int i=0; i<buffers_.size(); ++i)
00490 if( types_[i] == type && deriv_lvls_[i] == deriv_lvl ) {
00491 sidl::array<double> sa;
00492 sa.borrow( buffers_[i], 1, lower, upper, stride);
00493 sidl_buffers_.push_back(sa);
00494 return sidl_buffers_.back();
00495 }
00496
00497 }
00498
00499 Chemistry::QC::GaussianBasis::CompositeDescrInterface
00500 get_descriptor ()
00501 {
00502 Chemistry::QC::GaussianBasis::CompositeDescrInterface cdesc =
00503 ChemistryDescrCXX::CompositeDescr::_create();
00504 for( int i=0; i<evals_.size(); ++i)
00505 for( int j=0; j<evals_[i].second.get_n_descr(); ++j )
00506 cdesc.add_descr( evals_[i].second.get_descr(j) );
00507 return cdesc;
00508 }
00509
00510 void compute ( computer_type* computer )
00511 {
00512 for( int i=0; i<evals_.size(); ++i)
00513 computer->compute( evals_[i].first, 0 );
00514 }
00515
00516 double compute_bounds( computer_type* computer )
00517 {
00518 double bounds=0;
00519 if( evals_.size() )
00520 for( int i=0; i<evals_.size(); ++i)
00521 bounds = std::max( computer->compute_bounds(evals_[i].first),
00522 bounds );
00523
00524 return bounds;
00525 }
00526
00527
00528 sidl::array<double> compute_array ( computer_type* computer,
00529 std::string type,
00530 int deriv_lvl,
00531 int buffer_size )
00532 {
00533 if( have_new_shells_ )
00534 compute( computer );
00535
00536 for( int i=0; i<buffers_.size(); ++i)
00537 if( types_[i] == type && deriv_lvls_[i] == deriv_lvl ) {
00538 return sidl_buffers_[i];
00539 }
00540
00541 return NULL;
00542 }
00543
00544 };
00545 }