// // transform_tbint.cc // // Copyright (C) 2004 Edward Valeev // // Author: Edward Valeev // Maintainer: EV // // This file is part of the SC Toolkit. // // The SC Toolkit is free software; you can redistribute it and/or modify // it under the terms of the GNU Library General Public License as published by // the Free Software Foundation; either version 2, or (at your option) // any later version. // // The SC Toolkit is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Library General Public License for more details. // // You should have received a copy of the GNU Library General Public License // along with the SC Toolkit; see the file COPYING.LIB. If not, write to // the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. // // The U.S. Government is granted a limited license as per AL 91-7. // #ifdef __GNUG__ #pragma implementation #endif #include #include #include #include #include #include #include #include #include using namespace std; using namespace sc; inline int max(int a,int b) { return (a > b) ? a : b;} /*----------- TwoBodyMOIntsTransform -----------*/ static ClassDesc TwoBodyMOIntsTransform_cd( typeid(TwoBodyMOIntsTransform),"TwoBodyMOIntsTransform",1,"virtual public SavableState", 0, 0, 0); TwoBodyMOIntsTransform::TwoBodyMOIntsTransform(const std::string& name, const Ref& factory, const Ref& space1, const Ref& space2, const Ref& space3, const Ref& space4) : name_(name), factory_(factory), space1_(space1), space2_(space2), space3_(space3), space4_(space4) { mem_ = MemoryGrp::get_default_memorygrp(); msg_ = MessageGrp::get_default_messagegrp(); thr_ = ThreadGrp::get_default_threadgrp(); // Default values num_te_types_ = 1; memory_ = factory_->memory(); debug_ = factory_->debug(); dynamic_ = factory_->dynamic(); print_percent_ = factory_->print_percent(); ints_method_ = factory_->ints_method(); file_prefix_ = factory_->file_prefix(); } TwoBodyMOIntsTransform::TwoBodyMOIntsTransform(StateIn& si) : SavableState(si) { si.get(name_); factory_ << SavableState::restore_state(si); ints_acc_ << SavableState::restore_state(si); space1_ << SavableState::restore_state(si); space2_ << SavableState::restore_state(si); space3_ << SavableState::restore_state(si); space4_ << SavableState::restore_state(si); mem_ = MemoryGrp::get_default_memorygrp(); msg_ = MessageGrp::get_default_messagegrp(); thr_ = ThreadGrp::get_default_threadgrp(); si.get(num_te_types_); double memory; si.get(memory); memory_ = (size_t) memory; si.get(debug_); int dynamic; si.get(dynamic); dynamic_ = (bool) dynamic; si.get(print_percent_); int ints_method; si.get(ints_method); ints_method_ = (MOIntsTransformFactory::StoreMethod) ints_method; si.get(file_prefix_); } TwoBodyMOIntsTransform::~TwoBodyMOIntsTransform() { } void TwoBodyMOIntsTransform::save_data_state(StateOut& so) { so.put(name_); SavableState::save_state(factory_.pointer(),so); SavableState::save_state(ints_acc_.pointer(),so); SavableState::save_state(space1_.pointer(),so); SavableState::save_state(space2_.pointer(),so); SavableState::save_state(space3_.pointer(),so); SavableState::save_state(space4_.pointer(),so); so.put(num_te_types_); so.put((double)memory_); so.put(debug_); so.put((int)dynamic_); so.put(print_percent_); so.put((int)ints_method_); so.put(file_prefix_); } void TwoBodyMOIntsTransform::set_num_te_types(const int num_te_types) { // need to figure out how to determine the number of te types supported by this TwoBodyInt if (num_te_types < 1 || num_te_types > TwoBodyInt::num_tbint_types) throw std::runtime_error("TwoBodyMOIntsTransform::set_num_te_types() -- "); num_te_types_ = num_te_types; init_vars(); } void TwoBodyMOIntsTransform::set_memory(const size_t memory) { memory_ = memory; init_vars(); } Ref TwoBodyMOIntsTransform::mem() const {return mem_; } Ref TwoBodyMOIntsTransform::msg() const {return msg_; } Ref TwoBodyMOIntsTransform::ints_acc() const {return ints_acc_; } Ref TwoBodyMOIntsTransform::space1() const {return space1_;} Ref TwoBodyMOIntsTransform::space2() const {return space2_;} Ref TwoBodyMOIntsTransform::space3() const {return space3_;} Ref TwoBodyMOIntsTransform::space4() const {return space4_;} double TwoBodyMOIntsTransform::print_percent() const {return print_percent_; } int TwoBodyMOIntsTransform::batchsize() const {return batchsize_; } int TwoBodyMOIntsTransform::debug() const {return debug_; } bool TwoBodyMOIntsTransform::dynamic() const {return dynamic_; } int TwoBodyMOIntsTransform::num_te_types() const { return num_te_types_; } unsigned int TwoBodyMOIntsTransform::restart_orbital() const { return (ints_acc_.null() ? 0 : ints_acc_->next_orbital()); } /////////////////////////////////////////////////////// // Compute the batchsize for the transformation // // Only arrays allocated before exiting the loop over // i-batches are included here - only these arrays // affect the batch size. /////////////////////////////////////////////////////// int TwoBodyMOIntsTransform::compute_transform_batchsize_(size_t mem_static, int rank_i) { // Check is have enough for even static objects size_t mem_dyn = 0; if (memory_ <= mem_static) return 0; else mem_dyn = memory_ - mem_static; // Determine if calculation is possible at all (i.e., if ni=1 possible) int ni = 1; distsize_t maxdyn = compute_transform_dynamic_memory_(ni); if (maxdyn > mem_dyn) { return 0; } ni = 2; while (ni<=rank_i) { maxdyn = compute_transform_dynamic_memory_(ni); if (maxdyn >= mem_dyn) { ni--; break; } ni++; } if (ni > rank_i) ni = rank_i; return ni; } void TwoBodyMOIntsTransform::init_vars() { int me = msg_->me(); int restart_orbital = ints_acc_.nonnull() ? ints_acc_->next_orbital() : 0; int rank_i = space1_->rank() - restart_orbital; mem_static_ = 0; if (me == 0) { // mem_static should include storage in MOIndexSpace mem_static_ = space1_->memory_in_use() + space2_->memory_in_use() + space3_->memory_in_use() + space4_->memory_in_use(); // scf vector int nthreads = thr_->nthread(); // ... plus the integrals evaluators mem_static_ += nthreads * factory_->integral()->storage_required_grt(space1_->basis(),space2_->basis(), space3_->basis(),space4_->basis()); batchsize_ = compute_transform_batchsize_(mem_static_,rank_i); } // Send value of ni and mem_static to other nodes msg_->bcast(batchsize_); double mem_static_double = static_cast(mem_static_); msg_->bcast(mem_static_double); mem_static_ = static_cast(mem_static_double); if (batchsize_ == 0) throw std::runtime_error("TwoBodyMOIntsTransform::init_vars() -- batch size is 0: more memory or processors are needed"); npass_ = 0; int rest = 0; if (batchsize_ == rank_i) { npass_ = 1; rest = 0; } else { rest = rank_i%batchsize_; npass_ = (rank_i - rest)/batchsize_ + 1; if (rest == 0) npass_--; } } void TwoBodyMOIntsTransform::reinit_acc() { if (ints_acc_.nonnull()) ints_acc_ = 0; init_acc(); } void TwoBodyMOIntsTransform::obsolete() { reinit_acc(); } void TwoBodyMOIntsTransform::alloc_mem(const size_t localmem) { if (mem_.null()) throw std::runtime_error("TwoBodyMOIntsTransform::alloc_mem() -- memory group not initialized"); mem_->set_localsize(localmem); if (debug_ >= 1) { ExEnv::out0() << indent << "Size of global distributed array: " << mem_->totalsize() << " Bytes" << endl; } } void TwoBodyMOIntsTransform::dealloc_mem() { if (mem_.null()) throw std::runtime_error("TwoBodyMOIntsTransform::dealloc_mem() -- memory group not initialized"); mem_->set_localsize(0); } int TwoBodyMOIntsTransform::compute_nij(const int rank_i, const int rank_j, const int nproc, const int me) { // compute nij as nij on node 0, since nij on node 0 is >= nij on other nodes int index = 0; int nij = 0; for (int i=0; inext_orbital() : 0; int rank_i_restart = space1_->rank() - restart_orbital; os << indent << "Memory available per node: " << memory_ << " Bytes" << endl; os << indent << "Static memory used per node: " << mem_static_ << " Bytes" << endl; os << indent << "Total memory used per node: " << mem_dyn+mem_static_ << " Bytes" << endl; os << indent << "Memory required for one pass: " << compute_transform_dynamic_memory_(rank_i_restart)+mem_static_ << " Bytes" << endl; os << indent << "Minimum memory required: " << compute_transform_dynamic_memory_(1)+mem_static_ << " Bytes" << endl; os << indent << "Number of passes: " << (rank_i_restart+batchsize_-1)/batchsize_ << endl; os << indent << "Batch size: " << batchsize_ << endl; } void TwoBodyMOIntsTransform::mospace_report(std::ostream& os) const { os << indent << "MO space 1" << endl << incindent; space1_->print_summary(os); os << decindent; os << indent << "MO space 2" << endl << incindent; space2_->print_summary(os); os << decindent; os << indent << "MO space 3" << endl << incindent; space3_->print_summary(os); os << decindent; os << indent << "MO space 4" << endl << incindent; space4_->print_summary(os); os << decindent; } void TwoBodyMOIntsTransform::print_header(std::ostream& os) const { if (debug_ >= 0) os << indent << "Entered " << name_ << " integrals evaluator (transform type " << type() <<")" << endl; os << incindent; int nproc = msg_->n(); if (debug_ >= 1) os << indent << scprintf("nproc = %i", nproc) << endl; if (restart_orbital() && debug_ >= 1) { os << indent << scprintf("Restarting at orbital %d", restart_orbital()) << endl; } memory_report(os); if (dynamic_) os << indent << "Using dynamic load balancing." << endl; if (debug_ >= 1) mospace_report(os); } void TwoBodyMOIntsTransform::print_footer(std::ostream& os) const { os << decindent; if (debug_ >= 0) os << indent << "Exited " << name_ << " integrals evaluator (transform type " << type() <<")" << endl; } ///////////////////////////////////////////////////////////////////////////// // Local Variables: // mode: c++ // c-file-style: "CLJ-CONDENSED" // End: