From: <ev...@us...> - 2010-06-04 20:53:48
|
Revision: 9444 http://mpqc.svn.sourceforge.net/mpqc/?rev=9444&view=rev Author: evaleev Date: 2010-06-04 20:53:41 +0000 (Fri, 04 Jun 2010) Log Message: ----------- Complete task: implemented a variety of DF solvers. Modified Paths: -------------- trunk/mpqc/src/lib/chemistry/qc/df/df.cc trunk/mpqc/src/lib/chemistry/qc/df/df.h trunk/mpqc/src/lib/chemistry/qc/df/df_runtime.cc trunk/mpqc/src/lib/chemistry/qc/df/df_runtime.h trunk/mpqc/src/lib/chemistry/qc/mbptr12/f77sym.in trunk/mpqc/src/lib/chemistry/qc/mbptr12/fockbuilder.cc trunk/mpqc/src/lib/chemistry/qc/mbptr12/lapack.h trunk/mpqc/src/lib/chemistry/qc/mbptr12/moints_runtime.cc trunk/mpqc/src/lib/chemistry/qc/mbptr12/moints_runtime.h trunk/mpqc/src/lib/chemistry/qc/mbptr12/svd.cc trunk/mpqc/src/lib/chemistry/qc/mbptr12/svd.h trunk/mpqc/src/lib/chemistry/qc/mbptr12/transform_ixjy_df.cc trunk/mpqc/src/lib/chemistry/qc/mbptr12/wfnworld.cc trunk/mpqc/src/lib/chemistry/qc/mbptr12/wfnworld.h Modified: trunk/mpqc/src/lib/chemistry/qc/df/df.cc =================================================================== --- trunk/mpqc/src/lib/chemistry/qc/df/df.cc 2010-06-04 20:52:34 UTC (rev 9443) +++ trunk/mpqc/src/lib/chemistry/qc/df/df.cc 2010-06-04 20:53:41 UTC (rev 9444) @@ -54,6 +54,7 @@ DensityFitting::DensityFitting(const Ref<MOIntsRuntime>& mointsruntime, const std::string& kernel_key, + SolveMethod solver, const Ref<OrbitalSpace>& space1, const Ref<OrbitalSpace>& space2, const Ref<GaussianBasisSet>& fitting_basis) : @@ -61,12 +62,12 @@ space1_(space1), space2_(space2), fbasis_(fitting_basis), - kernel_key_(kernel_key) + kernel_key_(kernel_key), + solver_(solver) { // only Coulomb fitting is supported at the moment if (kernel_key_ != std::string("1/r_{12}")) throw FeatureNotImplemented("Non-Coulomb fitting kernels are not supported",__FILE__,__LINE__); - solvemethod_ = SolveMethod_DSPSVX; // fitting dimension RefSCDimension fdim = new SCDimension(fbasis_->nbasis(), ""); @@ -81,13 +82,12 @@ space1_ << SavableState::restore_state(si); space2_ << SavableState::restore_state(si); si.get(kernel_key_); + int solvemethod; si.get(solvemethod); solver_ = static_cast<SolveMethod>(solvemethod); cC_ << SavableState::restore_state(si); C_ << SavableState::restore_state(si); int count; detail::FromStateIn<RefSymmSCMatrix>::get(kernel_,si,count); - - int solvemethod; si.get(solvemethod); solvemethod_ = static_cast<SolveMethod>(solvemethod); } void @@ -97,13 +97,12 @@ SavableState::save_state(space1_.pointer(),so); SavableState::save_state(space2_.pointer(),so); so.put(kernel_key_); + so.put((int)solver_); SavableState::save_state(cC_.pointer(),so); SavableState::save_state(C_.pointer(),so); int count; detail::ToStateOut<RefSymmSCMatrix>::put(kernel_,so,count); - - so.put((int)solvemethod_); } RefSCDimension @@ -220,12 +219,16 @@ std::vector<int> ipiv; // factorize or invert kernel - switch (solvemethod_) { - case SolveMethod_Inverse: + switch (solver_) { + case SolveMethod_InverseBunchKaufman: + case SolveMethod_InverseCholesky: { RefSymmSCMatrix kernel_i_mat = kernel_.clone(); kernel_i_mat.assign(kernel_); - exp::lapack_invert_symmnondef(kernel_i_mat, 1e10); + if (solver_ == SolveMethod_InverseBunchKaufman) + exp::lapack_invert_symmnondef(kernel_i_mat, 1e10); + if (solver_ == SolveMethod_InverseCholesky) + exp::lapack_invert_symmposdef(kernel_i_mat, 1e10); // convert kernel_i to dense rectangular form kernel_i.resize(n3 * n3); @@ -239,13 +242,28 @@ } break; - case SolveMethod_DSPSVX: + case SolveMethod_Cholesky: + case SolveMethod_RefinedCholesky: { // convert kernel_ to a packed upper-triangle form kernel_packed.resize(n3 * (n3 + 1) / 2); kernel_->convert(&(kernel_packed[0])); // factorize kernel_ using diagonal pivoting from LAPACK's DSPTRF kernel_factorized.resize(n3 * (n3 + 1) / 2); + sc::exp::lapack_cholesky_symmposdef(kernel_, + &(kernel_factorized[0]), + 1e10); + } + break; + + case SolveMethod_BunchKaufman: + case SolveMethod_RefinedBunchKaufman: + { + // convert kernel_ to a packed upper-triangle form + kernel_packed.resize(n3 * (n3 + 1) / 2); + kernel_->convert(&(kernel_packed[0])); + // factorize kernel_ using diagonal pivoting from LAPACK's DSPTRF + kernel_factorized.resize(n3 * (n3 + 1) / 2); ipiv.resize(n3); sc::exp::lapack_dpf_symmnondef(kernel_, &(kernel_factorized[0]), &(ipiv[0]), 1e10); @@ -264,21 +282,37 @@ const double* cC_jR = cC_->retrieve_pair_block(0, i, TwoBodyOper::eri); + bool refine_solution = true; // solve the linear system - switch (solvemethod_) { - case SolveMethod_Inverse: + switch (solver_) { + case SolveMethod_InverseCholesky: + case SolveMethod_InverseBunchKaufman: { C_DGEMM('n', 'n', n2, n3, n3, 1.0, cC_jR, n3, &(kernel_i[0]), n3, 0.0, &(C_jR[0]), n3); } break; - case SolveMethod_DSPSVX: + case SolveMethod_Cholesky: + refine_solution = false; + case SolveMethod_RefinedCholesky: { + sc::exp::lapack_linsolv_cholesky_symmposdef(&(kernel_packed[0]), n3, + &(kernel_factorized[0]), + &(C_jR[0]), cC_jR, n2, + refine_solution); + } + break; + + case SolveMethod_BunchKaufman: + refine_solution = false; + case SolveMethod_RefinedBunchKaufman: + { //sc::exp::lapack_linsolv_symmnondef(&(kernel_packed[0]), n3, &(C_jR[0]), cC_jR, n2); sc::exp::lapack_linsolv_dpf_symmnondef(&(kernel_packed[0]), n3, &(kernel_factorized[0]), - &(ipiv[0]), &(C_jR[0]), cC_jR, n2); + &(ipiv[0]), &(C_jR[0]), cC_jR, n2, + refine_solution); } break; @@ -317,11 +351,12 @@ TransformedDensityFitting::TransformedDensityFitting(const Ref<MOIntsRuntime>& rtime, const std::string& kernel_key, + DensityFitting::SolveMethod solver, const Ref<OrbitalSpace>& space1, const Ref<OrbitalSpace>& space2, const Ref<GaussianBasisSet>& fitting_basis, const Ref<DistArray4>& mo1_ao2_df) : - DensityFitting(rtime, kernel_key, space1, space2, fitting_basis), + DensityFitting(rtime, kernel_key, solver, space1, space2, fitting_basis), mo1_ao2_df_(mo1_ao2_df) { // make sure that mo1_ao2_df is a valid input @@ -428,11 +463,12 @@ PermutedDensityFitting::PermutedDensityFitting(const Ref<MOIntsRuntime>& rtime, const std::string& kernel_key, + DensityFitting::SolveMethod solver, const Ref<OrbitalSpace>& space1, const Ref<OrbitalSpace>& space2, const Ref<GaussianBasisSet>& fitting_basis, const Ref<DistArray4>& df21) : - DensityFitting(rtime, kernel_key, space1, space2, fitting_basis), + DensityFitting(rtime, kernel_key, solver, space1, space2, fitting_basis), df21_(df21) { // make sure that mo1_ao2_df is a valid input @@ -444,6 +480,7 @@ PermutedDensityFitting::PermutedDensityFitting(const Ref<DensityFitting>& df21) : DensityFitting(df21->runtime(), df21->kernel_key(), + df21->solver(), df21->space2(), df21->space1(), // swapped! df21->fbasis()), df21_(df21->C()) Modified: trunk/mpqc/src/lib/chemistry/qc/df/df.h =================================================================== --- trunk/mpqc/src/lib/chemistry/qc/df/df.h 2010-06-04 20:52:34 UTC (rev 9443) +++ trunk/mpqc/src/lib/chemistry/qc/df/df.h 2010-06-04 20:53:41 UTC (rev 9444) @@ -64,16 +64,30 @@ class DensityFitting: virtual public SavableState { public: enum SolveMethod { - SolveMethod_Inverse = 0, + SolveMethod_InverseCholesky = 0, SolveMethod_Cholesky = 1, - SolveMethod_DSPSVX = 2 + SolveMethod_RefinedCholesky = 2, + SolveMethod_InverseBunchKaufman = 3, + SolveMethod_BunchKaufman = 4, + SolveMethod_RefinedBunchKaufman = 5 }; typedef TwoBodyMOIntsRuntimeUnion23 MOIntsRuntime; ~DensityFitting(); + /** + * Determines density fitting of product (space1 space2) in terms of fitting basis. + * @param rtime + * @param kernel_key + * @param solver_key + * @param space1 + * @param space2 + * @param fitting_basis + * @return + */ DensityFitting(const Ref<MOIntsRuntime>& rtime, const std::string& kernel_key, + SolveMethod solver, const Ref<OrbitalSpace>& space1, const Ref<OrbitalSpace>& space2, const Ref<GaussianBasisSet>& fitting_basis); @@ -88,6 +102,7 @@ const Ref<OrbitalSpace>& space2() const { return space2_; } const Ref<GaussianBasisSet>& fbasis() const { return fbasis_; } const std::string& kernel_key() const { return kernel_key_; } + SolveMethod solver() const { return solver_; } /// returns the fitting coeffcients const Ref<DistArray4>& C() const { return C_; @@ -104,7 +119,7 @@ Ref<OrbitalSpace> space1_; Ref<OrbitalSpace> space2_; std::string kernel_key_; - SolveMethod solvemethod_; + SolveMethod solver_; bool evaluated_; @@ -140,6 +155,7 @@ /// compute density fitting for |mo1 mo2) from |mo1 ao2) TransformedDensityFitting(const Ref<MOIntsRuntime>& rtime, const std::string& kernel_key, + SolveMethod solver, const Ref<OrbitalSpace>& space1, const Ref<OrbitalSpace>& space2, const Ref<GaussianBasisSet>& fitting_basis, @@ -167,6 +183,7 @@ /// compute density fitting for |mo1 mo2) from |mo1 ao2) PermutedDensityFitting(const Ref<MOIntsRuntime>& rtime, const std::string& kernel_key, + SolveMethod solver, const Ref<OrbitalSpace>& space1, const Ref<OrbitalSpace>& space2, const Ref<GaussianBasisSet>& fitting_basis, Modified: trunk/mpqc/src/lib/chemistry/qc/df/df_runtime.cc =================================================================== --- trunk/mpqc/src/lib/chemistry/qc/df/df_runtime.cc 2010-06-04 20:52:34 UTC (rev 9443) +++ trunk/mpqc/src/lib/chemistry/qc/df/df_runtime.cc 2010-06-04 20:53:41 UTC (rev 9444) @@ -100,7 +100,7 @@ create<this_type> ); DensityFittingRuntime::DensityFittingRuntime(const Ref<MOIntsRuntime>& r) : - moints_runtime_(r), + moints_runtime_(r), solver_(DensityFitting::SolveMethod_RefinedBunchKaufman), results_(ResultRegistry::instance()) { } @@ -108,6 +108,7 @@ DensityFittingRuntime::DensityFittingRuntime(StateIn& si) { moints_runtime_ << SavableState::restore_state(si); + { int s; si.get(s); solver_ = static_cast<DensityFitting::SolveMethod>(s); } results_ = ResultRegistry::restore_instance(si); } @@ -115,6 +116,7 @@ DensityFittingRuntime::save_data_state(StateOut& so) { SavableState::save_state(moints_runtime_.pointer(),so); + so.put((int)solver_); ResultRegistry::save_instance(results_,so); } @@ -181,7 +183,7 @@ { const std::string bkey = ParsedResultKey::key(space2->id(), space1->id(), fspace->id()); if (this->exists(bkey)) { - Ref<DensityFitting> df = new PermutedDensityFitting(moints_runtime_, "1/r_{12}", + Ref<DensityFitting> df = new PermutedDensityFitting(moints_runtime_, "1/r_{12}", solver_, space1, space2, fspace->basis(), this->get(bkey)); df->compute(); @@ -205,7 +207,7 @@ if (!space2_is_ao) { const std::string bkey = ParsedResultKey::key(space1->id(), space2_ao->id(), fspace->id()); if (this->exists(bkey)) { - Ref<DensityFitting> df = new TransformedDensityFitting(moints_runtime_, "1/r_{12}", + Ref<DensityFitting> df = new TransformedDensityFitting(moints_runtime_, "1/r_{12}", solver_, space1, space2, fspace->basis(), this->get(bkey)); df->compute(); @@ -219,7 +221,7 @@ if (!space1_is_ao) { const std::string bkey = ParsedResultKey::key(space2->id(), space1_ao->id(), fspace->id()); if (this->exists(bkey)) { - Ref<DensityFitting> df = new TransformedDensityFitting(moints_runtime_, "1/r_{12}", + Ref<DensityFitting> df = new TransformedDensityFitting(moints_runtime_, "1/r_{12}", solver_, space2, space1, fspace->basis(), this->get(bkey)); const std::string tkey = ParsedResultKey::key(space2->id(), space1->id(), fspace->id()); @@ -234,7 +236,7 @@ if (!space1_is_ao) { const std::string bkey = ParsedResultKey::key(space1_ao->id(), space2->id(), fspace->id()); if (this->exists(bkey)) { - Ref<DensityFitting> df = new PermutedDensityFitting(moints_runtime_, "1/r_{12}", + Ref<DensityFitting> df = new PermutedDensityFitting(moints_runtime_, "1/r_{12}", solver_, space2, space1_ao, fspace->basis(), this->get(bkey)); const std::string tkey = ParsedResultKey::key(space2->id(), space1_ao->id(), fspace->id()); @@ -249,7 +251,7 @@ if (!space2_is_ao) { const std::string bkey = ParsedResultKey::key(space2_ao->id(), space1->id(), fspace->id()); if (this->exists(bkey)) { - Ref<DensityFitting> df = new PermutedDensityFitting(moints_runtime_, "1/r_{12}", + Ref<DensityFitting> df = new PermutedDensityFitting(moints_runtime_, "1/r_{12}", solver_, space1, space2_ao, fspace->basis(), this->get(bkey)); const std::string tkey = ParsedResultKey::key(space1->id(), space2_ao->id(), fspace->id()); @@ -283,7 +285,7 @@ aospace = space2_ao; } const std::string bkey = ParsedResultKey::key(mospace->id(), aospace->id(), fspace->id()); - Ref<DensityFitting> df = new DensityFitting(moints_runtime_, "1/r_{12}", + Ref<DensityFitting> df = new DensityFitting(moints_runtime_, "1/r_{12}", solver_, mospace, aospace, fspace->basis()); df->compute(); results_->add(bkey, df->C()); @@ -291,7 +293,7 @@ } #endif { - Ref<DensityFitting> df = new DensityFitting(moints_runtime_, "1/r_{12}", + Ref<DensityFitting> df = new DensityFitting(moints_runtime_, "1/r_{12}", solver_, space1, space2, fspace->basis()); df->compute(); ResultRef result = df->C(); @@ -306,6 +308,77 @@ ///////////////////////////////////////////////////////////////////////////// ClassDesc +DensityFittingParams::class_desc_(typeid(DensityFittingParams), + "DensityFittingParams", + 1, // version + "virtual public SavableState", // must match parent + 0, 0, create<DensityFittingParams> + ); + +DensityFittingParams::DensityFittingParams(const Ref<GaussianBasisSet>& basis, + const std::string& kernel, + const std::string& solver) : + basis_(basis), + kernel_(kernel) +{ + if (solver == "cholesky_inv") + solver_ = DensityFitting::SolveMethod_InverseCholesky; + else if (solver == "cholesky") + solver_ = DensityFitting::SolveMethod_Cholesky; + else if (solver == "cholesky_refine") + solver_ = DensityFitting::SolveMethod_RefinedCholesky; + else if (solver == "bunchkaufman_inv") + solver_ = DensityFitting::SolveMethod_InverseBunchKaufman; + else if (solver == "bunchkaufman") + solver_ = DensityFitting::SolveMethod_BunchKaufman; + else if (solver == "bunchkaufman_refine") + solver_ = DensityFitting::SolveMethod_RefinedBunchKaufman; + else + throw ProgrammingError("invalid solver", __FILE__, __LINE__, class_desc()); +} + +DensityFittingParams::DensityFittingParams(StateIn& si) : SavableState(si) { + basis_ << SavableState::restore_state(si); + si.get(kernel_); + int s; si.get(s); solver_ = static_cast<DensityFitting::SolveMethod>(s); +} + +DensityFittingParams::~DensityFittingParams() { +} + +void +DensityFittingParams::save_data_state(StateOut& so) { + SavableState::save_state(basis_.pointer(), so); + so.put(kernel_); + so.put((int)solver_); +} + +void +DensityFittingParams::print(std::ostream& o) const { + o << indent << "Density-Fitting Parameters:" << std::endl; + o << incindent; + o << indent << "basis set:" << std::endl; + o << incindent; + basis_->print(o); + o << decindent; + o << indent << "kernel = " << kernel_ << std::endl; + o << indent << "solver = "; + switch(solver_) { + case DensityFitting::SolveMethod_InverseBunchKaufman: o << "Bunch-Kaufman (inverse)"; break; + case DensityFitting::SolveMethod_BunchKaufman: o << "Bunch-Kaufman"; break; + case DensityFitting::SolveMethod_RefinedBunchKaufman: o << "Bunch-Kaufman (refine)"; break; + case DensityFitting::SolveMethod_InverseCholesky: o << "Cholesky (inverse)"; break; + case DensityFitting::SolveMethod_Cholesky: o << "Cholesky"; break; + case DensityFitting::SolveMethod_RefinedCholesky: o << "Cholesky (refine)"; break; + default: assert(false); // unreachable + } + o << std::endl; + o << decindent; +} + +///////////////////////////////////////////////////////////////////////////// + +ClassDesc DensityFittingInfo::class_desc_(typeid(this_type), "DensityFittingInfo", 1, Modified: trunk/mpqc/src/lib/chemistry/qc/df/df_runtime.h =================================================================== --- trunk/mpqc/src/lib/chemistry/qc/df/df_runtime.h 2010-06-04 20:52:34 UTC (rev 9443) +++ trunk/mpqc/src/lib/chemistry/qc/df/df_runtime.h 2010-06-04 20:53:41 UTC (rev 9444) @@ -78,6 +78,11 @@ /// obsoletes this object void obsolete(); + /// which density fitting solver will be used to compute? + DensityFitting::SolveMethod solver() const { return solver_; } + /// change default solver to this + void set_solver(DensityFitting::SolveMethod s) { solver_ = s; } + /** Returns true if the given DensityFitting is available */ bool exists(const std::string& key) const; @@ -95,6 +100,7 @@ private: Ref<MOIntsRuntime> moints_runtime_; + DensityFitting::SolveMethod solver_; typedef Registry<std::string, ResultRef, detail::NonsingletonCreationPolicy > ResultRegistry; Ref<ResultRegistry> results_; @@ -106,40 +112,66 @@ }; + /// DensityFittingParams defines parameters needed to compute density fitting objects + class DensityFittingParams : virtual public SavableState { + public: + /** + * Encapsulates parameters used by all density fitting objects + * @param basis + * @param kernel + * @param solver + * @return + */ + DensityFittingParams(const Ref<GaussianBasisSet>& basis, + const std::string& kernel, + const std::string& solver); + DensityFittingParams(StateIn&); + ~DensityFittingParams(); + void save_data_state(StateOut&); + + const Ref<GaussianBasisSet>& basis() const { return basis_; } + const std::string& kernel() const { return kernel_; } + DensityFitting::SolveMethod solver() const { return solver_; } + + void print(std::ostream& o) const; + + private: + static ClassDesc class_desc_; + + Ref<GaussianBasisSet> basis_; + std::string kernel_; + DensityFitting::SolveMethod solver_; + + }; + /// this class encapsulates objects needed to perform density fitting of a 4-center integral struct DensityFittingInfo : virtual public SavableState { public: typedef DensityFittingInfo this_type; - DensityFittingInfo(const Ref<GaussianBasisSet>& b1, - const Ref<GaussianBasisSet>& b2, + DensityFittingInfo(const Ref<DensityFittingParams>& p, const Ref<DensityFittingRuntime>& r) : - basis1_(b1), basis2_(b2), runtime_(r) {} + params_(p), runtime_(r) {} DensityFittingInfo(StateIn& si) { - basis1_ << SavableState::restore_state(si); - basis2_ << SavableState::restore_state(si); + params_ << SavableState::restore_state(si); runtime_ << SavableState::restore_state(si); } void save_data_state(StateOut& so) { - SavableState::save_state(basis1_.pointer(),so); - SavableState::save_state(basis2_.pointer(),so); + SavableState::save_state(params_.pointer(),so); SavableState::save_state(runtime_.pointer(),so); } - const Ref<GaussianBasisSet>& basis1() const { return basis1_; } - const Ref<GaussianBasisSet>& basis2() const { return basis2_; } + const Ref<DensityFittingParams>& params() const { return params_; } const Ref<DensityFittingRuntime>& runtime() const { return runtime_; } private: - Ref<GaussianBasisSet> basis1_; - Ref<GaussianBasisSet> basis2_; + Ref<DensityFittingParams> params_; Ref<DensityFittingRuntime> runtime_; static ClassDesc class_desc_; }; - } // end of namespace sc #endif // end of header guard Modified: trunk/mpqc/src/lib/chemistry/qc/mbptr12/f77sym.in =================================================================== --- trunk/mpqc/src/lib/chemistry/qc/mbptr12/f77sym.in 2010-06-04 20:52:34 UTC (rev 9443) +++ trunk/mpqc/src/lib/chemistry/qc/mbptr12/f77sym.in 2010-06-04 20:53:41 UTC (rev 9444) @@ -7,10 +7,15 @@ #define F77_DSPSVX #define F77_DSYEVD #define F77_DSPTRF +#define F77_DPPTRF #define F77_DSPTRI +#define F77_DPPTRI #define F77_DLANSP #define F77_DSPCON +#define F77_DPPCON #define F77_DLAMCH #define F77_DLACPY #define F77_DSPTRS +#define F77_DPPTRS #define F77_DSPRFS +#define F77_DPPRFS Modified: trunk/mpqc/src/lib/chemistry/qc/mbptr12/fockbuilder.cc =================================================================== --- trunk/mpqc/src/lib/chemistry/qc/mbptr12/fockbuilder.cc 2010-06-04 20:52:34 UTC (rev 9443) +++ trunk/mpqc/src/lib/chemistry/qc/mbptr12/fockbuilder.cc 2010-06-04 20:53:41 UTC (rev 9444) @@ -913,7 +913,7 @@ const Ref<AOSpaceRegistry> ao_registry = df_info->runtime()->moints_runtime()->factory()->ao_registry(); const Ref<OrbitalSpace>& braspace = ao_registry->value(brabs); const Ref<OrbitalSpace>& ketspace = ao_registry->value(ketbs); - const Ref<OrbitalSpace>& dfspace = ao_registry->value(df_info->basis1()); + const Ref<OrbitalSpace>& dfspace = ao_registry->value(df_info->params()->basis()); const Ref<OrbitalSpace>& obs_space = ao_registry->value(obs); const Ref<DensityFittingRuntime>& df_rtime = df_info->runtime(); @@ -1079,7 +1079,7 @@ const Ref<AOSpaceRegistry> ao_registry = df_info->runtime()->moints_runtime()->factory()->ao_registry(); const Ref<OrbitalSpace>& braspace = ao_registry->value(brabs); const Ref<OrbitalSpace>& ketspace = ao_registry->value(ketbs); - const Ref<OrbitalSpace>& dfspace = ao_registry->value(df_info->basis1()); + const Ref<OrbitalSpace>& dfspace = ao_registry->value(df_info->params()->basis()); const Ref<OrbitalSpace>& obs_space = ao_registry->value(obs); const Ref<DensityFittingRuntime>& df_rtime = df_info->runtime(); Modified: trunk/mpqc/src/lib/chemistry/qc/mbptr12/lapack.h =================================================================== --- trunk/mpqc/src/lib/chemistry/qc/mbptr12/lapack.h 2010-06-04 20:52:34 UTC (rev 9443) +++ trunk/mpqc/src/lib/chemistry/qc/mbptr12/lapack.h 2010-06-04 20:53:41 UTC (rev 9444) @@ -16,13 +16,20 @@ extern void F77_DSPTRF(const char* uplo, const int* n, double* AP, int* ipiv, int* info); +extern void F77_DPPTRF(const char* uplo, const int* n, double* AP, int* info); + extern void F77_DSPTRI(const char* uplo, const int* n, double* AP, const int* ipiv, double* work, int* info); +extern void F77_DPPTRI(const char* uplo, const int* n, double* AP, int* info); + extern double F77_DLANSP(const char* norm, const char* uplo, const int* n, const double* A_packed, double* work); extern void F77_DSPCON(const char* uplo, const int* n, const double* A_packed, const int* ipiv, const double* anorm, double* rcond, double* work, int* iwork, int* info); +extern void F77_DPPCON(const char* uplo, const int* n, const double* A_packed, + const double* anorm, double* rcond, double* work, int* iwork, int* info); + extern double F77_DLAMCH(const char* e); extern void F77_DLACPY(const char* uplo, const int* m, const int* n, const double* A, const int* lda, @@ -31,8 +38,16 @@ extern void F77_DSPTRS(const char* uplo, const int* n, const int* nrhs, const double* AFP, const int* ipiv, const double* X, const int* ldx, int* info); +extern void F77_DPPTRS(const char* uplo, const int* n, const int* nrhs, const double* AFP, + const double* X, const int* ldx, int* info); + extern void F77_DSPRFS(const char* uplo, const int* n, const int* nrhs, const double* A, const double* AF, const int* ipiv, const double* B, const int* ldb, const double* X, const int* ldx, double* ferr, double* berr, double* work, int* iwork, int* info); + +extern void F77_DPPRFS(const char* uplo, const int* n, const int* nrhs, const double* A, const double* AF, + const double* B, const int* ldb, const double* X, + const int* ldx, double* ferr, double* berr, double* work, int* iwork, int* info); + } Modified: trunk/mpqc/src/lib/chemistry/qc/mbptr12/moints_runtime.cc =================================================================== --- trunk/mpqc/src/lib/chemistry/qc/mbptr12/moints_runtime.cc 2010-06-04 20:52:34 UTC (rev 9443) +++ trunk/mpqc/src/lib/chemistry/qc/mbptr12/moints_runtime.cc 2010-06-04 20:53:41 UTC (rev 9444) @@ -43,17 +43,18 @@ create<this_type> ); MOIntsRuntime::MOIntsRuntime(const Ref<MOIntsTransformFactory>& factory, - const Ref<GaussianBasisSet>& dfbasis) : - factory_(factory), dfbasis_(dfbasis), + const Ref<DensityFittingParams>& dfparams) : + factory_(factory), dfparams_(dfparams), runtime_2c_(new TwoBodyTwoCenterMOIntsRuntime(factory_)), runtime_3c_(new TwoBodyThreeCenterMOIntsRuntime(factory_)), runtime_4c_(new TwoBodyFourCenterMOIntsRuntime(factory_)) { - if (dfbasis_.nonnull()) { + if (dfparams_.nonnull()) { runtime_df_ = new DensityFittingRuntime(new DensityFitting::MOIntsRuntime(factory_,runtime_2c_,runtime_3c_)); - typedef TwoBodyFourCenterMOIntsRuntime::Params DFParams; - const DFParams* params = new DFParams(dfbasis_, dfbasis_, runtime_df_); - runtime_4c_->params(params); + runtime_df_->set_solver(dfparams->solver()); + typedef TwoBodyFourCenterMOIntsRuntime::Params DFInfo; + const DFInfo* dfinfo = new DFInfo(dfparams_, runtime_df_); + runtime_4c_->params(dfinfo); } } @@ -62,7 +63,7 @@ MOIntsRuntime::MOIntsRuntime(StateIn& si) { factory_ << SavableState::restore_state(si); - dfbasis_ << SavableState::restore_state(si); + dfparams_ << SavableState::restore_state(si); runtime_2c_ << SavableState::restore_state(si); runtime_3c_ << SavableState::restore_state(si); runtime_4c_ << SavableState::restore_state(si); @@ -71,7 +72,7 @@ void MOIntsRuntime::save_data_state(StateOut& so) { SavableState::save_state(factory_.pointer(),so); - SavableState::save_state(dfbasis_.pointer(),so); + SavableState::save_state(dfparams_.pointer(),so); SavableState::save_state(runtime_2c_.pointer(),so); SavableState::save_state(runtime_3c_.pointer(),so); SavableState::save_state(runtime_4c_.pointer(),so); Modified: trunk/mpqc/src/lib/chemistry/qc/mbptr12/moints_runtime.h =================================================================== --- trunk/mpqc/src/lib/chemistry/qc/mbptr12/moints_runtime.h 2010-06-04 20:52:34 UTC (rev 9443) +++ trunk/mpqc/src/lib/chemistry/qc/mbptr12/moints_runtime.h 2010-06-04 20:53:41 UTC (rev 9444) @@ -46,7 +46,7 @@ /// give density fitting basis to enable density fitting, when possible MOIntsRuntime(const Ref<MOIntsTransformFactory>& factory, - const Ref<GaussianBasisSet>& dfbasis = 0); + const Ref<DensityFittingParams>& dfparams = 0); ~MOIntsRuntime(); MOIntsRuntime(StateIn&); void save_data_state(StateOut&); @@ -57,7 +57,7 @@ /// factory for creating AO->MO transforms const Ref<MOIntsTransformFactory>& factory() const { return factory_; } /// density fitting basis set. May be null. - const Ref<GaussianBasisSet>& dfbasis() const { return dfbasis_; } + const Ref<DensityFittingParams>& dfparams() const { return dfparams_; } /// runtime for density fitting matrices. Returns null if density fitting basis was not given. const Ref<DensityFittingRuntime>& runtime_df() const { return runtime_df_; } /// runtime for 2-center integrals @@ -71,7 +71,7 @@ static ClassDesc class_desc_; Ref<MOIntsTransformFactory> factory_; - Ref<GaussianBasisSet> dfbasis_; + Ref<DensityFittingParams> dfparams_; Ref<DensityFittingRuntime> runtime_df_; Ref<TwoBodyTwoCenterMOIntsRuntime> runtime_2c_; Ref<TwoBodyThreeCenterMOIntsRuntime> runtime_3c_; Modified: trunk/mpqc/src/lib/chemistry/qc/mbptr12/svd.cc =================================================================== --- trunk/mpqc/src/lib/chemistry/qc/mbptr12/svd.cc 2010-06-04 20:52:34 UTC (rev 9443) +++ trunk/mpqc/src/lib/chemistry/qc/mbptr12/svd.cc 2010-06-04 20:53:41 UTC (rev 9444) @@ -441,7 +441,8 @@ const int* ipiv, double* Xt, const double* Bt, - int ncolB) + int ncolB, + bool refine) { const int n = nA; const char uplo = 'U'; @@ -454,17 +455,124 @@ // solve the linear system F77_DSPTRS(&uplo, &n, &ncolB, AF, ipiv, Xt, &n, &info); - // Use iterative refinement to improve the computed solutions and - // compute error bounds and backward error estimates for them. - std::vector<double> ferr(ncolB); - std::vector<double> berr(ncolB); + if (refine) { + // Use iterative refinement to improve the computed solutions and + // compute error bounds and backward error estimates for them. + std::vector<double> ferr(ncolB); + std::vector<double> berr(ncolB); + std::vector<double> work(3 * n); + std::vector<int> iwork(n); + F77_DSPRFS(&uplo, &n, &ncolB, A, AF, ipiv, Bt, &n, Xt, &n, &(ferr[0]), + &(berr[0]), &(work[0]), &(iwork[0]), &info); + } + + } + + void lapack_cholesky_symmposdef(const RefSymmSCMatrix& A, + double* AF, + double condition_number_threshold) { + + const int n = A.dim().n(); + char uplo = 'U'; + int info; std::vector<double> work(3*n); std::vector<int> iwork(n); - F77_DSPRFS(&uplo, &n, &ncolB, A, AF, ipiv, Bt, &n, Xt, &n, &(ferr[0]), - &(berr[0]), &(work[0]), &(iwork[0]), &info); + // compute the infinity-norm of A + A.convert(AF); + char norm = 'I'; + const double anorm = F77_DLANSP(&norm, &uplo, &n, AF, &(work[0])); + + // factorize A = Ut.U + F77_DPPTRF(&uplo, &n, AF, &info); + if (info) { + if (info < 0) + throw std::runtime_error("lapack_cholesky_symmnondef() -- one of the arguments to F77_DPPTRF is invalid"); + if (info > 0) + throw std::runtime_error("lapack_cholesky_symmnondef() -- matrix A has factors which are negative"); + assert(false); // unreachable + } + + // estimate the condition number + double rcond; + F77_DPPCON(&uplo, &n, AF, &anorm, &rcond, &(work[0]), &(iwork[0]), &info); + if (info) { + if (info < 0) + throw std::runtime_error("lapack_cholesky_symmnondef() -- one of the arguments to F77_DPPCON is invalid"); + assert(false); // unreachable + } + // if the condition number is above the threshold or its inverse below the working precision, throw + if (condition_number_threshold != 0.0) { + if (condition_number_threshold < 0.0) + ExEnv::out0() << indent << "condition number estimate in lapack_cholesky_symmnondef() = " << 1.0/rcond << std::endl; + else if (1.0/rcond > condition_number_threshold) + ExEnv::err0() << indent << "WARNING: large condition number in lapack_cholesky_symmnondef(): threshold = " + << condition_number_threshold << " actual = " << 1.0/rcond << std::endl; + const char epsilon = 'E'; + if (rcond < F77_DLAMCH(&epsilon)) + ExEnv::err0() << indent << "WARNING: condition number in lapack_cholesky_symmnondef() exceeds the working precision" << std::endl; + } + } + void + lapack_linsolv_cholesky_symmposdef(const double* A, + int nA, + const double* AF, + double* Xt, + const double* Bt, + int ncolB, + bool refine) + { + const int n = nA; + const char uplo = 'U'; + int info; + + // copy B into X + const char full = 'F'; + F77_DLACPY(&full, &n, &ncolB, Bt, &n, Xt, &n, &info); + + // solve the linear system + F77_DPPTRS(&uplo, &n, &ncolB, AF, Xt, &n, &info); + + if (refine) { + // Use iterative refinement to improve the computed solutions and + // compute error bounds and backward error estimates for them. + std::vector<double> ferr(ncolB); + std::vector<double> berr(ncolB); + std::vector<double> work(3 * n); + std::vector<int> iwork(n); + F77_DPPRFS(&uplo, &n, &ncolB, A, AF, Bt, &n, Xt, &n, &(ferr[0]), + &(berr[0]), &(work[0]), &(iwork[0]), &info); + } + + } + + void + lapack_invert_symmposdef(RefSymmSCMatrix& A, double condition_number_threshold) + { + const int n = A.dim().n(); + const int ntri = n*(n+1)/2; + char uplo = 'U'; + std::vector<double> AF(ntri); + int info; + + // compute Cholesky factorization of A + lapack_cholesky_symmposdef(A, &(AF[0]), condition_number_threshold); + + // compute the inverse + F77_DPPTRI(&uplo, &n, &(AF[0]), &info); + if (info) { + if (info < 0) + throw std::runtime_error("lapack_invert_symmposdef() -- one of the arguments to F77_DPPTRI is invalid"); + if (info > 0) + throw std::runtime_error("lapack_invert_symmposdef() -- matrix A has factors which are exactly zero"); + assert(false); // unreachable + } + + A.assign( &(AF[0]) ); + } + }; }; Modified: trunk/mpqc/src/lib/chemistry/qc/mbptr12/svd.h =================================================================== --- trunk/mpqc/src/lib/chemistry/qc/mbptr12/svd.h 2010-06-04 20:52:34 UTC (rev 9443) +++ trunk/mpqc/src/lib/chemistry/qc/mbptr12/svd.h 2010-06-04 20:53:41 UTC (rev 9444) @@ -71,7 +71,7 @@ int ncolB); /** invert symmetric non-definite matrix using DSPTRF LAPACK routine - that implements using the Bunch-Kaufman diagonal pivoting method. + that implements the Bunch-Kaufman diagonal pivoting method. \param condition_number_threshold when the estimate of the condition number (see lapack function DSPCON) exceeds this threshold print a warning to ExEnv::err0(). No warning will be produced if the threshold is 0.0. @@ -80,9 +80,9 @@ void lapack_invert_symmnondef(RefSymmSCMatrix& A, double condition_number_threshold = 0.0); /** Compute factorization of a symmetric non-definite matrix using DSPTRF LAPACK routine - that implements using the Bunch-Kaufman diagonal pivoting method. + that implements the Bunch-Kaufman diagonal pivoting method. The resulting factorization (AF and ipiv) can be used to solve a linear system A X = B - using lapack_linsolv_symmnondef(); + using lapack_linsolv_dpf_symmnondef(); \param condition_number_threshold when the estimate of the condition number (see lapack function DSPCON) exceeds this threshold print a warning to ExEnv::err0(). No warning will be produced if the threshold is 0.0. @@ -96,13 +96,70 @@ void lapack_dpf_symmnondef(const RefSymmSCMatrix& A, double* AF, int* ipiv, double condition_number_threshold = 0.0); + /** invert symmetric positive-definite matrix using DPPTRF LAPACK routine + that implements the Cholesky method. + + \param condition_number_threshold when the estimate of the condition number (see lapack function DPPCON) + exceeds this threshold print a warning to ExEnv::err0(). No warning will be produced if the threshold is 0.0. + Negative threshold will prompt the estimate of the condition number of A to be printed out to ExEnv::out0(). + */ + void lapack_invert_symmposdef(RefSymmSCMatrix& A, double condition_number_threshold = 0.0); + + /** + * Solves a symmetric indefinite system of linear equations AX=B, + * where A is held in packed storage, using the factorization computed by lapack_dpf_symmnondef + * @param A + * @param nA + * @param AF + * @param ipiv + * @param Xt + * @param Bt + * @param ncolB + * @param refine set to false to avoid the iterative refinement of the solution that was obtained by substitution (using LAPACK dsptrs function) + */ void lapack_linsolv_dpf_symmnondef(const double* A, int nA, const double* AF, const int* ipiv, double* Xt, const double* Bt, - int ncolB); + int ncolB, + bool refine = true); + + /** Compute factorization of a symmetric positive-definite matrix using DPPTRF LAPACK routine + that implements the Cholesky method. + The resulting factorization (AF and ipiv) can be used to solve a linear system A X = B + using lapack_linsolv_cholesky_symmposdef(); + + \param condition_number_threshold when the estimate of the condition number (see lapack function DSPCON) + exceeds this threshold print a warning to ExEnv::err0(). No warning will be produced if the threshold is 0.0. + Negative threshold will prompt the estimate of the condition number of A to be printed out to ExEnv::out0(). + + \param AF array of size A.dim().n() * (A.dim().n() + 1)/2. On output contains the desired factorization. + + */ + void lapack_cholesky_symmposdef(const RefSymmSCMatrix& A, double* AF, + double condition_number_threshold = 0.0); + + /** + * Solves a symmetric indefinite system of linear equations AX=B, + * where A is held in packed storage, using the factorization computed by lapack_cholesky_symmnondef + * @param A + * @param nA + * @param AF + * @param Xt + * @param Bt + * @param ncolB + * @param refine set to false to avoid the iterative refinement of the solution that was obtained by substitution (using LAPACK dsptrs function) + */ + void lapack_linsolv_cholesky_symmposdef(const double* A, + int nA, + const double* AF, + double* Xt, + const double* Bt, + int ncolB, + bool refine = true); + } } Modified: trunk/mpqc/src/lib/chemistry/qc/mbptr12/transform_ixjy_df.cc =================================================================== --- trunk/mpqc/src/lib/chemistry/qc/mbptr12/transform_ixjy_df.cc 2010-06-04 20:52:34 UTC (rev 9443) +++ trunk/mpqc/src/lib/chemistry/qc/mbptr12/transform_ixjy_df.cc 2010-06-04 20:53:41 UTC (rev 9444) @@ -66,7 +66,7 @@ const Ref<OrbitalSpace>& space1, const Ref<OrbitalSpace>& space2, const Ref<OrbitalSpace>& space3, const Ref<OrbitalSpace>& space4) : TwoBodyMOIntsTransform(name,df_info->runtime()->moints_runtime()->factory(),tbintdescr,space1,space2,space3,space4), - runtime_(df_info->runtime()), dfbasis12_(df_info->basis1()), dfbasis34_(df_info->basis2()) + runtime_(df_info->runtime()), dfbasis12_(df_info->params()->basis()), dfbasis34_(df_info->params()->basis()) { // assuming for now that all densities will be fit in the same basis // TODO generalize to different fitting basis sets Modified: trunk/mpqc/src/lib/chemistry/qc/mbptr12/wfnworld.cc =================================================================== --- trunk/mpqc/src/lib/chemistry/qc/mbptr12/wfnworld.cc 2010-06-04 20:52:34 UTC (rev 9443) +++ trunk/mpqc/src/lib/chemistry/qc/mbptr12/wfnworld.cc 2010-06-04 20:53:41 UTC (rev 9444) @@ -32,6 +32,8 @@ // includes go here #include <chemistry/qc/mbptr12/wfnworld.h> #include <chemistry/qc/basis/petite.h> +#include <util/class/scexception.h> +#include <chemistry/qc/df/df_runtime.h> using namespace sc; @@ -54,7 +56,32 @@ keyval->describedclassvalue("df_basis").pointer(), "R12Technology::R12Technology\n" ); + if (bs_df_.nonnull()) { + df_kernel_ = keyval->stringvalue("df_kernel", KeyValValuestring("coulomb")); + if (df_kernel_ != "coulomb") + throw InputError("invalid value", + __FILE__, + __LINE__, + "df_kernel", + df_kernel_.c_str(), + class_desc()); + df_solver_ = keyval->stringvalue("df_solver", KeyValValuestring("bunchkaufman_refine")); + if (df_solver_ != "bunchkaufman" && + df_solver_ != "bunchkaufman_inv" && + df_solver_ != "bunchkaufman_refine" && + df_solver_ != "cholesky" && + df_solver_ != "cholesky_inv" && + df_solver_ != "cholesky_refine" + ) + throw InputError("invalid value", + __FILE__, + __LINE__, + "df_solver", + df_solver_.c_str(), + class_desc()); + } + // Determine how to store MO integrals std::string ints_str = keyval->stringvalue("store_ints",KeyValValuestring("posix")); if (ints_str == std::string("mem")) { @@ -170,7 +197,11 @@ aoidxreg->add(mu->basis(),mu); // create MO integrals runtime - moints_runtime_ = new MOIntsRuntime(tfactory_, bs_df_); + Ref<DensityFittingParams> dfparams; + if (bs_df_.nonnull()) { + dfparams = new DensityFittingParams(bs_df_, df_kernel_, df_solver_); + } + moints_runtime_ = new MOIntsRuntime(tfactory_, dfparams); // to boot Fock build runtime we need densities // make zero densities to start with @@ -224,8 +255,8 @@ o << incindent; if (bs_df_.nonnull()) { - o << indent << "Density-Fitting Basis Set (DFBS):" << std::endl; - o << incindent; bs_df_->print(o); o << decindent << std::endl; + Ref<DensityFittingParams> dfparams = new DensityFittingParams(bs_df_, df_kernel_, df_solver_); + dfparams->print(o); } std::string ints_str; Modified: trunk/mpqc/src/lib/chemistry/qc/mbptr12/wfnworld.h =================================================================== --- trunk/mpqc/src/lib/chemistry/qc/mbptr12/wfnworld.h 2010-06-04 20:52:34 UTC (rev 9443) +++ trunk/mpqc/src/lib/chemistry/qc/mbptr12/wfnworld.h 2010-06-04 20:53:41 UTC (rev 9444) @@ -88,6 +88,24 @@ <dt><tt>df_basis</tt><dd> This optional GaussianBasisSet object specifies the density-fitting basis. There is no default (no density fitting will be performed). + <dt><tt>df_kernel</tt><dd> If df_basis is specified, this keyword will be queried to determine the kernel + for density-fitting. The only supported value is <tt>coulomb</tt>. + + <dt><tt>df_solver</tt><dd> If df_basis is specified, this keyword will be queried to determine the method by which + density-fitting will be performed. Valid values are: + <dl> + + <dt><tt>cholesky_inv</tt><dd> Use Cholesky inverse. Only valid if <tt>df_kernel=coulomb</tt>. + <dt><tt>cholesky</tt><dd> Use Cholesky linear solver. Only valid if <tt>df_kernel=coulomb</tt>. + <dt><tt>cholesky_refine</tt><dd> Use Cholesky linear solver + iterative refinement. Only valid if <tt>df_kernel=coulomb</tt>. + + <dt><tt>bunchkaufman_inv</tt><dd> Use Bunch-Kaufman inverse. Valid for any value of <tt>df_kernel</tt>. + <dt><tt>bunchkaufman</tt><dd> Use Bunch-Kaufman linear solver. Valid for any value of <tt>df_kernel</tt>. + <dt><tt>bunchkaufman_refine</tt><dd> Use Bunch-Kaufman linear solver + iterative refinement. Valid for any value of <tt>df_kernel</tt>. + This is the default. + + </dl> + <dt><tt>memory</tt><dd> This keyword specifies the amount of memory to be used. The default is 32000000 bytes. <dt><tt>dynamic</tt><dd> This boolean keyword specifies whether dynamic load balancing @@ -155,6 +173,8 @@ /// whose World is it? Wavefunction* wfn_; Ref<GaussianBasisSet> bs_df_; //!< the density-fitting basis + std::string df_kernel_; //!< the density-fitting kernel + std::string df_solver_; //!< the density-fitting solver Ref<MessageGrp> msg_; Ref<MemoryGrp> mem_; Ref<ThreadGrp> thr_; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |