From a6ff5c204970ce777b712ac4ede0d3c407b26b5f Mon Sep 17 00:00:00 2001 From: Sergio Daniel Pineda Flores Date: Tue, 10 Sep 2019 11:17:20 -0600 Subject: [PATCH 01/41] fixed DiracDeterminants inability to read in more than the minimal number of orbitals --- src/Optimize/VariableSet.cpp | 2 +- src/QMCWaveFunctions/Fermion/DelayedUpdate.h | 6 +++--- src/QMCWaveFunctions/Fermion/DiracDeterminant.cpp | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Optimize/VariableSet.cpp b/src/Optimize/VariableSet.cpp index 6b51f4f35..49af4f305 100644 --- a/src/Optimize/VariableSet.cpp +++ b/src/Optimize/VariableSet.cpp @@ -274,7 +274,7 @@ void VariableSet::print(std::ostream& os, int leftPadSpaces, bool printHeader) << setw(max_value_len) << NameAndValue[i].second << " " << setw(max_type_len) << ParameterType[i].second << " " << setw(max_recompute_len) << Recompute[i].second << " "; - os << std::defaultfloat; +// os << std::defaultfloat; if (Index[i] < 0) os << setw(max_use_len) << "OFF" << std::endl; diff --git a/src/QMCWaveFunctions/Fermion/DelayedUpdate.h b/src/QMCWaveFunctions/Fermion/DelayedUpdate.h index 30c8367f3..bbb0cbb3a 100644 --- a/src/QMCWaveFunctions/Fermion/DelayedUpdate.h +++ b/src/QMCWaveFunctions/Fermion/DelayedUpdate.h @@ -106,7 +106,7 @@ public: } const T cone(1); const T czero(0); - const int norb = Ainv.rows(); + const int norb = Ainv.cols(); const int lda_Binv = Binv.cols(); // save Ainv[rowchanged] to invRow std::copy_n(Ainv[rowchanged], norb, invRow.data()); @@ -128,7 +128,7 @@ public: { const T cminusone(-1); const T czero(0); - const int norb = Ainv.rows(); + const int norb = Ainv.cols(); const int lda_Binv = Binv.cols(); std::copy_n(Ainv[rowchanged], norb, V[delay_count]); std::copy_n(psiV.data(), norb, U[delay_count]); @@ -165,7 +165,7 @@ public: // update the inverse matrix const T cone(1); const T czero(0); - const int norb = Ainv.rows(); + const int norb = Ainv.cols(); if (delay_count == 1) { // this is a special case invoking the Fahy's variant of Sherman-Morrison update. diff --git a/src/QMCWaveFunctions/Fermion/DiracDeterminant.cpp b/src/QMCWaveFunctions/Fermion/DiracDeterminant.cpp index 8479e73e3..5e2e321b7 100644 --- a/src/QMCWaveFunctions/Fermion/DiracDeterminant.cpp +++ b/src/QMCWaveFunctions/Fermion/DiracDeterminant.cpp @@ -44,7 +44,7 @@ void DiracDeterminant::set(int first, int nel, int delay) { FirstIndex = first; ndelay = delay; - resize(nel, nel); + resize(nel, Phi->OrbitalSetSize); } template From 52b564864541a4bc1e4664fa85c9653b5361dadb Mon Sep 17 00:00:00 2001 From: Sergio Daniel Pineda Flores Date: Tue, 10 Sep 2019 15:35:58 -0600 Subject: [PATCH 02/41] added RotationHelper class; Functions with MultiSlaterDetFast class --- src/QMCWaveFunctions/CMakeLists.txt | 1 + .../Fermion/RotationHelper.cpp | 877 ++++++++++++++++++ src/QMCWaveFunctions/Fermion/RotationHelper.h | 275 ++++++ .../Fermion/SlaterDetBuilder.cpp | 9 +- src/QMCWaveFunctions/SPOSet.h | 5 + src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp | 17 + src/QMCWaveFunctions/lcao/LCAOrbitalSet.h | 8 + 7 files changed, 1190 insertions(+), 2 deletions(-) create mode 100644 src/QMCWaveFunctions/Fermion/RotationHelper.cpp create mode 100644 src/QMCWaveFunctions/Fermion/RotationHelper.h diff --git a/src/QMCWaveFunctions/CMakeLists.txt b/src/QMCWaveFunctions/CMakeLists.txt index 9e5a667b6..3200a1a21 100644 --- a/src/QMCWaveFunctions/CMakeLists.txt +++ b/src/QMCWaveFunctions/CMakeLists.txt @@ -188,6 +188,7 @@ IF(OHMMS_DIM MATCHES 3) ENDIF(OHMMS_DIM MATCHES 3) SET(FERMION_SRCS ${FERMION_SRCS} + Fermion/RotationHelper.cpp Fermion/DiracDeterminant.cpp Fermion/SlaterDet.cpp Fermion/SlaterDetBuilder.cpp diff --git a/src/QMCWaveFunctions/Fermion/RotationHelper.cpp b/src/QMCWaveFunctions/Fermion/RotationHelper.cpp new file mode 100644 index 000000000..91e18aa22 --- /dev/null +++ b/src/QMCWaveFunctions/Fermion/RotationHelper.cpp @@ -0,0 +1,877 @@ +#include "QMCWaveFunctions/Fermion/RotationHelper.h" +#include +#include "Numerics/OhmmsBlas.h" + + +namespace qmcplusplus +{ + +RotationHelper::RotationHelper(SPOSet* spos) + : Phi(spos), + params_supplied(false), + IsCloned(false) +{ + app_log() << "SDP RotationHelper Constructor called. \n"; + Optimizable = spos->Optimizable; + spos->returnMemberVariables(C_original, C_sposet, params_supplied, params); + OrbitalSetSize = Phi->OrbitalSetSize; + app_log() << "SDP Current value of IsCloned is ..." << IsCloned << " \n"; +} + +RotationHelper::~RotationHelper() +{ + app_log() << "SDP RotationHelper Destructor called. \n"; +} + +void RotationHelper::buildOptVariables(const size_t& nel) +{ +// Phi->buildOptVariables(nel); +#if !defined(QMC_COMPLEX) + const size_t nmo = Phi->getOrbitalSetSize(); + + // create active rotation parameter indices + std::vector> created_m_act_rot_inds; + + // only core->active rotations created + for (int i = 0; i < nel; i++) + for (int j = nel; j < nmo; j++) + created_m_act_rot_inds.push_back(std::pair(i,j)); + + buildOptVariables(created_m_act_rot_inds); + +#endif +} + +void RotationHelper::buildOptVariables(const std::vector>& rotations) +{ +#if !defined(QMC_COMPLEX) + const size_t nmo = Phi->getOrbitalSetSize(); + const size_t nb = Phi->getBasisSetSize(); + + // create active rotations + m_act_rot_inds = rotations; + + // This will add the orbital rotation parameters to myVars + // and will also read in initial parameter values supplied in input file + int p, q; + int nparams_active = m_act_rot_inds.size(); + + app_log() << "nparams_active: " << nparams_active << " params2.size(): " << params.size() << std::endl; + if (params_supplied) + if (nparams_active != params.size()) + APP_ABORT("The number of supplied orbital rotation parameters does not match number prdouced by the slater " + "expansion. \n"); + + for (int i = 0; i < nparams_active; i++) + { + p = m_act_rot_inds[i].first; + q = m_act_rot_inds[i].second; + std::stringstream sstr; + sstr << Phi->objectName << "_orb_rot_" << (p < 10 ? "0" : "") << (p < 100 ? "0" : "") << (p < 1000 ? "0" : "") << p + << "_" << (q < 10 ? "0" : "") << (q < 100 ? "0" : "") << (q < 1000 ? "0" : "") << q; + + // If the user input parameteres, use those. Otherwise, initialize the parameters to zero + if (params_supplied) + { + myVars.insert(sstr.str(), params[i]); + } + else + { + myVars.insert(sstr.str(), 0.0); + } + } + + //Printing the parameters + if (true) + { + app_log() << std::string(16, ' ') << "Parameter name" << std::string(15, ' ') << "Value\n"; + myVars.print(app_log()); + } + + std::vector param(m_act_rot_inds.size()); + for (int i = 0; i < m_act_rot_inds.size(); i++) + { + param[i] = myVars[i]; + } + apply_rotation(param); + + if (params_supplied) + { + app_log() << "PRINTING MO COEFFICIENTS CREATED BY SUPPLIED PARAMS\n"; + for (int j = 0; j < nmo; j++) + { + for (int i = 0; i < nb; i++) + { + app_log() << " " << std::right << std::fixed << std::setprecision(16) << std::setw(23) << std::scientific + << *(C_sposet->data() + j * nb + i); + + if ((j * nb + i + 1) % 4 == 0) + { + app_log() << std::endl; + } + } + } + app_log() << "\n done printing molecular orbital coefficients\n"; + app_log() << std::endl; + } + + if (!Optimizable) + { + //THIS ALLOWS FOR ORBITAL PARAMETERS TO BE READ IN EVEN WHEN THOSE PARAMETERS ARE NOT BEING OPTIMIZED + //this assumes there are only CI coefficients ahead of the M_orb_coefficients + myVars.Index.erase(myVars.Index.begin(), myVars.Index.end()); + myVars.NameAndValue.erase(myVars.NameAndValue.begin(), myVars.NameAndValue.end()); + myVars.ParameterType.erase(myVars.ParameterType.begin(), myVars.ParameterType.end()); + myVars.Recompute.erase(myVars.Recompute.begin(), myVars.Recompute.end()); + } +#endif +} + +void RotationHelper::apply_rotation(const std::vector& param) +{ + assert(param.size() == m_act_rot_inds.size()); + + const size_t nmo = Phi->getOrbitalSetSize(); + const size_t nb = Phi->getBasisSetSize(); + ValueMatrix_t rot_mat(nmo, nmo); + rot_mat = ValueType(0); + + // read out the parameters that define the rotation into an antisymmetric matrix + for (int i = 0; i < m_act_rot_inds.size(); i++) + { + const int p = m_act_rot_inds[i].first; + const int q = m_act_rot_inds[i].second; + const RealType x = param[i]; + + rot_mat[q][p] = x; + rot_mat[p][q] = -x; + } + + exponentiate_antisym_matrix(rot_mat); + + BLAS::gemm('N', 'T', nb, nmo, nmo, RealType(1.0), C_original.data(), nb, rot_mat.data(), nmo, RealType(0.0), C_sposet->data(), + nb); +} + + +// compute exponential of a real, antisymmetric matrix by diagonalizing and exponentiating eigenvalues +void RotationHelper::exponentiate_antisym_matrix(ValueMatrix_t& mat) +{ + const int n = mat.rows(); + std::vector> mat_h(n * n, 0); + std::vector eval(n, 0); + std::vector> work(2 * n, 0); + std::vector rwork(3 * n, 0); + std::vector> mat_d(n * n, 0); + std::vector> mat_t(n * n, 0); + // exponentiating e^X = e^iY (Y hermitian) + // i(-iX) = X, so -iX is hermitian + // diagonalize -iX = UDU^T, exponentiate e^iD, and return U e^iD U^T + // construct hermitian analogue of mat by multiplying by -i + for (int i = 0; i < n; ++i) + { + for (int j = i; j < n; ++j) + { + mat_h[i + n * j] = std::complex(0, -1.0 * mat[j][i]); + mat_h[j + n * i] = std::complex(0, 1.0 * mat[j][i]); + } + } + // diagonalize the matrix + char JOBZ('V'); + char UPLO('U'); + int N(n); + int LDA(n); + int LWORK(2 * n); + int info = 0; + LAPACK::heev(JOBZ, UPLO, N, &mat_h.at(0), LDA, &eval.at(0), &work.at(0), LWORK, &rwork.at(0), info); + if (info != 0) + { + std::ostringstream msg; + msg << "heev failed with info = " << info << " in MultiSlaterDeterminantFast::exponentiate_antisym_matrix"; + app_log() << msg.str() << std::endl; + APP_ABORT(msg.str()); + } + // iterate through diagonal matrix, exponentiate terms + for (int i = 0; i < n; ++i) + { + for (int j = 0; j < n; ++j) + { + mat_d[i + j * n] = (i == j) ? std::exp(std::complex(0.0, eval[i])) : std::complex(0.0, 0.0); + } + } + // perform matrix multiplication + // assume row major + BLAS::gemm('N', 'C', n, n, n, std::complex(1.0, 0), &mat_d.at(0), n, &mat_h.at(0), n, + std::complex(0.0, 0.0), &mat_t.at(0), n); + BLAS::gemm('N', 'N', n, n, n, std::complex(1.0, 0), &mat_h.at(0), n, &mat_t.at(0), n, + std::complex(0.0, 0.0), &mat_d.at(0), n); + for (int i = 0; i < n; ++i) + for (int j = 0; j < n; ++j) + { + if (mat_d[i + n * j].imag() > 1e-12) + { + app_log() << "warning: large imaginary value in orbital rotation matrix: (i,j) = (" << i << "," << j + << "), im = " << mat_d[i + n * j].imag() << std::endl; + } + mat[j][i] = mat_d[i + n * j].real(); + } +} + + +void RotationHelper::evaluateDerivatives(ParticleSet& P, + const opt_variables_type& optvars, + std::vector& dlogpsi, + std::vector& dhpsioverpsi, + const int& FirstIndex, + const int& LastIndex) +{ +//perform derivative here... +// Phi->evaluateDerivatives(P, optvars, dlogpsi, dhpsioverpsi, FirstIndex, LastIndex); + const size_t nel = LastIndex - FirstIndex; + const size_t nmo = Phi->getOrbitalSetSize(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~PART1 + myG_temp.resize(nel); myG_J.resize(nel); + myL_temp.resize(nel); myL_J.resize(nel); + + myG_temp = 0; myG_J = 0; + myL_temp = 0; myL_J = 0; + + Bbar.resize(nel,nmo); + psiM_inv.resize(nel,nel); + psiM_all.resize(nel,nmo); + dpsiM_all.resize(nel,nmo); + d2psiM_all.resize(nel,nmo); + + Bbar = 0; + psiM_inv = 0; + psiM_all = 0; + dpsiM_all = 0; + d2psiM_all = 0; + + + Phi->evaluate_notranspose(P, FirstIndex, LastIndex, psiM_all, dpsiM_all, d2psiM_all); + + for (int i=0; i& dlogpsi, + std::vector& dhpsioverpsi, + const ValueType& psiCurrent, + const std::vector& Coeff, + const std::vector& C2node_up, + const std::vector& C2node_dn, + const ValueVector_t& detValues_up, + const ValueVector_t& detValues_dn, + const GradMatrix_t& grads_up, + const GradMatrix_t& grads_dn, + const ValueMatrix_t& lapls_up, + const ValueMatrix_t& lapls_dn, + const ValueMatrix_t& M_up, + const ValueMatrix_t& M_dn, + const ValueMatrix_t& Minv_up, + const ValueMatrix_t& Minv_dn, + const GradMatrix_t& B_grad, + const ValueMatrix_t& B_lapl, + const std::vector& detData_up, + const size_t N1, + const size_t N2, + const size_t NP1, + const size_t NP2, + const std::vector>& lookup_tbl) +{ + bool recalculate(false); + for (int k = 0; k < myVars.size(); ++k) + { + int kk = myVars.where(k); + if (kk < 0) + continue; + if (optvars.recompute(kk)) + recalculate = true; + } + if (recalculate) + { + ParticleSet::ParticleGradient_t myG_temp, myG_J; + ParticleSet::ParticleLaplacian_t myL_temp, myL_J; + const int NP = P.getTotalNum(); + myG_temp.resize(NP); + myG_temp = 0.0; + myL_temp.resize(NP); + myL_temp = 0.0; + myG_J.resize(NP); + myG_J = 0.0; + myL_J.resize(NP); + myL_J = 0.0; + const size_t nmo = Phi->getOrbitalSetSize(); + const size_t nb = Phi->getBasisSetSize(); + const size_t nel = P.last(0) - P.first(0); + + const RealType* restrict C_p = Coeff.data(); + for (int i = 0; i < Coeff.size(); i++) + { + const size_t upC = C2node_up[i]; + const size_t dnC = C2node_dn[i]; + const ValueType tmp1 = C_p[i] * detValues_dn[dnC]; + const ValueType tmp2 = C_p[i] * detValues_up[upC]; + for (size_t k = 0, j = N1; k < NP1; k++, j++) + { + myG_temp[j] += tmp1 * grads_up(upC, k); + myL_temp[j] += tmp1 * lapls_up(upC, k); + } + for (size_t k = 0, j = N2; k < NP2; k++, j++) + { + myG_temp[j] += tmp2 * grads_dn(dnC, k); + myL_temp[j] += tmp2 * lapls_dn(dnC, k); + } + } + + myG_temp *= (1 / psiCurrent); + myL_temp *= (1 / psiCurrent); + + // calculation of myG_J which will be used to represent \frac{\nabla\psi_{J}}{\psi_{J}} + // calculation of myL_J will be used to represent \frac{\nabla^2\psi_{J}}{\psi_{J}} + // IMPORTANT NOTE: The value of P.L holds \nabla^2 ln[\psi] but we need \frac{\nabla^2 \psi}{\psi} and this is what myL_J will hold + for (int iat = 0; iat < (myL_temp.size()); iat++) + { + myG_J[iat] = (P.G[iat] - myG_temp[iat]); + myL_J[iat] = (P.L[iat] + dot(P.G[iat], P.G[iat]) - myL_temp[iat]); + } + + + table_method_eval(dlogpsi, dhpsioverpsi, myL_J, myG_J, nel, nmo, psiCurrent, Coeff, C2node_up, C2node_dn, + detValues_up, detValues_dn, grads_up, grads_dn, lapls_up, lapls_dn, M_up, M_dn, Minv_up, Minv_dn, + B_grad, B_lapl, detData_up, N1, N2, NP1, NP2, lookup_tbl); + } +} + +void RotationHelper::table_method_eval(std::vector& dlogpsi, + std::vector& dhpsioverpsi, + const ParticleSet::ParticleLaplacian_t& myL_J, + const ParticleSet::ParticleGradient_t& myG_J, + const size_t nel, + const size_t nmo, + const ValueType& psiCurrent, + const std::vector& Coeff, + const std::vector& C2node_up, + const std::vector& C2node_dn, + const ValueVector_t& detValues_up, + const ValueVector_t& detValues_dn, + const GradMatrix_t& grads_up, + const GradMatrix_t& grads_dn, + const ValueMatrix_t& lapls_up, + const ValueMatrix_t& lapls_dn, + const ValueMatrix_t& M_up, + const ValueMatrix_t& M_dn, + const ValueMatrix_t& Minv_up, + const ValueMatrix_t& Minv_dn, + const GradMatrix_t& B_grad, + const ValueMatrix_t& B_lapl, + const std::vector& detData_up, + const size_t N1, + const size_t N2, + const size_t NP1, + const size_t NP2, + const std::vector>& lookup_tbl) +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +GUIDE TO THE MATICES BEING BUILT +---------------------------------------------- +The idea here is that there is a loop over all unique determinants. For each determiant the table method is employed to calculate the contributions to the parameter derivatives (dhpsioverpsi/dlogpsi) + + loop through unquie determinants + loop through parameters + evaluate contributaion to dlogpsi and dhpsioverpsi +\noindent + + BLAS GUIDE for matrix multiplication of [ alpha * A.B + beta * C = C ] + Matrix A is of dimensions a1,a2 and Matrix B is b1,b2 in which a2=b1 + The BLAS command is as follows... + + BLAS::gemm('N','N', b2, a1, a2 ,alpha, B, b2, A, a2, beta, C, b2); + +Below is a human readable format for the matrix multiplications performed below... + +This notation is inspired by http://dx.doi.org/10.1063/1.4948778 +\newline +\hfill\break +$ + A_{i,j}=\phi_j(r_{i}) \\ + T = A^{-1} \widetilde{A} \\ + B_{i,j} =\nabla^2 \phi_{j}(r_i) + \frac{\nabla_{i}J}{J} \cdot \nabla \phi_{j}(r_{i}) + \frac{\nabla^2_i J}{J} \phi_{j}(r_{i}) \\ + \hat{O_{I}} = \hat{O}D_{I} \\ + D_{I}=det(A_{I}) \newline + \psi_{MS} = \sum_{I=0} C_{I} D_{I\uparrow}D_{I\downarrow} \\ + \Psi_{total} = \psi_{J}\psi_{MS} \\ + \alpha_{I} = P^{T}_{I}TQ_{I} \\ + M_{I} = P^{T}_{I} \widetilde{M} Q_{I} = P^{T}_{I} (A^{-1}\widetilde{B} - A^{-1} B A^{-1}\widetilde{A} )Q_{I} \\ +$ +\newline +There are three constants I use in the expressions for dhpsioverpsi and dlogpsi +\newline +\hfill\break +$ + const0 = C_{0}*det(A_{0\downarrow})+\sum_{I=1} C_{I}*det(A_{I\downarrow})* det(\alpha_{I\uparrow}) \\ + const1 = C_{0}*\hat{O} det(A_{0\downarrow})+\sum_{I=1} C_{I}*\hat{O}det(A_{I\downarrow})* det(\alpha_{I\uparrow}) \\ + const2 = \sum_{I=1} C_{I}*det(A_{I\downarrow})* Tr[\alpha_{I}^{-1}M_{I}]*det(\alpha_{I}) \\ +$ +\newline +Below is a translation of the shorthand I use to represent matrices independent of ``excitation matrix". +\newline +\hfill\break +$ + Y_{1} = A^{-1}B \\ + Y_{2} = A^{-1}BA^{-1}\widetilde{A} \\ + Y_{3} = A^{-1}\widetilde{B} \\ + Y_{4} = \widetilde{M} = (A^{-1}\widetilde{B} - A^{-1} B A^{-1}\widetilde{A} )\\ +$ +\newline +Below is a translation of the shorthand I use to represent matrices dependent on ``excitation" with respect to the reference Matrix and sums of matrices. Above this line I have represented these excitation matrices with a subscript ``I" but from this point on The subscript will be omitted and it is clear that whenever a matrix depends on $P^{T}_I$ and $Q_{I}$ that this is an excitation matrix. The reference matrix is always $A_{0}$ and is always the Hartree Fock Matrix. +\newline +\hfill\break +$ + Y_{5} = TQ \\ + Y_{6} = (P^{T}TQ)^{-1} = \alpha_{I}^{-1}\\ + Y_{7} = \alpha_{I}^{-1} P^{T} \\ + Y_{11} = \widetilde{M}Q \\ + Y_{23} = P^{T}\widetilde{M}Q \\ + Y_{24} = \alpha_{I}^{-1}P^{T}\widetilde{M}Q \\ + Y_{25} = \alpha_{I}^{-1}P^{T}\widetilde{M}Q\alpha_{I}^{-1} \\ + Y_{26} = \alpha_{I}^{-1}P^{T}\widetilde{M}Q\alpha_{I}^{-1}P^{T}\\ +$ +\newline +So far you will notice that I have not included up or down arrows to specify what spin the matrices are of. This is because we are calculating the derivative of all up or all down spin orbital rotation parameters at a time. If we are finding the up spin derivatives then any term that is down spin will be constant. The following assumes that we are taking up-spin MO rotation parameter derivatives. Of course the down spin expression can be retrieved by swapping the up and down arrows. I have dubbed any expression with lowercase p prefix as a "precursor" to an expression actually used... +\newline +\hfill\break +$ + \dot{C_{I}} = C_{I}*det(A_{I\downarrow})\\ + \ddot{C_{I}} = C_{I}*\hat{O}det(A_{I\downarrow}) \\ + pK1 = \sum_{I=1} \dot{C_{I}} det(\alpha_{I}) Tr[\alpha_{I}^{-1}M_{I}] (Q\alpha_{I}^{-1}P^{T}) \\ + pK2 = \sum_{I=1} \dot{C_{I}} det(\alpha_{I}) (Q\alpha_{I}^{-1}P^{T}) \\ + pK3 = \sum_{I=1} \ddot{C_{I}} det(\alpha_{I}) (Q\alpha_{I}^{-1}P^{T}) \\ + pK4 = \sum_{I=1} \dot{C_{I}} det(A_{I}) (Q\alpha_{I}^{-1}P^{T}) \\ + pK5 = \sum_{I=1} \dot{C_{I}} det(\alpha_{I}) (Q\alpha_{I}^{-1} M_{I} \alpha_{I}^{-1}P^{T}) \\ +$ +\newline +Now these p matrices will be used to make various expressions via BLAS commands. +\newline +\hfill\break +$ + K1T = const0^{-1}*pK1.T =const0^{-1} \sum_{I=1} \dot{C_{I}} det(\alpha_{I}) Tr[\alpha_{I}^{-1}M_{I}] (Q\alpha_{I}^{-1}P^{T}T) \\ + TK1T = T.K1T = const0^{-1} \sum_{I=1} \dot{C_{I}} det(\alpha_{I}) Tr[\alpha_{I}^{-1}M_{I}] (TQ\alpha_{I}^{-1}P^{T}T)\\ \\ + K2AiB = const0^{-1} \sum_{I=1} \dot{C_{I}} det(\alpha_{I}) (Q\alpha_{I}^{-1}P^{T}A^{-1}\widetilde{B})\\ + TK2AiB = T.K2AiB = const0^{-1} \sum_{I=1} \dot{C_{I}} det(\alpha_{I}) (TQ\alpha_{I}^{-1}P^{T}A^{-1}\widetilde{B})\\ + K2XA = const0^{-1} \sum_{I=1} \dot{C_{I}} det(\alpha_{I}) (Q\alpha_{I}^{-1}P^{T}X\widetilde{A})\\ + TK2XA = T.K2XA = const0^{-1} \sum_{I=1} \dot{C_{I}} det(\alpha_{I}) (TQ\alpha_{I}^{-1}P^{T}X\widetilde{A})\\ \\ + K2T = \frac{const1}{const0^{2}} \sum_{I=1} \dot{C_{I}} det(\alpha_{I}) (Q\alpha_{I}^{-1}P^{T}T) \\ + TK2T = T.K2T =\frac{const1}{const0^{2}} \sum_{I=1} \dot{C_{I}} det(\alpha_{I}) (TQ\alpha_{I}^{-1}P^{T}T) \\ + MK2T = \frac{const0}{const1} Y_{4}.K2T= const0^{-1} \sum_{I=1} \dot{C_{I}} det(\alpha_{I}) (\widetilde{M}Q\alpha_{I}^{-1}P^{T}T)\\ \\ + K3T = const0^{-1} \sum_{I=1} \ddot{C_{I}} det(\alpha_{I}) (Q\alpha_{I}^{-1}P^{T}T) \\ + TK3T = T.K3T = const0^{-1} \sum_{I=1} \ddot{C_{I}} det(\alpha_{I}) (TQ\alpha_{I}^{-1}P^{T}T)\\ \\ + K4T = \sum_{I=1} \dot{C_{I}} det(A_{I}) (Q\alpha_{I}^{-1}P^{T}T) \\ + TK4T = T.K4T = \sum_{I=1} \dot{C_{I}} det(A_{I}) (TQ\alpha_{I}^{-1}P^{T}T) \\ \\ + K5T = const0^{-1} \sum_{I=1} \dot{C_{I}} det(\alpha_{I}) (Q\alpha_{I}^{-1} M_{I} \alpha_{I}^{-1}P^{T} T) \\ + TK5T = T.K5T = \sum_{I=1} \dot{C_{I}} det(\alpha_{I}) (T Q\alpha_{I}^{-1} M_{I} \alpha_{I}^{-1}P^{T} T) \\ +$ +\newline +Now with all these matrices and constants the expressions of dhpsioverpsi and dlogpsi can be created. + + + + +In addition I will be using a special generalization of the kinetic operator which I will denote as O. Our Slater matrix with the special O operator applied to each element will be called B_bar + +$ +``Bbar"_{i,j} =\nabla^2 \phi_{j}(r_i) + \frac{\nabla_{i}J}{J} \cdot \nabla \phi_{j}(r_{i}) + \frac{\nabla^2_i J}{J} \phi_{j}(r_{i}) +$ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ +{ + ValueMatrix_t Table; + ValueMatrix_t Bbar; + ValueMatrix_t Y1, Y2, Y3, Y4, Y5, Y6, Y7, Y11, Y23, Y24, Y25, Y26; + ValueMatrix_t pK1, K1T, TK1T, pK2, K2AiB, TK2AiB, K2XA, TK2XA, K2T, TK2T, MK2T, pK3, K3T, TK3T, pK4, K4T, TK4T, pK5, + K5T, TK5T; + + Table.resize(nel, nmo); + + Bbar.resize(nel, nmo); + + Y1.resize(nel, nel); + Y2.resize(nel, nmo); + Y3.resize(nel, nmo); + Y4.resize(nel, nmo); + + pK1.resize(nmo, nel); + K1T.resize(nmo, nmo); + TK1T.resize(nel, nmo); + + pK2.resize(nmo, nel); + K2AiB.resize(nmo, nmo); + TK2AiB.resize(nel, nmo); + K2XA.resize(nmo, nmo); + TK2XA.resize(nel, nmo); + K2T.resize(nmo, nmo); + TK2T.resize(nel, nmo); + MK2T.resize(nel, nmo); + + pK3.resize(nmo, nel); + K3T.resize(nmo, nmo); + TK3T.resize(nel, nmo); + + pK4.resize(nmo, nel); + K4T.resize(nmo, nmo); + TK4T.resize(nel, nmo); + + pK5.resize(nmo, nel); + K5T.resize(nmo, nmo); + TK5T.resize(nel, nmo); + + const int parameters_size(m_act_rot_inds.size()); + const int parameter_start_index(0); + + const size_t num_unique_up_dets(detValues_up.size()); + const size_t num_unique_dn_dets(detValues_dn.size()); + + const RealType* restrict cptr = Coeff.data(); + const size_t nc = Coeff.size(); + const size_t* restrict upC(C2node_up.data()); + const size_t* restrict dnC(C2node_dn.data()); + //B_grad holds the gardient operator + //B_lapl holds the laplacian operator + //B_bar will hold our special O operator + + const int offset1(N1); + const int offset2(N2); + const int NPother(NP2); + + RealType* T(Table.data()); + + //possibly replace wit BLAS calls + for (int i = 0; i < nel; i++) + for (int j = 0; j < nmo; j++) + Bbar(i, j) = B_lapl(i, j) + 2 * dot(myG_J[i + offset1], B_grad(i, j)) + myL_J[i + offset1] * M_up(i, j); + + const RealType* restrict B(Bbar.data()); + const RealType* restrict A(M_up.data()); + const RealType* restrict Ainv(Minv_up.data()); + //IMPORTANT NOTE: THE Dets[0]->psiMinv OBJECT DOES NOT HOLD THE INVERSE IF THE MULTIDIRACDETERMINANTBASE ONLY CONTAINES ONE ELECTRON. NEED A FIX FOR THIS CASE + // The T matrix should be calculated and stored for use + // T = A^{-1} \widetilde A + //REMINDER: that the ValueMatrix_t "matrix" stores data in a row major order and that BLAS commands assume column major + BLAS::gemm('N', 'N', nmo, nel, nel, RealType(1.0), A, nmo, Ainv, nel, RealType(0.0), T, nmo); + + BLAS::gemm('N', 'N', nel, nel, nel, RealType(1.0), B, nmo, Ainv, nel, RealType(0.0), Y1.data(), nel); + BLAS::gemm('N', 'N', nmo, nel, nel, RealType(1.0), T, nmo, Y1.data(), nel, RealType(0.0), Y2.data(), nmo); + BLAS::gemm('N', 'N', nmo, nel, nel, RealType(1.0), B, nmo, Ainv, nel, RealType(0.0), Y3.data(), nmo); + + //possibly replace with BLAS call + Y4 = Y3 - Y2; + + //Need to create the constants: (Oi, const0, const1, const2)to take advantage of minimal BLAS commands; + //Oi is the special operator applied to the slater matrix "A subscript i" from the total CI expansion + //\hat{O_{i}} = \hat{O}D_{i} with D_{i}=det(A_{i}) and Multi-Slater component defined as \sum_{i=0} C_{i} D_{i\uparrow}D_{i\downarrow} + std::vector Oi(num_unique_dn_dets); + + for (int index = 0; index < num_unique_dn_dets; index++) + for (int iat = 0; iat < NPother; iat++) + Oi[index] += lapls_dn(index, iat) + 2 * dot(grads_dn(index, iat), myG_J[offset2 + iat]) + + myL_J[offset2 + iat] * detValues_dn[index]; + + //const0 = C_{0}*det(A_{0\downarrow})+\sum_{i=1} C_{i}*det(A_{i\downarrow})* det(\alpha_{i\uparrow}) + //const1 = C_{0}*\hat{O} det(A_{0\downarrow})+\sum_{i=1} C_{i}*\hat{O}det(A_{i\downarrow})* det(\alpha_{i\uparrow}) + //const2 = \sum_{i=1} C_{i}*det(A_{i\downarrow})* Tr[\alpha_{i}^{-1}M_{i}]*det(\alpha_{i}) + RealType const0(0.0), const1(0.0), const2(0.0); + for (size_t i = 0; i < nc; ++i) + { + const RealType c = cptr[i]; + const size_t up = upC[i]; + const size_t down = dnC[i]; + + const0 += c * detValues_dn[down] * (detValues_up[up] / detValues_up[0]); + const1 += c * Oi[down] * (detValues_up[up] / detValues_up[0]); + } + + std::fill(pK1.begin(), pK1.end(), 0.0); + std::fill(pK2.begin(), pK2.end(), 0.0); + std::fill(pK3.begin(), pK3.end(), 0.0); + std::fill(pK4.begin(), pK4.end(), 0.0); + std::fill(pK5.begin(), pK5.end(), 0.0); + + //Now we are going to loop through all unique determinants. + //The few lines above are for the reference matrix contribution. + //Although I start the loop below from index 0, the loop only performs actions when the index is >= 1 + //the detData object contains all the information about the P^T and Q matrices (projection matrices) needed in the table method + const int* restrict data_it = detData_up.data(); + for (int index = 0, datum = 0; index < num_unique_up_dets; index++) + { + const int k = data_it[datum]; + + if (k == 0) + { + datum += 3 * k + 1; + } + + else + { + //Number of rows and cols of P^T + const int prows = k; + const int pcols = nel; + //Number of rows and cols of Q + const int qrows = nmo; + const int qcols = k; + + Y5.resize(nel, k); + Y6.resize(k, k); + + //Any matrix multiplication of P^T or Q is simply a projection + //Explicit matrix multiplication can be avoided; instead column or row copying can be done + //BlAS::copy(size of col/row being copied, + // Matrix pointer + place to begin copying, + // storage spacing (number of elements btw next row/col element), + // Pointer to resultant matrix + place to begin pasting, + // storage spacing of resultant matrix) + //For example the next 4 lines is the matrix multiplication of T*Q = Y5 + std::fill(Y5.begin(), Y5.end(), 0.0); + for (int i = 0; i < k; i++) + { + BLAS::copy(nel, T + data_it[datum + 1 + k + i], nmo, Y5.data() + i, k); + } + + std::fill(Y6.begin(), Y6.end(), 0.0); + for (int i = 0; i < k; i++) + { + BLAS::copy(k, Y5.data() + (data_it[datum + 1 + i]) * k, 1, (Y6.data() + i * k), 1); + } + + + Vector WS; + Vector Piv; + WS.resize(k); + Piv.resize(k); + RealType PhaseR = 0.0; + InvertWithLog(Y6.data(), k, k, WS.data(), Piv.data(), PhaseR); + + Y11.resize(nel, k); + Y23.resize(k, k); + Y24.resize(k, k); + Y25.resize(k, k); + Y26.resize(k, nel); + + std::fill(Y11.begin(), Y11.end(), 0.0); + for (int i = 0; i < k; i++) + { + BLAS::copy(nel, Y4.data() + (data_it[datum + 1 + k + i]), nmo, Y11.data() + i, k); + } + + std::fill(Y23.begin(), Y23.end(), 0.0); + for (int i = 0; i < k; i++) + { + BLAS::copy(k, Y11.data() + (data_it[datum + 1 + i]) * k, 1, (Y23.data() + i * k), 1); + } + + BLAS::gemm('N', 'N', k, k, k, RealType(1.0), Y23.data(), k, Y6.data(), k, RealType(0.0), Y24.data(), k); + BLAS::gemm('N', 'N', k, k, k, RealType(1.0), Y6.data(), k, Y24.data(), k, RealType(0.0), Y25.data(), k); + + + Y26.resize(k, nel); + + std::fill(Y26.begin(), Y26.end(), 0.0); + for (int i = 0; i < k; i++) + { + BLAS::copy(k, Y25.data() + i, k, Y26.data() + (data_it[datum + 1 + i]), nel); + } + + + Y7.resize(k, nel); + + std::fill(Y7.begin(), Y7.end(), 0.0); + for (int i = 0; i < k; i++) + { + BLAS::copy(k, Y6.data() + i, k, Y7.data() + (data_it[datum + 1 + i]), nel); + } + + // c_Tr_AlphaI_MI is a constant contributing to constant const2 + // c_Tr_AlphaI_MI = Tr[\alpha_{I}^{-1}(P^{T}\widetilde{M} Q)] + RealType c_Tr_AlphaI_MI = 0.0; + for (int i = 0; i < k; i++) + { + c_Tr_AlphaI_MI += Y24(i, i); + } + + for (int p = 0; p < lookup_tbl[index].size(); p++) + { + //el_p is the element position that contains information about the CI coefficient, and det up/dn values associated with the current unique determinant + const int el_p(lookup_tbl[index][p]); + const RealType c = cptr[el_p]; + const size_t up = upC[el_p]; + const size_t down = dnC[el_p]; + + const RealType alpha_1(c * detValues_dn[down] * detValues_up[up] / detValues_up[0] * c_Tr_AlphaI_MI); + const RealType alpha_2(c * detValues_dn[down] * detValues_up[up] / detValues_up[0]); + const RealType alpha_3(c * Oi[down] * detValues_up[up] / detValues_up[0]); + const RealType alpha_4(c * detValues_dn[down] * detValues_up[up] * (1 / psiCurrent)); + + const2 += alpha_1; + + for (int i = 0; i < k; i++) + { + BLAS::axpy(nel, alpha_1, Y7.data() + i * nel, 1, pK1.data() + (data_it[datum + 1 + k + i]) * nel, 1); + BLAS::axpy(nel, alpha_2, Y7.data() + i * nel, 1, pK2.data() + (data_it[datum + 1 + k + i]) * nel, 1); + BLAS::axpy(nel, alpha_3, Y7.data() + i * nel, 1, pK3.data() + (data_it[datum + 1 + k + i]) * nel, 1); + BLAS::axpy(nel, alpha_4, Y7.data() + i * nel, 1, pK4.data() + (data_it[datum + 1 + k + i]) * nel, 1); + BLAS::axpy(nel, alpha_2, Y26.data() + i * nel, 1, pK5.data() + (data_it[datum + 1 + k + i]) * nel, 1); + } + } + datum += 3 * k + 1; + } + } + + + BLAS::gemm('N', 'N', nmo, nmo, nel, 1.0 / const0, T, nmo, pK1.data(), nel, RealType(0.0), K1T.data(), nmo); + BLAS::gemm('N', 'N', nmo, nel, nmo, RealType(1.0), K1T.data(), nmo, T, nmo, RealType(0.0), TK1T.data(), nmo); + + BLAS::gemm('N', 'N', nmo, nmo, nel, 1.0 / const0, Y3.data(), nmo, pK2.data(), nel, RealType(0.0), K2AiB.data(), nmo); + BLAS::gemm('N', 'N', nmo, nel, nmo, RealType(1.0), K2AiB.data(), nmo, T, nmo, RealType(0.0), TK2AiB.data(), nmo); + BLAS::gemm('N', 'N', nmo, nmo, nel, 1.0 / const0, Y2.data(), nmo, pK2.data(), nel, RealType(0.0), K2XA.data(), nmo); + BLAS::gemm('N', 'N', nmo, nel, nmo, RealType(1.0), K2XA.data(), nmo, T, nmo, RealType(0.0), TK2XA.data(), nmo); + + BLAS::gemm('N', 'N', nmo, nmo, nel, const1 / (const0 * const0), T, nmo, pK2.data(), nel, RealType(0.0), K2T.data(), + nmo); + BLAS::gemm('N', 'N', nmo, nel, nmo, RealType(1.0), K2T.data(), nmo, T, nmo, RealType(0.0), TK2T.data(), nmo); + BLAS::gemm('N', 'N', nmo, nel, nmo, const0 / const1, K2T.data(), nmo, Y4.data(), nmo, RealType(0.0), MK2T.data(), + nmo); + + BLAS::gemm('N', 'N', nmo, nmo, nel, 1.0 / const0, T, nmo, pK3.data(), nel, RealType(0.0), K3T.data(), nmo); + BLAS::gemm('N', 'N', nmo, nel, nmo, RealType(1.0), K3T.data(), nmo, T, nmo, RealType(0.0), TK3T.data(), nmo); + + BLAS::gemm('N', 'N', nmo, nmo, nel, RealType(1.0), T, nmo, pK4.data(), nel, RealType(0.0), K4T.data(), nmo); + BLAS::gemm('N', 'N', nmo, nel, nmo, RealType(1.0), K4T.data(), nmo, T, nmo, RealType(0.0), TK4T.data(), nmo); + + BLAS::gemm('N', 'N', nmo, nmo, nel, 1.0 / const0, T, nmo, pK5.data(), nel, RealType(0.0), K5T.data(), nmo); + BLAS::gemm('N', 'N', nmo, nel, nmo, RealType(1.0), K5T.data(), nmo, T, nmo, RealType(0.0), TK5T.data(), nmo); + + + for (int mu = 0, k = parameter_start_index; k < (parameter_start_index + parameters_size); k++, mu++) + { + int kk = myVars.where(k); + const int i(m_act_rot_inds[mu].first), j(m_act_rot_inds[mu].second); + if (i <= nel - 1 && j > nel - 1) + { + dlogpsi[kk] += ValueType( detValues_up[0] * (Table(i, j)) * const0 * (1 / psiCurrent) + (K4T(i, j) - K4T(j, i) - TK4T(i, j)) ); + + dhpsioverpsi[kk] += ValueType( -0.5 * Y4(i, j) - + 0.5 * + (-K5T(i, j) + K5T(j, i) + TK5T(i, j) + K2AiB(i, j) - K2AiB(j, i) - TK2AiB(i, j) - K2XA(i, j) + + K2XA(j, i) + TK2XA(i, j) - MK2T(i, j) + K1T(i, j) - K1T(j, i) - TK1T(i, j) - + const2 / const1 * K2T(i, j) + const2 / const1 * K2T(j, i) + const2 / const1 * TK2T(i, j) + K3T(i, j) - + K3T(j, i) - TK3T(i, j) - K2T(i, j) + K2T(j, i) + TK2T(i, j)) ); + } + else if (i <= nel - 1 && j <= nel - 1) + { + dlogpsi[kk] += ValueType( detValues_up[0] * (Table(i, j) - Table(j, i)) * const0 * (1 / psiCurrent) + + (K4T(i, j) - TK4T(i, j) - K4T(j, i) + TK4T(j, i)) ); + + dhpsioverpsi[kk] += ValueType( -0.5 * (Y4(i, j) - Y4(j, i)) - + 0.5 * + (-K5T(i, j) + K5T(j, i) + TK5T(i, j) - TK5T(j, i) + K2AiB(i, j) - K2AiB(j, i) - TK2AiB(i, j) + + TK2AiB(j, i) - K2XA(i, j) + K2XA(j, i) + TK2XA(i, j) - TK2XA(j, i) - MK2T(i, j) + MK2T(j, i) + + K1T(i, j) - K1T(j, i) - TK1T(i, j) + TK1T(j, i) - const2 / const1 * K2T(i, j) + + const2 / const1 * K2T(j, i) + const2 / const1 * TK2T(i, j) - const2 / const1 * TK2T(j, i) + K3T(i, j) - + K3T(j, i) - TK3T(i, j) + TK3T(j, i) - K2T(i, j) + K2T(j, i) + TK2T(i, j) - TK2T(j, i)) ); + } + else + { + dlogpsi[kk] += ValueType( (K4T(i, j) - K4T(j, i)) ); + + dhpsioverpsi[kk] += ValueType( -0.5 * + (-K5T(i, j) + K5T(j, i) + K2AiB(i, j) - K2AiB(j, i) - K2XA(i, j) + K2XA(j, i) + + + K1T(i, j) - K1T(j, i) - const2 / const1 * K2T(i, j) + const2 / const1 * K2T(j, i) + K3T(i, j) - K3T(j, i) - + K2T(i, j) + K2T(j, i)) ); + } + } +} + + + +SPOSet* RotationHelper::makeClone() const +{ + RotationHelper* myclone = new RotationHelper(Phi->makeClone()); + + myclone->IsCloned = true; + myclone->params = this->params; + myclone->params_supplied = this->params_supplied; + myclone->m_act_rot_inds = this->m_act_rot_inds; + myclone->Optimizable = this->Optimizable; + myclone->C_original = this->C_original; + myclone->C_sposet = this->C_sposet; + myclone->myVars = this->myVars; + return myclone; +} + + + + +} // namespace qmcplusplus diff --git a/src/QMCWaveFunctions/Fermion/RotationHelper.h b/src/QMCWaveFunctions/Fermion/RotationHelper.h new file mode 100644 index 000000000..4dd0c6ce8 --- /dev/null +++ b/src/QMCWaveFunctions/Fermion/RotationHelper.h @@ -0,0 +1,275 @@ +#ifndef ROTATION_HELPER_H +#define ROTATION_HELPER_H + +#include "QMCWaveFunctions/SPOSet.h" +#include +#include "QMCWaveFunctions/BasisSetBase.h" + +#include +#include "Numerics/DeterminantOperators.h" + + + +namespace qmcplusplus +{ + +class RotationHelper : public SPOSet +{ +public: + //constructor + RotationHelper(SPOSet* spos); + //destructor + ~RotationHelper(); + + //Copy of Original Coefficient Matrix + ValueMatrix_t C_original; + //access to Coefficient Matrix of SPOSet + std::shared_ptr C_sposet; + + //vector that contains active orbital rotation parameter indices + std::vector> m_act_rot_inds; + + //function to perform orbital rotations + void apply_rotation(const std::vector& param); + + //helper function to apply_rotation + void exponentiate_antisym_matrix(ValueMatrix_t& mat); + + //A particualr SPOSet used for Orbitals + SPOSet* Phi; + + /// true if SPO parameters (orbital rotation parameters) have been supplied by input + bool params_supplied; + /// list of supplied orbital rotation parameters + std::vector params; + + bool IsCloned; + + SPOSet* makeClone() const; + + // myG_temp (myL_temp) is the Gradient (Laplacian) value of of the Determinant part of the wfn + // myG_J is the Gradient of the all other parts of the wavefunction (typically just the Jastrow). + // It represents \frac{\nabla\psi_{J}}{\psi_{J}} + // myL_J will be used to represent \frac{\nabla^2\psi_{J}}{\psi_{J}} . The Laplacian portion + // IMPORTANT NOTE: The value of P.L holds \nabla^2 ln[\psi] but we need \frac{\nabla^2 \psi}{\psi} and this is what myL_J will hold + ParticleSet::ParticleGradient_t myG_temp, myG_J; + ParticleSet::ParticleLaplacian_t myL_temp, myL_J; + + ValueMatrix_t Bbar; + ValueMatrix_t psiM_inv; + ValueMatrix_t psiM_all; + GradMatrix_t dpsiM_all; + ValueMatrix_t d2psiM_all; + + + // Single Slater creation + void buildOptVariables(const size_t& nel); + // For the MSD case rotations must be created in MultiSlaterFast class + void buildOptVariables(const std::vector>& rotations); + + + void evaluateDerivatives(ParticleSet& P, + const opt_variables_type& optvars, + std::vector& dlogpsi, + std::vector& dhpsioverpsi, + const int& FirstIndex, + const int& LastIndex); + + void evaluateDerivatives(ParticleSet& P, + const opt_variables_type& optvars, + std::vector& dlogpsi, + std::vector& dhpsioverpsi, + const ValueType& psiCurrent, + const std::vector& Coeff, + const std::vector& C2node_up, + const std::vector& C2node_dn, + const ValueVector_t& detValues_up, + const ValueVector_t& detValues_dn, + const GradMatrix_t& grads_up, + const GradMatrix_t& grads_dn, + const ValueMatrix_t& lapls_up, + const ValueMatrix_t& lapls_dn, + const ValueMatrix_t& M_up, + const ValueMatrix_t& M_dn, + const ValueMatrix_t& Minv_up, + const ValueMatrix_t& Minv_dn, + const GradMatrix_t& B_grad, + const ValueMatrix_t& B_lapl, + const std::vector& detData_up, + const size_t N1, + const size_t N2, + const size_t NP1, + const size_t NP2, + const std::vector>& lookup_tbl); + +//helper function to evaluatederivative; evaluate orbital rotation parameter derivative using table method + void table_method_eval(std::vector& dlogpsi, + std::vector& dhpsioverpsi, + const ParticleSet::ParticleLaplacian_t& myL_J, + const ParticleSet::ParticleGradient_t& myG_J, + const size_t nel, + const size_t nmo, + const ValueType& psiCurrent, + const std::vector& Coeff, + const std::vector& C2node_up, + const std::vector& C2node_dn, + const ValueVector_t& detValues_up, + const ValueVector_t& detValues_dn, + const GradMatrix_t& grads_up, + const GradMatrix_t& grads_dn, + const ValueMatrix_t& lapls_up, + const ValueMatrix_t& lapls_dn, + const ValueMatrix_t& M_up, + const ValueMatrix_t& M_dn, + const ValueMatrix_t& Minv_up, + const ValueMatrix_t& Minv_dn, + const GradMatrix_t& B_grad, + const ValueMatrix_t& B_lapl, + const std::vector& detData_up, + const size_t N1, + const size_t N2, + const size_t NP1, + const size_t NP2, + const std::vector>& lookup_tbl); + + void checkInVariables(opt_variables_type& active) + { +// Phi->checkInVariables(active); + if (Optimizable && !IsCloned) + { + if (myVars.size()) + active.insertFrom(myVars); + else{ + Optimizable = false; + } + } + } + + void checkOutVariables(const opt_variables_type& active) + { +// Phi->checkOutVariables(active); + if (Optimizable && !IsCloned) + { + myVars.getIndex(active); + } + } + + + ///reset + void resetParameters(const opt_variables_type& active) + { +// Phi->resetParameters(active); +#if !defined(QMC_COMPLEX) + if (Optimizable) + { + std::vector param(m_act_rot_inds.size()); + for (int i = 0; i < m_act_rot_inds.size(); i++) + { + int loc = myVars.where(i); + param[i] = myVars[i] = active[loc]; + } + apply_rotation(param); + } +#endif + } + //********************************************************************************* + //the following functions simply call Phi's corresponding functions + void resetTargetParticleSet(ParticleSet& P) + {Phi->resetTargetParticleSet(P); } + + void setOrbitalSetSize(int norbs) + {Phi->setOrbitalSetSize(norbs); } + +// void setBasisSet(basis_type* bs); + + int getBasisSetSize() + {return Phi->getBasisSetSize(); } + +// bool setIdentity(bool useIdentity) +// {return Phi->setIdentity(useIdentity); } + + void checkObject() + {Phi->checkObject(); } + + void evaluate(const ParticleSet& P, int iat, ValueVector_t& psi) + {Phi->evaluate(P, iat, psi); } + + + void evaluate(const ParticleSet& P, + int iat, + ValueVector_t& psi, + GradVector_t& dpsi, + ValueVector_t& d2psi) + {Phi->evaluate(P, iat, psi, dpsi, d2psi); } + + void evaluateDetRatios(const VirtualParticleSet& VP, + ValueVector_t& psi, + const ValueVector_t& psiinv, + std::vector& ratios) + {Phi->evaluateDetRatios(VP, psi, psiinv, ratios); } + + void evaluate(const ParticleSet& P, int iat, ValueVector_t& psi, GradVector_t& dpsi, HessVector_t& grad_grad_psi) + {Phi->evaluate(P, iat, psi, dpsi, grad_grad_psi); } + + + void evaluate(const ParticleSet& P, + int iat, + ValueVector_t& psi, + GradVector_t& dpsi, + HessVector_t& grad_grad_psi, + GGGVector_t& grad_grad_grad_psi) + {Phi->evaluate(P, iat, psi, dpsi, grad_grad_psi, grad_grad_grad_psi); } + + + void evaluate_notranspose(const ParticleSet& P, + int first, + int last, + ValueMatrix_t& logdet, + GradMatrix_t& dlogdet, + ValueMatrix_t& d2logdet) + {Phi->evaluate_notranspose(P, first, last, logdet, dlogdet, d2logdet); } + + void evaluate_notranspose(const ParticleSet& P, + int first, + int last, + ValueMatrix_t& logdet, + GradMatrix_t& dlogdet, + HessMatrix_t& grad_grad_logdet) + {Phi->evaluate_notranspose(P, first, last, logdet, dlogdet, grad_grad_logdet); } + + void evaluate_notranspose(const ParticleSet& P, + int first, + int last, + ValueMatrix_t& logdet, + GradMatrix_t& dlogdet, + HessMatrix_t& grad_grad_logdet, + GGGMatrix_t& grad_grad_grad_logdet) + {Phi->evaluate_notranspose(P, first, last, logdet, dlogdet, grad_grad_logdet, grad_grad_grad_logdet); } + + void evaluateGradSource(const ParticleSet& P, + int first, + int last, + const ParticleSet& source, + int iat_src, + GradMatrix_t& grad_phi) + {Phi->evaluateGradSource(P, first, last, source, iat_src, grad_phi); } + + void evaluateGradSource(const ParticleSet& P, + int first, + int last, + const ParticleSet& source, + int iat_src, + GradMatrix_t& grad_phi, + HessMatrix_t& grad_grad_phi, + GradMatrix_t& grad_lapl_phi) + {Phi->evaluateGradSource(P, first, last, source, iat_src, grad_phi, grad_grad_phi, grad_lapl_phi); } + +// void evaluateThirdDeriv(const ParticleSet& P, int first, int last, GGGMatrix_t& grad_grad_grad_logdet) +// {Phi->evaluateThridDeriv(P, first, last, grad_grad_grad_logdet); } + + +}; + +} //namespace qmcplusplus + +#endif diff --git a/src/QMCWaveFunctions/Fermion/SlaterDetBuilder.cpp b/src/QMCWaveFunctions/Fermion/SlaterDetBuilder.cpp index fc6b2b179..72f98d53c 100644 --- a/src/QMCWaveFunctions/Fermion/SlaterDetBuilder.cpp +++ b/src/QMCWaveFunctions/Fermion/SlaterDetBuilder.cpp @@ -22,6 +22,7 @@ #include "Utilities/ProgressReportEngine.h" #include "OhmmsData/AttributeSet.h" +#include "QMCWaveFunctions/Fermion/RotationHelper.h" #include "QMCWaveFunctions/Fermion/MultiSlaterDeterminant.h" #include "QMCWaveFunctions/Fermion/MultiSlaterDeterminantFast.h" #if !defined(QMC_COMPLEX) && !defined(ENABLE_SOA) @@ -301,11 +302,15 @@ bool SlaterDetBuilder::put(xmlNodePtr cur) app_log() << "Using Bryan's algorithm for MultiSlaterDeterminant expansion. \n"; MultiDiracDeterminant* up_det = 0; MultiDiracDeterminant* dn_det = 0; + RotationHelper *rot_helper_up_det, *rot_helper_dn_det; app_log() << "Creating base determinant (up) for MSD expansion. \n"; - up_det = new MultiDiracDeterminant((SPOSetPtr)spomap.find(spo_alpha)->second, 0); + rot_helper_up_det = new RotationHelper((SPOSetPtr)spomap.find(spo_alpha)->second); + up_det = new MultiDiracDeterminant(rot_helper_up_det, 0); app_log() << "Creating base determinant (down) for MSD expansion. \n"; - dn_det = new MultiDiracDeterminant((SPOSetPtr)spomap.find(spo_beta)->second, 1); + rot_helper_dn_det = new RotationHelper((SPOSetPtr)spomap.find(spo_beta)->second); + dn_det = new MultiDiracDeterminant(rot_helper_dn_det, 1); multislaterdetfast_0 = new MultiSlaterDeterminantFast(targetPtcl, up_det, dn_det); + success = createMSDFast(multislaterdetfast_0, cur); } else diff --git a/src/QMCWaveFunctions/SPOSet.h b/src/QMCWaveFunctions/SPOSet.h index f6490cf19..6c369cdea 100644 --- a/src/QMCWaveFunctions/SPOSet.h +++ b/src/QMCWaveFunctions/SPOSet.h @@ -150,6 +150,11 @@ public: /// create optimizable orbital rotation parameters virtual void buildOptVariables(const std::vector>& rotations) {} + virtual void returnMemberVariables(ValueMatrix_t& C_original, + std::shared_ptr& C_sposet, + bool& params_supplied, + std::vector& params) + { APP_ABORT("SPOSet does not have a way to pass member variables to Rotation Helper class\n"); } /// reset parameters to the values from optimizer virtual void resetParameters(const opt_variables_type& optVariables) = 0; diff --git a/src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp b/src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp index 9a844d34b..b155a81e7 100644 --- a/src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp +++ b/src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp @@ -608,6 +608,23 @@ void LCAOrbitalSet::evaluateThirdDeriv(const ParticleSet& P, int first, int last { APP_ABORT("LCAOrbitalSet::evaluateThirdDeriv(P,istart,istop,ggg_logdet) not implemented\n"); } +void LCAOrbitalSet::returnMemberVariables(ValueMatrix_t& C_original, + std::shared_ptr& C_sposet, + bool& params_supplied, + std::vector& params) +{ +//std::cout << "SDP returnMemberVariables called\n"; +// if(!IsCloned) + if(true) + { +// std::cout << " SDP if !IsCloned conditional found \n"; + C_original = *C; + C_sposet = C; + params = this->params; + params_supplied = this->params_supplied; +// IsCloned = this->IsCloned; + } +} void LCAOrbitalSet::buildOptVariables(const std::vector>& rotations) { diff --git a/src/QMCWaveFunctions/lcao/LCAOrbitalSet.h b/src/QMCWaveFunctions/lcao/LCAOrbitalSet.h index db198675e..a07c4ca2b 100644 --- a/src/QMCWaveFunctions/lcao/LCAOrbitalSet.h +++ b/src/QMCWaveFunctions/lcao/LCAOrbitalSet.h @@ -79,6 +79,14 @@ public: SPOSet* makeClone() const; + //RotationHelper uses this function that make a hard copy of this SPOset's C matrix as + // C_original, and then sets a shared pointer to the C matrix as C_sposet. + // The values of the read in parameters, and IsCloned status is also returned. + void returnMemberVariables(ValueMatrix_t& C_original, + std::shared_ptr& C_sposet, + bool& params_supplied, + std::vector& params); + /// create optimizable orbital rotation parameters void buildOptVariables(const std::vector>& rotations); From 872cad18aeabc83bccd530019b61ee6949f215d8 Mon Sep 17 00:00:00 2001 From: Sergio Daniel Pineda Flores Date: Wed, 11 Sep 2019 10:09:49 -0600 Subject: [PATCH 03/41] RotationHelper working for both MSDFast and DiracDeterminant classes; Both with and without threading as well --- src/QMCWaveFunctions/Fermion/DiracDeterminant.cpp | 9 ++++++++- .../Fermion/MultiDiracDeterminant.cpp | 1 + src/QMCWaveFunctions/Fermion/RotationHelper.cpp | 12 +++--------- src/QMCWaveFunctions/Fermion/RotationHelper.h | 7 +------ src/QMCWaveFunctions/Fermion/SlaterDetBuilder.cpp | 10 +++++++++- src/QMCWaveFunctions/SPOSet.h | 9 +++++++++ src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp | 7 ------- 7 files changed, 31 insertions(+), 24 deletions(-) diff --git a/src/QMCWaveFunctions/Fermion/DiracDeterminant.cpp b/src/QMCWaveFunctions/Fermion/DiracDeterminant.cpp index 5e2e321b7..6f40b35dc 100644 --- a/src/QMCWaveFunctions/Fermion/DiracDeterminant.cpp +++ b/src/QMCWaveFunctions/Fermion/DiracDeterminant.cpp @@ -44,7 +44,11 @@ void DiracDeterminant::set(int first, int nel, int delay) { FirstIndex = first; ndelay = delay; + resize(nel, Phi->OrbitalSetSize); + + if(Optimizable) + Phi->buildOptVariables(nel); } template @@ -556,7 +560,10 @@ void DiracDeterminant::evaluateDerivatives(ParticleSet& P, const opt_variables_type& active, std::vector& dlogpsi, std::vector& dhpsioverpsi) -{} +{ + + Phi->evaluateDerivatives(P, active, dlogpsi, dhpsioverpsi, FirstIndex, LastIndex); +} template DiracDeterminant* DiracDeterminant::makeCopy(SPOSetPtr spo) const diff --git a/src/QMCWaveFunctions/Fermion/MultiDiracDeterminant.cpp b/src/QMCWaveFunctions/Fermion/MultiDiracDeterminant.cpp index 31a465296..62817e0cf 100644 --- a/src/QMCWaveFunctions/Fermion/MultiDiracDeterminant.cpp +++ b/src/QMCWaveFunctions/Fermion/MultiDiracDeterminant.cpp @@ -355,6 +355,7 @@ MultiDiracDeterminant::MultiDiracDeterminant(const MultiDiracDeterminant& s) detData = s.detData; uniquePairs = s.uniquePairs; DetSigns = s.DetSigns; + Optimizable = s.Optimizable; registerTimers(); Phi = (s.Phi->makeClone()); diff --git a/src/QMCWaveFunctions/Fermion/RotationHelper.cpp b/src/QMCWaveFunctions/Fermion/RotationHelper.cpp index 91e18aa22..facc0dfff 100644 --- a/src/QMCWaveFunctions/Fermion/RotationHelper.cpp +++ b/src/QMCWaveFunctions/Fermion/RotationHelper.cpp @@ -11,17 +11,13 @@ RotationHelper::RotationHelper(SPOSet* spos) params_supplied(false), IsCloned(false) { - app_log() << "SDP RotationHelper Constructor called. \n"; Optimizable = spos->Optimizable; - spos->returnMemberVariables(C_original, C_sposet, params_supplied, params); OrbitalSetSize = Phi->OrbitalSetSize; - app_log() << "SDP Current value of IsCloned is ..." << IsCloned << " \n"; + spos->returnMemberVariables(C_original, C_sposet, params_supplied, params); } RotationHelper::~RotationHelper() -{ - app_log() << "SDP RotationHelper Destructor called. \n"; -} +{} void RotationHelper::buildOptVariables(const size_t& nel) { @@ -225,8 +221,6 @@ void RotationHelper::evaluateDerivatives(ParticleSet& P, const int& FirstIndex, const int& LastIndex) { -//perform derivative here... -// Phi->evaluateDerivatives(P, optvars, dlogpsi, dhpsioverpsi, FirstIndex, LastIndex); const size_t nel = LastIndex - FirstIndex; const size_t nmo = Phi->getOrbitalSetSize(); @@ -312,7 +306,7 @@ void RotationHelper::evaluateDerivatives(ParticleSet& P, int kk = myVars.where(i); const int p = m_act_rot_inds.at(i).first; const int q = m_act_rot_inds.at(i).second; - dlogpsi.at(kk) = T(p,q);; + dlogpsi.at(kk) = T(p,q); dhpsioverpsi.at(kk) = ValueType(-0.5) * Y4(p,q); } } diff --git a/src/QMCWaveFunctions/Fermion/RotationHelper.h b/src/QMCWaveFunctions/Fermion/RotationHelper.h index 4dd0c6ce8..1417efb0c 100644 --- a/src/QMCWaveFunctions/Fermion/RotationHelper.h +++ b/src/QMCWaveFunctions/Fermion/RotationHelper.h @@ -134,7 +134,6 @@ public: void checkInVariables(opt_variables_type& active) { -// Phi->checkInVariables(active); if (Optimizable && !IsCloned) { if (myVars.size()) @@ -147,7 +146,6 @@ public: void checkOutVariables(const opt_variables_type& active) { -// Phi->checkOutVariables(active); if (Optimizable && !IsCloned) { myVars.getIndex(active); @@ -158,9 +156,7 @@ public: ///reset void resetParameters(const opt_variables_type& active) { -// Phi->resetParameters(active); -#if !defined(QMC_COMPLEX) - if (Optimizable) + if (Optimizable && !IsCloned) { std::vector param(m_act_rot_inds.size()); for (int i = 0; i < m_act_rot_inds.size(); i++) @@ -170,7 +166,6 @@ public: } apply_rotation(param); } -#endif } //********************************************************************************* //the following functions simply call Phi's corresponding functions diff --git a/src/QMCWaveFunctions/Fermion/SlaterDetBuilder.cpp b/src/QMCWaveFunctions/Fermion/SlaterDetBuilder.cpp index 72f98d53c..3134a5859 100644 --- a/src/QMCWaveFunctions/Fermion/SlaterDetBuilder.cpp +++ b/src/QMCWaveFunctions/Fermion/SlaterDetBuilder.cpp @@ -239,7 +239,15 @@ bool SlaterDetBuilder::put(xmlNodePtr cur) std::map::iterator iter; for (iter = spomap.begin(); iter != spomap.end(); iter++) { - slaterdet_0->add(iter->second, iter->first); + // This line is added here so that the spo get its object name before a RotationHelper object is instantiated + // this is necessary because the constructor of rotationhelper will ask to build the variables and uses + // spo->objectname inorder to name the variables. + iter->second->objectName = iter->first; + + RotationHelper* rot_helper; + rot_helper = new RotationHelper(iter->second); + slaterdet_0->add(rot_helper, iter->first); + } size_t spin_group = 0; xmlNodePtr tcur = cur->children; diff --git a/src/QMCWaveFunctions/SPOSet.h b/src/QMCWaveFunctions/SPOSet.h index 6c369cdea..d725896e7 100644 --- a/src/QMCWaveFunctions/SPOSet.h +++ b/src/QMCWaveFunctions/SPOSet.h @@ -148,6 +148,9 @@ public: #endif /// create optimizable orbital rotation parameters + // Single Slater creation + virtual void buildOptVariables(const size_t& nel) {} + // For the MSD case rotations must be created in MultiSlaterFast class virtual void buildOptVariables(const std::vector>& rotations) {} virtual void returnMemberVariables(ValueMatrix_t& C_original, @@ -162,6 +165,12 @@ public: virtual void checkInVariables(opt_variables_type& active) {} virtual void checkOutVariables(const opt_variables_type& active) {} + virtual void evaluateDerivatives(ParticleSet& P, + const opt_variables_type& optvars, + std::vector& dlogpsi, + std::vector& dhpsioverpsi, + const int& FirstIndex, + const int& LastIndex) {} /** Evaluate the derivative of the optimized orbitals with respect to the parameters * this is used only for MSD, to be refined for better serving both single and multi SD */ diff --git a/src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp b/src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp index b155a81e7..091a91f9c 100644 --- a/src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp +++ b/src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp @@ -613,17 +613,10 @@ void LCAOrbitalSet::returnMemberVariables(ValueMatrix_t& C_original, bool& params_supplied, std::vector& params) { -//std::cout << "SDP returnMemberVariables called\n"; -// if(!IsCloned) - if(true) - { -// std::cout << " SDP if !IsCloned conditional found \n"; C_original = *C; C_sposet = C; params = this->params; params_supplied = this->params_supplied; -// IsCloned = this->IsCloned; - } } void LCAOrbitalSet::buildOptVariables(const std::vector>& rotations) From 9103d04c2f662f1ab1b46a17153d8936a75a351d Mon Sep 17 00:00:00 2001 From: Sergio Daniel Pineda Flores Date: Wed, 11 Sep 2019 10:40:03 -0600 Subject: [PATCH 04/41] edited wfn files for the test called short-H4-orb-opt --- tests/molecules/H4_ae/H4.wfs_2.xml | 62 +++++++++++--------------- tests/molecules/H4_ae/H4.wfs_3.xml | 70 +++++++++++++++--------------- 2 files changed, 60 insertions(+), 72 deletions(-) diff --git a/tests/molecules/H4_ae/H4.wfs_2.xml b/tests/molecules/H4_ae/H4.wfs_2.xml index b4af7cca1..88f6b44f1 100644 --- a/tests/molecules/H4_ae/H4.wfs_2.xml +++ b/tests/molecules/H4_ae/H4.wfs_2.xml @@ -1,9 +1,9 @@ - - + + - + @@ -12,41 +12,33 @@ - - - - - 0.2 0.0 0.0 0.0 - + + + + + 5.04668000000000e-01 4.50114000000000e-01 3.58423000000000e-01 1.26449000000000e-01 + -2.40452000000000e-01 -3.20413000000000e-01 4.66777000000000e-01 7.03549000000000e-01 + 8.80080000000000e-02 -5.04842000000000e-01 8.07522000000000e-01 -7.19301000000000e-01 + 1.03323500000000e+00 -8.77213000000000e-01 -3.90492000000000e-01 2.12318000000000e-01 + + +0.2 0.0 0.0 0.0 + - - - - 0.2 0.0 0.0 0.0 - + + + + 5.04668000000000e-01 4.50114000000000e-01 3.58423000000000e-01 1.26449000000000e-01 + -2.40452000000000e-01 -3.20413000000000e-01 4.66777000000000e-01 7.03549000000000e-01 + 8.80080000000000e-02 -5.04842000000000e-01 8.07522000000000e-01 -7.19301000000000e-01 + 1.03323500000000e+00 -8.77213000000000e-01 -3.90492000000000e-01 2.12318000000000e-01 + + +0.2 0.0 0.0 0.0 + - - - - - 5.04668000000000e-01 4.50114000000000e-01 3.58423000000000e-01 1.26449000000000e-01 - -2.40452000000000e-01 -3.20413000000000e-01 4.66777000000000e-01 7.03549000000000e-01 - 8.80080000000000e-02 -5.04842000000000e-01 8.07522000000000e-01 -7.19301000000000e-01 - 1.03323500000000e+00 -8.77213000000000e-01 -3.90492000000000e-01 2.12318000000000e-01 - - - - - - 5.04668000000000e-01 4.50114000000000e-01 3.58423000000000e-01 1.26449000000000e-01 - -2.40452000000000e-01 -3.20413000000000e-01 4.66777000000000e-01 7.03549000000000e-01 - 8.80080000000000e-02 -5.04842000000000e-01 8.07522000000000e-01 -7.19301000000000e-01 - 1.03323500000000e+00 -8.77213000000000e-01 -3.90492000000000e-01 2.12318000000000e-01 - - - 0.04661440939 0.0555644703 0.1286335481 0.1077457768 0.0811381484 0.0626555805 0.0436904683 0.02811397453 0.01572772511 0.006258753264 @@ -55,12 +47,10 @@ 0.4465508582 0.3603308616 0.2893897103 0.2269436006 0.1717850082 0.1250275368 0.08538908372 0.05318480503 0.02806504868 0.01035981902 - 0.0167926566 0.1405038909 0.1611311956 0.1198446618 0.06764720157 0.03602453588 0.02460661286 0.01952889643 0.01300432967 0.005621933949 - diff --git a/tests/molecules/H4_ae/H4.wfs_3.xml b/tests/molecules/H4_ae/H4.wfs_3.xml index 19c6f2713..255202b4b 100644 --- a/tests/molecules/H4_ae/H4.wfs_3.xml +++ b/tests/molecules/H4_ae/H4.wfs_3.xml @@ -1,9 +1,9 @@ - - + + - + @@ -12,41 +12,42 @@ - - - - - -6.2352e-02 - 1.5072e-02 - 8.3825e-02 - -2.4339e-02 - - - - - - -6.2352e-02 - 1.5072e-02 - 8.3825e-02 - -2.4339e-02 - - - - - - - + + + + 5.04668000000000e-01 4.50114000000000e-01 3.58423000000000e-01 1.26449000000000e-01 -2.40452000000000e-01 -3.20413000000000e-01 4.66777000000000e-01 7.03549000000000e-01 8.80080000000000e-02 -5.04842000000000e-01 8.07522000000000e-01 -7.19301000000000e-01 1.03323500000000e+00 -8.77213000000000e-01 -3.90492000000000e-01 2.12318000000000e-01 - + + -6.2352e-02 + 1.5072e-02 + 8.3825e-02 + -2.4339e-02 + + + + + + 5.04668000000000e-01 4.50114000000000e-01 3.58423000000000e-01 1.26449000000000e-01 + -2.40452000000000e-01 -3.20413000000000e-01 4.66777000000000e-01 7.03549000000000e-01 + 8.80080000000000e-02 -5.04842000000000e-01 8.07522000000000e-01 -7.19301000000000e-01 + 1.03323500000000e+00 -8.77213000000000e-01 -3.90492000000000e-01 2.12318000000000e-01 + + + -6.2352e-02 + 1.5072e-02 + 8.3825e-02 + -2.4339e-02 + + + - - + 2.2381e-02 1.5167e-01 1.0912e-01 @@ -60,7 +61,7 @@ - + 4.7842e-01 3.9434e-01 3.2027e-01 @@ -74,10 +75,9 @@ - - + 2.5151e-02 1.4825e-01 1.6955e-01 @@ -88,9 +88,7 @@ 2.3827e-02 1.5289e-02 6.2995e-03 - - + - From db6bb590de932fabf3d8789f814040f098cb47d1 Mon Sep 17 00:00:00 2001 From: Ye Luo Date: Tue, 1 Oct 2019 14:32:11 -0500 Subject: [PATCH 05/41] Fix compilation. --- src/QMCWaveFunctions/Fermion/DiracDeterminant.cpp | 2 +- src/QMCWaveFunctions/Fermion/RotationHelper.cpp | 7 +++---- src/QMCWaveFunctions/Fermion/RotationHelper.h | 5 ----- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/src/QMCWaveFunctions/Fermion/DiracDeterminant.cpp b/src/QMCWaveFunctions/Fermion/DiracDeterminant.cpp index 6f40b35dc..9142057be 100644 --- a/src/QMCWaveFunctions/Fermion/DiracDeterminant.cpp +++ b/src/QMCWaveFunctions/Fermion/DiracDeterminant.cpp @@ -45,7 +45,7 @@ void DiracDeterminant::set(int first, int nel, int delay) FirstIndex = first; ndelay = delay; - resize(nel, Phi->OrbitalSetSize); + resize(nel, Phi->getOrbitalSetSize()); if(Optimizable) Phi->buildOptVariables(nel); diff --git a/src/QMCWaveFunctions/Fermion/RotationHelper.cpp b/src/QMCWaveFunctions/Fermion/RotationHelper.cpp index facc0dfff..4fe1d4e82 100644 --- a/src/QMCWaveFunctions/Fermion/RotationHelper.cpp +++ b/src/QMCWaveFunctions/Fermion/RotationHelper.cpp @@ -7,12 +7,12 @@ namespace qmcplusplus { RotationHelper::RotationHelper(SPOSet* spos) - : Phi(spos), + : SPOSet(false, true), + Phi(spos), params_supplied(false), IsCloned(false) { - Optimizable = spos->Optimizable; - OrbitalSetSize = Phi->OrbitalSetSize; + OrbitalSetSize = Phi->getOrbitalSetSize(); spos->returnMemberVariables(C_original, C_sposet, params_supplied, params); } @@ -858,7 +858,6 @@ SPOSet* RotationHelper::makeClone() const myclone->params = this->params; myclone->params_supplied = this->params_supplied; myclone->m_act_rot_inds = this->m_act_rot_inds; - myclone->Optimizable = this->Optimizable; myclone->C_original = this->C_original; myclone->C_sposet = this->C_sposet; myclone->myVars = this->myVars; diff --git a/src/QMCWaveFunctions/Fermion/RotationHelper.h b/src/QMCWaveFunctions/Fermion/RotationHelper.h index 1417efb0c..442b6bbda 100644 --- a/src/QMCWaveFunctions/Fermion/RotationHelper.h +++ b/src/QMCWaveFunctions/Fermion/RotationHelper.h @@ -135,13 +135,8 @@ public: void checkInVariables(opt_variables_type& active) { if (Optimizable && !IsCloned) - { if (myVars.size()) active.insertFrom(myVars); - else{ - Optimizable = false; - } - } } void checkOutVariables(const opt_variables_type& active) From 8b114cf44e6f60947a0c75c2ea56e023c9f02b62 Mon Sep 17 00:00:00 2001 From: Ye Luo Date: Tue, 8 Oct 2019 12:32:28 -0500 Subject: [PATCH 06/41] Change how RotationHelper is connected. --- src/QMCWaveFunctions/CMakeLists.txt | 2 +- .../Fermion/SlaterDetBuilder.cpp | 21 +++---------------- .../{Fermion => }/RotationHelper.cpp | 3 ++- .../{Fermion => }/RotationHelper.h | 0 src/QMCWaveFunctions/SPOSetBuilderFactory.cpp | 10 ++++++++- 5 files changed, 15 insertions(+), 21 deletions(-) rename src/QMCWaveFunctions/{Fermion => }/RotationHelper.cpp (99%) rename src/QMCWaveFunctions/{Fermion => }/RotationHelper.h (100%) diff --git a/src/QMCWaveFunctions/CMakeLists.txt b/src/QMCWaveFunctions/CMakeLists.txt index de27bc62d..18354f4ce 100644 --- a/src/QMCWaveFunctions/CMakeLists.txt +++ b/src/QMCWaveFunctions/CMakeLists.txt @@ -28,6 +28,7 @@ SET(WFBASE_SRCS SPOSetInfo.cpp SPOSetInputInfo.cpp SPOSet.cpp + RotationHelper.cpp CompositeSPOSet.cpp HarmonicOscillator/SHOSet.cpp HarmonicOscillator/SHOSetBuilder.cpp @@ -183,7 +184,6 @@ IF(OHMMS_DIM MATCHES 3) ENDIF(OHMMS_DIM MATCHES 3) SET(FERMION_SRCS ${FERMION_SRCS} - Fermion/RotationHelper.cpp Fermion/DiracDeterminant.cpp Fermion/SlaterDet.cpp Fermion/SlaterDetBuilder.cpp diff --git a/src/QMCWaveFunctions/Fermion/SlaterDetBuilder.cpp b/src/QMCWaveFunctions/Fermion/SlaterDetBuilder.cpp index 570a9b57e..ee2fa6ab8 100644 --- a/src/QMCWaveFunctions/Fermion/SlaterDetBuilder.cpp +++ b/src/QMCWaveFunctions/Fermion/SlaterDetBuilder.cpp @@ -22,7 +22,6 @@ #include "Utilities/ProgressReportEngine.h" #include "OhmmsData/AttributeSet.h" -#include "QMCWaveFunctions/Fermion/RotationHelper.h" #include "QMCWaveFunctions/Fermion/MultiSlaterDeterminant.h" #include "QMCWaveFunctions/Fermion/MultiSlaterDeterminantFast.h" #if !defined(QMC_COMPLEX) && !defined(ENABLE_SOA) @@ -229,17 +228,7 @@ WaveFunctionComponent* SlaterDetBuilder::buildComponent(xmlNodePtr cur) // Copy any entries in sposetmap into slaterdet_0 std::map::iterator iter; for (iter = spomap.begin(); iter != spomap.end(); iter++) - { - // This line is added here so that the spo get its object name before a RotationHelper object is instantiated - // this is necessary because the constructor of rotationhelper will ask to build the variables and uses - // spo->objectname inorder to name the variables. - iter->second->objectName = iter->first; - - RotationHelper* rot_helper; - rot_helper = new RotationHelper(iter->second); - slaterdet_0->add(rot_helper, iter->first); - - } + slaterdet_0->add(iter->second, iter->first); size_t spin_group = 0; xmlNodePtr tcur = cur->children; while (tcur != NULL) @@ -301,15 +290,11 @@ WaveFunctionComponent* SlaterDetBuilder::buildComponent(xmlNodePtr cur) app_log() << "Using Bryan's algorithm for MultiSlaterDeterminant expansion. \n"; MultiDiracDeterminant* up_det = 0; MultiDiracDeterminant* dn_det = 0; - RotationHelper *rot_helper_up_det, *rot_helper_dn_det; app_log() << "Creating base determinant (up) for MSD expansion. \n"; - rot_helper_up_det = new RotationHelper((SPOSetPtr)spomap.find(spo_alpha)->second); - up_det = new MultiDiracDeterminant(rot_helper_up_det, 0); + up_det = new MultiDiracDeterminant((SPOSetPtr)spomap.find(spo_alpha)->second, 0); app_log() << "Creating base determinant (down) for MSD expansion. \n"; - rot_helper_dn_det = new RotationHelper((SPOSetPtr)spomap.find(spo_beta)->second); - dn_det = new MultiDiracDeterminant(rot_helper_dn_det, 1); + dn_det = new MultiDiracDeterminant((SPOSetPtr)spomap.find(spo_beta)->second, 1); multislaterdetfast_0 = new MultiSlaterDeterminantFast(targetPtcl, up_det, dn_det); - success = createMSDFast(multislaterdetfast_0, cur); } else diff --git a/src/QMCWaveFunctions/Fermion/RotationHelper.cpp b/src/QMCWaveFunctions/RotationHelper.cpp similarity index 99% rename from src/QMCWaveFunctions/Fermion/RotationHelper.cpp rename to src/QMCWaveFunctions/RotationHelper.cpp index 4fe1d4e82..86dc673c3 100644 --- a/src/QMCWaveFunctions/Fermion/RotationHelper.cpp +++ b/src/QMCWaveFunctions/RotationHelper.cpp @@ -1,4 +1,4 @@ -#include "QMCWaveFunctions/Fermion/RotationHelper.h" +#include "QMCWaveFunctions/RotationHelper.h" #include #include "Numerics/OhmmsBlas.h" @@ -12,6 +12,7 @@ RotationHelper::RotationHelper(SPOSet* spos) params_supplied(false), IsCloned(false) { + className = "RotationHelper"; OrbitalSetSize = Phi->getOrbitalSetSize(); spos->returnMemberVariables(C_original, C_sposet, params_supplied, params); } diff --git a/src/QMCWaveFunctions/Fermion/RotationHelper.h b/src/QMCWaveFunctions/RotationHelper.h similarity index 100% rename from src/QMCWaveFunctions/Fermion/RotationHelper.h rename to src/QMCWaveFunctions/RotationHelper.h diff --git a/src/QMCWaveFunctions/SPOSetBuilderFactory.cpp b/src/QMCWaveFunctions/SPOSetBuilderFactory.cpp index 0ed506bf2..84e0254b0 100644 --- a/src/QMCWaveFunctions/SPOSetBuilderFactory.cpp +++ b/src/QMCWaveFunctions/SPOSetBuilderFactory.cpp @@ -35,6 +35,7 @@ #include "QMCWaveFunctions/EinsplineSetBuilder.h" #endif #endif +#include "QMCWaveFunctions/RotationHelper.h" #include "QMCWaveFunctions/CompositeSPOSet.h" #include "Utilities/ProgressReportEngine.h" #include "Utilities/IteratorUtility.h" @@ -246,10 +247,12 @@ SPOSet* SPOSetBuilderFactory::createSPOSet(xmlNodePtr cur) std::string bname(""); std::string sname(""); std::string type(""); + std::string rotation("no"); OhmmsAttributeSet aAttrib; aAttrib.add(bname, "basisset"); aAttrib.add(sname, "name"); aAttrib.add(type, "type"); + aAttrib.add(rotation, "optimize"); //aAttrib.put(rcur); aAttrib.put(cur); @@ -279,7 +282,12 @@ SPOSet* SPOSetBuilderFactory::createSPOSet(xmlNodePtr cur) if (bb) { app_log() << " Building SPOSet '" << sname << "' with '" << bname << "' basis set." << std::endl; - return bb->createSPOSet(cur); + SPOSet* spo; + spo = bb->createSPOSet(cur); + spo->objectName = sname; + if (rotation == "yes") + spo = new RotationHelper(spo); + return spo; } else { From 71f04aa91ce8eb4a2c4e11f881c4b33a76c58a07 Mon Sep 17 00:00:00 2001 From: Ye Luo Date: Tue, 8 Oct 2019 20:07:20 -0500 Subject: [PATCH 07/41] Move the rotation operation into SPOSet --- src/QMCWaveFunctions/RotationHelper.cpp | 37 +++---------------- src/QMCWaveFunctions/RotationHelper.h | 13 +++---- src/QMCWaveFunctions/SPOSet.h | 15 +++++--- src/QMCWaveFunctions/SPOSetBuilderFactory.cpp | 19 ++++++++-- src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp | 27 ++++++++++---- src/QMCWaveFunctions/lcao/LCAOrbitalSet.h | 12 +++--- 6 files changed, 59 insertions(+), 64 deletions(-) diff --git a/src/QMCWaveFunctions/RotationHelper.cpp b/src/QMCWaveFunctions/RotationHelper.cpp index 86dc673c3..1d90bf797 100644 --- a/src/QMCWaveFunctions/RotationHelper.cpp +++ b/src/QMCWaveFunctions/RotationHelper.cpp @@ -7,14 +7,13 @@ namespace qmcplusplus { RotationHelper::RotationHelper(SPOSet* spos) - : SPOSet(false, true), + : SPOSet(spos->hasIonDerivs(), true), Phi(spos), params_supplied(false), IsCloned(false) { className = "RotationHelper"; OrbitalSetSize = Phi->getOrbitalSetSize(); - spos->returnMemberVariables(C_original, C_sposet, params_supplied, params); } RotationHelper::~RotationHelper() @@ -54,7 +53,7 @@ void RotationHelper::buildOptVariables(const std::vector>& r int nparams_active = m_act_rot_inds.size(); app_log() << "nparams_active: " << nparams_active << " params2.size(): " << params.size() << std::endl; - if (params_supplied) + if (params_supplied) if (nparams_active != params.size()) APP_ABORT("The number of supplied orbital rotation parameters does not match number prdouced by the slater " "expansion. \n"); @@ -87,30 +86,8 @@ void RotationHelper::buildOptVariables(const std::vector>& r std::vector param(m_act_rot_inds.size()); for (int i = 0; i < m_act_rot_inds.size(); i++) - { param[i] = myVars[i]; - } - apply_rotation(param); - - if (params_supplied) - { - app_log() << "PRINTING MO COEFFICIENTS CREATED BY SUPPLIED PARAMS\n"; - for (int j = 0; j < nmo; j++) - { - for (int i = 0; i < nb; i++) - { - app_log() << " " << std::right << std::fixed << std::setprecision(16) << std::setw(23) << std::scientific - << *(C_sposet->data() + j * nb + i); - - if ((j * nb + i + 1) % 4 == 0) - { - app_log() << std::endl; - } - } - } - app_log() << "\n done printing molecular orbital coefficients\n"; - app_log() << std::endl; - } + apply_rotation(param, false); if (!Optimizable) { @@ -124,12 +101,11 @@ void RotationHelper::buildOptVariables(const std::vector>& r #endif } -void RotationHelper::apply_rotation(const std::vector& param) +void RotationHelper::apply_rotation(const std::vector& param, bool use_stored_copy) { assert(param.size() == m_act_rot_inds.size()); const size_t nmo = Phi->getOrbitalSetSize(); - const size_t nb = Phi->getBasisSetSize(); ValueMatrix_t rot_mat(nmo, nmo); rot_mat = ValueType(0); @@ -146,8 +122,7 @@ void RotationHelper::apply_rotation(const std::vector& param) exponentiate_antisym_matrix(rot_mat); - BLAS::gemm('N', 'T', nb, nmo, nmo, RealType(1.0), C_original.data(), nb, rot_mat.data(), nmo, RealType(0.0), C_sposet->data(), - nb); + Phi->applyRotation(rot_mat, use_stored_copy); } @@ -859,8 +834,6 @@ SPOSet* RotationHelper::makeClone() const myclone->params = this->params; myclone->params_supplied = this->params_supplied; myclone->m_act_rot_inds = this->m_act_rot_inds; - myclone->C_original = this->C_original; - myclone->C_sposet = this->C_sposet; myclone->myVars = this->myVars; return myclone; } diff --git a/src/QMCWaveFunctions/RotationHelper.h b/src/QMCWaveFunctions/RotationHelper.h index 442b6bbda..b5cc6a39e 100644 --- a/src/QMCWaveFunctions/RotationHelper.h +++ b/src/QMCWaveFunctions/RotationHelper.h @@ -21,16 +21,11 @@ public: //destructor ~RotationHelper(); - //Copy of Original Coefficient Matrix - ValueMatrix_t C_original; - //access to Coefficient Matrix of SPOSet - std::shared_ptr C_sposet; - //vector that contains active orbital rotation parameter indices std::vector> m_act_rot_inds; //function to perform orbital rotations - void apply_rotation(const std::vector& param); + void apply_rotation(const std::vector& param, bool use_stored_copy); //helper function to apply_rotation void exponentiate_antisym_matrix(ValueMatrix_t& mat); @@ -135,8 +130,11 @@ public: void checkInVariables(opt_variables_type& active) { if (Optimizable && !IsCloned) + { if (myVars.size()) active.insertFrom(myVars); + Phi->storeParamsBeforeRotation(); + } } void checkOutVariables(const opt_variables_type& active) @@ -147,7 +145,6 @@ public: } } - ///reset void resetParameters(const opt_variables_type& active) { @@ -159,7 +156,7 @@ public: int loc = myVars.where(i); param[i] = myVars[i] = active[loc]; } - apply_rotation(param); + apply_rotation(param, true); } } //********************************************************************************* diff --git a/src/QMCWaveFunctions/SPOSet.h b/src/QMCWaveFunctions/SPOSet.h index fffe8edc3..45dd3235c 100644 --- a/src/QMCWaveFunctions/SPOSet.h +++ b/src/QMCWaveFunctions/SPOSet.h @@ -141,12 +141,15 @@ public: virtual void buildOptVariables(const size_t& nel) {} // For the MSD case rotations must be created in MultiSlaterFast class virtual void buildOptVariables(const std::vector>& rotations) {} - - virtual void returnMemberVariables(ValueMatrix_t& C_original, - std::shared_ptr& C_sposet, - bool& params_supplied, - std::vector& params) - { APP_ABORT("SPOSet does not have a way to pass member variables to Rotation Helper class\n"); } + // store parameters before getting destroyed by rotation. + virtual void storeParamsBeforeRotation() {} + // apply rotation to all the orbitals + virtual void applyRotation(const ValueMatrix_t& rot_mat, bool use_stored_copy = false) + { + std::ostringstream o; + o << "SPOSet::applyRotation is not implemented by " << className << std::endl; + APP_ABORT(o.str()); + } /// reset parameters to the values from optimizer virtual void resetParameters(const opt_variables_type& optVariables) = 0; diff --git a/src/QMCWaveFunctions/SPOSetBuilderFactory.cpp b/src/QMCWaveFunctions/SPOSetBuilderFactory.cpp index 84e0254b0..8e1368865 100644 --- a/src/QMCWaveFunctions/SPOSetBuilderFactory.cpp +++ b/src/QMCWaveFunctions/SPOSetBuilderFactory.cpp @@ -282,11 +282,24 @@ SPOSet* SPOSetBuilderFactory::createSPOSet(xmlNodePtr cur) if (bb) { app_log() << " Building SPOSet '" << sname << "' with '" << bname << "' basis set." << std::endl; - SPOSet* spo; - spo = bb->createSPOSet(cur); + SPOSet* spo = bb->createSPOSet(cur); spo->objectName = sname; if (rotation == "yes") - spo = new RotationHelper(spo); + { + auto* rot_spo = new RotationHelper(spo); + xmlNodePtr tcur = cur->xmlChildrenNode; + while (tcur != NULL) + { + std::string cname((const char*)(tcur->name)); + if (cname == "opt_vars") + { + rot_spo->params_supplied = true; + putContent(rot_spo->params, tcur); + } + tcur = tcur->next; + } + spo = rot_spo; + } return spo; } else diff --git a/src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp b/src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp index b49893eae..c39f49891 100644 --- a/src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp +++ b/src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp @@ -606,15 +606,26 @@ void LCAOrbitalSet::evaluateThirdDeriv(const ParticleSet& P, int first, int last { APP_ABORT("LCAOrbitalSet::evaluateThirdDeriv(P,istart,istop,ggg_logdet) not implemented\n"); } -void LCAOrbitalSet::returnMemberVariables(ValueMatrix_t& C_original, - std::shared_ptr& C_sposet, - bool& params_supplied, - std::vector& params) + +void LCAOrbitalSet::applyRotation(const ValueMatrix_t& rot_mat, bool use_stored_copy) { - C_original = *C; - C_sposet = C; - params = this->params; - params_supplied = this->params_supplied; + if (!use_stored_copy) C_copy = *C; + //gemm is out-of-place + BLAS::gemm('N', 'T', BasisSetSize, OrbitalSetSize, OrbitalSetSize, RealType(1.0), C_copy.data(), + BasisSetSize, rot_mat.data(), OrbitalSetSize, RealType(0.0), C->data(), BasisSetSize); + + /* debugging code + app_log() << "PRINTING MO COEFFICIENTS AFTER ROTATION " << objectName << std::endl; + for (int j = 0; j < OrbitalSetSize; j++) + for (int i = 0; i < BasisSetSize; i++) + { + app_log() << " " << std::right << std::fixed << std::setprecision(16) << std::setw(23) << std::scientific + << *(C->data() + j * BasisSetSize + i); + + if ((j * BasisSetSize + i + 1) % 4 == 0) + app_log() << std::endl; + } + */ } void LCAOrbitalSet::buildOptVariables(const std::vector>& rotations) diff --git a/src/QMCWaveFunctions/lcao/LCAOrbitalSet.h b/src/QMCWaveFunctions/lcao/LCAOrbitalSet.h index 926c3312c..d5348c3c4 100644 --- a/src/QMCWaveFunctions/lcao/LCAOrbitalSet.h +++ b/src/QMCWaveFunctions/lcao/LCAOrbitalSet.h @@ -40,6 +40,8 @@ public: IndexType BasisSetSize; /// pointer to matrix containing the coefficients std::shared_ptr C; + /// a copy of the original C before orbital rotation is applied; + ValueMatrix_t C_copy; /// Scratch space for the initial coefficents before the rotation is applied ValueMatrix_t m_init_B; /// true if SPO parameters (orbital rotation parameters) have been supplied by input @@ -79,13 +81,9 @@ public: SPOSet* makeClone() const; - //RotationHelper uses this function that make a hard copy of this SPOset's C matrix as - // C_original, and then sets a shared pointer to the C matrix as C_sposet. - // The values of the read in parameters, and IsCloned status is also returned. - void returnMemberVariables(ValueMatrix_t& C_original, - std::shared_ptr& C_sposet, - bool& params_supplied, - std::vector& params); + void storeParamsBeforeRotation() { C_copy = *C; } + + void applyRotation(const ValueMatrix_t& rot_mat, bool use_stored_copy); /// create optimizable orbital rotation parameters void buildOptVariables(const std::vector>& rotations); From 81504b6aaf83e3b5a751cc854922e507c89ce850 Mon Sep 17 00:00:00 2001 From: Ye Luo Date: Tue, 8 Oct 2019 20:28:38 -0500 Subject: [PATCH 08/41] Fix broken input xml. --- tests/molecules/H4_ae/H4.wfs_3.xml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/molecules/H4_ae/H4.wfs_3.xml b/tests/molecules/H4_ae/H4.wfs_3.xml index 255202b4b..401683c16 100644 --- a/tests/molecules/H4_ae/H4.wfs_3.xml +++ b/tests/molecules/H4_ae/H4.wfs_3.xml @@ -47,7 +47,7 @@ - + 2.2381e-02 1.5167e-01 1.0912e-01 @@ -61,7 +61,7 @@ - + 4.7842e-01 3.9434e-01 3.2027e-01 @@ -77,7 +77,7 @@ - + 2.5151e-02 1.4825e-01 1.6955e-01 @@ -88,7 +88,8 @@ 2.3827e-02 1.5289e-02 6.2995e-03 - + + From c638e36b53cfcb07bfda6c82fcb2ab6ecccb73fe Mon Sep 17 00:00:00 2001 From: Ye Luo Date: Tue, 8 Oct 2019 20:29:02 -0500 Subject: [PATCH 09/41] Use the same objectName as underlying Phi. --- src/QMCWaveFunctions/SPOSetBuilderFactory.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/QMCWaveFunctions/SPOSetBuilderFactory.cpp b/src/QMCWaveFunctions/SPOSetBuilderFactory.cpp index 8e1368865..e9c7107dc 100644 --- a/src/QMCWaveFunctions/SPOSetBuilderFactory.cpp +++ b/src/QMCWaveFunctions/SPOSetBuilderFactory.cpp @@ -299,6 +299,7 @@ SPOSet* SPOSetBuilderFactory::createSPOSet(xmlNodePtr cur) tcur = tcur->next; } spo = rot_spo; + spo->objectName = sname; } return spo; } From 58469d4f01efc413da379b5175a4ae6a8bdbc02f Mon Sep 17 00:00:00 2001 From: Ye Luo Date: Tue, 8 Oct 2019 20:52:31 -0500 Subject: [PATCH 10/41] Format RotationHelper. --- src/QMCWaveFunctions/RotationHelper.cpp | 233 ++++++++++++------------ src/QMCWaveFunctions/RotationHelper.h | 125 +++++++------ 2 files changed, 182 insertions(+), 176 deletions(-) diff --git a/src/QMCWaveFunctions/RotationHelper.cpp b/src/QMCWaveFunctions/RotationHelper.cpp index 1d90bf797..610d5092b 100644 --- a/src/QMCWaveFunctions/RotationHelper.cpp +++ b/src/QMCWaveFunctions/RotationHelper.cpp @@ -5,21 +5,16 @@ namespace qmcplusplus { - RotationHelper::RotationHelper(SPOSet* spos) - : SPOSet(spos->hasIonDerivs(), true), - Phi(spos), - params_supplied(false), - IsCloned(false) + : SPOSet(spos->hasIonDerivs(), true), Phi(spos), params_supplied(false), IsCloned(false) { - className = "RotationHelper"; + className = "RotationHelper"; OrbitalSetSize = Phi->getOrbitalSetSize(); } -RotationHelper::~RotationHelper() -{} +RotationHelper::~RotationHelper() {} -void RotationHelper::buildOptVariables(const size_t& nel) +void RotationHelper::buildOptVariables(const size_t& nel) { // Phi->buildOptVariables(nel); #if !defined(QMC_COMPLEX) @@ -29,9 +24,9 @@ void RotationHelper::buildOptVariables(const size_t& nel) std::vector> created_m_act_rot_inds; // only core->active rotations created - for (int i = 0; i < nel; i++) - for (int j = nel; j < nmo; j++) - created_m_act_rot_inds.push_back(std::pair(i,j)); + for (int i = 0; i < nel; i++) + for (int j = nel; j < nmo; j++) + created_m_act_rot_inds.push_back(std::pair(i, j)); buildOptVariables(created_m_act_rot_inds); @@ -191,128 +186,134 @@ void RotationHelper::exponentiate_antisym_matrix(ValueMatrix_t& mat) void RotationHelper::evaluateDerivatives(ParticleSet& P, - const opt_variables_type& optvars, - std::vector& dlogpsi, - std::vector& dhpsioverpsi, - const int& FirstIndex, - const int& LastIndex) + const opt_variables_type& optvars, + std::vector& dlogpsi, + std::vector& dhpsioverpsi, + const int& FirstIndex, + const int& LastIndex) { const size_t nel = LastIndex - FirstIndex; const size_t nmo = Phi->getOrbitalSetSize(); -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~PART1 - myG_temp.resize(nel); myG_J.resize(nel); - myL_temp.resize(nel); myL_J.resize(nel); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~PART1 + myG_temp.resize(nel); + myG_J.resize(nel); + myL_temp.resize(nel); + myL_J.resize(nel); - myG_temp = 0; myG_J = 0; - myL_temp = 0; myL_J = 0; - - Bbar.resize(nel,nmo); - psiM_inv.resize(nel,nel); - psiM_all.resize(nel,nmo); - dpsiM_all.resize(nel,nmo); - d2psiM_all.resize(nel,nmo); + myG_temp = 0; + myG_J = 0; + myL_temp = 0; + myL_J = 0; - Bbar = 0; - psiM_inv = 0; - psiM_all = 0; - dpsiM_all = 0; + Bbar.resize(nel, nmo); + psiM_inv.resize(nel, nel); + psiM_all.resize(nel, nmo); + dpsiM_all.resize(nel, nmo); + d2psiM_all.resize(nel, nmo); + + Bbar = 0; + psiM_inv = 0; + psiM_all = 0; + dpsiM_all = 0; d2psiM_all = 0; Phi->evaluate_notranspose(P, FirstIndex, LastIndex, psiM_all, dpsiM_all, d2psiM_all); - for (int i=0; i& dlogpsi, - std::vector& dhpsioverpsi, - const ValueType& psiCurrent, - const std::vector& Coeff, - const std::vector& C2node_up, - const std::vector& C2node_dn, - const ValueVector_t& detValues_up, - const ValueVector_t& detValues_dn, - const GradMatrix_t& grads_up, - const GradMatrix_t& grads_dn, - const ValueMatrix_t& lapls_up, - const ValueMatrix_t& lapls_dn, - const ValueMatrix_t& M_up, - const ValueMatrix_t& M_dn, - const ValueMatrix_t& Minv_up, - const ValueMatrix_t& Minv_dn, - const GradMatrix_t& B_grad, - const ValueMatrix_t& B_lapl, - const std::vector& detData_up, - const size_t N1, - const size_t N2, - const size_t NP1, - const size_t NP2, - const std::vector>& lookup_tbl) +void RotationHelper::evaluateDerivatives(ParticleSet& P, + const opt_variables_type& optvars, + std::vector& dlogpsi, + std::vector& dhpsioverpsi, + const ValueType& psiCurrent, + const std::vector& Coeff, + const std::vector& C2node_up, + const std::vector& C2node_dn, + const ValueVector_t& detValues_up, + const ValueVector_t& detValues_dn, + const GradMatrix_t& grads_up, + const GradMatrix_t& grads_dn, + const ValueMatrix_t& lapls_up, + const ValueMatrix_t& lapls_dn, + const ValueMatrix_t& M_up, + const ValueMatrix_t& M_dn, + const ValueMatrix_t& Minv_up, + const ValueMatrix_t& Minv_dn, + const GradMatrix_t& B_grad, + const ValueMatrix_t& B_lapl, + const std::vector& detData_up, + const size_t N1, + const size_t N2, + const size_t NP1, + const size_t NP2, + const std::vector>& lookup_tbl) { bool recalculate(false); for (int k = 0; k < myVars.size(); ++k) @@ -336,8 +337,8 @@ void RotationHelper::evaluateDerivatives(ParticleSet& P, myG_J = 0.0; myL_J.resize(NP); myL_J = 0.0; - const size_t nmo = Phi->getOrbitalSetSize(); - const size_t nb = Phi->getBasisSetSize(); + const size_t nmo = Phi->getOrbitalSetSize(); + const size_t nb = Phi->getBasisSetSize(); const size_t nel = P.last(0) - P.first(0); const RealType* restrict C_p = Coeff.data(); @@ -789,56 +790,56 @@ $ const int i(m_act_rot_inds[mu].first), j(m_act_rot_inds[mu].second); if (i <= nel - 1 && j > nel - 1) { - dlogpsi[kk] += ValueType( detValues_up[0] * (Table(i, j)) * const0 * (1 / psiCurrent) + (K4T(i, j) - K4T(j, i) - TK4T(i, j)) ); + dlogpsi[kk] += + ValueType(detValues_up[0] * (Table(i, j)) * const0 * (1 / psiCurrent) + (K4T(i, j) - K4T(j, i) - TK4T(i, j))); - dhpsioverpsi[kk] += ValueType( -0.5 * Y4(i, j) - - 0.5 * - (-K5T(i, j) + K5T(j, i) + TK5T(i, j) + K2AiB(i, j) - K2AiB(j, i) - TK2AiB(i, j) - K2XA(i, j) + - K2XA(j, i) + TK2XA(i, j) - MK2T(i, j) + K1T(i, j) - K1T(j, i) - TK1T(i, j) - - const2 / const1 * K2T(i, j) + const2 / const1 * K2T(j, i) + const2 / const1 * TK2T(i, j) + K3T(i, j) - - K3T(j, i) - TK3T(i, j) - K2T(i, j) + K2T(j, i) + TK2T(i, j)) ); + dhpsioverpsi[kk] += + ValueType(-0.5 * Y4(i, j) - + 0.5 * + (-K5T(i, j) + K5T(j, i) + TK5T(i, j) + K2AiB(i, j) - K2AiB(j, i) - TK2AiB(i, j) - K2XA(i, j) + + K2XA(j, i) + TK2XA(i, j) - MK2T(i, j) + K1T(i, j) - K1T(j, i) - TK1T(i, j) - + const2 / const1 * K2T(i, j) + const2 / const1 * K2T(j, i) + const2 / const1 * TK2T(i, j) + + K3T(i, j) - K3T(j, i) - TK3T(i, j) - K2T(i, j) + K2T(j, i) + TK2T(i, j))); } else if (i <= nel - 1 && j <= nel - 1) { - dlogpsi[kk] += ValueType( detValues_up[0] * (Table(i, j) - Table(j, i)) * const0 * (1 / psiCurrent) + - (K4T(i, j) - TK4T(i, j) - K4T(j, i) + TK4T(j, i)) ); + dlogpsi[kk] += ValueType(detValues_up[0] * (Table(i, j) - Table(j, i)) * const0 * (1 / psiCurrent) + + (K4T(i, j) - TK4T(i, j) - K4T(j, i) + TK4T(j, i))); - dhpsioverpsi[kk] += ValueType( -0.5 * (Y4(i, j) - Y4(j, i)) - + dhpsioverpsi[kk] += ValueType( + -0.5 * (Y4(i, j) - Y4(j, i)) - 0.5 * (-K5T(i, j) + K5T(j, i) + TK5T(i, j) - TK5T(j, i) + K2AiB(i, j) - K2AiB(j, i) - TK2AiB(i, j) + TK2AiB(j, i) - K2XA(i, j) + K2XA(j, i) + TK2XA(i, j) - TK2XA(j, i) - MK2T(i, j) + MK2T(j, i) + K1T(i, j) - K1T(j, i) - TK1T(i, j) + TK1T(j, i) - const2 / const1 * K2T(i, j) + const2 / const1 * K2T(j, i) + const2 / const1 * TK2T(i, j) - const2 / const1 * TK2T(j, i) + K3T(i, j) - - K3T(j, i) - TK3T(i, j) + TK3T(j, i) - K2T(i, j) + K2T(j, i) + TK2T(i, j) - TK2T(j, i)) ); + K3T(j, i) - TK3T(i, j) + TK3T(j, i) - K2T(i, j) + K2T(j, i) + TK2T(i, j) - TK2T(j, i))); } else { - dlogpsi[kk] += ValueType( (K4T(i, j) - K4T(j, i)) ); + dlogpsi[kk] += ValueType((K4T(i, j) - K4T(j, i))); - dhpsioverpsi[kk] += ValueType( -0.5 * - (-K5T(i, j) + K5T(j, i) + K2AiB(i, j) - K2AiB(j, i) - K2XA(i, j) + K2XA(j, i) + dhpsioverpsi[kk] += ValueType(-0.5 * + (-K5T(i, j) + K5T(j, i) + K2AiB(i, j) - K2AiB(j, i) - K2XA(i, j) + K2XA(j, i) - + K1T(i, j) - K1T(j, i) - const2 / const1 * K2T(i, j) + const2 / const1 * K2T(j, i) + K3T(i, j) - K3T(j, i) - - K2T(i, j) + K2T(j, i)) ); + + K1T(i, j) - K1T(j, i) - const2 / const1 * K2T(i, j) + + const2 / const1 * K2T(j, i) + K3T(i, j) - K3T(j, i) - K2T(i, j) + K2T(j, i))); } } } - SPOSet* RotationHelper::makeClone() const { - RotationHelper* myclone = new RotationHelper(Phi->makeClone()); + RotationHelper* myclone = new RotationHelper(Phi->makeClone()); - myclone->IsCloned = true; - myclone->params = this->params; - myclone->params_supplied = this->params_supplied; - myclone->m_act_rot_inds = this->m_act_rot_inds; - myclone->myVars = this->myVars; + myclone->IsCloned = true; + myclone->params = this->params; + myclone->params_supplied = this->params_supplied; + myclone->m_act_rot_inds = this->m_act_rot_inds; + myclone->myVars = this->myVars; return myclone; } - - } // namespace qmcplusplus diff --git a/src/QMCWaveFunctions/RotationHelper.h b/src/QMCWaveFunctions/RotationHelper.h index b5cc6a39e..fe3c20871 100644 --- a/src/QMCWaveFunctions/RotationHelper.h +++ b/src/QMCWaveFunctions/RotationHelper.h @@ -1,4 +1,4 @@ -#ifndef ROTATION_HELPER_H +#ifndef ROTATION_HELPER_H #define ROTATION_HELPER_H #include "QMCWaveFunctions/SPOSet.h" @@ -9,13 +9,11 @@ #include "Numerics/DeterminantOperators.h" - namespace qmcplusplus { - -class RotationHelper : public SPOSet +class RotationHelper : public SPOSet { -public: +public: //constructor RotationHelper(SPOSet* spos); //destructor @@ -30,7 +28,7 @@ public: //helper function to apply_rotation void exponentiate_antisym_matrix(ValueMatrix_t& mat); - //A particualr SPOSet used for Orbitals + //A particualr SPOSet used for Orbitals SPOSet* Phi; /// true if SPO parameters (orbital rotation parameters) have been supplied by input @@ -43,30 +41,30 @@ public: SPOSet* makeClone() const; // myG_temp (myL_temp) is the Gradient (Laplacian) value of of the Determinant part of the wfn - // myG_J is the Gradient of the all other parts of the wavefunction (typically just the Jastrow). - // It represents \frac{\nabla\psi_{J}}{\psi_{J}} + // myG_J is the Gradient of the all other parts of the wavefunction (typically just the Jastrow). + // It represents \frac{\nabla\psi_{J}}{\psi_{J}} // myL_J will be used to represent \frac{\nabla^2\psi_{J}}{\psi_{J}} . The Laplacian portion - // IMPORTANT NOTE: The value of P.L holds \nabla^2 ln[\psi] but we need \frac{\nabla^2 \psi}{\psi} and this is what myL_J will hold - ParticleSet::ParticleGradient_t myG_temp, myG_J; + // IMPORTANT NOTE: The value of P.L holds \nabla^2 ln[\psi] but we need \frac{\nabla^2 \psi}{\psi} and this is what myL_J will hold + ParticleSet::ParticleGradient_t myG_temp, myG_J; ParticleSet::ParticleLaplacian_t myL_temp, myL_J; ValueMatrix_t Bbar; ValueMatrix_t psiM_inv; ValueMatrix_t psiM_all; - GradMatrix_t dpsiM_all; + GradMatrix_t dpsiM_all; ValueMatrix_t d2psiM_all; // Single Slater creation - void buildOptVariables(const size_t& nel); - // For the MSD case rotations must be created in MultiSlaterFast class + void buildOptVariables(const size_t& nel); + // For the MSD case rotations must be created in MultiSlaterFast class void buildOptVariables(const std::vector>& rotations); void evaluateDerivatives(ParticleSet& P, const opt_variables_type& optvars, std::vector& dlogpsi, - std::vector& dhpsioverpsi, + std::vector& dhpsioverpsi, const int& FirstIndex, const int& LastIndex); @@ -91,13 +89,13 @@ public: const GradMatrix_t& B_grad, const ValueMatrix_t& B_lapl, const std::vector& detData_up, - const size_t N1, + const size_t N1, const size_t N2, const size_t NP1, const size_t NP2, const std::vector>& lookup_tbl); - -//helper function to evaluatederivative; evaluate orbital rotation parameter derivative using table method + + //helper function to evaluatederivative; evaluate orbital rotation parameter derivative using table method void table_method_eval(std::vector& dlogpsi, std::vector& dhpsioverpsi, const ParticleSet::ParticleLaplacian_t& myL_J, @@ -161,51 +159,50 @@ public: } //********************************************************************************* //the following functions simply call Phi's corresponding functions - void resetTargetParticleSet(ParticleSet& P) - {Phi->resetTargetParticleSet(P); } + void resetTargetParticleSet(ParticleSet& P) { Phi->resetTargetParticleSet(P); } - void setOrbitalSetSize(int norbs) - {Phi->setOrbitalSetSize(norbs); } + void setOrbitalSetSize(int norbs) { Phi->setOrbitalSetSize(norbs); } -// void setBasisSet(basis_type* bs); + // void setBasisSet(basis_type* bs); - int getBasisSetSize() - {return Phi->getBasisSetSize(); } + int getBasisSetSize() { return Phi->getBasisSetSize(); } -// bool setIdentity(bool useIdentity) -// {return Phi->setIdentity(useIdentity); } + // bool setIdentity(bool useIdentity) + // {return Phi->setIdentity(useIdentity); } - void checkObject() - {Phi->checkObject(); } + void checkObject() { Phi->checkObject(); } - void evaluate(const ParticleSet& P, int iat, ValueVector_t& psi) - {Phi->evaluate(P, iat, psi); } + void evaluate(const ParticleSet& P, int iat, ValueVector_t& psi) { Phi->evaluate(P, iat, psi); } + + + void evaluate(const ParticleSet& P, int iat, ValueVector_t& psi, GradVector_t& dpsi, ValueVector_t& d2psi) + { + Phi->evaluate(P, iat, psi, dpsi, d2psi); + } + + void evaluateDetRatios(const VirtualParticleSet& VP, + ValueVector_t& psi, + const ValueVector_t& psiinv, + std::vector& ratios) + { + Phi->evaluateDetRatios(VP, psi, psiinv, ratios); + } + + void evaluate(const ParticleSet& P, int iat, ValueVector_t& psi, GradVector_t& dpsi, HessVector_t& grad_grad_psi) + { + Phi->evaluate(P, iat, psi, dpsi, grad_grad_psi); + } void evaluate(const ParticleSet& P, int iat, ValueVector_t& psi, GradVector_t& dpsi, - ValueVector_t& d2psi) - {Phi->evaluate(P, iat, psi, dpsi, d2psi); } - - void evaluateDetRatios(const VirtualParticleSet& VP, - ValueVector_t& psi, - const ValueVector_t& psiinv, - std::vector& ratios) - {Phi->evaluateDetRatios(VP, psi, psiinv, ratios); } - - void evaluate(const ParticleSet& P, int iat, ValueVector_t& psi, GradVector_t& dpsi, HessVector_t& grad_grad_psi) - {Phi->evaluate(P, iat, psi, dpsi, grad_grad_psi); } - - - void evaluate(const ParticleSet& P, - int iat, - ValueVector_t& psi, - GradVector_t& dpsi, - HessVector_t& grad_grad_psi, - GGGVector_t& grad_grad_grad_psi) - {Phi->evaluate(P, iat, psi, dpsi, grad_grad_psi, grad_grad_grad_psi); } + HessVector_t& grad_grad_psi, + GGGVector_t& grad_grad_grad_psi) + { + Phi->evaluate(P, iat, psi, dpsi, grad_grad_psi, grad_grad_grad_psi); + } void evaluate_notranspose(const ParticleSet& P, @@ -213,8 +210,10 @@ public: int last, ValueMatrix_t& logdet, GradMatrix_t& dlogdet, - ValueMatrix_t& d2logdet) - {Phi->evaluate_notranspose(P, first, last, logdet, dlogdet, d2logdet); } + ValueMatrix_t& d2logdet) + { + Phi->evaluate_notranspose(P, first, last, logdet, dlogdet, d2logdet); + } void evaluate_notranspose(const ParticleSet& P, int first, @@ -222,7 +221,9 @@ public: ValueMatrix_t& logdet, GradMatrix_t& dlogdet, HessMatrix_t& grad_grad_logdet) - {Phi->evaluate_notranspose(P, first, last, logdet, dlogdet, grad_grad_logdet); } + { + Phi->evaluate_notranspose(P, first, last, logdet, dlogdet, grad_grad_logdet); + } void evaluate_notranspose(const ParticleSet& P, int first, @@ -231,7 +232,9 @@ public: GradMatrix_t& dlogdet, HessMatrix_t& grad_grad_logdet, GGGMatrix_t& grad_grad_grad_logdet) - {Phi->evaluate_notranspose(P, first, last, logdet, dlogdet, grad_grad_logdet, grad_grad_grad_logdet); } + { + Phi->evaluate_notranspose(P, first, last, logdet, dlogdet, grad_grad_logdet, grad_grad_grad_logdet); + } void evaluateGradSource(const ParticleSet& P, int first, @@ -239,7 +242,9 @@ public: const ParticleSet& source, int iat_src, GradMatrix_t& grad_phi) - {Phi->evaluateGradSource(P, first, last, source, iat_src, grad_phi); } + { + Phi->evaluateGradSource(P, first, last, source, iat_src, grad_phi); + } void evaluateGradSource(const ParticleSet& P, int first, @@ -249,12 +254,12 @@ public: GradMatrix_t& grad_phi, HessMatrix_t& grad_grad_phi, GradMatrix_t& grad_lapl_phi) - {Phi->evaluateGradSource(P, first, last, source, iat_src, grad_phi, grad_grad_phi, grad_lapl_phi); } - -// void evaluateThirdDeriv(const ParticleSet& P, int first, int last, GGGMatrix_t& grad_grad_grad_logdet) -// {Phi->evaluateThridDeriv(P, first, last, grad_grad_grad_logdet); } - + { + Phi->evaluateGradSource(P, first, last, source, iat_src, grad_phi, grad_grad_phi, grad_lapl_phi); + } + // void evaluateThirdDeriv(const ParticleSet& P, int first, int last, GGGMatrix_t& grad_grad_grad_logdet) + // {Phi->evaluateThridDeriv(P, first, last, grad_grad_grad_logdet); } }; } //namespace qmcplusplus From 829d140f9040744d6b4c70aa2acaf02e999fcdb9 Mon Sep 17 00:00:00 2001 From: Sergio Daniel Pineda Flores Date: Wed, 16 Oct 2019 15:22:50 -0600 Subject: [PATCH 11/41] recovered H4.wfs_3.xml file; fixed Ainv.cols in DelayedUpdate.h; removed redundant code in LCAOrbitalSet that is now in Rotation Helper; Changed ResetParameters so that parameters are zeroed after rotation is applyed to Coefficient matrix --- src/QMCWaveFunctions/Fermion/DelayedUpdate.h | 2 +- src/QMCWaveFunctions/RotationHelper.cpp | 1 - src/QMCWaveFunctions/RotationHelper.h | 4 + .../lcao/LCAOrbitalBuilder.cpp | 5 - src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp | 717 +----------------- src/QMCWaveFunctions/lcao/LCAOrbitalSet.h | 96 +-- tests/molecules/H4_ae/H4.wfs_3.xml | 55 +- 7 files changed, 37 insertions(+), 843 deletions(-) diff --git a/src/QMCWaveFunctions/Fermion/DelayedUpdate.h b/src/QMCWaveFunctions/Fermion/DelayedUpdate.h index bbb0cbb3a..7130636d4 100644 --- a/src/QMCWaveFunctions/Fermion/DelayedUpdate.h +++ b/src/QMCWaveFunctions/Fermion/DelayedUpdate.h @@ -106,7 +106,7 @@ public: } const T cone(1); const T czero(0); - const int norb = Ainv.cols(); + const int norb = Ainv.rows(); const int lda_Binv = Binv.cols(); // save Ainv[rowchanged] to invRow std::copy_n(Ainv[rowchanged], norb, invRow.data()); diff --git a/src/QMCWaveFunctions/RotationHelper.cpp b/src/QMCWaveFunctions/RotationHelper.cpp index 610d5092b..cf82072aa 100644 --- a/src/QMCWaveFunctions/RotationHelper.cpp +++ b/src/QMCWaveFunctions/RotationHelper.cpp @@ -16,7 +16,6 @@ RotationHelper::~RotationHelper() {} void RotationHelper::buildOptVariables(const size_t& nel) { -// Phi->buildOptVariables(nel); #if !defined(QMC_COMPLEX) const size_t nmo = Phi->getOrbitalSetSize(); diff --git a/src/QMCWaveFunctions/RotationHelper.h b/src/QMCWaveFunctions/RotationHelper.h index fe3c20871..63784516b 100644 --- a/src/QMCWaveFunctions/RotationHelper.h +++ b/src/QMCWaveFunctions/RotationHelper.h @@ -127,6 +127,10 @@ public: void checkInVariables(opt_variables_type& active) { + //reset parameters to zero after coefficient matrix has been updated + for (int k = 0; k < myVars.size(); ++k) + myVars[k] = 0.0; + if (Optimizable && !IsCloned) { if (myVars.size()) diff --git a/src/QMCWaveFunctions/lcao/LCAOrbitalBuilder.cpp b/src/QMCWaveFunctions/lcao/LCAOrbitalBuilder.cpp index 1d2c01289..4e90fc601 100644 --- a/src/QMCWaveFunctions/lcao/LCAOrbitalBuilder.cpp +++ b/src/QMCWaveFunctions/lcao/LCAOrbitalBuilder.cpp @@ -540,11 +540,6 @@ bool LCAOrbitalBuilder::loadMO(LCAOrbitalSet& spo, xmlNodePtr cur) { coeff_ptr = cur; } - else if (cname == "opt_vars") - { - spo.params_supplied = true; - putContent(spo.params, cur); - } cur = cur->next; } if (coeff_ptr == NULL) diff --git a/src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp b/src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp index 6e8e19377..c03706f83 100644 --- a/src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp +++ b/src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp @@ -17,7 +17,7 @@ namespace qmcplusplus { LCAOrbitalSet::LCAOrbitalSet(basis_type* bs, bool optimize) - : SPOSet(true, optimize), myBasisSet(nullptr), BasisSetSize(0), params_supplied(false), Identity(true) + : SPOSet(true, optimize), myBasisSet(nullptr), BasisSetSize(0), Identity(true) { if (bs != nullptr) setBasisSet(bs); @@ -628,720 +628,5 @@ void LCAOrbitalSet::applyRotation(const ValueMatrix_t& rot_mat, bool use_stored_ */ } -void LCAOrbitalSet::buildOptVariables(const std::vector>& rotations) -{ -#if !defined(QMC_COMPLEX) - const size_t nmo = OrbitalSetSize; - const size_t nb = BasisSetSize; - m_init_B = *C; - - // create active rotations - m_act_rot_inds = rotations; - - // This will add the orbital rotation parameters to myVars - // and will also read in initial parameter values supplied in input file - int p, q; - int nparams_active = m_act_rot_inds.size(); - if (params_supplied) - if (nparams_active != params.size()) - APP_ABORT("The number of supplied orbital rotation parameters does not match number prdouced by the slater " - "expansion. \n"); - - for (int i = 0; i < nparams_active; i++) - { - p = m_act_rot_inds[i].first; - q = m_act_rot_inds[i].second; - std::stringstream sstr; - sstr << objectName << "_orb_rot_" << (p < 10 ? "0" : "") << (p < 100 ? "0" : "") << (p < 1000 ? "0" : "") << p - << "_" << (q < 10 ? "0" : "") << (q < 100 ? "0" : "") << (q < 1000 ? "0" : "") << q; - - // If the user input parameteres, use those. Otherwise, initialize the parameters to zero - if (params_supplied) - { - myVars.insert(sstr.str(), params[i]); - } - else - { - myVars.insert(sstr.str(), 0.0); - } - } - - //Printing the parameters - if (false) - { - app_log() << std::string(16, ' ') << "Parameter name" << std::string(15, ' ') << "Value\n"; - myVars.print(app_log()); - } - - std::vector param(m_act_rot_inds.size()); - for (int i = 0; i < m_act_rot_inds.size(); i++) - { - param[i] = myVars[i]; - } - apply_rotation(param); - - if (params_supplied) - { - app_log() << "PRINTING MO COEFFICIENTS CREATED BY SUPPLIED PARAMS\n"; - for (int j = 0; j < nmo; j++) - { - for (int i = 0; i < nb; i++) - { - app_log() << " " << std::right << std::fixed << std::setprecision(16) << std::setw(23) << std::scientific - << *(C->data() + j * nb + i); - - if ((j * nb + i + 1) % 4 == 0) - { - app_log() << std::endl; - } - } - } - app_log() << "\n done printing molecular orbital coefficients\n"; - app_log() << std::endl; - } - - if (!Optimizable) - { - //THIS ALLOWS FOR ORBITAL PARAMETERS TO BE READ IN EVEN WHEN THOSE PARAMETERS ARE NOT BEING OPTIMIZED - //this assumes there are only CI coefficients ahead of the M_orb_coefficients - myVars.Index.erase(myVars.Index.begin(), myVars.Index.end()); - myVars.NameAndValue.erase(myVars.NameAndValue.begin(), myVars.NameAndValue.end()); - myVars.ParameterType.erase(myVars.ParameterType.begin(), myVars.ParameterType.end()); - myVars.Recompute.erase(myVars.Recompute.begin(), myVars.Recompute.end()); - } -#endif -} - -void LCAOrbitalSet::evaluateDerivatives(ParticleSet& P, - const opt_variables_type& optvars, - std::vector& dlogpsi, - std::vector& dhpsioverpsi, - const ValueType& psiCurrent, - const std::vector& Coeff, - const std::vector& C2node_up, - const std::vector& C2node_dn, - const ValueVector_t& detValues_up, - const ValueVector_t& detValues_dn, - const GradMatrix_t& grads_up, - const GradMatrix_t& grads_dn, - const ValueMatrix_t& lapls_up, - const ValueMatrix_t& lapls_dn, - const ValueMatrix_t& M_up, - const ValueMatrix_t& M_dn, - const ValueMatrix_t& Minv_up, - const ValueMatrix_t& Minv_dn, - const GradMatrix_t& B_grad, - const ValueMatrix_t& B_lapl, - const std::vector& detData_up, - const size_t N1, - const size_t N2, - const size_t NP1, - const size_t NP2, - const std::vector>& lookup_tbl) -{ -#if !defined(QMC_COMPLEX) - bool recalculate(false); - for (int k = 0; k < myVars.size(); ++k) - { - int kk = myVars.where(k); - if (kk < 0) - continue; - if (optvars.recompute(kk)) - recalculate = true; - } - if (recalculate) - { - ParticleSet::ParticleGradient_t myG_temp, myG_J; - ParticleSet::ParticleLaplacian_t myL_temp, myL_J; - const int NP = P.getTotalNum(); - myG_temp.resize(NP); - myG_temp = 0.0; - myL_temp.resize(NP); - myL_temp = 0.0; - myG_J.resize(NP); - myG_J = 0.0; - myL_J.resize(NP); - myL_J = 0.0; - const size_t nmo = OrbitalSetSize; - const size_t nb = BasisSetSize; - const size_t nel = P.last(0) - P.first(0); - - const RealType* restrict C_p = Coeff.data(); - for (int i = 0; i < Coeff.size(); i++) - { - const size_t upC = C2node_up[i]; - const size_t dnC = C2node_dn[i]; - const ValueType tmp1 = C_p[i] * detValues_dn[dnC]; - const ValueType tmp2 = C_p[i] * detValues_up[upC]; - for (size_t k = 0, j = N1; k < NP1; k++, j++) - { - myG_temp[j] += tmp1 * grads_up(upC, k); - myL_temp[j] += tmp1 * lapls_up(upC, k); - } - for (size_t k = 0, j = N2; k < NP2; k++, j++) - { - myG_temp[j] += tmp2 * grads_dn(dnC, k); - myL_temp[j] += tmp2 * lapls_dn(dnC, k); - } - } - - myG_temp *= (1 / psiCurrent); - myL_temp *= (1 / psiCurrent); - - // calculation of myG_J which will be used to represent \frac{\nabla\psi_{J}}{\psi_{J}} - // calculation of myL_J will be used to represent \frac{\nabla^2\psi_{J}}{\psi_{J}} - // IMPORTANT NOTE: The value of P.L holds \nabla^2 ln[\psi] but we need \frac{\nabla^2 \psi}{\psi} and this is what myL_J will hold - for (int iat = 0; iat < (myL_temp.size()); iat++) - { - myG_J[iat] = (P.G[iat] - myG_temp[iat]); - myL_J[iat] = (P.L[iat] + dot(P.G[iat], P.G[iat]) - myL_temp[iat]); - } - - - table_method_eval(dlogpsi, dhpsioverpsi, myL_J, myG_J, nel, nmo, psiCurrent, Coeff, C2node_up, C2node_dn, - detValues_up, detValues_dn, grads_up, grads_dn, lapls_up, lapls_dn, M_up, M_dn, Minv_up, Minv_dn, - B_grad, B_lapl, detData_up, N1, N2, NP1, NP2, lookup_tbl); - } -#endif -} - -#if !defined(QMC_COMPLEX) -void LCAOrbitalSet::apply_rotation(const std::vector& param) -{ - assert(param.size() == m_act_rot_inds.size()); - - const size_t nmo = OrbitalSetSize; - const size_t nb = BasisSetSize; - ValueMatrix_t rot_mat(nmo, nmo); - rot_mat = ValueType(0); - - // read out the parameters that define the rotation into an antisymmetric matrix - for (int i = 0; i < m_act_rot_inds.size(); i++) - { - const int p = m_act_rot_inds[i].first; - const int q = m_act_rot_inds[i].second; - const RealType x = param[i]; - - rot_mat[q][p] = x; - rot_mat[p][q] = -x; - } - - exponentiate_antisym_matrix(rot_mat); - - BLAS::gemm('N', 'T', nb, nmo, nmo, RealType(1.0), m_init_B.data(), nb, rot_mat.data(), nmo, RealType(0.0), C->data(), - nb); -} - - -// compute exponential of a real, antisymmetric matrix by diagonalizing and exponentiating eigenvalues -void LCAOrbitalSet::exponentiate_antisym_matrix(ValueMatrix_t& mat) -{ - const int n = mat.rows(); - std::vector> mat_h(n * n, 0); - std::vector eval(n, 0); - std::vector> work(2 * n, 0); - std::vector rwork(3 * n, 0); - std::vector> mat_d(n * n, 0); - std::vector> mat_t(n * n, 0); - // exponentiating e^X = e^iY (Y hermitian) - // i(-iX) = X, so -iX is hermitian - // diagonalize -iX = UDU^T, exponentiate e^iD, and return U e^iD U^T - // construct hermitian analogue of mat by multiplying by -i - for (int i = 0; i < n; ++i) - { - for (int j = i; j < n; ++j) - { - mat_h[i + n * j] = std::complex(0, -1.0 * mat[j][i]); - mat_h[j + n * i] = std::complex(0, 1.0 * mat[j][i]); - } - } - // diagonalize the matrix - char JOBZ('V'); - char UPLO('U'); - int N(n); - int LDA(n); - int LWORK(2 * n); - int info = 0; - LAPACK::heev(JOBZ, UPLO, N, &mat_h.at(0), LDA, &eval.at(0), &work.at(0), LWORK, &rwork.at(0), info); - if (info != 0) - { - std::ostringstream msg; - msg << "heev failed with info = " << info << " in MultiSlaterDeterminantFast::exponentiate_antisym_matrix"; - app_log() << msg.str() << std::endl; - APP_ABORT(msg.str()); - } - // iterate through diagonal matrix, exponentiate terms - for (int i = 0; i < n; ++i) - { - for (int j = 0; j < n; ++j) - { - mat_d[i + j * n] = (i == j) ? std::exp(std::complex(0.0, eval[i])) : std::complex(0.0, 0.0); - } - } - // perform matrix multiplication - // assume row major - BLAS::gemm('N', 'C', n, n, n, std::complex(1.0, 0), &mat_d.at(0), n, &mat_h.at(0), n, - std::complex(0.0, 0.0), &mat_t.at(0), n); - BLAS::gemm('N', 'N', n, n, n, std::complex(1.0, 0), &mat_h.at(0), n, &mat_t.at(0), n, - std::complex(0.0, 0.0), &mat_d.at(0), n); - for (int i = 0; i < n; ++i) - for (int j = 0; j < n; ++j) - { - if (mat_d[i + n * j].imag() > 1e-12) - { - app_log() << "warning: large imaginary value in orbital rotation matrix: (i,j) = (" << i << "," << j - << "), im = " << mat_d[i + n * j].imag() << std::endl; - } - mat[j][i] = mat_d[i + n * j].real(); - } -} - -void LCAOrbitalSet::table_method_eval(std::vector& dlogpsi, - std::vector& dhpsioverpsi, - const ParticleSet::ParticleLaplacian_t& myL_J, - const ParticleSet::ParticleGradient_t& myG_J, - const size_t nel, - const size_t nmo, - const ValueType& psiCurrent, - const std::vector& Coeff, - const std::vector& C2node_up, - const std::vector& C2node_dn, - const ValueVector_t& detValues_up, - const ValueVector_t& detValues_dn, - const GradMatrix_t& grads_up, - const GradMatrix_t& grads_dn, - const ValueMatrix_t& lapls_up, - const ValueMatrix_t& lapls_dn, - const ValueMatrix_t& M_up, - const ValueMatrix_t& M_dn, - const ValueMatrix_t& Minv_up, - const ValueMatrix_t& Minv_dn, - const GradMatrix_t& B_grad, - const ValueMatrix_t& B_lapl, - const std::vector& detData_up, - const size_t N1, - const size_t N2, - const size_t NP1, - const size_t NP2, - const std::vector>& lookup_tbl) -/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -GUIDE TO THE MATICES BEING BUILT ----------------------------------------------- -The idea here is that there is a loop over all unique determinants. For each determiant the table method is employed to calculate the contributions to the parameter derivatives (dhpsioverpsi/dlogpsi) - - loop through unquie determinants - loop through parameters - evaluate contributaion to dlogpsi and dhpsioverpsi -\noindent - - BLAS GUIDE for matrix multiplication of [ alpha * A.B + beta * C = C ] - Matrix A is of dimensions a1,a2 and Matrix B is b1,b2 in which a2=b1 - The BLAS command is as follows... - - BLAS::gemm('N','N', b2, a1, a2 ,alpha, B, b2, A, a2, beta, C, b2); - -Below is a human readable format for the matrix multiplications performed below... - -This notation is inspired by http://dx.doi.org/10.1063/1.4948778 -\newline -\hfill\break -$ - A_{i,j}=\phi_j(r_{i}) \\ - T = A^{-1} \widetilde{A} \\ - B_{i,j} =\nabla^2 \phi_{j}(r_i) + \frac{\nabla_{i}J}{J} \cdot \nabla \phi_{j}(r_{i}) + \frac{\nabla^2_i J}{J} \phi_{j}(r_{i}) \\ - \hat{O_{I}} = \hat{O}D_{I} \\ - D_{I}=det(A_{I}) \newline - \psi_{MS} = \sum_{I=0} C_{I} D_{I\uparrow}D_{I\downarrow} \\ - \Psi_{total} = \psi_{J}\psi_{MS} \\ - \alpha_{I} = P^{T}_{I}TQ_{I} \\ - M_{I} = P^{T}_{I} \widetilde{M} Q_{I} = P^{T}_{I} (A^{-1}\widetilde{B} - A^{-1} B A^{-1}\widetilde{A} )Q_{I} \\ -$ -\newline -There are three constants I use in the expressions for dhpsioverpsi and dlogpsi -\newline -\hfill\break -$ - const0 = C_{0}*det(A_{0\downarrow})+\sum_{I=1} C_{I}*det(A_{I\downarrow})* det(\alpha_{I\uparrow}) \\ - const1 = C_{0}*\hat{O} det(A_{0\downarrow})+\sum_{I=1} C_{I}*\hat{O}det(A_{I\downarrow})* det(\alpha_{I\uparrow}) \\ - const2 = \sum_{I=1} C_{I}*det(A_{I\downarrow})* Tr[\alpha_{I}^{-1}M_{I}]*det(\alpha_{I}) \\ -$ -\newline -Below is a translation of the shorthand I use to represent matrices independent of ``excitation matrix". -\newline -\hfill\break -$ - Y_{1} = A^{-1}B \\ - Y_{2} = A^{-1}BA^{-1}\widetilde{A} \\ - Y_{3} = A^{-1}\widetilde{B} \\ - Y_{4} = \widetilde{M} = (A^{-1}\widetilde{B} - A^{-1} B A^{-1}\widetilde{A} )\\ -$ -\newline -Below is a translation of the shorthand I use to represent matrices dependent on ``excitation" with respect to the reference Matrix and sums of matrices. Above this line I have represented these excitation matrices with a subscript ``I" but from this point on The subscript will be omitted and it is clear that whenever a matrix depends on $P^{T}_I$ and $Q_{I}$ that this is an excitation matrix. The reference matrix is always $A_{0}$ and is always the Hartree Fock Matrix. -\newline -\hfill\break -$ - Y_{5} = TQ \\ - Y_{6} = (P^{T}TQ)^{-1} = \alpha_{I}^{-1}\\ - Y_{7} = \alpha_{I}^{-1} P^{T} \\ - Y_{11} = \widetilde{M}Q \\ - Y_{23} = P^{T}\widetilde{M}Q \\ - Y_{24} = \alpha_{I}^{-1}P^{T}\widetilde{M}Q \\ - Y_{25} = \alpha_{I}^{-1}P^{T}\widetilde{M}Q\alpha_{I}^{-1} \\ - Y_{26} = \alpha_{I}^{-1}P^{T}\widetilde{M}Q\alpha_{I}^{-1}P^{T}\\ -$ -\newline -So far you will notice that I have not included up or down arrows to specify what spin the matrices are of. This is because we are calculating the derivative of all up or all down spin orbital rotation parameters at a time. If we are finding the up spin derivatives then any term that is down spin will be constant. The following assumes that we are taking up-spin MO rotation parameter derivatives. Of course the down spin expression can be retrieved by swapping the up and down arrows. I have dubbed any expression with lowercase p prefix as a "precursor" to an expression actually used... -\newline -\hfill\break -$ - \dot{C_{I}} = C_{I}*det(A_{I\downarrow})\\ - \ddot{C_{I}} = C_{I}*\hat{O}det(A_{I\downarrow}) \\ - pK1 = \sum_{I=1} \dot{C_{I}} det(\alpha_{I}) Tr[\alpha_{I}^{-1}M_{I}] (Q\alpha_{I}^{-1}P^{T}) \\ - pK2 = \sum_{I=1} \dot{C_{I}} det(\alpha_{I}) (Q\alpha_{I}^{-1}P^{T}) \\ - pK3 = \sum_{I=1} \ddot{C_{I}} det(\alpha_{I}) (Q\alpha_{I}^{-1}P^{T}) \\ - pK4 = \sum_{I=1} \dot{C_{I}} det(A_{I}) (Q\alpha_{I}^{-1}P^{T}) \\ - pK5 = \sum_{I=1} \dot{C_{I}} det(\alpha_{I}) (Q\alpha_{I}^{-1} M_{I} \alpha_{I}^{-1}P^{T}) \\ -$ -\newline -Now these p matrices will be used to make various expressions via BLAS commands. -\newline -\hfill\break -$ - K1T = const0^{-1}*pK1.T =const0^{-1} \sum_{I=1} \dot{C_{I}} det(\alpha_{I}) Tr[\alpha_{I}^{-1}M_{I}] (Q\alpha_{I}^{-1}P^{T}T) \\ - TK1T = T.K1T = const0^{-1} \sum_{I=1} \dot{C_{I}} det(\alpha_{I}) Tr[\alpha_{I}^{-1}M_{I}] (TQ\alpha_{I}^{-1}P^{T}T)\\ \\ - K2AiB = const0^{-1} \sum_{I=1} \dot{C_{I}} det(\alpha_{I}) (Q\alpha_{I}^{-1}P^{T}A^{-1}\widetilde{B})\\ - TK2AiB = T.K2AiB = const0^{-1} \sum_{I=1} \dot{C_{I}} det(\alpha_{I}) (TQ\alpha_{I}^{-1}P^{T}A^{-1}\widetilde{B})\\ - K2XA = const0^{-1} \sum_{I=1} \dot{C_{I}} det(\alpha_{I}) (Q\alpha_{I}^{-1}P^{T}X\widetilde{A})\\ - TK2XA = T.K2XA = const0^{-1} \sum_{I=1} \dot{C_{I}} det(\alpha_{I}) (TQ\alpha_{I}^{-1}P^{T}X\widetilde{A})\\ \\ - K2T = \frac{const1}{const0^{2}} \sum_{I=1} \dot{C_{I}} det(\alpha_{I}) (Q\alpha_{I}^{-1}P^{T}T) \\ - TK2T = T.K2T =\frac{const1}{const0^{2}} \sum_{I=1} \dot{C_{I}} det(\alpha_{I}) (TQ\alpha_{I}^{-1}P^{T}T) \\ - MK2T = \frac{const0}{const1} Y_{4}.K2T= const0^{-1} \sum_{I=1} \dot{C_{I}} det(\alpha_{I}) (\widetilde{M}Q\alpha_{I}^{-1}P^{T}T)\\ \\ - K3T = const0^{-1} \sum_{I=1} \ddot{C_{I}} det(\alpha_{I}) (Q\alpha_{I}^{-1}P^{T}T) \\ - TK3T = T.K3T = const0^{-1} \sum_{I=1} \ddot{C_{I}} det(\alpha_{I}) (TQ\alpha_{I}^{-1}P^{T}T)\\ \\ - K4T = \sum_{I=1} \dot{C_{I}} det(A_{I}) (Q\alpha_{I}^{-1}P^{T}T) \\ - TK4T = T.K4T = \sum_{I=1} \dot{C_{I}} det(A_{I}) (TQ\alpha_{I}^{-1}P^{T}T) \\ \\ - K5T = const0^{-1} \sum_{I=1} \dot{C_{I}} det(\alpha_{I}) (Q\alpha_{I}^{-1} M_{I} \alpha_{I}^{-1}P^{T} T) \\ - TK5T = T.K5T = \sum_{I=1} \dot{C_{I}} det(\alpha_{I}) (T Q\alpha_{I}^{-1} M_{I} \alpha_{I}^{-1}P^{T} T) \\ -$ -\newline -Now with all these matrices and constants the expressions of dhpsioverpsi and dlogpsi can be created. - - - - -In addition I will be using a special generalization of the kinetic operator which I will denote as O. Our Slater matrix with the special O operator applied to each element will be called B_bar - -$ -``Bbar"_{i,j} =\nabla^2 \phi_{j}(r_i) + \frac{\nabla_{i}J}{J} \cdot \nabla \phi_{j}(r_{i}) + \frac{\nabla^2_i J}{J} \phi_{j}(r_{i}) -$ -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ -{ - ValueMatrix_t Table; - ValueMatrix_t Bbar; - ValueMatrix_t Y1, Y2, Y3, Y4, Y5, Y6, Y7, Y11, Y23, Y24, Y25, Y26; - ValueMatrix_t pK1, K1T, TK1T, pK2, K2AiB, TK2AiB, K2XA, TK2XA, K2T, TK2T, MK2T, pK3, K3T, TK3T, pK4, K4T, TK4T, pK5, - K5T, TK5T; - - Table.resize(nel, nmo); - - Bbar.resize(nel, nmo); - - Y1.resize(nel, nel); - Y2.resize(nel, nmo); - Y3.resize(nel, nmo); - Y4.resize(nel, nmo); - - pK1.resize(nmo, nel); - K1T.resize(nmo, nmo); - TK1T.resize(nel, nmo); - - pK2.resize(nmo, nel); - K2AiB.resize(nmo, nmo); - TK2AiB.resize(nel, nmo); - K2XA.resize(nmo, nmo); - TK2XA.resize(nel, nmo); - K2T.resize(nmo, nmo); - TK2T.resize(nel, nmo); - MK2T.resize(nel, nmo); - - pK3.resize(nmo, nel); - K3T.resize(nmo, nmo); - TK3T.resize(nel, nmo); - - pK4.resize(nmo, nel); - K4T.resize(nmo, nmo); - TK4T.resize(nel, nmo); - - pK5.resize(nmo, nel); - K5T.resize(nmo, nmo); - TK5T.resize(nel, nmo); - - const int parameters_size(m_act_rot_inds.size()); - const int parameter_start_index(0); - - const size_t num_unique_up_dets(detValues_up.size()); - const size_t num_unique_dn_dets(detValues_dn.size()); - - const RealType* restrict cptr = Coeff.data(); - const size_t nc = Coeff.size(); - const size_t* restrict upC(C2node_up.data()); - const size_t* restrict dnC(C2node_dn.data()); - //B_grad holds the gardient operator - //B_lapl holds the laplacian operator - //B_bar will hold our special O operator - - const int offset1(N1); - const int offset2(N2); - const int NPother(NP2); - - RealType* T(Table.data()); - - //possibly replace wit BLAS calls - for (int i = 0; i < nel; i++) - for (int j = 0; j < nmo; j++) - Bbar(i, j) = B_lapl(i, j) + 2 * dot(myG_J[i + offset1], B_grad(i, j)) + myL_J[i + offset1] * M_up(i, j); - - const RealType* restrict B(Bbar.data()); - const RealType* restrict A(M_up.data()); - const RealType* restrict Ainv(Minv_up.data()); - //IMPORTANT NOTE: THE Dets[0]->psiMinv OBJECT DOES NOT HOLD THE INVERSE IF THE MULTIDIRACDETERMINANTBASE ONLY CONTAINES ONE ELECTRON. NEED A FIX FOR THIS CASE - // The T matrix should be calculated and stored for use - // T = A^{-1} \widetilde A - //REMINDER: that the ValueMatrix_t "matrix" stores data in a row major order and that BLAS commands assume column major - BLAS::gemm('N', 'N', nmo, nel, nel, RealType(1.0), A, nmo, Ainv, nel, RealType(0.0), T, nmo); - - BLAS::gemm('N', 'N', nel, nel, nel, RealType(1.0), B, nmo, Ainv, nel, RealType(0.0), Y1.data(), nel); - BLAS::gemm('N', 'N', nmo, nel, nel, RealType(1.0), T, nmo, Y1.data(), nel, RealType(0.0), Y2.data(), nmo); - BLAS::gemm('N', 'N', nmo, nel, nel, RealType(1.0), B, nmo, Ainv, nel, RealType(0.0), Y3.data(), nmo); - - //possibly replace with BLAS call - Y4 = Y3 - Y2; - - //Need to create the constants: (Oi, const0, const1, const2)to take advantage of minimal BLAS commands; - //Oi is the special operator applied to the slater matrix "A subscript i" from the total CI expansion - //\hat{O_{i}} = \hat{O}D_{i} with D_{i}=det(A_{i}) and Multi-Slater component defined as \sum_{i=0} C_{i} D_{i\uparrow}D_{i\downarrow} - std::vector Oi(num_unique_dn_dets); - - for (int index = 0; index < num_unique_dn_dets; index++) - for (int iat = 0; iat < NPother; iat++) - Oi[index] += lapls_dn(index, iat) + 2 * dot(grads_dn(index, iat), myG_J[offset2 + iat]) + - myL_J[offset2 + iat] * detValues_dn[index]; - - //const0 = C_{0}*det(A_{0\downarrow})+\sum_{i=1} C_{i}*det(A_{i\downarrow})* det(\alpha_{i\uparrow}) - //const1 = C_{0}*\hat{O} det(A_{0\downarrow})+\sum_{i=1} C_{i}*\hat{O}det(A_{i\downarrow})* det(\alpha_{i\uparrow}) - //const2 = \sum_{i=1} C_{i}*det(A_{i\downarrow})* Tr[\alpha_{i}^{-1}M_{i}]*det(\alpha_{i}) - RealType const0(0.0), const1(0.0), const2(0.0); - for (size_t i = 0; i < nc; ++i) - { - const RealType c = cptr[i]; - const size_t up = upC[i]; - const size_t down = dnC[i]; - - const0 += c * detValues_dn[down] * (detValues_up[up] / detValues_up[0]); - const1 += c * Oi[down] * (detValues_up[up] / detValues_up[0]); - } - - std::fill(pK1.begin(), pK1.end(), 0.0); - std::fill(pK2.begin(), pK2.end(), 0.0); - std::fill(pK3.begin(), pK3.end(), 0.0); - std::fill(pK4.begin(), pK4.end(), 0.0); - std::fill(pK5.begin(), pK5.end(), 0.0); - - //Now we are going to loop through all unique determinants. - //The few lines above are for the reference matrix contribution. - //Although I start the loop below from index 0, the loop only performs actions when the index is >= 1 - //the detData object contains all the information about the P^T and Q matrices (projection matrices) needed in the table method - const int* restrict data_it = detData_up.data(); - for (int index = 0, datum = 0; index < num_unique_up_dets; index++) - { - const int k = data_it[datum]; - - if (k == 0) - { - datum += 3 * k + 1; - } - - else - { - //Number of rows and cols of P^T - const int prows = k; - const int pcols = nel; - //Number of rows and cols of Q - const int qrows = nmo; - const int qcols = k; - - Y5.resize(nel, k); - Y6.resize(k, k); - - //Any matrix multiplication of P^T or Q is simply a projection - //Explicit matrix multiplication can be avoided; instead column or row copying can be done - //BlAS::copy(size of col/row being copied, - // Matrix pointer + place to begin copying, - // storage spacing (number of elements btw next row/col element), - // Pointer to resultant matrix + place to begin pasting, - // storage spacing of resultant matrix) - //For example the next 4 lines is the matrix multiplication of T*Q = Y5 - std::fill(Y5.begin(), Y5.end(), 0.0); - for (int i = 0; i < k; i++) - { - BLAS::copy(nel, T + data_it[datum + 1 + k + i], nmo, Y5.data() + i, k); - } - - std::fill(Y6.begin(), Y6.end(), 0.0); - for (int i = 0; i < k; i++) - { - BLAS::copy(k, Y5.data() + (data_it[datum + 1 + i]) * k, 1, (Y6.data() + i * k), 1); - } - - - Vector WS; - Vector Piv; - WS.resize(k); - Piv.resize(k); - RealType PhaseR = 0.0; - InvertWithLog(Y6.data(), k, k, WS.data(), Piv.data(), PhaseR); - - Y11.resize(nel, k); - Y23.resize(k, k); - Y24.resize(k, k); - Y25.resize(k, k); - Y26.resize(k, nel); - - std::fill(Y11.begin(), Y11.end(), 0.0); - for (int i = 0; i < k; i++) - { - BLAS::copy(nel, Y4.data() + (data_it[datum + 1 + k + i]), nmo, Y11.data() + i, k); - } - - std::fill(Y23.begin(), Y23.end(), 0.0); - for (int i = 0; i < k; i++) - { - BLAS::copy(k, Y11.data() + (data_it[datum + 1 + i]) * k, 1, (Y23.data() + i * k), 1); - } - - BLAS::gemm('N', 'N', k, k, k, RealType(1.0), Y23.data(), k, Y6.data(), k, RealType(0.0), Y24.data(), k); - BLAS::gemm('N', 'N', k, k, k, RealType(1.0), Y6.data(), k, Y24.data(), k, RealType(0.0), Y25.data(), k); - - - Y26.resize(k, nel); - - std::fill(Y26.begin(), Y26.end(), 0.0); - for (int i = 0; i < k; i++) - { - BLAS::copy(k, Y25.data() + i, k, Y26.data() + (data_it[datum + 1 + i]), nel); - } - - - Y7.resize(k, nel); - - std::fill(Y7.begin(), Y7.end(), 0.0); - for (int i = 0; i < k; i++) - { - BLAS::copy(k, Y6.data() + i, k, Y7.data() + (data_it[datum + 1 + i]), nel); - } - - // c_Tr_AlphaI_MI is a constant contributing to constant const2 - // c_Tr_AlphaI_MI = Tr[\alpha_{I}^{-1}(P^{T}\widetilde{M} Q)] - RealType c_Tr_AlphaI_MI = 0.0; - for (int i = 0; i < k; i++) - { - c_Tr_AlphaI_MI += Y24(i, i); - } - - for (int p = 0; p < lookup_tbl[index].size(); p++) - { - //el_p is the element position that contains information about the CI coefficient, and det up/dn values associated with the current unique determinant - const int el_p(lookup_tbl[index][p]); - const RealType c = cptr[el_p]; - const size_t up = upC[el_p]; - const size_t down = dnC[el_p]; - - const RealType alpha_1(c * detValues_dn[down] * detValues_up[up] / detValues_up[0] * c_Tr_AlphaI_MI); - const RealType alpha_2(c * detValues_dn[down] * detValues_up[up] / detValues_up[0]); - const RealType alpha_3(c * Oi[down] * detValues_up[up] / detValues_up[0]); - const RealType alpha_4(c * detValues_dn[down] * detValues_up[up] * (1 / psiCurrent)); - - const2 += alpha_1; - - for (int i = 0; i < k; i++) - { - BLAS::axpy(nel, alpha_1, Y7.data() + i * nel, 1, pK1.data() + (data_it[datum + 1 + k + i]) * nel, 1); - BLAS::axpy(nel, alpha_2, Y7.data() + i * nel, 1, pK2.data() + (data_it[datum + 1 + k + i]) * nel, 1); - BLAS::axpy(nel, alpha_3, Y7.data() + i * nel, 1, pK3.data() + (data_it[datum + 1 + k + i]) * nel, 1); - BLAS::axpy(nel, alpha_4, Y7.data() + i * nel, 1, pK4.data() + (data_it[datum + 1 + k + i]) * nel, 1); - BLAS::axpy(nel, alpha_2, Y26.data() + i * nel, 1, pK5.data() + (data_it[datum + 1 + k + i]) * nel, 1); - } - } - datum += 3 * k + 1; - } - } - - - BLAS::gemm('N', 'N', nmo, nmo, nel, 1.0 / const0, T, nmo, pK1.data(), nel, RealType(0.0), K1T.data(), nmo); - BLAS::gemm('N', 'N', nmo, nel, nmo, RealType(1.0), K1T.data(), nmo, T, nmo, RealType(0.0), TK1T.data(), nmo); - - BLAS::gemm('N', 'N', nmo, nmo, nel, 1.0 / const0, Y3.data(), nmo, pK2.data(), nel, RealType(0.0), K2AiB.data(), nmo); - BLAS::gemm('N', 'N', nmo, nel, nmo, RealType(1.0), K2AiB.data(), nmo, T, nmo, RealType(0.0), TK2AiB.data(), nmo); - BLAS::gemm('N', 'N', nmo, nmo, nel, 1.0 / const0, Y2.data(), nmo, pK2.data(), nel, RealType(0.0), K2XA.data(), nmo); - BLAS::gemm('N', 'N', nmo, nel, nmo, RealType(1.0), K2XA.data(), nmo, T, nmo, RealType(0.0), TK2XA.data(), nmo); - - BLAS::gemm('N', 'N', nmo, nmo, nel, const1 / (const0 * const0), T, nmo, pK2.data(), nel, RealType(0.0), K2T.data(), - nmo); - BLAS::gemm('N', 'N', nmo, nel, nmo, RealType(1.0), K2T.data(), nmo, T, nmo, RealType(0.0), TK2T.data(), nmo); - BLAS::gemm('N', 'N', nmo, nel, nmo, const0 / const1, K2T.data(), nmo, Y4.data(), nmo, RealType(0.0), MK2T.data(), - nmo); - - BLAS::gemm('N', 'N', nmo, nmo, nel, 1.0 / const0, T, nmo, pK3.data(), nel, RealType(0.0), K3T.data(), nmo); - BLAS::gemm('N', 'N', nmo, nel, nmo, RealType(1.0), K3T.data(), nmo, T, nmo, RealType(0.0), TK3T.data(), nmo); - - BLAS::gemm('N', 'N', nmo, nmo, nel, RealType(1.0), T, nmo, pK4.data(), nel, RealType(0.0), K4T.data(), nmo); - BLAS::gemm('N', 'N', nmo, nel, nmo, RealType(1.0), K4T.data(), nmo, T, nmo, RealType(0.0), TK4T.data(), nmo); - - BLAS::gemm('N', 'N', nmo, nmo, nel, 1.0 / const0, T, nmo, pK5.data(), nel, RealType(0.0), K5T.data(), nmo); - BLAS::gemm('N', 'N', nmo, nel, nmo, RealType(1.0), K5T.data(), nmo, T, nmo, RealType(0.0), TK5T.data(), nmo); - - - for (int mu = 0, k = parameter_start_index; k < (parameter_start_index + parameters_size); k++, mu++) - { - int kk = myVars.where(k); - const int i(m_act_rot_inds[mu].first), j(m_act_rot_inds[mu].second); - if (i <= nel - 1 && j > nel - 1) - { - dlogpsi[kk] += ValueType( detValues_up[0] * (Table(i, j)) * const0 * (1 / psiCurrent) + (K4T(i, j) - K4T(j, i) - TK4T(i, j)) ); - - dhpsioverpsi[kk] += ValueType( -0.5 * Y4(i, j) - - 0.5 * - (-K5T(i, j) + K5T(j, i) + TK5T(i, j) + K2AiB(i, j) - K2AiB(j, i) - TK2AiB(i, j) - K2XA(i, j) + - K2XA(j, i) + TK2XA(i, j) - MK2T(i, j) + K1T(i, j) - K1T(j, i) - TK1T(i, j) - - const2 / const1 * K2T(i, j) + const2 / const1 * K2T(j, i) + const2 / const1 * TK2T(i, j) + K3T(i, j) - - K3T(j, i) - TK3T(i, j) - K2T(i, j) + K2T(j, i) + TK2T(i, j)) ); - } - else if (i <= nel - 1 && j <= nel - 1) - { - dlogpsi[kk] += ValueType( detValues_up[0] * (Table(i, j) - Table(j, i)) * const0 * (1 / psiCurrent) + - (K4T(i, j) - TK4T(i, j) - K4T(j, i) + TK4T(j, i)) ); - - dhpsioverpsi[kk] += ValueType( -0.5 * (Y4(i, j) - Y4(j, i)) - - 0.5 * - (-K5T(i, j) + K5T(j, i) + TK5T(i, j) - TK5T(j, i) + K2AiB(i, j) - K2AiB(j, i) - TK2AiB(i, j) + - TK2AiB(j, i) - K2XA(i, j) + K2XA(j, i) + TK2XA(i, j) - TK2XA(j, i) - MK2T(i, j) + MK2T(j, i) + - K1T(i, j) - K1T(j, i) - TK1T(i, j) + TK1T(j, i) - const2 / const1 * K2T(i, j) + - const2 / const1 * K2T(j, i) + const2 / const1 * TK2T(i, j) - const2 / const1 * TK2T(j, i) + K3T(i, j) - - K3T(j, i) - TK3T(i, j) + TK3T(j, i) - K2T(i, j) + K2T(j, i) + TK2T(i, j) - TK2T(j, i)) ); - } - else - { - dlogpsi[kk] += ValueType( (K4T(i, j) - K4T(j, i)) ); - - dhpsioverpsi[kk] += ValueType( -0.5 * - (-K5T(i, j) + K5T(j, i) + K2AiB(i, j) - K2AiB(j, i) - K2XA(i, j) + K2XA(j, i) - - + K1T(i, j) - K1T(j, i) - const2 / const1 * K2T(i, j) + const2 / const1 * K2T(j, i) + K3T(i, j) - K3T(j, i) - - K2T(i, j) + K2T(j, i)) ); - } - } -} -#endif // !defined(QMC_COMPLEX) - } // namespace qmcplusplus diff --git a/src/QMCWaveFunctions/lcao/LCAOrbitalSet.h b/src/QMCWaveFunctions/lcao/LCAOrbitalSet.h index d5348c3c4..9a2b32f7d 100644 --- a/src/QMCWaveFunctions/lcao/LCAOrbitalSet.h +++ b/src/QMCWaveFunctions/lcao/LCAOrbitalSet.h @@ -42,12 +42,6 @@ public: std::shared_ptr C; /// a copy of the original C before orbital rotation is applied; ValueMatrix_t C_copy; - /// Scratch space for the initial coefficents before the rotation is applied - ValueMatrix_t m_init_B; - /// true if SPO parameters (orbital rotation parameters) have been supplied by input - bool params_supplied; - /// list of supplied orbital rotation parameters - std::vector params; ///true if C is an identity matrix bool Identity; @@ -70,8 +64,6 @@ public: //Nbasis x [1(value)+3(gradient)+6(hessian)+10(grad_hessian)] vghgh_type Tempghv; - //vector that contains active orbital rotation parameter indices - std::vector> m_act_rot_inds; /** constructor * @param bs pointer to the BasisSet */ @@ -85,64 +77,20 @@ public: void applyRotation(const ValueMatrix_t& rot_mat, bool use_stored_copy); - /// create optimizable orbital rotation parameters - void buildOptVariables(const std::vector>& rotations); - - void evaluateDerivatives(ParticleSet& P, - const opt_variables_type& optvars, - std::vector& dlogpsi, - std::vector& dhpsioverpsi, - const ValueType& psiCurrent, - const std::vector& Coeff, - const std::vector& C2node_up, - const std::vector& C2node_dn, - const ValueVector_t& detValues_up, - const ValueVector_t& detValues_dn, - const GradMatrix_t& grads_up, - const GradMatrix_t& grads_dn, - const ValueMatrix_t& lapls_up, - const ValueMatrix_t& lapls_dn, - const ValueMatrix_t& M_up, - const ValueMatrix_t& M_dn, - const ValueMatrix_t& Minv_up, - const ValueMatrix_t& Minv_dn, - const GradMatrix_t& B_grad, - const ValueMatrix_t& B_lapl, - const std::vector& detData_up, - const size_t N1, - const size_t N2, - const size_t NP1, - const size_t NP2, - const std::vector>& lookup_tbl); - void checkInVariables(opt_variables_type& active) { - if (Optimizable) - if (myVars.size()) - active.insertFrom(myVars); + APP_ABORT("LCAOrbitalSet should not call checkInVariables"); } void checkOutVariables(const opt_variables_type& active) { - if (Optimizable) - myVars.getIndex(active); + APP_ABORT("LCAOrbitalSet should not call checkOutVariables"); } ///reset void resetParameters(const opt_variables_type& active) { -#if !defined(QMC_COMPLEX) - if (Optimizable) - { - std::vector param(m_act_rot_inds.size()); - for (int i = 0; i < m_act_rot_inds.size(); i++) - { - int loc = myVars.where(i); - param[i] = myVars[i] = active[loc]; - } - apply_rotation(param); - } -#endif + APP_ABORT("LCAOrbitalSet should not call resetParameters"); } ///reset the target particleset @@ -333,44 +281,6 @@ private: GradMatrix_t& dllogdet) const; -#if !defined(QMC_COMPLEX) - //function to perform orbital rotations - void apply_rotation(const std::vector& param); - - //helper function to apply_rotation - void exponentiate_antisym_matrix(ValueMatrix_t& mat); - - - //helper function to evaluatederivative; evaluate orbital rotation parameter derivative using table method - void table_method_eval(std::vector& dlogpsi, - std::vector& dhpsioverpsi, - const ParticleSet::ParticleLaplacian_t& myL_J, - const ParticleSet::ParticleGradient_t& myG_J, - const size_t nel, - const size_t nmo, - const ValueType& psiCurrent, - const std::vector& Coeff, - const std::vector& C2node_up, - const std::vector& C2node_dn, - const ValueVector_t& detValues_up, - const ValueVector_t& detValues_dn, - const GradMatrix_t& grads_up, - const GradMatrix_t& grads_dn, - const ValueMatrix_t& lapls_up, - const ValueMatrix_t& lapls_dn, - const ValueMatrix_t& M_up, - const ValueMatrix_t& M_dn, - const ValueMatrix_t& Minv_up, - const ValueMatrix_t& Minv_dn, - const GradMatrix_t& B_grad, - const ValueMatrix_t& B_lapl, - const std::vector& detData_up, - const size_t N1, - const size_t N2, - const size_t NP1, - const size_t NP2, - const std::vector>& lookup_tbl); -#endif }; } // namespace qmcplusplus #endif diff --git a/tests/molecules/H4_ae/H4.wfs_3.xml b/tests/molecules/H4_ae/H4.wfs_3.xml index 401683c16..19c6f2713 100644 --- a/tests/molecules/H4_ae/H4.wfs_3.xml +++ b/tests/molecules/H4_ae/H4.wfs_3.xml @@ -1,9 +1,9 @@ - - + + - + @@ -12,42 +12,41 @@ - - - - - 5.04668000000000e-01 4.50114000000000e-01 3.58423000000000e-01 1.26449000000000e-01 - -2.40452000000000e-01 -3.20413000000000e-01 4.66777000000000e-01 7.03549000000000e-01 - 8.80080000000000e-02 -5.04842000000000e-01 8.07522000000000e-01 -7.19301000000000e-01 - 1.03323500000000e+00 -8.77213000000000e-01 -3.90492000000000e-01 2.12318000000000e-01 - - + + + + -6.2352e-02 1.5072e-02 8.3825e-02 -2.4339e-02 - + - - - - 5.04668000000000e-01 4.50114000000000e-01 3.58423000000000e-01 1.26449000000000e-01 - -2.40452000000000e-01 -3.20413000000000e-01 4.66777000000000e-01 7.03549000000000e-01 - 8.80080000000000e-02 -5.04842000000000e-01 8.07522000000000e-01 -7.19301000000000e-01 - 1.03323500000000e+00 -8.77213000000000e-01 -3.90492000000000e-01 2.12318000000000e-01 - - + + + -6.2352e-02 1.5072e-02 8.3825e-02 -2.4339e-02 - + + + + + + 5.04668000000000e-01 4.50114000000000e-01 3.58423000000000e-01 1.26449000000000e-01 + -2.40452000000000e-01 -3.20413000000000e-01 4.66777000000000e-01 7.03549000000000e-01 + 8.80080000000000e-02 -5.04842000000000e-01 8.07522000000000e-01 -7.19301000000000e-01 + 1.03323500000000e+00 -8.77213000000000e-01 -3.90492000000000e-01 2.12318000000000e-01 + + + - + 2.2381e-02 1.5167e-01 1.0912e-01 @@ -61,7 +60,7 @@ - + 4.7842e-01 3.9434e-01 3.2027e-01 @@ -75,9 +74,10 @@ + - + 2.5151e-02 1.4825e-01 1.6955e-01 @@ -91,5 +91,6 @@ + From 55d98241be541bcc29899fde5f32c59396f5cd71 Mon Sep 17 00:00:00 2001 From: Sergio Daniel Pineda Flores Date: Wed, 16 Oct 2019 15:59:47 -0600 Subject: [PATCH 12/41] Updated header guard for RotationHelper; Added license to both cpp and h files of RotationHelper; Removed unnecessary inclusions in RotationHelper.h --- src/QMCWaveFunctions/RotationHelper.cpp | 12 ++++++++++++ src/QMCWaveFunctions/RotationHelper.h | 20 +++++++++++++------- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/QMCWaveFunctions/RotationHelper.cpp b/src/QMCWaveFunctions/RotationHelper.cpp index cf82072aa..f9778edd9 100644 --- a/src/QMCWaveFunctions/RotationHelper.cpp +++ b/src/QMCWaveFunctions/RotationHelper.cpp @@ -1,5 +1,17 @@ +////////////////////////////////////////////////////////////////////////////////////// +//// This file is distributed under the University of Illinois/NCSA Open Source License. +//// See LICENSE file in top directory for details. +//// +//// Copyright (c) 2016 Jeongnim Kim and QMCPACK developers. +//// +//// File developed by: Sergio D. Pineda Flores, sergio_pinedaflores@berkeley.edu, University of California, Berkeley +//// Eric Neuscamman, eneuscamman@berkeley.edu, University of California, Berkeley +//// +//// File created by: Sergio D. Pineda Flores, sergio_pinedaflores@berkeley.edu, University of California, Berkeley +//////////////////////////////////////////////////////////////////////////////////////// #include "QMCWaveFunctions/RotationHelper.h" #include +#include "Numerics/DeterminantOperators.h" #include "Numerics/OhmmsBlas.h" diff --git a/src/QMCWaveFunctions/RotationHelper.h b/src/QMCWaveFunctions/RotationHelper.h index 63784516b..ca36fd962 100644 --- a/src/QMCWaveFunctions/RotationHelper.h +++ b/src/QMCWaveFunctions/RotationHelper.h @@ -1,12 +1,18 @@ -#ifndef ROTATION_HELPER_H -#define ROTATION_HELPER_H +////////////////////////////////////////////////////////////////////////////////////// +//// This file is distributed under the University of Illinois/NCSA Open Source License. +//// See LICENSE file in top directory for details. +//// +//// Copyright (c) 2016 Jeongnim Kim and QMCPACK developers. +//// +//// File developed by: Sergio D. Pineda Flores, sergio_pinedaflores@berkeley.edu, University of California, Berkeley +//// Eric Neuscamman, eneuscamman@berkeley.edu, University of California, Berkeley +//// +//// File created by: Sergio D. Pineda Flores, sergio_pinedaflores@berkeley.edu, University of California, Berkeley +//////////////////////////////////////////////////////////////////////////////////////// +#ifndef QMCPLUSPLUS_ROTATION_HELPER_H +#define QMCPLUSPLUS_ROTATION_HELPER_H #include "QMCWaveFunctions/SPOSet.h" -#include -#include "QMCWaveFunctions/BasisSetBase.h" - -#include -#include "Numerics/DeterminantOperators.h" namespace qmcplusplus From 7265366f38dc45cf871e56821effeaf11db30de1 Mon Sep 17 00:00:00 2001 From: Juha Tiihonen Date: Fri, 18 Oct 2019 14:25:15 -0400 Subject: [PATCH 13/41] Add necessary force attribute to nexus --- nexus/lib/qmcpack_input.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nexus/lib/qmcpack_input.py b/nexus/lib/qmcpack_input.py index 3b58b114e..ae976ff63 100644 --- a/nexus/lib/qmcpack_input.py +++ b/nexus/lib/qmcpack_input.py @@ -2036,7 +2036,7 @@ class hamiltonian(QIxml): class coulomb(QIxml): tag = 'pairpot' - attributes = ['type','name','source','target','physical'] + attributes = ['type','name','source','target','physical','forces'] write_types = obj(physical=yesno) identifier = 'name' #end class coulomb From 35dc0ad2c8680aa96541194d6ae02694247ad6e7 Mon Sep 17 00:00:00 2001 From: Ye Luo Date: Fri, 18 Oct 2019 14:06:27 -0500 Subject: [PATCH 14/41] Adjust input. --- tests/molecules/H4_ae/H4.wfs_2.xml | 38 ++++++----------- tests/molecules/H4_ae/H4.wfs_3.xml | 68 ++++++------------------------ 2 files changed, 28 insertions(+), 78 deletions(-) diff --git a/tests/molecules/H4_ae/H4.wfs_2.xml b/tests/molecules/H4_ae/H4.wfs_2.xml index 88f6b44f1..6da53f596 100644 --- a/tests/molecules/H4_ae/H4.wfs_2.xml +++ b/tests/molecules/H4_ae/H4.wfs_2.xml @@ -12,31 +12,21 @@ + + + + 5.04668000000000e-01 4.50114000000000e-01 3.58423000000000e-01 1.26449000000000e-01 + -2.40452000000000e-01 -3.20413000000000e-01 4.66777000000000e-01 7.03549000000000e-01 + 8.80080000000000e-02 -5.04842000000000e-01 8.07522000000000e-01 -7.19301000000000e-01 + 1.03323500000000e+00 -8.77213000000000e-01 -3.90492000000000e-01 2.12318000000000e-01 + + + 0.2 0.0 0.0 0.0 + + - - - - 5.04668000000000e-01 4.50114000000000e-01 3.58423000000000e-01 1.26449000000000e-01 - -2.40452000000000e-01 -3.20413000000000e-01 4.66777000000000e-01 7.03549000000000e-01 - 8.80080000000000e-02 -5.04842000000000e-01 8.07522000000000e-01 -7.19301000000000e-01 - 1.03323500000000e+00 -8.77213000000000e-01 -3.90492000000000e-01 2.12318000000000e-01 - - -0.2 0.0 0.0 0.0 - - - - - - 5.04668000000000e-01 4.50114000000000e-01 3.58423000000000e-01 1.26449000000000e-01 - -2.40452000000000e-01 -3.20413000000000e-01 4.66777000000000e-01 7.03549000000000e-01 - 8.80080000000000e-02 -5.04842000000000e-01 8.07522000000000e-01 -7.19301000000000e-01 - 1.03323500000000e+00 -8.77213000000000e-01 -3.90492000000000e-01 2.12318000000000e-01 - - -0.2 0.0 0.0 0.0 - - + + diff --git a/tests/molecules/H4_ae/H4.wfs_3.xml b/tests/molecules/H4_ae/H4.wfs_3.xml index 19c6f2713..0769f8c28 100644 --- a/tests/molecules/H4_ae/H4.wfs_3.xml +++ b/tests/molecules/H4_ae/H4.wfs_3.xml @@ -12,27 +12,6 @@ - - - - - -6.2352e-02 - 1.5072e-02 - 8.3825e-02 - -2.4339e-02 - - - - - - -6.2352e-02 - 1.5072e-02 - 8.3825e-02 - -2.4339e-02 - - - - @@ -40,54 +19,35 @@ -2.40452000000000e-01 -3.20413000000000e-01 4.66777000000000e-01 7.03549000000000e-01 8.80080000000000e-02 -5.04842000000000e-01 8.07522000000000e-01 -7.19301000000000e-01 1.03323500000000e+00 -8.77213000000000e-01 -3.90492000000000e-01 2.12318000000000e-01 - + + + -6.2352e-02 1.5072e-02 8.3825e-02 -2.4339e-02 + + + + + - - 2.2381e-02 - 1.5167e-01 - 1.0912e-01 - 1.0807e-01 - 8.1643e-02 - 6.1254e-02 - 4.3210e-02 - 2.7384e-02 - 1.5194e-02 - 6.3094e-03 + 2.2381e-02 1.5167e-01 1.0912e-01 1.0807e-01 8.1643e-02 + 6.1254e-02 4.3210e-02 2.7384e-02 1.5194e-02 6.3094e-03 - 4.7842e-01 - 3.9434e-01 - 3.2027e-01 - 2.5477e-01 - 1.9602e-01 - 1.4543e-01 - 1.0142e-01 - 6.4350e-02 - 3.4675e-02 - 1.3348e-02 + 4.7842e-01 3.9434e-01 3.2027e-01 2.5477e-01 1.9602e-01 + 1.4543e-01 1.0142e-01 6.4350e-02 3.4675e-02 1.3348e-02 - - 2.5151e-02 - 1.4825e-01 - 1.6955e-01 - 1.2869e-01 - 7.6468e-02 - 4.4240e-02 - 3.1098e-02 - 2.3827e-02 - 1.5289e-02 - 6.2995e-03 + 2.5151e-02 1.4825e-01 1.6955e-01 1.2869e-01 7.6468e-02 + 4.4240e-02 3.1098e-02 2.3827e-02 1.5289e-02 6.2995e-03 From 32c696906017a49b53012a11fce30e9beedf364e Mon Sep 17 00:00:00 2001 From: Ye Luo Date: Fri, 18 Oct 2019 16:30:09 -0500 Subject: [PATCH 15/41] Avoid unnecessary changes. --- src/QMCWaveFunctions/Fermion/DelayedUpdate.h | 4 ++-- src/QMCWaveFunctions/Fermion/DiracDeterminant.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/QMCWaveFunctions/Fermion/DelayedUpdate.h b/src/QMCWaveFunctions/Fermion/DelayedUpdate.h index 7130636d4..30c8367f3 100644 --- a/src/QMCWaveFunctions/Fermion/DelayedUpdate.h +++ b/src/QMCWaveFunctions/Fermion/DelayedUpdate.h @@ -128,7 +128,7 @@ public: { const T cminusone(-1); const T czero(0); - const int norb = Ainv.cols(); + const int norb = Ainv.rows(); const int lda_Binv = Binv.cols(); std::copy_n(Ainv[rowchanged], norb, V[delay_count]); std::copy_n(psiV.data(), norb, U[delay_count]); @@ -165,7 +165,7 @@ public: // update the inverse matrix const T cone(1); const T czero(0); - const int norb = Ainv.cols(); + const int norb = Ainv.rows(); if (delay_count == 1) { // this is a special case invoking the Fahy's variant of Sherman-Morrison update. diff --git a/src/QMCWaveFunctions/Fermion/DiracDeterminant.cpp b/src/QMCWaveFunctions/Fermion/DiracDeterminant.cpp index 9142057be..ccfd453f4 100644 --- a/src/QMCWaveFunctions/Fermion/DiracDeterminant.cpp +++ b/src/QMCWaveFunctions/Fermion/DiracDeterminant.cpp @@ -45,7 +45,7 @@ void DiracDeterminant::set(int first, int nel, int delay) FirstIndex = first; ndelay = delay; - resize(nel, Phi->getOrbitalSetSize()); + resize(nel, nel); if(Optimizable) Phi->buildOptVariables(nel); From 0329a857c9f586639fe7839bb58ab4cb57463780 Mon Sep 17 00:00:00 2001 From: Ye Luo Date: Fri, 18 Oct 2019 16:31:07 -0500 Subject: [PATCH 16/41] Define OrbitalSetSize for RotationHelper. --- src/QMCWaveFunctions/RotationHelper.cpp | 27 ++++++++++++++++--------- src/QMCWaveFunctions/RotationHelper.h | 8 +++++++- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/src/QMCWaveFunctions/RotationHelper.cpp b/src/QMCWaveFunctions/RotationHelper.cpp index f9778edd9..9d27528da 100644 --- a/src/QMCWaveFunctions/RotationHelper.cpp +++ b/src/QMCWaveFunctions/RotationHelper.cpp @@ -21,7 +21,7 @@ RotationHelper::RotationHelper(SPOSet* spos) : SPOSet(spos->hasIonDerivs(), true), Phi(spos), params_supplied(false), IsCloned(false) { className = "RotationHelper"; - OrbitalSetSize = Phi->getOrbitalSetSize(); + OrbitalSetSize = 0; } RotationHelper::~RotationHelper() {} @@ -29,18 +29,26 @@ RotationHelper::~RotationHelper() {} void RotationHelper::buildOptVariables(const size_t& nel) { #if !defined(QMC_COMPLEX) - const size_t nmo = Phi->getOrbitalSetSize(); + /* Only rebuild optimized variables if more after-rotation orbitals are needed + * Consider ROHF, there is only one set of SPO for both spin up and down Nup > Ndown. + * OrbitalSetSize will be set Nup. + */ + if (nel > OrbitalSetSize) + { + OrbitalSetSize = nel; - // create active rotation parameter indices - std::vector> created_m_act_rot_inds; + const size_t nmo = Phi->getOrbitalSetSize(); - // only core->active rotations created - for (int i = 0; i < nel; i++) - for (int j = nel; j < nmo; j++) - created_m_act_rot_inds.push_back(std::pair(i, j)); + // create active rotation parameter indices + std::vector> created_m_act_rot_inds; - buildOptVariables(created_m_act_rot_inds); + // only core->active rotations created + for (int i = 0; i < nel; i++) + for (int j = nel; j < nmo; j++) + created_m_act_rot_inds.push_back(std::pair(i, j)); + buildOptVariables(created_m_act_rot_inds); + } #endif } @@ -64,6 +72,7 @@ void RotationHelper::buildOptVariables(const std::vector>& r APP_ABORT("The number of supplied orbital rotation parameters does not match number prdouced by the slater " "expansion. \n"); + myVars.clear(); for (int i = 0; i < nparams_active; i++) { p = m_act_rot_inds[i].first; diff --git a/src/QMCWaveFunctions/RotationHelper.h b/src/QMCWaveFunctions/RotationHelper.h index ca36fd962..98413fab7 100644 --- a/src/QMCWaveFunctions/RotationHelper.h +++ b/src/QMCWaveFunctions/RotationHelper.h @@ -182,11 +182,16 @@ public: void checkObject() { Phi->checkObject(); } - void evaluate(const ParticleSet& P, int iat, ValueVector_t& psi) { Phi->evaluate(P, iat, psi); } + void evaluate(const ParticleSet& P, int iat, ValueVector_t& psi) + { + assert(psi.size() <= OrbitalSetSize); + Phi->evaluate(P, iat, psi); + } void evaluate(const ParticleSet& P, int iat, ValueVector_t& psi, GradVector_t& dpsi, ValueVector_t& d2psi) { + assert(psi.size() <= OrbitalSetSize); Phi->evaluate(P, iat, psi, dpsi, d2psi); } @@ -200,6 +205,7 @@ public: void evaluate(const ParticleSet& P, int iat, ValueVector_t& psi, GradVector_t& dpsi, HessVector_t& grad_grad_psi) { + assert(psi.size() <= OrbitalSetSize); Phi->evaluate(P, iat, psi, dpsi, grad_grad_psi); } From 9d3f49c260b513995b4dde41590a5dbafd95d3d7 Mon Sep 17 00:00:00 2001 From: Ye Luo Date: Fri, 18 Oct 2019 17:35:40 -0500 Subject: [PATCH 17/41] The number of orbitals evaluated based on output. Support up to OrbitalSetSize orbitals. --- src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp | 62 ++++++++++++++------- src/QMCWaveFunctions/tests/test_MO.cpp | 2 +- 2 files changed, 42 insertions(+), 22 deletions(-) diff --git a/src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp b/src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp index 66f925819..1593feab4 100644 --- a/src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp +++ b/src/QMCWaveFunctions/lcao/LCAOrbitalSet.cpp @@ -70,7 +70,9 @@ void LCAOrbitalSet::evaluate(const ParticleSet& P, int iat, ValueVector_t& psi) { Vector vTemp(Temp.data(0), BasisSetSize); myBasisSet->evaluateV(P, iat, vTemp.data()); - simd::gemv(*C, Temp.data(0), psi.data()); + assert(psi.size() <= OrbitalSetSize); + ValueMatrix_t C_partial_view(C->data(), psi.size(), BasisSetSize); + simd::gemv(C_partial_view, vTemp.data(), psi.data()); } } @@ -91,17 +93,18 @@ inline void LCAOrbitalSet::evaluate_vgl_impl(const vgl_type& temp, GradVector_t& dpsi, ValueVector_t& d2psi) const { - std::copy_n(temp.data(0), OrbitalSetSize, psi.data()); + const size_t output_size = psi.size(); + std::copy_n(temp.data(0), output_size, psi.data()); const ValueType* restrict gx = temp.data(1); const ValueType* restrict gy = temp.data(2); const ValueType* restrict gz = temp.data(3); - for (size_t j = 0; j < OrbitalSetSize; j++) + for (size_t j = 0; j < output_size; j++) { dpsi[j][0] = gx[j]; dpsi[j][1] = gy[j]; dpsi[j][2] = gz[j]; } - std::copy_n(temp.data(4), OrbitalSetSize, d2psi.data()); + std::copy_n(temp.data(4), output_size, d2psi.data()); } inline void LCAOrbitalSet::evaluate_vgh_impl(const vgh_type& temp, @@ -109,7 +112,8 @@ inline void LCAOrbitalSet::evaluate_vgh_impl(const vgh_type& temp, GradVector_t& dpsi, HessVector_t& d2psi) const { - std::copy_n(temp.data(0), OrbitalSetSize, psi.data()); + const size_t output_size = psi.size(); + std::copy_n(temp.data(0), output_size, psi.data()); const ValueType* restrict gx = temp.data(1); const ValueType* restrict gy = temp.data(2); const ValueType* restrict gz = temp.data(3); @@ -120,7 +124,7 @@ inline void LCAOrbitalSet::evaluate_vgh_impl(const vgh_type& temp, const ValueType* restrict hyz = temp.data(8); const ValueType* restrict hzz = temp.data(9); - for (size_t j = 0; j < OrbitalSetSize; j++) + for (size_t j = 0; j < output_size; j++) { dpsi[j][0] = gx[j]; dpsi[j][1] = gy[j]; @@ -142,7 +146,8 @@ inline void LCAOrbitalSet::evaluate_vghgh_impl(const vghgh_type& temp, HessMatrix_t& d2psi, GGGMatrix_t& dghpsi) const { - std::copy_n(temp.data(0), OrbitalSetSize, psi[i]); + const size_t output_size = psi.cols(); + std::copy_n(temp.data(0), output_size, psi[i]); const ValueType* restrict gx = temp.data(1); const ValueType* restrict gy = temp.data(2); const ValueType* restrict gz = temp.data(3); @@ -163,7 +168,7 @@ inline void LCAOrbitalSet::evaluate_vghgh_impl(const vghgh_type& temp, const ValueType* restrict gh_yzz = temp.data(18); const ValueType* restrict gh_zzz = temp.data(19); - for (size_t j = 0; j < OrbitalSetSize; j++) + for (size_t j = 0; j < output_size; j++) { dpsi[i][j][0] = gx[j]; dpsi[i][j][1] = gy[j]; @@ -214,7 +219,8 @@ inline void LCAOrbitalSet::evaluate_vghgh_impl(const vghgh_type& temp, HessVector_t& d2psi, GGGVector_t& dghpsi) const { - std::copy_n(temp.data(0), OrbitalSetSize, psi.data()); + const size_t output_size = psi.size(); + std::copy_n(temp.data(0), output_size, psi.data()); const ValueType* restrict gx = temp.data(1); const ValueType* restrict gy = temp.data(2); const ValueType* restrict gz = temp.data(3); @@ -235,7 +241,7 @@ inline void LCAOrbitalSet::evaluate_vghgh_impl(const vghgh_type& temp, const ValueType* restrict gh_yzz = temp.data(18); const ValueType* restrict gh_zzz = temp.data(19); - for (size_t j = 0; j < OrbitalSetSize; j++) + for (size_t j = 0; j < output_size; j++) { dpsi[j][0] = gx[j]; dpsi[j][1] = gy[j]; @@ -293,7 +299,9 @@ void LCAOrbitalSet::evaluate(const ParticleSet& P, evaluate_vgl_impl(Temp, psi, dpsi, d2psi); else { - Product_ABt(Temp, *C, Tempv); + assert(psi.size() <= OrbitalSetSize); + ValueMatrix_t C_partial_view(C->data(), psi.size(), BasisSetSize); + Product_ABt(Temp, C_partial_view, Tempv); evaluate_vgl_impl(Tempv, psi, dpsi, d2psi); } } @@ -327,7 +335,9 @@ void LCAOrbitalSet::evaluate(const ParticleSet& P, evaluate_vgh_impl(Temph, psi, dpsi, dhpsi); else { - Product_ABt(Temph, *C, Temphv); + assert(psi.size() <= OrbitalSetSize); + ValueMatrix_t C_partial_view(C->data(), psi.size(), BasisSetSize); + Product_ABt(Temph, C_partial_view, Temphv); evaluate_vgh_impl(Temphv, psi, dpsi, dhpsi); } } @@ -347,7 +357,9 @@ void LCAOrbitalSet::evaluate(const ParticleSet& P, evaluate_vghgh_impl(Tempgh, psi, dpsi, dhpsi, dghpsi); else { - Product_ABt(Tempgh, *C, Tempghv); + assert(psi.size() <= OrbitalSetSize); + ValueMatrix_t C_partial_view(C->data(), psi.size(), BasisSetSize); + Product_ABt(Tempgh, C_partial_view, Tempghv); evaluate_vghgh_impl(Tempghv, psi, dpsi, dhpsi, dghpsi); } } @@ -359,17 +371,18 @@ inline void LCAOrbitalSet::evaluate_vgl_impl(const vgl_type& temp, GradMatrix_t& dlogdet, ValueMatrix_t& d2logdet) const { - std::copy_n(temp.data(0), OrbitalSetSize, logdet[i]); + const size_t output_size = logdet.cols(); + std::copy_n(temp.data(0), output_size, logdet[i]); const ValueType* restrict gx = temp.data(1); const ValueType* restrict gy = temp.data(2); const ValueType* restrict gz = temp.data(3); - for (size_t j = 0; j < OrbitalSetSize; j++) + for (size_t j = 0; j < output_size; j++) { dlogdet[i][j][0] = gx[j]; dlogdet[i][j][1] = gy[j]; dlogdet[i][j][2] = gz[j]; } - std::copy_n(temp.data(4), OrbitalSetSize, d2logdet[i]); + std::copy_n(temp.data(4), output_size, d2logdet[i]); } inline void LCAOrbitalSet::evaluate_vgh_impl(const vgh_type& temp, @@ -378,7 +391,8 @@ inline void LCAOrbitalSet::evaluate_vgh_impl(const vgh_type& temp, GradMatrix_t& dpsi, HessMatrix_t& d2psi) const { - std::copy_n(temp.data(0), OrbitalSetSize, psi[i]); + const size_t output_size = psi.cols(); + std::copy_n(temp.data(0), output_size, psi[i]); const ValueType* restrict gx = temp.data(1); const ValueType* restrict gy = temp.data(2); const ValueType* restrict gz = temp.data(3); @@ -389,7 +403,7 @@ inline void LCAOrbitalSet::evaluate_vgh_impl(const vgh_type& temp, const ValueType* restrict hyz = temp.data(8); const ValueType* restrict hzz = temp.data(9); - for (size_t j = 0; j < OrbitalSetSize; j++) + for (size_t j = 0; j < output_size; j++) { dpsi[i][j][0] = gx[j]; dpsi[i][j][1] = gy[j]; @@ -490,10 +504,12 @@ void LCAOrbitalSet::evaluate_notranspose(const ParticleSet& P, } else { + assert(logdet.cols() <= OrbitalSetSize); + ValueMatrix_t C_partial_view(C->data(), logdet.cols(), BasisSetSize); for (size_t i = 0, iat = first; iat < last; i++, iat++) { myBasisSet->evaluateVGL(P, iat, Temp); - Product_ABt(Temp, *C, Tempv); + Product_ABt(Temp, C_partial_view, Tempv); evaluate_vgl_impl(Tempv, i, logdet, dlogdet, d2logdet); } } @@ -516,10 +532,12 @@ void LCAOrbitalSet::evaluate_notranspose(const ParticleSet& P, } else { + assert(logdet.cols() <= OrbitalSetSize); + ValueMatrix_t C_partial_view(C->data(), logdet.cols(), BasisSetSize); for (size_t i = 0, iat = first; iat < last; i++, iat++) { myBasisSet->evaluateVGH(P, iat, Temph); - Product_ABt(Temph, *C, Temphv); + Product_ABt(Temph, C_partial_view, Temphv); evaluate_vgh_impl(Temphv, i, logdet, dlogdet, grad_grad_logdet); } } @@ -543,10 +561,12 @@ void LCAOrbitalSet::evaluate_notranspose(const ParticleSet& P, } else { + assert(logdet.cols() <= OrbitalSetSize); + ValueMatrix_t C_partial_view(C->data(), logdet.cols(), BasisSetSize); for (size_t i = 0, iat = first; iat < last; i++, iat++) { myBasisSet->evaluateVGHGH(P, iat, Tempgh); - Product_ABt(Tempgh, *C, Tempghv); + Product_ABt(Tempgh, C_partial_view, Tempghv); evaluate_vghgh_impl(Tempghv, i, logdet, dlogdet, grad_grad_logdet, grad_grad_grad_logdet); } } diff --git a/src/QMCWaveFunctions/tests/test_MO.cpp b/src/QMCWaveFunctions/tests/test_MO.cpp index bd66ba2bd..2d4cb653b 100644 --- a/src/QMCWaveFunctions/tests/test_MO.cpp +++ b/src/QMCWaveFunctions/tests/test_MO.cpp @@ -543,7 +543,7 @@ void test_HCN(bool transform) SPOSet::HessMatrix_t diongradpsi(elec.R.size(), sposet->getOrbitalSetSize()); SPOSet::GradMatrix_t dionlaplpsi(elec.R.size(), sposet->getOrbitalSetSize()); - sposet->evaluateGradSource(elec, 0, elec.R.size(),ions,0, dionpsi,diongradpsi,dionlaplpsi); + sposet->evaluateGradSource(elec, 0, elec.R.size(), ions, 0, dionpsi,diongradpsi,dionlaplpsi); //============== Ion 0 Component 0 =================== REQUIRE( dionpsi[0][0][0] == Approx( 0.0453112082) ); From 8a0070c77bf49372e9459e4767a22f4c0ed752d6 Mon Sep 17 00:00:00 2001 From: Ye Luo Date: Fri, 18 Oct 2019 17:57:04 -0500 Subject: [PATCH 18/41] Minor change. --- src/QMCWaveFunctions/Fermion/SlaterDetBuilder.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/QMCWaveFunctions/Fermion/SlaterDetBuilder.cpp b/src/QMCWaveFunctions/Fermion/SlaterDetBuilder.cpp index 4f660dff1..bc52d1c70 100644 --- a/src/QMCWaveFunctions/Fermion/SlaterDetBuilder.cpp +++ b/src/QMCWaveFunctions/Fermion/SlaterDetBuilder.cpp @@ -293,7 +293,8 @@ WaveFunctionComponent* SlaterDetBuilder::buildComponent(xmlNodePtr cur) app_log() << "Creating base determinant (up) for MSD expansion. \n"; up_det = new MultiDiracDeterminant((SPOSetPtr)spomap.find(spo_alpha)->second, 0); app_log() << "Creating base determinant (down) for MSD expansion. \n"; - dn_det = new MultiDiracDeterminant((SPOSetPtr)spomap.find(spo_beta)->second, 1); + dn_det = new MultiDiracDeterminant((SPOSetPtr)spomap.find(spo_beta)->second, 1); + multislaterdetfast_0 = new MultiSlaterDeterminantFast(targetPtcl, up_det, dn_det); success = createMSDFast(multislaterdetfast_0, cur); } From 3cd144fcced8ee16cfc33353e93a966159c915ec Mon Sep 17 00:00:00 2001 From: Ye Luo Date: Fri, 18 Oct 2019 18:47:26 -0500 Subject: [PATCH 19/41] Fix short-H4-msd-orb-opt-16-1. --- src/QMCWaveFunctions/RotationHelper.cpp | 12 ++++++------ src/QMCWaveFunctions/RotationHelper.h | 5 ++++- src/QMCWaveFunctions/SPOSet.h | 2 +- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/QMCWaveFunctions/RotationHelper.cpp b/src/QMCWaveFunctions/RotationHelper.cpp index 9d27528da..723a5cf35 100644 --- a/src/QMCWaveFunctions/RotationHelper.cpp +++ b/src/QMCWaveFunctions/RotationHelper.cpp @@ -18,24 +18,24 @@ namespace qmcplusplus { RotationHelper::RotationHelper(SPOSet* spos) - : SPOSet(spos->hasIonDerivs(), true), Phi(spos), params_supplied(false), IsCloned(false) + : SPOSet(spos->hasIonDerivs(), true), Phi(spos), params_supplied(false), IsCloned(false), nel_major_(0) { className = "RotationHelper"; - OrbitalSetSize = 0; + OrbitalSetSize = Phi->getOrbitalSetSize(); } RotationHelper::~RotationHelper() {} -void RotationHelper::buildOptVariables(const size_t& nel) +void RotationHelper::buildOptVariables(const size_t nel) { #if !defined(QMC_COMPLEX) /* Only rebuild optimized variables if more after-rotation orbitals are needed * Consider ROHF, there is only one set of SPO for both spin up and down Nup > Ndown. - * OrbitalSetSize will be set Nup. + * nel_major_ will be set Nup. */ - if (nel > OrbitalSetSize) + if (nel > nel_major_) { - OrbitalSetSize = nel; + nel_major_ = nel; const size_t nmo = Phi->getOrbitalSetSize(); diff --git a/src/QMCWaveFunctions/RotationHelper.h b/src/QMCWaveFunctions/RotationHelper.h index 98413fab7..954b1af76 100644 --- a/src/QMCWaveFunctions/RotationHelper.h +++ b/src/QMCWaveFunctions/RotationHelper.h @@ -44,6 +44,9 @@ public: bool IsCloned; + /// the number of electrons of the majority spin + size_t nel_major_; + SPOSet* makeClone() const; // myG_temp (myL_temp) is the Gradient (Laplacian) value of of the Determinant part of the wfn @@ -62,7 +65,7 @@ public: // Single Slater creation - void buildOptVariables(const size_t& nel); + void buildOptVariables(const size_t nel); // For the MSD case rotations must be created in MultiSlaterFast class void buildOptVariables(const std::vector>& rotations); diff --git a/src/QMCWaveFunctions/SPOSet.h b/src/QMCWaveFunctions/SPOSet.h index 45dd3235c..56d06b09d 100644 --- a/src/QMCWaveFunctions/SPOSet.h +++ b/src/QMCWaveFunctions/SPOSet.h @@ -138,7 +138,7 @@ public: /// create optimizable orbital rotation parameters // Single Slater creation - virtual void buildOptVariables(const size_t& nel) {} + virtual void buildOptVariables(const size_t nel) {} // For the MSD case rotations must be created in MultiSlaterFast class virtual void buildOptVariables(const std::vector>& rotations) {} // store parameters before getting destroyed by rotation. From 3af3431baf85d790f5718553f1e294d1471f4ccb Mon Sep 17 00:00:00 2001 From: Ye Luo Date: Fri, 18 Oct 2019 20:15:11 -0500 Subject: [PATCH 20/41] Add H4_UHF_orb_opt which matches AoS. --- tests/molecules/H4_ae/CMakeLists.txt | 15 ++++- tests/molecules/H4_ae/H4.wfs_2_UHF.xml | 58 +++++++++++++++++++ tests/molecules/H4_ae/H4_UHF_orb_opt.xml | 39 +++++++++++++ .../H4_ae/{h4_orb_opt.xml => H4_orb_opt.xml} | 0 ...{h4_orb_opt_dmc.xml => H4_orb_opt_dmc.xml} | 0 5 files changed, 109 insertions(+), 3 deletions(-) create mode 100644 tests/molecules/H4_ae/H4.wfs_2_UHF.xml create mode 100644 tests/molecules/H4_ae/H4_UHF_orb_opt.xml rename tests/molecules/H4_ae/{h4_orb_opt.xml => H4_orb_opt.xml} (100%) rename tests/molecules/H4_ae/{h4_orb_opt_dmc.xml => H4_orb_opt_dmc.xml} (100%) diff --git a/tests/molecules/H4_ae/CMakeLists.txt b/tests/molecules/H4_ae/CMakeLists.txt index 32b0931d6..1c05f32a8 100644 --- a/tests/molecules/H4_ae/CMakeLists.txt +++ b/tests/molecules/H4_ae/CMakeLists.txt @@ -87,7 +87,16 @@ IF (NOT QMC_CUDA) QMC_RUN_AND_CHECK(short-H4-orb-opt "${CMAKE_SOURCE_DIR}/tests/molecules/H4_ae" H4 - h4_orb_opt.xml + H4_orb_opt.xml + 16 1 + ${MP_SUCCESS} + 14 H4_ORB_OPT_SCALARS # Final VMC step + TRUE) + + QMC_RUN_AND_CHECK(short-H4-UHF-orb-opt + "${CMAKE_SOURCE_DIR}/tests/molecules/H4_ae" + H4 + H4_UHF_orb_opt.xml 16 1 ${MP_SUCCESS} 14 H4_ORB_OPT_SCALARS # Final VMC step @@ -102,7 +111,7 @@ IF (NOT QMC_CUDA) QMC_RUN_AND_CHECK(short-H4-orb-opt-dmc "${CMAKE_SOURCE_DIR}/tests/molecules/H4_ae" H4 - h4_orb_opt_dmc.xml + H4_orb_opt_dmc.xml 16 1 ${MP_SUCCESS} 3 H4_ORB_OPT_DMC_SCALARS # Test the DMC results @@ -111,7 +120,7 @@ IF (NOT QMC_CUDA) QMC_RUN_AND_CHECK(short-H4-orb-opt-dmc "${CMAKE_SOURCE_DIR}/tests/molecules/H4_ae" H4 - h4_orb_opt_dmc.xml + H4_orb_opt_dmc.xml 1 16 ${MP_SUCCESS} 3 H4_ORB_OPT_DMC_SCALARS # Test the DMC results diff --git a/tests/molecules/H4_ae/H4.wfs_2_UHF.xml b/tests/molecules/H4_ae/H4.wfs_2_UHF.xml new file mode 100644 index 000000000..1d7d6c675 --- /dev/null +++ b/tests/molecules/H4_ae/H4.wfs_2_UHF.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + 5.04668000000000e-01 4.50114000000000e-01 3.58423000000000e-01 1.26449000000000e-01 + -2.40452000000000e-01 -3.20413000000000e-01 4.66777000000000e-01 7.03549000000000e-01 + 8.80080000000000e-02 -5.04842000000000e-01 8.07522000000000e-01 -7.19301000000000e-01 + 1.03323500000000e+00 -8.77213000000000e-01 -3.90492000000000e-01 2.12318000000000e-01 + + + 0.2 0.0 0.0 0.0 + + + + + + 5.04668000000000e-01 4.50114000000000e-01 3.58423000000000e-01 1.26449000000000e-01 + -2.40452000000000e-01 -3.20413000000000e-01 4.66777000000000e-01 7.03549000000000e-01 + 8.80080000000000e-02 -5.04842000000000e-01 8.07522000000000e-01 -7.19301000000000e-01 + 1.03323500000000e+00 -8.77213000000000e-01 -3.90492000000000e-01 2.12318000000000e-01 + + + 0.2 0.0 0.0 0.0 + + + + + + + + + + 0.04661440939 0.0555644703 0.1286335481 0.1077457768 0.0811381484 0.0626555805 0.0436904683 0.02811397453 0.01572772511 0.006258753264 + + + 0.4465508582 0.3603308616 0.2893897103 0.2269436006 0.1717850082 0.1250275368 0.08538908372 0.05318480503 0.02806504868 0.01035981902 + + + + + 0.0167926566 0.1405038909 0.1611311956 0.1198446618 0.06764720157 0.03602453588 0.02460661286 0.01952889643 0.01300432967 0.005621933949 + + + + diff --git a/tests/molecules/H4_ae/H4_UHF_orb_opt.xml b/tests/molecules/H4_ae/H4_UHF_orb_opt.xml new file mode 100644 index 000000000..27522a640 --- /dev/null +++ b/tests/molecules/H4_ae/H4_UHF_orb_opt.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + 1 + 256 + 500 + 1 + 10 + 0.05 + 64000 + yes + mixed + 15.0 + + no + yes + adaptive + 1.0 + 1.0 + 1.0e-4 + 100.0 + 3.0e-1 + yes + -3.2 + + + diff --git a/tests/molecules/H4_ae/h4_orb_opt.xml b/tests/molecules/H4_ae/H4_orb_opt.xml similarity index 100% rename from tests/molecules/H4_ae/h4_orb_opt.xml rename to tests/molecules/H4_ae/H4_orb_opt.xml diff --git a/tests/molecules/H4_ae/h4_orb_opt_dmc.xml b/tests/molecules/H4_ae/H4_orb_opt_dmc.xml similarity index 100% rename from tests/molecules/H4_ae/h4_orb_opt_dmc.xml rename to tests/molecules/H4_ae/H4_orb_opt_dmc.xml From c06affac138e37d2c2621becf58c9c2192a98396 Mon Sep 17 00:00:00 2001 From: Ye Luo Date: Fri, 18 Oct 2019 21:17:22 -0500 Subject: [PATCH 21/41] Fix complex and mixed precision compilation. --- src/QMCWaveFunctions/CMakeLists.txt | 2 +- src/QMCWaveFunctions/RotationHelper.cpp | 6 +++--- src/QMCWaveFunctions/SPOSetBuilderFactory.cpp | 7 ++++++- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/QMCWaveFunctions/CMakeLists.txt b/src/QMCWaveFunctions/CMakeLists.txt index 18354f4ce..3739eb731 100644 --- a/src/QMCWaveFunctions/CMakeLists.txt +++ b/src/QMCWaveFunctions/CMakeLists.txt @@ -28,7 +28,6 @@ SET(WFBASE_SRCS SPOSetInfo.cpp SPOSetInputInfo.cpp SPOSet.cpp - RotationHelper.cpp CompositeSPOSet.cpp HarmonicOscillator/SHOSet.cpp HarmonicOscillator/SHOSetBuilder.cpp @@ -38,6 +37,7 @@ SET(WFBASE_SRCS IF(NOT QMC_COMPLEX) SET(WFBASE_SRCS ${WFBASE_SRCS} + RotationHelper.cpp FDLRWfn.cpp ) ENDIF(NOT QMC_COMPLEX) diff --git a/src/QMCWaveFunctions/RotationHelper.cpp b/src/QMCWaveFunctions/RotationHelper.cpp index 723a5cf35..823ca1473 100644 --- a/src/QMCWaveFunctions/RotationHelper.cpp +++ b/src/QMCWaveFunctions/RotationHelper.cpp @@ -275,9 +275,9 @@ void RotationHelper::evaluateDerivatives(ParticleSet& P, //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~PART2 - const double* const A(psiM_all.data()); - const double* const Ainv(psiM_inv.data()); - const double* const B(Bbar.data()); + const ValueType* const A(psiM_all.data()); + const ValueType* const Ainv(psiM_inv.data()); + const ValueType* const B(Bbar.data()); SPOSet::ValueMatrix_t T; SPOSet::ValueMatrix_t Y1; SPOSet::ValueMatrix_t Y2; diff --git a/src/QMCWaveFunctions/SPOSetBuilderFactory.cpp b/src/QMCWaveFunctions/SPOSetBuilderFactory.cpp index e9c7107dc..346ad99db 100644 --- a/src/QMCWaveFunctions/SPOSetBuilderFactory.cpp +++ b/src/QMCWaveFunctions/SPOSetBuilderFactory.cpp @@ -28,6 +28,7 @@ #include "QMCWaveFunctions/MolecularOrbitals/GTOBuilder.h" #include "QMCWaveFunctions/MolecularOrbitals/STOBuilder.h" #include "QMCWaveFunctions/MolecularOrbitals/MolecularSPOBuilder.h" +#include "QMCWaveFunctions/RotationHelper.h" #endif #endif @@ -35,7 +36,6 @@ #include "QMCWaveFunctions/EinsplineSetBuilder.h" #endif #endif -#include "QMCWaveFunctions/RotationHelper.h" #include "QMCWaveFunctions/CompositeSPOSet.h" #include "Utilities/ProgressReportEngine.h" #include "Utilities/IteratorUtility.h" @@ -286,6 +286,10 @@ SPOSet* SPOSetBuilderFactory::createSPOSet(xmlNodePtr cur) spo->objectName = sname; if (rotation == "yes") { +#ifdef QMC_COMPLEX + app_error() << "Orbital optimization via rotation doesn't support complex wavefunction yet.\n"; + abort(); +#else auto* rot_spo = new RotationHelper(spo); xmlNodePtr tcur = cur->xmlChildrenNode; while (tcur != NULL) @@ -300,6 +304,7 @@ SPOSet* SPOSetBuilderFactory::createSPOSet(xmlNodePtr cur) } spo = rot_spo; spo->objectName = sname; +#endif } return spo; } From c6d0bff4ebb2bcb62ff009390b433b631a362673 Mon Sep 17 00:00:00 2001 From: Ye Luo Date: Fri, 18 Oct 2019 21:51:26 -0500 Subject: [PATCH 22/41] Rename RotationHelper to RotatedSPOs. --- src/QMCWaveFunctions/CMakeLists.txt | 2 +- .../{RotationHelper.cpp => RotatedSPOs.cpp} | 26 +++++++++---------- .../{RotationHelper.h => RotatedSPOs.h} | 6 ++--- src/QMCWaveFunctions/SPOSetBuilderFactory.cpp | 7 +++-- 4 files changed, 22 insertions(+), 19 deletions(-) rename src/QMCWaveFunctions/{RotationHelper.cpp => RotatedSPOs.cpp} (97%) rename src/QMCWaveFunctions/{RotationHelper.h => RotatedSPOs.h} (99%) diff --git a/src/QMCWaveFunctions/CMakeLists.txt b/src/QMCWaveFunctions/CMakeLists.txt index 3739eb731..2fa66a201 100644 --- a/src/QMCWaveFunctions/CMakeLists.txt +++ b/src/QMCWaveFunctions/CMakeLists.txt @@ -37,7 +37,7 @@ SET(WFBASE_SRCS IF(NOT QMC_COMPLEX) SET(WFBASE_SRCS ${WFBASE_SRCS} - RotationHelper.cpp + RotatedSPOs.cpp FDLRWfn.cpp ) ENDIF(NOT QMC_COMPLEX) diff --git a/src/QMCWaveFunctions/RotationHelper.cpp b/src/QMCWaveFunctions/RotatedSPOs.cpp similarity index 97% rename from src/QMCWaveFunctions/RotationHelper.cpp rename to src/QMCWaveFunctions/RotatedSPOs.cpp index 823ca1473..d82fa6952 100644 --- a/src/QMCWaveFunctions/RotationHelper.cpp +++ b/src/QMCWaveFunctions/RotatedSPOs.cpp @@ -9,7 +9,7 @@ //// //// File created by: Sergio D. Pineda Flores, sergio_pinedaflores@berkeley.edu, University of California, Berkeley //////////////////////////////////////////////////////////////////////////////////////// -#include "QMCWaveFunctions/RotationHelper.h" +#include "QMCWaveFunctions/RotatedSPOs.h" #include #include "Numerics/DeterminantOperators.h" #include "Numerics/OhmmsBlas.h" @@ -17,16 +17,16 @@ namespace qmcplusplus { -RotationHelper::RotationHelper(SPOSet* spos) +RotatedSPOs::RotatedSPOs(SPOSet* spos) : SPOSet(spos->hasIonDerivs(), true), Phi(spos), params_supplied(false), IsCloned(false), nel_major_(0) { - className = "RotationHelper"; + className = "RotatedSPOs"; OrbitalSetSize = Phi->getOrbitalSetSize(); } -RotationHelper::~RotationHelper() {} +RotatedSPOs::~RotatedSPOs() {} -void RotationHelper::buildOptVariables(const size_t nel) +void RotatedSPOs::buildOptVariables(const size_t nel) { #if !defined(QMC_COMPLEX) /* Only rebuild optimized variables if more after-rotation orbitals are needed @@ -52,7 +52,7 @@ void RotationHelper::buildOptVariables(const size_t nel) #endif } -void RotationHelper::buildOptVariables(const std::vector>& rotations) +void RotatedSPOs::buildOptVariables(const std::vector>& rotations) { #if !defined(QMC_COMPLEX) const size_t nmo = Phi->getOrbitalSetSize(); @@ -116,7 +116,7 @@ void RotationHelper::buildOptVariables(const std::vector>& r #endif } -void RotationHelper::apply_rotation(const std::vector& param, bool use_stored_copy) +void RotatedSPOs::apply_rotation(const std::vector& param, bool use_stored_copy) { assert(param.size() == m_act_rot_inds.size()); @@ -142,7 +142,7 @@ void RotationHelper::apply_rotation(const std::vector& param, bool use // compute exponential of a real, antisymmetric matrix by diagonalizing and exponentiating eigenvalues -void RotationHelper::exponentiate_antisym_matrix(ValueMatrix_t& mat) +void RotatedSPOs::exponentiate_antisym_matrix(ValueMatrix_t& mat) { const int n = mat.rows(); std::vector> mat_h(n * n, 0); @@ -205,7 +205,7 @@ void RotationHelper::exponentiate_antisym_matrix(ValueMatrix_t& mat) } -void RotationHelper::evaluateDerivatives(ParticleSet& P, +void RotatedSPOs::evaluateDerivatives(ParticleSet& P, const opt_variables_type& optvars, std::vector& dlogpsi, std::vector& dhpsioverpsi, @@ -308,7 +308,7 @@ void RotationHelper::evaluateDerivatives(ParticleSet& P, } } -void RotationHelper::evaluateDerivatives(ParticleSet& P, +void RotatedSPOs::evaluateDerivatives(ParticleSet& P, const opt_variables_type& optvars, std::vector& dlogpsi, std::vector& dhpsioverpsi, @@ -399,7 +399,7 @@ void RotationHelper::evaluateDerivatives(ParticleSet& P, } } -void RotationHelper::table_method_eval(std::vector& dlogpsi, +void RotatedSPOs::table_method_eval(std::vector& dlogpsi, std::vector& dhpsioverpsi, const ParticleSet::ParticleLaplacian_t& myL_J, const ParticleSet::ParticleGradient_t& myG_J, @@ -849,9 +849,9 @@ $ } -SPOSet* RotationHelper::makeClone() const +SPOSet* RotatedSPOs::makeClone() const { - RotationHelper* myclone = new RotationHelper(Phi->makeClone()); + RotatedSPOs* myclone = new RotatedSPOs(Phi->makeClone()); myclone->IsCloned = true; myclone->params = this->params; diff --git a/src/QMCWaveFunctions/RotationHelper.h b/src/QMCWaveFunctions/RotatedSPOs.h similarity index 99% rename from src/QMCWaveFunctions/RotationHelper.h rename to src/QMCWaveFunctions/RotatedSPOs.h index 954b1af76..9cf4695dd 100644 --- a/src/QMCWaveFunctions/RotationHelper.h +++ b/src/QMCWaveFunctions/RotatedSPOs.h @@ -17,13 +17,13 @@ namespace qmcplusplus { -class RotationHelper : public SPOSet +class RotatedSPOs : public SPOSet { public: //constructor - RotationHelper(SPOSet* spos); + RotatedSPOs(SPOSet* spos); //destructor - ~RotationHelper(); + ~RotatedSPOs(); //vector that contains active orbital rotation parameter indices std::vector> m_act_rot_inds; diff --git a/src/QMCWaveFunctions/SPOSetBuilderFactory.cpp b/src/QMCWaveFunctions/SPOSetBuilderFactory.cpp index 346ad99db..e3c054201 100644 --- a/src/QMCWaveFunctions/SPOSetBuilderFactory.cpp +++ b/src/QMCWaveFunctions/SPOSetBuilderFactory.cpp @@ -28,10 +28,13 @@ #include "QMCWaveFunctions/MolecularOrbitals/GTOBuilder.h" #include "QMCWaveFunctions/MolecularOrbitals/STOBuilder.h" #include "QMCWaveFunctions/MolecularOrbitals/MolecularSPOBuilder.h" -#include "QMCWaveFunctions/RotationHelper.h" #endif #endif +#if !defined(QMC_COMPLEX) +#include "QMCWaveFunctions/RotatedSPOs.h" +#endif + #if defined(HAVE_EINSPLINE) #include "QMCWaveFunctions/EinsplineSetBuilder.h" #endif @@ -290,7 +293,7 @@ SPOSet* SPOSetBuilderFactory::createSPOSet(xmlNodePtr cur) app_error() << "Orbital optimization via rotation doesn't support complex wavefunction yet.\n"; abort(); #else - auto* rot_spo = new RotationHelper(spo); + auto* rot_spo = new RotatedSPOs(spo); xmlNodePtr tcur = cur->xmlChildrenNode; while (tcur != NULL) { From 3c92c66a13f9403e967f86d14173e28bb071713b Mon Sep 17 00:00:00 2001 From: Ye Luo Date: Fri, 18 Oct 2019 22:39:20 -0500 Subject: [PATCH 23/41] Add short-H4-orb-opt-1-16 --- src/QMCWaveFunctions/RotatedSPOs.cpp | 3 ++- src/QMCWaveFunctions/RotatedSPOs.h | 3 ++- tests/molecules/H2_ae/h2.wfn.xml | 15 +++------------ tests/molecules/H4_ae/CMakeLists.txt | 15 ++++++++++++--- tests/molecules/H4_ae/H4.wfs_2.xml | 18 +++++++++++++++--- .../{H4.wfs_2_UHF.xml => H4.wfs_2_RHF.xml} | 18 +++--------------- .../{H4_UHF_orb_opt.xml => H4_RHF_orb_opt.xml} | 2 +- 7 files changed, 38 insertions(+), 36 deletions(-) rename tests/molecules/H4_ae/{H4.wfs_2_UHF.xml => H4.wfs_2_RHF.xml} (75%) rename tests/molecules/H4_ae/{H4_UHF_orb_opt.xml => H4_RHF_orb_opt.xml} (97%) diff --git a/src/QMCWaveFunctions/RotatedSPOs.cpp b/src/QMCWaveFunctions/RotatedSPOs.cpp index d82fa6952..3f8144437 100644 --- a/src/QMCWaveFunctions/RotatedSPOs.cpp +++ b/src/QMCWaveFunctions/RotatedSPOs.cpp @@ -2,10 +2,11 @@ //// This file is distributed under the University of Illinois/NCSA Open Source License. //// See LICENSE file in top directory for details. //// -//// Copyright (c) 2016 Jeongnim Kim and QMCPACK developers. +//// Copyright (c) QMCPACK developers. //// //// File developed by: Sergio D. Pineda Flores, sergio_pinedaflores@berkeley.edu, University of California, Berkeley //// Eric Neuscamman, eneuscamman@berkeley.edu, University of California, Berkeley +//// Ye Luo, yeluo@anl.gov, Argonne National Laboratory //// //// File created by: Sergio D. Pineda Flores, sergio_pinedaflores@berkeley.edu, University of California, Berkeley //////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/QMCWaveFunctions/RotatedSPOs.h b/src/QMCWaveFunctions/RotatedSPOs.h index 9cf4695dd..87fb7f530 100644 --- a/src/QMCWaveFunctions/RotatedSPOs.h +++ b/src/QMCWaveFunctions/RotatedSPOs.h @@ -2,10 +2,11 @@ //// This file is distributed under the University of Illinois/NCSA Open Source License. //// See LICENSE file in top directory for details. //// -//// Copyright (c) 2016 Jeongnim Kim and QMCPACK developers. +//// Copyright (c) QMCPACK developers. //// //// File developed by: Sergio D. Pineda Flores, sergio_pinedaflores@berkeley.edu, University of California, Berkeley //// Eric Neuscamman, eneuscamman@berkeley.edu, University of California, Berkeley +//// Ye Luo, yeluo@anl.gov, Argonne National Laboratory //// //// File created by: Sergio D. Pineda Flores, sergio_pinedaflores@berkeley.edu, University of California, Berkeley //////////////////////////////////////////////////////////////////////////////////////// diff --git a/tests/molecules/H2_ae/h2.wfn.xml b/tests/molecules/H2_ae/h2.wfn.xml index 82539b71b..81278cb4c 100644 --- a/tests/molecules/H2_ae/h2.wfn.xml +++ b/tests/molecules/H2_ae/h2.wfn.xml @@ -34,18 +34,9 @@ - - - - 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 - - - - - - 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 - - + + + diff --git a/tests/molecules/H4_ae/CMakeLists.txt b/tests/molecules/H4_ae/CMakeLists.txt index 1c05f32a8..dd7176924 100644 --- a/tests/molecules/H4_ae/CMakeLists.txt +++ b/tests/molecules/H4_ae/CMakeLists.txt @@ -84,6 +84,15 @@ IF (NOT QMC_CUDA) # LIST(APPEND H4_ORB_OPT_SCALARS "totenergy" "-2.0889 0.001") # total energy + QMC_RUN_AND_CHECK(short-H4-RHF-orb-opt + "${CMAKE_SOURCE_DIR}/tests/molecules/H4_ae" + H4 + H4_RHF_orb_opt.xml + 16 1 + ${MP_SUCCESS} + 14 H4_ORB_OPT_SCALARS # Final VMC step + TRUE) + QMC_RUN_AND_CHECK(short-H4-orb-opt "${CMAKE_SOURCE_DIR}/tests/molecules/H4_ae" H4 @@ -93,11 +102,11 @@ IF (NOT QMC_CUDA) 14 H4_ORB_OPT_SCALARS # Final VMC step TRUE) - QMC_RUN_AND_CHECK(short-H4-UHF-orb-opt + QMC_RUN_AND_CHECK(short-H4-orb-opt "${CMAKE_SOURCE_DIR}/tests/molecules/H4_ae" H4 - H4_UHF_orb_opt.xml - 16 1 + H4_orb_opt.xml + 1 16 ${MP_SUCCESS} 14 H4_ORB_OPT_SCALARS # Final VMC step TRUE) diff --git a/tests/molecules/H4_ae/H4.wfs_2.xml b/tests/molecules/H4_ae/H4.wfs_2.xml index 6da53f596..1d7d6c675 100644 --- a/tests/molecules/H4_ae/H4.wfs_2.xml +++ b/tests/molecules/H4_ae/H4.wfs_2.xml @@ -12,7 +12,19 @@ - + + + + 5.04668000000000e-01 4.50114000000000e-01 3.58423000000000e-01 1.26449000000000e-01 + -2.40452000000000e-01 -3.20413000000000e-01 4.66777000000000e-01 7.03549000000000e-01 + 8.80080000000000e-02 -5.04842000000000e-01 8.07522000000000e-01 -7.19301000000000e-01 + 1.03323500000000e+00 -8.77213000000000e-01 -3.90492000000000e-01 2.12318000000000e-01 + + + 0.2 0.0 0.0 0.0 + + + 5.04668000000000e-01 4.50114000000000e-01 3.58423000000000e-01 1.26449000000000e-01 @@ -25,8 +37,8 @@ - - + + diff --git a/tests/molecules/H4_ae/H4.wfs_2_UHF.xml b/tests/molecules/H4_ae/H4.wfs_2_RHF.xml similarity index 75% rename from tests/molecules/H4_ae/H4.wfs_2_UHF.xml rename to tests/molecules/H4_ae/H4.wfs_2_RHF.xml index 1d7d6c675..6da53f596 100644 --- a/tests/molecules/H4_ae/H4.wfs_2_UHF.xml +++ b/tests/molecules/H4_ae/H4.wfs_2_RHF.xml @@ -12,19 +12,7 @@ - - - - 5.04668000000000e-01 4.50114000000000e-01 3.58423000000000e-01 1.26449000000000e-01 - -2.40452000000000e-01 -3.20413000000000e-01 4.66777000000000e-01 7.03549000000000e-01 - 8.80080000000000e-02 -5.04842000000000e-01 8.07522000000000e-01 -7.19301000000000e-01 - 1.03323500000000e+00 -8.77213000000000e-01 -3.90492000000000e-01 2.12318000000000e-01 - - - 0.2 0.0 0.0 0.0 - - - + 5.04668000000000e-01 4.50114000000000e-01 3.58423000000000e-01 1.26449000000000e-01 @@ -37,8 +25,8 @@ - - + + diff --git a/tests/molecules/H4_ae/H4_UHF_orb_opt.xml b/tests/molecules/H4_ae/H4_RHF_orb_opt.xml similarity index 97% rename from tests/molecules/H4_ae/H4_UHF_orb_opt.xml rename to tests/molecules/H4_ae/H4_RHF_orb_opt.xml index 27522a640..63f5564b0 100644 --- a/tests/molecules/H4_ae/H4_UHF_orb_opt.xml +++ b/tests/molecules/H4_ae/H4_RHF_orb_opt.xml @@ -4,7 +4,7 @@ - + From 308233f4d93b949aa42cdc2e9a9dda1828fc38ff Mon Sep 17 00:00:00 2001 From: Ye Luo Date: Sun, 20 Oct 2019 11:06:01 -0500 Subject: [PATCH 24/41] Remove AoS orbital rotation related classes. --- src/QMCWaveFunctions/CMakeLists.txt | 6 - .../Fermion/SlaterDetBuilder.cpp | 59 - src/QMCWaveFunctions/Fermion/SlaterDetOpt.cpp | 1280 ----------------- src/QMCWaveFunctions/Fermion/SlaterDetOpt.h | 210 --- .../MolecularOrbitals/LCOrbitalSetOpt.h | 826 ----------- .../MolecularOrbitals/MolecularSPOBuilder.h | 14 +- src/QMCWaveFunctions/SPOSet.cpp | 4 - src/QMCWaveFunctions/SPOSet.h | 16 - .../lcao/LCAOrbitalBuilder.cpp | 2 - 9 files changed, 1 insertion(+), 2416 deletions(-) delete mode 100644 src/QMCWaveFunctions/Fermion/SlaterDetOpt.cpp delete mode 100644 src/QMCWaveFunctions/Fermion/SlaterDetOpt.h delete mode 100644 src/QMCWaveFunctions/MolecularOrbitals/LCOrbitalSetOpt.h diff --git a/src/QMCWaveFunctions/CMakeLists.txt b/src/QMCWaveFunctions/CMakeLists.txt index 2fa66a201..842f7ddad 100644 --- a/src/QMCWaveFunctions/CMakeLists.txt +++ b/src/QMCWaveFunctions/CMakeLists.txt @@ -204,12 +204,6 @@ IF(ENABLE_CUDA) SET(FERMION_SRCS ${FERMION_SRCS} Fermion/delayed_update_helper.cu) ENDIF(ENABLE_CUDA) -IF(NOT QMC_COMPLEX AND NOT ENABLE_SOA) - SET(FERMION_SRCS ${FERMION_SRCS} - Fermion/SlaterDetOpt.cpp - ) -ENDIF(NOT QMC_COMPLEX AND NOT ENABLE_SOA) - #################################### # create libqmcwfs #################################### diff --git a/src/QMCWaveFunctions/Fermion/SlaterDetBuilder.cpp b/src/QMCWaveFunctions/Fermion/SlaterDetBuilder.cpp index bc52d1c70..3580ec408 100644 --- a/src/QMCWaveFunctions/Fermion/SlaterDetBuilder.cpp +++ b/src/QMCWaveFunctions/Fermion/SlaterDetBuilder.cpp @@ -24,13 +24,6 @@ #include "QMCWaveFunctions/Fermion/MultiSlaterDeterminant.h" #include "QMCWaveFunctions/Fermion/MultiSlaterDeterminantFast.h" -#if !defined(QMC_COMPLEX) && !defined(ENABLE_SOA) -//Cannot use complex with SlaterDetOpt -#include "QMCWaveFunctions/MolecularOrbitals/NGOBuilder.h" -#include "QMCWaveFunctions/MolecularOrbitals/LocalizedBasisSet.h" -#include "QMCWaveFunctions/MolecularOrbitals/LCOrbitalSetOpt.h" -#include "QMCWaveFunctions/Fermion/SlaterDetOpt.h" -#endif #if defined(QMC_CUDA) #include "QMCWaveFunctions/Fermion/DiracDeterminantCUDA.h" #endif @@ -484,58 +477,6 @@ bool SlaterDetBuilder::putDeterminant(xmlNodePtr cur, int spin_group) #else if (UseBackflow) adet = new DiracDeterminantWithBackflow(targetPtcl, psi, BFTrans, firstIndex); -#ifndef ENABLE_SOA - else if (optimize == "yes") - { -#ifdef QMC_COMPLEX - app_error() << "Orbital optimization via rotation doesn't support complex wavefunction yet.\n"; - abort(); -#else - std::vector params; - bool params_supplied = false; - - // Search for the XML tag called "opt_vars", which will specify - // initial values for the determinant's optimiziable variables. - std::string subdet_name; - for (xmlNodePtr subdet_cur = cur->children; subdet_cur != NULL; subdet_cur = subdet_cur->next) - { - getNodeName(subdet_name, subdet_cur); - if (subdet_name == "opt_vars") - { - params_supplied = true; - putContent(params, subdet_cur); - } - } - - // YE: need check - // get a pointer to the single particle orbital set and make sure it is of the correct type - if (!psi->is_of_type_LCOrbitalSetOpt()) - { - std::string newname = "LCOrbitalSetOpt_" + psi->objectName; - SPOSetPtr newpsi = get_sposet(newname); - if (newpsi == nullptr) - { - app_log() << "using an existing SPO object " << psi->objectName - << " (not a clone) for the basis of an optimizable SPO set.\n"; - newpsi = new LCOrbitalSetOpt>(psi); - // YE: FIXME, need to register newpsi - } - else - { - psi = newpsi; - } - } - - // build the optimizable slater determinant - SlaterDetOpt* const retval = new SlaterDetOpt(targetPtcl, psi, spin_group); - - // load extra parameters for SlaterDetOpt - retval->buildOptVariables(params, params_supplied, true); - - adet = retval; -#endif - } -#endif #if defined(ENABLE_CUDA) else if (useGPU == "yes") { diff --git a/src/QMCWaveFunctions/Fermion/SlaterDetOpt.cpp b/src/QMCWaveFunctions/Fermion/SlaterDetOpt.cpp deleted file mode 100644 index 79674946a..000000000 --- a/src/QMCWaveFunctions/Fermion/SlaterDetOpt.cpp +++ /dev/null @@ -1,1280 +0,0 @@ -////////////////////////////////////////////////////////////////////////////////////// -// This file is distributed under the University of Illinois/NCSA Open Source License. -// See LICENSE file in top directory for details. -// -// Copyright (c) 2017 Jeongnim Kim and QMCPACK developers. -// -// File developed by: Eric Neuscamman, eneuscamman@berkeley.edu, University of California, Berkeley -// Nick Blunt, nicksblunt@gmail.com, University of Cambridge -// -// File created by: Eric Neuscamman, eneuscamman@berkeley.edu, University of California, Berkeley -////////////////////////////////////////////////////////////////////////////////////// - -#include -#include -#include -#include -#include - -namespace qmcplusplus -{ -/////////////////////////////////////////////////////////////////////////////////////////////////// -/// \brief Creates a slater determinant of the given spin with the given optimizable orbital set. -/// -/// \param[in] ptcl the particle set -/// \param[in] spo_ptr pointer to the optimizable single particle orbital set -/// \param[in] up_or_down 0 for up spin, 1 for down -/// \param[in] nmo number of optimizable molecular orbitals -/// -/////////////////////////////////////////////////////////////////////////////////////////////////// -SlaterDetOpt::SlaterDetOpt(ParticleSet& ptcl, SPOSet* spo_ptr, const int up_or_down) - : DiracDeterminantBase(spo_ptr), - m_up_or_down(up_or_down), - m_nmo(spo_ptr->size()), - m_first_var_pos(-1), - m_act_rot_inds() -{ - targetPtcl = &ptcl; - - Optimizable = true; - ClassName = "SlaterDetOpt"; - - // set which and how many particles we care about - m_first = ptcl.first(m_up_or_down); - m_last = ptcl.last(m_up_or_down); - m_nel = m_last - m_first; - - resize(m_nel, m_nmo); - - m_nlc = Phi->getOrbitalSetSize(); - m_nb = Phi->getBasisSetSize(); - - // make sure we didn't start with a bad m_nlc - check_index_sanity(); - - // by default set all rotations to be active - m_act_rot_inds.resize(m_nlc * (m_nlc - 1) / 2); - int rots_recorded = 0; - for (int j = 1; j < m_nlc; j++) - for (int i = 0; i < j; i++) - m_act_rot_inds.at(rots_recorded++) = std::pair(i, j); - if (m_act_rot_inds.size() != rots_recorded) - throw std::runtime_error("wrong number of active rotations recorded in SlaterDetOpt constructor."); - - // make sure we didn't do something stupid - check_index_sanity(); - - // prepare matrices that will hold derivatives wrt orbital rotations - this->initialize_matrices(); - - // add this determinant's contribution to the orbital linear combinations' derivatives - set_optimizable_rotation_ranges(0, m_nel, m_nel, m_nmo); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/// \brief Adds the optimizable orbital set trial function component to the given trial function -/// if it wasn't already there. -/// -/// \param[in] twf the trial wave function to add the component to -/// \param[in] name a name for the component -/// -/////////////////////////////////////////////////////////////////////////////////////////////////// -//void SlaterDetOpt::add_orbs_to_tf(TrialWaveFunction & twf, const std::string & name) { -// if ( std::find(twf.getOrbitals().begin(), twf.getOrbitals().end(), Phi->tf_component()) == twf.getOrbitals().end() ) -// twf.addOrbital(Phi->tf_component(), name, false); -//} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/// \brief verifies that the number of linear combinations and the list of active rotation -/// indices is sane -/// -/////////////////////////////////////////////////////////////////////////////////////////////////// -void SlaterDetOpt::check_index_sanity() const -{ - // ensure the number of linear combinations is not negative - if (m_nlc < 0) - throw std::runtime_error("check_index_sanity found a negative number of linear combinations"); - - // throw an error if any active rotation index is unreasonable - for (std::vector>::const_iterator it = m_act_rot_inds.begin(); it != m_act_rot_inds.end(); it++) - { - if (it->first >= it->second) - { - std::stringstream error_msg; - error_msg << "check_index_sanity found an active rotation index pair (" << it->first << "," << it->second - << ") in which the first index was not smaller than the second"; - throw std::runtime_error(error_msg.str()); - } - if (it->first < 0 || it->first >= m_nlc) - { - std::stringstream error_msg; - error_msg << it->first << " is an out of bounds first active rotation index in check_index_sanity"; - throw std::runtime_error(error_msg.str()); - } - if (it->second < 0 || it->second >= m_nlc) - { - std::stringstream error_msg; - error_msg << it->second << " is an out of bounds second active rotation index in check_index_sanity"; - throw std::runtime_error(error_msg.str()); - } - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/// \brief Makes a clone (copy) of the object that uses the supplied single -/// particle orbital set. -/// -/// \param[in] spo the single particle orbital set the copy should use -/// -/////////////////////////////////////////////////////////////////////////////////////////////////// -SlaterDetOpt* SlaterDetOpt::makeCopy(SPOSetPtr spo) const -{ - SlaterDetOpt* copy = new SlaterDetOpt(*targetPtcl, spo, m_up_or_down); - - copy->myVars = myVars; - copy->Optimizable = Optimizable; - copy->m_first_var_pos = m_first_var_pos; - - return copy; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/// \brief Destructor has nothing to do for now -/// -/////////////////////////////////////////////////////////////////////////////////////////////////// -SlaterDetOpt::~SlaterDetOpt() {} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/// \brief prepares the matrices that will hold derivatives w.r.t. orbital rotations by -/// ensuring they are the right size and that their elements are all zero -/// -/////////////////////////////////////////////////////////////////////////////////////////////////// -void SlaterDetOpt::initialize_matrices() -{ - // initialize matrix for Log(Psi) derivatives - m_pder_mat.resize(m_nlc * m_nlc); - std::fill(m_pder_mat.begin(), m_pder_mat.end(), 0.0); - - // initialize matrix for ( H Psi ) / Psi derivatives - m_hder_mat.resize(m_nlc * m_nlc); - std::fill(m_hder_mat.begin(), m_hder_mat.end(), 0.0); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/// \brief Exponentiates a matrix -/// -/// \param[in] n matrix dimensions -/// \param[in,out] mat On entry, the n by n matrix. -/// On exit, the exponential of the matrix. -/// -/////////////////////////////////////////////////////////////////////////////////////////////////// -void SlaterDetOpt::exponentiate_matrix(const int n, RealType* const mat) -{ - // save initial matrix and get some workspace - std::vector mat_a(mat, mat + n * n); - std::vector mat_b(mat, mat + n * n); - std::vector mat_c(mat, mat + n * n); - RealType* ptr_a = &mat_a.at(0); - RealType* ptr_b = &mat_b.at(0); - RealType* ptr_c = &mat_c.at(0); - - // initialize output to identity matrix - for (int j = 0; j < n; j++) - for (int i = 0; i < n; i++) - mat[i + n * j] = (i == j ? 1.0 : 0.0); - - // compute exponential of matrix - for (int q = 1; q < 20; q++) - { - BLAS::axpy(n * n, RealType(1.0), ptr_b, mat); - BLAS::gemm('N', 'N', n, n, n, RealType(1.0) / (q + 1), ptr_a, n, ptr_b, n, RealType(0.0), ptr_c, n); - std::swap(ptr_b, ptr_c); - RealType max_elem = 0.0; - for (int i = 0; i < n * n; i++) - if (std::abs(ptr_b[i]) > max_elem) - max_elem = std::abs(ptr_b[i]); - if (max_elem < 1.0e-15) - break; - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/// \brief resize and initialize arrays -/// -/////////////////////////////////////////////////////////////////////////////////////////////////// -void SlaterDetOpt::resize(int m_nel, int m_nmo) -{ - // resize matrices and arrays - m_orb_val_mat_all.resize(m_nel, m_nmo); - m_orb_der_mat_all.resize(m_nel, m_nmo); - m_orb_lap_mat_all.resize(m_nel, m_nmo); - m_orb_inv_mat.resize(m_nel, m_nel); - m_orb_val_mat.resize(m_nel, m_nel); - m_orb_der_mat.resize(m_nel, m_nel); - m_orb_lap_mat.resize(m_nel, m_nel); - m_orb_val_vec.resize(m_nel); - m_orb_der_vec.resize(m_nel); - m_orb_lap_vec.resize(m_nel); - m_dp0.resize(m_nel, m_nmo); - m_dh0.resize(m_nel, m_nmo); - m_dh1.resize(3 * m_nel, m_nmo); - m_dh2.resize(m_nel, m_nmo); - m_work.resize(std::max(size_t(m_dh1.size()), size_t(std::max(m_nel, 10) * m_nel + m_nel * m_nel))); - m_pivot.resize(m_nel); - - // ensure some of the matrices are filled with zeros - std::fill(m_dp0.begin(), m_dp0.end(), 0.0); - std::fill(m_dh0.begin(), m_dh0.end(), 0.0); - std::fill(m_dh1.begin(), m_dh1.end(), 0.0); - std::fill(m_dh2.begin(), m_dh2.end(), 0.0); - std::fill(m_work.begin(), m_work.end(), 0.0); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/// \brief Evaluates the Slater determinant's matrix, its inverse, its first derivatives w.r.t. -/// particle positions, and its summed second derivatives w.r.t. particle positions. -/// Returns the log of the determinant value. -/// -/// \param[in] P the particle set -/// \param[in] all whether to additionally evaluate data for all molecular orbitals, -/// including those not present in the determinant -/// -/// \return the log of the determinant value -/// -/////////////////////////////////////////////////////////////////////////////////////////////////// -WaveFunctionComponent::RealType SlaterDetOpt::evaluate_matrices_from_scratch(ParticleSet& P, const bool all) -{ - //app_log() << " EWN ENTERING SlaterDetOpt::evaluate_matrices_from_scratch(ParticleSet& P, const bool all)" << std::endl; - - // either evaluate all of the molecular orbitals - if (all) - { - Phi->evaluate_notranspose(P, m_first, m_last, m_orb_val_mat_all, m_orb_der_mat_all, m_orb_lap_mat_all); - for (int i = 0; i < m_nel; i++) - for (int j = 0; j < m_nel; j++) - { - m_orb_val_mat(i, j) = m_orb_val_mat_all(i, j); - m_orb_der_mat(i, j) = m_orb_der_mat_all(i, j); - m_orb_lap_mat(i, j) = m_orb_lap_mat_all(i, j); - } - - // or just the molecular orbitals used by this determinant - } - else - { - Phi->evaluate_notranspose(P, m_first, m_last, m_orb_val_mat, m_orb_der_mat, m_orb_lap_mat); - } - - // m_orb_val_mat slow (i.e. first) index is now particles - // m_orb_der_mat slow (i.e. first) index is now particles - // m_orb_lap_mat slow (i.e. first) index is now particles - - // copy orbital values into inverse matrix, transposing so the slow index will end up as the one we want - qmcplusplus::MatrixOperators::transpose(m_orb_val_mat, - m_orb_inv_mat); // m_orb_inv_mat slow (i.e. first) index is now combinations - - // get the log of the determinant and the inverse of the orbital value matrix - return InvertWithLog(m_orb_inv_mat.data(), - m_nel, - m_nel, - &m_work.at(0), - &m_pivot.at(0), - PhaseValue); // m_orb_inv_mat slow (i.e. first) index is now particles -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/// \brief Evaluates the log of the determinant value and adds the gradient and laplacian of the -/// log of the determinant to the total gradient and laplacian -/// -/// \param[in] P the particle set -/// \param[in,out] G gradient to add to -/// \param[in,out] L laplacian to add to -/// -/// \return the log of the determinant value -/// -/////////////////////////////////////////////////////////////////////////////////////////////////// -WaveFunctionComponent::RealType SlaterDetOpt::evaluateLog(ParticleSet& P, - ParticleSet::ParticleGradient_t& G, - ParticleSet::ParticleLaplacian_t& L) -{ - //throw std::runtime_error("SlaterDetOpt::evaluateLog (P, G, L) die"); - LogValue = this->evaluate_matrices_from_scratch(P, false); - - // compute gradient and laplacian parts - const bool slow_loops = true; - if (slow_loops) - { - // gradient components - for (int a = 0, iat = m_first; a < m_nel; a++, iat++) - for (int i = 0; i < m_nel; i++) - for (int k = 0; k < 3; k++) - G[iat][k] += m_orb_inv_mat(a, i) * m_orb_der_mat(a, i)[k]; - // laplacian components - for (int a = 0, iat = m_first; a < m_nel; a++, iat++) - { - for (int i = 0; i < m_nel; i++) - L[iat] += m_orb_inv_mat(a, i) * m_orb_lap_mat(a, i); - for (int k = 0; k < 3; k++) - { - RealType Qdot_a_mu = 0.0; - for (int i = 0; i < m_nel; i++) - Qdot_a_mu += m_orb_inv_mat(a, i) * m_orb_der_mat(a, i)[k]; - L[iat] -= Qdot_a_mu * Qdot_a_mu; - } - } - } - else - { - // TO DO: replace slow loops with BLAS calls - } - - // return the log of the determinant - return LogValue; -} - -// BEGIN EWN DEBUG -//template void eval_grad_print_mat_opt(T & mat) { -// for (int i = 0; i < mat.rows(); i++) { -// for (int j = 0; j < mat.cols(); j++) -// app_log() << " " << mat(i,j); -// app_log() << std::endl; -// } -//} -// END EWN DEBUG - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/// \brief Evaluates and returns the gradient of the log of the determinant w.r.t. a specified -/// particle's position. -/// This function assumes that m_orb_inv_mat and m_orb_der_mat have already been prepared. -/// -/// \param[in] P the particle set -/// \param[in] iat index of the particle in question -/// -/// \return the one particle gradient of the log of the determinant value -/// -/////////////////////////////////////////////////////////////////////////////////////////////////// -WaveFunctionComponent::GradType SlaterDetOpt::evalGrad(ParticleSet& P, int iat) -{ - // TO DO: replace the loop(s) with BLAS calls - - // compute and return gradient w.r.t. position of particle iat - WaveFunctionComponent::GradType g; - g = 0.0; - if (iat >= m_first && iat < m_last) - { - // BEGIN EWN DEBUG - //this->evaluate_matrices_from_scratch(P, true); - //app_log() << "printing inverse matrix in evalGrad" << std::endl; - //eval_grad_print_mat_opt(m_orb_inv_mat); - //app_log() << "printing orbital grad matrix in evalGrad" << std::endl; - //eval_grad_print_mat_opt(m_orb_der_mat); - // END EWN DEBUG - const int a = iat - m_first; - for (int i = 0; i < m_nel; i++) - for (int k = 0; k < 3; k++) - g[k] += m_orb_inv_mat(a, i) * m_orb_der_mat(a, i)[k]; - } - return g; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/// \brief For a given one particle move, this function evaluates the ratio of the new and -/// old determinant values as well as the determinant's contribution to grad_iat, which is -/// the gradient (evaluated at the new position) of the log of the trial function w.r.t. -/// the moved particle's coordinates. -/// -/// \param[in] P the particle set, which I think carries information about the particle's move -/// \param[in] iat the id number of the moved particle -/// \param[in,out] grad_iat cumulative total of the gradient of the trial function's log w.r.t. the moved particle's coordinates -/// -/// \return the ratio of new and old determinant values -/// -/////////////////////////////////////////////////////////////////////////////////////////////////// -WaveFunctionComponent::ValueType SlaterDetOpt::ratioGrad(ParticleSet& P, int iat, GradType& grad_iat) -{ - // no contribution if the particle is not part of this determinant - if (iat < m_first || iat >= m_last) - return 1.0; - - // compute orbital values, gradients, and summed second derivatives for the particle's new position - Phi->evaluate(P, iat, m_orb_val_vec, m_orb_der_vec, m_orb_lap_vec); - - // compute the ratio of new to old determinant values - curRatio = simd::dot(m_orb_inv_mat[iat - m_first], m_orb_val_vec.data(), m_nel); - - // compute the determinant's contribution to the gradient of the log of the trial function - grad_iat += simd::dot(m_orb_inv_mat[iat - m_first], m_orb_der_vec.data(), m_nel) / curRatio; - - // return the ratio - return curRatio; -} - - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/// \brief Not yet implemented. -/// -/// \return ??? -/// -/////////////////////////////////////////////////////////////////////////////////////////////////// -WaveFunctionComponent::ValueType SlaterDetOpt::ratio(ParticleSet& P, int iat) -{ - // throw std::runtime_error("SlaterDetOpt::ratio(P, iat) not implemented"); - // return 0.0; - // no contribution if the particle is not part of this determinant - if (iat < m_first || iat >= m_last) - return 1.0; - - // compute orbital values, gradients, and summed second derivatives for the particle's new position - Phi->evaluate(P, iat, m_orb_val_vec, m_orb_der_vec, m_orb_lap_vec); - - // compute the ratio of new to old determinant values - curRatio = simd::dot(m_orb_inv_mat[iat - m_first], m_orb_val_vec.data(), m_nel); - return curRatio; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/// \brief Updates the orbital matrix and its inverse for a single particle move. -/// -/// \param[in] P the particle set, which I think carries information about the particle's move -/// \param[in] iat the id number of the moved particle -/// -/////////////////////////////////////////////////////////////////////////////////////////////////// -void SlaterDetOpt::acceptMove(ParticleSet& P, int iat) -{ - // nothing to do if particle does not belong to this determinant - if (iat < m_first || iat >= m_last) - return; - - // Update Log and Phase values, then reset the ratio to 1. - PhaseValue += evaluatePhase(curRatio); - LogValue += std::log(std::abs(curRatio)); - curRatio = 1.0; - - // get row difference - std::copy(m_orb_val_vec.begin(), m_orb_val_vec.end(), &m_work.at(0)); - BLAS::axpy(m_nel, -1.0, m_orb_val_mat[iat - m_first], &m_work.at(0)); - - // get inverse times row difference (remembering that m_orb_inv_mat slow index is particles) - BLAS::gemm('N', 'N', 1, m_nel, m_nel, 1.0, &m_work.at(0), 1, m_orb_inv_mat.data(), m_nel, 0.0, &m_work.at(m_nel), 1); - - // get inverse ratio - const double ir = 1.0 / (1.0 + m_work.at(m_nel + iat - m_first)); - - // perform rank one update of the inverse matrix (keeping in mind that it is stored with particles as the slow index) - std::copy(m_orb_inv_mat[iat - m_first], m_orb_inv_mat[iat - m_first] + m_nel, &m_work.at(0)); - BLAS::ger(m_nel, m_nel, -ir, &m_work.at(0), 1, &m_work.at(m_nel), 1, m_orb_inv_mat.data(), m_nel); - - // update the orbital matrix, orbital derivative matrix, and summed laplacian matrix - std::copy(m_orb_val_vec.begin(), m_orb_val_vec.end(), m_orb_val_mat[iat - m_first]); - std::copy(m_orb_der_vec.begin(), m_orb_der_vec.end(), m_orb_der_mat[iat - m_first]); - std::copy(m_orb_lap_vec.begin(), m_orb_lap_vec.end(), m_orb_lap_mat[iat - m_first]); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/// \brief Particle move rejected - simply reset the ratio of new to old wave functions -/// -/// \param[in] iat the id number of the moved particle -/// -/////////////////////////////////////////////////////////////////////////////////////////////////// -void SlaterDetOpt::restore(int iat) { curRatio = 1.0; } - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/// \brief Initialize the object for the given particle positions and add its essential internal -/// data to the supplied buffer -/// -/// \param[in] P the particle set -/// \param[in] buf the buffer to add essential data to -/// -/////////////////////////////////////////////////////////////////////////////////////////////////// -void SlaterDetOpt::registerData(ParticleSet& P, WFBufferType& buf) -{ - //app_log() << " EWN ENTERING SlaterDetOpt::registerData(ParticleSet& P, WFBufferType& buf)" << std::endl; - - // add the log of the wave function to the buffer - buf.add(LogValue); - - // add the phase of the wave function to the buffer - buf.add(PhaseValue); - - // add orbital matrix to the buffer - buf.add(m_orb_val_mat.first_address(), m_orb_val_mat.last_address()); - - // add the orbital derivative matrix to the buffer - buf.add(&m_orb_der_mat(0, 0)[0], &m_orb_der_mat(0, 0)[0] + m_orb_der_mat.size() * m_orb_der_mat(0, 0).size()); - - // add orbital laplacian matrix to the buffer - buf.add(m_orb_lap_mat.first_address(), m_orb_lap_mat.last_address()); - - // add inverse matrix to the buffer - buf.add(m_orb_inv_mat.first_address(), m_orb_inv_mat.last_address()); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/// \brief Initialize the object for the given particle positions and put its essential internal -/// data into the supplied buffer -/// -/// \param[in] P the particle set -/// \param[in] buf the buffer to save essential data in -/// \param[in] fromscratch ??? -/// -/// \return the log of the determinant value -/// -/////////////////////////////////////////////////////////////////////////////////////////////////// -WaveFunctionComponent::RealType SlaterDetOpt::updateBuffer(ParticleSet& P, WFBufferType& buf, bool fromscratch) -{ - // BEGIN EWN DEBUG - //app_log() << " EWN ENTERING SlaterDetOpt::updateBuffer(ParticleSet& P, WFBufferType& buf, bool fromscratch)" << std::endl; - //app_log() << "printing P.R" << std::endl; - //for (int i = 0; i < P.R.size(); i++) - // app_log() << P.R[i] << std::endl; - // END EWN DEBUG - - // !!! WE WILL EVENTUALLY WANT TO TAKE DIFFERENT ACTIONS DEPENDING ON THE VALUE OF fromscratch !!! - - // evaluate the orbital matrix, its inverse, and the log of the determinant value - LogValue = evaluateLog(P, P.G, P.L); - - // add the log of the wave function to the buffer - buf.put(LogValue); - - // add the phase of the wave function to the buffer - buf.put(PhaseValue); - - // add orbital matrix to the buffer - buf.put(m_orb_val_mat.first_address(), m_orb_val_mat.last_address()); - - // add the orbital derivative matrix to the buffer - buf.put(&m_orb_der_mat(0, 0)[0], &m_orb_der_mat(0, 0)[0] + m_orb_der_mat.size() * m_orb_der_mat(0, 0).size()); - - // add orbital laplacian matrix to the buffer - buf.put(m_orb_lap_mat.first_address(), m_orb_lap_mat.last_address()); - - // add inverse matrix to the buffer - buf.put(m_orb_inv_mat.first_address(), m_orb_inv_mat.last_address()); - - // return log of determinant value - return LogValue; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/// \brief Read in necessary internal data from the provided buffer -/// -/// \param[in] P the particle set -/// \param[in] buf the buffer to read from -/// -/////////////////////////////////////////////////////////////////////////////////////////////////// -void SlaterDetOpt::copyFromBuffer(ParticleSet& P, WFBufferType& buf) -{ - // read in the log of the wave function - buf.get(LogValue); - - // read in the phase of the wave function - buf.get(PhaseValue); - - // read in the orbital matrix - buf.get(m_orb_val_mat.first_address(), m_orb_val_mat.last_address()); - - // read in the orbital derivative matrix - buf.get(&m_orb_der_mat(0, 0)[0], &m_orb_der_mat(0, 0)[0] + m_orb_der_mat.size() * m_orb_der_mat(0, 0).size()); - - // read in the orbital laplacian matrix - buf.get(m_orb_lap_mat.first_address(), m_orb_lap_mat.last_address()); - - // read in the inverse matrix - buf.get(m_orb_inv_mat.first_address(), m_orb_inv_mat.last_address()); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/// \brief Check this object's optimizable variables into the supplied overall list of -/// optimizable variables. -/// -/// \param[in,out] active the overall list of optimizable variables -/// -/////////////////////////////////////////////////////////////////////////////////////////////////// -void SlaterDetOpt::checkInVariables(opt_variables_type& active) -{ - // add these variables to the overall list of optimizable variables - active.insertFrom(this->myVars); - - // reset my first variable's position to say that we don't know where it is yet - m_first_var_pos = -1; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/// \brief Records the positions of this object's optimizable variables in the supplied overall -/// list of optimizable variables, checks that the variables are stored contiguously, -/// and records the position of the first of this objects variables. -/// -/// \param[in] active the overall list of optimizable variables -/// -/////////////////////////////////////////////////////////////////////////////////////////////////// -void SlaterDetOpt::checkOutVariables(const opt_variables_type& active) -{ - // record the positions of this object's optimizable variables within the overall list of optimizable variables - myVars.getIndex(active); - - // ensure that this object's variables are stored contiguously - for (int i = 0; i < myVars.size(); i++) - { - if (myVars.where(i) - myVars.where(0) != i) - { - std::stringstream error_msg; - error_msg << "variable " << (i - 1) << " was not contiguous with variable " << i - << " in SlaterDetOpt::checkOutVariables"; - throw std::runtime_error(error_msg.str()); - } - } - - // record the position of my first variable - if (myVars.size() > 0) - m_first_var_pos = myVars.where(0); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/// \brief Nothing to reset, as the optimizable orbital variables are handled by the -/// orbital set's trial function component. -/// -/// \param[in] active ??? -/// -/////////////////////////////////////////////////////////////////////////////////////////////////// -void SlaterDetOpt::resetParameters(const opt_variables_type& active) -{ - // read out the parameters that define the rotation into an antisymmetric matrix - std::vector rot_mat(m_nlc * m_nlc, 0.0); - for (int i = 0; i < m_act_rot_inds.size(); i++) - { - const int p = m_act_rot_inds.at(i).first; - const int q = m_act_rot_inds.at(i).second; - //const RealType x = active[i + m_first_var_pos] - myVars[i]; - const RealType x = active[i + m_first_var_pos]; - rot_mat[p + q * m_nlc] = x; - rot_mat[q + p * m_nlc] = -x; - } - - // exponentiate antisymmetric matrix to get the unitary rotation - this->exponentiate_matrix(m_nlc, &rot_mat.at(0)); - - // get the linear combination coefficients by applying the rotation to the old coefficients - Phi->rotate_B(rot_mat); - - // Store the orbital rotations parameters internally in myVars - for (int i = 0; i < m_act_rot_inds.size(); i++) - myVars[i] = active[i + m_first_var_pos]; - - //if (false) - // this->print_B(); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/// \brief add to the Log(Psi) and ( H Psi ) / Psi derivatives -/// -/// \param[in] nl The number of molecular orbitals. -/// \param[in] np The number of particles over which to sum derivative contributions. -/// \param[in] dp0 An nl by np column-major-ordered matrix of the derivatives -/// of Log(Psi) with respect to the values of the -/// molecular orbitals at each particle's position. -/// \param[in] dh0 An nl by np column-major-ordered matrix of the derivatives -/// of ( H Psi ) / Psi with respect to the values of the -/// molecular orbitals at each particle's position. -/// \param[in] dh1 Three nl by np column-major-ordered matrices (stored contiguously -/// one after the other) of the derivatives of -/// of ( H Psi ) / Psi with respect to the values of the -/// molecular orbitals' first position derivatives (w.r.t. x,y,z) -/// at each particle's position. -/// \param[in] dh2 An nl by np column-major-ordered matrix of the derivatives -/// of ( H Psi ) / Psi with respect to the values of the -/// molecular orbitals' second position derivatives at each -/// particle's position. Note that we assume the derivatives of -/// ( H Psi ) / Psi are the same for each of the three directions' -/// (x,y,z) second derivatives and so dh2 is defined as the -/// derivatives corresponding to the x coordinate's second derivative, -/// NOT the sum of the derivatives for all three x, y, and z. -/// \param[in] Bchi An nl by np column-major-ordered matrix of the values of the -/// molecular orbitals at each particle's position. -/// \param[in] dBchi Three nl by np column-major-ordered matrices (stored contiguously -/// one after the other) of the first position derivatives of the -/// molecular orbitals at each particle's position. -/// \param[in] d2Bchi An nl by np column-major-ordered matrix of the molecular orbitals' -/// x-y-z summed second derivatives at each particle's position. -/// -/////////////////////////////////////////////////////////////////////////////////////////////////// -void SlaterDetOpt::add_derivatives(const int nl, - const int np, - const RealType* const dp0, - const RealType* const dh0, - const RealType* const dh1, - const RealType* const dh2, - const RealType* const Bchi, - const RealType* const dBchi, - const RealType* const d2Bchi) -{ - // ensure the number of linear combinations is correct - if (nl != m_nlc) - { - std::stringstream error_msg; - error_msg << "supplied number of linear combinations (" << nl << ") does not match that held internally (" << m_nlc - << ") in add_derivatives"; - throw std::runtime_error(error_msg.str()); - } - - // ensure orbital derivative matrices are the correct size - if (m_pder_mat.size() != nl * nl) - { - std::stringstream error_msg; - error_msg << "nl (" << nl << ") does not match size of m_pder_mat (" << m_pder_mat.size() << ") in add_derivatives"; - throw std::runtime_error(error_msg.str()); - } - if (m_hder_mat.size() != nl * nl) - { - std::stringstream error_msg; - error_msg << "nl (" << nl << ") does not match size of m_hder_mat (" << m_hder_mat.size() << ") in add_derivatives"; - throw std::runtime_error(error_msg.str()); - } - - // contract Log(Psi) derivatives with the current linear combination values and add result to the Log(Psi) derivatives w.r.t. the matrix C - //for (int j = 0; j < nl; j++) - //for (int i = 0; i < nl; i++) - // for (int k = 0; k < np; k++) - // m_pder_mat.at(i+j*nl) += dp0[i+k*nl] * Bchi[j+k*nl]; - BLAS::gemm('N', 'T', nl, nl, np, RealType(1.0), dp0, nl, Bchi, nl, RealType(1.0), &m_pder_mat.at(0), nl); - - // compute products of ( H Psi ) / Psi derivatives with linear combination values and their derivatives and add results to energy derivatives w.r.t. the matrix C - BLAS::gemm('N', 'T', nl, nl, np, RealType(1.0), dh0, nl, Bchi, nl, RealType(1.0), &m_hder_mat.at(0), nl); - for (int i = 0; i < 3; i++) - BLAS::gemm('N', - 'T', - nl, - nl, - np, - RealType(1.0), - dh1 + i * nl * np, - nl, - dBchi + i * nl * np, - nl, - RealType(1.0), - &m_hder_mat.at(0), - nl); - BLAS::gemm('N', 'T', nl, nl, np, RealType(1.0), dh2, nl, d2Bchi, nl, RealType(1.0), &m_hder_mat.at(0), nl); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/// \brief add to the \grad(\textrm{log}(Psi)) derivatives -/// -/// \param[in] nl The number of molecular orbitals. -/// \param[in] np The number of particles over which to sum derivative contributions. -/// \param[in] dh0 An nl by np column-major-ordered matrix of the derivatives -/// of \grad(\textrm{log}(Psi)) with respect to the values of the -/// molecular orbitals at each particle's position. -/// \param[in] dh1 Three nl by np column-major-ordered matrices (stored contiguously -/// one after the other) of the derivatives of -/// of \grad(\textrm{log}(Psi)) with respect to the values of the -/// molecular orbitals' first position derivatives (w.r.t. x,y,z) -/// at each particle's position. -/// \param[in] Bchi An nl by np column-major-ordered matrix of the values of the -/// molecular orbitals at each particle's position. -/// \param[in] dBchi Three nl by np column-major-ordered matrices (stored contiguously -/// one after the other) of the first position derivatives of the -/// molecular orbitals at each particle's position. -/// -/////////////////////////////////////////////////////////////////////////////////////////////////// -void SlaterDetOpt::add_grad_derivatives(const int nl, - const int np, - const RealType* const dh0, - const RealType* const dh1, - const RealType* const Bchi, - const RealType* const dBchi) -{ - // ensure the number of linear combinations is correct - if (nl != m_nlc) - { - std::stringstream error_msg; - error_msg << "supplied number of linear combinations (" << nl << ") does not match that held internally (" << m_nlc - << ") in LCOrbitalSetOptTrialFunc::add_grad_derivatives"; - throw std::runtime_error(error_msg.str()); - } - - // ensure orbital derivative matrices are the correct size - if (m_hder_mat.size() != nl * nl) - { - std::stringstream error_msg; - error_msg << "nl (" << nl << ") does not match size of m_hder_mat (" << m_hder_mat.size() - << ") in LCOrbitalSetOptTrialFunc::add_grad_derivatives"; - throw std::runtime_error(error_msg.str()); - } - - BLAS::gemm('N', 'T', nl, nl, np, RealType(1.0), dh0, nl, Bchi, nl, RealType(1.0), &m_hder_mat.at(0), nl); - for (int i = 0; i < 3; i++) - BLAS::gemm('N', - 'T', - nl, - nl, - np, - RealType(1.0), - dh1 + i * nl * np, - nl, - dBchi + i * nl * np, - nl, - RealType(1.0), - &m_hder_mat.at(0), - nl); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/// \brief Evaluate the determinant's contribution to the derivatives of log of the trial function -/// and the local energy w.r.t. the molecular orbital coefficients, which will be used -/// by the orbital set's trial function component determine the corresponding derivatives -/// w.r.t. rotations between its molecular orbitals. -/// -/// \param[in] P the particle set -/// \param[in] optvars unused here as we are just preparing what Phi will need -/// \param[in,out] dlogpsi unused here as we are just preparing what Phi will need -/// \param[in,out] dhpsioverpsi unused here as we are just preparing what Phi will need -/// -/////////////////////////////////////////////////////////////////////////////////////////////////// -void SlaterDetOpt::evaluateDerivatives(ParticleSet& P, - const opt_variables_type& optvars, - std::vector& dlogpsi, - std::vector& dhpsioverpsi) -{ - // Evaluate orbital data for all orbitals (not just those in this determinant). - // Prepares: m_orb_val_mat_all, m_orb_der_mat_all, m_orb_lap_mat_all, m_orb_val_mat, m_orb_der_mat, m_orb_lap_mat, and m_orb_inv_mat - LogValue = this->evaluate_matrices_from_scratch(P, true); - - // print for debugging - if (false) - { - std::vector buff(1000, ' '); - - app_log() << "printing m_orb_val_mat_all" << std::endl; - for (int p = 0; p < m_nmo; p++) - { // loop over orbitals - for (int a = 0; a < m_nel; a++) - { // loop over particles - const int len = std::sprintf(&buff[0], " %12.6f", m_orb_val_mat_all(a, p)); - for (int k = 0; k < len; k++) - app_log() << buff[k]; - } - app_log() << std::endl; - } - app_log() << std::endl; - - app_log() << "printing m_orb_der_mat_all" << std::endl; - for (int p = 0; p < m_nmo; p++) - { // loop over orbitals - for (int a = 0; a < m_nel; a++) - { // loop over particles - for (int k = 0; k < 3; k++) - { // loop over x,y,z directions - const int len = std::sprintf(&buff[0], " %12.6f", m_orb_der_mat_all(a, p)[k]); - for (int k = 0; k < len; k++) - app_log() << buff[k]; - } - app_log() << " "; - } - app_log() << std::endl; - } - app_log() << std::endl; - - app_log() << "printing m_orb_lap_mat_all" << std::endl; - for (int p = 0; p < m_nmo; p++) - { // loop over orbitals - for (int a = 0; a < m_nel; a++) - { // loop over particles - const int len = std::sprintf(&buff[0], " %12.6f", m_orb_lap_mat_all(a, p)); - for (int k = 0; k < len; k++) - app_log() << buff[k]; - } - app_log() << std::endl; - } - app_log() << std::endl; - - app_log() << "printing P.G" << std::endl; - for (int a = 0; a < m_nel; a++) - { // loop over particles - for (int k = 0; k < 3; k++) - { // loop over x,y,z directions - const int len = std::sprintf(&buff[0], " %12.6f", P.G[m_first + a][k]); - for (int k = 0; k < len; k++) - app_log() << buff[k]; - } - app_log() << " "; - } - app_log() << std::endl; - app_log() << std::endl; - - app_log() << "printing m_orb_inv_mat" << std::endl; - for (int b = 0; b < m_nel; b++) - { - for (int a = 0; a < m_nel; a++) - { - const int len = std::sprintf(&buff[0], " %12.6f", m_orb_inv_mat(a, b)); - for (int k = 0; k < len; k++) - app_log() << buff[k]; - } - app_log() << std::endl; - } - app_log() << std::endl; - - app_log() << "printing m_orb_der_mat" << std::endl; - for (int p = 0; p < m_nel; p++) - { - for (int a = 0; a < m_nel; a++) - { - for (int k = 0; k < 3; k++) - { - const int len = std::sprintf(&buff[0], " %12.6f", m_orb_der_mat(a, p)[k]); - for (int k = 0; k < len; k++) - app_log() << buff[k]; - } - app_log() << " "; - } - app_log() << std::endl; - } - app_log() << std::endl; - - app_log() << "printing m_orb_lap_mat" << std::endl; - for (int p = 0; p < m_nel; p++) - { - for (int a = 0; a < m_nel; a++) - { - const int len = std::sprintf(&buff[0], " %12.6f", m_orb_lap_mat(a, p)); - for (int k = 0; k < len; k++) - app_log() << buff[k]; - } - app_log() << std::endl; - } - app_log() << std::endl; - } - - // fill matrix of contributions to derivatives of log of det value w.r.t. molecular orbital values - for (int a = 0; a < m_nel; a++) // loop over particles - for (int p = 0; p < m_nel; p++) // loop over orbitals - m_dp0(a, p) = m_orb_inv_mat(a, p); - - // construct temporary Y matrix - RealType* const Ymat = &m_work.at(0); - for (int b = 0; b < m_nel; b++) - { // loop over particles - const WaveFunctionComponent::GradType g = P.G[m_first + b] - simd::dot(m_orb_inv_mat[b], m_orb_der_mat[b], m_nel); - for (int q = 0; q < m_nel; q++) // loop over orbitals - Ymat[q + b * m_nel] = 0.5 * m_orb_lap_mat(b, q) + qmcplusplus::dot(m_orb_der_mat(b, q), g); - } - - // contract Y with inverse matrices to get contribution of local energy derivatives w.r.t. orbital values - BLAS::gemm('N', - 'T', - m_nel, - m_nel, - m_nel, - 1.0, - m_orb_inv_mat.data(), - m_nel, - Ymat, - m_nel, - 0.0, - &m_work.at(m_nel * m_nel), - m_nel); - BLAS::gemm('N', - 'N', - m_nel, - m_nel, - m_nel, - 1.0, - &m_work.at(m_nel * m_nel), - m_nel, - m_orb_inv_mat.data(), - m_nel, - 0.0, - &m_work.at(0), - m_nel); - - // fill result of contraction into top of local energy derivatives w.r.t. molecular orbital value matrix (derivatives w.r.t. virtual orbitals are zero and so we leave the bottom of the matrix alone) - for (int b = 0; b < m_nel; b++) // loop over particles - for (int q = 0; q < m_nel; q++) // loop over orbitals - m_dh0(b, q) = m_work[q + b * m_nel]; - - // fill matrices of contributions to local energy derivatives w.r.t. orbital first derivatives - for (int a = 0; a < m_nel; a++) - { // loop over particles - const WaveFunctionComponent::GradType g = simd::dot(m_orb_inv_mat[a], m_orb_der_mat[a], m_nel) - P.G[m_first + a]; - for (int v = 0; v < 3; v++) // loop over particle coordinates x,y,z - for (int p = 0; p < m_nel; p++) // loop over orbitals - m_dh1(a + v * m_nel, p) = m_orb_inv_mat(a, p) * g[v]; - } - - // fill matrix of contributions to local energy derivatives w.r.t. orbital second derivatives - for (int a = 0; a < m_nel; a++) // loop over particles - for (int p = 0; p < m_nel; p++) // loop over orbitals - m_dh2(a, p) = -0.5 * m_orb_inv_mat(a, p); - - // use the work matrix to arrange the molecular orbital derivative data in the order needed - for (int a = 0; a < m_nel; a++) // loop over particles - for (int p = 0; p < m_nmo; p++) // loop over orbitals - for (int k = 0; k < 3; k++) // loop over particle coordinates x,y,z - m_work[p + a * m_nmo + k * m_nmo * m_nel] = m_orb_der_mat_all(a, p)[k]; - - // add this determinant's contribution to the orbital linear combinations' derivatives - add_derivatives(m_nmo, - m_nel, - m_dp0.data(), - m_dh0.data(), - m_dh1.data(), - m_dh2.data(), - m_orb_val_mat_all.data(), - &m_work.at(0), - m_orb_lap_mat_all.data()); - - - // check that we have the position of the first of our variables in the overall list - if (myVars.size() > 0 && m_first_var_pos < 0) - throw std::runtime_error("position of first variable was not set on entry to SlaterDetOpt::evaluateDerivatives"); - - // check that my number of variables is consistent with the number of active rotations - if (myVars.size() != m_act_rot_inds.size()) - { - std::stringstream error_msg; - error_msg << "mismatch between myVars.size() (" << myVars.size() << ") and m_act_rot_inds.size() (" - << m_act_rot_inds.size() << ") in SlaterDetOpt::evaluateDerivatives"; - throw std::runtime_error(error_msg.str()); - } - - for (int i = 0; i < m_act_rot_inds.size(); i++) - { - const int p = m_act_rot_inds.at(i).first; - const int q = m_act_rot_inds.at(i).second; - dlogpsi.at(m_first_var_pos + i) += ValueType( m_pder_mat.at(p + q * m_nlc) - m_pder_mat.at(q + p * m_nlc) ); - dhpsioverpsi.at(m_first_var_pos + i) += ValueType( m_hder_mat.at(p + q * m_nlc) - m_hder_mat.at(q + p * m_nlc) ); - if (false) - { - std::vector buff(1000, ' '); - const int len = std::sprintf(&buff[0], - " p = %4i q = %4i dlogpsi = %20.12f dhpsioverpsi = %20.12f", - p, - q, - dlogpsi.at(m_first_var_pos + i), - dhpsioverpsi.at(m_first_var_pos + i)); - for (int k = 0; k < len; k++) - app_log() << buff[k]; - app_log() << std::endl; - } - } - - // reset the internally stored derivatives to zero in preparation for the next sample - this->initialize_matrices(); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/// \brief Evaluate the derivatives (with respect to optimizable parameters) of the gradient of -/// the logarithm of the optimizable determinant wave function. The dot product of this -/// object is then taken (with respect to the gradient vector components) with the -/// input G_in gradient vector. The resulting object is a vector in the optimizable -/// parameter components, which is returned by this function in dgradlogpsi. -/// -/// \param[in] G_in Some gradient vector to be dotted with d(\grad(\textrm{log}(\psi))) -/// where \psi is just the optimiziable determinant. -/// \param[out] dgradlogpsi The dot product of G_in with d(\grad(\textrm{log}(\psi))) -/// (not calculated here but in the evaluateGradDerivatives function in -/// LCOrbitalSetOpt.h, for this particular wave function ansatz). -/// -/////////////////////////////////////////////////////////////////////////////////////////////////// -void SlaterDetOpt::evaluateGradDerivatives(const ParticleSet::ParticleGradient_t& G_in, - std::vector& dgradlogpsi) -{ - // construct temporary Y matrix - RealType* const Ymat = &m_work.at(0); - - for (int b = 0; b < m_nel; b++) - { // loop over particles - const WaveFunctionComponent::GradType g = G_in[m_first + b]; - for (int q = 0; q < m_nel; q++) // loop over orbitals - Ymat[q + b * m_nel] = -qmcplusplus::dot(m_orb_der_mat(b, q), g); - } - - // contract Y with inverse matrices to get contribution of gradient - // derivatives w.r.t. orbital values - BLAS::gemm('N', - 'T', - m_nel, - m_nel, - m_nel, - 1.0, - m_orb_inv_mat.data(), - m_nel, - Ymat, - m_nel, - 0.0, - &m_work.at(m_nel * m_nel), - m_nel); - BLAS::gemm('N', - 'N', - m_nel, - m_nel, - m_nel, - 1.0, - &m_work.at(m_nel * m_nel), - m_nel, - m_orb_inv_mat.data(), - m_nel, - 0.0, - &m_work.at(0), - m_nel); - - // fill result of contraction into top of gradient derivatives w.r.t. - // molecular orbital value matrix (derivatives w.r.t. virtual orbitals are - // zero and so we leave the bottom of the matrix alone) - for (int b = 0; b < m_nel; b++) // loop over particles - for (int q = 0; q < m_nel; q++) // loop over orbitals - m_dh0(b, q) = m_work[q + b * m_nel]; - - // fill matrices of contributions to gradient derivatives w.r.t. orbital - // first derivatives - for (int a = 0; a < m_nel; a++) - { // loop over particles - const WaveFunctionComponent::GradType g = G_in[m_first + a]; - for (int v = 0; v < 3; v++) // loop over particle coordinates x,y,z - for (int p = 0; p < m_nel; p++) // loop over orbitals - m_dh1(a + v * m_nel, p) = m_orb_inv_mat(a, p) * g[v]; - } - - // use the work matrix to arrange the molecular orbital derivative data in - // the order needed - for (int a = 0; a < m_nel; a++) // loop over particles - for (int p = 0; p < m_nmo; p++) // loop over orbitals - for (int k = 0; k < 3; k++) // loop over particle coordinates x,y,z - m_work[p + a * m_nmo + k * m_nmo * m_nel] = m_orb_der_mat_all(a, p)[k]; - - // add this determinant's contribution to the orbital linear combinations' derivatives - add_grad_derivatives(m_nmo, m_nel, m_dh0.data(), m_dh1.data(), m_orb_val_mat_all.data(), &m_work.at(0)); - - // check that we have the position of the first of our variables in the - // overall list. - if (myVars.size() > 0 && m_first_var_pos < 0) - throw std::runtime_error("position of first variable was not set on entry to " - "LCOrbitalSetOptTrialFunc::evaluateGradDerivatives"); - - // check that my number of variables is consistent with the - // number of active rotations. - if (myVars.size() != m_act_rot_inds.size()) - { - std::stringstream error_msg; - error_msg << "mismatch between myVars.size() (" << myVars.size() << ") and m_act_rot_inds.size() (" - << m_act_rot_inds.size() << ") in LCOrbitalSetOptTrialFunc::evaluateGradDerivatives"; - throw std::runtime_error(error_msg.str()); - } - - // add derivatives to totals. - for (int i = 0; i < m_act_rot_inds.size(); i++) - { - const int p = m_act_rot_inds.at(i).first; - const int q = m_act_rot_inds.at(i).second; - dgradlogpsi.at(m_first_var_pos + i) += ValueType( m_hder_mat.at(p + q * m_nlc) - m_hder_mat.at(q + p * m_nlc) ); - } - - // reset the internally stored derivatives to zero in preparation for the next sample - this->initialize_matrices(); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/// \brief Set the optimizable rotations to be those between the two specified orbital sets. -/// -/// \param[in] istart 1st index in the 1st orbital set -/// \param[in] iend one past the last index in the 1st orbital set -/// \param[in] jstart 1st index in the 2nd orbital set -/// \param[in] jend one past the last index in the 2nd orbital set -/// -/////////////////////////////////////////////////////////////////////////////////////////////////// -void SlaterDetOpt::set_optimizable_rotation_ranges(const int istart, const int iend, const int jstart, const int jend) -{ - // check sanity - assert(istart >= 0); - assert(iend >= 0); - assert(jstart >= 0); - assert(jend >= 0); - assert(istart <= iend); - assert(jstart <= jend); - - // remove any existing rotations - m_act_rot_inds.clear(); - - // add all rotations between the orbital sets [istart, iend) and [jstart, jend) - for (int i = istart; i < iend; i++) - for (int j = jstart; j < jend; j++) - if (i != j) - m_act_rot_inds.push_back(std::pair(std::min(i, j), std::max(i, j))); -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/// \brief Build this object's list of its own optimizable variables, and optionally set them -/// to input values which may be provided in input_params. If input_params is empty on -/// input, then params_supplied should be false, and each parameter will be set to 0. -/// Then, also apply the initial rotation using the provided input parameters. -/// -/// \param[in] input_params the input list of parameters - can be empty, if no parameters -/// were supplied by the user -/// \param[in] params_supplied true if parameters are provided in input_params, false if -/// input_params is empty -/// \param[in] print_vars if true, then print out the initialized values of the variables -/// -/////////////////////////////////////////////////////////////////////////////////////////////////// -void SlaterDetOpt::buildOptVariables(std::vector& input_params, bool params_supplied, bool print_vars) -{ - int p, q; - int nparams_active = m_act_rot_inds.size(); - - if (params_supplied) - { - int nparams_input = input_params.size(); - if (nparams_input != nparams_active) - throw std::runtime_error("Number of parameters provided for orbital rotations " - "is not consistent with the expected number."); - } - - for (int i = 0; i < nparams_active; i++) - { - p = m_act_rot_inds.at(i).first; - q = m_act_rot_inds.at(i).second; - std::stringstream sstr; - sstr << Phi->objectName << "_orb_rot_" << (p < 10 ? "0" : "") << (p < 100 ? "0" : "") << (p < 1000 ? "0" : "") << p - << "_" << (q < 10 ? "0" : "") << (q < 100 ? "0" : "") << (q < 1000 ? "0" : "") << q; - - // If the user input parameters, use those. Otherwise, initialize the - // parameter to zero. - if (params_supplied) - { - myVars.insert(sstr.str(), input_params[i]); - } - else - { - myVars.insert(sstr.str(), 0.0); - } - } - - if (print_vars) - { - // Print the current values of all the optimisable parameters, - // hopefully with correct formatting. - app_log() << std::string(16, ' ') << "Parameter name" << std::string(15, ' ') << "Value\n"; - myVars.print(app_log()); - } - - // The code below applies the initial rotation requested by the user. - // This is basically doing the same as resetParameters, but that routine - // is a bit too specialized for what we want to do here. So we just - // rewrite the specific code we want, rather than calling that routine. - - // Read out the parameters that define the rotation into an antisymmetric matrix - std::vector rot_mat(m_nlc * m_nlc, 0.0); - for (int i = 0; i < m_act_rot_inds.size(); i++) - { - const int p = m_act_rot_inds.at(i).first; - const int q = m_act_rot_inds.at(i).second; - rot_mat[p + q * m_nlc] = myVars[i]; - rot_mat[q + p * m_nlc] = -myVars[i]; - } - // Exponentiate antisymmetric matrix to get the unitary rotation. - this->exponentiate_matrix(m_nlc, &rot_mat.at(0)); - // get the linear combination coefficients by applying the rotation to the old coefficients - Phi->rotate_B(rot_mat); -} - -} // namespace qmcplusplus diff --git a/src/QMCWaveFunctions/Fermion/SlaterDetOpt.h b/src/QMCWaveFunctions/Fermion/SlaterDetOpt.h deleted file mode 100644 index d24ad6139..000000000 --- a/src/QMCWaveFunctions/Fermion/SlaterDetOpt.h +++ /dev/null @@ -1,210 +0,0 @@ -////////////////////////////////////////////////////////////////////////////////////// -// This file is distributed under the University of Illinois/NCSA Open Source License. -// See LICENSE file in top directory for details. -// -// Copyright (c) 2017 Jeongnim Kim and QMCPACK developers. -// -// File developed by: Eric Neuscamman, eneuscamman@berkeley.edu, University of California, Berkeley -// Nick Blunt, nicksblunt@gmail.com, University of Cambridge -// -// File created by: Eric Neuscamman, eneuscamman@berkeley.edu, University of California, Berkeley -////////////////////////////////////////////////////////////////////////////////////// - -#ifndef QMCPLUSPLUS_SLATERDETOPT_H -#define QMCPLUSPLUS_SLATERDETOPT_H - -#include "QMCWaveFunctions/Fermion/DiracDeterminantBase.h" -#include - -namespace qmcplusplus -{ -class TrialWaveFunction; - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/// \brief A class for a Slater determinant with optimizable orbitals. -/// -/////////////////////////////////////////////////////////////////////////////////////////////////// -class SlaterDetOpt : public DiracDeterminantBase -{ - // private data members -private: - /// \brief pointer to the set of optimizable single particle orbitals - //SPOSet * m_spo; - - /// \brief whether this is for up or down spins (0 for up, 1 for down) - int m_up_or_down; - - /// \brief index of the determinant's first electron - int m_first; - - /// \brief index one past the determinant's last electron - int m_last; - - /// \brief number of electrons - int m_nel; - - /// \brief total number of molecular orbitals (i.e. linear combinations) in the optimizable set, including those not occupied in this determinant - int m_nmo; - - /// \brief number of linear combinations of basis functions (i.e. molecular orbitals) - int m_nlc; - - /// \brief number of basis functions - int m_nb; - - // Ratio of new to old values of the wave function, after a particle move. - ValueType curRatio; - - /// \brief matrix of orbital values for orbitals in this determinant - SPOSet::ValueMatrix_t m_orb_val_mat; - - /// \brief inverse of the orbital value matrix - SPOSet::ValueMatrix_t m_orb_inv_mat; - - /// \brief matrix of orbital gradients for orbitals in this determinant (each element is a length 3 tiny vector) - SPOSet::GradMatrix_t m_orb_der_mat; - - /// \brief matrix of x,y,z summed orbital laplacians for orbitals in this determinant (each element is the sum of the d2dx2, d2dy2, and d2dz2 derivatives for the orbital) - SPOSet::ValueMatrix_t m_orb_lap_mat; - - /// \brief matrix of orbital values for all molecular orbitals - SPOSet::ValueMatrix_t m_orb_val_mat_all; - - /// \brief matrix of orbital gradients for all molecular orbitals (each element is a length 3 tiny vector) - SPOSet::GradMatrix_t m_orb_der_mat_all; - - /// \brief matrix of x,y,z summed orbital laplacians for all molecular orbitals (each element is the sum of the d2dx2, d2dy2, and d2dz2 derivatives for the orbital) - SPOSet::ValueMatrix_t m_orb_lap_mat_all; - - /// \brief vector of orbital values for orbitals in this determinant for a particular particle - SPOSet::ValueVector_t m_orb_val_vec; - - /// \brief vector of orbital gradients for orbitals in this determinant for a particular particle - SPOSet::GradVector_t m_orb_der_vec; - - /// \brief vector of x,y,z summed orbital laplacians for orbitals in this determinant for a particular particle - SPOSet::ValueVector_t m_orb_lap_vec; - - /// \brief matrix to hold partial derivatives of the log of determinant with respect to molecular orbital values - SPOSet::ValueMatrix_t m_dp0; - - /// \brief matrix to hold partial derivatives of the local energy with respect to molecular orbital values - SPOSet::ValueMatrix_t m_dh0; - - /// \brief matrix to hold partial derivatives of the local energy with respect to molecular orbital gradients - SPOSet::ValueMatrix_t m_dh1; - - /// \brief matrix to hold partial derivatives of the local energy with respect to molecular orbital laplacians - SPOSet::ValueMatrix_t m_dh2; - - /// \brief workspace - std::vector m_work; - - /// \brief pivot workspace - std::vector m_pivot; - - // protected data members -protected: - /// \brief position of the first of this object's optimizable variables in the overall list of optimizable variables - int m_first_var_pos; - - /// \brief vector of active rotation indices, stored in pairs with the first element of the pair less than the second - std::vector> m_act_rot_inds; - - /// \brief matrix of derivatives of Log(Psi) w.r.t. the m_nlc by m_nlc orbital rotation matrix C - std::vector m_pder_mat; - - /// \brief matrix of derivatives of (H Psi) / Psi w.r.t. the m_nlc by m_nlc orbital rotation matrix C - std::vector m_hder_mat; - - // private member functions -private: - WaveFunctionComponent::RealType evaluate_matrices_from_scratch(ParticleSet& P, const bool all); - - // public type definitions -public: - typedef OrbitalSetTraits::IndexVector_t IndexVector_t; - typedef OrbitalSetTraits::ValueVector_t ValueVector_t; - typedef OrbitalSetTraits::GradVector_t GradVector_t; - typedef OrbitalSetTraits::HessMatrix_t HessMatrix_t; - typedef OrbitalSetTraits::HessType HessType; - typedef Array HessArray_t; - typedef TinyVector GGGType; - typedef Vector GGGVector_t; - typedef Matrix GGGMatrix_t; - typedef ParticleSet::Walker_t Walker_t; - - // public member functions -public: - SlaterDetOpt(ParticleSet& targetPtcl, SPOSet* spo_ptr, const int up_or_down); - - ~SlaterDetOpt(); - - //void add_orbs_to_tf(TrialWaveFunction & twf, const std::string & name); - - void check_index_sanity() const; - - void initialize_matrices(); - - void exponentiate_matrix(const int n, RealType* const mat); - - void set_optimizable_rotation_ranges(const int istart, const int iend, const int jstart, const int jend); - - void buildOptVariables(std::vector& input_params, bool params_supplied, bool print_vars); - - void checkInVariables(opt_variables_type& active); - - void checkOutVariables(const opt_variables_type& active); - - void resetParameters(const opt_variables_type& active); - - void resize(int m_nel, int m_nmo); - - RealType evaluateLog(ParticleSet& P, ParticleSet::ParticleGradient_t& G, ParticleSet::ParticleLaplacian_t& L); - - GradType evalGrad(ParticleSet& P, int iat); - - ValueType ratioGrad(ParticleSet& P, int iat, GradType& grad_iat); - - ValueType ratio(ParticleSet& P, int iat); - - void acceptMove(ParticleSet& P, int iat); - - void restore(int iat); - - void registerData(ParticleSet& P, WFBufferType& buf); - - RealType updateBuffer(ParticleSet& P, WFBufferType& buf, bool fromscratch = false); - - void copyFromBuffer(ParticleSet& P, WFBufferType& buf); - - SlaterDetOpt* makeCopy(SPOSet* spo) const; - - void add_derivatives(const int nl, - const int np, - const RealType* const dp0, - const RealType* const dh0, - const RealType* const dh1, - const RealType* const dh2, - const RealType* const Bchi, - const RealType* const dBchi, - const RealType* const d2Bchi); - - void add_grad_derivatives(const int nl, - const int np, - const RealType* const dh0, - const RealType* const dh1, - const RealType* const Bchi, - const RealType* const dBchi); - - void evaluateDerivatives(ParticleSet& P, - const opt_variables_type& optvars, - std::vector& dlogpsi, - std::vector& dhpsioverpsi); - - void evaluateGradDerivatives(const ParticleSet::ParticleGradient_t& G_in, std::vector& dgradlogpsi); -}; - -} // namespace qmcplusplus - -#endif diff --git a/src/QMCWaveFunctions/MolecularOrbitals/LCOrbitalSetOpt.h b/src/QMCWaveFunctions/MolecularOrbitals/LCOrbitalSetOpt.h deleted file mode 100644 index bc20e4b45..000000000 --- a/src/QMCWaveFunctions/MolecularOrbitals/LCOrbitalSetOpt.h +++ /dev/null @@ -1,826 +0,0 @@ -////////////////////////////////////////////////////////////////////////////////////// -// This file is distributed under the University of Illinois/NCSA Open Source License. -// See LICENSE file in top directory for details. -// -// Copyright (c) 2017 Jeongnim Kim and QMCPACK developers. -// -// File developed by: Eric Neuscamman, eneuscamman@berkeley.edu, University of California, Berkeley -// Nick Blunt, nicksblunt@gmail.com, University of Cambridge -// -// File created by: Eric Neuscamman, eneuscamman@berkeley.edu, University of California, Berkeley -////////////////////////////////////////////////////////////////////////////////////// - -#ifndef QMCPLUSPLUS_LINEARCOMIBINATIONORBITALSET_OPTIMIZABLE_H -#define QMCPLUSPLUS_LINEARCOMIBINATIONORBITALSET_OPTIMIZABLE_H - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -namespace qmcplusplus -{ -/////////////////////////////////////////////////////////////////////////////////////////////////// -/// \brief A class for a set of optimizable linear combinations of the single particle orbitals -/// provided by either another SPO set or by a basis set of the templated type BS. -/// We refer to the linear combinations of basis orbitals as molecular orbitals. -/// The set of molecular orbitals is optimized by rotating them amongst each other. -/// -/////////////////////////////////////////////////////////////////////////////////////////////////// -template -class LCOrbitalSetOpt : public SPOSet -{ - // protected data members -protected: - /// \brief pointer that, if not null, will be used to evaluate the basis orbitals - SPOSet* m_spo_set; - - /// \brief pointer to the basis set that evaluates the basis orbitals if m_spo_set == 0 - BS* m_basis_set; - - /// \brief number of linear combinations of basis functions (i.e. molecular orbitals) - int m_nlc; - - /// \brief number of basis functions - int m_nb; - - /// \brief the level of printing - int m_report_level; - - /// For use by the LCOrbitalSetOpt class, derived from this: - /// the column-major-order m_nb by m_nlc matrix of orbital coefficients - /// resulting from a rotation of the old coefficients - std::vector m_B; - - /// the column-major-order m_nb by m_nlc initial orbital coefficients - /// at the start of the simulation, from which rotations are performed - std::vector m_init_B; - - /// \brief workspace matrix - std::vector m_lc_coeffs; - - /// \brief workspace matrix - std::vector m_basis_vals; - - /// \brief workspace matrix - std::vector m_basis_der1; - - /// \brief workspace matrix - std::vector m_basis_der2; - - /// \brief vector to put temporary orbital data in - ValueVector_t m_temp_p; - - /// \brief vector to put temporary gradient data in - GradVector_t m_temp_g; - - /// \brief vector to put temporary laplacian data in - ValueVector_t m_temp_l; - - /// \brief factor controlling how much to mix the initial orbitals - double m_omixfac; - - // protected member functions -protected: - /////////////////////////////////////////////////////////////////////////////////////////////////// - /// \brief Ensures the supplied dimension is reasonable and throws an exception if not - /// - /// \param[in] name a name for the thing whose dimension in being checked - /// \param[in] caller a name for the calling function - /// \param[in] n the dimension - /// \param[in] s the maximum allowed length for the dimension - /// - /////////////////////////////////////////////////////////////////////////////////////////////////// - void check_input_dim(const std::string& name, const std::string& caller, const int n, const int s) const - { - // ensure dimension is nonzero - if (n <= 0) - throw std::runtime_error(name + " has a length less than one in " + caller); - - // ensure vector is not too long - if (n > s) - throw std::runtime_error(name + " is too long in " + caller); - } - - /// \brief vector to hold orbital indices - std::vector m_oidx; - - /// \brief vector to hold particle indices - std::vector m_pidx; - - /////////////////////////////////////////////////////////////////////////////////////////////////// - /// \brief Place the indices from a range of indices specified by iterators into a vector. - /// Note that the vector may be longer than the index range (it is not shrunk to fit it) - /// but that an iterator to the end of the range is returned. - /// - /// \param[in] start iterator for the start of the range (should dereference to int) - /// \param[in] end iterator for the end of the range (should dereference to int) - /// \param[in] vec vector to store the range in - /// - /// \return iterator to the end of the entered range - /// - /////////////////////////////////////////////////////////////////////////////////////////////////// - template - static std::vector::iterator prepare_index_vector(IntIter start, IntIter end, std::vector& vec) - { - // get the length - int length = 0; - for (IntIter s = start; s != end; s++) - length++; - - // expand the vector if necessary - ensure_vector_is_big_enough(vec, length); - - // put the values in the vector - std::copy(start, end, vec.begin()); - - // return an iterator to the end of the range inside the vector - return (vec.begin() + length); - } - - /////////////////////////////////////////////////////////////////////////////////////////////////// - /// \brief Place a range of contiguous indices [start,end) into a vector. - /// Note that the vector may be longer than the index range (it is not shrunk to fit it) - /// but an iterator to the end of the range returned. - /// - /// \param[in] start start of the range - /// \param[in] end end of the range - /// \param[in] vec vector to store the range in - /// - /// \return iterator to the end of the entered range - /// - /////////////////////////////////////////////////////////////////////////////////////////////////// - static std::vector::iterator prepare_index_vector_contiguous(const int start, - const int end, - std::vector& vec) - { - // check sanity - if (end < start) - throw std::runtime_error("end is less than start in prepare_index_vector_contiguous"); - - // expand the vector if necessary - ensure_vector_is_big_enough(vec, end - start); - - // put the range into the vector - std::vector::iterator it = vec.begin(); - for (int i = start; i < end; i++, it++) - *it = i; - - // return the end of the range - return it; - } - - /////////////////////////////////////////////////////////////////////////////////////////////////// - /// \brief Enlarges the supplied vector if it is not big enough - /// - /// \param[in,out] v the vector - /// \param[in] n the minimum length we want the vector to have - /// - /////////////////////////////////////////////////////////////////////////////////////////////////// - template - static void ensure_vector_is_big_enough(T& v, const size_t n) - { - if (v.size() < n) - v.resize(n); - } - - // public member functions -public: - /////////////////////////////////////////////////////////////////////////////////////////////////// - /// \brief initializes this object and its data. In particular, the number of atomic and - /// molecular orbitals, and the arrays to hold the rotated and unrotated orbitals - /// themselves. Also performs mixing of orbitals, if requested, and prints them. - /// - /// \param[in] mix_factor factor controlling mixing of the initial orbitals - /// - /////////////////////////////////////////////////////////////////////////////////////////////////// - void init_LCOrbitalSetOpt(const double mix_factor) - { - m_omixfac = mix_factor; - - m_nlc = OrbitalSetSize; - m_nb = BasisSetSize; - - m_B.resize(m_nlc * m_nb, 0.0); - m_init_B.resize(m_nlc * m_nb, 0.0); - - std::copy(C->data(), C->data() + m_B.size(), m_B.begin()); - std::copy(C->data(), C->data() + m_init_B.size(), m_init_B.begin()); - - // if requested, mix the initial basis orbitals together - if (mix_factor != 0.0) - { - // mix - for (int i = m_nb - 1; i >= 0; i--) - { - for (int j = 0; j < m_nlc; j++) - { - m_B.at(i + j * m_nb) += mix_factor * 2.0 * (Random() - 0.5); - } - } - - // re-orthonormalize - for (int j = 0; j < m_nlc; j++) - { - const RealType norm = std::abs(std::sqrt(BLAS::dot(m_nb, &m_B.at(0 + j * m_nb), &m_B.at(0 + j * m_nb)))); - BLAS::scal(m_nb, static_cast(1) / norm, &m_B.at(0 + j * m_nb)); - for (int k = j + 1; k < m_nlc; k++) - { - const RealType x = BLAS::dot(m_nb, &m_B.at(0 + j * m_nb), &m_B.at(0 + k * m_nb)); - BLAS::axpy(m_nb, -x, &m_B.at(0 + j * m_nb), 1, &m_B.at(0 + k * m_nb), 1); - } - } - - m_init_B = m_B; - } - - this->print_B(); - } - - - /////////////////////////////////////////////////////////////////////////////////////////////////// - /// \brief rotate m_init_B to m_B - /// \param[in] rot_mat rotation matrix - /// - /////////////////////////////////////////////////////////////////////////////////////////////////// - void rotate_B(const std::vector& rot_mat) - { - // get the linear combination coefficients by applying the rotation to the old coefficients - BLAS::gemm('N', 'T', m_nb, m_nlc, m_nlc, RealType(1.0), m_init_B.data(), m_nb, rot_mat.data(), m_nlc, RealType(0.0), - m_B.data(), m_nb); - } - - /////////////////////////////////////////////////////////////////////////////////////////////////// - /// \brief constructor from basis set and reporting level - /// - /// \param[in] bs pointer to the basis set to use - /// \param[in] rl reporting level to use - /// - /////////////////////////////////////////////////////////////////////////////////////////////////// - LCOrbitalSetOpt(BS* const bs = 0, const int rl = 0) : m_spo_set(0), m_basis_set(0), m_report_level(rl), m_omixfac(0) - { - className = "LCOrbitalSetOpt"; - // set the basis set - if (bs) - this->setBasisSet(bs); - - // initialize number of molecular orbitals as zero - setOrbitalSetSize(0); - } - - /////////////////////////////////////////////////////////////////////////////////////////////////// - /// \brief constructor from SPO set and reporting level - /// - /// \param[in] spo pointer to the spo set to use - /// \param[in] rl reporting level to use - /// - /////////////////////////////////////////////////////////////////////////////////////////////////// - LCOrbitalSetOpt(SPOSet* const spo, const int rl = 0) : m_spo_set(0), m_basis_set(0), m_report_level(rl), m_omixfac(0) - { - // set the internal SPO set - if (spo) - this->setSPOSet(spo); - - // initialize number of molecular orbitals as zero - setOrbitalSetSize(0); - } - - /////////////////////////////////////////////////////////////////////////////////////////////////// - /// \brief the destructor, which assumes deallocation of basis set is done elsewhere - /// - /////////////////////////////////////////////////////////////////////////////////////////////////// - ~LCOrbitalSetOpt() {} - - /////////////////////////////////////////////////////////////////////////////////////////////////// - /// \brief returns that this is indeed an LCOrbitalSetOpt object - /// - /////////////////////////////////////////////////////////////////////////////////////////////////// - bool is_of_type_LCOrbitalSetOpt() const { return true; } - - /////////////////////////////////////////////////////////////////////////////////////////////////// - /// \brief print the molecular orbital coefficients, one MO per column - /// - /////////////////////////////////////////////////////////////////////////////////////////////////// - void print_B() - { - app_log() << std::endl; - app_log() << "printing molecular orbital coefficients" << std::endl; - for (int i = 0; i < m_nb; i++) - { - for (int j = 0; j < m_nlc; j++) - app_log() << " " << std::right << std::fixed << std::setprecision(16) << std::setw(22) << m_B.at(i + j * m_nb); - app_log() << std::endl; - } - app_log() << std::endl; - } - - /////////////////////////////////////////////////////////////////////////////////////////////////// - /// \brief set the basis set the object should use - /// - /// \param[in] bs pointer to the basis set to use - /// - /////////////////////////////////////////////////////////////////////////////////////////////////// - void setBasisSet(BS* const bs) - { - // error if the pointer is empty - if (!bs) - throw std::runtime_error("basis set pointer was empty in LCOrbitalSetOpt::setBasisSet"); - - // remember the basis set - m_basis_set = bs; - - // extract the number of single particle orbitals in the basis set - this->BasisSetSize = m_basis_set->getBasisSetSize(); - } - - /////////////////////////////////////////////////////////////////////////////////////////////////// - /// \brief set the internal SPO set object to use - /// - /// \param[in] spo pointer to the SPO set to use - /// - /////////////////////////////////////////////////////////////////////////////////////////////////// - void setSPOSet(SPOSet* const spo) - { - // error if the pointer is empty - if (!spo) - throw std::runtime_error("spo set pointer was empty in LCOrbitalSetOpt::setSPOSet"); - - // remember the basis set - m_spo_set = spo; - - // extract the number of single particle orbitals in the basis set - this->BasisSetSize = m_spo_set->getOrbitalSetSize(); - } - - /////////////////////////////////////////////////////////////////////////////////////////////////// - /// \brief clone the object (specialization of the base class virtual function) - /// - /// This is a specialization of the SPOSet class virtual function. - /// - /// \return a base class pointer to the clone - /// - /////////////////////////////////////////////////////////////////////////////////////////////////// - SPOSet* makeClone() const - { - // create a clone that contains a cloned spo set or basis set - LCOrbitalSetOpt* retval; - - if (m_spo_set) - retval = new LCOrbitalSetOpt(m_spo_set->makeClone(), m_report_level); - else - retval = new LCOrbitalSetOpt(m_basis_set->makeClone(), m_report_level); - - retval->C = C; - retval->setOrbitalSetSize(OrbitalSetSize); - retval->init_LCOrbitalSetOpt(0.0); - - retval->m_B = m_B; - retval->m_init_B = m_init_B; - - // return the clone - return retval; - } - - /////////////////////////////////////////////////////////////////////////////////////////////////// - /// \brief reset the basis's target particleset - /// - /// This is a specialization of the SPOSet class virtual function. - /// - /// \param[in,out] P ??? - /// - /////////////////////////////////////////////////////////////////////////////////////////////////// - void resetTargetParticleSet(ParticleSet& P) - { - if (m_spo_set) - m_spo_set->resetTargetParticleSet(P); - else - m_basis_set->resetTargetParticleSet(P); - } - - /////////////////////////////////////////////////////////////////////////////////////////////////// - /// \brief Nothing to do for this as the variable rotations are handled by the trial function - /// component subobject. - /// - /// \param[in] optvars not used here - /// - /////////////////////////////////////////////////////////////////////////////////////////////////// - void resetParameters(const opt_variables_type& optvars) - { - //app_log() << "WARNING: LCOrbitalSetOpt::resetParameters is not doing anything" << std::endl; - } - - /////////////////////////////////////////////////////////////////////////////////////////////////// - /// \brief set the number of linear combinations of basis functions (i.e. molecular orbitals) - /// - /// This is a specialization of the SPOSet class virtual function. - /// - /// \param[in] norbs how many linear combinations are desired - /// - /////////////////////////////////////////////////////////////////////////////////////////////////// - void setOrbitalSetSize(int norbs) - { - // record the number of linear combinations (i.e. molecular orbitals) - OrbitalSetSize = norbs; - app_log() << "LCOrbitalSetOpt finished setOrbitalSetSize with norbs = " << norbs << std::endl; - } - - // !!! this function does not appear to be callable via the base class pointer as it is not virtual in SPOSet - // inline int getBasisSetSize() const - // { - // return (m_basis_set==0)? 0: m_basis_set->getBasisSetSize(); - // } - - /////////////////////////////////////////////////////////////////////////////////////////////////// - /// \brief Evaluates the values, x,y,z derivatives, and x-y-z-summed second derivatives of the - /// specified linear combinations of basis set orbitals at the specified particles' - /// positions. - /// - /// \param[in] P Object containing information on particle positions. - /// \param[in] mt the move type: 'p' for particle move, 'w' for walker move - /// \param[in] ostart Iterator for the start of the index range specifying which linear combinations of orbitals to evaluate. - /// \param[in] oend Iterator for the end of the index range specifying which linear combinations of orbitals to evaluate. - /// \param[in] pstart Iterator for the start of the index range specifying which particles' positions to use. - /// \param[in] pend Iterator for the end of the index range specifying which particles' positions to use. - /// \param[in,out] vmat On input, points to an array of length (# of linear combinations) * (# of particle). - /// On exit, holds a column-major-ordered (# of linear combinations) by (# of particle) matrix - /// of the values of the specified linear combinations for the specified particles' positions. - /// \param[in,out] gmat On input, points to an array of length (# of linear combinations) * (# of particle). - /// On exit, holds a column-major-ordered (# of linear combinations) by (# of particle) matrix, - /// each element of which is a length 3 vector containing the x,y,z gradients of the values in vmat. - /// \param[in,out] lmat On input, points to an array of length (# of linear combinations) * (# of particle). - /// On exit, holds a column-major-ordered (# of linear combinations) by (# of particle) matrix, - /// each element of which is the sum of x^2, y^2, and z^2 second derivatives of the values in vmat. - /// - /////////////////////////////////////////////////////////////////////////////////////////////////// - void evaluate_notranspose_general(const ParticleSet& P, - const char mt, - std::vector::const_iterator ostart, - std::vector::const_iterator oend, - std::vector::const_iterator pstart, - std::vector::const_iterator pend, - ValueType* const vmat, - GradType* const gmat, - ValueType* const lmat) - { - // get the number of linear combinations - const int no = std::distance(ostart, oend); - - // get the number of particles - const int np = std::distance(pstart, pend); - - // get the number of basis orbitals - const int nb = BasisSetSize; - - // check sanity of matrix dimensions - assert(no > 0); - assert(np > 0); - assert(nb > 0); - assert(nb >= no); - assert(nb >= np); - - // resize the temporary arrays if they are not big enough - ensure_vector_is_big_enough(m_lc_coeffs, no * nb); - ensure_vector_is_big_enough(m_basis_vals, np * nb); - ensure_vector_is_big_enough(m_basis_der1, 3 * np * nb); - ensure_vector_is_big_enough(m_basis_der2, np * nb); - if (m_temp_p.size() != nb) - m_temp_p.resize(nb); - if (m_temp_g.size() != nb) - m_temp_g.resize(nb); - if (m_temp_l.size() != nb) - m_temp_l.resize(nb); - - // get convenient name for iterator type - typedef std::vector::const_iterator Iter; - - // choose whether to use careful loops or BLAS copies for moving gradient data - const bool careful_loops_for_grad = true; - - // Evaluate and store the basis values, derivatives, and second derivatives for each particle position. - // We store these data in five column-major-ordered (# of basis states) by (# of particles) matrices, - // ( 1 matrix in m_basis_vals, 1 matrix in m_basis_der2, and 3 matrices in m_basis_der1 ) - { - int i = 0; - for (Iter it = pstart; it != pend; it++, i++) - { - // evaluate basis set data using the internal spo set if we have one - if (m_spo_set) - m_spo_set->evaluate(P, *it, m_temp_p, m_temp_g, m_temp_l); - - // evaluate basis set data for a particle move - else if (mt == 'p') - m_basis_set->evaluateAllForPtclMove(P, *it); - - // evaluate basis set data for a walker move - else if (mt == 'w') - m_basis_set->evaluateForWalkerMove(P, *it); - - // error for no internal spo set and an unknown move type - else - throw std::runtime_error("unknown move type in LCOrbitalSetOpt::evaluate_notranspose_general"); - - // sanity checks - if (m_basis_set) - { - assert(m_basis_set->Phi.size() == nb); - assert(m_basis_set->d2Phi.size() == nb); - assert(m_basis_set->dPhi.size() == nb); - assert(m_basis_set->dPhi[0].size() == 3); - } - - // get references to the basis set data - ValueVector_t& data_p = (m_spo_set ? m_temp_p : m_basis_set->Phi); - GradVector_t& data_g = (m_spo_set ? m_temp_g : m_basis_set->dPhi); - ValueVector_t& data_l = (m_spo_set ? m_temp_l : m_basis_set->d2Phi); - - // copy values into a column of the basis value matrix - BLAS::copy(nb, &data_p[0], 1, &m_basis_vals[i * nb], 1); - - // copy summed 2nd derivatives into a column of the basis 2nd derivative matrix - BLAS::copy(nb, &data_l[0], 1, &m_basis_der2[i * nb], 1); - - // copy 1st derivatives into columns of the three different basis 1st derivative matrices - if (careful_loops_for_grad) - { - for (int p = 0; p < 3; p++) - for (int j = 0; j < nb; j++) - m_basis_der1[j + i * nb + p * np * nb] = data_g[j][p]; - } - else - { - for (int p = 0; p < 3; p++) - BLAS::copy(nb, &data_g[0][p], 3, &m_basis_der1[i * nb + p * np * nb], 1); - } - } - } - - // Store the slice of the linear combination coefficient matrix that we need in a column-major-ordered - // (# of linear combinations) by (# of basis states) matrix. - { - int i = 0; - for (Iter it = ostart; it != oend; it++, i++) - BLAS::copy(nb, &(*m_B.begin()) + (*it) * nb, 1, &m_lc_coeffs[i], no); - } - - // print what is in C - if (false) - { - app_log() << "printing C" << std::endl; - std::vector buff(1000, ' '); - for (int i = 0; i < BasisSetSize; i++) - { - for (int j = 0; j < OrbitalSetSize; j++) - { - const int len = std::sprintf(&buff[0], " %12.6f", m_B[i + j * BasisSetSize]); - for (int k = 0; k < len; k++) - app_log() << buff[k]; - } - app_log() << std::endl; - } - app_log() << std::endl; - throw std::runtime_error("done printing C"); - } - - // compute the matrix of linear combination values for each particle - BLAS::gemm('N', 'N', no, np, nb, ValueType(1.0), &m_lc_coeffs[0], no, &m_basis_vals[0], nb, ValueType(0.0), vmat, - no); - - // compute the matrix of summed 2nd derivatives of linear combinations for each particle - BLAS::gemm('N', 'N', no, np, nb, ValueType(1.0), &m_lc_coeffs[0], no, &m_basis_der2[0], nb, ValueType(0.0), lmat, - no); - - // compute the matrix of 1st derivatives of linear combinations for each particle (using m_basis_vals as temporary storage) - for (int p = 0; p < 3; p++) - { - BLAS::gemm('N', 'N', no, np, nb, ValueType(1.0), &m_lc_coeffs[0], no, &m_basis_der1[p * np * nb], nb, - ValueType(0.0), &m_basis_vals[0], no); - if (careful_loops_for_grad) - { - for (int j = 0; j < np; j++) - for (int i = 0; i < no; i++) - gmat[i + j * no][p] = m_basis_vals[i + j * no]; - } - else - { - BLAS::copy(no * np, &m_basis_vals[0], 1, &gmat[0][p], 3); - } - } - } - - /////////////////////////////////////////////////////////////////////////////////////////////////// - /// \brief Evaluates the values, x,y,z derivatives, and x-y-z-summed second derivatives of the - /// linear combinations in the range [os,oe) at the particle positions in the range [ps,pe). - /// - /// \param[in] P Object containing information on particle positions. - /// \param[in] mt the move type: 'p' for particle move, 'w' for walker move - /// \param[in] os Beginning of the range specifying which linear combinations of orbitals to evaluate. - /// \param[in] oe End of the range specifying which linear combinations of orbitals to evaluate. - /// \param[in] ps Beginning of the range specifying which particles' positions to use. - /// \param[in] pe End of the range specifying which particles' positions to use. - /// \param[in,out] vmat On input, points to an array of length (# of linear combinations) * (# of particle). - /// On exit, holds a column-major-ordered (# of linear combinations) by (# of particle) matrix - /// of the values of the specified linear combinations for the specified particles' positions. - /// \param[in,out] gmat On input, points to an array of length (# of linear combinations) * (# of particle). - /// On exit, holds a column-major-ordered (# of linear combinations) by (# of particle) matrix, - /// each element of which is a length 3 vector containing the x,y,z gradients of the values in vmat. - /// \param[in,out] lmat On input, points to an array of length (# of linear combinations) * (# of particle). - /// On exit, holds a column-major-ordered (# of linear combinations) by (# of particle) matrix, - /// each element of which is the sum of x^2, y^2, and z^2 second derivatives of the values in vmat. - /// - /////////////////////////////////////////////////////////////////////////////////////////////////// - void evaluate_notranspose_ranges(const ParticleSet& P, - const char mt, - const int os, - const int oe, - const int ps, - const int pe, - ValueType* const vmat, - GradType* const gmat, - ValueType* const lmat) - { - // check sanity - if (oe < os) - throw std::runtime_error( - "orbitital end (oe) is less than start (os) in LCOrbitalSetOpt::evaluate_notranspose_ranges"); - if (pe < ps) - throw std::runtime_error( - "particle end (pe) is less than start (ps) in LCOrbitalSetOpt::evaluate_notranspose_ranges"); - - // prepare orbital list - std::vector::const_iterator oend = prepare_index_vector_contiguous(os, oe, m_oidx); - - // prepare particle list - std::vector::const_iterator pend = prepare_index_vector_contiguous(ps, pe, m_pidx); - - // evaluate - evaluate_notranspose_general(P, mt, m_oidx.begin(), oend, m_pidx.begin(), pend, vmat, gmat, lmat); - } - - /////////////////////////////////////////////////////////////////////////////////////////////////// - /// \brief Evaluates the values, x,y,z derivatives, and x-y-z-summed second derivatives of the - /// linear combinations in the range [0,logdet.cols()) at the particle positions in the - /// range [first,last). - /// - /// \param[in] P Object containing information on particle positions. - /// \param[in] first Beginning of the range specifying which particles' positions to use. - /// \param[in] last End of the range specifying which particles' positions to use. - /// \param[in,out] logdet On input, a row-major-ordered matrix of dimension (# of particle) by (# of linear combinations). - /// On exit, holds the linear combinations' values for the specified particles' positions. - /// \param[in,out] dlogdet On input, a row-major-ordered matrix of dimension (# of particle) by (# of linear combinations). - /// On exit, holds the linear combinations' x,y,z gradients for the specified particles' positions. - /// each element of which is a length 3 vector containing the x,y,z gradients of the values in vmat. - /// \param[in,out] d2logdet On input, a row-major-ordered matrix of dimension (# of particle) by (# of linear combinations). - /// On exit, each element is the sum of x^2, y^2, and z^2 second derivatives of the values in logdet. - /// - /////////////////////////////////////////////////////////////////////////////////////////////////// - void evaluate_notranspose(const ParticleSet& P, - int first, - int last, - ValueMatrix_t& logdet, - GradMatrix_t& dlogdet, - ValueMatrix_t& d2logdet) - { - //app_log() << "logdet.cols() = " << logdet.cols() << std::endl; - //app_log() << "logdet.rows() = " << logdet.rows() << std::endl; - //app_log() << "dlogdet.cols() = " << dlogdet.cols() << std::endl; - //app_log() << "dlogdet.rows() = " << dlogdet.rows() << std::endl; - //app_log() << "d2logdet.cols() = " << d2logdet.cols() << std::endl; - //app_log() << "d2logdet.rows() = " << d2logdet.rows() << std::endl; - //app_log() << "this->OrbitalSetSize = " << this->OrbitalSetSize << std::endl; - // check sanity - this->check_input_dim("logdet # of columns", "LCOrbitalSetOpt::evaluate_notranspose", logdet.cols(), - OrbitalSetSize); - if (logdet.cols() != dlogdet.cols() || logdet.cols() != d2logdet.cols()) - throw std::runtime_error("logdet, dlogdet, and d2logdet should have the same number of columns in " - "LCOrbitalSetOpt::evaluate_notranspose"); - if (logdet.rows() != dlogdet.rows() || logdet.rows() != d2logdet.rows()) - throw std::runtime_error( - "logdet, dlogdet, and d2logdet should have the same number of rows in LCOrbitalSetOpt::evaluate_notranspose"); - - // evaluate the first logdet.cols() orbitals for the particles in the range [first, last) - this->evaluate_notranspose_ranges(P, 'w', 0, logdet.cols(), first, last, logdet.data(), dlogdet.data(), - d2logdet.data()); - } - - /////////////////////////////////////////////////////////////////////////////////////////////////// - /// \brief Evaluates the values of the linear combinations in the range [0,psi.size()) at a - /// particular particle's position. - /// - /// \param[in] P Object containing information on particle positions. - /// \param[in] iat Index of the particle whose position will be used. - /// \param[in,out] psi On input, a vector of dimension (# of linear combinations). - /// On exit, holds the linear combinations' values for the specified particle position. - /// - /////////////////////////////////////////////////////////////////////////////////////////////////// - inline void evaluate(const ParticleSet& P, int iat, ValueVector_t& psi) - { - // check input vector dimension - this->check_input_dim("psi", "LCOrbitalSetOpt::evaluate", psi.size(), OrbitalSetSize); - - // resize temporary arrays if necessary - if (m_temp_g.size() != BasisSetSize) - m_temp_g.resize(BasisSetSize); - if (m_temp_l.size() != BasisSetSize) - m_temp_l.resize(BasisSetSize); - - // sanity check - if (m_temp_g.size() < psi.size()) - throw std::runtime_error("unexpected too-small size of m_temp_g in LCOrbitalSetOpt::evaluate"); - - // evaluate the first psi.size() orbitals for the particle with index iat - this->evaluate_notranspose_ranges(P, 'p', 0, psi.size(), iat, iat + 1, psi.data(), &m_temp_g[0], &m_temp_l[0]); - } - - /////////////////////////////////////////////////////////////////////////////////////////////////// - /// \brief Evaluates the values, x,y,z derivatives, and x-y-z-summed second derivatives of the - /// linear combinations in the range [0,psi.size()) at the position of particle iat. - /// - /// \param[in] P Object containing information on particle positions. - /// \param[in] iat Index of the particle whose position will be used. - /// \param[in,out] psi On input, a vector of dimension (# of linear combinations). - /// On exit, holds the linear combinations' values for the specified particle position. - /// \param[in,out] dlogdet On input, a vector of dimension (# of linear combinations). - /// On exit, holds the linear combinations' x,y,z gradients for the specified particle position. - /// \param[in,out] d2logdet On input, a vector of dimension (# of linear combinations). - /// On exit, each element is the sum of x^2, y^2, and z^2 second derivatives for the specified particle position. - /// - /////////////////////////////////////////////////////////////////////////////////////////////////// - inline void evaluate(const ParticleSet& P, int iat, ValueVector_t& psi, GradVector_t& dpsi, ValueVector_t& d2psi) - { - // check sanity - this->check_input_dim("d2psi", "LCOrbitalSetOpt::evaluate", d2psi.size(), OrbitalSetSize); - this->check_input_dim("dpsi", "LCOrbitalSetOpt::evaluate", dpsi.size(), OrbitalSetSize); - this->check_input_dim("psi", "LCOrbitalSetOpt::evaluate", psi.size(), OrbitalSetSize); - if (psi.size() != dpsi.size() || psi.size() != d2psi.size()) - throw std::runtime_error("psi, dpsi, and d2psi vectors must be the same length in LCOrbitalSetOpt::evaluate"); - - // evaluate the first psi.size() orbitals and derivatives for the particle with index iat - this->evaluate_notranspose_ranges(P, 'p', 0, psi.size(), iat, iat + 1, psi.data(), dpsi.data(), d2psi.data()); - } - - /////////////////////////////////////////////////////////////////////////////////////////////////// - /// \brief An evaluate function that has not yet been implemented. - /// - /////////////////////////////////////////////////////////////////////////////////////////////////// - void evaluate_notranspose(const ParticleSet& P, - int first, - int last, - ValueMatrix_t& logdet, - GradMatrix_t& dlogdet, - HessMatrix_t& grad_grad_logdet) - { - throw std::runtime_error( - "LCOrbitalSetOpt::evaluate_notranspose(P, first, last, logdet, dlogdet, grad_grad_logdet) not implemented"); - } - - /////////////////////////////////////////////////////////////////////////////////////////////////// - /// \brief An evaluate function that has not yet been implemented. - /// - /////////////////////////////////////////////////////////////////////////////////////////////////// - void evaluate_notranspose(const ParticleSet& P, - int first, - int last, - ValueMatrix_t& logdet, - GradMatrix_t& dlogdet, - HessMatrix_t& grad_grad_logdet, - GGGMatrix_t& grad_grad_grad_logdet) - { - throw std::runtime_error("LCOrbitalSetOpt::evaluate_notranspose(P, first, last, logdet, dlogdet, grad_grad_logdet, " - "grad_grad_grad_logdet) not implemented"); - } - - /////////////////////////////////////////////////////////////////////////////////////////////////// - /// \brief An evaluate function that has not yet been implemented. - /////////////////////////////////////////////////////////////////////////////////////////////////// - void evaluateDetRatios(const VirtualParticleSet& VP, - ValueVector_t& psi, - const ValueVector_t& psiinv, - std::vector& ratios) - { - throw std::runtime_error( - "LCOrbitalSetOpt::evaluateDetRatios() not implemented in AoS LCAO! Avoid using the batched algorithm."); - } - - /////////////////////////////////////////////////////////////////////////////////////////////////// - /// \brief An evaluate function that has not yet been implemented. - /// - /////////////////////////////////////////////////////////////////////////////////////////////////// - void evaluateThirdDeriv(const ParticleSet& P, int first, int last, GGGMatrix_t& grad_grad_grad_logdet) - { - throw std::runtime_error( - "LCOrbitalSetOpt::evaluateThirdDeriv(P, first, last, grad_grad_grad_logdet) not yet implemented"); - } -}; - -} // end namespace qmcplusplus - -#endif diff --git a/src/QMCWaveFunctions/MolecularOrbitals/MolecularSPOBuilder.h b/src/QMCWaveFunctions/MolecularOrbitals/MolecularSPOBuilder.h index c12f13498..4c157492b 100644 --- a/src/QMCWaveFunctions/MolecularOrbitals/MolecularSPOBuilder.h +++ b/src/QMCWaveFunctions/MolecularOrbitals/MolecularSPOBuilder.h @@ -21,9 +21,6 @@ #include "QMCWaveFunctions/MolecularOrbitals/LocalizedBasisSet.h" #include "QMCWaveFunctions/MolecularOrbitals/AtomicBasisBuilder.h" #include "QMCWaveFunctions/MolecularOrbitals/LCOrbitalSet.h" -#ifndef ENABLE_SOA -#include "QMCWaveFunctions/MolecularOrbitals/LCOrbitalSetOpt.h" -#endif #include "Utilities/ProgressReportEngine.h" #include "OhmmsData/AttributeSet.h" #include "io/hdf_archive.h" @@ -265,16 +262,7 @@ public: { if (use_new_opt_class == "yes") { -#ifndef ENABLE_SOA - app_log() << "Creating LCOrbitalSetOpt with the input coefficients" << std::endl; - lcos = new LCOrbitalSetOpt(thisBasisSet, rank() == 0); - if (spo_name != "") - lcos->objectName = spo_name; - else - APP_ABORT("LCOrbitalSetOpt spo set must have a name"); -#else - APP_ABORT("Orbital Rotation is not supported by SoA builds yet!"); -#endif + APP_ABORT("MolecularSPOBuilder Orbital optimization via rotation has been removed in AoS builds.\n"); } else { diff --git a/src/QMCWaveFunctions/SPOSet.cpp b/src/QMCWaveFunctions/SPOSet.cpp index ac24128fe..20b9e9e83 100644 --- a/src/QMCWaveFunctions/SPOSet.cpp +++ b/src/QMCWaveFunctions/SPOSet.cpp @@ -158,13 +158,11 @@ bool SPOSet::put(xmlNodePtr cur) //initialize the number of orbital by the basis set size int norb = BasisSetSize; std::string debugc("no"); - double orbital_mix_magnitude = 0.0; bool PBC = false; OhmmsAttributeSet aAttrib; aAttrib.add(norb, "orbitals"); aAttrib.add(norb, "size"); aAttrib.add(debugc, "debug"); - aAttrib.add(orbital_mix_magnitude, "orbital_mix_magnitude"); aAttrib.put(cur); setOrbitalSetSize(norb); xmlNodePtr occ_ptr = NULL; @@ -226,8 +224,6 @@ bool SPOSet::put(xmlNodePtr cur) app_log() << C << std::endl; } - init_LCOrbitalSetOpt(orbital_mix_magnitude); - return success && success2; } diff --git a/src/QMCWaveFunctions/SPOSet.h b/src/QMCWaveFunctions/SPOSet.h index 56d06b09d..f26996589 100644 --- a/src/QMCWaveFunctions/SPOSet.h +++ b/src/QMCWaveFunctions/SPOSet.h @@ -317,12 +317,6 @@ public: */ virtual void evaluateThirdDeriv(const ParticleSet& P, int first, int last, GGGMatrix_t& grad_grad_grad_logdet); - /////////////////////////////////////////////////////////////////////////////////////////////////// - /// \brief returns whether this is an LCOrbitalSetOpt object - /// Ye: This should be removed as AoS. On the SoA side, LCAOrbitalSet replace LCOrbitalSet and LCOrbitalSetOpt - /////////////////////////////////////////////////////////////////////////////////////////////////// - virtual bool is_of_type_LCOrbitalSetOpt() const { return false; } - /** evaluate the values, gradients and laplacians of this single-particle orbital for [first,last) particles * @param P current ParticleSet * @param first starting index of the particles @@ -430,16 +424,6 @@ public: */ virtual void finalizeConstruction() {} - // Routine to set up data for the LCOrbitalSetOpt child class specifically - // Should be left empty for other derived classes - // Ye: This interface should be removed with AoS. - virtual void init_LCOrbitalSetOpt(const double mix_factor = 0.0){}; - - // Routine to update internal data for the LCOrbitalSetOpt child class specifically - // Should be left empty for other derived classes - // Ye: This interface should be removed with AoS. - virtual void rotate_B(const std::vector& rot_mat){}; - #ifdef QMC_CUDA using CTS = CUDAGlobalTypes; diff --git a/src/QMCWaveFunctions/lcao/LCAOrbitalBuilder.cpp b/src/QMCWaveFunctions/lcao/LCAOrbitalBuilder.cpp index c37ab612b..75cad0c93 100644 --- a/src/QMCWaveFunctions/lcao/LCAOrbitalBuilder.cpp +++ b/src/QMCWaveFunctions/lcao/LCAOrbitalBuilder.cpp @@ -577,8 +577,6 @@ bool LCAOrbitalBuilder::loadMO(LCAOrbitalSet& spo, xmlNodePtr cur) app_log() << *spo.C << std::endl; } - //init_LCOrbitalSetOpt(orbital_mix_magnitude); - return success; } From c3dea18a12a6cd35dce34fd9b3ef5f5f6b1d6866 Mon Sep 17 00:00:00 2001 From: Ye Luo Date: Sun, 20 Oct 2019 11:08:04 -0500 Subject: [PATCH 25/41] Revert change. --- src/Optimize/VariableSet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Optimize/VariableSet.cpp b/src/Optimize/VariableSet.cpp index 49af4f305..6b51f4f35 100644 --- a/src/Optimize/VariableSet.cpp +++ b/src/Optimize/VariableSet.cpp @@ -274,7 +274,7 @@ void VariableSet::print(std::ostream& os, int leftPadSpaces, bool printHeader) << setw(max_value_len) << NameAndValue[i].second << " " << setw(max_type_len) << ParameterType[i].second << " " << setw(max_recompute_len) << Recompute[i].second << " "; -// os << std::defaultfloat; + os << std::defaultfloat; if (Index[i] < 0) os << setw(max_use_len) << "OFF" << std::endl; From 3ecc0d41c6596f2c3fb3a777db2af494f939a678 Mon Sep 17 00:00:00 2001 From: Juha Tiihonen Date: Mon, 21 Oct 2019 13:40:15 -0400 Subject: [PATCH 26/41] Separation of LR handlers for forces and energies --- src/LongRange/LRCoulombSingleton.cpp | 8 ++++---- src/QMCHamiltonians/CoulombPBCAA.cpp | 26 ++++++++++++++++++++------ src/QMCHamiltonians/CoulombPBCAA.h | 5 +++++ 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/src/LongRange/LRCoulombSingleton.cpp b/src/LongRange/LRCoulombSingleton.cpp index 15c8b93b1..070a5952a 100644 --- a/src/LongRange/LRCoulombSingleton.cpp +++ b/src/LongRange/LRCoulombSingleton.cpp @@ -148,10 +148,10 @@ LRCoulombSingleton::LRHandlerType* LRCoulombSingleton::getDerivHandler(ParticleS //APP_ABORT("SR Coulomb Basis Handler has cloning issues. Stress also has some kinks"); if (CoulombDerivHandler == 0) { - app_log() << "\n Creating CoulombHandler with the optimal breakup of SR piece. " << std::endl; - CoulombDerivHandler = new LRHandlerSRCoulomb, LPQHISRCoulombBasis>(ref); - //app_log() << "\n Creating CoulombDerivHandler with the Ewald3D breakup. " << std::endl; - //CoulombDerivHandler= new EwaldHandler3D(ref); + //app_log() << "\n Creating CoulombHandler with the optimal breakup of SR piece. " << std::endl; + //CoulombDerivHandler = new LRHandlerSRCoulomb, LPQHISRCoulombBasis>(ref); + app_log() << "\n Creating CoulombDerivHandler with the Ewald3D breakup. " << std::endl; + CoulombDerivHandler= new EwaldHandler3D(ref); // CoulombDerivHandler = new LRDerivHandler, LPQHIBasis> (ref); //CoulombDerivHandler= new EwaldHandler(ref); CoulombDerivHandler->initBreakup(ref); diff --git a/src/QMCHamiltonians/CoulombPBCAA.cpp b/src/QMCHamiltonians/CoulombPBCAA.cpp index af67030bf..54588bdcb 100644 --- a/src/QMCHamiltonians/CoulombPBCAA.cpp +++ b/src/QMCHamiltonians/CoulombPBCAA.cpp @@ -26,6 +26,9 @@ CoulombPBCAA::CoulombPBCAA(ParticleSet& ref, bool active, bool computeForces) AA(0), myGrid(0), rVs(0), + dAA(0), + myGridforce(0), + rVsforce(0), is_active(active), FirstTime(true), myConst(0.0), @@ -304,6 +307,14 @@ void CoulombPBCAA::initBreakup(ParticleSet& P) { rVs = LRCoulombSingleton::createSpline4RbyVs(AA, myRcut, myGrid); } + if ( ComputeForces ) + { + dAA = LRCoulombSingleton::getDerivHandler(P); + if (rVsforce == 0) + { + rVsforce = LRCoulombSingleton::createSpline4RbyVs(dAA, myRcut, myGridforce); + } + } P.update(); } @@ -318,7 +329,8 @@ CoulombPBCAA::Return_t CoulombPBCAA::evalLRwithForces(ParticleSet& P) RealType Z2 = Zspec[spec2]; for (int iat = 0; iat < grad.size(); iat++) grad[iat] = TinyVector(0.0); - AA->evaluateGrad(P, P, spec2, Zat, grad); + //AA->evaluateGrad(P, P, spec2, Zat, grad); + dAA->evaluateGrad(P, P, spec2, Zat, grad); for (int iat = 0; iat < grad.size(); iat++) forces[iat] += Z2 * grad[iat]; } //spec2 @@ -341,9 +353,10 @@ CoulombPBCAA::Return_t CoulombPBCAA::evalSRwithForces(ParticleSet& P) { RealType V, rV, d_rV_dr, d2_rV_dr2; RealType rinv = 1.0 / dist[j]; - rV = rVs->splint(dist[j], d_rV_dr, d2_rV_dr2); + rV = rVsforce->splint(dist[j], d_rV_dr, d2_rV_dr2); V = rV * rinv; - esum += Zat[j] * V; + //esum += Zat[j] * V; + esum += Zat[j] * rVs->splint(dist[j]) * rinv; PosType grad = Zat[j] * Zat[ipart] * (d_rV_dr - V) * rinv * rinv * dr[j]; forces[ipart] += grad; @@ -360,9 +373,10 @@ CoulombPBCAA::Return_t CoulombPBCAA::evalSRwithForces(ParticleSet& P) { RealType V, rV, d_rV_dr, d2_rV_dr2; RealType rinv = 1.0 / dist[j]; - rV = rVs->splint(dist[j], d_rV_dr, d2_rV_dr2); + rV = rVsforce->splint(dist[j], d_rV_dr, d2_rV_dr2); V = rV * rinv; - esum += Zat[j] * V; + //esum += Zat[j] * V; + esum += Zat[j] * rVs->splint(dist[j]) * rinv; PosType grad = Zat[j] * Zat[NumCenters - ipart] * (d_rV_dr - V) * rinv * rinv * dr[j]; forces[NumCenters - ipart] += grad; @@ -380,7 +394,7 @@ CoulombPBCAA::Return_t CoulombPBCAA::evalSRwithForces(ParticleSet& P) for (int nn = d_aa.M[ipart], jpart = ipart + 1; nn < d_aa.M[ipart + 1]; nn++, jpart++) { RealType rV, d_rV_dr, d2_rV_dr2; - rV = rVs->splint(d_aa.r(nn), d_rV_dr, d2_rV_dr2); + rV = rVsforce->splint(d_aa.r(nn), d_rV_dr, d2_rV_dr2); RealType V = rV * d_aa.rinv(nn); esum += Zat[jpart] * d_aa.rinv(nn) * rV; PosType grad = Zat[jpart] * Zat[ipart] * (d_rV_dr - V) * d_aa.rinv(nn) * d_aa.rinv(nn) * d_aa.dr(nn); diff --git a/src/QMCHamiltonians/CoulombPBCAA.h b/src/QMCHamiltonians/CoulombPBCAA.h index ad8600647..966b404b3 100644 --- a/src/QMCHamiltonians/CoulombPBCAA.h +++ b/src/QMCHamiltonians/CoulombPBCAA.h @@ -38,9 +38,14 @@ struct CoulombPBCAA : public OperatorBase, public ForceBase typedef DistanceTableData::RowContainer RowContainerType; + // energy-optimized LRHandlerType* AA; GridType* myGrid; RadFunctorType* rVs; + // force-optimized + LRHandlerType* dAA; + GridType* myGridforce; + RadFunctorType* rVsforce; bool is_active; bool FirstTime; From b9428093ddc3dab9c073e71e8513beacf9c835bb Mon Sep 17 00:00:00 2001 From: Juha Tiihonen Date: Mon, 21 Oct 2019 13:45:05 -0400 Subject: [PATCH 27/41] Fix a bug and naming in ForceChiesaPBCAA estimator --- src/QMCHamiltonians/ForceChiesaPBCAA.cpp | 27 ++++++++++++------------ src/QMCHamiltonians/ForceChiesaPBCAA.h | 2 +- src/QMCHamiltonians/tests/test_force.cpp | 1 + 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/QMCHamiltonians/ForceChiesaPBCAA.cpp b/src/QMCHamiltonians/ForceChiesaPBCAA.cpp index 50666b3af..83b1ed230 100644 --- a/src/QMCHamiltonians/ForceChiesaPBCAA.cpp +++ b/src/QMCHamiltonians/ForceChiesaPBCAA.cpp @@ -132,10 +132,9 @@ void ForceChiesaPBCAA::initBreakup(ParticleSet& P) minkc = std::min(PtclA.Lattice.LR_kc, P.Lattice.LR_kc); //AB->initBreakup(*PtclB); //initBreakup is called only once - //AB = LRCoulombSingleton::getHandler(*PtclB); - AB = LRCoulombSingleton::getDerivHandler(P); + dAB = LRCoulombSingleton::getDerivHandler(P); // myConst=evalConsts(); - myRcut = AB->get_rc(); //Basis.get_rc(); + myRcut = dAB->get_rc(); //Basis.get_rc(); // create the spline function for the short-range part assuming pure potential // if(V0==0) // { @@ -160,7 +159,7 @@ void ForceChiesaPBCAA::evaluateLR(ParticleSet& P) { for (int iat = 0; iat < grad.size(); iat++) grad[iat] = TinyVector(0.0, 0.0, 0.0); - AB->evaluateGrad(PtclA, P, j, Zat, grad); + dAB->evaluateGrad(PtclA, P, j, Zat, grad); for (int iat = 0; iat < grad.size(); iat++) { forces[iat] += Qspec[j] * grad[iat]; @@ -184,7 +183,7 @@ void ForceChiesaPBCAA::evaluateSR(ParticleSet& P) const RealType r = dist[iat]; const RealType rinv = RealType(1) / r; RealType g_f = g_filter(r); - RealType V = -AB->srDf(r, rinv); + RealType V = -dAB->srDf(r, rinv); PosType drhat = rinv * d_ab.Displacements[jat][iat]; forces[iat] += g_f * Zat[iat] * Qat[jat] * V * drhat; } @@ -206,7 +205,7 @@ void ForceChiesaPBCAA::evaluateSR(ParticleSet& P) RealType V; RealType g_f = g_filter(d_ab.r(nn)); //rV = rVs->splint(d_ab.r(nn), d_rV_dr, d2_rV_dr2); - V = -AB->srDf(d_ab.r(nn), d_ab.rinv(nn)); + V = -dAB->srDf(d_ab.r(nn), d_ab.rinv(nn)); // std::stringstream wee; // wee<<"srDf() #"<srDf(dist[jpart], RealType(1) / dist[jpart]); - PosType grad = -Zat[jpart] * Zat[ipart] * V * dist[jpart] * d_aa.Displacements[ipart][jpart]; + RealType V = -dAB->srDf(dist[jpart], RealType(1) / dist[jpart]); + PosType grad = -Zat[jpart] * Zat[ipart] * V / dist[jpart] * d_aa.Displacements[ipart][jpart]; forces_IonIon[ipart] += grad; forces_IonIon[jpart] -= grad; } } - for (size_t ipart = 0; ipart < NptclA; ++ipart) - std::cout << "debug evaluateSR_AA " << forces_IonIon[ipart] << std::endl; + //for (size_t ipart = 0; ipart < NptclA; ++ipart) + //std::cout << "debug evaluateSR_AA " << forces_IonIon[ipart] << std::endl; } else { @@ -251,7 +250,7 @@ void ForceChiesaPBCAA::evaluateSR_AA() { for (int nn = d_aa.M[ipart], jpart = ipart + 1; nn < d_aa.M[ipart + 1]; nn++, jpart++) { - RealType V = -AB->srDf(d_aa.r(nn), d_aa.rinv(nn)); + RealType V = -dAB->srDf(d_aa.r(nn), d_aa.rinv(nn)); PosType grad = -Zat[jpart] * Zat[ipart] * V * d_aa.rinv(nn) * d_aa.dr(nn); forces_IonIon[ipart] += grad; forces_IonIon[jpart] -= grad; @@ -259,7 +258,7 @@ void ForceChiesaPBCAA::evaluateSR_AA() // app_log() <<"grad[" <(0.0); - AB->evaluateGrad(PtclA, PtclA, spec2, Zat, grad); + dAB->evaluateGrad(PtclA, PtclA, spec2, Zat, grad); for (int iat = 0; iat < grad.size(); iat++) { @@ -347,7 +346,7 @@ bool ForceChiesaPBCAA::put(xmlNodePtr cur) void ForceChiesaPBCAA::resetTargetParticleSet(ParticleSet& P) { - AB->resetTargetParticleSet(P); + dAB->resetTargetParticleSet(P); } void ForceChiesaPBCAA::addObservables(PropertySetType& plist, BufferType& collectables) diff --git a/src/QMCHamiltonians/ForceChiesaPBCAA.h b/src/QMCHamiltonians/ForceChiesaPBCAA.h index e024dbc8d..1fd667d51 100644 --- a/src/QMCHamiltonians/ForceChiesaPBCAA.h +++ b/src/QMCHamiltonians/ForceChiesaPBCAA.h @@ -42,7 +42,7 @@ struct ForceChiesaPBCAA : public OperatorBase, public ForceBase ///source particle set ParticleSet& PtclA; ///long-range Handler - LRHandlerType* AB; + LRHandlerType* dAB; ///number of species of A particle set int NumSpeciesA; ///number of species of B particle set diff --git a/src/QMCHamiltonians/tests/test_force.cpp b/src/QMCHamiltonians/tests/test_force.cpp index 6408d8673..adade128d 100644 --- a/src/QMCHamiltonians/tests/test_force.cpp +++ b/src/QMCHamiltonians/tests/test_force.cpp @@ -164,6 +164,7 @@ TEST_CASE("Chiesa Force", "[hamiltonian]") CrystalLattice Lattice; Lattice.BoxBConds = true; // periodic Lattice.R.diagonal(5.0); + Lattice.LR_dim_cutoff = 25; Lattice.reset(); From b50611753127aec4aafde03a4e2d66116c710259 Mon Sep 17 00:00:00 2001 From: Jaron Krogel Date: Mon, 21 Oct 2019 15:12:42 -0400 Subject: [PATCH 28/41] nexus: enable corrected energy with MPC alone --- nexus/bin/qmca | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/nexus/bin/qmca b/nexus/bin/qmca index 481abca95..7761642b7 100755 --- a/nexus/bin/qmca +++ b/nexus/bin/qmca @@ -1847,6 +1847,10 @@ class DatAnalyzer(QBase): v = data.LocalEnergy - data.ElecElec + data.MPC + data.KEcorr data.CorrectedEnergy = v stats.CorrectedEnergy = self.stat_value(v[nbe:]) + elif 'LocalEnergy' in data and 'ElecElec' in data and 'MPC' in data: + v = data.LocalEnergy - data.ElecElec + data.MPC + data.CorrectedEnergy = v + stats.CorrectedEnergy = self.stat_value(v[nbe:]) #end if if len(data)>0: example = data.first() From 0e3683674523da18709caf2c4fbd4ee636d1182f Mon Sep 17 00:00:00 2001 From: Ye Luo Date: Mon, 21 Oct 2019 17:20:57 -0500 Subject: [PATCH 29/41] Default delay_rank to 32 when >=192 elecs in det. --- .../Fermion/SlaterDetBuilder.cpp | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/QMCWaveFunctions/Fermion/SlaterDetBuilder.cpp b/src/QMCWaveFunctions/Fermion/SlaterDetBuilder.cpp index 3580ec408..c8e6bcb1e 100644 --- a/src/QMCWaveFunctions/Fermion/SlaterDetBuilder.cpp +++ b/src/QMCWaveFunctions/Fermion/SlaterDetBuilder.cpp @@ -416,7 +416,7 @@ bool SlaterDetBuilder::putDeterminant(xmlNodePtr cur, int spin_group) #else std::string useGPU("no"); #endif - int delay_rank(1); + int delay_rank(0); OhmmsAttributeSet sdAttrib; sdAttrib.add(delay_rank, "delay_rank"); sdAttrib.add(optimize, "optimize"); @@ -480,18 +480,19 @@ bool SlaterDetBuilder::putDeterminant(xmlNodePtr cur, int spin_group) #if defined(ENABLE_CUDA) else if (useGPU == "yes") { - app_log() << "Using DiracDeterminant with DelayedUpdateCUDA engine" << std::endl; + app_log() << " Using DiracDeterminant with DelayedUpdateCUDA engine" << std::endl; adet = new DiracDeterminant>(psi,firstIndex); } #endif else { - app_log() << "Using DiracDeterminant with DelayedUpdate engine" << std::endl; + app_log() << " Using DiracDeterminant with DelayedUpdate engine" << std::endl; adet = new DiracDeterminant<>(psi, firstIndex); } #endif } - if (delay_rank <= 0 || delay_rank > lastIndex - firstIndex) + + if (delay_rank < 0 || delay_rank > lastIndex - firstIndex) { std::ostringstream err_msg; err_msg << "SlaterDetBuilder::putDeterminant delay_rank must be positive " @@ -500,10 +501,19 @@ bool SlaterDetBuilder::putDeterminant(xmlNodePtr cur, int spin_group) << "user input " + std::to_string(delay_rank); APP_ABORT(err_msg.str()); } - else if (delay_rank > 1) - app_log() << "Using rank-" << delay_rank << " delayed update" << std::endl; + else if (delay_rank == 0) + { + app_log() << " Setting delay_rank by default!" << std::endl; + if (lastIndex - firstIndex >= 192) + delay_rank = 32; + else + delay_rank = 1; + } + + if (delay_rank > 1) + app_log() << " Using rank-" << delay_rank << " delayed update" << std::endl; else - app_log() << "Using rank-1 Sherman-Morrison Fahy update" << std::endl; + app_log() << " Using rank-1 Sherman-Morrison Fahy update" << std::endl; adet->set(firstIndex, lastIndex - firstIndex, delay_rank); #ifdef QMC_CUDA targetPsi.setndelay(delay_rank); From 2a1c27da6512cab663a29f4e0149d19a1ff21da1 Mon Sep 17 00:00:00 2001 From: Ye Luo Date: Mon, 21 Oct 2019 17:47:27 -0500 Subject: [PATCH 30/41] Skip orbital rotation tests on AoS build. --- tests/molecules/H2_ae/CMakeLists.txt | 26 +++++++++++++------------- tests/molecules/H4_ae/CMakeLists.txt | 5 +++++ 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/tests/molecules/H2_ae/CMakeLists.txt b/tests/molecules/H2_ae/CMakeLists.txt index 3eae16d00..e3730be9a 100644 --- a/tests/molecules/H2_ae/CMakeLists.txt +++ b/tests/molecules/H2_ae/CMakeLists.txt @@ -1,21 +1,21 @@ IF (NOT QMC_CUDA) - IF (NOT QMC_COMPLEX) + IF (NOT QMC_COMPLEX AND ENABLE_SOA) + IF(BUILD_LMYENGINE_INTERFACE) # # H2 test in a DZV basis set, using optimizable determinants, and the adaptive linear method # LIST(APPEND H2_OPT_SCALARS "totenergy" "-1.124563 0.00084") # total energy - IF(BUILD_LMYENGINE_INTERFACE) - QMC_RUN_AND_CHECK(short-H2-orb-opt - "${CMAKE_SOURCE_DIR}/tests/molecules/H2_ae" - H2 - h2_orb_opt.xml - 16 1 - ${MP_SUCCESS} - 10 H2_OPT_SCALARS # Final VMC step - TRUE) + QMC_RUN_AND_CHECK(short-H2-orb-opt + "${CMAKE_SOURCE_DIR}/tests/molecules/H2_ae" + H2 + h2_orb_opt.xml + 16 1 + ${MP_SUCCESS} + 10 H2_OPT_SCALARS # Final VMC step + TRUE) # # H2 starting from unoptimized CIS coefficients and orbital @@ -33,12 +33,12 @@ IF (NOT QMC_CUDA) 6 H2_FDLR_SCALARS # Final VMC step TRUE) ELSE() - MESSAGE_VERBOSE("Skipping H4_FDLR test because lmyengine interface was not built (BUILD_LMYENGINE_INTERFACE=0)") + MESSAGE_VERBOSE("Skipping H2 test because lmyengine interface was not built (BUILD_LMYENGINE_INTERFACE=0)") ENDIF(BUILD_LMYENGINE_INTERFACE) ELSE() - MESSAGE_VERBOSE("Skipping H4_FDLR tests because gaussian basis sets are not supported by complex build (QMC_COMPLEX=1)") + MESSAGE_VERBOSE("Skipping H2 tests because orbital rotation is not supported by complex build (QMC_COMPLEX=1) and SoA build (ENABLE_SOA=1) is required") ENDIF() ELSE() - MESSAGE_VERBOSE("Skipping H4_FDLR tests because gaussian basis sets are not supported by CUDA build (QMC_CUDA=1)") + MESSAGE_VERBOSE("Skipping H2 tests because gaussian basis sets are not supported by CUDA build (QMC_CUDA=1)") ENDIF() diff --git a/tests/molecules/H4_ae/CMakeLists.txt b/tests/molecules/H4_ae/CMakeLists.txt index dd7176924..6b8e41147 100644 --- a/tests/molecules/H4_ae/CMakeLists.txt +++ b/tests/molecules/H4_ae/CMakeLists.txt @@ -79,6 +79,8 @@ IF (NOT QMC_CUDA) ${MP_SUCCESS} 5 H4_OPT_SCALARS # OPT step 5 ) + + IF(ENABLE_SOA) # # H4 starting from perturbed orbitals, using optimizable determinants, and the adaptive linear method # @@ -147,6 +149,9 @@ IF (NOT QMC_CUDA) ${MP_SUCCESS} 8 H4_FDLR_SCALARS # Final VMC step TRUE) + ELSE() + MESSAGE("Skipping H4_ae orbital rotation tests because they are no more supported with AoS builds.") + ENDIF(ENABLE_SOA) LIST(APPEND H4_CJS_SCALARS "totenergy" "-2.0438 0.0045") # total energy From 50a9a943684e69a603791b2f3640af13af2698fc Mon Sep 17 00:00:00 2001 From: Peter Doak Date: Mon, 21 Oct 2019 19:36:36 -0400 Subject: [PATCH 31/41] removal of unecessary header from DMCBatched.h --- src/QMCDrivers/DMC/DMCBatched.cpp | 1 + src/QMCDrivers/DMC/DMCBatched.h | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/QMCDrivers/DMC/DMCBatched.cpp b/src/QMCDrivers/DMC/DMCBatched.cpp index 3034253c7..7511f5744 100644 --- a/src/QMCDrivers/DMC/DMCBatched.cpp +++ b/src/QMCDrivers/DMC/DMCBatched.cpp @@ -12,6 +12,7 @@ #include #include "QMCDrivers/DMC/DMCBatched.h" +#include "QMCDrivers/GreenFunctionModifiers/DriftModifierBase.h" #include "Concurrency/TasksOneToOne.hpp" #include "Concurrency/Info.hpp" #include "Utilities/RunTimeManager.h" diff --git a/src/QMCDrivers/DMC/DMCBatched.h b/src/QMCDrivers/DMC/DMCBatched.h index a0ba91cbd..efcf3fa5f 100644 --- a/src/QMCDrivers/DMC/DMCBatched.h +++ b/src/QMCDrivers/DMC/DMCBatched.h @@ -17,10 +17,12 @@ #include "QMCDrivers/DMC/DMCDriverInput.h" #include "QMCDrivers/MCPopulation.h" #include "QMCDrivers/ContextForSteps.h" -#include "QMCDrivers/GreenFunctionModifiers/DriftModifierBase.h" namespace qmcplusplus { + +class DriverModifierBase; + /** @ingroup QMCDrivers ParticleByParticle * @brief Implements a DMC using particle-by-particle move. Threaded execution. */ From c2e5b216eeace91d471efab3e6751c9b5d356f07 Mon Sep 17 00:00:00 2001 From: Peter Doak Date: Mon, 21 Oct 2019 19:37:16 -0400 Subject: [PATCH 32/41] VParamType doesn't need TinyVector now based on std::array. --- src/QMCDrivers/SimpleFixedNodeBranch.cpp | 399 ++++++++++++----------- src/QMCDrivers/SimpleFixedNodeBranch.h | 117 ++++--- 2 files changed, 273 insertions(+), 243 deletions(-) diff --git a/src/QMCDrivers/SimpleFixedNodeBranch.cpp b/src/QMCDrivers/SimpleFixedNodeBranch.cpp index d4629c711..578460711 100644 --- a/src/QMCDrivers/SimpleFixedNodeBranch.cpp +++ b/src/QMCDrivers/SimpleFixedNodeBranch.cpp @@ -38,17 +38,18 @@ enum }; SimpleFixedNodeBranch::SimpleFixedNodeBranch(RealType tau, int nideal) - : vParam(1.0), MyEstimator(0) //, PopHist(5), DMCEnergyHist(5) + : MyEstimator(0) //, PopHist(5), DMCEnergyHist(5) { BranchMode.set(B_DMCSTAGE, 0); //warmup stage BranchMode.set(B_POPCONTROL, 1); //use standard DMC BranchMode.set(B_USETAUEFF, 1); //use taueff BranchMode.set(B_CLEARHISTORY, 0); //clear history and start with the current average BranchMode.set(B_KILLNODES, 0); //when killing walkers at nodes etrial is updated differently - vParam[B_TAU] = tau; - vParam[B_TAUEFF] = tau; - vParam[B_FEEDBACK] = 1.0; - vParam[B_FILTERSCALE] = 10; + vParam.fill(1.0); + vParam[SBVP::TAU] = tau; + vParam[SBVP::TAUEFF] = tau; + vParam[SBVP::FEEDBACK] = 1.0; + vParam[SBVP::FILTERSCALE] = 10; R2Accepted(1.0e-10); R2Proposed(1.0e-10); //set the default values for integer parameters @@ -93,17 +94,17 @@ void SimpleFixedNodeBranch::registerParameters() m_param.add(iParam[B_TARGETWALKERS], "targetwalkers", "int"); m_param.add(iParam[B_TARGETWALKERS], "target_walkers", "int"); //trial energy - m_param.add(vParam[B_EREF], "refEnergy", "AU"); - m_param.add(vParam[B_EREF], "ref_energy", "AU"); - m_param.add(vParam[B_EREF], "en_ref", "AU"); - m_param.add(vParam[B_TAU], "tau", "AU"); - m_param.add(vParam[B_TAU], "timestep", "AU"); - m_param.add(vParam[B_TAU], "timeStep", "AU"); - m_param.add(vParam[B_TAU], "TimeStep", "AU"); + m_param.add(vParam[SBVP::EREF], "refEnergy", "AU"); + m_param.add(vParam[SBVP::EREF], "ref_energy", "AU"); + m_param.add(vParam[SBVP::EREF], "en_ref", "AU"); + m_param.add(vParam[SBVP::TAU], "tau", "AU"); + m_param.add(vParam[SBVP::TAU], "timestep", "AU"); + m_param.add(vParam[SBVP::TAU], "timeStep", "AU"); + m_param.add(vParam[SBVP::TAU], "TimeStep", "AU"); //filterscale: sets the filtercutoff to sigma*filterscale - m_param.add(vParam[B_FILTERSCALE], "filterscale", "double"); + m_param.add(vParam[SBVP::FILTERSCALE], "filterscale", "double"); //feed back parameter for population control - m_param.add(vParam[B_FEEDBACK], "feedback", "double"); + m_param.add(vParam[SBVP::FEEDBACK], "feedback", "double"); //turn on/off effective tau onl for time-step error comparisons m_param.add(sParam[USETAUOPT], "useBareTau", "option"); m_param.add(sParam[MIXDMCOPT], "warmupByReconfiguration", "opt"); @@ -123,9 +124,9 @@ int SimpleFixedNodeBranch::initWalkerController(MCWalkerConfiguration& walkers, BranchMode.set(B_DMCSTAGE, iParam[B_WARMUPSTEPS] == 0); //use warmup //this is not necessary //check if tau is different and set the initial values - //vParam[B_TAU]=tau; + //vParam[SBVP::TAU]=tau; bool fromscratch = false; - FullPrecRealType tau = vParam[B_TAU]; + FullPrecRealType tau = vParam[SBVP::TAU]; int nwtot_now = walkers.getGlobalNumWalkers(); @@ -150,7 +151,7 @@ int SimpleFixedNodeBranch::initWalkerController(MCWalkerConfiguration& walkers, { fromscratch = true; app_log() << " START ALL OVER " << std::endl; - vParam[B_TAUEFF] = tau; + vParam[SBVP::TAUEFF] = tau; BranchMode.set(B_POPCONTROL, !fixW); //fixW -> 0 BranchMode.set(B_KILLNODES, killwalker); iParam[B_MAXWALKERS] = WalkerController->get_n_max(); @@ -176,28 +177,28 @@ int SimpleFixedNodeBranch::initWalkerController(MCWalkerConfiguration& walkers, //update the simulation parameters WalkerController->put(myNode); //assign current Eref and a large number for variance - WalkerController->setTrialEnergy(vParam[B_ETRIAL]); + WalkerController->setTrialEnergy(vParam[SBVP::ETRIAL]); this->reset(); if (fromscratch) { //determine the branch cutoff to limit wild weights based on the sigma and sigmaBound - setBranchCutoff(vParam[B_SIGMA2], WalkerController->get_target_sigma(), 50, walkers.R.size()); - vParam[B_TAUEFF] = tau * R2Accepted.result() / R2Proposed.result(); + setBranchCutoff(vParam[SBVP::SIGMA2], WalkerController->get_target_sigma(), 50, walkers.R.size()); + vParam[SBVP::TAUEFF] = tau * R2Accepted.result() / R2Proposed.result(); } //reset controller WalkerController->reset(); if (BackupWalkerController) BackupWalkerController->reset(); app_log() << " QMC counter = " << iParam[B_COUNTER] << std::endl; - app_log() << " time step = " << vParam[B_TAU] << std::endl; - app_log() << " effective time step = " << vParam[B_TAUEFF] << std::endl; - app_log() << " trial energy = " << vParam[B_ETRIAL] << std::endl; - app_log() << " reference energy = " << vParam[B_EREF] << std::endl; - app_log() << " Feedback = " << vParam[B_FEEDBACK] << std::endl; - app_log() << " reference variance = " << vParam[B_SIGMA2] << std::endl; + app_log() << " time step = " << vParam[SBVP::TAU] << std::endl; + app_log() << " effective time step = " << vParam[SBVP::TAUEFF] << std::endl; + app_log() << " trial energy = " << vParam[SBVP::ETRIAL] << std::endl; + app_log() << " reference energy = " << vParam[SBVP::EREF] << std::endl; + app_log() << " Feedback = " << vParam[SBVP::FEEDBACK] << std::endl; + app_log() << " reference variance = " << vParam[SBVP::SIGMA2] << std::endl; app_log() << " target walkers = " << iParam[B_TARGETWALKERS] << std::endl; app_log() << " branching cutoff scheme " << branching_cutoff_scheme << std::endl; - app_log() << " branch cutoff = " << vParam[B_BRANCHCUTOFF] << " " << vParam[B_BRANCHMAX] << std::endl; + app_log() << " branch cutoff = " << vParam[SBVP::BRANCHCUTOFF] << " " << vParam[SBVP::BRANCHMAX] << std::endl; app_log() << " Max and minimum walkers per node= " << iParam[B_MAXWALKERS] << " " << iParam[B_MINWALKERS] << std::endl; app_log() << " QMC Status (BranchMode) = " << BranchMode << std::endl; @@ -211,16 +212,17 @@ int SimpleFixedNodeBranch::initWalkerController(MCPopulation& population, bool f BranchMode.set(B_DMCSTAGE, iParam[B_WARMUPSTEPS] == 0); //use warmup //this is not necessary //check if tau is different and set the initial values - //vParam[B_TAU]=tau; + //vParam[SBVP::TAU]=tau; bool fromscratch = false; - FullPrecRealType tau = vParam[B_TAU]; + FullPrecRealType tau = vParam[SBVP::TAU]; int nwtot_now = population.get_num_global_walkers(); if (WalkerController != nullptr) throw std::runtime_error( - "Unified Driver initWalkerController called with existing WalkerController,\n this is a violation of the assumed " - "state module for SimpleFixedNodeBranch in the Unified Driver design"); + "Unified Driver initWalkerController called with existing WalkerController\n" + "this is a violation SimpleFixedNodeBranch is created to a valid state only\n" + "once in the Unified Driver design."); if (iParam[B_TARGETWALKERS] == 0) { // has "important" side effect of updating the walker offsets @@ -231,7 +233,7 @@ int SimpleFixedNodeBranch::initWalkerController(MCPopulation& population, bool f { fromscratch = true; app_log() << " START ALL OVER " << std::endl; - vParam[B_TAUEFF] = tau; + vParam[SBVP::TAUEFF] = tau; BranchMode.set(B_POPCONTROL, !fixW); //fixW -> 0 BranchMode.set(B_KILLNODES, killwalker); iParam[B_MAXWALKERS] = WalkerController->get_n_max(); @@ -261,30 +263,30 @@ int SimpleFixedNodeBranch::initWalkerController(MCPopulation& population, bool f //update the simulation parameters WalkerController->put(myNode); //assign current Eref and a large number for variance - WalkerController->setTrialEnergy(vParam[B_ETRIAL]); + WalkerController->setTrialEnergy(vParam[SBVP::ETRIAL]); this->reset(); if (fromscratch) { //determine the branch cutoff to limit wild weights based on the sigma and sigmaBound // Was check MCWC's particle set for number of R which I take to mean number of particles // will this assumption change if various spin freedoms also are added to ParticleSet? - setBranchCutoff(vParam[B_SIGMA2], WalkerController->get_target_sigma(), 50, population.get_num_particles()); - vParam[B_TAUEFF] = tau * R2Accepted.result() / R2Proposed.result(); + setBranchCutoff(vParam[SBVP::SIGMA2], WalkerController->get_target_sigma(), 50, population.get_num_particles()); + vParam[SBVP::TAUEFF] = tau * R2Accepted.result() / R2Proposed.result(); } //reset controller WalkerController->reset(); if (BackupWalkerController) BackupWalkerController->reset(); app_log() << " QMC counter = " << iParam[B_COUNTER] << std::endl; - app_log() << " time step = " << vParam[B_TAU] << std::endl; - app_log() << " effective time step = " << vParam[B_TAUEFF] << std::endl; - app_log() << " trial energy = " << vParam[B_ETRIAL] << std::endl; - app_log() << " reference energy = " << vParam[B_EREF] << std::endl; - app_log() << " Feedback = " << vParam[B_FEEDBACK] << std::endl; - app_log() << " reference variance = " << vParam[B_SIGMA2] << std::endl; + app_log() << " time step = " << vParam[SBVP::TAU] << std::endl; + app_log() << " effective time step = " << vParam[SBVP::TAUEFF] << std::endl; + app_log() << " trial energy = " << vParam[SBVP::ETRIAL] << std::endl; + app_log() << " reference energy = " << vParam[SBVP::EREF] << std::endl; + app_log() << " Feedback = " << vParam[SBVP::FEEDBACK] << std::endl; + app_log() << " reference variance = " << vParam[SBVP::SIGMA2] << std::endl; app_log() << " target walkers = " << iParam[B_TARGETWALKERS] << std::endl; app_log() << " branching cutoff scheme " << branching_cutoff_scheme << std::endl; - app_log() << " branch cutoff = " << vParam[B_BRANCHCUTOFF] << " " << vParam[B_BRANCHMAX] << std::endl; + app_log() << " branch cutoff = " << vParam[SBVP::BRANCHCUTOFF] << " " << vParam[SBVP::BRANCHMAX] << std::endl; app_log() << " Max and minimum walkers per node= " << iParam[B_MAXWALKERS] << " " << iParam[B_MINWALKERS] << std::endl; app_log() << " QMC Status (BranchMode) = " << BranchMode << std::endl; @@ -299,9 +301,9 @@ void SimpleFixedNodeBranch::initReptile(MCWalkerConfiguration& W) BranchMode.set(B_RMCSTAGE, iParam[B_WARMUPSTEPS] == 0); //use warmup //this is not necessary //check if tau is different and set the initial values - //vParam[B_TAU]=tau; + //vParam[SBVP::TAU]=tau; bool fromscratch = false; - FullPrecRealType tau = vParam[B_TAU]; + FullPrecRealType tau = vParam[SBVP::TAU]; //this is the first time DMC is used if (WalkerController == 0) { @@ -322,7 +324,7 @@ void SimpleFixedNodeBranch::initReptile(MCWalkerConfiguration& W) { fromscratch = true; app_log() << " START ALL OVER " << std::endl; - vParam[B_TAUEFF] = tau; + vParam[SBVP::TAUEFF] = tau; //PopHist.clear(); //PopHist.reserve(std::max(iParam[B_ENERGYUPDATEINTERVAL],5)); } @@ -336,18 +338,18 @@ void SimpleFixedNodeBranch::initReptile(MCWalkerConfiguration& W) if (fromscratch) { //determine the branch cutoff to limit wild weights based on the sigma and sigmaBound - setBranchCutoff(vParam[B_SIGMA2], allowedFlux, 50, W.R.size()); - vParam[B_TAUEFF] = tau * R2Accepted.result() / R2Proposed.result(); + setBranchCutoff(vParam[SBVP::SIGMA2], allowedFlux, 50, W.R.size()); + vParam[SBVP::TAUEFF] = tau * R2Accepted.result() / R2Proposed.result(); } //reset controller app_log() << " QMC counter = " << iParam[B_COUNTER] << std::endl; - app_log() << " time step = " << vParam[B_TAU] << std::endl; - app_log() << " effective time step = " << vParam[B_TAUEFF] << std::endl; - app_log() << " reference energy = " << vParam[B_EREF] << std::endl; - app_log() << " Feedback = " << vParam[B_FEEDBACK] << std::endl; - app_log() << " reference variance = " << vParam[B_SIGMA2] << std::endl; + app_log() << " time step = " << vParam[SBVP::TAU] << std::endl; + app_log() << " effective time step = " << vParam[SBVP::TAUEFF] << std::endl; + app_log() << " reference energy = " << vParam[SBVP::EREF] << std::endl; + app_log() << " Feedback = " << vParam[SBVP::FEEDBACK] << std::endl; + app_log() << " reference variance = " << vParam[SBVP::SIGMA2] << std::endl; app_log() << " branching cutoff scheme " << branching_cutoff_scheme << std::endl; - app_log() << " branch cutoff = " << vParam[B_BRANCHCUTOFF] << " " << vParam[B_BRANCHMAX] << std::endl; + app_log() << " branch cutoff = " << vParam[SBVP::BRANCHCUTOFF] << " " << vParam[SBVP::BRANCHMAX] << std::endl; app_log() << " QMC Status (BranchMode) = " << BranchMode << std::endl; } @@ -369,18 +371,18 @@ void SimpleFixedNodeBranch::branch(int iter, MCWalkerConfiguration& walkers) //population for trial energy modification should not include any released node walkers. pop_now -= WalkerController->get_ensemble_property().RNSamples; //current energy - vParam[B_ENOW] = WalkerController->get_ensemble_property().Energy; + vParam[SBVP::ENOW] = WalkerController->get_ensemble_property().Energy; VarianceHist(WalkerController->get_ensemble_property().Variance); R2Accepted(WalkerController->get_ensemble_property().R2Accepted); R2Proposed(WalkerController->get_ensemble_property().R2Proposed); //PopHist(pop_now); - vParam[B_EREF] = EnergyHist.mean(); //current mean + vParam[SBVP::EREF] = EnergyHist.mean(); //current mean if (BranchMode[B_USETAUEFF]) - vParam[B_TAUEFF] = vParam[B_TAU] * R2Accepted.result() / R2Proposed.result(); + vParam[SBVP::TAUEFF] = vParam[SBVP::TAU] * R2Accepted.result() / R2Proposed.result(); if (BranchMode[B_KILLNODES]) - EnergyHist(vParam[B_ENOW] - std::log(WalkerController->get_ensemble_property().LivingFraction) / vParam[B_TAUEFF]); + EnergyHist(vParam[SBVP::ENOW] - std::log(WalkerController->get_ensemble_property().LivingFraction) / vParam[SBVP::TAUEFF]); else - EnergyHist(vParam[B_ENOW]); + EnergyHist(vParam[SBVP::ENOW]); if (BranchMode[B_DMCSTAGE]) // main stage { if (BranchMode[B_POPCONTROL]) @@ -389,66 +391,66 @@ void SimpleFixedNodeBranch::branch(int iter, MCWalkerConfiguration& walkers) --ToDoSteps; else { - vParam[B_ETRIAL] = vParam[B_EREF] + vParam[B_FEEDBACK] * (logN - std::log(pop_now)); + vParam[SBVP::ETRIAL] = vParam[SBVP::EREF] + vParam[SBVP::FEEDBACK] * (logN - std::log(pop_now)); ToDoSteps = iParam[B_ENERGYUPDATEINTERVAL] - 1; } } else - vParam[B_ETRIAL] = vParam[B_EREF]; + vParam[SBVP::ETRIAL] = vParam[SBVP::EREF]; } else //warmup { if (BranchMode[B_USETAUEFF]) - vParam[B_TAUEFF] = vParam[B_TAU] * R2Accepted.result() / R2Proposed.result(); + vParam[SBVP::TAUEFF] = vParam[SBVP::TAU] * R2Accepted.result() / R2Proposed.result(); if (BranchMode[B_POPCONTROL]) { - //RealType emix=((iParam[B_WARMUPSTEPS]-ToDoSteps)<100)?(0.25*vParam[B_EREF]+0.75*vParam[B_ENOW]):vParam[B_EREF]; - //vParam[B_ETRIAL]=emix+Feedback*(logN-std::log(pop_now)); - //vParam[B_ETRIAL]=vParam[B_EREF]+Feedback*(logN-std::log(pop_now)); + //RealType emix=((iParam[B_WARMUPSTEPS]-ToDoSteps)<100)?(0.25*vParam[SBVP::EREF]+0.75*vParam[SBVP::ENOW]):vParam[SBVP::EREF]; + //vParam[SBVP::ETRIAL]=emix+Feedback*(logN-std::log(pop_now)); + //vParam[SBVP::ETRIAL]=vParam[SBVP::EREF]+Feedback*(logN-std::log(pop_now)); if (BranchMode[B_KILLNODES]) - vParam[B_ETRIAL] = (0.00 * vParam[B_EREF] + 1.0 * vParam[B_ENOW]) + - vParam[B_FEEDBACK] * (logN - std::log(pop_now)) - - std::log(WalkerController->get_ensemble_property().LivingFraction) / vParam[B_TAU]; + vParam[SBVP::ETRIAL] = (0.00 * vParam[SBVP::EREF] + 1.0 * vParam[SBVP::ENOW]) + + vParam[SBVP::FEEDBACK] * (logN - std::log(pop_now)) - + std::log(WalkerController->get_ensemble_property().LivingFraction) / vParam[SBVP::TAU]; else - vParam[B_ETRIAL] = vParam[B_ENOW] + (logN - std::log(pop_now)) / vParam[B_TAU]; + vParam[SBVP::ETRIAL] = vParam[SBVP::ENOW] + (logN - std::log(pop_now)) / vParam[SBVP::TAU]; } else - vParam[B_ETRIAL] = vParam[B_EREF]; + vParam[SBVP::ETRIAL] = vParam[SBVP::EREF]; --ToDoSteps; if (ToDoSteps == 0) //warmup is done { - vParam[B_SIGMA2] = VarianceHist.mean(); - setBranchCutoff(vParam[B_SIGMA2], WalkerController->get_target_sigma(), 10, walkers.R.size()); + vParam[SBVP::SIGMA2] = VarianceHist.mean(); + setBranchCutoff(vParam[SBVP::SIGMA2], WalkerController->get_target_sigma(), 10, walkers.R.size()); app_log() << "\n Warmup is completed after " << iParam[B_WARMUPSTEPS] << std::endl; if (BranchMode[B_USETAUEFF]) - app_log() << "\n TauEff = " << vParam[B_TAUEFF] << "\n TauEff/Tau = " << vParam[B_TAUEFF] / vParam[B_TAU]; + app_log() << "\n TauEff = " << vParam[SBVP::TAUEFF] << "\n TauEff/Tau = " << vParam[SBVP::TAUEFF] / vParam[SBVP::TAU]; else - app_log() << "\n TauEff proposed = " << vParam[B_TAUEFF] * R2Accepted.result() / R2Proposed.result(); - app_log() << "\n Etrial = " << vParam[B_ETRIAL] << std::endl; + app_log() << "\n TauEff proposed = " << vParam[SBVP::TAUEFF] * R2Accepted.result() / R2Proposed.result(); + app_log() << "\n Etrial = " << vParam[SBVP::ETRIAL] << std::endl; app_log() << " Running average of energy = " << EnergyHist.mean() << std::endl; - app_log() << " Variance = " << vParam[B_SIGMA2] << std::endl; - app_log() << "branch cutoff = " << vParam[B_BRANCHCUTOFF] << " " << vParam[B_BRANCHMAX] << std::endl; + app_log() << " Variance = " << vParam[SBVP::SIGMA2] << std::endl; + app_log() << "branch cutoff = " << vParam[SBVP::BRANCHCUTOFF] << " " << vParam[SBVP::BRANCHMAX] << std::endl; ToDoSteps = iParam[B_ENERGYUPDATEINTERVAL] - 1; iParam[B_WARMUPSTEPS] = 0; BranchMode.set(B_DMCSTAGE, 1); //set BranchModex to main stage //reset the histogram EnergyHist.clear(); - EnergyHist(vParam[B_ENOW]); + EnergyHist(vParam[SBVP::ENOW]); if (sParam[MIXDMCOPT] == "yes") { app_log() << "Switching to DMC with fluctuating populations" << std::endl; BranchMode.set(B_POPCONTROL, 1); //use standard DMC WalkerController = std::move(BackupWalkerController); BackupWalkerController = 0; - vParam[B_ETRIAL] = vParam[B_EREF]; - app_log() << " Etrial = " << vParam[B_ETRIAL] << std::endl; + vParam[SBVP::ETRIAL] = vParam[SBVP::EREF]; + app_log() << " Etrial = " << vParam[SBVP::ETRIAL] << std::endl; WalkerController->start(); } //This is not necessary //EnergyHist(DMCEnergyHist.mean()); } } - WalkerController->setTrialEnergy(vParam[B_ETRIAL]); + WalkerController->setTrialEnergy(vParam[SBVP::ETRIAL]); //accumulate collectables and energies for scalar.dat FullPrecRealType wgt_inv = WalkerController->get_num_contexts() / WalkerController->get_ensemble_property().Weight; walkers.Collectables *= wgt_inv; @@ -470,18 +472,18 @@ void SimpleFixedNodeBranch::branch(int iter, UPtrVector& crowds, MCPopul MCDataType& wc_ensemble_prop = WalkerController->get_ensemble_property(); pop_now -= wc_ensemble_prop.RNSamples; //current energy - vParam[B_ENOW] = wc_ensemble_prop.Energy; + vParam[SBVP::ENOW] = wc_ensemble_prop.Energy; VarianceHist(wc_ensemble_prop.Variance); R2Accepted(wc_ensemble_prop.R2Accepted); R2Proposed(wc_ensemble_prop.R2Proposed); //PopHist(pop_now); - vParam[B_EREF] = EnergyHist.mean(); //current mean + vParam[SBVP::EREF] = EnergyHist.mean(); //current mean if (BranchMode[B_USETAUEFF]) - vParam[B_TAUEFF] = vParam[B_TAU] * R2Accepted.result() / R2Proposed.result(); + vParam[SBVP::TAUEFF] = vParam[SBVP::TAU] * R2Accepted.result() / R2Proposed.result(); if (BranchMode[B_KILLNODES]) - EnergyHist(vParam[B_ENOW] - std::log(wc_ensemble_prop.LivingFraction) / vParam[B_TAUEFF]); + EnergyHist(vParam[SBVP::ENOW] - std::log(wc_ensemble_prop.LivingFraction) / vParam[SBVP::TAUEFF]); else - EnergyHist(vParam[B_ENOW]); + EnergyHist(vParam[SBVP::ENOW]); if (BranchMode[B_DMCSTAGE]) // main stage { if (BranchMode[B_POPCONTROL]) @@ -490,66 +492,66 @@ void SimpleFixedNodeBranch::branch(int iter, UPtrVector& crowds, MCPopul --ToDoSteps; else { - vParam[B_ETRIAL] = vParam[B_EREF] + vParam[B_FEEDBACK] * (logN - std::log(pop_now)); + vParam[SBVP::ETRIAL] = vParam[SBVP::EREF] + vParam[SBVP::FEEDBACK] * (logN - std::log(pop_now)); ToDoSteps = iParam[B_ENERGYUPDATEINTERVAL] - 1; } } else - vParam[B_ETRIAL] = vParam[B_EREF]; + vParam[SBVP::ETRIAL] = vParam[SBVP::EREF]; } else //warmup { if (BranchMode[B_USETAUEFF]) - vParam[B_TAUEFF] = vParam[B_TAU] * R2Accepted.result() / R2Proposed.result(); + vParam[SBVP::TAUEFF] = vParam[SBVP::TAU] * R2Accepted.result() / R2Proposed.result(); if (BranchMode[B_POPCONTROL]) { - //RealType emix=((iParam[B_WARMUPSTEPS]-ToDoSteps)<100)?(0.25*vParam[B_EREF]+0.75*vParam[B_ENOW]):vParam[B_EREF]; - //vParam[B_ETRIAL]=emix+Feedback*(logN-std::log(pop_now)); - //vParam[B_ETRIAL]=vParam[B_EREF]+Feedback*(logN-std::log(pop_now)); + //RealType emix=((iParam[B_WARMUPSTEPS]-ToDoSteps)<100)?(0.25*vParam[SBVP::EREF]+0.75*vParam[SBVP::ENOW]):vParam[SBVP::EREF]; + //vParam[SBVP::ETRIAL]=emix+Feedback*(logN-std::log(pop_now)); + //vParam[SBVP::ETRIAL]=vParam[SBVP::EREF]+Feedback*(logN-std::log(pop_now)); if (BranchMode[B_KILLNODES]) - vParam[B_ETRIAL] = (0.00 * vParam[B_EREF] + 1.0 * vParam[B_ENOW]) + - vParam[B_FEEDBACK] * (logN - std::log(pop_now)) - - std::log(wc_ensemble_prop.LivingFraction) / vParam[B_TAU]; + vParam[SBVP::ETRIAL] = (0.00 * vParam[SBVP::EREF] + 1.0 * vParam[SBVP::ENOW]) + + vParam[SBVP::FEEDBACK] * (logN - std::log(pop_now)) - + std::log(wc_ensemble_prop.LivingFraction) / vParam[SBVP::TAU]; else - vParam[B_ETRIAL] = vParam[B_ENOW] + (logN - std::log(pop_now)) / vParam[B_TAU]; + vParam[SBVP::ETRIAL] = vParam[SBVP::ENOW] + (logN - std::log(pop_now)) / vParam[SBVP::TAU]; } else - vParam[B_ETRIAL] = vParam[B_EREF]; + vParam[SBVP::ETRIAL] = vParam[SBVP::EREF]; --ToDoSteps; if (ToDoSteps == 0) //warmup is done { - vParam[B_SIGMA2] = VarianceHist.mean(); - setBranchCutoff(vParam[B_SIGMA2], WalkerController->get_target_sigma(), 10, population.get_num_particles()); + vParam[SBVP::SIGMA2] = VarianceHist.mean(); + setBranchCutoff(vParam[SBVP::SIGMA2], WalkerController->get_target_sigma(), 10, population.get_num_particles()); app_log() << "\n Warmup is completed after " << iParam[B_WARMUPSTEPS] << std::endl; if (BranchMode[B_USETAUEFF]) - app_log() << "\n TauEff = " << vParam[B_TAUEFF] << "\n TauEff/Tau = " << vParam[B_TAUEFF] / vParam[B_TAU]; + app_log() << "\n TauEff = " << vParam[SBVP::TAUEFF] << "\n TauEff/Tau = " << vParam[SBVP::TAUEFF] / vParam[SBVP::TAU]; else - app_log() << "\n TauEff proposed = " << vParam[B_TAUEFF] * R2Accepted.result() / R2Proposed.result(); - app_log() << "\n Etrial = " << vParam[B_ETRIAL] << std::endl; + app_log() << "\n TauEff proposed = " << vParam[SBVP::TAUEFF] * R2Accepted.result() / R2Proposed.result(); + app_log() << "\n Etrial = " << vParam[SBVP::ETRIAL] << std::endl; app_log() << " Running average of energy = " << EnergyHist.mean() << std::endl; - app_log() << " Variance = " << vParam[B_SIGMA2] << std::endl; - app_log() << "branch cutoff = " << vParam[B_BRANCHCUTOFF] << " " << vParam[B_BRANCHMAX] << std::endl; + app_log() << " Variance = " << vParam[SBVP::SIGMA2] << std::endl; + app_log() << "branch cutoff = " << vParam[SBVP::BRANCHCUTOFF] << " " << vParam[SBVP::BRANCHMAX] << std::endl; ToDoSteps = iParam[B_ENERGYUPDATEINTERVAL] - 1; iParam[B_WARMUPSTEPS] = 0; BranchMode.set(B_DMCSTAGE, 1); //set BranchModex to main stage //reset the histogram EnergyHist.clear(); - EnergyHist(vParam[B_ENOW]); + EnergyHist(vParam[SBVP::ENOW]); if (sParam[MIXDMCOPT] == "yes") { app_log() << "Switching to DMC with fluctuating populations" << std::endl; BranchMode.set(B_POPCONTROL, 1); //use standard DMC WalkerController = std::move(BackupWalkerController); BackupWalkerController = 0; - vParam[B_ETRIAL] = vParam[B_EREF]; - app_log() << " Etrial = " << vParam[B_ETRIAL] << std::endl; + vParam[SBVP::ETRIAL] = vParam[SBVP::EREF]; + app_log() << " Etrial = " << vParam[SBVP::ETRIAL] << std::endl; WalkerController->start(); } //This is not necessary //EnergyHist(DMCEnergyHist.mean()); } } - WalkerController->setTrialEnergy(vParam[B_ETRIAL]); + WalkerController->setTrialEnergy(vParam[SBVP::ETRIAL]); //accumulate collectables and energies for scalar.dat FullPrecRealType wgt_inv = WalkerController->get_num_contexts() / wc_ensemble_prop.Weight; //walkers.Collectables *= wgt_inv; @@ -565,14 +567,14 @@ void SimpleFixedNodeBranch::collect(int iter, MCWalkerConfiguration& W) //Update the current energy and accumulate. MCWalkerConfiguration::Walker_t& head = W.reptile->getHead(); MCWalkerConfiguration::Walker_t& tail = W.reptile->getTail(); - vParam[B_ENOW] = 0.5 * (head.Properties(LOCALENERGY) + tail.Properties(LOCALENERGY)); + vParam[SBVP::ENOW] = 0.5 * (head.Properties(LOCALENERGY) + tail.Properties(LOCALENERGY)); // app_log()<<"IN SimpleFixedNodeBranch::collect\n"; - // app_log()<<"\tvParam[B_ENOW]="< = "< = "<^2 = "<(iParam[B_TARGETWALKERS])); logN = std::log(static_cast(iParam[B_TARGETWALKERS])); - if (vParam[B_FEEDBACK] == 0.0) - vParam[B_FEEDBACK] = 1.0; + if (vParam[SBVP::FEEDBACK] == 0.0) + vParam[SBVP::FEEDBACK] = 1.0; } else { //may set Eref to a safe value //if(EnergyHistory.count()<5) Eref -= vParam[EnergyWindowIndex]; - vParam[B_ETRIAL] = vParam[B_EREF]; - vParam[B_FEEDBACK] = 0.0; + vParam[SBVP::ETRIAL] = vParam[SBVP::EREF]; + vParam[SBVP::FEEDBACK] = 0.0; logN = 0.0; } // vParam(abranch.vParam) @@ -779,9 +781,9 @@ int SimpleFixedNodeBranch::resetRun(xmlNodePtr cur) BranchMode[B_POPCONTROL] = (WalkerController->get_method() == 0); if (BranchMode[B_POPCONTROL]) { - vParam[B_ETRIAL] = vParam[B_EREF]; - if (vParam[B_FEEDBACK] == 0.0) - vParam[B_FEEDBACK] = 1.0; + vParam[SBVP::ETRIAL] = vParam[SBVP::EREF]; + if (vParam[SBVP::FEEDBACK] == 0.0) + vParam[SBVP::FEEDBACK] = 1.0; } } @@ -793,7 +795,7 @@ int SimpleFixedNodeBranch::resetRun(xmlNodePtr cur) BranchMode[B_DMCSTAGE] = 0; WalkerController->put(myNode); ToDoSteps = iParam[B_WARMUPSTEPS] = (iParam[B_WARMUPSTEPS]) ? iParam[B_WARMUPSTEPS] : 10; - setBranchCutoff(vParam[B_SIGMA2], WalkerController->get_target_sigma(), 10); + setBranchCutoff(vParam[SBVP::SIGMA2], WalkerController->get_target_sigma(), 10); WalkerController->reset(); #ifdef QMC_CUDA reset(); // needed. Ye @@ -824,17 +826,17 @@ void SimpleFixedNodeBranch::checkParameters(MCWalkerConfiguration& w) { FullPrecRealType e, sigma2; MyEstimator->getCurrentStatistics(w, e, sigma2); - vParam[B_ETRIAL] = vParam[B_EREF] = e; - vParam[B_SIGMA2] = sigma2; + vParam[SBVP::ETRIAL] = vParam[SBVP::EREF] = e; + vParam[SBVP::SIGMA2] = sigma2; EnergyHist.clear(); VarianceHist.clear(); //DMCEnergyHist.clear(); - EnergyHist(vParam[B_EREF]); - VarianceHist(vParam[B_SIGMA2]); - //DMCEnergyHist(vParam[B_EREF]); + EnergyHist(vParam[SBVP::EREF]); + VarianceHist(vParam[SBVP::SIGMA2]); + //DMCEnergyHist(vParam[SBVP::EREF]); o << "SimpleFixedNodeBranch::checkParameters " << std::endl; o << " Average Energy of a population = " << e << std::endl; - o << " Energy Variance = " << vParam[B_SIGMA2] << std::endl; + o << " Energy Variance = " << vParam[SBVP::SIGMA2] << std::endl; } app_log() << o.str() << std::endl; app_log().flush(); @@ -847,17 +849,17 @@ void SimpleFixedNodeBranch::checkParameters(const int global_walkers, RefVector< { FullPrecRealType e, sigma2; MyEstimator->getCurrentStatistics(global_walkers, walkers, e, sigma2); - vParam[B_ETRIAL] = vParam[B_EREF] = e; - vParam[B_SIGMA2] = sigma2; + vParam[SBVP::ETRIAL] = vParam[SBVP::EREF] = e; + vParam[SBVP::SIGMA2] = sigma2; EnergyHist.clear(); VarianceHist.clear(); //DMCEnergyHist.clear(); - EnergyHist(vParam[B_EREF]); - VarianceHist(vParam[B_SIGMA2]); - //DMCEnergyHist(vParam[B_EREF]); + EnergyHist(vParam[SBVP::EREF]); + VarianceHist(vParam[SBVP::SIGMA2]); + //DMCEnergyHist(vParam[SBVP::EREF]); o << "SimpleFixedNodeBranch::checkParameters " << std::endl; o << " Average Energy of a population = " << e << std::endl; - o << " Energy Variance = " << vParam[B_SIGMA2] << std::endl; + o << " Energy Variance = " << vParam[SBVP::SIGMA2] << std::endl; } app_log() << o.str() << std::endl; app_log().flush(); @@ -871,15 +873,15 @@ void SimpleFixedNodeBranch::finalize(const int global_walkers, RefVectorgetEnergyAndWeight(e,w,sigma2); MyEstimator->getCurrentStatistics(global_walkers, walkers , e, sigma2); - vParam[B_ETRIAL] = vParam[B_EREF] = e; - vParam[B_SIGMA2] = sigma2; + vParam[SBVP::ETRIAL] = vParam[SBVP::EREF] = e; + vParam[SBVP::SIGMA2] = sigma2; //this is just to avoid diving by n-1 == 0 - EnergyHist(vParam[B_EREF]); + EnergyHist(vParam[SBVP::EREF]); //add Eref to the DMCEnergyHistory - //DMCEnergyHist(vParam[B_EREF]); + //DMCEnergyHist(vParam[SBVP::EREF]); o << "===================================================="; o << "\n SimpleFixedNodeBranch::finalize after a VMC block"; o << "\n QMC counter = " << iParam[B_COUNTER]; - o << "\n time step = " << vParam[B_TAU]; - o << "\n reference energy = " << vParam[B_EREF]; - o << "\n reference variance = " << vParam[B_SIGMA2]; + o << "\n time step = " << vParam[SBVP::TAU]; + o << "\n reference energy = " << vParam[SBVP::EREF]; + o << "\n reference variance = " << vParam[SBVP::SIGMA2]; o << "\n===================================================="; } app_log() << o.str() << std::endl; @@ -929,15 +931,15 @@ void SimpleFixedNodeBranch::finalize(MCWalkerConfiguration& w) o << "===================================================="; o << "\n SimpleFixedNodeBranch::finalize after a DMC block"; o << "\n QMC counter = " << iParam[B_COUNTER]; - o << "\n time step = " << vParam[B_TAU]; - o << "\n effective time step = " << vParam[B_TAUEFF]; - o << "\n trial energy = " << vParam[B_ETRIAL]; - o << "\n reference energy = " << vParam[B_EREF]; - o << "\n reference variance = " << vParam[B_SIGMA2]; + o << "\n time step = " << vParam[SBVP::TAU]; + o << "\n effective time step = " << vParam[SBVP::TAUEFF]; + o << "\n trial energy = " << vParam[SBVP::ETRIAL]; + o << "\n reference energy = " << vParam[SBVP::EREF]; + o << "\n reference variance = " << vParam[SBVP::SIGMA2]; o << "\n target walkers = " << iParam[B_TARGETWALKERS]; - o << "\n branch cutoff = " << vParam[B_BRANCHCUTOFF] << " " << vParam[B_BRANCHMAX]; + o << "\n branch cutoff = " << vParam[SBVP::BRANCHCUTOFF] << " " << vParam[SBVP::BRANCHMAX]; o << "\n Max and minimum walkers per node= " << iParam[B_MAXWALKERS] << " " << iParam[B_MINWALKERS]; - o << "\n Feedback = " << vParam[B_FEEDBACK]; + o << "\n Feedback = " << vParam[SBVP::FEEDBACK]; o << "\n QMC Status (BranchMode) = " << BranchMode; o << "\n===================================================="; } @@ -947,11 +949,11 @@ void SimpleFixedNodeBranch::finalize(MCWalkerConfiguration& w) o << "===================================================="; o << "\n SimpleFixedNodeBranch::finalize after a RMC block"; o << "\n QMC counter = " << iParam[B_COUNTER]; - o << "\n time step = " << vParam[B_TAU]; - o << "\n effective time step = " << vParam[B_TAUEFF]; - o << "\n reference energy = " << vParam[B_EREF]; - o << "\n reference variance = " << vParam[B_SIGMA2]; - o << "\n cutoff energy = " << vParam[B_BRANCHCUTOFF] << " " << vParam[B_BRANCHMAX]; + o << "\n time step = " << vParam[SBVP::TAU]; + o << "\n effective time step = " << vParam[SBVP::TAUEFF]; + o << "\n reference energy = " << vParam[SBVP::EREF]; + o << "\n reference variance = " << vParam[SBVP::SIGMA2]; + o << "\n cutoff energy = " << vParam[SBVP::BRANCHCUTOFF] << " " << vParam[SBVP::BRANCHMAX]; o << "\n QMC Status (BranchMode) = " << BranchMode; o << "\n===================================================="; } @@ -961,18 +963,18 @@ void SimpleFixedNodeBranch::finalize(MCWalkerConfiguration& w) FullPrecRealType e, sigma2; //MyEstimator->getEnergyAndWeight(e,w,sigma2); MyEstimator->getCurrentStatistics(w, e, sigma2); - vParam[B_ETRIAL] = vParam[B_EREF] = e; - vParam[B_SIGMA2] = sigma2; + vParam[SBVP::ETRIAL] = vParam[SBVP::EREF] = e; + vParam[SBVP::SIGMA2] = sigma2; //this is just to avoid diving by n-1 == 0 - EnergyHist(vParam[B_EREF]); + EnergyHist(vParam[SBVP::EREF]); //add Eref to the DMCEnergyHistory - //DMCEnergyHist(vParam[B_EREF]); + //DMCEnergyHist(vParam[SBVP::EREF]); o << "===================================================="; o << "\n SimpleFixedNodeBranch::finalize after a VMC block"; o << "\n QMC counter = " << iParam[B_COUNTER]; - o << "\n time step = " << vParam[B_TAU]; - o << "\n reference energy = " << vParam[B_EREF]; - o << "\n reference variance = " << vParam[B_SIGMA2]; + o << "\n time step = " << vParam[SBVP::TAU]; + o << "\n reference energy = " << vParam[SBVP::EREF]; + o << "\n reference variance = " << vParam[SBVP::SIGMA2]; o << "\n===================================================="; } app_log() << o.str() << std::endl; @@ -1007,8 +1009,8 @@ void SimpleFixedNodeBranch::write(const std::string& fname, bool overwrite) if (MyEstimator->is_manager()) { //\since 2008-06-24 - vParam[B_ACC_ENERGY] = EnergyHist.result(); - vParam[B_ACC_SAMPLES] = EnergyHist.count(); + vParam[SBVP::ACC_ENERGY] = EnergyHist.result(); + vParam[SBVP::ACC_SAMPLES] = EnergyHist.count(); BranchIO hh(*this, MyEstimator->getCommunicator()); bool success = hh.write(fname); } @@ -1019,8 +1021,8 @@ void SimpleFixedNodeBranch::read(const std::string& fname) BranchMode.set(B_RESTART, 0); if (fname.empty()) return; - vParam[B_ACC_ENERGY] = EnergyHist.result(); - vParam[B_ACC_SAMPLES] = EnergyHist.count(); + vParam[SBVP::ACC_ENERGY] = EnergyHist.result(); + vParam[SBVP::ACC_SAMPLES] = EnergyHist.count(); BranchIO hh(*this, MyEstimator->getCommunicator()); BranchModeType bmode(BranchMode); bool success = hh.read(fname); @@ -1054,30 +1056,37 @@ void SimpleFixedNodeBranch::setBranchCutoff(FullPrecRealType variance, { // eq.(3), J. Chem. Phys. 89, 3629 (1988). // eq.(9), J. Chem. Phys. 99, 2865 (1993). - vParam[B_BRANCHCUTOFF] = 2.0 / std::sqrt(vParam[B_TAU]); + vParam[SBVP::BRANCHCUTOFF] = 2.0 / std::sqrt(vParam[SBVP::TAU]); } else if (branching_cutoff_scheme == "ZSGMA") { // eq.(6), Phys. Rev. B 93, 241118(R) (2016) // do nothing if Nelec is not passed in. if (Nelec > 0) - vParam[B_BRANCHCUTOFF] = 0.2 * std::sqrt(Nelec / vParam[B_TAU]); + vParam[SBVP::BRANCHCUTOFF] = 0.2 * std::sqrt(Nelec / vParam[SBVP::TAU]); } else if (branching_cutoff_scheme == "YL") { // a scheme from Ye Luo. - vParam[B_BRANCHCUTOFF] = std::sqrt(variance) * std::min(targetSigma, std::sqrt(1.0 / vParam[B_TAU])); + vParam[SBVP::BRANCHCUTOFF] = std::sqrt(variance) * std::min(targetSigma, std::sqrt(1.0 / vParam[SBVP::TAU])); } else if (branching_cutoff_scheme == "classic") { // default QMCPACK choice which is the same as v3.0.0 and before. - vParam[B_BRANCHCUTOFF] = std::min(std::max(variance * targetSigma, maxSigma), 2.5 / vParam[B_TAU]); + vParam[SBVP::BRANCHCUTOFF] = std::min(std::max(variance * targetSigma, maxSigma), 2.5 / vParam[SBVP::TAU]); } else APP_ABORT("SimpleFixedNodeBranch::setBranchCutoff unknown branching cutoff scheme " + branching_cutoff_scheme); - vParam[B_BRANCHMAX] = vParam[B_BRANCHCUTOFF] * 1.5; - vParam[B_BRANCHFILTER] = 1.0 / (vParam[B_BRANCHMAX] - vParam[B_BRANCHCUTOFF]); + vParam[SBVP::BRANCHMAX] = vParam[SBVP::BRANCHCUTOFF] * 1.5; + vParam[SBVP::BRANCHFILTER] = 1.0 / (vParam[SBVP::BRANCHMAX] - vParam[SBVP::BRANCHCUTOFF]); +} + +std::ostream& operator<<(std::ostream& os, SimpleFixedNodeBranch::VParamType& rhs) +{ + for(auto value : rhs) + os << std::setw(18) << std::setprecision(10) << value; + return os; } } // namespace qmcplusplus diff --git a/src/QMCDrivers/SimpleFixedNodeBranch.h b/src/QMCDrivers/SimpleFixedNodeBranch.h index 8c478ebdf..df407e7aa 100644 --- a/src/QMCDrivers/SimpleFixedNodeBranch.h +++ b/src/QMCDrivers/SimpleFixedNodeBranch.h @@ -21,6 +21,7 @@ #ifndef QMCPLUSPLUS_SIMPLE_FIXEDNODE_BRANCHER_H #define QMCPLUSPLUS_SIMPLE_FIXEDNODE_BRANCHER_H +#include #include #include #include @@ -38,6 +39,12 @@ namespace qmcplusplus class EstimatorManagerBase; /** Manages the state of QMC sections and handles population control for DMCs + * + * TODO: Remove duplicate reading of Driver XML section with own copies of input + * parameters. + * TODO: Rename, it is the only branching class so its name is too much + * TODO: Use normal types for data members, don't be clever to be clever + * the parameter enums violate KISS and make debugging annoying * * QMCDriver object owns a SimpleFixedNodeBranch to keep track of the * progress of a qmc section. It implements several methods to control the @@ -116,30 +123,41 @@ struct SimpleFixedNodeBranch : public QMCTraits typedef TinyVector IParamType; IParamType iParam; - /*! enum for vParam */ - enum + /** enum for vParam + * + * Easy serialization is a relatively minor concern compared to the + * annoyance this causes elsewhere. + */ + enum class SBVP { - B_TAU = 0, - B_TAUEFF, - B_ETRIAL, - B_EREF, - B_ENOW, - B_BRANCHMAX, - B_BRANCHCUTOFF, - B_BRANCHFILTER, - B_SIGMA2, - B_ACC_ENERGY, - B_ACC_SAMPLES, - B_FEEDBACK, - B_FILTERSCALE, - B_VPARAM_MAX = 17 + TAU = 0, + TAUEFF, + ETRIAL, + EREF, + ENOW, + BRANCHMAX, + BRANCHCUTOFF, + BRANCHFILTER, + SIGMA2, + ACC_ENERGY, + ACC_SAMPLES, + FEEDBACK, + FILTERSCALE, + VPARAM_MAX = 17 // four extra, why? Sloppy or undocumented hack? }; /** controlling parameters of real type * * Mostly internal */ - typedef TinyVector VParamType; + struct VParamType : public std::array(SBVP::VPARAM_MAX)> + { + using Base = std::array(SBVP::VPARAM_MAX)>; + FullPrecRealType& operator[](SBVP sbvp) { return Base::operator[](static_cast(sbvp)); } + const FullPrecRealType& operator[](SBVP sbvp) const { return Base::operator[](static_cast(sbvp)); } + FullPrecRealType& operator[](int sbvp) { return Base::operator[](sbvp); } + const FullPrecRealType& operator[](int sbvp) const { return Base::operator[](sbvp); } + }; VParamType vParam; /** number of remaning steps for a specific tasks @@ -203,6 +221,7 @@ struct SimpleFixedNodeBranch : public QMCTraits inline bool phaseChanged(RealType psi0) const { +// TODO: remove ifdef #if defined(QMC_COMPLEX) return false; #else @@ -261,13 +280,13 @@ struct SimpleFixedNodeBranch : public QMCTraits */ inline RealType branchWeightBare(RealType enew, RealType eold) const { - return std::exp(vParam[B_TAUEFF] * (vParam[B_ETRIAL] - 0.5 * (enew + eold))); + return std::exp(vParam[SBVP::TAUEFF] * (vParam[SBVP::ETRIAL] - 0.5 * (enew + eold))); } inline RealType branchWeightReleasedNode(RealType enew, RealType eold, RealType eref) const { if (BranchMode[B_DMCSTAGE]) - return std::exp(vParam[B_TAU] * (eref - 0.5 * (enew + eold))); + return std::exp(vParam[SBVP::TAU] * (eref - 0.5 * (enew + eold))); else return 1.0; } @@ -278,25 +297,25 @@ struct SimpleFixedNodeBranch : public QMCTraits */ inline RealType branchWeight(FullPrecRealType enew, FullPrecRealType eold) const { - FullPrecRealType taueff_ = vParam[B_TAUEFF] * 0.5; - FullPrecRealType x = std::max(vParam[B_EREF] - enew, vParam[B_EREF] - eold); - if (x > vParam[B_BRANCHMAX]) + FullPrecRealType taueff_ = vParam[SBVP::TAUEFF] * 0.5; + FullPrecRealType x = std::max(vParam[SBVP::EREF] - enew, vParam[SBVP::EREF] - eold); + if (x > vParam[SBVP::BRANCHMAX]) taueff_ = 0.0; - else if (x > vParam[B_BRANCHCUTOFF]) - taueff_ *= (1.0 - (x - vParam[B_BRANCHCUTOFF]) * vParam[B_BRANCHFILTER]); - return std::exp(taueff_ * (vParam[B_ETRIAL] * 2.0 - enew - eold)); + else if (x > vParam[SBVP::BRANCHCUTOFF]) + taueff_ *= (1.0 - (x - vParam[SBVP::BRANCHCUTOFF]) * vParam[SBVP::BRANCHFILTER]); + return std::exp(taueff_ * (vParam[SBVP::ETRIAL] * 2.0 - enew - eold)); } inline RealType symLinkAction(RealType logGf, RealType logGb, RealType enew, RealType eold) const { RealType driftaction = -0.5 * (logGf + logGb); //RealType energyaction = - RealType taueff_ = vParam[B_TAUEFF] * 0.5; - RealType x = std::max(vParam[B_EREF] - enew, vParam[B_EREF] - eold); - if (x > vParam[B_BRANCHMAX]) + RealType taueff_ = vParam[SBVP::TAUEFF] * 0.5; + RealType x = std::max(vParam[SBVP::EREF] - enew, vParam[SBVP::EREF] - eold); + if (x > vParam[SBVP::BRANCHMAX]) taueff_ = 0.0; - else if (x > vParam[B_BRANCHCUTOFF]) - taueff_ *= (1.0 - (x - vParam[B_BRANCHCUTOFF]) * vParam[B_BRANCHFILTER]); + else if (x > vParam[SBVP::BRANCHCUTOFF]) + taueff_ *= (1.0 - (x - vParam[SBVP::BRANCHCUTOFF]) * vParam[SBVP::BRANCHFILTER]); RealType energyaction = taueff_ * (enew + eold); return driftaction + energyaction; } @@ -304,7 +323,7 @@ struct SimpleFixedNodeBranch : public QMCTraits inline RealType symLinkActionBare(RealType logGf, RealType logGb, RealType enew, RealType eold) const { RealType driftaction = -0.5 * (logGf + logGb); - RealType taueff_ = vParam[B_TAUEFF] * 0.5; + RealType taueff_ = vParam[SBVP::TAUEFF] * 0.5; RealType energyaction = taueff_ * (enew + eold); // RealType wavefunctionaction= -psinew + psiold; return driftaction + energyaction; @@ -312,12 +331,12 @@ struct SimpleFixedNodeBranch : public QMCTraits inline RealType DMCLinkAction(RealType enew, RealType eold) const { - RealType taueff_ = vParam[B_TAUEFF] * 0.5; - RealType x = std::max(vParam[B_EREF] - enew, vParam[B_EREF] - eold); - if (x > vParam[B_BRANCHMAX]) + RealType taueff_ = vParam[SBVP::TAUEFF] * 0.5; + RealType x = std::max(vParam[SBVP::EREF] - enew, vParam[SBVP::EREF] - eold); + if (x > vParam[SBVP::BRANCHMAX]) taueff_ = 0.0; - else if (x > vParam[B_BRANCHCUTOFF]) - taueff_ *= (1.0 - (x - vParam[B_BRANCHCUTOFF]) * vParam[B_BRANCHFILTER]); + else if (x > vParam[SBVP::BRANCHCUTOFF]) + taueff_ *= (1.0 - (x - vParam[SBVP::BRANCHCUTOFF]) * vParam[SBVP::BRANCHFILTER]); return taueff_ * (enew + eold); } /** return the branch weight according to JCP1993 Umrigar et al. Appendix A p=1, q=0 @@ -328,9 +347,9 @@ struct SimpleFixedNodeBranch : public QMCTraits */ inline RealType branchWeight(RealType enew, RealType eold, RealType scnew, RealType scold) const { - FullPrecRealType s1 = (vParam[B_ETRIAL] - vParam[B_EREF]) + (vParam[B_EREF] - enew) * scnew; - FullPrecRealType s0 = (vParam[B_ETRIAL] - vParam[B_EREF]) + (vParam[B_EREF] - eold) * scold; - return std::exp(vParam[B_TAUEFF] * 0.5 * (s1 + s0)); + FullPrecRealType s1 = (vParam[SBVP::ETRIAL] - vParam[SBVP::EREF]) + (vParam[SBVP::EREF] - enew) * scnew; + FullPrecRealType s0 = (vParam[SBVP::ETRIAL] - vParam[SBVP::EREF]) + (vParam[SBVP::EREF] - eold) * scold; + return std::exp(vParam[SBVP::TAUEFF] * 0.5 * (s1 + s0)); } /** return the branch weight according to JCP1993 Umrigar et al. Appendix A @@ -342,9 +361,9 @@ struct SimpleFixedNodeBranch : public QMCTraits */ inline RealType branchWeight(RealType enew, RealType eold, RealType scnew, RealType scold, RealType p) const { - FullPrecRealType s1 = (vParam[B_ETRIAL] - vParam[B_EREF]) + (vParam[B_EREF] - enew) * scnew; - FullPrecRealType s0 = (vParam[B_ETRIAL] - vParam[B_EREF]) + (vParam[B_EREF] - eold) * scold; - return std::exp(vParam[B_TAUEFF] * (p * 0.5 * (s1 - s0) + s0)); + FullPrecRealType s1 = (vParam[SBVP::ETRIAL] - vParam[SBVP::EREF]) + (vParam[SBVP::EREF] - enew) * scnew; + FullPrecRealType s0 = (vParam[SBVP::ETRIAL] - vParam[SBVP::EREF]) + (vParam[SBVP::EREF] - eold) * scold; + return std::exp(vParam[SBVP::TAUEFF] * (p * 0.5 * (s1 - s0) + s0)); //return std::exp(TauEff*(p*0.5*(sp-sq)+sq)); } @@ -359,15 +378,15 @@ struct SimpleFixedNodeBranch : public QMCTraits ScaleSum += scnew + scold; ScaleNum += 2; FullPrecRealType scavg = (ScaleNum > 10000) ? ScaleSum / (RealType)ScaleNum : 1.0; - FullPrecRealType s1 = (vParam[B_ETRIAL] - vParam[B_EREF]) + (vParam[B_EREF] - enew) * scnew / scavg; - FullPrecRealType s0 = (vParam[B_ETRIAL] - vParam[B_EREF]) + (vParam[B_EREF] - eold) * scold / scavg; + FullPrecRealType s1 = (vParam[SBVP::ETRIAL] - vParam[SBVP::EREF]) + (vParam[SBVP::EREF] - enew) * scnew / scavg; + FullPrecRealType s0 = (vParam[SBVP::ETRIAL] - vParam[SBVP::EREF]) + (vParam[SBVP::EREF] - eold) * scold / scavg; return std::exp(taueff * 0.5 * (s1 + s0)); } - inline RealType getEref() const { return vParam[B_EREF]; } - inline RealType getEtrial() const { return vParam[B_ETRIAL]; } - inline RealType getTau() const { return vParam[B_TAU]; } - inline RealType getTauEff() const { return vParam[B_TAUEFF]; } + inline RealType getEref() const { return vParam[SBVP::EREF]; } + inline RealType getEtrial() const { return vParam[SBVP::ETRIAL]; } + inline RealType getTau() const { return vParam[SBVP::TAU]; } + inline RealType getTauEff() const { return vParam[SBVP::TAUEFF]; } /** perform branching * @param iter current step @@ -434,5 +453,7 @@ private: int Nelec = 0); }; +std::ostream& operator<<(std::ostream& os, SimpleFixedNodeBranch::VParamType& rhs); + } // namespace qmcplusplus #endif From f52453f3e7c3d09ea83c34816414015f6aa379b6 Mon Sep 17 00:00:00 2001 From: Ye Luo Date: Mon, 21 Oct 2019 18:57:25 -0500 Subject: [PATCH 33/41] Fix manual compilation. --- manual/gaussian_orbitals_solids.tex | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/manual/gaussian_orbitals_solids.tex b/manual/gaussian_orbitals_solids.tex index d71442fac..2e5c176d4 100644 --- a/manual/gaussian_orbitals_solids.tex +++ b/manual/gaussian_orbitals_solids.tex @@ -177,7 +177,7 @@ calculation and will generate the HDF5 similarly to the nonperiodic PySCF calculation in Section~\ref{sec:convert4qmc} (convert4qmc). The function is distributed with QMCPACK and is located in the qmcpack/src/QMCTools directory under the name -\textit{PyscfToQmcpack.py}. Note that you need to specify the supertwist coordinates that was used with the provided kpoints. The supertwist must match the coordinates of the K-points otherwise the phase factor for the atomic orbital will be incorrect and incorrect results will be obtained. (For more details on how to generate tiling with PySCF and Nexus, refer to the Nexus guide or the 2019 QMCPACK Workshop material available on github: \href{https://github.com/QMCPACK/qmcpack_workshop_2019} under \textbf{qmcpack_workshop_2019/day2_nexus/pyscf/04_pyscf_diamond_hf_qmc/} +\textit{PyscfToQmcpack.py}. Note that you need to specify the supertwist coordinates that was used with the provided kpoints. The supertwist must match the coordinates of the K-points otherwise the phase factor for the atomic orbital will be incorrect and incorrect results will be obtained. (For more details on how to generate tiling with PySCF and Nexus, refer to the Nexus guide or the 2019 QMCPACK Workshop material available on github: \url{https://github.com/QMCPACK/qmcpack_workshop_2019} under \textbf{qmcpack\_workshop\_2019/day2\_nexus/pyscf/04\_pyscf\_diamond\_hf\_qmc/} For the converter in the script to be called properly, you need to specify the path to the file in your PYTHONPATH such as @@ -275,7 +275,7 @@ $\Gamma$-point or using multiple k-points will work without further modification. Running convert4qmc will generate 3 input files:\\ -\begin{lstlisting}[style=QMCPXML,caption=C_diamond-tiled-cplx.structure.xml. This file contains the geometry of the system.] +\begin{lstlisting}[style=QMCPXML,caption=C\_diamond-tiled-cplx.structure.xml. This file contains the geometry of the system.] @@ -315,7 +315,7 @@ Running convert4qmc will generate 3 input files:\\ \end{lstlisting} As one can see, for both examples, the two-atom primitive cell has been expanded to contain four atoms in a $2 \times 1 \times 1$ carbon cell. -\begin{lstlisting}[style=QMCPXML,caption=C_diamond-tiled-cplx.wfj.xml. This file contains the trial wavefunction.] +\begin{lstlisting}[style=QMCPXML,caption=C\_diamond-tiled-cplx.wfj.xml. This file contains the trial wavefunction.] From f98d68335ffceff1b48698a140387eeb2b77597e Mon Sep 17 00:00:00 2001 From: Ye Luo Date: Mon, 21 Oct 2019 18:57:45 -0500 Subject: [PATCH 34/41] Update manual. --- manual/singledeterminant.tex | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/manual/singledeterminant.tex b/manual/singledeterminant.tex index 4e5722836..f416ee806 100644 --- a/manual/singledeterminant.tex +++ b/manual/singledeterminant.tex @@ -14,7 +14,7 @@ Table~\ref{table:singledet}. \multicolumn{2}{l}{Child elements:} & \multicolumn{4}{l}{\texttt{determinant}}\\ \multicolumn{2}{l}{Attribute:} & \multicolumn{4}{l}{}\\ & \bfseries Name & \bfseries Datatype & \bfseries Values & \bfseries Default & \bfseries Description \\ - & \texttt{delay\_rank} & Integer & >0 & 1 & Number of delayed updates. \\ + & \texttt{delay\_rank} & Integer & >=0 & 1 & Number of delayed updates. \\ & \texttt{optimize} & Text & yes/no & yes & Enable orbital optimization. \\ \hline \end{tabularx} @@ -39,7 +39,8 @@ Table~\ref{table:singledet}. Additional information: \begin{itemize} \item \ixml{delay\_rank}. This option enables delayed updates of the Slater matrix inverse when particle-by-particle move is used. -By default, \ixml{delay\_rank=1} uses the Fahy's variant~\cite{Fahy1990} of the Sherman-Morrison rank-1 update, which is mostly using memory bandwidth-bound BLAS-2 calls. +By default or if \ixml{delay\_rank=0} given in the input file, QMCPACK sets 1 for Slater matrices with a leading dimension $<192$ and 32 otherwise. +\ixml{delay\_rank=1} uses the Fahy's variant~\cite{Fahy1990} of the Sherman-Morrison rank-1 update, which is mostly using memory bandwidth-bound BLAS-2 calls. With \ixml{delay\_rank>1}, the delayed update algorithm~\cite{Luo2018delayedupdate,McDaniel2017} turns most of the computation to compute bound BLAS-3 calls. Tuning this parameter is highly recommended to gain the best performance on medium-to-large problem sizes ($>200$ electrons). We have seen up to an order of magnitude speedup on large problem sizes. From 55ecc21b1caf663e7690dfb7be56e5dd56562c6a Mon Sep 17 00:00:00 2001 From: Peter Doak Date: Mon, 21 Oct 2019 22:14:41 -0400 Subject: [PATCH 35/41] improved killing and spawning of walkers NLMH set for all ham --- src/QMCDrivers/MCPopulation.cpp | 107 +++++++++++------------ src/QMCDrivers/MCPopulation.h | 7 +- src/QMCDrivers/QMCDriverNew.cpp | 42 +++++---- src/QMCDrivers/QMCDriverNew.h | 11 ++- src/QMCDrivers/SimpleFixedNodeBranch.cpp | 2 +- src/QMCDrivers/WalkerControlBase.cpp | 2 +- 6 files changed, 92 insertions(+), 79 deletions(-) diff --git a/src/QMCDrivers/MCPopulation.cpp b/src/QMCDrivers/MCPopulation.cpp index 8525c0da8..4a789b3fc 100644 --- a/src/QMCDrivers/MCPopulation.cpp +++ b/src/QMCDrivers/MCPopulation.cpp @@ -22,7 +22,7 @@ MCPopulation::MCPopulation(int num_ranks, ParticleSet* elecs, TrialWaveFunction* trial_wf, QMCHamiltonian* hamiltonian, - int this_rank) + int this_rank) : num_ranks_(num_ranks), trial_wf_(trial_wf), elec_particle_set_(elecs), hamiltonian_(hamiltonian), rank_(this_rank) { walker_offsets_ = mcwc.WalkerOffsets; @@ -54,15 +54,12 @@ MCPopulation::MCPopulation(int num_ranks, /** Default creates walkers equal to num_local_walkers_ and zeroed positions */ -void MCPopulation::createWalkers() -{ - createWalkers(num_local_walkers_); -} +void MCPopulation::createWalkers() { createWalkers(num_local_walkers_); } void MCPopulation::createWalkerInplace(UPtr& walker_ptr) { //SO this would be where the walker reuse hack would go - walker_ptr = std::make_unique(num_particles_); + walker_ptr = std::make_unique(num_particles_); walker_ptr->R = elec_particle_set_->R; walker_ptr->registerData(); walker_ptr->Properties = elec_particle_set_->Properties; @@ -97,9 +94,9 @@ void MCPopulation::createWalkers(IndexType num_walkers) } int num_walkers_created = 0; - for(auto& walker_ptr: walkers_) + for (auto& walker_ptr : walkers_) { - if( walker_ptr->ID == 0 ) + if (walker_ptr->ID == 0) { // And so walker ID's start at one because 0 is magic. // TODO: This is C++ all indexes start at 0, make uninitialized ID = -1 @@ -107,7 +104,7 @@ void MCPopulation::createWalkers(IndexType num_walkers) walker_ptr->ParentID = walker_ptr->ID; } } - + outputManager.pause(); // Sadly the wfc makeClone interface depends on the full particle set as a way to not to keep track @@ -127,7 +124,7 @@ void MCPopulation::createWalkers(IndexType num_walkers) while (it_wtw != walker_trial_wavefunctions_.end()) { it_wtw->reset(trial_wf_->makeClone(**it_weps)); - it_ham->reset(hamiltonian_->makeClone(**it_weps,**it_wtw)); + it_ham->reset(hamiltonian_->makeClone(**it_weps, **it_wtw)); ++it_weps; ++it_wtw; ++it_ham; @@ -137,25 +134,15 @@ void MCPopulation::createWalkers(IndexType num_walkers) RefVector mcp_wfbuffers; mcp_wfbuffers.reserve(num_walkers); - std::for_each(walkers_.begin(), - walkers_.end(), - [&mcp_wfbuffers](auto& walker) { - mcp_wfbuffers.push_back((*walker).DataSet); - }); + std::for_each(walkers_.begin(), walkers_.end(), + [&mcp_wfbuffers](auto& walker) { mcp_wfbuffers.push_back((*walker).DataSet); }); - TrialWaveFunction::flex_registerData(walker_trial_wavefunctions_, - walker_elec_particle_sets_, - mcp_wfbuffers); + TrialWaveFunction::flex_registerData(walker_trial_wavefunctions_, walker_elec_particle_sets_, mcp_wfbuffers); - std::for_each(walkers_.begin(), - walkers_.end(), - [](auto& walker) { - (*walker).DataSet.allocate(); - }); + std::for_each(walkers_.begin(), walkers_.end(), [](auto& walker) { (*walker).DataSet.allocate(); }); } - /** creates a walker and returns a reference * * none of the objects are "reused" @@ -165,40 +152,41 @@ void MCPopulation::createWalkers(IndexType num_walkers) MCPopulation::MCPWalker& MCPopulation::spawnWalker() { ++num_local_walkers_; - auto it_walkers = walkers_.begin(); - int walker_index = 0; - while (it_walkers != walkers_.end()) - { - if (*it_walkers == nullptr) - { - createWalkerInplace(*it_walkers); - allocateWalkerStuffInplace(walker_index); - return **it_walkers; - } - ++it_walkers; - ++walker_index; - } - - walkers_.push_back(std::make_unique(num_particles_)); outputManager.pause(); - - walkers_.back()->R = elec_particle_set_->R; - walkers_.back()->registerData(); - walkers_.back()->Properties = elec_particle_set_->Properties; + if (dead_walkers_.size() > 0) + { + walkers_.push_back(std::move(dead_walkers_.back())); + dead_walkers_.pop_back(); + } + else + { + walkers_.push_back(std::make_unique(num_particles_)); + walkers_.back()->R = elec_particle_set_->R; + walkers_.back()->registerData(); + walkers_.back()->Properties = elec_particle_set_->Properties; + } walker_elec_particle_sets_.push_back(std::make_unique(*elec_particle_set_)); walker_trial_wavefunctions_.push_back(UPtr{}); walker_trial_wavefunctions_.back().reset(trial_wf_->makeClone(*(walker_elec_particle_sets_.back()))); walker_hamiltonians_.push_back(UPtr{}); - walker_hamiltonians_.back().reset(hamiltonian_->makeClone(*(walker_elec_particle_sets_.back()), - *(walker_trial_wavefunctions_.back()))); - + walker_hamiltonians_.back().reset( + hamiltonian_->makeClone(*(walker_elec_particle_sets_.back()), *(walker_trial_wavefunctions_.back()))); outputManager.resume(); - - walker_trial_wavefunctions_.back()->registerData(*(walker_elec_particle_sets_.back()), - walkers_.back()->DataSet); + walker_trial_wavefunctions_.back()->registerData(*(walker_elec_particle_sets_.back()), walkers_.back()->DataSet); return *(walkers_.back()); } +/** Kill last walker + */ +void MCPopulation::killLastWalker() +{ + --num_local_walkers_; + dead_walkers_.push_back(std::move(walkers_.back())); + walkers_.pop_back(); + walker_elec_particle_sets_.pop_back(); + walker_trial_wavefunctions_.pop_back(); + walker_hamiltonians_.pop_back(); +} /** Kill a walker */ void MCPopulation::killWalker(MCPWalker& walker) @@ -206,31 +194,42 @@ void MCPopulation::killWalker(MCPWalker& walker) --num_local_walkers_; // find the walker and null its pointer in the walker vector auto it_walkers = walkers_.begin(); + auto it_psets = walker_elec_particle_sets_.begin(); + auto it_twfs = walker_trial_wavefunctions_.begin(); + auto it_hams = walker_hamiltonians_.begin(); while (it_walkers != walkers_.end()) { if (&walker == (*it_walkers).get()) { - (*it_walkers).reset(nullptr); + dead_walkers_.push_back(std::move(*it_walkers)); + walkers_.erase(it_walkers); + walker_elec_particle_sets_.erase(it_psets); + walker_trial_wavefunctions_.erase(it_twfs); + walker_hamiltonians_.erase(it_hams); return; } + ++it_walkers; + ++it_psets; + ++it_twfs; + ++it_hams; } throw std::runtime_error("Attempt to kill nonexistent walker in MCPopulation!"); } QMCTraits::IndexType MCPopulation::update_num_global_walkers(Communicate* comm) { - int ncontexts = comm->size(); + int ncontexts = comm->size(); std::vector nw(ncontexts, 0); std::vector nwoff(ncontexts + 1, 0); - + nw[comm->rank()] = num_local_walkers_; comm->allreduce(nw); - + for (int ip = 0; ip < ncontexts; ++ip) nwoff[ip + 1] = nwoff[ip] + nw[ip]; num_global_walkers_ = nwoff[ncontexts]; - walker_offsets_ = nwoff; + walker_offsets_ = nwoff; return num_global_walkers_; } diff --git a/src/QMCDrivers/MCPopulation.h b/src/QMCDrivers/MCPopulation.h index 4bf578b6f..e06605305 100644 --- a/src/QMCDrivers/MCPopulation.h +++ b/src/QMCDrivers/MCPopulation.h @@ -53,7 +53,8 @@ private: ParticleSet ions_; std::vector walker_offsets_; // By making this a linked list and creating the crowds at the same time we could get first touch. - std::vector> walkers_; + UPtrVector walkers_; + UPtrVector dead_walkers_; std::vector> particle_group_indexes_; SpeciesSet species_set_; std::vector ptclgrp_mass_; @@ -118,6 +119,7 @@ public: */ MCPWalker& spawnWalker(); void killWalker(MCPWalker&); + void killLastWalker(); void createWalkerInplace(UPtr& walker_ptr); void allocateWalkerStuffInplace(int walker_index); /** }@ */ @@ -172,7 +174,7 @@ public: * is invalid. Ideally MCPopulation not process any calls in this state, next best would be to only * process calls to become valid. */ - IndexType get_active_walkers() const { return walkers_.size(); } + //IndexType get_active_walkers() const { return walkers_.size(); } int get_num_ranks() const { return num_ranks_; } IndexType get_num_global_walkers() const { return num_global_walkers_; } IndexType update_num_global_walkers(Communicate* comm); @@ -198,6 +200,7 @@ public: } UPtrVector& get_walkers() { return walkers_; } + UPtrVector& get_hamiltonians() { return walker_hamiltonians_; } const std::vector>& get_particle_group_indexes() const { return particle_group_indexes_; } const std::vector& get_ptclgrp_mass() const { return ptclgrp_mass_; } const std::vector& get_ptclgrp_inv_mass() const { return ptclgrp_inv_mass_; } diff --git a/src/QMCDrivers/QMCDriverNew.cpp b/src/QMCDrivers/QMCDriverNew.cpp index 78fa14048..460565c9a 100644 --- a/src/QMCDrivers/QMCDriverNew.cpp +++ b/src/QMCDrivers/QMCDriverNew.cpp @@ -149,6 +149,9 @@ void QMCDriverNew::process(xmlNodePtr cur) if (!drift_modifier_) drift_modifier_.reset(createDriftModifier(qmcdriver_input_)); + // I don't think its at all good that the branch engine gets mutated here + // Carrying the population on is one thing but a branch engine seems like it + // should be fresh per section. branch_engine_->put(cur); estimator_manager_->put(H, cur); @@ -321,27 +324,30 @@ void QMCDriverNew::setupWalkers() IndexType local_walkers = calc_default_local_walkers(qmcdriver_input_.get_walkers_per_rank()); // side effect updates walkers_per_crowd_; - addWalkers(local_walkers, ParticleAttrib>(population_.get_num_particles())); + makeLocalWalkers(local_walkers, ParticleAttrib>(population_.get_num_particles())); } -/** Add walkers to the end of the ensemble of walkers. - * @param nwalkers number of walkers to add - * - */ -void QMCDriverNew::addWalkers(int nwalkers, const ParticleAttrib>& positions) +void QMCDriverNew::makeLocalWalkers(int nwalkers, const ParticleAttrib>& positions) { - setNonLocalMoveHandler_(population_.get_golden_hamiltonian()); - population_.createWalkers(nwalkers); - // else if (nwalkers < 0) - // { - // W.destroyWalkers(-nwalkers); - // app_log() << " Removed " << -nwalkers << " walkers. Current number of walkers =" << W.getActiveWalkers() - // << std::endl; - // } - // else - // { - // app_log() << " Using the current " << W.getActiveWalkers() << " walkers." << std::endl; - // } + if (population_.get_walkers().size() == 0) + { + population_.createWalkers(nwalkers); + } + else if(population_.get_walkers().size() < nwalkers) + { + IndexType num_additional_walkers = nwalkers - population_.get_walkers().size(); + for(int i = 0; i < num_additional_walkers; ++i) + population_.spawnWalker(); + } + else + { + IndexType num_walkers_to_kill = population_.get_walkers().size() - nwalkers; + for(int i = 0; i < num_walkers_to_kill; ++i) + population_.killLastWalker(); + } + for(UPtr& ham : population_.get_hamiltonians()) + setNonLocalMoveHandler_(*ham); + // setWalkerOffsets(); // ////update the global number of walkers // ////int nw=W.getActiveWalkers(); diff --git a/src/QMCDrivers/QMCDriverNew.h b/src/QMCDrivers/QMCDriverNew.h index 36a8e1789..eedec3a55 100644 --- a/src/QMCDrivers/QMCDriverNew.h +++ b/src/QMCDrivers/QMCDriverNew.h @@ -167,7 +167,7 @@ public: std::string getEngineName() { return QMCType; } unsigned long getDriverMode() { return qmc_driver_mode_.to_ulong(); } IndexType get_walkers_per_crowd() const { return walkers_per_crowd_; } - IndexType get_living_walkers() const { return population_.get_active_walkers(); } + IndexType get_living_walkers() const { return population_.get_walkers().size(); } /** @ingroup Legacy interface to be dropped * @{ @@ -183,7 +183,7 @@ public: static void initialLogEvaluation(int crowd_id, UPtrVector& crowds, UPtrVector& step_context); - + /** should be set in input don't see a reason to set individually * @param pbyp if true, use particle-by-particle update */ @@ -349,12 +349,17 @@ public: bool putQMCInfo(xmlNodePtr cur); - void addWalkers(int nwalkers, const ParticleAttrib>& positions); + /** Adjust populations local walkers to this number + * @param nwalkers number of walkers to add + * + */ + void makeLocalWalkers(int nwalkers, const ParticleAttrib>& positions); int get_num_crowds() { return num_crowds_; } void set_num_crowds(int num_crowds, const std::string& reason); void set_walkers_per_rank(int walkers_per_rank, const std::string& reason); DriftModifierBase& get_drift_modifier() const { return *drift_modifier_; } + /** record the state of the block * @param block current block * diff --git a/src/QMCDrivers/SimpleFixedNodeBranch.cpp b/src/QMCDrivers/SimpleFixedNodeBranch.cpp index 578460711..5a4e0ff53 100644 --- a/src/QMCDrivers/SimpleFixedNodeBranch.cpp +++ b/src/QMCDrivers/SimpleFixedNodeBranch.cpp @@ -464,7 +464,7 @@ void SimpleFixedNodeBranch::branch(int iter, UPtrVector& crowds, MCPopul RefVector walkers(convertUPtrToRefVector(population.get_walkers())); FullPrecRealType pop_now; - if (BranchMode[B_DMCSTAGE] || iter) + if (false) //BranchMode[B_DMCSTAGE] || iter) pop_now = WalkerController->branch(iter, population, 0.1); else pop_now = WalkerController->doNotBranch(iter, population); //do not branch for the first step of a warmup diff --git a/src/QMCDrivers/WalkerControlBase.cpp b/src/QMCDrivers/WalkerControlBase.cpp index ec026abba..22ae33560 100644 --- a/src/QMCDrivers/WalkerControlBase.cpp +++ b/src/QMCDrivers/WalkerControlBase.cpp @@ -633,7 +633,7 @@ WalkerControlBase::PopulationAdjustment WalkerControlBase::calcPopulationAdjustm //update curData curData[ENERGY_INDEX] = esum; curData[ENERGY_SQ_INDEX] = e2sum; - curData[WALKERSIZE_INDEX] = pop.get_active_walkers(); + curData[WALKERSIZE_INDEX] = pop.get_walkers().size(); curData[WEIGHT_INDEX] = wsum; curData[EREF_INDEX] = ecum; curData[R2ACCEPTED_INDEX] = r2_accepted; From 8e54ac201a8f5341da456f6fe88006b6cd613fec Mon Sep 17 00:00:00 2001 From: Peter Doak Date: Mon, 21 Oct 2019 22:33:59 -0400 Subject: [PATCH 36/41] turn on non local moves --- .../solids/diamondC_2x1x1_pp/qmc_short_vmcbatch_dmcbatch.in.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/solids/diamondC_2x1x1_pp/qmc_short_vmcbatch_dmcbatch.in.xml b/tests/solids/diamondC_2x1x1_pp/qmc_short_vmcbatch_dmcbatch.in.xml index c228f3aaf..3c791abe7 100644 --- a/tests/solids/diamondC_2x1x1_pp/qmc_short_vmcbatch_dmcbatch.in.xml +++ b/tests/solids/diamondC_2x1x1_pp/qmc_short_vmcbatch_dmcbatch.in.xml @@ -101,7 +101,7 @@ 0.005 100 25 - no + yes From 1fcc5d5d3aac7ffde7e0f513bab4d24118090a93 Mon Sep 17 00:00:00 2001 From: Peter Doak Date: Tue, 22 Oct 2019 12:45:50 -0400 Subject: [PATCH 37/41] vParam now has type safe operator[], IO functions don't require int --- src/QMCDrivers/BranchIO.cpp | 13 +++++++------ src/QMCDrivers/BranchIO.h | 10 ++++++---- src/QMCDrivers/SimpleFixedNodeBranch.h | 19 ++++++++++--------- 3 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/QMCDrivers/BranchIO.cpp b/src/QMCDrivers/BranchIO.cpp index 6e48cd3e9..ef669eb54 100644 --- a/src/QMCDrivers/BranchIO.cpp +++ b/src/QMCDrivers/BranchIO.cpp @@ -120,8 +120,9 @@ bool BranchIO::write(const std::string& fname) // Put log filename in property tree pt.put("state.branchmode", ref.BranchMode); - for (int i = 0; i < vParamName.size(); ++i) - pt.put("state.vparam." + vParamName[i], ref.vParam[i]); + auto it_vparam = ref.vParam.begin(); + for (auto& name : vParamName) + pt.put("state.vparam." + name, *(it_vparam++)); for (int i = 0; i < iParamName.size(); ++i) pt.put("state.iparam." + iParamName[i], ref.iParam[i]); @@ -188,10 +189,10 @@ bool BranchIO::read(const std::string& fname) { ref.iParam[i++] = v.second.get_value(); } - i = 0; + auto it_vparam = ref.vParam.begin(); BOOST_FOREACH (const ptree::value_type& v, pt.get_child("state.vparam")) { - ref.vParam[i++] = v.second.get_value(); + *(it_vparam++) = v.second.get_value(); } found_config = 1; } @@ -278,8 +279,8 @@ void BranchIO::bcast_state() if (myComm->rank()) { int ii = 0; - for (int i = 0; i < ref.vParam.size(); ++i, ++ii) - ref.vParam[i] = pdata[ii]; + for (auto& vpar : ref.vParam) + vpar = pdata[ii++]; for (int i = 0; i < ref.iParam.size(); ++i, ++ii) ref.iParam[i] = static_cast(pdata[ii]); ref.BranchMode = static_cast(pdata[ii]); diff --git a/src/QMCDrivers/BranchIO.h b/src/QMCDrivers/BranchIO.h index fc2ec3fa9..0d7c1f96c 100644 --- a/src/QMCDrivers/BranchIO.h +++ b/src/QMCDrivers/BranchIO.h @@ -21,10 +21,11 @@ namespace qmcplusplus { struct BranchIO { - typedef SimpleFixedNodeBranch::RealType RealType; - typedef SimpleFixedNodeBranch::BranchModeType BranchModeType; - typedef SimpleFixedNodeBranch::IParamType IParamType; - typedef SimpleFixedNodeBranch::VParamType VParamType; + using SFNB = SimpleFixedNodeBranch; + using RealType = SFNB::RealType; + using BranchModeType = SFNB::BranchModeType; + using IParamType = SFNB::IParamType; + using VParamType = SFNB::VParamType; SimpleFixedNodeBranch& ref; Communicate* myComm; @@ -34,6 +35,7 @@ struct BranchIO bool read(const std::string& fname); void bcast_state(); + // TODO: names should be defined with the enum in SimpleFixedNodeBranch.h static std::vector vParamName; static std::vector iParamName; diff --git a/src/QMCDrivers/SimpleFixedNodeBranch.h b/src/QMCDrivers/SimpleFixedNodeBranch.h index df407e7aa..638639a6c 100644 --- a/src/QMCDrivers/SimpleFixedNodeBranch.h +++ b/src/QMCDrivers/SimpleFixedNodeBranch.h @@ -128,7 +128,7 @@ struct SimpleFixedNodeBranch : public QMCTraits * Easy serialization is a relatively minor concern compared to the * annoyance this causes elsewhere. */ - enum class SBVP + enum class SimpleBranchVectorParameter { TAU = 0, TAUEFF, @@ -145,19 +145,20 @@ struct SimpleFixedNodeBranch : public QMCTraits FILTERSCALE, VPARAM_MAX = 17 // four extra, why? Sloppy or undocumented hack? }; - - /** controlling parameters of real type + using SBVP = SimpleBranchVectorParameter; + + /** controlling parameters of full precision real type * * Mostly internal */ - struct VParamType : public std::array(SBVP::VPARAM_MAX)> + template + struct VParams : public std::array(PAR_ENUM::VPARAM_MAX)> { - using Base = std::array(SBVP::VPARAM_MAX)>; - FullPrecRealType& operator[](SBVP sbvp) { return Base::operator[](static_cast(sbvp)); } - const FullPrecRealType& operator[](SBVP sbvp) const { return Base::operator[](static_cast(sbvp)); } - FullPrecRealType& operator[](int sbvp) { return Base::operator[](sbvp); } - const FullPrecRealType& operator[](int sbvp) const { return Base::operator[](sbvp); } + using Base = std::array(PAR_ENUM::VPARAM_MAX)>; + FullPrecRealType& operator[](PAR_ENUM sbvp) { return Base::operator[](static_cast(sbvp)); } + const FullPrecRealType& operator[](PAR_ENUM sbvp) const { return Base::operator[](static_cast(sbvp)); } }; + using VParamType = VParams; VParamType vParam; /** number of remaning steps for a specific tasks From 3e4c5c74c0b622d37fdbc5913461fb6510e122a5 Mon Sep 17 00:00:00 2001 From: Peter Doak Date: Tue, 22 Oct 2019 12:48:02 -0400 Subject: [PATCH 38/41] removing have boost ifdef, not having boost is a fatal build error --- src/QMCDrivers/BranchIO.cpp | 46 ------------------------------------- 1 file changed, 46 deletions(-) diff --git a/src/QMCDrivers/BranchIO.cpp b/src/QMCDrivers/BranchIO.cpp index ef669eb54..09401a6ce 100644 --- a/src/QMCDrivers/BranchIO.cpp +++ b/src/QMCDrivers/BranchIO.cpp @@ -167,7 +167,6 @@ bool BranchIO::read(const std::string& fname) { int found_config = 0; -#if defined(HAVE_LIBBOOST) if (myComm->rank() == 0) { initAttributes(); @@ -197,51 +196,6 @@ bool BranchIO::read(const std::string& fname) found_config = 1; } } -#else - if (myComm->rank() == 0) - { - HDFVersion res_version(0, 4); //start using major=0 and minor=4 - HDFVersion res_20080624(0, 5); //major revision on 2008-06-24 0.5 - HDFVersion in_version(0, 1); - - //append .config.h5 if missing - std::string h5name(fname); - if (fname.find("qmc.h5") >= fname.size()) - h5name.append(".qmc.h5"); - - hdf_archive prevconfig(myComm, true); - found_config = prevconfig.open(h5name, H5F_ACC_RDONLY); - - if (found_config) - { - int n = ref.vParam.size() + ref.iParam.size(); - /** temporary storage to broadcast restart data */ - prevconfig.read(in_version.version, hdf::version); - myComm->bcast(in_version.version); - prevconfig.push(hdf::main_state, false); - if (in_version >= res_20080624) - { - //need a better version control - prevconfig.push(hdf::qmc_status, false); - prevconfig.read(ref.vParam, "vparam"); - prevconfig.read(ref.iParam, "iparam"); - prevconfig.read(ref.BranchMode, "branchmode"); - - prevconfig.push("histogram", false); - prevconfig.read(ref.EnergyHist, "energy"); - prevconfig.read(ref.VarianceHist, "variance"); - prevconfig.read(ref.R2Accepted, "r2accepted"); - prevconfig.read(ref.R2Proposed, "r2proposed"); - prevconfig.pop(); - - prevconfig.pop(); - } - else - found_config = false; - prevconfig.pop(); - } - } -#endif myComm->bcast(found_config); if (!found_config) From 34f62b035b1da9bf98e619a06322a6e15fa60ecf Mon Sep 17 00:00:00 2001 From: Juha Tiihonen Date: Tue, 22 Oct 2019 14:33:57 -0400 Subject: [PATCH 39/41] Add ChiesaPBCAA IonIon forces to existing unit test --- src/QMCHamiltonians/tests/test_force.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/QMCHamiltonians/tests/test_force.cpp b/src/QMCHamiltonians/tests/test_force.cpp index adade128d..8d7e599e7 100644 --- a/src/QMCHamiltonians/tests/test_force.cpp +++ b/src/QMCHamiltonians/tests/test_force.cpp @@ -172,10 +172,13 @@ TEST_CASE("Chiesa Force", "[hamiltonian]") ParticleSet elec; ions.setName("ion"); - ions.create(1); + ions.create(2); ions.R[0][0] = 0.0; ions.R[0][1] = 0.0; ions.R[0][2] = 0.0; + ions.R[1][0] = 2.0; + ions.R[1][1] = 0.0; + ions.R[1][2] = 0.0; elec.setName("elec"); elec.create(2); @@ -224,11 +227,18 @@ TEST_CASE("Chiesa Force", "[hamiltonian]") elec.update(); force.evaluate(elec); std::cout << " Force = " << force.forces << std::endl; + std::cout << " Forces_IonIon = " << force.forces_IonIon << std::endl; // Unvalidated externally REQUIRE(force.forces[0][0] == Approx(3.186559306)); REQUIRE(force.forces[0][1] == Approx(3.352572459)); REQUIRE(force.forces[0][2] == Approx(0.0)); + REQUIRE(force.forces_IonIon[0][0] == Approx(-0.1478626893)); + REQUIRE(force.forces_IonIon[0][1] == Approx(0.0)); + REQUIRE(force.forces_IonIon[0][2] == Approx(0.0)); + REQUIRE(force.forces_IonIon[0][0] == Approx(0.1478626893)); + REQUIRE(force.forces_IonIon[0][1] == Approx(0.0)); + REQUIRE(force.forces_IonIon[0][2] == Approx(0.0)); // It seems a bit silly to test the makeClone method From 4d0a9e62452104b5511832f5512ce73680d4f7d0 Mon Sep 17 00:00:00 2001 From: Juha Tiihonen Date: Tue, 22 Oct 2019 15:08:54 -0400 Subject: [PATCH 40/41] Fix recent unit test --- src/QMCHamiltonians/tests/test_force.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/QMCHamiltonians/tests/test_force.cpp b/src/QMCHamiltonians/tests/test_force.cpp index 8d7e599e7..896e3d6b0 100644 --- a/src/QMCHamiltonians/tests/test_force.cpp +++ b/src/QMCHamiltonians/tests/test_force.cpp @@ -236,10 +236,9 @@ TEST_CASE("Chiesa Force", "[hamiltonian]") REQUIRE(force.forces_IonIon[0][0] == Approx(-0.1478626893)); REQUIRE(force.forces_IonIon[0][1] == Approx(0.0)); REQUIRE(force.forces_IonIon[0][2] == Approx(0.0)); - REQUIRE(force.forces_IonIon[0][0] == Approx(0.1478626893)); - REQUIRE(force.forces_IonIon[0][1] == Approx(0.0)); - REQUIRE(force.forces_IonIon[0][2] == Approx(0.0)); - + REQUIRE(force.forces_IonIon[1][0] == Approx(0.1478626893)); + REQUIRE(force.forces_IonIon[1][1] == Approx(0.0)); + REQUIRE(force.forces_IonIon[1][2] == Approx(0.0)); // It seems a bit silly to test the makeClone method // but this class does not use the compiler's copy constructor and From af1bb56cd7689ab0050ae4dec8ec9ee71c09e6aa Mon Sep 17 00:00:00 2001 From: Juha Tiihonen Date: Tue, 22 Oct 2019 17:39:17 -0400 Subject: [PATCH 41/41] Fix CoulombPBCAA IonIon forces and add unit test --- src/QMCHamiltonians/CoulombPBCAA.cpp | 7 +++---- src/QMCHamiltonians/tests/test_force.cpp | 6 ++++++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/QMCHamiltonians/CoulombPBCAA.cpp b/src/QMCHamiltonians/CoulombPBCAA.cpp index 54588bdcb..c663c223a 100644 --- a/src/QMCHamiltonians/CoulombPBCAA.cpp +++ b/src/QMCHamiltonians/CoulombPBCAA.cpp @@ -355,10 +355,9 @@ CoulombPBCAA::Return_t CoulombPBCAA::evalSRwithForces(ParticleSet& P) RealType rinv = 1.0 / dist[j]; rV = rVsforce->splint(dist[j], d_rV_dr, d2_rV_dr2); V = rV * rinv; - //esum += Zat[j] * V; esum += Zat[j] * rVs->splint(dist[j]) * rinv; - PosType grad = Zat[j] * Zat[ipart] * (d_rV_dr - V) * rinv * rinv * dr[j]; + PosType grad = Zat[j] * Zat[ipart] * (d_rV_dr - V) * rinv * rinv * d_aa.Displacements[ipart][j]; forces[ipart] += grad; forces[j] -= grad; } @@ -375,10 +374,10 @@ CoulombPBCAA::Return_t CoulombPBCAA::evalSRwithForces(ParticleSet& P) RealType rinv = 1.0 / dist[j]; rV = rVsforce->splint(dist[j], d_rV_dr, d2_rV_dr2); V = rV * rinv; - //esum += Zat[j] * V; esum += Zat[j] * rVs->splint(dist[j]) * rinv; - PosType grad = Zat[j] * Zat[NumCenters - ipart] * (d_rV_dr - V) * rinv * rinv * dr[j]; + PosType grad = Zat[j] * Zat[NumCenters - ipart] * (d_rV_dr - V) + * rinv * rinv * d_aa.Displacements[NumCenters-ipart][j]; forces[NumCenters - ipart] += grad; forces[j] -= grad; } diff --git a/src/QMCHamiltonians/tests/test_force.cpp b/src/QMCHamiltonians/tests/test_force.cpp index 896e3d6b0..bcf13fc32 100644 --- a/src/QMCHamiltonians/tests/test_force.cpp +++ b/src/QMCHamiltonians/tests/test_force.cpp @@ -24,6 +24,7 @@ #include "QMCHamiltonians/ForceChiesaPBCAA.h" #include "QMCHamiltonians/ForceCeperley.h" #include "QMCHamiltonians/CoulombPotential.h" +#include "QMCHamiltonians/CoulombPBCAA.h" #include "QMCWaveFunctions/TrialWaveFunction.h" @@ -240,6 +241,11 @@ TEST_CASE("Chiesa Force", "[hamiltonian]") REQUIRE(force.forces_IonIon[1][1] == Approx(0.0)); REQUIRE(force.forces_IonIon[1][2] == Approx(0.0)); + // Let's test CoulombPBCAA IonIon forces, too + CoulombPBCAA ionForce(ions, false, true); + REQUIRE(ionForce.forces[0][0] == Approx(-0.1478626893)); + REQUIRE(ionForce.forces[1][0] == Approx(0.1478626893)); + // It seems a bit silly to test the makeClone method // but this class does not use the compiler's copy constructor and // there was a bug where the addionion member did not get