Merge branch 'develop' into deterministic_test

This commit is contained in:
Paul R. C. Kent 2019-10-23 09:46:17 -04:00 committed by GitHub
commit 4051fdc1ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
48 changed files with 1913 additions and 3781 deletions

View File

@ -177,7 +177,7 @@ calculation and will generate the HDF5 similarly to the nonperiodic
PySCF calculation in Section~\ref{sec:convert4qmc} (convert4qmc). The PySCF calculation in Section~\ref{sec:convert4qmc} (convert4qmc). The
function is distributed with QMCPACK and is located in the function is distributed with QMCPACK and is located in the
qmcpack/src/QMCTools directory under the name 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 For the converter in the script to be called properly, you need
to specify the path to the file in your PYTHONPATH such as 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. modification.
Running convert4qmc will generate 3 input files:\\ 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.]
<?xml version="1.0"?> <?xml version="1.0"?>
<qmcsystem> <qmcsystem>
<simulationcell> <simulationcell>
@ -315,7 +315,7 @@ Running convert4qmc will generate 3 input files:\\
\end{lstlisting} \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. 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.]
<?xml version="1.0"?> <?xml version="1.0"?>
<qmcsystem> <qmcsystem>
<wavefunction name="psi0" target="e"> <wavefunction name="psi0" target="e">

View File

@ -14,7 +14,7 @@ Table~\ref{table:singledet}.
\multicolumn{2}{l}{Child elements:} & \multicolumn{4}{l}{\texttt{determinant}}\\ \multicolumn{2}{l}{Child elements:} & \multicolumn{4}{l}{\texttt{determinant}}\\
\multicolumn{2}{l}{Attribute:} & \multicolumn{4}{l}{}\\ \multicolumn{2}{l}{Attribute:} & \multicolumn{4}{l}{}\\
& \bfseries Name & \bfseries Datatype & \bfseries Values & \bfseries Default & \bfseries Description \\ & \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. \\ & \texttt{optimize} & Text & yes/no & yes & Enable orbital optimization. \\
\hline \hline
\end{tabularx} \end{tabularx}
@ -39,7 +39,8 @@ Table~\ref{table:singledet}.
Additional information: Additional information:
\begin{itemize} \begin{itemize}
\item \ixml{delay\_rank}. This option enables delayed updates of the Slater matrix inverse when particle-by-particle move is used. \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. 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). 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. We have seen up to an order of magnitude speedup on large problem sizes.

View File

@ -1847,6 +1847,10 @@ class DatAnalyzer(QBase):
v = data.LocalEnergy - data.ElecElec + data.MPC + data.KEcorr v = data.LocalEnergy - data.ElecElec + data.MPC + data.KEcorr
data.CorrectedEnergy = v data.CorrectedEnergy = v
stats.CorrectedEnergy = self.stat_value(v[nbe:]) 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 #end if
if len(data)>0: if len(data)>0:
example = data.first() example = data.first()

View File

@ -2082,7 +2082,7 @@ class hamiltonian(QIxml):
class coulomb(QIxml): class coulomb(QIxml):
tag = 'pairpot' tag = 'pairpot'
attributes = ['type','name','source','target','physical'] attributes = ['type','name','source','target','physical','forces']
write_types = obj(physical=yesno) write_types = obj(physical=yesno)
identifier = 'name' identifier = 'name'
#end class coulomb #end class coulomb

View File

@ -148,10 +148,10 @@ LRCoulombSingleton::LRHandlerType* LRCoulombSingleton::getDerivHandler(ParticleS
//APP_ABORT("SR Coulomb Basis Handler has cloning issues. Stress also has some kinks"); //APP_ABORT("SR Coulomb Basis Handler has cloning issues. Stress also has some kinks");
if (CoulombDerivHandler == 0) if (CoulombDerivHandler == 0)
{ {
app_log() << "\n Creating CoulombHandler with the optimal breakup of SR piece. " << std::endl; //app_log() << "\n Creating CoulombHandler with the optimal breakup of SR piece. " << std::endl;
CoulombDerivHandler = new LRHandlerSRCoulomb<CoulombFunctor<mRealType>, LPQHISRCoulombBasis>(ref); //CoulombDerivHandler = new LRHandlerSRCoulomb<CoulombFunctor<mRealType>, LPQHISRCoulombBasis>(ref);
//app_log() << "\n Creating CoulombDerivHandler with the Ewald3D breakup. " << std::endl; app_log() << "\n Creating CoulombDerivHandler with the Ewald3D breakup. " << std::endl;
//CoulombDerivHandler= new EwaldHandler3D(ref); CoulombDerivHandler= new EwaldHandler3D(ref);
// CoulombDerivHandler = new LRDerivHandler<CoulombFunctor<mRealType>, LPQHIBasis> (ref); // CoulombDerivHandler = new LRDerivHandler<CoulombFunctor<mRealType>, LPQHIBasis> (ref);
//CoulombDerivHandler= new EwaldHandler(ref); //CoulombDerivHandler= new EwaldHandler(ref);
CoulombDerivHandler->initBreakup(ref); CoulombDerivHandler->initBreakup(ref);

View File

@ -120,8 +120,9 @@ bool BranchIO::write(const std::string& fname)
// Put log filename in property tree // Put log filename in property tree
pt.put("state.branchmode", ref.BranchMode); pt.put("state.branchmode", ref.BranchMode);
for (int i = 0; i < vParamName.size(); ++i) auto it_vparam = ref.vParam.begin();
pt.put("state.vparam." + vParamName[i], ref.vParam[i]); for (auto& name : vParamName)
pt.put("state.vparam." + name, *(it_vparam++));
for (int i = 0; i < iParamName.size(); ++i) for (int i = 0; i < iParamName.size(); ++i)
pt.put("state.iparam." + iParamName[i], ref.iParam[i]); pt.put("state.iparam." + iParamName[i], ref.iParam[i]);
@ -166,7 +167,6 @@ bool BranchIO::read(const std::string& fname)
{ {
int found_config = 0; int found_config = 0;
#if defined(HAVE_LIBBOOST)
if (myComm->rank() == 0) if (myComm->rank() == 0)
{ {
initAttributes(); initAttributes();
@ -188,59 +188,14 @@ bool BranchIO::read(const std::string& fname)
{ {
ref.iParam[i++] = v.second.get_value<int>(); ref.iParam[i++] = v.second.get_value<int>();
} }
i = 0; auto it_vparam = ref.vParam.begin();
BOOST_FOREACH (const ptree::value_type& v, pt.get_child("state.vparam")) BOOST_FOREACH (const ptree::value_type& v, pt.get_child("state.vparam"))
{ {
ref.vParam[i++] = v.second.get_value<double>(); *(it_vparam++) = v.second.get_value<double>();
} }
found_config = 1; 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); myComm->bcast(found_config);
if (!found_config) if (!found_config)
@ -278,8 +233,8 @@ void BranchIO::bcast_state()
if (myComm->rank()) if (myComm->rank())
{ {
int ii = 0; int ii = 0;
for (int i = 0; i < ref.vParam.size(); ++i, ++ii) for (auto& vpar : ref.vParam)
ref.vParam[i] = pdata[ii]; vpar = pdata[ii++];
for (int i = 0; i < ref.iParam.size(); ++i, ++ii) for (int i = 0; i < ref.iParam.size(); ++i, ++ii)
ref.iParam[i] = static_cast<int>(pdata[ii]); ref.iParam[i] = static_cast<int>(pdata[ii]);
ref.BranchMode = static_cast<unsigned long>(pdata[ii]); ref.BranchMode = static_cast<unsigned long>(pdata[ii]);

View File

@ -21,10 +21,11 @@ namespace qmcplusplus
{ {
struct BranchIO struct BranchIO
{ {
typedef SimpleFixedNodeBranch::RealType RealType; using SFNB = SimpleFixedNodeBranch;
typedef SimpleFixedNodeBranch::BranchModeType BranchModeType; using RealType = SFNB::RealType;
typedef SimpleFixedNodeBranch::IParamType IParamType; using BranchModeType = SFNB::BranchModeType;
typedef SimpleFixedNodeBranch::VParamType VParamType; using IParamType = SFNB::IParamType;
using VParamType = SFNB::VParamType;
SimpleFixedNodeBranch& ref; SimpleFixedNodeBranch& ref;
Communicate* myComm; Communicate* myComm;
@ -34,6 +35,7 @@ struct BranchIO
bool read(const std::string& fname); bool read(const std::string& fname);
void bcast_state(); void bcast_state();
// TODO: names should be defined with the enum in SimpleFixedNodeBranch.h
static std::vector<std::string> vParamName; static std::vector<std::string> vParamName;
static std::vector<std::string> iParamName; static std::vector<std::string> iParamName;

View File

@ -12,6 +12,7 @@
#include <functional> #include <functional>
#include "QMCDrivers/DMC/DMCBatched.h" #include "QMCDrivers/DMC/DMCBatched.h"
#include "QMCDrivers/GreenFunctionModifiers/DriftModifierBase.h"
#include "Concurrency/TasksOneToOne.hpp" #include "Concurrency/TasksOneToOne.hpp"
#include "Concurrency/Info.hpp" #include "Concurrency/Info.hpp"
#include "Utilities/RunTimeManager.h" #include "Utilities/RunTimeManager.h"

View File

@ -17,10 +17,12 @@
#include "QMCDrivers/DMC/DMCDriverInput.h" #include "QMCDrivers/DMC/DMCDriverInput.h"
#include "QMCDrivers/MCPopulation.h" #include "QMCDrivers/MCPopulation.h"
#include "QMCDrivers/ContextForSteps.h" #include "QMCDrivers/ContextForSteps.h"
#include "QMCDrivers/GreenFunctionModifiers/DriftModifierBase.h"
namespace qmcplusplus namespace qmcplusplus
{ {
class DriverModifierBase;
/** @ingroup QMCDrivers ParticleByParticle /** @ingroup QMCDrivers ParticleByParticle
* @brief Implements a DMC using particle-by-particle move. Threaded execution. * @brief Implements a DMC using particle-by-particle move. Threaded execution.
*/ */

View File

@ -22,7 +22,7 @@ MCPopulation::MCPopulation(int num_ranks,
ParticleSet* elecs, ParticleSet* elecs,
TrialWaveFunction* trial_wf, TrialWaveFunction* trial_wf,
QMCHamiltonian* hamiltonian, 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) : num_ranks_(num_ranks), trial_wf_(trial_wf), elec_particle_set_(elecs), hamiltonian_(hamiltonian), rank_(this_rank)
{ {
walker_offsets_ = mcwc.WalkerOffsets; walker_offsets_ = mcwc.WalkerOffsets;
@ -54,15 +54,12 @@ MCPopulation::MCPopulation(int num_ranks,
/** Default creates walkers equal to num_local_walkers_ and zeroed positions /** Default creates walkers equal to num_local_walkers_ and zeroed positions
*/ */
void MCPopulation::createWalkers() void MCPopulation::createWalkers() { createWalkers(num_local_walkers_); }
{
createWalkers(num_local_walkers_);
}
void MCPopulation::createWalkerInplace(UPtr<MCPWalker>& walker_ptr) void MCPopulation::createWalkerInplace(UPtr<MCPWalker>& walker_ptr)
{ {
//SO this would be where the walker reuse hack would go //SO this would be where the walker reuse hack would go
walker_ptr = std::make_unique<MCPWalker>(num_particles_); walker_ptr = std::make_unique<MCPWalker>(num_particles_);
walker_ptr->R = elec_particle_set_->R; walker_ptr->R = elec_particle_set_->R;
walker_ptr->registerData(); walker_ptr->registerData();
walker_ptr->Properties = elec_particle_set_->Properties; walker_ptr->Properties = elec_particle_set_->Properties;
@ -97,9 +94,9 @@ void MCPopulation::createWalkers(IndexType num_walkers)
} }
int num_walkers_created = 0; 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. // 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 // 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; walker_ptr->ParentID = walker_ptr->ID;
} }
} }
outputManager.pause(); outputManager.pause();
// Sadly the wfc makeClone interface depends on the full particle set as a way to not to keep track // 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()) while (it_wtw != walker_trial_wavefunctions_.end())
{ {
it_wtw->reset(trial_wf_->makeClone(**it_weps)); 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_weps;
++it_wtw; ++it_wtw;
++it_ham; ++it_ham;
@ -137,25 +134,15 @@ void MCPopulation::createWalkers(IndexType num_walkers)
RefVector<WFBuffer> mcp_wfbuffers; RefVector<WFBuffer> mcp_wfbuffers;
mcp_wfbuffers.reserve(num_walkers); mcp_wfbuffers.reserve(num_walkers);
std::for_each(walkers_.begin(), std::for_each(walkers_.begin(), walkers_.end(),
walkers_.end(), [&mcp_wfbuffers](auto& walker) { mcp_wfbuffers.push_back((*walker).DataSet); });
[&mcp_wfbuffers](auto& walker) {
mcp_wfbuffers.push_back((*walker).DataSet);
});
TrialWaveFunction::flex_registerData(walker_trial_wavefunctions_, TrialWaveFunction::flex_registerData(walker_trial_wavefunctions_, walker_elec_particle_sets_, mcp_wfbuffers);
walker_elec_particle_sets_,
mcp_wfbuffers);
std::for_each(walkers_.begin(), std::for_each(walkers_.begin(), walkers_.end(), [](auto& walker) { (*walker).DataSet.allocate(); });
walkers_.end(),
[](auto& walker) {
(*walker).DataSet.allocate();
});
} }
/** creates a walker and returns a reference /** creates a walker and returns a reference
* *
* none of the objects are "reused" * none of the objects are "reused"
@ -165,40 +152,41 @@ void MCPopulation::createWalkers(IndexType num_walkers)
MCPopulation::MCPWalker& MCPopulation::spawnWalker() MCPopulation::MCPWalker& MCPopulation::spawnWalker()
{ {
++num_local_walkers_; ++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<MCPWalker>(num_particles_));
outputManager.pause(); outputManager.pause();
if (dead_walkers_.size() > 0)
walkers_.back()->R = elec_particle_set_->R; {
walkers_.back()->registerData(); walkers_.push_back(std::move(dead_walkers_.back()));
walkers_.back()->Properties = elec_particle_set_->Properties; dead_walkers_.pop_back();
}
else
{
walkers_.push_back(std::make_unique<MCPWalker>(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<ParticleSet>(*elec_particle_set_)); walker_elec_particle_sets_.push_back(std::make_unique<ParticleSet>(*elec_particle_set_));
walker_trial_wavefunctions_.push_back(UPtr<TrialWaveFunction>{}); walker_trial_wavefunctions_.push_back(UPtr<TrialWaveFunction>{});
walker_trial_wavefunctions_.back().reset(trial_wf_->makeClone(*(walker_elec_particle_sets_.back()))); walker_trial_wavefunctions_.back().reset(trial_wf_->makeClone(*(walker_elec_particle_sets_.back())));
walker_hamiltonians_.push_back(UPtr<QMCHamiltonian>{}); walker_hamiltonians_.push_back(UPtr<QMCHamiltonian>{});
walker_hamiltonians_.back().reset(hamiltonian_->makeClone(*(walker_elec_particle_sets_.back()), walker_hamiltonians_.back().reset(
*(walker_trial_wavefunctions_.back()))); hamiltonian_->makeClone(*(walker_elec_particle_sets_.back()), *(walker_trial_wavefunctions_.back())));
outputManager.resume(); 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()); 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 /** Kill a walker
*/ */
void MCPopulation::killWalker(MCPWalker& walker) void MCPopulation::killWalker(MCPWalker& walker)
@ -206,31 +194,42 @@ void MCPopulation::killWalker(MCPWalker& walker)
--num_local_walkers_; --num_local_walkers_;
// find the walker and null its pointer in the walker vector // find the walker and null its pointer in the walker vector
auto it_walkers = walkers_.begin(); 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()) while (it_walkers != walkers_.end())
{ {
if (&walker == (*it_walkers).get()) 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; return;
} }
++it_walkers;
++it_psets;
++it_twfs;
++it_hams;
} }
throw std::runtime_error("Attempt to kill nonexistent walker in MCPopulation!"); throw std::runtime_error("Attempt to kill nonexistent walker in MCPopulation!");
} }
QMCTraits::IndexType MCPopulation::update_num_global_walkers(Communicate* comm) QMCTraits::IndexType MCPopulation::update_num_global_walkers(Communicate* comm)
{ {
int ncontexts = comm->size(); int ncontexts = comm->size();
std::vector<int> nw(ncontexts, 0); std::vector<int> nw(ncontexts, 0);
std::vector<int> nwoff(ncontexts + 1, 0); std::vector<int> nwoff(ncontexts + 1, 0);
nw[comm->rank()] = num_local_walkers_; nw[comm->rank()] = num_local_walkers_;
comm->allreduce(nw); comm->allreduce(nw);
for (int ip = 0; ip < ncontexts; ++ip) for (int ip = 0; ip < ncontexts; ++ip)
nwoff[ip + 1] = nwoff[ip] + nw[ip]; nwoff[ip + 1] = nwoff[ip] + nw[ip];
num_global_walkers_ = nwoff[ncontexts]; num_global_walkers_ = nwoff[ncontexts];
walker_offsets_ = nwoff; walker_offsets_ = nwoff;
return num_global_walkers_; return num_global_walkers_;
} }

View File

@ -53,7 +53,8 @@ private:
ParticleSet ions_; ParticleSet ions_;
std::vector<IndexType> walker_offsets_; std::vector<IndexType> walker_offsets_;
// By making this a linked list and creating the crowds at the same time we could get first touch. // By making this a linked list and creating the crowds at the same time we could get first touch.
std::vector<std::unique_ptr<MCPWalker>> walkers_; UPtrVector<MCPWalker> walkers_;
UPtrVector<MCPWalker> dead_walkers_;
std::vector<std::pair<int, int>> particle_group_indexes_; std::vector<std::pair<int, int>> particle_group_indexes_;
SpeciesSet species_set_; SpeciesSet species_set_;
std::vector<RealType> ptclgrp_mass_; std::vector<RealType> ptclgrp_mass_;
@ -118,6 +119,7 @@ public:
*/ */
MCPWalker& spawnWalker(); MCPWalker& spawnWalker();
void killWalker(MCPWalker&); void killWalker(MCPWalker&);
void killLastWalker();
void createWalkerInplace(UPtr<MCPWalker>& walker_ptr); void createWalkerInplace(UPtr<MCPWalker>& walker_ptr);
void allocateWalkerStuffInplace(int walker_index); 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 * is invalid. Ideally MCPopulation not process any calls in this state, next best would be to only
* process calls to become valid. * 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_; } int get_num_ranks() const { return num_ranks_; }
IndexType get_num_global_walkers() const { return num_global_walkers_; } IndexType get_num_global_walkers() const { return num_global_walkers_; }
IndexType update_num_global_walkers(Communicate* comm); IndexType update_num_global_walkers(Communicate* comm);
@ -198,6 +200,7 @@ public:
} }
UPtrVector<MCPWalker>& get_walkers() { return walkers_; } UPtrVector<MCPWalker>& get_walkers() { return walkers_; }
UPtrVector<QMCHamiltonian>& get_hamiltonians() { return walker_hamiltonians_; }
const std::vector<std::pair<int, int>>& get_particle_group_indexes() const { return particle_group_indexes_; } const std::vector<std::pair<int, int>>& get_particle_group_indexes() const { return particle_group_indexes_; }
const std::vector<RealType>& get_ptclgrp_mass() const { return ptclgrp_mass_; } const std::vector<RealType>& get_ptclgrp_mass() const { return ptclgrp_mass_; }
const std::vector<RealType>& get_ptclgrp_inv_mass() const { return ptclgrp_inv_mass_; } const std::vector<RealType>& get_ptclgrp_inv_mass() const { return ptclgrp_inv_mass_; }

View File

@ -149,6 +149,9 @@ void QMCDriverNew::process(xmlNodePtr cur)
if (!drift_modifier_) if (!drift_modifier_)
drift_modifier_.reset(createDriftModifier(qmcdriver_input_)); 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); branch_engine_->put(cur);
estimator_manager_->put(H, 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()); IndexType local_walkers = calc_default_local_walkers(qmcdriver_input_.get_walkers_per_rank());
// side effect updates walkers_per_crowd_; // side effect updates walkers_per_crowd_;
addWalkers(local_walkers, ParticleAttrib<TinyVector<QMCTraits::RealType, 3>>(population_.get_num_particles())); makeLocalWalkers(local_walkers, ParticleAttrib<TinyVector<QMCTraits::RealType, 3>>(population_.get_num_particles()));
} }
/** Add walkers to the end of the ensemble of walkers. void QMCDriverNew::makeLocalWalkers(int nwalkers, const ParticleAttrib<TinyVector<QMCTraits::RealType, 3>>& positions)
* @param nwalkers number of walkers to add
*
*/
void QMCDriverNew::addWalkers(int nwalkers, const ParticleAttrib<TinyVector<QMCTraits::RealType, 3>>& positions)
{ {
setNonLocalMoveHandler_(population_.get_golden_hamiltonian()); if (population_.get_walkers().size() == 0)
population_.createWalkers(nwalkers); {
// else if (nwalkers < 0) population_.createWalkers(nwalkers);
// { }
// W.destroyWalkers(-nwalkers); else if(population_.get_walkers().size() < nwalkers)
// app_log() << " Removed " << -nwalkers << " walkers. Current number of walkers =" << W.getActiveWalkers() {
// << std::endl; IndexType num_additional_walkers = nwalkers - population_.get_walkers().size();
// } for(int i = 0; i < num_additional_walkers; ++i)
// else population_.spawnWalker();
// { }
// app_log() << " Using the current " << W.getActiveWalkers() << " walkers." << std::endl; 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<QMCHamiltonian>& ham : population_.get_hamiltonians())
setNonLocalMoveHandler_(*ham);
// setWalkerOffsets(); // setWalkerOffsets();
// ////update the global number of walkers // ////update the global number of walkers
// ////int nw=W.getActiveWalkers(); // ////int nw=W.getActiveWalkers();

View File

@ -167,7 +167,7 @@ public:
std::string getEngineName() { return QMCType; } std::string getEngineName() { return QMCType; }
unsigned long getDriverMode() { return qmc_driver_mode_.to_ulong(); } unsigned long getDriverMode() { return qmc_driver_mode_.to_ulong(); }
IndexType get_walkers_per_crowd() const { return walkers_per_crowd_; } 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 /** @ingroup Legacy interface to be dropped
* @{ * @{
@ -183,7 +183,7 @@ public:
static void initialLogEvaluation(int crowd_id, UPtrVector<Crowd>& crowds, UPtrVector<ContextForSteps>& step_context); static void initialLogEvaluation(int crowd_id, UPtrVector<Crowd>& crowds, UPtrVector<ContextForSteps>& step_context);
/** should be set in input don't see a reason to set individually /** should be set in input don't see a reason to set individually
* @param pbyp if true, use particle-by-particle update * @param pbyp if true, use particle-by-particle update
*/ */
@ -349,12 +349,17 @@ public:
bool putQMCInfo(xmlNodePtr cur); bool putQMCInfo(xmlNodePtr cur);
void addWalkers(int nwalkers, const ParticleAttrib<TinyVector<QMCTraits::RealType, 3>>& positions); /** Adjust populations local walkers to this number
* @param nwalkers number of walkers to add
*
*/
void makeLocalWalkers(int nwalkers, const ParticleAttrib<TinyVector<QMCTraits::RealType, 3>>& positions);
int get_num_crowds() { return num_crowds_; } int get_num_crowds() { return num_crowds_; }
void set_num_crowds(int num_crowds, const std::string& reason); void set_num_crowds(int num_crowds, const std::string& reason);
void set_walkers_per_rank(int walkers_per_rank, 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_; } DriftModifierBase& get_drift_modifier() const { return *drift_modifier_; }
/** record the state of the block /** record the state of the block
* @param block current block * @param block current block
* *

View File

@ -38,17 +38,18 @@ enum
}; };
SimpleFixedNodeBranch::SimpleFixedNodeBranch(RealType tau, int nideal) 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_DMCSTAGE, 0); //warmup stage
BranchMode.set(B_POPCONTROL, 1); //use standard DMC BranchMode.set(B_POPCONTROL, 1); //use standard DMC
BranchMode.set(B_USETAUEFF, 1); //use taueff BranchMode.set(B_USETAUEFF, 1); //use taueff
BranchMode.set(B_CLEARHISTORY, 0); //clear history and start with the current average 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 BranchMode.set(B_KILLNODES, 0); //when killing walkers at nodes etrial is updated differently
vParam[B_TAU] = tau; vParam.fill(1.0);
vParam[B_TAUEFF] = tau; vParam[SBVP::TAU] = tau;
vParam[B_FEEDBACK] = 1.0; vParam[SBVP::TAUEFF] = tau;
vParam[B_FILTERSCALE] = 10; vParam[SBVP::FEEDBACK] = 1.0;
vParam[SBVP::FILTERSCALE] = 10;
R2Accepted(1.0e-10); R2Accepted(1.0e-10);
R2Proposed(1.0e-10); R2Proposed(1.0e-10);
//set the default values for integer parameters //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], "targetwalkers", "int");
m_param.add(iParam[B_TARGETWALKERS], "target_walkers", "int"); m_param.add(iParam[B_TARGETWALKERS], "target_walkers", "int");
//trial energy //trial energy
m_param.add(vParam[B_EREF], "refEnergy", "AU"); m_param.add(vParam[SBVP::EREF], "refEnergy", "AU");
m_param.add(vParam[B_EREF], "ref_energy", "AU"); m_param.add(vParam[SBVP::EREF], "ref_energy", "AU");
m_param.add(vParam[B_EREF], "en_ref", "AU"); m_param.add(vParam[SBVP::EREF], "en_ref", "AU");
m_param.add(vParam[B_TAU], "tau", "AU"); m_param.add(vParam[SBVP::TAU], "tau", "AU");
m_param.add(vParam[B_TAU], "timestep", "AU"); m_param.add(vParam[SBVP::TAU], "timestep", "AU");
m_param.add(vParam[B_TAU], "timeStep", "AU"); m_param.add(vParam[SBVP::TAU], "timeStep", "AU");
m_param.add(vParam[B_TAU], "TimeStep", "AU"); m_param.add(vParam[SBVP::TAU], "TimeStep", "AU");
//filterscale: sets the filtercutoff to sigma*filterscale //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 //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 //turn on/off effective tau onl for time-step error comparisons
m_param.add(sParam[USETAUOPT], "useBareTau", "option"); m_param.add(sParam[USETAUOPT], "useBareTau", "option");
m_param.add(sParam[MIXDMCOPT], "warmupByReconfiguration", "opt"); 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 BranchMode.set(B_DMCSTAGE, iParam[B_WARMUPSTEPS] == 0); //use warmup
//this is not necessary //this is not necessary
//check if tau is different and set the initial values //check if tau is different and set the initial values
//vParam[B_TAU]=tau; //vParam[SBVP::TAU]=tau;
bool fromscratch = false; bool fromscratch = false;
FullPrecRealType tau = vParam[B_TAU]; FullPrecRealType tau = vParam[SBVP::TAU];
int nwtot_now = walkers.getGlobalNumWalkers(); int nwtot_now = walkers.getGlobalNumWalkers();
@ -150,7 +151,7 @@ int SimpleFixedNodeBranch::initWalkerController(MCWalkerConfiguration& walkers,
{ {
fromscratch = true; fromscratch = true;
app_log() << " START ALL OVER " << std::endl; 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_POPCONTROL, !fixW); //fixW -> 0
BranchMode.set(B_KILLNODES, killwalker); BranchMode.set(B_KILLNODES, killwalker);
iParam[B_MAXWALKERS] = WalkerController->get_n_max(); iParam[B_MAXWALKERS] = WalkerController->get_n_max();
@ -176,28 +177,28 @@ int SimpleFixedNodeBranch::initWalkerController(MCWalkerConfiguration& walkers,
//update the simulation parameters //update the simulation parameters
WalkerController->put(myNode); WalkerController->put(myNode);
//assign current Eref and a large number for variance //assign current Eref and a large number for variance
WalkerController->setTrialEnergy(vParam[B_ETRIAL]); WalkerController->setTrialEnergy(vParam[SBVP::ETRIAL]);
this->reset(); this->reset();
if (fromscratch) if (fromscratch)
{ {
//determine the branch cutoff to limit wild weights based on the sigma and sigmaBound //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()); setBranchCutoff(vParam[SBVP::SIGMA2], WalkerController->get_target_sigma(), 50, walkers.R.size());
vParam[B_TAUEFF] = tau * R2Accepted.result() / R2Proposed.result(); vParam[SBVP::TAUEFF] = tau * R2Accepted.result() / R2Proposed.result();
} }
//reset controller //reset controller
WalkerController->reset(); WalkerController->reset();
if (BackupWalkerController) if (BackupWalkerController)
BackupWalkerController->reset(); BackupWalkerController->reset();
app_log() << " QMC counter = " << iParam[B_COUNTER] << std::endl; app_log() << " QMC counter = " << iParam[B_COUNTER] << std::endl;
app_log() << " time step = " << vParam[B_TAU] << std::endl; app_log() << " time step = " << vParam[SBVP::TAU] << std::endl;
app_log() << " effective time step = " << vParam[B_TAUEFF] << std::endl; app_log() << " effective time step = " << vParam[SBVP::TAUEFF] << std::endl;
app_log() << " trial energy = " << vParam[B_ETRIAL] << std::endl; app_log() << " trial energy = " << vParam[SBVP::ETRIAL] << std::endl;
app_log() << " reference energy = " << vParam[B_EREF] << std::endl; app_log() << " reference energy = " << vParam[SBVP::EREF] << std::endl;
app_log() << " Feedback = " << vParam[B_FEEDBACK] << std::endl; app_log() << " Feedback = " << vParam[SBVP::FEEDBACK] << std::endl;
app_log() << " reference variance = " << vParam[B_SIGMA2] << std::endl; app_log() << " reference variance = " << vParam[SBVP::SIGMA2] << std::endl;
app_log() << " target walkers = " << iParam[B_TARGETWALKERS] << std::endl; app_log() << " target walkers = " << iParam[B_TARGETWALKERS] << std::endl;
app_log() << " branching cutoff scheme " << branching_cutoff_scheme << 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] app_log() << " Max and minimum walkers per node= " << iParam[B_MAXWALKERS] << " " << iParam[B_MINWALKERS]
<< std::endl; << std::endl;
app_log() << " QMC Status (BranchMode) = " << BranchMode << 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 BranchMode.set(B_DMCSTAGE, iParam[B_WARMUPSTEPS] == 0); //use warmup
//this is not necessary //this is not necessary
//check if tau is different and set the initial values //check if tau is different and set the initial values
//vParam[B_TAU]=tau; //vParam[SBVP::TAU]=tau;
bool fromscratch = false; bool fromscratch = false;
FullPrecRealType tau = vParam[B_TAU]; FullPrecRealType tau = vParam[SBVP::TAU];
int nwtot_now = population.get_num_global_walkers(); int nwtot_now = population.get_num_global_walkers();
if (WalkerController != nullptr) if (WalkerController != nullptr)
throw std::runtime_error( throw std::runtime_error(
"Unified Driver initWalkerController called with existing WalkerController,\n this is a violation of the assumed " "Unified Driver initWalkerController called with existing WalkerController\n"
"state module for SimpleFixedNodeBranch in the Unified Driver design"); "this is a violation SimpleFixedNodeBranch is created to a valid state only\n"
"once in the Unified Driver design.");
if (iParam[B_TARGETWALKERS] == 0) if (iParam[B_TARGETWALKERS] == 0)
{ {
// has "important" side effect of updating the walker offsets // has "important" side effect of updating the walker offsets
@ -231,7 +233,7 @@ int SimpleFixedNodeBranch::initWalkerController(MCPopulation& population, bool f
{ {
fromscratch = true; fromscratch = true;
app_log() << " START ALL OVER " << std::endl; 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_POPCONTROL, !fixW); //fixW -> 0
BranchMode.set(B_KILLNODES, killwalker); BranchMode.set(B_KILLNODES, killwalker);
iParam[B_MAXWALKERS] = WalkerController->get_n_max(); iParam[B_MAXWALKERS] = WalkerController->get_n_max();
@ -261,30 +263,30 @@ int SimpleFixedNodeBranch::initWalkerController(MCPopulation& population, bool f
//update the simulation parameters //update the simulation parameters
WalkerController->put(myNode); WalkerController->put(myNode);
//assign current Eref and a large number for variance //assign current Eref and a large number for variance
WalkerController->setTrialEnergy(vParam[B_ETRIAL]); WalkerController->setTrialEnergy(vParam[SBVP::ETRIAL]);
this->reset(); this->reset();
if (fromscratch) if (fromscratch)
{ {
//determine the branch cutoff to limit wild weights based on the sigma and sigmaBound //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 // 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? // 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()); setBranchCutoff(vParam[SBVP::SIGMA2], WalkerController->get_target_sigma(), 50, population.get_num_particles());
vParam[B_TAUEFF] = tau * R2Accepted.result() / R2Proposed.result(); vParam[SBVP::TAUEFF] = tau * R2Accepted.result() / R2Proposed.result();
} }
//reset controller //reset controller
WalkerController->reset(); WalkerController->reset();
if (BackupWalkerController) if (BackupWalkerController)
BackupWalkerController->reset(); BackupWalkerController->reset();
app_log() << " QMC counter = " << iParam[B_COUNTER] << std::endl; app_log() << " QMC counter = " << iParam[B_COUNTER] << std::endl;
app_log() << " time step = " << vParam[B_TAU] << std::endl; app_log() << " time step = " << vParam[SBVP::TAU] << std::endl;
app_log() << " effective time step = " << vParam[B_TAUEFF] << std::endl; app_log() << " effective time step = " << vParam[SBVP::TAUEFF] << std::endl;
app_log() << " trial energy = " << vParam[B_ETRIAL] << std::endl; app_log() << " trial energy = " << vParam[SBVP::ETRIAL] << std::endl;
app_log() << " reference energy = " << vParam[B_EREF] << std::endl; app_log() << " reference energy = " << vParam[SBVP::EREF] << std::endl;
app_log() << " Feedback = " << vParam[B_FEEDBACK] << std::endl; app_log() << " Feedback = " << vParam[SBVP::FEEDBACK] << std::endl;
app_log() << " reference variance = " << vParam[B_SIGMA2] << std::endl; app_log() << " reference variance = " << vParam[SBVP::SIGMA2] << std::endl;
app_log() << " target walkers = " << iParam[B_TARGETWALKERS] << std::endl; app_log() << " target walkers = " << iParam[B_TARGETWALKERS] << std::endl;
app_log() << " branching cutoff scheme " << branching_cutoff_scheme << 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] app_log() << " Max and minimum walkers per node= " << iParam[B_MAXWALKERS] << " " << iParam[B_MINWALKERS]
<< std::endl; << std::endl;
app_log() << " QMC Status (BranchMode) = " << BranchMode << 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 BranchMode.set(B_RMCSTAGE, iParam[B_WARMUPSTEPS] == 0); //use warmup
//this is not necessary //this is not necessary
//check if tau is different and set the initial values //check if tau is different and set the initial values
//vParam[B_TAU]=tau; //vParam[SBVP::TAU]=tau;
bool fromscratch = false; bool fromscratch = false;
FullPrecRealType tau = vParam[B_TAU]; FullPrecRealType tau = vParam[SBVP::TAU];
//this is the first time DMC is used //this is the first time DMC is used
if (WalkerController == 0) if (WalkerController == 0)
{ {
@ -322,7 +324,7 @@ void SimpleFixedNodeBranch::initReptile(MCWalkerConfiguration& W)
{ {
fromscratch = true; fromscratch = true;
app_log() << " START ALL OVER " << std::endl; app_log() << " START ALL OVER " << std::endl;
vParam[B_TAUEFF] = tau; vParam[SBVP::TAUEFF] = tau;
//PopHist.clear(); //PopHist.clear();
//PopHist.reserve(std::max(iParam[B_ENERGYUPDATEINTERVAL],5)); //PopHist.reserve(std::max(iParam[B_ENERGYUPDATEINTERVAL],5));
} }
@ -336,18 +338,18 @@ void SimpleFixedNodeBranch::initReptile(MCWalkerConfiguration& W)
if (fromscratch) if (fromscratch)
{ {
//determine the branch cutoff to limit wild weights based on the sigma and sigmaBound //determine the branch cutoff to limit wild weights based on the sigma and sigmaBound
setBranchCutoff(vParam[B_SIGMA2], allowedFlux, 50, W.R.size()); setBranchCutoff(vParam[SBVP::SIGMA2], allowedFlux, 50, W.R.size());
vParam[B_TAUEFF] = tau * R2Accepted.result() / R2Proposed.result(); vParam[SBVP::TAUEFF] = tau * R2Accepted.result() / R2Proposed.result();
} }
//reset controller //reset controller
app_log() << " QMC counter = " << iParam[B_COUNTER] << std::endl; app_log() << " QMC counter = " << iParam[B_COUNTER] << std::endl;
app_log() << " time step = " << vParam[B_TAU] << std::endl; app_log() << " time step = " << vParam[SBVP::TAU] << std::endl;
app_log() << " effective time step = " << vParam[B_TAUEFF] << std::endl; app_log() << " effective time step = " << vParam[SBVP::TAUEFF] << std::endl;
app_log() << " reference energy = " << vParam[B_EREF] << std::endl; app_log() << " reference energy = " << vParam[SBVP::EREF] << std::endl;
app_log() << " Feedback = " << vParam[B_FEEDBACK] << std::endl; app_log() << " Feedback = " << vParam[SBVP::FEEDBACK] << std::endl;
app_log() << " reference variance = " << vParam[B_SIGMA2] << std::endl; app_log() << " reference variance = " << vParam[SBVP::SIGMA2] << std::endl;
app_log() << " branching cutoff scheme " << branching_cutoff_scheme << 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; 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. //population for trial energy modification should not include any released node walkers.
pop_now -= WalkerController->get_ensemble_property().RNSamples; pop_now -= WalkerController->get_ensemble_property().RNSamples;
//current energy //current energy
vParam[B_ENOW] = WalkerController->get_ensemble_property().Energy; vParam[SBVP::ENOW] = WalkerController->get_ensemble_property().Energy;
VarianceHist(WalkerController->get_ensemble_property().Variance); VarianceHist(WalkerController->get_ensemble_property().Variance);
R2Accepted(WalkerController->get_ensemble_property().R2Accepted); R2Accepted(WalkerController->get_ensemble_property().R2Accepted);
R2Proposed(WalkerController->get_ensemble_property().R2Proposed); R2Proposed(WalkerController->get_ensemble_property().R2Proposed);
//PopHist(pop_now); //PopHist(pop_now);
vParam[B_EREF] = EnergyHist.mean(); //current mean vParam[SBVP::EREF] = EnergyHist.mean(); //current mean
if (BranchMode[B_USETAUEFF]) 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]) 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 else
EnergyHist(vParam[B_ENOW]); EnergyHist(vParam[SBVP::ENOW]);
if (BranchMode[B_DMCSTAGE]) // main stage if (BranchMode[B_DMCSTAGE]) // main stage
{ {
if (BranchMode[B_POPCONTROL]) if (BranchMode[B_POPCONTROL])
@ -389,66 +391,66 @@ void SimpleFixedNodeBranch::branch(int iter, MCWalkerConfiguration& walkers)
--ToDoSteps; --ToDoSteps;
else 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; ToDoSteps = iParam[B_ENERGYUPDATEINTERVAL] - 1;
} }
} }
else else
vParam[B_ETRIAL] = vParam[B_EREF]; vParam[SBVP::ETRIAL] = vParam[SBVP::EREF];
} }
else //warmup else //warmup
{ {
if (BranchMode[B_USETAUEFF]) 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]) if (BranchMode[B_POPCONTROL])
{ {
//RealType emix=((iParam[B_WARMUPSTEPS]-ToDoSteps)<100)?(0.25*vParam[B_EREF]+0.75*vParam[B_ENOW]):vParam[B_EREF]; //RealType emix=((iParam[B_WARMUPSTEPS]-ToDoSteps)<100)?(0.25*vParam[SBVP::EREF]+0.75*vParam[SBVP::ENOW]):vParam[SBVP::EREF];
//vParam[B_ETRIAL]=emix+Feedback*(logN-std::log(pop_now)); //vParam[SBVP::ETRIAL]=emix+Feedback*(logN-std::log(pop_now));
//vParam[B_ETRIAL]=vParam[B_EREF]+Feedback*(logN-std::log(pop_now)); //vParam[SBVP::ETRIAL]=vParam[SBVP::EREF]+Feedback*(logN-std::log(pop_now));
if (BranchMode[B_KILLNODES]) if (BranchMode[B_KILLNODES])
vParam[B_ETRIAL] = (0.00 * vParam[B_EREF] + 1.0 * vParam[B_ENOW]) + vParam[SBVP::ETRIAL] = (0.00 * vParam[SBVP::EREF] + 1.0 * vParam[SBVP::ENOW]) +
vParam[B_FEEDBACK] * (logN - std::log(pop_now)) - vParam[SBVP::FEEDBACK] * (logN - std::log(pop_now)) -
std::log(WalkerController->get_ensemble_property().LivingFraction) / vParam[B_TAU]; std::log(WalkerController->get_ensemble_property().LivingFraction) / vParam[SBVP::TAU];
else 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 else
vParam[B_ETRIAL] = vParam[B_EREF]; vParam[SBVP::ETRIAL] = vParam[SBVP::EREF];
--ToDoSteps; --ToDoSteps;
if (ToDoSteps == 0) //warmup is done if (ToDoSteps == 0) //warmup is done
{ {
vParam[B_SIGMA2] = VarianceHist.mean(); vParam[SBVP::SIGMA2] = VarianceHist.mean();
setBranchCutoff(vParam[B_SIGMA2], WalkerController->get_target_sigma(), 10, walkers.R.size()); setBranchCutoff(vParam[SBVP::SIGMA2], WalkerController->get_target_sigma(), 10, walkers.R.size());
app_log() << "\n Warmup is completed after " << iParam[B_WARMUPSTEPS] << std::endl; app_log() << "\n Warmup is completed after " << iParam[B_WARMUPSTEPS] << std::endl;
if (BranchMode[B_USETAUEFF]) 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 else
app_log() << "\n TauEff proposed = " << vParam[B_TAUEFF] * R2Accepted.result() / R2Proposed.result(); app_log() << "\n TauEff proposed = " << vParam[SBVP::TAUEFF] * R2Accepted.result() / R2Proposed.result();
app_log() << "\n Etrial = " << vParam[B_ETRIAL] << std::endl; app_log() << "\n Etrial = " << vParam[SBVP::ETRIAL] << std::endl;
app_log() << " Running average of energy = " << EnergyHist.mean() << std::endl; app_log() << " Running average of energy = " << EnergyHist.mean() << std::endl;
app_log() << " Variance = " << vParam[B_SIGMA2] << std::endl; app_log() << " Variance = " << vParam[SBVP::SIGMA2] << 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;
ToDoSteps = iParam[B_ENERGYUPDATEINTERVAL] - 1; ToDoSteps = iParam[B_ENERGYUPDATEINTERVAL] - 1;
iParam[B_WARMUPSTEPS] = 0; iParam[B_WARMUPSTEPS] = 0;
BranchMode.set(B_DMCSTAGE, 1); //set BranchModex to main stage BranchMode.set(B_DMCSTAGE, 1); //set BranchModex to main stage
//reset the histogram //reset the histogram
EnergyHist.clear(); EnergyHist.clear();
EnergyHist(vParam[B_ENOW]); EnergyHist(vParam[SBVP::ENOW]);
if (sParam[MIXDMCOPT] == "yes") if (sParam[MIXDMCOPT] == "yes")
{ {
app_log() << "Switching to DMC with fluctuating populations" << std::endl; app_log() << "Switching to DMC with fluctuating populations" << std::endl;
BranchMode.set(B_POPCONTROL, 1); //use standard DMC BranchMode.set(B_POPCONTROL, 1); //use standard DMC
WalkerController = std::move(BackupWalkerController); WalkerController = std::move(BackupWalkerController);
BackupWalkerController = 0; BackupWalkerController = 0;
vParam[B_ETRIAL] = vParam[B_EREF]; vParam[SBVP::ETRIAL] = vParam[SBVP::EREF];
app_log() << " Etrial = " << vParam[B_ETRIAL] << std::endl; app_log() << " Etrial = " << vParam[SBVP::ETRIAL] << std::endl;
WalkerController->start(); WalkerController->start();
} }
//This is not necessary //This is not necessary
//EnergyHist(DMCEnergyHist.mean()); //EnergyHist(DMCEnergyHist.mean());
} }
} }
WalkerController->setTrialEnergy(vParam[B_ETRIAL]); WalkerController->setTrialEnergy(vParam[SBVP::ETRIAL]);
//accumulate collectables and energies for scalar.dat //accumulate collectables and energies for scalar.dat
FullPrecRealType wgt_inv = WalkerController->get_num_contexts() / WalkerController->get_ensemble_property().Weight; FullPrecRealType wgt_inv = WalkerController->get_num_contexts() / WalkerController->get_ensemble_property().Weight;
walkers.Collectables *= wgt_inv; walkers.Collectables *= wgt_inv;
@ -462,7 +464,7 @@ void SimpleFixedNodeBranch::branch(int iter, UPtrVector<Crowd>& crowds, MCPopul
RefVector<MCPWalker> walkers(convertUPtrToRefVector(population.get_walkers())); RefVector<MCPWalker> walkers(convertUPtrToRefVector(population.get_walkers()));
FullPrecRealType pop_now; FullPrecRealType pop_now;
if (BranchMode[B_DMCSTAGE] || iter) if (false) //BranchMode[B_DMCSTAGE] || iter)
pop_now = WalkerController->branch(iter, population, 0.1); pop_now = WalkerController->branch(iter, population, 0.1);
else else
pop_now = WalkerController->doNotBranch(iter, population); //do not branch for the first step of a warmup pop_now = WalkerController->doNotBranch(iter, population); //do not branch for the first step of a warmup
@ -470,18 +472,18 @@ void SimpleFixedNodeBranch::branch(int iter, UPtrVector<Crowd>& crowds, MCPopul
MCDataType<FullPrecRealType>& wc_ensemble_prop = WalkerController->get_ensemble_property(); MCDataType<FullPrecRealType>& wc_ensemble_prop = WalkerController->get_ensemble_property();
pop_now -= wc_ensemble_prop.RNSamples; pop_now -= wc_ensemble_prop.RNSamples;
//current energy //current energy
vParam[B_ENOW] = wc_ensemble_prop.Energy; vParam[SBVP::ENOW] = wc_ensemble_prop.Energy;
VarianceHist(wc_ensemble_prop.Variance); VarianceHist(wc_ensemble_prop.Variance);
R2Accepted(wc_ensemble_prop.R2Accepted); R2Accepted(wc_ensemble_prop.R2Accepted);
R2Proposed(wc_ensemble_prop.R2Proposed); R2Proposed(wc_ensemble_prop.R2Proposed);
//PopHist(pop_now); //PopHist(pop_now);
vParam[B_EREF] = EnergyHist.mean(); //current mean vParam[SBVP::EREF] = EnergyHist.mean(); //current mean
if (BranchMode[B_USETAUEFF]) 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]) 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 else
EnergyHist(vParam[B_ENOW]); EnergyHist(vParam[SBVP::ENOW]);
if (BranchMode[B_DMCSTAGE]) // main stage if (BranchMode[B_DMCSTAGE]) // main stage
{ {
if (BranchMode[B_POPCONTROL]) if (BranchMode[B_POPCONTROL])
@ -490,66 +492,66 @@ void SimpleFixedNodeBranch::branch(int iter, UPtrVector<Crowd>& crowds, MCPopul
--ToDoSteps; --ToDoSteps;
else 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; ToDoSteps = iParam[B_ENERGYUPDATEINTERVAL] - 1;
} }
} }
else else
vParam[B_ETRIAL] = vParam[B_EREF]; vParam[SBVP::ETRIAL] = vParam[SBVP::EREF];
} }
else //warmup else //warmup
{ {
if (BranchMode[B_USETAUEFF]) 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]) if (BranchMode[B_POPCONTROL])
{ {
//RealType emix=((iParam[B_WARMUPSTEPS]-ToDoSteps)<100)?(0.25*vParam[B_EREF]+0.75*vParam[B_ENOW]):vParam[B_EREF]; //RealType emix=((iParam[B_WARMUPSTEPS]-ToDoSteps)<100)?(0.25*vParam[SBVP::EREF]+0.75*vParam[SBVP::ENOW]):vParam[SBVP::EREF];
//vParam[B_ETRIAL]=emix+Feedback*(logN-std::log(pop_now)); //vParam[SBVP::ETRIAL]=emix+Feedback*(logN-std::log(pop_now));
//vParam[B_ETRIAL]=vParam[B_EREF]+Feedback*(logN-std::log(pop_now)); //vParam[SBVP::ETRIAL]=vParam[SBVP::EREF]+Feedback*(logN-std::log(pop_now));
if (BranchMode[B_KILLNODES]) if (BranchMode[B_KILLNODES])
vParam[B_ETRIAL] = (0.00 * vParam[B_EREF] + 1.0 * vParam[B_ENOW]) + vParam[SBVP::ETRIAL] = (0.00 * vParam[SBVP::EREF] + 1.0 * vParam[SBVP::ENOW]) +
vParam[B_FEEDBACK] * (logN - std::log(pop_now)) - vParam[SBVP::FEEDBACK] * (logN - std::log(pop_now)) -
std::log(wc_ensemble_prop.LivingFraction) / vParam[B_TAU]; std::log(wc_ensemble_prop.LivingFraction) / vParam[SBVP::TAU];
else 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 else
vParam[B_ETRIAL] = vParam[B_EREF]; vParam[SBVP::ETRIAL] = vParam[SBVP::EREF];
--ToDoSteps; --ToDoSteps;
if (ToDoSteps == 0) //warmup is done if (ToDoSteps == 0) //warmup is done
{ {
vParam[B_SIGMA2] = VarianceHist.mean(); vParam[SBVP::SIGMA2] = VarianceHist.mean();
setBranchCutoff(vParam[B_SIGMA2], WalkerController->get_target_sigma(), 10, population.get_num_particles()); 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; app_log() << "\n Warmup is completed after " << iParam[B_WARMUPSTEPS] << std::endl;
if (BranchMode[B_USETAUEFF]) 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 else
app_log() << "\n TauEff proposed = " << vParam[B_TAUEFF] * R2Accepted.result() / R2Proposed.result(); app_log() << "\n TauEff proposed = " << vParam[SBVP::TAUEFF] * R2Accepted.result() / R2Proposed.result();
app_log() << "\n Etrial = " << vParam[B_ETRIAL] << std::endl; app_log() << "\n Etrial = " << vParam[SBVP::ETRIAL] << std::endl;
app_log() << " Running average of energy = " << EnergyHist.mean() << std::endl; app_log() << " Running average of energy = " << EnergyHist.mean() << std::endl;
app_log() << " Variance = " << vParam[B_SIGMA2] << std::endl; app_log() << " Variance = " << vParam[SBVP::SIGMA2] << 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;
ToDoSteps = iParam[B_ENERGYUPDATEINTERVAL] - 1; ToDoSteps = iParam[B_ENERGYUPDATEINTERVAL] - 1;
iParam[B_WARMUPSTEPS] = 0; iParam[B_WARMUPSTEPS] = 0;
BranchMode.set(B_DMCSTAGE, 1); //set BranchModex to main stage BranchMode.set(B_DMCSTAGE, 1); //set BranchModex to main stage
//reset the histogram //reset the histogram
EnergyHist.clear(); EnergyHist.clear();
EnergyHist(vParam[B_ENOW]); EnergyHist(vParam[SBVP::ENOW]);
if (sParam[MIXDMCOPT] == "yes") if (sParam[MIXDMCOPT] == "yes")
{ {
app_log() << "Switching to DMC with fluctuating populations" << std::endl; app_log() << "Switching to DMC with fluctuating populations" << std::endl;
BranchMode.set(B_POPCONTROL, 1); //use standard DMC BranchMode.set(B_POPCONTROL, 1); //use standard DMC
WalkerController = std::move(BackupWalkerController); WalkerController = std::move(BackupWalkerController);
BackupWalkerController = 0; BackupWalkerController = 0;
vParam[B_ETRIAL] = vParam[B_EREF]; vParam[SBVP::ETRIAL] = vParam[SBVP::EREF];
app_log() << " Etrial = " << vParam[B_ETRIAL] << std::endl; app_log() << " Etrial = " << vParam[SBVP::ETRIAL] << std::endl;
WalkerController->start(); WalkerController->start();
} }
//This is not necessary //This is not necessary
//EnergyHist(DMCEnergyHist.mean()); //EnergyHist(DMCEnergyHist.mean());
} }
} }
WalkerController->setTrialEnergy(vParam[B_ETRIAL]); WalkerController->setTrialEnergy(vParam[SBVP::ETRIAL]);
//accumulate collectables and energies for scalar.dat //accumulate collectables and energies for scalar.dat
FullPrecRealType wgt_inv = WalkerController->get_num_contexts() / wc_ensemble_prop.Weight; FullPrecRealType wgt_inv = WalkerController->get_num_contexts() / wc_ensemble_prop.Weight;
//walkers.Collectables *= wgt_inv; //walkers.Collectables *= wgt_inv;
@ -565,14 +567,14 @@ void SimpleFixedNodeBranch::collect(int iter, MCWalkerConfiguration& W)
//Update the current energy and accumulate. //Update the current energy and accumulate.
MCWalkerConfiguration::Walker_t& head = W.reptile->getHead(); MCWalkerConfiguration::Walker_t& head = W.reptile->getHead();
MCWalkerConfiguration::Walker_t& tail = W.reptile->getTail(); 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()<<"IN SimpleFixedNodeBranch::collect\n";
// app_log()<<"\tvParam[B_ENOW]="<<vParam[B_ENOW]<< std::endl; // app_log()<<"\tvParam[SBVP::ENOW]="<<vParam[SBVP::ENOW]<< std::endl;
EnergyHist(vParam[B_ENOW]); EnergyHist(vParam[SBVP::ENOW]);
vParam[B_EREF] = EnergyHist.mean(); vParam[SBVP::EREF] = EnergyHist.mean();
// app_log()<<"\tvParam[B_EREF]="<<vParam[B_EREF]<< std::endl; // app_log()<<"\tvParam[SBVP::EREF]="<<vParam[SBVP::EREF]<< std::endl;
//Update the energy variance and R2 for effective timestep and filtering. //Update the energy variance and R2 for effective timestep and filtering.
VarianceHist(std::pow(vParam[B_ENOW] - vParam[B_EREF], 2)); VarianceHist(std::pow(vParam[SBVP::ENOW] - vParam[SBVP::EREF], 2));
R2Accepted(head.Properties(R2ACCEPTED)); R2Accepted(head.Properties(R2ACCEPTED));
R2Proposed(head.Properties(R2PROPOSED)); R2Proposed(head.Properties(R2PROPOSED));
// app_log()<<"\thead.Properties(R2ACCEPTED)="<<head.Properties(R2ACCEPTED)<< std::endl; // app_log()<<"\thead.Properties(R2ACCEPTED)="<<head.Properties(R2ACCEPTED)<< std::endl;
@ -589,8 +591,8 @@ void SimpleFixedNodeBranch::collect(int iter, MCWalkerConfiguration& W)
if (BranchMode[B_USETAUEFF]) if (BranchMode[B_USETAUEFF])
{ {
//app_log()<<" BRANCHMODE = "<<BranchMode[B_USETAUEFF]<< std::endl; //app_log()<<" BRANCHMODE = "<<BranchMode[B_USETAUEFF]<< std::endl;
vParam[B_TAUEFF] = vParam[B_TAU] * R2Accepted.result() / R2Proposed.result(); vParam[SBVP::TAUEFF] = vParam[SBVP::TAU] * R2Accepted.result() / R2Proposed.result();
// app_log()<<"\tvParam[B_TAU]="<<vParam[B_TAU]<<" "<<vParam[B_TAUEFF]<< std::endl; // app_log()<<"\tvParam[SBVP::TAU]="<<vParam[SBVP::TAU]<<" "<<vParam[SBVP::TAUEFF]<< std::endl;
} }
/* /*
if(BranchMode[B_RMCSTAGE]) // main stage if(BranchMode[B_RMCSTAGE]) // main stage
@ -601,18 +603,18 @@ void SimpleFixedNodeBranch::collect(int iter, MCWalkerConfiguration& W)
--ToDoSteps; --ToDoSteps;
else 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; ToDoSteps=iParam[B_ENERGYUPDATEINTERVAL]-1;
} }
} }
else else
vParam[B_ETRIAL]=vParam[B_EREF]; vParam[SBVP::ETRIAL]=vParam[SBVP::EREF];
}*/ }*/
//app_log()<<"BranchMode[B_RMCSTAGE]="<<BranchMode[B_RMCSTAGE]<< std::endl; //app_log()<<"BranchMode[B_RMCSTAGE]="<<BranchMode[B_RMCSTAGE]<< std::endl;
if (!BranchMode[B_RMCSTAGE]) //warmup if (!BranchMode[B_RMCSTAGE]) //warmup
{ {
if (BranchMode[B_USETAUEFF]) if (BranchMode[B_USETAUEFF])
vParam[B_TAUEFF] = vParam[B_TAU] * R2Accepted.result() / R2Proposed.result(); vParam[SBVP::TAUEFF] = vParam[SBVP::TAU] * R2Accepted.result() / R2Proposed.result();
// app_log()<<"\t <E^2> = "<<VarianceHist.mean()<< std::endl; // app_log()<<"\t <E^2> = "<<VarianceHist.mean()<< std::endl;
// app_log()<<"\t <E> = "<<EnergyHist.mean()<< std::endl; // app_log()<<"\t <E> = "<<EnergyHist.mean()<< std::endl;
// app_log()<<"\t <E>^2 = "<<std::pow(EnergyHist.mean(),2)<< std::endl; // app_log()<<"\t <E>^2 = "<<std::pow(EnergyHist.mean(),2)<< std::endl;
@ -620,27 +622,27 @@ void SimpleFixedNodeBranch::collect(int iter, MCWalkerConfiguration& W)
// app_log()<<"\t var = "<<VarianceHist.mean()<< std::endl; // app_log()<<"\t var = "<<VarianceHist.mean()<< std::endl;
// app_log()<<"----\n"; // app_log()<<"----\n";
//app_log()<<"ToDoSteps="<<ToDoSteps<< std::endl; //app_log()<<"ToDoSteps="<<ToDoSteps<< std::endl;
vParam[B_ETRIAL] = vParam[B_EREF]; vParam[SBVP::ETRIAL] = vParam[SBVP::EREF];
--ToDoSteps; --ToDoSteps;
if (ToDoSteps == 0) //warmup is done if (ToDoSteps == 0) //warmup is done
{ {
vParam[B_TAUEFF] = vParam[B_TAU] * R2Accepted.result() / R2Proposed.result(); vParam[SBVP::TAUEFF] = vParam[SBVP::TAU] * R2Accepted.result() / R2Proposed.result();
vParam[B_SIGMA2] = VarianceHist.mean(); vParam[SBVP::SIGMA2] = VarianceHist.mean();
setBranchCutoff(vParam[B_SIGMA2], vParam[B_FILTERSCALE], vParam[B_FILTERSCALE], W.R.size()); setBranchCutoff(vParam[SBVP::SIGMA2], vParam[SBVP::FILTERSCALE], vParam[SBVP::FILTERSCALE], W.R.size());
app_log() << "\n Warmup is completed after " << iParam[B_WARMUPSTEPS] << " steps." << std::endl; app_log() << "\n Warmup is completed after " << iParam[B_WARMUPSTEPS] << " steps." << std::endl;
if (BranchMode[B_USETAUEFF]) 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 else
app_log() << "\n TauEff proposed = " << vParam[B_TAUEFF] * R2Accepted.result() / R2Proposed.result(); app_log() << "\n TauEff proposed = " << vParam[SBVP::TAUEFF] * R2Accepted.result() / R2Proposed.result();
app_log() << "\n Running average of energy = " << EnergyHist.mean() << std::endl; app_log() << "\n Running average of energy = " << EnergyHist.mean() << std::endl;
app_log() << "\n Variance = " << vParam[B_SIGMA2] << std::endl; app_log() << "\n Variance = " << vParam[SBVP::SIGMA2] << std::endl;
app_log() << "\nbranch cutoff = " << vParam[B_BRANCHCUTOFF] << " " << vParam[B_BRANCHMAX] << std::endl; app_log() << "\nbranch cutoff = " << vParam[SBVP::BRANCHCUTOFF] << " " << vParam[SBVP::BRANCHMAX] << std::endl;
ToDoSteps = iParam[B_ENERGYUPDATEINTERVAL] - 1; ToDoSteps = iParam[B_ENERGYUPDATEINTERVAL] - 1;
iParam[B_WARMUPSTEPS] = 0; iParam[B_WARMUPSTEPS] = 0;
BranchMode.set(B_RMCSTAGE, 1); //set BranchModex to main stage BranchMode.set(B_RMCSTAGE, 1); //set BranchModex to main stage
//reset the histogram //reset the histogram
EnergyHist.clear(); EnergyHist.clear();
EnergyHist(vParam[B_ENOW]); EnergyHist(vParam[SBVP::ENOW]);
} }
} }
//accumulate collectables and energies for scalar.dat //accumulate collectables and energies for scalar.dat
@ -670,15 +672,15 @@ void SimpleFixedNodeBranch::reset()
{ {
//logN = Feedback*std::log(static_cast<RealType>(iParam[B_TARGETWALKERS])); //logN = Feedback*std::log(static_cast<RealType>(iParam[B_TARGETWALKERS]));
logN = std::log(static_cast<FullPrecRealType>(iParam[B_TARGETWALKERS])); logN = std::log(static_cast<FullPrecRealType>(iParam[B_TARGETWALKERS]));
if (vParam[B_FEEDBACK] == 0.0) if (vParam[SBVP::FEEDBACK] == 0.0)
vParam[B_FEEDBACK] = 1.0; vParam[SBVP::FEEDBACK] = 1.0;
} }
else else
{ {
//may set Eref to a safe value //may set Eref to a safe value
//if(EnergyHistory.count()<5) Eref -= vParam[EnergyWindowIndex]; //if(EnergyHistory.count()<5) Eref -= vParam[EnergyWindowIndex];
vParam[B_ETRIAL] = vParam[B_EREF]; vParam[SBVP::ETRIAL] = vParam[SBVP::EREF];
vParam[B_FEEDBACK] = 0.0; vParam[SBVP::FEEDBACK] = 0.0;
logN = 0.0; logN = 0.0;
} }
// vParam(abranch.vParam) // vParam(abranch.vParam)
@ -779,9 +781,9 @@ int SimpleFixedNodeBranch::resetRun(xmlNodePtr cur)
BranchMode[B_POPCONTROL] = (WalkerController->get_method() == 0); BranchMode[B_POPCONTROL] = (WalkerController->get_method() == 0);
if (BranchMode[B_POPCONTROL]) if (BranchMode[B_POPCONTROL])
{ {
vParam[B_ETRIAL] = vParam[B_EREF]; vParam[SBVP::ETRIAL] = vParam[SBVP::EREF];
if (vParam[B_FEEDBACK] == 0.0) if (vParam[SBVP::FEEDBACK] == 0.0)
vParam[B_FEEDBACK] = 1.0; vParam[SBVP::FEEDBACK] = 1.0;
} }
} }
@ -793,7 +795,7 @@ int SimpleFixedNodeBranch::resetRun(xmlNodePtr cur)
BranchMode[B_DMCSTAGE] = 0; BranchMode[B_DMCSTAGE] = 0;
WalkerController->put(myNode); WalkerController->put(myNode);
ToDoSteps = iParam[B_WARMUPSTEPS] = (iParam[B_WARMUPSTEPS]) ? iParam[B_WARMUPSTEPS] : 10; 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(); WalkerController->reset();
#ifdef QMC_CUDA #ifdef QMC_CUDA
reset(); // needed. Ye reset(); // needed. Ye
@ -824,17 +826,17 @@ void SimpleFixedNodeBranch::checkParameters(MCWalkerConfiguration& w)
{ {
FullPrecRealType e, sigma2; FullPrecRealType e, sigma2;
MyEstimator->getCurrentStatistics(w, e, sigma2); MyEstimator->getCurrentStatistics(w, e, sigma2);
vParam[B_ETRIAL] = vParam[B_EREF] = e; vParam[SBVP::ETRIAL] = vParam[SBVP::EREF] = e;
vParam[B_SIGMA2] = sigma2; vParam[SBVP::SIGMA2] = sigma2;
EnergyHist.clear(); EnergyHist.clear();
VarianceHist.clear(); VarianceHist.clear();
//DMCEnergyHist.clear(); //DMCEnergyHist.clear();
EnergyHist(vParam[B_EREF]); EnergyHist(vParam[SBVP::EREF]);
VarianceHist(vParam[B_SIGMA2]); VarianceHist(vParam[SBVP::SIGMA2]);
//DMCEnergyHist(vParam[B_EREF]); //DMCEnergyHist(vParam[SBVP::EREF]);
o << "SimpleFixedNodeBranch::checkParameters " << std::endl; o << "SimpleFixedNodeBranch::checkParameters " << std::endl;
o << " Average Energy of a population = " << e << 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() << o.str() << std::endl;
app_log().flush(); app_log().flush();
@ -847,17 +849,17 @@ void SimpleFixedNodeBranch::checkParameters(const int global_walkers, RefVector<
{ {
FullPrecRealType e, sigma2; FullPrecRealType e, sigma2;
MyEstimator->getCurrentStatistics(global_walkers, walkers, e, sigma2); MyEstimator->getCurrentStatistics(global_walkers, walkers, e, sigma2);
vParam[B_ETRIAL] = vParam[B_EREF] = e; vParam[SBVP::ETRIAL] = vParam[SBVP::EREF] = e;
vParam[B_SIGMA2] = sigma2; vParam[SBVP::SIGMA2] = sigma2;
EnergyHist.clear(); EnergyHist.clear();
VarianceHist.clear(); VarianceHist.clear();
//DMCEnergyHist.clear(); //DMCEnergyHist.clear();
EnergyHist(vParam[B_EREF]); EnergyHist(vParam[SBVP::EREF]);
VarianceHist(vParam[B_SIGMA2]); VarianceHist(vParam[SBVP::SIGMA2]);
//DMCEnergyHist(vParam[B_EREF]); //DMCEnergyHist(vParam[SBVP::EREF]);
o << "SimpleFixedNodeBranch::checkParameters " << std::endl; o << "SimpleFixedNodeBranch::checkParameters " << std::endl;
o << " Average Energy of a population = " << e << 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() << o.str() << std::endl;
app_log().flush(); app_log().flush();
@ -871,15 +873,15 @@ void SimpleFixedNodeBranch::finalize(const int global_walkers, RefVector<MCPWalk
o << "===================================================="; o << "====================================================";
o << "\n SimpleFixedNodeBranch::finalize after a DMC block"; o << "\n SimpleFixedNodeBranch::finalize after a DMC block";
o << "\n QMC counter = " << iParam[B_COUNTER]; o << "\n QMC counter = " << iParam[B_COUNTER];
o << "\n time step = " << vParam[B_TAU]; o << "\n time step = " << vParam[SBVP::TAU];
o << "\n effective time step = " << vParam[B_TAUEFF]; o << "\n effective time step = " << vParam[SBVP::TAUEFF];
o << "\n trial energy = " << vParam[B_ETRIAL]; o << "\n trial energy = " << vParam[SBVP::ETRIAL];
o << "\n reference energy = " << vParam[B_EREF]; o << "\n reference energy = " << vParam[SBVP::EREF];
o << "\n reference variance = " << vParam[B_SIGMA2]; o << "\n reference variance = " << vParam[SBVP::SIGMA2];
o << "\n target walkers = " << iParam[B_TARGETWALKERS]; 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 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 QMC Status (BranchMode) = " << BranchMode;
o << "\n===================================================="; o << "\n====================================================";
} }
@ -889,11 +891,11 @@ void SimpleFixedNodeBranch::finalize(const int global_walkers, RefVector<MCPWalk
o << "===================================================="; o << "====================================================";
o << "\n SimpleFixedNodeBranch::finalize after a RMC block"; o << "\n SimpleFixedNodeBranch::finalize after a RMC block";
o << "\n QMC counter = " << iParam[B_COUNTER]; o << "\n QMC counter = " << iParam[B_COUNTER];
o << "\n time step = " << vParam[B_TAU]; o << "\n time step = " << vParam[SBVP::TAU];
o << "\n effective time step = " << vParam[B_TAUEFF]; o << "\n effective time step = " << vParam[SBVP::TAUEFF];
o << "\n reference energy = " << vParam[B_EREF]; o << "\n reference energy = " << vParam[SBVP::EREF];
o << "\n reference variance = " << vParam[B_SIGMA2]; o << "\n reference variance = " << vParam[SBVP::SIGMA2];
o << "\n cutoff energy = " << vParam[B_BRANCHCUTOFF] << " " << vParam[B_BRANCHMAX]; o << "\n cutoff energy = " << vParam[SBVP::BRANCHCUTOFF] << " " << vParam[SBVP::BRANCHMAX];
o << "\n QMC Status (BranchMode) = " << BranchMode; o << "\n QMC Status (BranchMode) = " << BranchMode;
o << "\n===================================================="; o << "\n====================================================";
} }
@ -903,18 +905,18 @@ void SimpleFixedNodeBranch::finalize(const int global_walkers, RefVector<MCPWalk
FullPrecRealType e, sigma2; FullPrecRealType e, sigma2;
//MyEstimator->getEnergyAndWeight(e,w,sigma2); //MyEstimator->getEnergyAndWeight(e,w,sigma2);
MyEstimator->getCurrentStatistics(global_walkers, walkers , e, sigma2); MyEstimator->getCurrentStatistics(global_walkers, walkers , e, sigma2);
vParam[B_ETRIAL] = vParam[B_EREF] = e; vParam[SBVP::ETRIAL] = vParam[SBVP::EREF] = e;
vParam[B_SIGMA2] = sigma2; vParam[SBVP::SIGMA2] = sigma2;
//this is just to avoid diving by n-1 == 0 //this is just to avoid diving by n-1 == 0
EnergyHist(vParam[B_EREF]); EnergyHist(vParam[SBVP::EREF]);
//add Eref to the DMCEnergyHistory //add Eref to the DMCEnergyHistory
//DMCEnergyHist(vParam[B_EREF]); //DMCEnergyHist(vParam[SBVP::EREF]);
o << "===================================================="; o << "====================================================";
o << "\n SimpleFixedNodeBranch::finalize after a VMC block"; o << "\n SimpleFixedNodeBranch::finalize after a VMC block";
o << "\n QMC counter = " << iParam[B_COUNTER]; o << "\n QMC counter = " << iParam[B_COUNTER];
o << "\n time step = " << vParam[B_TAU]; o << "\n time step = " << vParam[SBVP::TAU];
o << "\n reference energy = " << vParam[B_EREF]; o << "\n reference energy = " << vParam[SBVP::EREF];
o << "\n reference variance = " << vParam[B_SIGMA2]; o << "\n reference variance = " << vParam[SBVP::SIGMA2];
o << "\n===================================================="; o << "\n====================================================";
} }
app_log() << o.str() << std::endl; app_log() << o.str() << std::endl;
@ -929,15 +931,15 @@ void SimpleFixedNodeBranch::finalize(MCWalkerConfiguration& w)
o << "===================================================="; o << "====================================================";
o << "\n SimpleFixedNodeBranch::finalize after a DMC block"; o << "\n SimpleFixedNodeBranch::finalize after a DMC block";
o << "\n QMC counter = " << iParam[B_COUNTER]; o << "\n QMC counter = " << iParam[B_COUNTER];
o << "\n time step = " << vParam[B_TAU]; o << "\n time step = " << vParam[SBVP::TAU];
o << "\n effective time step = " << vParam[B_TAUEFF]; o << "\n effective time step = " << vParam[SBVP::TAUEFF];
o << "\n trial energy = " << vParam[B_ETRIAL]; o << "\n trial energy = " << vParam[SBVP::ETRIAL];
o << "\n reference energy = " << vParam[B_EREF]; o << "\n reference energy = " << vParam[SBVP::EREF];
o << "\n reference variance = " << vParam[B_SIGMA2]; o << "\n reference variance = " << vParam[SBVP::SIGMA2];
o << "\n target walkers = " << iParam[B_TARGETWALKERS]; 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 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 QMC Status (BranchMode) = " << BranchMode;
o << "\n===================================================="; o << "\n====================================================";
} }
@ -947,11 +949,11 @@ void SimpleFixedNodeBranch::finalize(MCWalkerConfiguration& w)
o << "===================================================="; o << "====================================================";
o << "\n SimpleFixedNodeBranch::finalize after a RMC block"; o << "\n SimpleFixedNodeBranch::finalize after a RMC block";
o << "\n QMC counter = " << iParam[B_COUNTER]; o << "\n QMC counter = " << iParam[B_COUNTER];
o << "\n time step = " << vParam[B_TAU]; o << "\n time step = " << vParam[SBVP::TAU];
o << "\n effective time step = " << vParam[B_TAUEFF]; o << "\n effective time step = " << vParam[SBVP::TAUEFF];
o << "\n reference energy = " << vParam[B_EREF]; o << "\n reference energy = " << vParam[SBVP::EREF];
o << "\n reference variance = " << vParam[B_SIGMA2]; o << "\n reference variance = " << vParam[SBVP::SIGMA2];
o << "\n cutoff energy = " << vParam[B_BRANCHCUTOFF] << " " << vParam[B_BRANCHMAX]; o << "\n cutoff energy = " << vParam[SBVP::BRANCHCUTOFF] << " " << vParam[SBVP::BRANCHMAX];
o << "\n QMC Status (BranchMode) = " << BranchMode; o << "\n QMC Status (BranchMode) = " << BranchMode;
o << "\n===================================================="; o << "\n====================================================";
} }
@ -961,18 +963,18 @@ void SimpleFixedNodeBranch::finalize(MCWalkerConfiguration& w)
FullPrecRealType e, sigma2; FullPrecRealType e, sigma2;
//MyEstimator->getEnergyAndWeight(e,w,sigma2); //MyEstimator->getEnergyAndWeight(e,w,sigma2);
MyEstimator->getCurrentStatistics(w, e, sigma2); MyEstimator->getCurrentStatistics(w, e, sigma2);
vParam[B_ETRIAL] = vParam[B_EREF] = e; vParam[SBVP::ETRIAL] = vParam[SBVP::EREF] = e;
vParam[B_SIGMA2] = sigma2; vParam[SBVP::SIGMA2] = sigma2;
//this is just to avoid diving by n-1 == 0 //this is just to avoid diving by n-1 == 0
EnergyHist(vParam[B_EREF]); EnergyHist(vParam[SBVP::EREF]);
//add Eref to the DMCEnergyHistory //add Eref to the DMCEnergyHistory
//DMCEnergyHist(vParam[B_EREF]); //DMCEnergyHist(vParam[SBVP::EREF]);
o << "===================================================="; o << "====================================================";
o << "\n SimpleFixedNodeBranch::finalize after a VMC block"; o << "\n SimpleFixedNodeBranch::finalize after a VMC block";
o << "\n QMC counter = " << iParam[B_COUNTER]; o << "\n QMC counter = " << iParam[B_COUNTER];
o << "\n time step = " << vParam[B_TAU]; o << "\n time step = " << vParam[SBVP::TAU];
o << "\n reference energy = " << vParam[B_EREF]; o << "\n reference energy = " << vParam[SBVP::EREF];
o << "\n reference variance = " << vParam[B_SIGMA2]; o << "\n reference variance = " << vParam[SBVP::SIGMA2];
o << "\n===================================================="; o << "\n====================================================";
} }
app_log() << o.str() << std::endl; app_log() << o.str() << std::endl;
@ -1007,8 +1009,8 @@ void SimpleFixedNodeBranch::write(const std::string& fname, bool overwrite)
if (MyEstimator->is_manager()) if (MyEstimator->is_manager())
{ {
//\since 2008-06-24 //\since 2008-06-24
vParam[B_ACC_ENERGY] = EnergyHist.result(); vParam[SBVP::ACC_ENERGY] = EnergyHist.result();
vParam[B_ACC_SAMPLES] = EnergyHist.count(); vParam[SBVP::ACC_SAMPLES] = EnergyHist.count();
BranchIO hh(*this, MyEstimator->getCommunicator()); BranchIO hh(*this, MyEstimator->getCommunicator());
bool success = hh.write(fname); bool success = hh.write(fname);
} }
@ -1019,8 +1021,8 @@ void SimpleFixedNodeBranch::read(const std::string& fname)
BranchMode.set(B_RESTART, 0); BranchMode.set(B_RESTART, 0);
if (fname.empty()) if (fname.empty())
return; return;
vParam[B_ACC_ENERGY] = EnergyHist.result(); vParam[SBVP::ACC_ENERGY] = EnergyHist.result();
vParam[B_ACC_SAMPLES] = EnergyHist.count(); vParam[SBVP::ACC_SAMPLES] = EnergyHist.count();
BranchIO hh(*this, MyEstimator->getCommunicator()); BranchIO hh(*this, MyEstimator->getCommunicator());
BranchModeType bmode(BranchMode); BranchModeType bmode(BranchMode);
bool success = hh.read(fname); bool success = hh.read(fname);
@ -1054,30 +1056,37 @@ void SimpleFixedNodeBranch::setBranchCutoff(FullPrecRealType variance,
{ {
// eq.(3), J. Chem. Phys. 89, 3629 (1988). // eq.(3), J. Chem. Phys. 89, 3629 (1988).
// eq.(9), J. Chem. Phys. 99, 2865 (1993). // 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") else if (branching_cutoff_scheme == "ZSGMA")
{ {
// eq.(6), Phys. Rev. B 93, 241118(R) (2016) // eq.(6), Phys. Rev. B 93, 241118(R) (2016)
// do nothing if Nelec is not passed in. // do nothing if Nelec is not passed in.
if (Nelec > 0) 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") else if (branching_cutoff_scheme == "YL")
{ {
// a scheme from Ye Luo. // 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") else if (branching_cutoff_scheme == "classic")
{ {
// default QMCPACK choice which is the same as v3.0.0 and before. // 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 else
APP_ABORT("SimpleFixedNodeBranch::setBranchCutoff unknown branching cutoff scheme " + branching_cutoff_scheme); APP_ABORT("SimpleFixedNodeBranch::setBranchCutoff unknown branching cutoff scheme " + branching_cutoff_scheme);
vParam[B_BRANCHMAX] = vParam[B_BRANCHCUTOFF] * 1.5; vParam[SBVP::BRANCHMAX] = vParam[SBVP::BRANCHCUTOFF] * 1.5;
vParam[B_BRANCHFILTER] = 1.0 / (vParam[B_BRANCHMAX] - vParam[B_BRANCHCUTOFF]); 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 } // namespace qmcplusplus

View File

@ -21,6 +21,7 @@
#ifndef QMCPLUSPLUS_SIMPLE_FIXEDNODE_BRANCHER_H #ifndef QMCPLUSPLUS_SIMPLE_FIXEDNODE_BRANCHER_H
#define QMCPLUSPLUS_SIMPLE_FIXEDNODE_BRANCHER_H #define QMCPLUSPLUS_SIMPLE_FIXEDNODE_BRANCHER_H
#include <array>
#include <Configuration.h> #include <Configuration.h>
#include <OhmmsData/ParameterSet.h> #include <OhmmsData/ParameterSet.h>
#include <Particle/MCWalkerConfiguration.h> #include <Particle/MCWalkerConfiguration.h>
@ -38,6 +39,12 @@ namespace qmcplusplus
class EstimatorManagerBase; class EstimatorManagerBase;
/** Manages the state of QMC sections and handles population control for DMCs /** 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 * QMCDriver object owns a SimpleFixedNodeBranch to keep track of the
* progress of a qmc section. It implements several methods to control the * progress of a qmc section. It implements several methods to control the
@ -116,30 +123,42 @@ struct SimpleFixedNodeBranch : public QMCTraits
typedef TinyVector<int, B_IPARAM_MAX> IParamType; typedef TinyVector<int, B_IPARAM_MAX> IParamType;
IParamType iParam; IParamType iParam;
/*! enum for vParam */ /** enum for vParam
enum *
* Easy serialization is a relatively minor concern compared to the
* annoyance this causes elsewhere.
*/
enum class SimpleBranchVectorParameter
{ {
B_TAU = 0, TAU = 0,
B_TAUEFF, TAUEFF,
B_ETRIAL, ETRIAL,
B_EREF, EREF,
B_ENOW, ENOW,
B_BRANCHMAX, BRANCHMAX,
B_BRANCHCUTOFF, BRANCHCUTOFF,
B_BRANCHFILTER, BRANCHFILTER,
B_SIGMA2, SIGMA2,
B_ACC_ENERGY, ACC_ENERGY,
B_ACC_SAMPLES, ACC_SAMPLES,
B_FEEDBACK, FEEDBACK,
B_FILTERSCALE, FILTERSCALE,
B_VPARAM_MAX = 17 VPARAM_MAX = 17 // four extra, why? Sloppy or undocumented hack?
}; };
using SBVP = SimpleBranchVectorParameter;
/** controlling parameters of real type
/** controlling parameters of full precision real type
* *
* Mostly internal * Mostly internal
*/ */
typedef TinyVector<FullPrecRealType, B_VPARAM_MAX> VParamType; template<typename PAR_ENUM>
struct VParams : public std::array<FullPrecRealType, static_cast<size_t>(PAR_ENUM::VPARAM_MAX)>
{
using Base = std::array<FullPrecRealType, static_cast<size_t>(PAR_ENUM::VPARAM_MAX)>;
FullPrecRealType& operator[](PAR_ENUM sbvp) { return Base::operator[](static_cast<size_t>(sbvp)); }
const FullPrecRealType& operator[](PAR_ENUM sbvp) const { return Base::operator[](static_cast<size_t>(sbvp)); }
};
using VParamType = VParams<SBVP>;
VParamType vParam; VParamType vParam;
/** number of remaning steps for a specific tasks /** number of remaning steps for a specific tasks
@ -203,6 +222,7 @@ struct SimpleFixedNodeBranch : public QMCTraits
inline bool phaseChanged(RealType psi0) const inline bool phaseChanged(RealType psi0) const
{ {
// TODO: remove ifdef
#if defined(QMC_COMPLEX) #if defined(QMC_COMPLEX)
return false; return false;
#else #else
@ -261,13 +281,13 @@ struct SimpleFixedNodeBranch : public QMCTraits
*/ */
inline RealType branchWeightBare(RealType enew, RealType eold) const 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 inline RealType branchWeightReleasedNode(RealType enew, RealType eold, RealType eref) const
{ {
if (BranchMode[B_DMCSTAGE]) 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 else
return 1.0; return 1.0;
} }
@ -278,25 +298,25 @@ struct SimpleFixedNodeBranch : public QMCTraits
*/ */
inline RealType branchWeight(FullPrecRealType enew, FullPrecRealType eold) const inline RealType branchWeight(FullPrecRealType enew, FullPrecRealType eold) const
{ {
FullPrecRealType taueff_ = vParam[B_TAUEFF] * 0.5; FullPrecRealType taueff_ = vParam[SBVP::TAUEFF] * 0.5;
FullPrecRealType x = std::max(vParam[B_EREF] - enew, vParam[B_EREF] - eold); FullPrecRealType x = std::max(vParam[SBVP::EREF] - enew, vParam[SBVP::EREF] - eold);
if (x > vParam[B_BRANCHMAX]) if (x > vParam[SBVP::BRANCHMAX])
taueff_ = 0.0; taueff_ = 0.0;
else if (x > vParam[B_BRANCHCUTOFF]) else if (x > vParam[SBVP::BRANCHCUTOFF])
taueff_ *= (1.0 - (x - vParam[B_BRANCHCUTOFF]) * vParam[B_BRANCHFILTER]); taueff_ *= (1.0 - (x - vParam[SBVP::BRANCHCUTOFF]) * vParam[SBVP::BRANCHFILTER]);
return std::exp(taueff_ * (vParam[B_ETRIAL] * 2.0 - enew - eold)); return std::exp(taueff_ * (vParam[SBVP::ETRIAL] * 2.0 - enew - eold));
} }
inline RealType symLinkAction(RealType logGf, RealType logGb, RealType enew, RealType eold) const inline RealType symLinkAction(RealType logGf, RealType logGb, RealType enew, RealType eold) const
{ {
RealType driftaction = -0.5 * (logGf + logGb); RealType driftaction = -0.5 * (logGf + logGb);
//RealType energyaction = //RealType energyaction =
RealType taueff_ = vParam[B_TAUEFF] * 0.5; RealType taueff_ = vParam[SBVP::TAUEFF] * 0.5;
RealType x = std::max(vParam[B_EREF] - enew, vParam[B_EREF] - eold); RealType x = std::max(vParam[SBVP::EREF] - enew, vParam[SBVP::EREF] - eold);
if (x > vParam[B_BRANCHMAX]) if (x > vParam[SBVP::BRANCHMAX])
taueff_ = 0.0; taueff_ = 0.0;
else if (x > vParam[B_BRANCHCUTOFF]) else if (x > vParam[SBVP::BRANCHCUTOFF])
taueff_ *= (1.0 - (x - vParam[B_BRANCHCUTOFF]) * vParam[B_BRANCHFILTER]); taueff_ *= (1.0 - (x - vParam[SBVP::BRANCHCUTOFF]) * vParam[SBVP::BRANCHFILTER]);
RealType energyaction = taueff_ * (enew + eold); RealType energyaction = taueff_ * (enew + eold);
return driftaction + energyaction; return driftaction + energyaction;
} }
@ -304,7 +324,7 @@ struct SimpleFixedNodeBranch : public QMCTraits
inline RealType symLinkActionBare(RealType logGf, RealType logGb, RealType enew, RealType eold) const inline RealType symLinkActionBare(RealType logGf, RealType logGb, RealType enew, RealType eold) const
{ {
RealType driftaction = -0.5 * (logGf + logGb); 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 energyaction = taueff_ * (enew + eold);
// RealType wavefunctionaction= -psinew + psiold; // RealType wavefunctionaction= -psinew + psiold;
return driftaction + energyaction; return driftaction + energyaction;
@ -312,12 +332,12 @@ struct SimpleFixedNodeBranch : public QMCTraits
inline RealType DMCLinkAction(RealType enew, RealType eold) const inline RealType DMCLinkAction(RealType enew, RealType eold) const
{ {
RealType taueff_ = vParam[B_TAUEFF] * 0.5; RealType taueff_ = vParam[SBVP::TAUEFF] * 0.5;
RealType x = std::max(vParam[B_EREF] - enew, vParam[B_EREF] - eold); RealType x = std::max(vParam[SBVP::EREF] - enew, vParam[SBVP::EREF] - eold);
if (x > vParam[B_BRANCHMAX]) if (x > vParam[SBVP::BRANCHMAX])
taueff_ = 0.0; taueff_ = 0.0;
else if (x > vParam[B_BRANCHCUTOFF]) else if (x > vParam[SBVP::BRANCHCUTOFF])
taueff_ *= (1.0 - (x - vParam[B_BRANCHCUTOFF]) * vParam[B_BRANCHFILTER]); taueff_ *= (1.0 - (x - vParam[SBVP::BRANCHCUTOFF]) * vParam[SBVP::BRANCHFILTER]);
return taueff_ * (enew + eold); return taueff_ * (enew + eold);
} }
/** return the branch weight according to JCP1993 Umrigar et al. Appendix A p=1, q=0 /** return the branch weight according to JCP1993 Umrigar et al. Appendix A p=1, q=0
@ -328,9 +348,9 @@ struct SimpleFixedNodeBranch : public QMCTraits
*/ */
inline RealType branchWeight(RealType enew, RealType eold, RealType scnew, RealType scold) const 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 s1 = (vParam[SBVP::ETRIAL] - vParam[SBVP::EREF]) + (vParam[SBVP::EREF] - enew) * scnew;
FullPrecRealType s0 = (vParam[B_ETRIAL] - vParam[B_EREF]) + (vParam[B_EREF] - eold) * scold; FullPrecRealType s0 = (vParam[SBVP::ETRIAL] - vParam[SBVP::EREF]) + (vParam[SBVP::EREF] - eold) * scold;
return std::exp(vParam[B_TAUEFF] * 0.5 * (s1 + s0)); return std::exp(vParam[SBVP::TAUEFF] * 0.5 * (s1 + s0));
} }
/** return the branch weight according to JCP1993 Umrigar et al. Appendix A /** return the branch weight according to JCP1993 Umrigar et al. Appendix A
@ -342,9 +362,9 @@ struct SimpleFixedNodeBranch : public QMCTraits
*/ */
inline RealType branchWeight(RealType enew, RealType eold, RealType scnew, RealType scold, RealType p) const 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 s1 = (vParam[SBVP::ETRIAL] - vParam[SBVP::EREF]) + (vParam[SBVP::EREF] - enew) * scnew;
FullPrecRealType s0 = (vParam[B_ETRIAL] - vParam[B_EREF]) + (vParam[B_EREF] - eold) * scold; FullPrecRealType s0 = (vParam[SBVP::ETRIAL] - vParam[SBVP::EREF]) + (vParam[SBVP::EREF] - eold) * scold;
return std::exp(vParam[B_TAUEFF] * (p * 0.5 * (s1 - s0) + s0)); return std::exp(vParam[SBVP::TAUEFF] * (p * 0.5 * (s1 - s0) + s0));
//return std::exp(TauEff*(p*0.5*(sp-sq)+sq)); //return std::exp(TauEff*(p*0.5*(sp-sq)+sq));
} }
@ -359,15 +379,15 @@ struct SimpleFixedNodeBranch : public QMCTraits
ScaleSum += scnew + scold; ScaleSum += scnew + scold;
ScaleNum += 2; ScaleNum += 2;
FullPrecRealType scavg = (ScaleNum > 10000) ? ScaleSum / (RealType)ScaleNum : 1.0; FullPrecRealType scavg = (ScaleNum > 10000) ? ScaleSum / (RealType)ScaleNum : 1.0;
FullPrecRealType s1 = (vParam[B_ETRIAL] - vParam[B_EREF]) + (vParam[B_EREF] - enew) * scnew / scavg; FullPrecRealType s1 = (vParam[SBVP::ETRIAL] - vParam[SBVP::EREF]) + (vParam[SBVP::EREF] - enew) * scnew / scavg;
FullPrecRealType s0 = (vParam[B_ETRIAL] - vParam[B_EREF]) + (vParam[B_EREF] - eold) * scold / scavg; FullPrecRealType s0 = (vParam[SBVP::ETRIAL] - vParam[SBVP::EREF]) + (vParam[SBVP::EREF] - eold) * scold / scavg;
return std::exp(taueff * 0.5 * (s1 + s0)); return std::exp(taueff * 0.5 * (s1 + s0));
} }
inline RealType getEref() const { return vParam[B_EREF]; } inline RealType getEref() const { return vParam[SBVP::EREF]; }
inline RealType getEtrial() const { return vParam[B_ETRIAL]; } inline RealType getEtrial() const { return vParam[SBVP::ETRIAL]; }
inline RealType getTau() const { return vParam[B_TAU]; } inline RealType getTau() const { return vParam[SBVP::TAU]; }
inline RealType getTauEff() const { return vParam[B_TAUEFF]; } inline RealType getTauEff() const { return vParam[SBVP::TAUEFF]; }
/** perform branching /** perform branching
* @param iter current step * @param iter current step
@ -434,5 +454,7 @@ private:
int Nelec = 0); int Nelec = 0);
}; };
std::ostream& operator<<(std::ostream& os, SimpleFixedNodeBranch::VParamType& rhs);
} // namespace qmcplusplus } // namespace qmcplusplus
#endif #endif

View File

@ -633,7 +633,7 @@ WalkerControlBase::PopulationAdjustment WalkerControlBase::calcPopulationAdjustm
//update curData //update curData
curData[ENERGY_INDEX] = esum; curData[ENERGY_INDEX] = esum;
curData[ENERGY_SQ_INDEX] = e2sum; curData[ENERGY_SQ_INDEX] = e2sum;
curData[WALKERSIZE_INDEX] = pop.get_active_walkers(); curData[WALKERSIZE_INDEX] = pop.get_walkers().size();
curData[WEIGHT_INDEX] = wsum; curData[WEIGHT_INDEX] = wsum;
curData[EREF_INDEX] = ecum; curData[EREF_INDEX] = ecum;
curData[R2ACCEPTED_INDEX] = r2_accepted; curData[R2ACCEPTED_INDEX] = r2_accepted;

View File

@ -26,6 +26,9 @@ CoulombPBCAA::CoulombPBCAA(ParticleSet& ref, bool active, bool computeForces)
AA(0), AA(0),
myGrid(0), myGrid(0),
rVs(0), rVs(0),
dAA(0),
myGridforce(0),
rVsforce(0),
is_active(active), is_active(active),
FirstTime(true), FirstTime(true),
myConst(0.0), myConst(0.0),
@ -304,6 +307,14 @@ void CoulombPBCAA::initBreakup(ParticleSet& P)
{ {
rVs = LRCoulombSingleton::createSpline4RbyVs(AA, myRcut, myGrid); rVs = LRCoulombSingleton::createSpline4RbyVs(AA, myRcut, myGrid);
} }
if ( ComputeForces )
{
dAA = LRCoulombSingleton::getDerivHandler(P);
if (rVsforce == 0)
{
rVsforce = LRCoulombSingleton::createSpline4RbyVs(dAA, myRcut, myGridforce);
}
}
P.update(); P.update();
} }
@ -318,7 +329,8 @@ CoulombPBCAA::Return_t CoulombPBCAA::evalLRwithForces(ParticleSet& P)
RealType Z2 = Zspec[spec2]; RealType Z2 = Zspec[spec2];
for (int iat = 0; iat < grad.size(); iat++) for (int iat = 0; iat < grad.size(); iat++)
grad[iat] = TinyVector<RealType, DIM>(0.0); grad[iat] = TinyVector<RealType, DIM>(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++) for (int iat = 0; iat < grad.size(); iat++)
forces[iat] += Z2 * grad[iat]; forces[iat] += Z2 * grad[iat];
} //spec2 } //spec2
@ -341,11 +353,11 @@ CoulombPBCAA::Return_t CoulombPBCAA::evalSRwithForces(ParticleSet& P)
{ {
RealType V, rV, d_rV_dr, d2_rV_dr2; RealType V, rV, d_rV_dr, d2_rV_dr2;
RealType rinv = 1.0 / dist[j]; 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; 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[ipart] += grad;
forces[j] -= grad; forces[j] -= grad;
} }
@ -360,11 +372,12 @@ CoulombPBCAA::Return_t CoulombPBCAA::evalSRwithForces(ParticleSet& P)
{ {
RealType V, rV, d_rV_dr, d2_rV_dr2; RealType V, rV, d_rV_dr, d2_rV_dr2;
RealType rinv = 1.0 / dist[j]; 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; 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[NumCenters - ipart] += grad;
forces[j] -= grad; forces[j] -= grad;
} }
@ -380,7 +393,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++) 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; 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); RealType V = rV * d_aa.rinv(nn);
esum += Zat[jpart] * d_aa.rinv(nn) * rV; 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); PosType grad = Zat[jpart] * Zat[ipart] * (d_rV_dr - V) * d_aa.rinv(nn) * d_aa.rinv(nn) * d_aa.dr(nn);

View File

@ -38,9 +38,14 @@ struct CoulombPBCAA : public OperatorBase, public ForceBase
typedef DistanceTableData::RowContainer RowContainerType; typedef DistanceTableData::RowContainer RowContainerType;
// energy-optimized
LRHandlerType* AA; LRHandlerType* AA;
GridType* myGrid; GridType* myGrid;
RadFunctorType* rVs; RadFunctorType* rVs;
// force-optimized
LRHandlerType* dAA;
GridType* myGridforce;
RadFunctorType* rVsforce;
bool is_active; bool is_active;
bool FirstTime; bool FirstTime;

View File

@ -132,10 +132,9 @@ void ForceChiesaPBCAA::initBreakup(ParticleSet& P)
minkc = std::min(PtclA.Lattice.LR_kc, P.Lattice.LR_kc); minkc = std::min(PtclA.Lattice.LR_kc, P.Lattice.LR_kc);
//AB->initBreakup(*PtclB); //AB->initBreakup(*PtclB);
//initBreakup is called only once //initBreakup is called only once
//AB = LRCoulombSingleton::getHandler(*PtclB); dAB = LRCoulombSingleton::getDerivHandler(P);
AB = LRCoulombSingleton::getDerivHandler(P);
// myConst=evalConsts(); // 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 // create the spline function for the short-range part assuming pure potential
// if(V0==0) // if(V0==0)
// { // {
@ -160,7 +159,7 @@ void ForceChiesaPBCAA::evaluateLR(ParticleSet& P)
{ {
for (int iat = 0; iat < grad.size(); iat++) for (int iat = 0; iat < grad.size(); iat++)
grad[iat] = TinyVector<RealType, DIM>(0.0, 0.0, 0.0); grad[iat] = TinyVector<RealType, DIM>(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++) for (int iat = 0; iat < grad.size(); iat++)
{ {
forces[iat] += Qspec[j] * grad[iat]; forces[iat] += Qspec[j] * grad[iat];
@ -184,7 +183,7 @@ void ForceChiesaPBCAA::evaluateSR(ParticleSet& P)
const RealType r = dist[iat]; const RealType r = dist[iat];
const RealType rinv = RealType(1) / r; const RealType rinv = RealType(1) / r;
RealType g_f = g_filter(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]; PosType drhat = rinv * d_ab.Displacements[jat][iat];
forces[iat] += g_f * Zat[iat] * Qat[jat] * V * drhat; forces[iat] += g_f * Zat[iat] * Qat[jat] * V * drhat;
} }
@ -206,7 +205,7 @@ void ForceChiesaPBCAA::evaluateSR(ParticleSet& P)
RealType V; RealType V;
RealType g_f = g_filter(d_ab.r(nn)); RealType g_f = g_filter(d_ab.r(nn));
//rV = rVs->splint(d_ab.r(nn), d_rV_dr, d2_rV_dr2); //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; // std::stringstream wee;
// wee<<"srDf() #"<<omp_get_thread_num()<<" V= "<<V<<" "<<iat<<" "<<nn<< std::endl; // wee<<"srDf() #"<<omp_get_thread_num()<<" V= "<<V<<" "<<iat<<" "<<nn<< std::endl;
// std::cout <<wee.str(); // std::cout <<wee.str();
@ -233,14 +232,14 @@ void ForceChiesaPBCAA::evaluateSR_AA()
const RealType* restrict dist = d_aa.Distances[ipart]; const RealType* restrict dist = d_aa.Distances[ipart];
for (size_t jpart = 0; jpart < ipart; ++jpart) for (size_t jpart = 0; jpart < ipart; ++jpart)
{ {
RealType V = -AB->srDf(dist[jpart], RealType(1) / dist[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]; PosType grad = -Zat[jpart] * Zat[ipart] * V / dist[jpart] * d_aa.Displacements[ipart][jpart];
forces_IonIon[ipart] += grad; forces_IonIon[ipart] += grad;
forces_IonIon[jpart] -= grad; forces_IonIon[jpart] -= grad;
} }
} }
for (size_t ipart = 0; ipart < NptclA; ++ipart) //for (size_t ipart = 0; ipart < NptclA; ++ipart)
std::cout << "debug evaluateSR_AA " << forces_IonIon[ipart] << std::endl; //std::cout << "debug evaluateSR_AA " << forces_IonIon[ipart] << std::endl;
} }
else 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++) 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); PosType grad = -Zat[jpart] * Zat[ipart] * V * d_aa.rinv(nn) * d_aa.dr(nn);
forces_IonIon[ipart] += grad; forces_IonIon[ipart] += grad;
forces_IonIon[jpart] -= grad; forces_IonIon[jpart] -= grad;
@ -259,7 +258,7 @@ void ForceChiesaPBCAA::evaluateSR_AA()
// app_log() <<"grad[" <<ipart<< "] = "<<grad<< std::endl; // app_log() <<"grad[" <<ipart<< "] = "<<grad<< std::endl;
// app_log() <<"Zat[" <<ipart<< "] = "<<Zat[ipart]<< std::endl; // app_log() <<"Zat[" <<ipart<< "] = "<<Zat[ipart]<< std::endl;
} }
std::cout << "debug evaluateSR_AA " << forces_IonIon[ipart] << std::endl; //std::cout << "debug evaluateSR_AA " << forces_IonIon[ipart] << std::endl;
} }
#endif #endif
} }
@ -274,7 +273,7 @@ void ForceChiesaPBCAA::evaluateLR_AA()
RealType Z2 = Zspec[spec2]; RealType Z2 = Zspec[spec2];
for (int iat = 0; iat < grad.size(); iat++) for (int iat = 0; iat < grad.size(); iat++)
grad[iat] = TinyVector<RealType, DIM>(0.0); grad[iat] = TinyVector<RealType, DIM>(0.0);
AB->evaluateGrad(PtclA, PtclA, spec2, Zat, grad); dAB->evaluateGrad(PtclA, PtclA, spec2, Zat, grad);
for (int iat = 0; iat < grad.size(); iat++) for (int iat = 0; iat < grad.size(); iat++)
{ {
@ -347,7 +346,7 @@ bool ForceChiesaPBCAA::put(xmlNodePtr cur)
void ForceChiesaPBCAA::resetTargetParticleSet(ParticleSet& P) void ForceChiesaPBCAA::resetTargetParticleSet(ParticleSet& P)
{ {
AB->resetTargetParticleSet(P); dAB->resetTargetParticleSet(P);
} }
void ForceChiesaPBCAA::addObservables(PropertySetType& plist, BufferType& collectables) void ForceChiesaPBCAA::addObservables(PropertySetType& plist, BufferType& collectables)

View File

@ -42,7 +42,7 @@ struct ForceChiesaPBCAA : public OperatorBase, public ForceBase
///source particle set ///source particle set
ParticleSet& PtclA; ParticleSet& PtclA;
///long-range Handler ///long-range Handler
LRHandlerType* AB; LRHandlerType* dAB;
///number of species of A particle set ///number of species of A particle set
int NumSpeciesA; int NumSpeciesA;
///number of species of B particle set ///number of species of B particle set

View File

@ -24,6 +24,7 @@
#include "QMCHamiltonians/ForceChiesaPBCAA.h" #include "QMCHamiltonians/ForceChiesaPBCAA.h"
#include "QMCHamiltonians/ForceCeperley.h" #include "QMCHamiltonians/ForceCeperley.h"
#include "QMCHamiltonians/CoulombPotential.h" #include "QMCHamiltonians/CoulombPotential.h"
#include "QMCHamiltonians/CoulombPBCAA.h"
#include "QMCWaveFunctions/TrialWaveFunction.h" #include "QMCWaveFunctions/TrialWaveFunction.h"
@ -164,6 +165,7 @@ TEST_CASE("Chiesa Force", "[hamiltonian]")
CrystalLattice<OHMMS_PRECISION, OHMMS_DIM> Lattice; CrystalLattice<OHMMS_PRECISION, OHMMS_DIM> Lattice;
Lattice.BoxBConds = true; // periodic Lattice.BoxBConds = true; // periodic
Lattice.R.diagonal(5.0); Lattice.R.diagonal(5.0);
Lattice.LR_dim_cutoff = 25;
Lattice.reset(); Lattice.reset();
@ -171,10 +173,13 @@ TEST_CASE("Chiesa Force", "[hamiltonian]")
ParticleSet elec; ParticleSet elec;
ions.setName("ion"); ions.setName("ion");
ions.create(1); ions.create(2);
ions.R[0][0] = 0.0; ions.R[0][0] = 0.0;
ions.R[0][1] = 0.0; ions.R[0][1] = 0.0;
ions.R[0][2] = 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.setName("elec");
elec.create(2); elec.create(2);
@ -223,12 +228,23 @@ TEST_CASE("Chiesa Force", "[hamiltonian]")
elec.update(); elec.update();
force.evaluate(elec); force.evaluate(elec);
std::cout << " Force = " << force.forces << std::endl; std::cout << " Force = " << force.forces << std::endl;
std::cout << " Forces_IonIon = " << force.forces_IonIon << std::endl;
// Unvalidated externally // Unvalidated externally
REQUIRE(force.forces[0][0] == Approx(3.186559306)); REQUIRE(force.forces[0][0] == Approx(3.186559306));
REQUIRE(force.forces[0][1] == Approx(3.352572459)); REQUIRE(force.forces[0][1] == Approx(3.352572459));
REQUIRE(force.forces[0][2] == Approx(0.0)); 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[1][0] == Approx(0.1478626893));
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 // It seems a bit silly to test the makeClone method
// but this class does not use the compiler's copy constructor and // but this class does not use the compiler's copy constructor and

View File

@ -37,6 +37,7 @@ SET(WFBASE_SRCS
IF(NOT QMC_COMPLEX) IF(NOT QMC_COMPLEX)
SET(WFBASE_SRCS ${WFBASE_SRCS} SET(WFBASE_SRCS ${WFBASE_SRCS}
RotatedSPOs.cpp
FDLRWfn.cpp FDLRWfn.cpp
) )
ENDIF(NOT QMC_COMPLEX) ENDIF(NOT QMC_COMPLEX)
@ -203,12 +204,6 @@ IF(ENABLE_CUDA)
SET(FERMION_SRCS ${FERMION_SRCS} Fermion/delayed_update_helper.cu) SET(FERMION_SRCS ${FERMION_SRCS} Fermion/delayed_update_helper.cu)
ENDIF(ENABLE_CUDA) 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 # create libqmcwfs
#################################### ####################################

View File

@ -44,7 +44,11 @@ void DiracDeterminant<DU_TYPE>::set(int first, int nel, int delay)
{ {
FirstIndex = first; FirstIndex = first;
ndelay = delay; ndelay = delay;
resize(nel, nel); resize(nel, nel);
if(Optimizable)
Phi->buildOptVariables(nel);
} }
template<typename DU_TYPE> template<typename DU_TYPE>
@ -556,7 +560,10 @@ void DiracDeterminant<DU_TYPE>::evaluateDerivatives(ParticleSet& P,
const opt_variables_type& active, const opt_variables_type& active,
std::vector<ValueType>& dlogpsi, std::vector<ValueType>& dlogpsi,
std::vector<ValueType>& dhpsioverpsi) std::vector<ValueType>& dhpsioverpsi)
{} {
Phi->evaluateDerivatives(P, active, dlogpsi, dhpsioverpsi, FirstIndex, LastIndex);
}
template<typename DU_TYPE> template<typename DU_TYPE>
DiracDeterminant<DU_TYPE>* DiracDeterminant<DU_TYPE>::makeCopy(SPOSetPtr spo) const DiracDeterminant<DU_TYPE>* DiracDeterminant<DU_TYPE>::makeCopy(SPOSetPtr spo) const

View File

@ -355,6 +355,7 @@ MultiDiracDeterminant::MultiDiracDeterminant(const MultiDiracDeterminant& s)
detData = s.detData; detData = s.detData;
uniquePairs = s.uniquePairs; uniquePairs = s.uniquePairs;
DetSigns = s.DetSigns; DetSigns = s.DetSigns;
Optimizable = s.Optimizable;
registerTimers(); registerTimers();
Phi = (s.Phi->makeClone()); Phi = (s.Phi->makeClone());

View File

@ -24,13 +24,6 @@
#include "QMCWaveFunctions/Fermion/MultiSlaterDeterminant.h" #include "QMCWaveFunctions/Fermion/MultiSlaterDeterminant.h"
#include "QMCWaveFunctions/Fermion/MultiSlaterDeterminantFast.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) #if defined(QMC_CUDA)
#include "QMCWaveFunctions/Fermion/DiracDeterminantCUDA.h" #include "QMCWaveFunctions/Fermion/DiracDeterminantCUDA.h"
#endif #endif
@ -228,9 +221,7 @@ WaveFunctionComponent* SlaterDetBuilder::buildComponent(xmlNodePtr cur)
// Copy any entries in sposetmap into slaterdet_0 // Copy any entries in sposetmap into slaterdet_0
std::map<std::string, SPOSetPtr>::iterator iter; std::map<std::string, SPOSetPtr>::iterator iter;
for (iter = spomap.begin(); iter != spomap.end(); iter++) for (iter = spomap.begin(); iter != spomap.end(); iter++)
{
slaterdet_0->add(iter->second, iter->first); slaterdet_0->add(iter->second, iter->first);
}
size_t spin_group = 0; size_t spin_group = 0;
xmlNodePtr tcur = cur->children; xmlNodePtr tcur = cur->children;
while (tcur != NULL) while (tcur != NULL)
@ -295,7 +286,8 @@ WaveFunctionComponent* SlaterDetBuilder::buildComponent(xmlNodePtr cur)
app_log() << "Creating base determinant (up) for MSD expansion. \n"; app_log() << "Creating base determinant (up) for MSD expansion. \n";
up_det = new MultiDiracDeterminant((SPOSetPtr)spomap.find(spo_alpha)->second, 0); up_det = new MultiDiracDeterminant((SPOSetPtr)spomap.find(spo_alpha)->second, 0);
app_log() << "Creating base determinant (down) for MSD expansion. \n"; 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); multislaterdetfast_0 = new MultiSlaterDeterminantFast(targetPtcl, up_det, dn_det);
success = createMSDFast(multislaterdetfast_0, cur); success = createMSDFast(multislaterdetfast_0, cur);
} }
@ -424,7 +416,7 @@ bool SlaterDetBuilder::putDeterminant(xmlNodePtr cur, int spin_group)
#else #else
std::string useGPU("no"); std::string useGPU("no");
#endif #endif
int delay_rank(1); int delay_rank(0);
OhmmsAttributeSet sdAttrib; OhmmsAttributeSet sdAttrib;
sdAttrib.add(delay_rank, "delay_rank"); sdAttrib.add(delay_rank, "delay_rank");
sdAttrib.add(optimize, "optimize"); sdAttrib.add(optimize, "optimize");
@ -485,73 +477,22 @@ bool SlaterDetBuilder::putDeterminant(xmlNodePtr cur, int spin_group)
#else #else
if (UseBackflow) if (UseBackflow)
adet = new DiracDeterminantWithBackflow(targetPtcl, psi, BFTrans, firstIndex); 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<RealType> 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<LocalizedBasisSet<NGOBuilder::CenteredOrbitalType>>(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) #if defined(ENABLE_CUDA)
else if (useGPU == "yes") 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<DelayedUpdateCUDA<ValueType, QMCTraits::QTFull::ValueType>>(psi,firstIndex); adet = new DiracDeterminant<DelayedUpdateCUDA<ValueType, QMCTraits::QTFull::ValueType>>(psi,firstIndex);
} }
#endif #endif
else else
{ {
app_log() << "Using DiracDeterminant with DelayedUpdate engine" << std::endl; app_log() << " Using DiracDeterminant with DelayedUpdate engine" << std::endl;
adet = new DiracDeterminant<>(psi, firstIndex); adet = new DiracDeterminant<>(psi, firstIndex);
} }
#endif #endif
} }
if (delay_rank <= 0 || delay_rank > lastIndex - firstIndex)
if (delay_rank < 0 || delay_rank > lastIndex - firstIndex)
{ {
std::ostringstream err_msg; std::ostringstream err_msg;
err_msg << "SlaterDetBuilder::putDeterminant delay_rank must be positive " err_msg << "SlaterDetBuilder::putDeterminant delay_rank must be positive "
@ -560,10 +501,19 @@ bool SlaterDetBuilder::putDeterminant(xmlNodePtr cur, int spin_group)
<< "user input " + std::to_string(delay_rank); << "user input " + std::to_string(delay_rank);
APP_ABORT(err_msg.str()); APP_ABORT(err_msg.str());
} }
else if (delay_rank > 1) else if (delay_rank == 0)
app_log() << "Using rank-" << delay_rank << " delayed update" << std::endl; {
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 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); adet->set(firstIndex, lastIndex - firstIndex, delay_rank);
#ifdef QMC_CUDA #ifdef QMC_CUDA
targetPsi.setndelay(delay_rank); targetPsi.setndelay(delay_rank);

File diff suppressed because it is too large Load Diff

View File

@ -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 <QMCWaveFunctions/SPOSet.h>
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<RealType> m_work;
/// \brief pivot workspace
std::vector<int> 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<std::pair<int, int>> 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<RealType> 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<RealType> m_hder_mat;
// private member functions
private:
WaveFunctionComponent::RealType evaluate_matrices_from_scratch(ParticleSet& P, const bool all);
// public type definitions
public:
typedef OrbitalSetTraits<ValueType>::IndexVector_t IndexVector_t;
typedef OrbitalSetTraits<ValueType>::ValueVector_t ValueVector_t;
typedef OrbitalSetTraits<ValueType>::GradVector_t GradVector_t;
typedef OrbitalSetTraits<ValueType>::HessMatrix_t HessMatrix_t;
typedef OrbitalSetTraits<ValueType>::HessType HessType;
typedef Array<HessType, 3> HessArray_t;
typedef TinyVector<HessType, OHMMS_DIM> GGGType;
typedef Vector<GGGType> GGGVector_t;
typedef Matrix<GGGType> 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<RealType>& 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<ValueType>& dlogpsi,
std::vector<ValueType>& dhpsioverpsi);
void evaluateGradDerivatives(const ParticleSet::ParticleGradient_t& G_in, std::vector<ValueType>& dgradlogpsi);
};
} // namespace qmcplusplus
#endif

View File

@ -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 <stdexcept>
#include <utility>
#include <iterator>
#include <cassert>
#include <algorithm>
#include <vector>
#include <string>
#include <sstream>
#include <QMCWaveFunctions/SPOSet.h>
#include <QMCWaveFunctions/WaveFunctionComponent.h>
#include <Numerics/MatrixOperators.h>
#include <Utilities/RandomGenerator.h>
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 BS>
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<RealType> 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<RealType> m_init_B;
/// \brief workspace matrix
std::vector<ValueType> m_lc_coeffs;
/// \brief workspace matrix
std::vector<ValueType> m_basis_vals;
/// \brief workspace matrix
std::vector<ValueType> m_basis_der1;
/// \brief workspace matrix
std::vector<ValueType> 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<int> m_oidx;
/// \brief vector to hold particle indices
std::vector<int> 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<class IntIter>
static std::vector<int>::iterator prepare_index_vector(IntIter start, IntIter end, std::vector<int>& 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<int>::iterator prepare_index_vector_contiguous(const int start,
const int end,
std::vector<int>& 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<int>::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<class T>
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<RealType>(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<RealType>& 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<int>::const_iterator ostart,
std::vector<int>::const_iterator oend,
std::vector<int>::const_iterator pstart,
std::vector<int>::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<int>::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<char> 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<int>::const_iterator oend = prepare_index_vector_contiguous(os, oe, m_oidx);
// prepare particle list
std::vector<int>::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<ValueType>& 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

View File

@ -21,9 +21,6 @@
#include "QMCWaveFunctions/MolecularOrbitals/LocalizedBasisSet.h" #include "QMCWaveFunctions/MolecularOrbitals/LocalizedBasisSet.h"
#include "QMCWaveFunctions/MolecularOrbitals/AtomicBasisBuilder.h" #include "QMCWaveFunctions/MolecularOrbitals/AtomicBasisBuilder.h"
#include "QMCWaveFunctions/MolecularOrbitals/LCOrbitalSet.h" #include "QMCWaveFunctions/MolecularOrbitals/LCOrbitalSet.h"
#ifndef ENABLE_SOA
#include "QMCWaveFunctions/MolecularOrbitals/LCOrbitalSetOpt.h"
#endif
#include "Utilities/ProgressReportEngine.h" #include "Utilities/ProgressReportEngine.h"
#include "OhmmsData/AttributeSet.h" #include "OhmmsData/AttributeSet.h"
#include "io/hdf_archive.h" #include "io/hdf_archive.h"
@ -265,16 +262,7 @@ public:
{ {
if (use_new_opt_class == "yes") if (use_new_opt_class == "yes")
{ {
#ifndef ENABLE_SOA APP_ABORT("MolecularSPOBuilder Orbital optimization via rotation has been removed in AoS builds.\n");
app_log() << "Creating LCOrbitalSetOpt with the input coefficients" << std::endl;
lcos = new LCOrbitalSetOpt<ThisBasisSetType>(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
} }
else else
{ {

View File

@ -0,0 +1,866 @@
//////////////////////////////////////////////////////////////////////////////////////
//// This file is distributed under the University of Illinois/NCSA Open Source License.
//// See LICENSE file in top directory for details.
////
//// 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
////////////////////////////////////////////////////////////////////////////////////////
#include "QMCWaveFunctions/RotatedSPOs.h"
#include <Numerics/MatrixOperators.h>
#include "Numerics/DeterminantOperators.h"
#include "Numerics/OhmmsBlas.h"
namespace qmcplusplus
{
RotatedSPOs::RotatedSPOs(SPOSet* spos)
: SPOSet(spos->hasIonDerivs(), true), Phi(spos), params_supplied(false), IsCloned(false), nel_major_(0)
{
className = "RotatedSPOs";
OrbitalSetSize = Phi->getOrbitalSetSize();
}
RotatedSPOs::~RotatedSPOs() {}
void RotatedSPOs::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.
* nel_major_ will be set Nup.
*/
if (nel > nel_major_)
{
nel_major_ = nel;
const size_t nmo = Phi->getOrbitalSetSize();
// create active rotation parameter indices
std::vector<std::pair<int, int>> 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<int, int>(i, j));
buildOptVariables(created_m_act_rot_inds);
}
#endif
}
void RotatedSPOs::buildOptVariables(const std::vector<std::pair<int, int>>& 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");
myVars.clear();
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<RealType> param(m_act_rot_inds.size());
for (int i = 0; i < m_act_rot_inds.size(); i++)
param[i] = myVars[i];
apply_rotation(param, false);
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 RotatedSPOs::apply_rotation(const std::vector<RealType>& param, bool use_stored_copy)
{
assert(param.size() == m_act_rot_inds.size());
const size_t nmo = Phi->getOrbitalSetSize();
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);
Phi->applyRotation(rot_mat, use_stored_copy);
}
// compute exponential of a real, antisymmetric matrix by diagonalizing and exponentiating eigenvalues
void RotatedSPOs::exponentiate_antisym_matrix(ValueMatrix_t& mat)
{
const int n = mat.rows();
std::vector<std::complex<RealType>> mat_h(n * n, 0);
std::vector<RealType> eval(n, 0);
std::vector<std::complex<RealType>> work(2 * n, 0);
std::vector<RealType> rwork(3 * n, 0);
std::vector<std::complex<RealType>> mat_d(n * n, 0);
std::vector<std::complex<RealType>> 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<RealType>(0, -1.0 * mat[j][i]);
mat_h[j + n * i] = std::complex<RealType>(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<RealType>(0.0, eval[i])) : std::complex<RealType>(0.0, 0.0);
}
}
// perform matrix multiplication
// assume row major
BLAS::gemm('N', 'C', n, n, n, std::complex<RealType>(1.0, 0), &mat_d.at(0), n, &mat_h.at(0), n,
std::complex<RealType>(0.0, 0.0), &mat_t.at(0), n);
BLAS::gemm('N', 'N', n, n, n, std::complex<RealType>(1.0, 0), &mat_h.at(0), n, &mat_t.at(0), n,
std::complex<RealType>(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 RotatedSPOs::evaluateDerivatives(ParticleSet& P,
const opt_variables_type& optvars,
std::vector<ValueType>& dlogpsi,
std::vector<ValueType>& 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);
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 < nel; i++)
for (int j = 0; j < nel; j++)
psiM_inv(i, j) = psiM_all(i, j);
Invert(psiM_inv.data(), nel, nel);
//current value of Gradient and Laplacian
// gradient components
for (int a = 0; a < nel; a++)
for (int i = 0; i < nel; i++)
for (int k = 0; k < 3; k++)
myG_temp[a][k] += psiM_inv(i, a) * dpsiM_all(a, i)[k];
// laplacian components
for (int a = 0; a < nel; a++)
{
for (int i = 0; i < nel; i++)
myL_temp[a] += psiM_inv(i, a) * d2psiM_all(a, i);
}
// 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 a = 0, iat = FirstIndex; a < nel; a++, iat++)
{
myG_J[a] = (P.G[iat] - myG_temp[a]);
myL_J[a] = (P.L[iat] + dot(P.G[iat], P.G[iat]) - myL_temp[a]);
}
//possibly replace wit BLAS calls
for (int i = 0; i < nel; i++)
for (int j = 0; j < nmo; j++)
Bbar(i, j) = d2psiM_all(i, j) + 2 * dot(myG_J[i], dpsiM_all(i, j)) + myL_J[i] * psiM_all(i, j);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~PART2
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;
SPOSet::ValueMatrix_t Y3;
SPOSet::ValueMatrix_t Y4;
T.resize(nel, nmo);
Y1.resize(nel, nel);
Y2.resize(nel, nmo);
Y3.resize(nel, nmo);
Y4.resize(nel, nmo);
BLAS::gemm('N', 'N', nmo, nel, nel, ValueType(1.0), A, nmo, Ainv, nel, ValueType(0.0), T.data(), nmo);
BLAS::gemm('N', 'N', nel, nel, nel, ValueType(1.0), B, nmo, Ainv, nel, ValueType(0.0), Y1.data(), nel);
BLAS::gemm('N', 'N', nmo, nel, nel, ValueType(1.0), T.data(), nmo, Y1.data(), nel, ValueType(0.0), Y2.data(), nmo);
BLAS::gemm('N', 'N', nmo, nel, nel, ValueType(1.0), B, nmo, Ainv, nel, ValueType(0.0), Y3.data(), nmo);
//possibly replace with BLAS call
Y4 = Y3 - Y2;
for (int i = 0; i < m_act_rot_inds.size(); i++)
{
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);
dhpsioverpsi.at(kk) = ValueType(-0.5) * Y4(p, q);
}
}
void RotatedSPOs::evaluateDerivatives(ParticleSet& P,
const opt_variables_type& optvars,
std::vector<ValueType>& dlogpsi,
std::vector<ValueType>& dhpsioverpsi,
const ValueType& psiCurrent,
const std::vector<ValueType>& Coeff,
const std::vector<size_t>& C2node_up,
const std::vector<size_t>& 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<int>& detData_up,
const size_t N1,
const size_t N2,
const size_t NP1,
const size_t NP2,
const std::vector<std::vector<int>>& 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 RotatedSPOs::table_method_eval(std::vector<ValueType>& dlogpsi,
std::vector<ValueType>& 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<RealType>& Coeff,
const std::vector<size_t>& C2node_up,
const std::vector<size_t>& 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<int>& detData_up,
const size_t N1,
const size_t N2,
const size_t NP1,
const size_t NP2,
const std::vector<std::vector<int>>& 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<RealType> 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<ValueType> WS;
Vector<IndexType> 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* RotatedSPOs::makeClone() const
{
RotatedSPOs* myclone = new RotatedSPOs(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;
return myclone;
}
} // namespace qmcplusplus

View File

@ -0,0 +1,287 @@
//////////////////////////////////////////////////////////////////////////////////////
//// This file is distributed under the University of Illinois/NCSA Open Source License.
//// See LICENSE file in top directory for details.
////
//// 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
////////////////////////////////////////////////////////////////////////////////////////
#ifndef QMCPLUSPLUS_ROTATION_HELPER_H
#define QMCPLUSPLUS_ROTATION_HELPER_H
#include "QMCWaveFunctions/SPOSet.h"
namespace qmcplusplus
{
class RotatedSPOs : public SPOSet
{
public:
//constructor
RotatedSPOs(SPOSet* spos);
//destructor
~RotatedSPOs();
//vector that contains active orbital rotation parameter indices
std::vector<std::pair<int, int>> m_act_rot_inds;
//function to perform orbital rotations
void apply_rotation(const std::vector<RealType>& param, bool use_stored_copy);
//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<RealType> params;
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
// 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<std::pair<int, int>>& rotations);
void evaluateDerivatives(ParticleSet& P,
const opt_variables_type& optvars,
std::vector<ValueType>& dlogpsi,
std::vector<ValueType>& dhpsioverpsi,
const int& FirstIndex,
const int& LastIndex);
void evaluateDerivatives(ParticleSet& P,
const opt_variables_type& optvars,
std::vector<ValueType>& dlogpsi,
std::vector<ValueType>& dhpsioverpsi,
const ValueType& psiCurrent,
const std::vector<ValueType>& Coeff,
const std::vector<size_t>& C2node_up,
const std::vector<size_t>& 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<int>& detData_up,
const size_t N1,
const size_t N2,
const size_t NP1,
const size_t NP2,
const std::vector<std::vector<int>>& lookup_tbl);
//helper function to evaluatederivative; evaluate orbital rotation parameter derivative using table method
void table_method_eval(std::vector<ValueType>& dlogpsi,
std::vector<ValueType>& 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<RealType>& Coeff,
const std::vector<size_t>& C2node_up,
const std::vector<size_t>& 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<int>& detData_up,
const size_t N1,
const size_t N2,
const size_t NP1,
const size_t NP2,
const std::vector<std::vector<int>>& lookup_tbl);
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())
active.insertFrom(myVars);
Phi->storeParamsBeforeRotation();
}
}
void checkOutVariables(const opt_variables_type& active)
{
if (Optimizable && !IsCloned)
{
myVars.getIndex(active);
}
}
///reset
void resetParameters(const opt_variables_type& active)
{
if (Optimizable && !IsCloned)
{
std::vector<RealType> 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, true);
}
}
//*********************************************************************************
//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)
{
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);
}
void evaluateDetRatios(const VirtualParticleSet& VP,
ValueVector_t& psi,
const ValueVector_t& psiinv,
std::vector<ValueType>& 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)
{
assert(psi.size() <= OrbitalSetSize);
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

View File

@ -158,13 +158,11 @@ bool SPOSet::put(xmlNodePtr cur)
//initialize the number of orbital by the basis set size //initialize the number of orbital by the basis set size
int norb = BasisSetSize; int norb = BasisSetSize;
std::string debugc("no"); std::string debugc("no");
double orbital_mix_magnitude = 0.0;
bool PBC = false; bool PBC = false;
OhmmsAttributeSet aAttrib; OhmmsAttributeSet aAttrib;
aAttrib.add(norb, "orbitals"); aAttrib.add(norb, "orbitals");
aAttrib.add(norb, "size"); aAttrib.add(norb, "size");
aAttrib.add(debugc, "debug"); aAttrib.add(debugc, "debug");
aAttrib.add(orbital_mix_magnitude, "orbital_mix_magnitude");
aAttrib.put(cur); aAttrib.put(cur);
setOrbitalSetSize(norb); setOrbitalSetSize(norb);
xmlNodePtr occ_ptr = NULL; xmlNodePtr occ_ptr = NULL;
@ -226,8 +224,6 @@ bool SPOSet::put(xmlNodePtr cur)
app_log() << C << std::endl; app_log() << C << std::endl;
} }
init_LCOrbitalSetOpt(orbital_mix_magnitude);
return success && success2; return success && success2;
} }

View File

@ -137,8 +137,19 @@ public:
#endif #endif
/// create optimizable orbital rotation parameters /// 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<std::pair<int, int>>& rotations) {} virtual void buildOptVariables(const std::vector<std::pair<int, int>>& rotations) {}
// 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 /// reset parameters to the values from optimizer
virtual void resetParameters(const opt_variables_type& optVariables) = 0; virtual void resetParameters(const opt_variables_type& optVariables) = 0;
@ -146,6 +157,12 @@ public:
virtual void checkInVariables(opt_variables_type& active) {} virtual void checkInVariables(opt_variables_type& active) {}
virtual void checkOutVariables(const opt_variables_type& active) {} virtual void checkOutVariables(const opt_variables_type& active) {}
virtual void evaluateDerivatives(ParticleSet& P,
const opt_variables_type& optvars,
std::vector<ValueType>& dlogpsi,
std::vector<ValueType>& dhpsioverpsi,
const int& FirstIndex,
const int& LastIndex) {}
/** Evaluate the derivative of the optimized orbitals with respect to the parameters /** 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 * this is used only for MSD, to be refined for better serving both single and multi SD
*/ */
@ -300,12 +317,6 @@ public:
*/ */
virtual void evaluateThirdDeriv(const ParticleSet& P, int first, int last, GGGMatrix_t& grad_grad_grad_logdet); 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 /** evaluate the values, gradients and laplacians of this single-particle orbital for [first,last) particles
* @param P current ParticleSet * @param P current ParticleSet
* @param first starting index of the particles * @param first starting index of the particles
@ -413,16 +424,6 @@ public:
*/ */
virtual void finalizeConstruction() {} 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<RealType>& rot_mat){};
#ifdef QMC_CUDA #ifdef QMC_CUDA
using CTS = CUDAGlobalTypes; using CTS = CUDAGlobalTypes;

View File

@ -31,6 +31,10 @@
#endif #endif
#endif #endif
#if !defined(QMC_COMPLEX)
#include "QMCWaveFunctions/RotatedSPOs.h"
#endif
#if defined(HAVE_EINSPLINE) #if defined(HAVE_EINSPLINE)
#include "QMCWaveFunctions/EinsplineSetBuilder.h" #include "QMCWaveFunctions/EinsplineSetBuilder.h"
#endif #endif
@ -246,10 +250,12 @@ SPOSet* SPOSetBuilderFactory::createSPOSet(xmlNodePtr cur)
std::string bname(""); std::string bname("");
std::string sname(""); std::string sname("");
std::string type(""); std::string type("");
std::string rotation("no");
OhmmsAttributeSet aAttrib; OhmmsAttributeSet aAttrib;
aAttrib.add(bname, "basisset"); aAttrib.add(bname, "basisset");
aAttrib.add(sname, "name"); aAttrib.add(sname, "name");
aAttrib.add(type, "type"); aAttrib.add(type, "type");
aAttrib.add(rotation, "optimize");
//aAttrib.put(rcur); //aAttrib.put(rcur);
aAttrib.put(cur); aAttrib.put(cur);
@ -279,7 +285,31 @@ SPOSet* SPOSetBuilderFactory::createSPOSet(xmlNodePtr cur)
if (bb) if (bb)
{ {
app_log() << " Building SPOSet '" << sname << "' with '" << bname << "' basis set." << std::endl; app_log() << " Building SPOSet '" << sname << "' with '" << bname << "' basis set." << std::endl;
return bb->createSPOSet(cur); SPOSet* spo = bb->createSPOSet(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 RotatedSPOs(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;
spo->objectName = sname;
#endif
}
return spo;
} }
else else
{ {

View File

@ -529,11 +529,6 @@ bool LCAOrbitalBuilder::loadMO(LCAOrbitalSet& spo, xmlNodePtr cur)
{ {
coeff_ptr = cur; coeff_ptr = cur;
} }
else if (cname == "opt_vars")
{
spo.params_supplied = true;
putContent(spo.params, cur);
}
cur = cur->next; cur = cur->next;
} }
if (coeff_ptr == NULL) if (coeff_ptr == NULL)
@ -582,8 +577,6 @@ bool LCAOrbitalBuilder::loadMO(LCAOrbitalSet& spo, xmlNodePtr cur)
app_log() << *spo.C << std::endl; app_log() << *spo.C << std::endl;
} }
//init_LCOrbitalSetOpt(orbital_mix_magnitude);
return success; return success;
} }

View File

@ -17,7 +17,7 @@
namespace qmcplusplus namespace qmcplusplus
{ {
LCAOrbitalSet::LCAOrbitalSet(basis_type* bs, bool optimize) 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) if (bs != nullptr)
setBasisSet(bs); setBasisSet(bs);
@ -70,7 +70,9 @@ void LCAOrbitalSet::evaluate(const ParticleSet& P, int iat, ValueVector_t& psi)
{ {
Vector<ValueType> vTemp(Temp.data(0), BasisSetSize); Vector<ValueType> vTemp(Temp.data(0), BasisSetSize);
myBasisSet->evaluateV(P, iat, vTemp.data()); 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, GradVector_t& dpsi,
ValueVector_t& d2psi) const 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 gx = temp.data(1);
const ValueType* restrict gy = temp.data(2); const ValueType* restrict gy = temp.data(2);
const ValueType* restrict gz = temp.data(3); 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][0] = gx[j];
dpsi[j][1] = gy[j]; dpsi[j][1] = gy[j];
dpsi[j][2] = gz[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, 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, GradVector_t& dpsi,
HessVector_t& d2psi) const 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 gx = temp.data(1);
const ValueType* restrict gy = temp.data(2); const ValueType* restrict gy = temp.data(2);
const ValueType* restrict gz = temp.data(3); 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 hyz = temp.data(8);
const ValueType* restrict hzz = temp.data(9); 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][0] = gx[j];
dpsi[j][1] = gy[j]; dpsi[j][1] = gy[j];
@ -142,7 +146,8 @@ inline void LCAOrbitalSet::evaluate_vghgh_impl(const vghgh_type& temp,
HessMatrix_t& d2psi, HessMatrix_t& d2psi,
GGGMatrix_t& dghpsi) const 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 gx = temp.data(1);
const ValueType* restrict gy = temp.data(2); const ValueType* restrict gy = temp.data(2);
const ValueType* restrict gz = temp.data(3); 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_yzz = temp.data(18);
const ValueType* restrict gh_zzz = temp.data(19); 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][0] = gx[j];
dpsi[i][j][1] = gy[j]; dpsi[i][j][1] = gy[j];
@ -214,7 +219,8 @@ inline void LCAOrbitalSet::evaluate_vghgh_impl(const vghgh_type& temp,
HessVector_t& d2psi, HessVector_t& d2psi,
GGGVector_t& dghpsi) const 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 gx = temp.data(1);
const ValueType* restrict gy = temp.data(2); const ValueType* restrict gy = temp.data(2);
const ValueType* restrict gz = temp.data(3); 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_yzz = temp.data(18);
const ValueType* restrict gh_zzz = temp.data(19); 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][0] = gx[j];
dpsi[j][1] = gy[j]; dpsi[j][1] = gy[j];
@ -293,7 +299,9 @@ void LCAOrbitalSet::evaluate(const ParticleSet& P,
evaluate_vgl_impl(Temp, psi, dpsi, d2psi); evaluate_vgl_impl(Temp, psi, dpsi, d2psi);
else 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); evaluate_vgl_impl(Tempv, psi, dpsi, d2psi);
} }
} }
@ -327,7 +335,9 @@ void LCAOrbitalSet::evaluate(const ParticleSet& P,
evaluate_vgh_impl(Temph, psi, dpsi, dhpsi); evaluate_vgh_impl(Temph, psi, dpsi, dhpsi);
else 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); 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); evaluate_vghgh_impl(Tempgh, psi, dpsi, dhpsi, dghpsi);
else 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); 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, GradMatrix_t& dlogdet,
ValueMatrix_t& d2logdet) const 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 gx = temp.data(1);
const ValueType* restrict gy = temp.data(2); const ValueType* restrict gy = temp.data(2);
const ValueType* restrict gz = temp.data(3); 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][0] = gx[j];
dlogdet[i][j][1] = gy[j]; dlogdet[i][j][1] = gy[j];
dlogdet[i][j][2] = gz[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, 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, GradMatrix_t& dpsi,
HessMatrix_t& d2psi) const 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 gx = temp.data(1);
const ValueType* restrict gy = temp.data(2); const ValueType* restrict gy = temp.data(2);
const ValueType* restrict gz = temp.data(3); 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 hyz = temp.data(8);
const ValueType* restrict hzz = temp.data(9); 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][0] = gx[j];
dpsi[i][j][1] = gy[j]; dpsi[i][j][1] = gy[j];
@ -490,10 +504,12 @@ void LCAOrbitalSet::evaluate_notranspose(const ParticleSet& P,
} }
else 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++) for (size_t i = 0, iat = first; iat < last; i++, iat++)
{ {
myBasisSet->evaluateVGL(P, iat, Temp); 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); evaluate_vgl_impl(Tempv, i, logdet, dlogdet, d2logdet);
} }
} }
@ -516,10 +532,12 @@ void LCAOrbitalSet::evaluate_notranspose(const ParticleSet& P,
} }
else 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++) for (size_t i = 0, iat = first; iat < last; i++, iat++)
{ {
myBasisSet->evaluateVGH(P, iat, Temph); 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); evaluate_vgh_impl(Temphv, i, logdet, dlogdet, grad_grad_logdet);
} }
} }
@ -543,10 +561,12 @@ void LCAOrbitalSet::evaluate_notranspose(const ParticleSet& P,
} }
else 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++) for (size_t i = 0, iat = first; iat < last; i++, iat++)
{ {
myBasisSet->evaluateVGHGH(P, iat, Tempgh); 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); evaluate_vghgh_impl(Tempghv, i, logdet, dlogdet, grad_grad_logdet, grad_grad_grad_logdet);
} }
} }
@ -606,720 +626,25 @@ void LCAOrbitalSet::evaluateThirdDeriv(const ParticleSet& P, int first, int last
APP_ABORT("LCAOrbitalSet::evaluateThirdDeriv(P,istart,istop,ggg_logdet) not implemented\n"); APP_ABORT("LCAOrbitalSet::evaluateThirdDeriv(P,istart,istop,ggg_logdet) not implemented\n");
} }
void LCAOrbitalSet::buildOptVariables(const std::vector<std::pair<int, int>>& rotations) void LCAOrbitalSet::applyRotation(const ValueMatrix_t& rot_mat, bool use_stored_copy)
{ {
#if !defined(QMC_COMPLEX) if (!use_stored_copy) C_copy = *C;
const size_t nmo = OrbitalSetSize; //gemm is out-of-place
const size_t nb = BasisSetSize; BLAS::gemm('N', 'T', BasisSetSize, OrbitalSetSize, OrbitalSetSize, RealType(1.0), C_copy.data(),
m_init_B = *C; BasisSetSize, rot_mat.data(), OrbitalSetSize, RealType(0.0), C->data(), BasisSetSize);
// create active rotations /* debugging code
m_act_rot_inds = rotations; app_log() << "PRINTING MO COEFFICIENTS AFTER ROTATION " << objectName << std::endl;
for (int j = 0; j < OrbitalSetSize; j++)
// This will add the orbital rotation parameters to myVars for (int i = 0; i < BasisSetSize; i++)
// 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]); 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;
} }
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<RealType> 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<ValueType>& dlogpsi,
std::vector<ValueType>& dhpsioverpsi,
const ValueType& psiCurrent,
const std::vector<ValueType>& Coeff,
const std::vector<size_t>& C2node_up,
const std::vector<size_t>& 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<int>& detData_up,
const size_t N1,
const size_t N2,
const size_t NP1,
const size_t NP2,
const std::vector<std::vector<int>>& 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 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<RealType>& 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<std::complex<RealType>> mat_h(n * n, 0);
std::vector<RealType> eval(n, 0);
std::vector<std::complex<RealType>> work(2 * n, 0);
std::vector<RealType> rwork(3 * n, 0);
std::vector<std::complex<RealType>> mat_d(n * n, 0);
std::vector<std::complex<RealType>> 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<RealType>(0, -1.0 * mat[j][i]);
mat_h[j + n * i] = std::complex<RealType>(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<RealType>(0.0, eval[i])) : std::complex<RealType>(0.0, 0.0);
}
}
// perform matrix multiplication
// assume row major
BLAS::gemm('N', 'C', n, n, n, std::complex<RealType>(1.0, 0), &mat_d.at(0), n, &mat_h.at(0), n,
std::complex<RealType>(0.0, 0.0), &mat_t.at(0), n);
BLAS::gemm('N', 'N', n, n, n, std::complex<RealType>(1.0, 0), &mat_h.at(0), n, &mat_t.at(0), n,
std::complex<RealType>(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<ValueType>& dlogpsi,
std::vector<ValueType>& 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<RealType>& Coeff,
const std::vector<size_t>& C2node_up,
const std::vector<size_t>& 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<int>& detData_up,
const size_t N1,
const size_t N2,
const size_t NP1,
const size_t NP2,
const std::vector<std::vector<int>>& 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<RealType> 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<ValueType> WS;
Vector<IndexType> 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 } // namespace qmcplusplus

View File

@ -40,12 +40,8 @@ public:
IndexType BasisSetSize; IndexType BasisSetSize;
/// pointer to matrix containing the coefficients /// pointer to matrix containing the coefficients
std::shared_ptr<ValueMatrix_t> C; std::shared_ptr<ValueMatrix_t> C;
/// Scratch space for the initial coefficents before the rotation is applied /// a copy of the original C before orbital rotation is applied;
ValueMatrix_t m_init_B; ValueMatrix_t C_copy;
/// true if SPO parameters (orbital rotation parameters) have been supplied by input
bool params_supplied;
/// list of supplied orbital rotation parameters
std::vector<RealType> params;
///true if C is an identity matrix ///true if C is an identity matrix
bool Identity; bool Identity;
@ -68,8 +64,6 @@ public:
//Nbasis x [1(value)+3(gradient)+6(hessian)+10(grad_hessian)] //Nbasis x [1(value)+3(gradient)+6(hessian)+10(grad_hessian)]
vghgh_type Tempghv; vghgh_type Tempghv;
//vector that contains active orbital rotation parameter indices
std::vector<std::pair<int, int>> m_act_rot_inds;
/** constructor /** constructor
* @param bs pointer to the BasisSet * @param bs pointer to the BasisSet
*/ */
@ -79,64 +73,24 @@ public:
SPOSet* makeClone() const; SPOSet* makeClone() const;
/// create optimizable orbital rotation parameters void storeParamsBeforeRotation() { C_copy = *C; }
void buildOptVariables(const std::vector<std::pair<int, int>>& rotations);
void evaluateDerivatives(ParticleSet& P, void applyRotation(const ValueMatrix_t& rot_mat, bool use_stored_copy);
const opt_variables_type& optvars,
std::vector<ValueType>& dlogpsi,
std::vector<ValueType>& dhpsioverpsi,
const ValueType& psiCurrent,
const std::vector<ValueType>& Coeff,
const std::vector<size_t>& C2node_up,
const std::vector<size_t>& 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<int>& detData_up,
const size_t N1,
const size_t N2,
const size_t NP1,
const size_t NP2,
const std::vector<std::vector<int>>& lookup_tbl);
void checkInVariables(opt_variables_type& active) void checkInVariables(opt_variables_type& active)
{ {
if (Optimizable) APP_ABORT("LCAOrbitalSet should not call checkInVariables");
if (myVars.size())
active.insertFrom(myVars);
} }
void checkOutVariables(const opt_variables_type& active) void checkOutVariables(const opt_variables_type& active)
{ {
if (Optimizable) APP_ABORT("LCAOrbitalSet should not call checkOutVariables");
myVars.getIndex(active);
} }
///reset ///reset
void resetParameters(const opt_variables_type& active) void resetParameters(const opt_variables_type& active)
{ {
#if !defined(QMC_COMPLEX) APP_ABORT("LCAOrbitalSet should not call resetParameters");
if (Optimizable)
{
std::vector<RealType> 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
} }
///reset the target particleset ///reset the target particleset
@ -327,44 +281,6 @@ private:
GradMatrix_t& dllogdet) const; GradMatrix_t& dllogdet) const;
#if !defined(QMC_COMPLEX)
//function to perform orbital rotations
void apply_rotation(const std::vector<RealType>& 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<ValueType>& dlogpsi,
std::vector<ValueType>& 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<RealType>& Coeff,
const std::vector<size_t>& C2node_up,
const std::vector<size_t>& 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<int>& detData_up,
const size_t N1,
const size_t N2,
const size_t NP1,
const size_t NP2,
const std::vector<std::vector<int>>& lookup_tbl);
#endif
}; };
} // namespace qmcplusplus } // namespace qmcplusplus
#endif #endif

View File

@ -543,7 +543,7 @@ void test_HCN(bool transform)
SPOSet::HessMatrix_t diongradpsi(elec.R.size(), sposet->getOrbitalSetSize()); SPOSet::HessMatrix_t diongradpsi(elec.R.size(), sposet->getOrbitalSetSize());
SPOSet::GradMatrix_t dionlaplpsi(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 =================== //============== Ion 0 Component 0 ===================
REQUIRE( dionpsi[0][0][0] == Approx( 0.0453112082) ); REQUIRE( dionpsi[0][0][0] == Approx( 0.0453112082) );

View File

@ -1,21 +1,21 @@
IF (NOT QMC_CUDA) 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 # 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 LIST(APPEND H2_OPT_SCALARS "totenergy" "-1.124563 0.00084") # total energy
IF(BUILD_LMYENGINE_INTERFACE) QMC_RUN_AND_CHECK(short-H2-orb-opt
QMC_RUN_AND_CHECK(short-H2-orb-opt "${CMAKE_SOURCE_DIR}/tests/molecules/H2_ae"
"${CMAKE_SOURCE_DIR}/tests/molecules/H2_ae" H2
H2 h2_orb_opt.xml
h2_orb_opt.xml 16 1
16 1 ${MP_SUCCESS}
${MP_SUCCESS} 10 H2_OPT_SCALARS # Final VMC step
10 H2_OPT_SCALARS # Final VMC step TRUE)
TRUE)
# #
# H2 starting from unoptimized CIS coefficients and orbital # H2 starting from unoptimized CIS coefficients and orbital
@ -33,12 +33,12 @@ IF (NOT QMC_CUDA)
6 H2_FDLR_SCALARS # Final VMC step 6 H2_FDLR_SCALARS # Final VMC step
TRUE) TRUE)
ELSE() 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) ENDIF(BUILD_LMYENGINE_INTERFACE)
ELSE() 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() ENDIF()
ELSE() 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() ENDIF()

View File

@ -34,18 +34,9 @@
</atomicBasisSet> </atomicBasisSet>
</basisset> </basisset>
<slaterdeterminant optimize="yes"> <slaterdeterminant>
<determinant id="det_up" sposet="spo-up"> <determinant id="det_up" sposet="spo-up"/>
<opt_vars size="27"> <determinant id="det_down" sposet="spo-dn"/>
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
</opt_vars>
</determinant>
<determinant id="det_down" sposet="spo-dn">
<opt_vars size="27">
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
</opt_vars>
</determinant>
</slaterdeterminant> </slaterdeterminant>
<sposet basisset="LCAOBSet" name="spo-up" size="28" optimize="yes"> <sposet basisset="LCAOBSet" name="spo-up" size="28" optimize="yes">

View File

@ -79,20 +79,40 @@ IF (NOT QMC_CUDA)
${MP_SUCCESS} ${MP_SUCCESS}
5 H4_OPT_SCALARS # OPT step 5 5 H4_OPT_SCALARS # OPT step 5
) )
IF(ENABLE_SOA)
# #
# H4 starting from perturbed orbitals, using optimizable determinants, and the adaptive linear method # H4 starting from perturbed orbitals, using optimizable determinants, and the adaptive linear method
# #
LIST(APPEND H4_ORB_OPT_SCALARS "totenergy" "-2.0889 0.001") # total energy 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 QMC_RUN_AND_CHECK(short-H4-orb-opt
"${CMAKE_SOURCE_DIR}/tests/molecules/H4_ae" "${CMAKE_SOURCE_DIR}/tests/molecules/H4_ae"
H4 H4
h4_orb_opt.xml H4_orb_opt.xml
16 1 16 1
${MP_SUCCESS} ${MP_SUCCESS}
14 H4_ORB_OPT_SCALARS # Final VMC step 14 H4_ORB_OPT_SCALARS # Final VMC step
TRUE) TRUE)
QMC_RUN_AND_CHECK(short-H4-orb-opt
"${CMAKE_SOURCE_DIR}/tests/molecules/H4_ae"
H4
H4_orb_opt.xml
1 16
${MP_SUCCESS}
14 H4_ORB_OPT_SCALARS # Final VMC step
TRUE)
# #
# H4 starting from converged wave function, doing a quick adaptive linear method run (using the same # H4 starting from converged wave function, doing a quick adaptive linear method run (using the same
# spo set for both spin-up and spin-down determinants) and then doing a DMC calculation # spo set for both spin-up and spin-down determinants) and then doing a DMC calculation
@ -102,7 +122,7 @@ IF (NOT QMC_CUDA)
QMC_RUN_AND_CHECK(short-H4-orb-opt-dmc QMC_RUN_AND_CHECK(short-H4-orb-opt-dmc
"${CMAKE_SOURCE_DIR}/tests/molecules/H4_ae" "${CMAKE_SOURCE_DIR}/tests/molecules/H4_ae"
H4 H4
h4_orb_opt_dmc.xml H4_orb_opt_dmc.xml
16 1 16 1
${MP_SUCCESS} ${MP_SUCCESS}
3 H4_ORB_OPT_DMC_SCALARS # Test the DMC results 3 H4_ORB_OPT_DMC_SCALARS # Test the DMC results
@ -111,7 +131,7 @@ IF (NOT QMC_CUDA)
QMC_RUN_AND_CHECK(short-H4-orb-opt-dmc QMC_RUN_AND_CHECK(short-H4-orb-opt-dmc
"${CMAKE_SOURCE_DIR}/tests/molecules/H4_ae" "${CMAKE_SOURCE_DIR}/tests/molecules/H4_ae"
H4 H4
h4_orb_opt_dmc.xml H4_orb_opt_dmc.xml
1 16 1 16
${MP_SUCCESS} ${MP_SUCCESS}
3 H4_ORB_OPT_DMC_SCALARS # Test the DMC results 3 H4_ORB_OPT_DMC_SCALARS # Test the DMC results
@ -129,6 +149,9 @@ IF (NOT QMC_CUDA)
${MP_SUCCESS} ${MP_SUCCESS}
8 H4_FDLR_SCALARS # Final VMC step 8 H4_FDLR_SCALARS # Final VMC step
TRUE) 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 LIST(APPEND H4_CJS_SCALARS "totenergy" "-2.0438 0.0045") # total energy

View File

@ -1,9 +1,9 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<qmcsystem> <qmcsystem>
<wavefunction id="psi0" target="e"> <wavefunction name="psi0" target="e">
<determinantset name="LCAOBSet" type="MolecularOrbital" transform="yes" source="ion0"> <determinantset type="MolecularOrbital" name="LCAOBSet" source="ion0" transform="yes">
<basisset name="LCAOBSet"> <basisset name="LCAOBSet">
<atomicBasisSet name="Gaussian-G2" angular="cartesian" type="Gaussian" elementType="H" normalized="no"> <atomicBasisSet name="Gaussian" angular="cartesian" type="Gaussian" elementType="H" normalized="no">
<grid type="log" ri="1.e-6" rf="1.e2" npts="1001"/> <grid type="log" ri="1.e-6" rf="1.e2" npts="1001"/>
<basisGroup rid="H00" n="0" l="0" type="Gaussian"> <basisGroup rid="H00" n="0" l="0" type="Gaussian">
<radfunc exponent="3.425250900000e+00" contraction="1.543289672950e-01"/> <radfunc exponent="3.425250900000e+00" contraction="1.543289672950e-01"/>
@ -12,41 +12,35 @@
</basisGroup> </basisGroup>
</atomicBasisSet> </atomicBasisSet>
</basisset> </basisset>
<slaterdeterminant optimize="yes">
<determinant id="det_up" sposet="spo-up">
<opt_vars size="4">
0.2 0.0 0.0 0.0
</opt_vars>
</determinant>
<determinant id="det_down" sposet="spo-dn">
<opt_vars size="4">
0.2 0.0 0.0 0.0
</opt_vars>
</determinant>
</slaterdeterminant>
<sposet basisset="LCAOBSet" name="spo-up" size="4" optimize="yes"> <sposet basisset="LCAOBSet" name="spo-up" size="4" optimize="yes">
<occupation mode="ground"/> <occupation mode="ground"/>
<coefficient size="4" id="updetC"> <coefficient size="4" id="detC">
5.04668000000000e-01 4.50114000000000e-01 3.58423000000000e-01 1.26449000000000e-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 -2.40452000000000e-01 -3.20413000000000e-01 4.66777000000000e-01 7.03549000000000e-01
8.80080000000000e-02 -5.04842000000000e-01 8.07522000000000e-01 -7.19301000000000e-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 1.03323500000000e+00 -8.77213000000000e-01 -3.90492000000000e-01 2.12318000000000e-01
</coefficient> </coefficient>
<opt_vars size="4">
0.2 0.0 0.0 0.0
</opt_vars>
</sposet> </sposet>
<sposet basisset="LCAOBSet" name="spo-dn" size="4" optimize="yes"> <sposet basisset="LCAOBSet" name="spo-dn" size="4" optimize="yes">
<occupation mode="ground"/> <occupation mode="ground"/>
<coefficient size="4" id="downdetC"> <coefficient size="4" id="detC">
5.04668000000000e-01 4.50114000000000e-01 3.58423000000000e-01 1.26449000000000e-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 -2.40452000000000e-01 -3.20413000000000e-01 4.66777000000000e-01 7.03549000000000e-01
8.80080000000000e-02 -5.04842000000000e-01 8.07522000000000e-01 -7.19301000000000e-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 1.03323500000000e+00 -8.77213000000000e-01 -3.90492000000000e-01 2.12318000000000e-01
</coefficient> </coefficient>
<opt_vars size="4">
0.2 0.0 0.0 0.0
</opt_vars>
</sposet> </sposet>
<slaterdeterminant>
<determinant id="det_up" sposet="spo-up"/>
<determinant id="det_down" sposet="spo-dn"/>
</slaterdeterminant>
</determinantset> </determinantset>
<jastrow name="J2" type="Two-Body" function="Bspline" print="yes"> <jastrow name="J2" type="Two-Body" function="Bspline" print="yes">
<correlation rcut="2" size="10" speciesA="u" speciesB="u"> <correlation rcut="2" size="10" speciesA="u" speciesB="u">
<coefficients id="uu" type="Array" optimize="no"> 0.04661440939 0.0555644703 0.1286335481 0.1077457768 0.0811381484 0.0626555805 0.0436904683 0.02811397453 0.01572772511 0.006258753264</coefficients> <coefficients id="uu" type="Array" optimize="no"> 0.04661440939 0.0555644703 0.1286335481 0.1077457768 0.0811381484 0.0626555805 0.0436904683 0.02811397453 0.01572772511 0.006258753264</coefficients>
@ -55,12 +49,10 @@
<coefficients id="ud" type="Array" optimize="no"> 0.4465508582 0.3603308616 0.2893897103 0.2269436006 0.1717850082 0.1250275368 0.08538908372 0.05318480503 0.02806504868 0.01035981902</coefficients> <coefficients id="ud" type="Array" optimize="no"> 0.4465508582 0.3603308616 0.2893897103 0.2269436006 0.1717850082 0.1250275368 0.08538908372 0.05318480503 0.02806504868 0.01035981902</coefficients>
</correlation> </correlation>
</jastrow> </jastrow>
<jastrow name="J1" type="One-Body" function="Bspline" source="ion0" print="yes"> <jastrow name="J1" type="One-Body" function="Bspline" source="ion0" print="yes">
<correlation rcut="2" size="10" cusp="1" elementType="H"> <correlation rcut="2" size="10" cusp="1" elementType="H">
<coefficients id="eH" type="Array" optimize="no"> 0.0167926566 0.1405038909 0.1611311956 0.1198446618 0.06764720157 0.03602453588 0.02460661286 0.01952889643 0.01300432967 0.005621933949</coefficients> <coefficients id="eH" type="Array" optimize="no"> 0.0167926566 0.1405038909 0.1611311956 0.1198446618 0.06764720157 0.03602453588 0.02460661286 0.01952889643 0.01300432967 0.005621933949</coefficients>
</correlation> </correlation>
</jastrow> </jastrow>
</wavefunction> </wavefunction>
</qmcsystem> </qmcsystem>

View File

@ -0,0 +1,46 @@
<?xml version="1.0"?>
<qmcsystem>
<wavefunction name="psi0" target="e">
<determinantset type="MolecularOrbital" name="LCAOBSet" source="ion0" transform="yes">
<basisset name="LCAOBSet">
<atomicBasisSet name="Gaussian" angular="cartesian" type="Gaussian" elementType="H" normalized="no">
<grid type="log" ri="1.e-6" rf="1.e2" npts="1001"/>
<basisGroup rid="H00" n="0" l="0" type="Gaussian">
<radfunc exponent="3.425250900000e+00" contraction="1.543289672950e-01"/>
<radfunc exponent="6.239137000000e-01" contraction="5.353281422820e-01"/>
<radfunc exponent="1.688554000000e-01" contraction="4.446345421850e-01"/>
</basisGroup>
</atomicBasisSet>
</basisset>
<sposet basisset="LCAOBSet" name="spo" size="4" optimize="yes">
<occupation mode="ground"/>
<coefficient size="4" id="detC">
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
</coefficient>
<opt_vars size="4">
0.2 0.0 0.0 0.0
</opt_vars>
</sposet>
<slaterdeterminant>
<determinant id="det_up" sposet="spo"/>
<determinant id="det_down" sposet="spo"/>
</slaterdeterminant>
</determinantset>
<jastrow name="J2" type="Two-Body" function="Bspline" print="yes">
<correlation rcut="2" size="10" speciesA="u" speciesB="u">
<coefficients id="uu" type="Array" optimize="no"> 0.04661440939 0.0555644703 0.1286335481 0.1077457768 0.0811381484 0.0626555805 0.0436904683 0.02811397453 0.01572772511 0.006258753264</coefficients>
</correlation>
<correlation rcut="2" size="10" speciesA="u" speciesB="d">
<coefficients id="ud" type="Array" optimize="no"> 0.4465508582 0.3603308616 0.2893897103 0.2269436006 0.1717850082 0.1250275368 0.08538908372 0.05318480503 0.02806504868 0.01035981902</coefficients>
</correlation>
</jastrow>
<jastrow name="J1" type="One-Body" function="Bspline" source="ion0" print="yes">
<correlation rcut="2" size="10" cusp="1" elementType="H">
<coefficients id="eH" type="Array" optimize="no"> 0.0167926566 0.1405038909 0.1611311956 0.1198446618 0.06764720157 0.03602453588 0.02460661286 0.01952889643 0.01300432967 0.005621933949</coefficients>
</correlation>
</jastrow>
</wavefunction>
</qmcsystem>

View File

@ -12,27 +12,6 @@
</basisGroup> </basisGroup>
</atomicBasisSet> </atomicBasisSet>
</basisset> </basisset>
<slaterdeterminant optimize="yes">
<determinant id="det_up" sposet="spo">
<opt_vars size="4">
-6.2352e-02
1.5072e-02
8.3825e-02
-2.4339e-02
</opt_vars>
</determinant>
<determinant id="det_down" sposet="spo">
<opt_vars size="4">
-6.2352e-02
1.5072e-02
8.3825e-02
-2.4339e-02
</opt_vars>
</determinant>
</slaterdeterminant>
<sposet basisset="LCAOBSet" name="spo" size="4" optimize="yes"> <sposet basisset="LCAOBSet" name="spo" size="4" optimize="yes">
<occupation mode="ground"/> <occupation mode="ground"/>
<coefficient size="4" id="detC"> <coefficient size="4" id="detC">
@ -40,54 +19,35 @@
-2.40452000000000e-01 -3.20413000000000e-01 4.66777000000000e-01 7.03549000000000e-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 8.80080000000000e-02 -5.04842000000000e-01 8.07522000000000e-01 -7.19301000000000e-01
1.03323500000000e+00 -8.77213000000000e-01 -3.90492000000000e-01 2.12318000000000e-01 1.03323500000000e+00 -8.77213000000000e-01 -3.90492000000000e-01 2.12318000000000e-01
</coefficient> </coefficient>
<opt_vars size="4">
-6.2352e-02 1.5072e-02 8.3825e-02 -2.4339e-02
</opt_vars>
</sposet> </sposet>
<slaterdeterminant>
<determinant id="det_up" sposet="spo"/>
<determinant id="det_down" sposet="spo"/>
</slaterdeterminant>
</determinantset> </determinantset>
<jastrow name="J2" type="Two-Body" function="Bspline" print="yes"> <jastrow name="J2" type="Two-Body" function="Bspline" print="yes">
<correlation rcut="2" size="10" speciesA="u" speciesB="u"> <correlation rcut="2" size="10" speciesA="u" speciesB="u">
<coefficients id="uu" type="Array"> <coefficients id="uu" type="Array">
2.2381e-02 2.2381e-02 1.5167e-01 1.0912e-01 1.0807e-01 8.1643e-02
1.5167e-01 6.1254e-02 4.3210e-02 2.7384e-02 1.5194e-02 6.3094e-03
1.0912e-01
1.0807e-01
8.1643e-02
6.1254e-02
4.3210e-02
2.7384e-02
1.5194e-02
6.3094e-03
</coefficients> </coefficients>
</correlation> </correlation>
<correlation rcut="2" size="10" speciesA="u" speciesB="d"> <correlation rcut="2" size="10" speciesA="u" speciesB="d">
<coefficients id="ud" type="Array"> <coefficients id="ud" type="Array">
4.7842e-01 4.7842e-01 3.9434e-01 3.2027e-01 2.5477e-01 1.9602e-01
3.9434e-01 1.4543e-01 1.0142e-01 6.4350e-02 3.4675e-02 1.3348e-02
3.2027e-01
2.5477e-01
1.9602e-01
1.4543e-01
1.0142e-01
6.4350e-02
3.4675e-02
1.3348e-02
</coefficients> </coefficients>
</correlation> </correlation>
</jastrow> </jastrow>
<jastrow name="J1" type="One-Body" function="Bspline" source="ion0" print="yes"> <jastrow name="J1" type="One-Body" function="Bspline" source="ion0" print="yes">
<correlation rcut="2" size="10" cusp="1" elementType="H"> <correlation rcut="2" size="10" cusp="1" elementType="H">
<coefficients id="eH" type="Array"> <coefficients id="eH" type="Array">
2.5151e-02 2.5151e-02 1.4825e-01 1.6955e-01 1.2869e-01 7.6468e-02
1.4825e-01 4.4240e-02 3.1098e-02 2.3827e-02 1.5289e-02 6.2995e-03
1.6955e-01
1.2869e-01
7.6468e-02
4.4240e-02
3.1098e-02
2.3827e-02
1.5289e-02
6.2995e-03
</coefficients> </coefficients>
</correlation> </correlation>
</jastrow> </jastrow>

View File

@ -0,0 +1,39 @@
<?xml version="1.0"?>
<simulation>
<project id="H4" series="0"/>
<random seed="281"/>
<!-- input from gaussian converter -->
<include href="H4.ptcl.xml"/>
<include href="H4.wfs_2_RHF.xml"/>
<hamiltonian name="h0" type="generic" target="e">
<pairpot name="ElecElec" type="coulomb" source="e" target="e"/>
<pairpot name="IonElec" type="coulomb" source="ion0"/>
<constant name="IonIon" type="coulomb" source="ion0" target="ion0"/>
</hamiltonian>
<loop max="15">
<qmc method="linear" move="pbyp" checkpoint="-1" gpu="no">
<parameter name="walkers"> 1 </parameter>
<parameter name="blocks"> 256 </parameter>
<parameter name="warmupsteps"> 500 </parameter>
<parameter name="steps"> 1 </parameter>
<parameter name="substeps"> 10 </parameter>
<parameter name="timestep"> 0.05 </parameter>
<parameter name="samples"> 64000 </parameter>
<parameter name="useDrift"> yes </parameter>
<parameter name="GEVMethod"> mixed </parameter>
<parameter name="bigchange">15.0</parameter>
<estimator name="LocalEnergy" hdf5="no"/>
<parameter name="usebuffer"> no </parameter>
<parameter name="nonlocalpp"> yes </parameter>
<parameter name="MinMethod">adaptive</parameter>
<parameter name="shift_i"> 1.0 </parameter>
<parameter name="shift_s"> 1.0 </parameter>
<parameter name="alloweddifference"> 1.0e-4 </parameter>
<parameter name="max_relative_cost_change"> 100.0 </parameter>
<parameter name="max_param_change"> 3.0e-1 </parameter>
<parameter name="targetExcited"> yes </parameter>
<parameter name="omega"> -3.2 </parameter>
</qmc>
</loop>
</simulation>

View File

@ -101,7 +101,7 @@
<parameter name="timestep"> 0.005 </parameter> <parameter name="timestep"> 0.005 </parameter>
<parameter name="steps"> 100 </parameter> <parameter name="steps"> 100 </parameter>
<parameter name="blocks"> 25 </parameter> <parameter name="blocks"> 25 </parameter>
<parameter name="nonlocalmoves"> no </parameter> <parameter name="nonlocalmoves"> yes </parameter>
</qmc> </qmc>
</simulation> </simulation>