diff --git a/docs/methods.rst b/docs/methods.rst index 25c5c49650..0067175873 100644 --- a/docs/methods.rst +++ b/docs/methods.rst @@ -1904,4 +1904,251 @@ declaration to ensure correct sampling: a new all-electron configuration, at which point the action is computed and the move is either accepted or rejected. + + +.. _walker_logging + +Walker Data Logging +=================== + +Detailed per-walker information can be written to HDF5 files for VMC or DMC by +including the XML element. This includes the LocalEnergy and +its components for each walker from each MC step. By default, more detailed +particle-level information (e.g. electron coordinates) is also written for the +lowest, highest, and median energy walkers at each MC step (modest disk usage). +Optionally, particle-level information can also be written for all walkers, +potentially requiring a huge amount of disk space. + +**Input specification** + +The default walker data logging functionality is enabled by including the + XML element (once) just before the QMC driver sections, +for example: + +:: + + + + 256 + 100 + 200 + 10 + 3 + 0.3 + yes + + + 256 + 40 + 800 + 20 + 0.01 + + + + +Optional XML attributes enable finer control over the behavior: + +.. table:: + + +------------------+--------------+--------------+-------------+----------------------------------------------------+ + | **Name** | **Datatype** | **Values** | **Default** | **Description** | + +==================+==============+==============+=============+====================================================+ + | ``step_period`` | integer | :math:`> 0` | 1 | Collect walker data every step_period MC steps | + +------------------+--------------+--------------+-------------+----------------------------------------------------+ + | ``particle`` | text | yes,no | no | Write particle data for all walkers | + +------------------+--------------+--------------+-------------+----------------------------------------------------+ + | ``quantiles`` | text | yes,no | yes | Write full data for min/max/median energy walkers | + +------------------+--------------+--------------+-------------+----------------------------------------------------+ + | ``min`` | text | yes,no | yes | Enable/disable write for min energy walker data | + +------------------+--------------+--------------+-------------+----------------------------------------------------+ + | ``max`` | text | yes,no | yes | Enable/disable write for max energy walker data | + +------------------+--------------+--------------+-------------+----------------------------------------------------+ + | ``median`` | text | yes,no | yes | Enable/disable write for median energy walker data | + +------------------+--------------+--------------+-------------+----------------------------------------------------+ + | ``verbose`` | text | yes,no | no | Write more log file information | + +------------------+--------------+--------------+-------------+----------------------------------------------------+ + + +Additional information: + +- ``step_period``: By default, data for each walker is collected every MC + step, corresponding to step_period=1. A sub-sampling of the walker + data may be obtained instead by setting step_period>1. For example, + with step_period=5, walker data is collected every 5th MC step. + +- ``particle``: This controls whether per-particle data is written to + the walker log HDF files along with scalar walker properties. These data + comprise: electron coordinates, spin coordinates (spinor runs only), + per-particle wavefunction gradients, and per-particle wavefunction + laplacian values. + +- ``quantiles``: Write out full (scalar and per-particle) data for walkers + at specific quantiles of the local energy distribution. Currently, + these quantiles are the minimum, maximum, and median. + +- ``min``: Selectively disable writing data for the minimum energy + walkers. Active only if qtiles=yes. + +- ``max``: Selectively disable writing data for the maximum energy + walkers. Active only if qtiles=yes. + +- ``median``: Selectively disable writing data for the median energy + walkers. Active only if qtiles=yes. + +- ``verbose``: If "yes", write function-call information related to + the walker logging functionality. This option is mainly intended + for developers, as it is of little use in practical runs. + + +**Output files** + +The HDF5 files created by the walker logging functionality have the extension \*.wlogs.h5. +For each VMC or DMC section, one of these files is written for every MPI rank in the run. + +For the example XML inputs shown above, QMCPACK run on 6 MPI ranks would produce (at least) +the following output data files: + +:: + + qmc.s000.scalar.dat + qmc.s000.stat.h5 + qmc.s000.p000.wlogs.h5 + qmc.s000.p001.wlogs.h5 + qmc.s000.p002.wlogs.h5 + qmc.s000.p003.wlogs.h5 + qmc.s000.p004.wlogs.h5 + qmc.s000.p005.wlogs.h5 + + qmc.s001.scalar.dat + qmc.s001.dmc.dat + qmc.s001.stat.h5 + qmc.s001.p000.wlogs.h5 + qmc.s001.p001.wlogs.h5 + qmc.s001.p002.wlogs.h5 + qmc.s001.p003.wlogs.h5 + qmc.s001.p004.wlogs.h5 + qmc.s001.p005.wlogs.h5 + + +A single wlogs.h5 file has several walker data buffers (names with underscores below): + +:: + + # scalar (int/real) data for all walkers + walker_property_int walker_property_real + + # scalar and per-particle data for min energy walkers + wmin_property_int wmin_property_real wmin_particle_real + + # scalar and per-particle data for max energy walkers + wmax_property_int wmax_property_real wmax_particle_real + + # scalar and per-particle data for median energy walkers + wmed_property_int wmed_property_real wmed_particle_real + + +Each data buffer contains packed walker data in the form of a large 2D array ("data" below): + +:: + + >h5ls qmc.s000.p000.wlogs.h5/walker_property_int + data Dataset {512000/Inf, 4} + data_layout Group + + >h5ls qmc.s000.p000.wlogs.h5/walker_property_real + data Dataset {512000/Inf, 15} + data_layout Group + + +Each row in the 2D data array/buffer contains data for a single walker at a single MC step. +In this case, 256 walkers were advanced through 200\*10=2000 steps for 512000 row entries total. + +The location of each particular walker quantity in each row is listed in "data_layout": + +:: + + >h5ls qmc.s000.p000.wlogs.h5/walker_property_int/data_layout + id Group # unique walker id + parent_id Group # id of parent (DMC branching) + step Group # MC step number + age Group # walker "age" + + >h5ls qmc.s000.p000.wlogs.h5/walker_property_real/data_layout + weight Group # statistical weight of the walker + LocalEnergy Group # the local (total) energy + Kinetic Group # kinetic energy + LocalPotential Group # full potential energy (all terms) + ElecElec Group # electron-electron energy + LocalECP Group # energy for local channel of ECP + NonLocalECP Group # energy for non-local channels of ECP + logpsi Group # log of wavefunction modulus + phase Group # wavefunction phase + dlogpsi2 Group # squared gradient of wavefunction log-modulus + dphase2 Group # squared gradient of wavefunction phase + dr_node_min Group # estimate of min distance to wfn node along any dimension + multiplicity Group # branching multiplicity (DMC only) + R2Accepted Group # average diffusion of accepted MC moves + R2Proposed Group # average diffusion of proposed MC moves + +From this we can see, e.g., that the value for the MC "step" is stored at column +index 0 in walker_property_int/data and the LocalEnergy is stored at column index 6 +in walker_property_real/data: + +:: + + >h5ls -d qmc.s000.p000.wlogs.h5/walker_property_int/data_layout/step/index_start + index_start Dataset {SCALAR} + Data: + (0) 0 + + >h5ls -d qmc.s000.p000.wlogs.h5/walker_property_real/data_layout/LocalEnergy/index_start + index_start Dataset {SCALAR} + Data: + (0) 6 + + +The per-particle data is arranged similarly: + +:: + + >h5ls -d qmc_log_dmc_legacy.s000.p000.wlogs.h5/wmin_particle_real/data_layout + R Group # electron coordinates + G Group # wavefunction gradient + L Group # wavefunction laplacian (per-particle) + + +However, more information is required in the data_layout to fully specify the location and +shape of the particle-level array data (simplified view for a run with 8 electrons and a +real-valued wavefunction): + +:: + + >h5ls -d qmc.s000.p000.wlogs.h5/wmin_particle_real/data_layout/R + index_start 0 # data starts at column index 0 + index_end 24 # data ends at column index 24 + dimension 2 # array is 2-dimensional + size 24 # array has 24 elements total + shape 8, 3, 0, 0 # array has shape 8x3 + unit_size 1 # each unit of data stored as 1 real value + + >h5ls -d qmc.s000.p000.wlogs.h5/wmin_particle_real/data_layout/G + index_start 24 # data starts at column index 24 + index_end 48 # data ends at column index 48 + dimension 2 # array is 2-dimensional + size 24 # array has 24 elements total + shape 8, 3, 0, 0 # array has shape 8x3 + unit_size 1 # data stored as single real values (2 if complex) + + >h5ls -d qmc.s000.p000.wlogs.h5/wmin_particle_real/data_layout/L + index_start 48 # data starts at column index 48 + index_end 56 # data ends at column index 56 + dimension 1 # array is 1-dimensional + size 8 # array has 8 elements total + shape 8, 0, 0, 0 # array has linear shape, length 8 + unit_size 1 # data stored as single real values (2 if complex) + + + + .. bibliography:: /bibs/methods.bib diff --git a/src/Estimators/tests/test_trace_manager.cpp b/src/Estimators/tests/test_trace_manager.cpp index aef62d4bcf..9e54a33a3c 100644 --- a/src/Estimators/tests/test_trace_manager.cpp +++ b/src/Estimators/tests/test_trace_manager.cpp @@ -4,7 +4,7 @@ // // Copyright (c) 2018 Jeongnim Kim and QMCPACK developers. // -// File developed by: Mark Dewing, mdewin@anl.gov, Argonne National Laboratory +// File developed by: Mark Dewing, mdewing@anl.gov, Argonne National Laboratory // // File created by: Mark Dewing, mdewing@anl.gov, Argonne National Laboratory ////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/QMCApp/QMCMain.cpp b/src/QMCApp/QMCMain.cpp index 85c085c0d4..96927cb22e 100644 --- a/src/QMCApp/QMCMain.cpp +++ b/src/QMCApp/QMCMain.cpp @@ -62,7 +62,8 @@ QMCMain::QMCMain(Communicate* c) psi_pool_(std::make_unique(my_project_.getRuntimeOptions(), *particle_set_pool_, myComm)), ham_pool_(std::make_unique(*particle_set_pool_, *psi_pool_, myComm)), qmc_system_(nullptr), - first_qmc_(true) + first_qmc_(true), + walker_logs_xml_(NULL) #if !defined(REMOVE_TRACEMANAGER) , traces_xml_(NULL) @@ -479,6 +480,10 @@ bool QMCMain::validateXML() traces_xml_ = cur; } #endif + else if (cname == "walkerlogs") + { + walker_logs_xml_ = cur; + } else { //everything else goes to m_qmcaction @@ -624,6 +629,7 @@ bool QMCMain::runQMC(xmlNodePtr cur, bool reuse) #if !defined(REMOVE_TRACEMANAGER) qmc_driver->putTraces(traces_xml_); #endif + qmc_driver->putWalkerLogs(walker_logs_xml_); { ScopedTimer qmc_run_timer(createGlobalTimer(qmc_driver->getEngineName(), timer_level_coarse)); Timer process_and_run; diff --git a/src/QMCApp/QMCMain.h b/src/QMCApp/QMCMain.h index 85be18eb16..ed6282d322 100644 --- a/src/QMCApp/QMCMain.h +++ b/src/QMCApp/QMCMain.h @@ -75,6 +75,9 @@ class QMCMain : public MPIObjectBase, public QMCAppBase ///xml mcwalkerset read-in elements std::vector walker_set_in_; + ///walkerlogs xml + xmlNodePtr walker_logs_xml_; + ///traces xml xmlNodePtr traces_xml_; diff --git a/src/QMCDrivers/CloneManager.cpp b/src/QMCDrivers/CloneManager.cpp index 9f5e283638..02e01f1659 100644 --- a/src/QMCDrivers/CloneManager.cpp +++ b/src/QMCDrivers/CloneManager.cpp @@ -27,6 +27,7 @@ #else using TraceManager = int; #endif +#include "WalkerLogManager.h" //comment this out to use only method to clone #define ENABLE_CLONE_PSI_AND_H @@ -86,6 +87,7 @@ CloneManager::~CloneManager() #if !defined(REMOVE_TRACEMANAGER) delete_iter(traceClones.begin(), traceClones.end()); #endif + delete_iter(wlog_collectors.begin(), wlog_collectors.end()); } void CloneManager::makeClones(MCWalkerConfiguration& w, TrialWaveFunction& psi, QMCHamiltonian& ham) diff --git a/src/QMCDrivers/CloneManager.h b/src/QMCDrivers/CloneManager.h index 0d3c86d15a..d8f41b962a 100644 --- a/src/QMCDrivers/CloneManager.h +++ b/src/QMCDrivers/CloneManager.h @@ -75,6 +75,8 @@ class CloneManager : public QMCTraits std::vector estimatorClones; ///trace managers std::vector traceClones; + ///trace collectors + std::vector wlog_collectors; //for correlated sampling. static std::vector> WPoolClones_uptr; diff --git a/src/QMCDrivers/Crowd.cpp b/src/QMCDrivers/Crowd.cpp index 2bb3aa7bc8..a00a458fa4 100644 --- a/src/QMCDrivers/Crowd.cpp +++ b/src/QMCDrivers/Crowd.cpp @@ -10,6 +10,7 @@ #include "Crowd.h" #include "QMCHamiltonians/QMCHamiltonian.h" + namespace qmcplusplus { Crowd::Crowd(EstimatorManagerNew& emb, @@ -81,8 +82,16 @@ void Crowd::startBlock(int num_steps) // VMCBatched does no nonlocal moves n_nonlocal_accept_ = 0; estimator_manager_crowd_.startBlock(num_steps); + wlog_collector_.startBlock(); } void Crowd::stopBlock() { estimator_manager_crowd_.stopBlock(); } +void Crowd::collectStepWalkerLog(int current_step) +{ + for (int iw = 0; iw < size(); ++iw) + wlog_collector_.collect(mcp_walkers_[iw], walker_elecs_[iw], walker_twfs_[iw], walker_hamiltonians_[iw], current_step); +} + + } // namespace qmcplusplus diff --git a/src/QMCDrivers/Crowd.h b/src/QMCDrivers/Crowd.h index 6de8b91195..ee468ce2b0 100644 --- a/src/QMCDrivers/Crowd.h +++ b/src/QMCDrivers/Crowd.h @@ -16,12 +16,14 @@ #include "MultiWalkerDispatchers.h" #include "DriverWalkerTypes.h" #include "Estimators/EstimatorManagerCrowd.h" +#include "WalkerLogManager.h" namespace qmcplusplus { // forward declaration class ResourceCollection; class EstimatorManagerNew; +class WalkerLogCollector; /** Driver synchronized step context * @@ -83,6 +85,9 @@ class Crowd estimator_manager_crowd_.accumulate(mcp_walkers_, walker_elecs_, walker_twfs_, walker_hamiltonians_, rng); } + /// Collect walker log data + void collectStepWalkerLog(int current_step); + void setRNGForHamiltonian(RandomBase& rng); auto beginWalkers() { return mcp_walkers_.begin(); } @@ -98,6 +103,7 @@ class Crowd const RefVector& get_walker_hamiltonians() const { return walker_hamiltonians_; } const EstimatorManagerCrowd& get_estimator_manager_crowd() const { return estimator_manager_crowd_; } + WalkerLogCollector& getWalkerLogCollector() { return wlog_collector_; } DriverWalkerResourceCollection& getSharedResource() { return driverwalker_resource_collection_; } @@ -129,6 +135,8 @@ class Crowd DriverWalkerResourceCollection driverwalker_resource_collection_; /// per crowd estimator manager EstimatorManagerCrowd estimator_manager_crowd_; + // collector for walker logs + WalkerLogCollector wlog_collector_; /** @name Step State * diff --git a/src/QMCDrivers/DMC/DMC.cpp b/src/QMCDrivers/DMC/DMC.cpp index 8592e073a6..46e705550e 100644 --- a/src/QMCDrivers/DMC/DMC.cpp +++ b/src/QMCDrivers/DMC/DMC.cpp @@ -36,6 +36,7 @@ #else using TraceManager = int; #endif +#include "WalkerLogManager.h" namespace qmcplusplus { @@ -93,6 +94,7 @@ void DMC::resetUpdateEngines() Rng.resize(NumThreads); estimatorClones.resize(NumThreads, nullptr); traceClones.resize(NumThreads, nullptr); + wlog_collectors.resize(NumThreads, nullptr); FairDivideLow(W.getActiveWalkers(), NumThreads, wPerRank); { @@ -130,6 +132,7 @@ void DMC::resetUpdateEngines() #if !defined(REMOVE_TRACEMANAGER) traceClones[ip] = Traces->makeClone(); #endif + wlog_collectors[ip] = wlog_manager_->makeCollector(); Rng[ip] = rngs_[ip]->makeClone(); hClones[ip]->setRandomGenerator(Rng[ip].get()); if (W.isSpinor()) @@ -140,7 +143,8 @@ void DMC::resetUpdateEngines() Movers[ip] = new SODMCUpdatePbyPWithRejectionFast(*wClones[ip], *psiClones[ip], *hClones[ip], *Rng[ip]); Movers[ip]->setSpinMass(SpinMass); Movers[ip]->put(qmcNode); - Movers[ip]->resetRun(branchEngine.get(), estimatorClones[ip], traceClones[ip], DriftModifier); + //Movers[ip]->resetRun(branchEngine.get(), estimatorClones[ip], traceClones[ip], DriftModifier); + Movers[ip]->resetRun2(branchEngine.get(), estimatorClones[ip], traceClones[ip], wlog_collectors[ip], DriftModifier); Movers[ip]->initWalkersForPbyP(W.begin() + wPerRank[ip], W.begin() + wPerRank[ip + 1]); } else @@ -158,7 +162,8 @@ void DMC::resetUpdateEngines() Movers[ip] = new DMCUpdatePbyPWithRejectionFast(*wClones[ip], *psiClones[ip], *hClones[ip], *Rng[ip]); Movers[ip]->put(qmcNode); - Movers[ip]->resetRun(branchEngine.get(), estimatorClones[ip], traceClones[ip], DriftModifier); + //Movers[ip]->resetRun(branchEngine.get(), estimatorClones[ip], traceClones[ip], DriftModifier); + Movers[ip]->resetRun2(branchEngine.get(), estimatorClones[ip], traceClones[ip], wlog_collectors[ip], DriftModifier); Movers[ip]->initWalkersForPbyP(W.begin() + wPerRank[ip], W.begin() + wPerRank[ip + 1]); } else @@ -168,7 +173,8 @@ void DMC::resetUpdateEngines() else Movers[ip] = new DMCUpdateAllWithRejection(*wClones[ip], *psiClones[ip], *hClones[ip], *Rng[ip]); Movers[ip]->put(qmcNode); - Movers[ip]->resetRun(branchEngine.get(), estimatorClones[ip], traceClones[ip], DriftModifier); + //Movers[ip]->resetRun(branchEngine.get(), estimatorClones[ip], traceClones[ip], DriftModifier); + Movers[ip]->resetRun2(branchEngine.get(), estimatorClones[ip], traceClones[ip], wlog_collectors[ip], DriftModifier); Movers[ip]->initWalkers(W.begin() + wPerRank[ip], W.begin() + wPerRank[ip + 1]); } } @@ -179,12 +185,9 @@ void DMC::resetUpdateEngines() { #pragma omp parallel for for (int ip = 0; ip < NumThreads; ++ip) - { traceClones[ip]->transfer_state_from(*Traces); - } } #endif - if (spinor) app_log() << " Spins treated as dynamic variable with SpinMass: " << SpinMass << std::endl; @@ -236,6 +239,7 @@ bool DMC::run() #if !defined(REMOVE_TRACEMANAGER) Traces->startRun(nBlocks, traceClones); #endif + wlog_manager_->startRun(wlog_collectors); IndexType block = 0; IndexType updatePeriod = (qmc_driver_mode[QMC_UPDATE_MODE]) ? Period4CheckProperties : (nBlocks + 1) * nSteps; int sample = 0; @@ -293,6 +297,7 @@ bool DMC::run() #if !defined(REMOVE_TRACEMANAGER) Traces->write_buffers(traceClones, block); #endif + wlog_manager_->writeBuffers(wlog_collectors); block++; if (DumpConfig && block % Period4CheckPoint == 0) { @@ -326,6 +331,7 @@ bool DMC::run() #if !defined(REMOVE_TRACEMANAGER) Traces->stopRun(); #endif + wlog_manager_->stopRun(); return finalize(nBlocks); } diff --git a/src/QMCDrivers/DMC/DMCBatched.cpp b/src/QMCDrivers/DMC/DMCBatched.cpp index c59ca331ba..4a8d97da6b 100644 --- a/src/QMCDrivers/DMC/DMCBatched.cpp +++ b/src/QMCDrivers/DMC/DMCBatched.cpp @@ -288,6 +288,9 @@ void DMCBatched::advanceWalkers(const StateForThread& sft, crowd.accumulate(step_context.get_random_gen()); } + // collect walker logs + crowd.collectStepWalkerLog(sft.global_step); + { // T-moves ScopedTimer tmove_timer(dmc_timers.tmove_timer); @@ -429,6 +432,14 @@ bool DMCBatched::run() IndexType num_blocks = qmcdriver_input_.get_max_blocks(); estimator_manager_->startDriverRun(); + + //start walker log manager + wlog_manager_ = std::make_unique(walker_logs_input, allow_walker_logs, get_root_name(), myComm); + std::vector wlog_collectors; + for (auto& c: crowds_) + wlog_collectors.push_back(&c->getWalkerLogCollector()); + wlog_manager_->startRun(wlog_collectors); + StateForThread dmc_state(qmcdriver_input_, *drift_modifier_, *branch_engine_, population_, steps_per_block_); LoopTimer<> dmc_loop; @@ -457,6 +468,7 @@ bool DMCBatched::run() ScopedTimer local_timer(timers_.production_timer); ParallelExecutor<> crowd_task; + int global_step = 0; for (int block = 0; block < num_blocks; ++block) { { @@ -473,7 +485,7 @@ bool DMCBatched::run() for (UPtr& crowd : crowds_) crowd->startBlock(steps_per_block_); - for (int step = 0; step < steps_per_block_; ++step) + for (int step = 0; step < steps_per_block_; ++step, ++global_step) { ScopedTimer local_timer(timers_.run_steps_timer); @@ -483,6 +495,7 @@ bool DMCBatched::run() setNonLocalMoveHandler(*ham); dmc_state.step = step; + dmc_state.global_step = global_step; crowd_task(crowds_.size(), runDMCStep, dmc_state, timers_, dmc_timers_, std::ref(step_contexts_), std::ref(crowds_)); @@ -500,6 +513,7 @@ bool DMCBatched::run() if (qmcdriver_input_.get_measure_imbalance()) measureImbalance("Block " + std::to_string(block)); endBlock(); + wlog_manager_->writeBuffers(wlog_collectors); recordBlock(block); } @@ -523,6 +537,7 @@ bool DMCBatched::run() print_mem("DMCBatched ends", app_log()); estimator_manager_->stopDriverRun(); + wlog_manager_->stopRun(); return finalize(num_blocks, true); } diff --git a/src/QMCDrivers/DMC/DMCBatched.h b/src/QMCDrivers/DMC/DMCBatched.h index d95ae0c8b6..fbb318ca7d 100644 --- a/src/QMCDrivers/DMC/DMCBatched.h +++ b/src/QMCDrivers/DMC/DMCBatched.h @@ -53,6 +53,7 @@ class DMCBatched : public QMCDriverNew IndexType recalculate_properties_period; const size_t steps_per_block; IndexType step = -1; + IndexType global_step = -1; bool is_recomputing_block = false; StateForThread(const QMCDriverInput& qmci, diff --git a/src/QMCDrivers/DMC/DMCUpdatePbyPFast.cpp b/src/QMCDrivers/DMC/DMCUpdatePbyPFast.cpp index 5fb7d657a1..e28f017980 100644 --- a/src/QMCDrivers/DMC/DMCUpdatePbyPFast.cpp +++ b/src/QMCDrivers/DMC/DMCUpdatePbyPFast.cpp @@ -24,6 +24,7 @@ #else using TraceManager = int; #endif +#include "WalkerLogManager.h" //#define TEST_INNERBRANCH @@ -170,6 +171,8 @@ void DMCUpdatePbyPWithRejectionFast::advanceWalker(Walker_t& thisWalker, bool re #if !defined(REMOVE_TRACEMANAGER) Traces->buffer_sample(W.current_step); #endif + if(wlog_collector) + wlog_collector->collect(thisWalker,W,Psi,H); { ScopedTimer local_timer(myTimers[DMC_tmoves]); const int NonLocalMoveAcceptedTemp = H.makeNonLocalMoves(W); diff --git a/src/QMCDrivers/QMCDriver.cpp b/src/QMCDrivers/QMCDriver.cpp index b60bc2d063..004fa45f27 100644 --- a/src/QMCDrivers/QMCDriver.cpp +++ b/src/QMCDrivers/QMCDriver.cpp @@ -36,6 +36,8 @@ #else using TraceManager = int; #endif +#include "WalkerLogInput.h" +#include "WalkerLogManager.h" namespace qmcplusplus { @@ -62,6 +64,8 @@ QMCDriver::QMCDriver(const ProjectData& project_data, DumpConfig = false; IsQMCDriver = true; allow_traces = false; + allow_walker_logs = false; + walker_logs_xml = NULL; MyCounter = 0; // value //accept multiple names for the same value @@ -198,11 +202,15 @@ void QMCDriver::process(xmlNodePtr cur) #if !defined(REMOVE_TRACEMANAGER) //create and initialize traces if (!Traces) - { Traces = std::make_unique(myComm); - } Traces->put(traces_xml, allow_traces, RootName); #endif + //create and initialize traces + if (!wlog_manager_) + { + WalkerLogInput walker_logs_input(walker_logs_xml); + wlog_manager_ = std::make_unique(walker_logs_input, allow_walker_logs, RootName, myComm); + } branchEngine->put(cur); Estimators->put(H, cur); if (!wOut) diff --git a/src/QMCDrivers/QMCDriver.h b/src/QMCDrivers/QMCDriver.h index 571fa3d858..0b62c24f29 100644 --- a/src/QMCDrivers/QMCDriver.h +++ b/src/QMCDrivers/QMCDriver.h @@ -31,6 +31,7 @@ #include "QMCWaveFunctions/WaveFunctionPool.h" #include "QMCHamiltonians/QMCHamiltonian.h" #include "Estimators/EstimatorManagerBase.h" +#include "WalkerLogManager.h" #include "QMCDrivers/DriverTraits.h" #include "QMCDrivers/QMCDriverInterface.h" #include "QMCDrivers/GreenFunctionModifiers/DriftModifierBase.h" @@ -62,6 +63,7 @@ namespace qmcplusplus class MCWalkerConfiguration; class HDFWalkerOutput; class TraceManager; +class WalkerLogManager; /** @ingroup QMCDrivers * @{ @@ -96,6 +98,11 @@ class QMCDriver : public QMCDriverInterface, public QMCTraits, public MPIObjectB /// traces xml xmlNodePtr traces_xml; + /// whether to allow traces + bool allow_walker_logs; + /// traces xml + xmlNodePtr walker_logs_xml; + /// Constructor. QMCDriver(const ProjectData& project_data, MCWalkerConfiguration& w, @@ -149,6 +156,10 @@ class QMCDriver : public QMCDriverInterface, public QMCTraits, public MPIObjectB inline void requestTraces(bool traces) override { allow_traces = traces; } + inline void putWalkerLogs(xmlNodePtr wlxml) override { walker_logs_xml = wlxml; } + + inline void requestWalkerLogs(bool allow_walker_logs_) override { allow_walker_logs = allow_walker_logs_; } + std::string getEngineName() override { return QMCType; } template @@ -184,6 +195,9 @@ class QMCDriver : public QMCDriverInterface, public QMCTraits, public MPIObjectB ///Traces manager std::unique_ptr Traces; + ///Traces manager + std::unique_ptr wlog_manager_; + ///return the random generators inline RefVector> getRngRefs() const { diff --git a/src/QMCDrivers/QMCDriverFactory.cpp b/src/QMCDrivers/QMCDriverFactory.cpp index 00d3abd629..64ddf0bf5d 100644 --- a/src/QMCDrivers/QMCDriverFactory.cpp +++ b/src/QMCDrivers/QMCDriverFactory.cpp @@ -76,6 +76,7 @@ QMCDriverFactory::DriverAssemblyState QMCDriverFactory::readSection(xmlNodePtr c aAttrib.add(append_tag, "append"); aAttrib.add(profiling_tag, "profiling"); aAttrib.add(das.traces_tag, "trace"); + aAttrib.add(das.walkerlogs_tag, "walkerlog"); aAttrib.put(cur); das.append_run = (append_tag == "yes"); das.enable_profiling = (profiling_tag == "yes"); @@ -294,6 +295,11 @@ std::unique_ptr QMCDriverFactory::createQMCDriver(xmlNodePtr (das.traces_tag == "none" && (das.new_run_type == QMCRunType::VMC || das.new_run_type == QMCRunType::DMC)); new_driver->requestTraces(allow_traces); + //add trace information + bool allow_walker_logs = das.walkerlogs_tag == "yes" || + (das.walkerlogs_tag == "none" && (das.new_run_type == QMCRunType::VMC || das.new_run_type == QMCRunType::DMC || das.new_run_type == QMCRunType::VMC_BATCH || das.new_run_type == QMCRunType::DMC_BATCH)); + new_driver->requestWalkerLogs(allow_walker_logs); + return new_driver; } } // namespace qmcplusplus diff --git a/src/QMCDrivers/QMCDriverFactory.h b/src/QMCDrivers/QMCDriverFactory.h index c1dd191b8f..e3397da8ea 100644 --- a/src/QMCDrivers/QMCDriverFactory.h +++ b/src/QMCDrivers/QMCDriverFactory.h @@ -47,6 +47,7 @@ class QMCDriverFactory bool append_run = false; bool enable_profiling = false; std::string traces_tag = "none"; + std::string walkerlogs_tag = "none"; QMCRunType new_run_type = QMCRunType::DUMMY; }; diff --git a/src/QMCDrivers/QMCDriverInterface.h b/src/QMCDrivers/QMCDriverInterface.h index 7e20915583..6209ec31fe 100644 --- a/src/QMCDrivers/QMCDriverInterface.h +++ b/src/QMCDrivers/QMCDriverInterface.h @@ -49,6 +49,8 @@ class QMCDriverInterface virtual void putWalkers(std::vector& wset) = 0; virtual void putTraces(xmlNodePtr txml) = 0; virtual void requestTraces(bool allow_traces) = 0; + virtual void putWalkerLogs(xmlNodePtr wlxml) = 0; + virtual void requestWalkerLogs(bool allow_walker_logs_) = 0; virtual void process(xmlNodePtr cur) = 0; virtual QMCRunType getRunType() = 0; virtual std::string getEngineName() = 0; diff --git a/src/QMCDrivers/QMCDriverNew.cpp b/src/QMCDrivers/QMCDriverNew.cpp index 1ea7106080..ab37238376 100644 --- a/src/QMCDrivers/QMCDriverNew.cpp +++ b/src/QMCDrivers/QMCDriverNew.cpp @@ -33,6 +33,8 @@ #include "Utilities/Timer.h" #include "Message/UniformCommunicateError.h" #include "EstimatorInputDelegates.h" +#include "WalkerLogInput.h" +#include "WalkerLogManager.h" namespace qmcplusplus @@ -205,6 +207,7 @@ void QMCDriverNew::setStatus(const std::string& aname, const std::string& h5name h5_file_root_ = h5name; } + /** Read walker configurations from *.config.h5 files * @param wset list of xml elements containing mcwalkerset * @@ -376,6 +379,18 @@ void QMCDriverNew::initialLogEvaluation(int crowd_id, doesDoinTheseLastMatter(walkers[iw]); } + +void QMCDriverNew::putWalkerLogs(xmlNodePtr wlxml) +{ + walker_logs_input.present = false; + if(wlxml) + { + walker_logs_input.readXML(wlxml); + walker_logs_input.present = true; + } +} + + std::ostream& operator<<(std::ostream& o_stream, const QMCDriverNew& qmcd) { o_stream << " time step = " << qmcd.qmcdriver_input_.get_tau() << '\n'; diff --git a/src/QMCDrivers/QMCDriverNew.h b/src/QMCDrivers/QMCDriverNew.h index 079850cf3a..68f5e0e67c 100644 --- a/src/QMCDrivers/QMCDriverNew.h +++ b/src/QMCDrivers/QMCDriverNew.h @@ -43,6 +43,7 @@ #include "DriverWalkerTypes.h" #include "TauParams.hpp" #include "Particle/MCCoords.hpp" +#include "WalkerLogInput.h" #include class Communicate; @@ -51,6 +52,7 @@ namespace qmcplusplus { //forward declarations: Do not include headers if not needed class TraceManager; +class WalkerLogManager; class EstimatorManagerNew; class TrialWaveFunction; class QMCHamiltonian; @@ -101,6 +103,12 @@ class QMCDriverNew : public QMCDriverInterface, public MPIObjectBase */ std::bitset qmc_driver_mode_; + /// whether to allow walker logs + bool allow_walker_logs; + /// walker logs input + WalkerLogInput walker_logs_input; + //xmlNodePtr walker_logs_xml; + protected: /** This is a data structure strictly for QMCDriver and its derived classes * @@ -241,6 +249,10 @@ class QMCDriverNew : public QMCDriverInterface, public MPIObjectBase void putTraces(xmlNodePtr txml) override {} void requestTraces(bool allow_traces) override {} + void putWalkerLogs(xmlNodePtr wlxml) override; + + void requestWalkerLogs(bool allow_walker_logs_) override { allow_walker_logs = allow_walker_logs_; } + // scales a MCCoords by sqrtTau. Chooses appropriate taus by CT template static void scaleBySqrtTau(const TauParams& taus, MCCoords& coords) @@ -431,6 +443,9 @@ class QMCDriverNew : public QMCDriverInterface, public MPIObjectBase */ std::unique_ptr estimator_manager_; + /// walker log manager + std::unique_ptr wlog_manager_; + ///record engine for walkers std::unique_ptr wOut; diff --git a/src/QMCDrivers/QMCUpdateBase.cpp b/src/QMCDrivers/QMCUpdateBase.cpp index 215bd37695..f23dd01bba 100644 --- a/src/QMCDrivers/QMCUpdateBase.cpp +++ b/src/QMCDrivers/QMCUpdateBase.cpp @@ -26,6 +26,7 @@ #else using TraceManager = int; #endif +#include "WalkerLogManager.h" namespace qmcplusplus { @@ -37,6 +38,7 @@ QMCUpdateBase::QMCUpdateBase(MCWalkerConfiguration& w, RandomBase& rg) : csoffset(0), Traces(0), + wlog_collector(0), W(w), Psi(psi), Guide(guide), @@ -57,6 +59,7 @@ QMCUpdateBase::QMCUpdateBase(MCWalkerConfiguration& w, RandomBase& rg) : csoffset(0), Traces(0), + wlog_collector(0), W(w), Psi(psi), Guide(psi), @@ -114,6 +117,16 @@ bool QMCUpdateBase::put(xmlNodePtr cur) return s; } +void QMCUpdateBase::resetRun2(BranchEngineType* brancher, + EstimatorManagerBase* est, + TraceManager* traces, + WalkerLogCollector* wlog_collector_, + const DriftModifierBase* driftmodifer) +{ + wlog_collector = wlog_collector_; + resetRun(brancher,est,traces,driftmodifer); +} + void QMCUpdateBase::resetRun(BranchEngineType* brancher, EstimatorManagerBase* est, TraceManager* traces, @@ -184,6 +197,8 @@ void QMCUpdateBase::startBlock(int steps) #if !defined(REMOVE_TRACEMANAGER) Traces->startBlock(steps); #endif + if(wlog_collector) + wlog_collector->startBlock(); nAccept = 0; nReject = 0; nAllRejected = 0; diff --git a/src/QMCDrivers/QMCUpdateBase.h b/src/QMCDrivers/QMCUpdateBase.h index 48d8a9315b..237b7048b4 100644 --- a/src/QMCDrivers/QMCUpdateBase.h +++ b/src/QMCDrivers/QMCUpdateBase.h @@ -23,6 +23,7 @@ #include "QMCWaveFunctions/TrialWaveFunction.h" #include "QMCHamiltonians/QMCHamiltonian.h" #include "QMCHamiltonians/NonLocalTOperator.h" +#include "WalkerLogManager.h" #include "GreenFunctionModifiers/DriftModifierBase.h" #include "SimpleFixedNodeBranch.h" #include "DriverDebugChecks.h" @@ -31,6 +32,7 @@ namespace qmcplusplus { class TraceManager; +class WalkerLogManager; /** @ingroup QMC * @brief Base class for update methods for each step * @@ -101,6 +103,12 @@ class QMCUpdateBase : public QMCTraits TraceManager* traces, const DriftModifierBase* driftmodifer); + void resetRun2(BranchEngineType* brancher, + EstimatorManagerBase* est, + TraceManager* traces, + WalkerLogCollector* wlog_collector_, + const DriftModifierBase* driftmodifer); + inline RealType getTau() { //SpeciesSet tspecies(W.getSpeciesSet()); @@ -238,6 +246,7 @@ class QMCUpdateBase : public QMCTraits public: ///traces TraceManager* Traces; + WalkerLogCollector* wlog_collector; protected: ///update particle-by-particle diff --git a/src/QMCDrivers/VMC/VMC.cpp b/src/QMCDrivers/VMC/VMC.cpp index bc97b82a66..508ae66561 100644 --- a/src/QMCDrivers/VMC/VMC.cpp +++ b/src/QMCDrivers/VMC/VMC.cpp @@ -32,6 +32,7 @@ #else using TraceManager = int; #endif +#include "WalkerLogManager.h" namespace qmcplusplus { @@ -66,6 +67,7 @@ bool VMC::run() #if !defined(REMOVE_TRACEMANAGER) Traces->startRun(nBlocks, traceClones); #endif + wlog_manager_->startRun(wlog_collectors); LoopTimer<> vmc_loop; RunTimeControl<> runtimeControl(run_time_manager, MaxCPUSecs, myComm->getName(), myComm->rank() == 0); @@ -109,6 +111,7 @@ bool VMC::run() #if !defined(REMOVE_TRACEMANAGER) Traces->write_buffers(traceClones, block); #endif + wlog_manager_->writeBuffers(wlog_collectors); recordBlock(block); vmc_loop.stop(); @@ -131,6 +134,7 @@ bool VMC::run() #if !defined(REMOVE_TRACEMANAGER) Traces->stopRun(); #endif + wlog_manager_->stopRun(); //copy back the random states for (int ip = 0; ip < NumThreads; ++ip) rngs_[ip] = Rng[ip]->makeClone(); @@ -165,6 +169,7 @@ void VMC::resetRun() Movers.resize(NumThreads, nullptr); estimatorClones.resize(NumThreads, nullptr); traceClones.resize(NumThreads, nullptr); + wlog_collectors.resize(NumThreads, nullptr); Rng.resize(NumThreads); // hdf_archive::hdf_archive() is not thread-safe @@ -180,6 +185,7 @@ void VMC::resetRun() #if !defined(REMOVE_TRACEMANAGER) traceClones[ip] = Traces->makeClone(); #endif + wlog_collectors[ip] = wlog_manager_->makeCollector(); Rng[ip] = rngs_[ip]->makeClone(); hClones[ip]->setRandomGenerator(Rng[ip].get()); if (W.isSpinor()) @@ -215,9 +221,7 @@ void VMC::resetRun() { #pragma omp parallel for for (int ip = 0; ip < NumThreads; ++ip) - { traceClones[ip]->transfer_state_from(*Traces); - } } #endif if (qmc_driver_mode[QMC_UPDATE_MODE]) @@ -262,7 +266,8 @@ void VMC::resetRun() { //int ip=omp_get_thread_num(); Movers[ip]->put(qmcNode); - Movers[ip]->resetRun(branchEngine.get(), estimatorClones[ip], traceClones[ip], DriftModifier); + //Movers[ip]->resetRun(branchEngine.get(), estimatorClones[ip], traceClones[ip], DriftModifier); + Movers[ip]->resetRun2(branchEngine.get(), estimatorClones[ip], traceClones[ip], wlog_collectors[ip], DriftModifier); if (qmc_driver_mode[QMC_UPDATE_MODE]) Movers[ip]->initWalkersForPbyP(W.begin() + wPerRank[ip], W.begin() + wPerRank[ip + 1]); else diff --git a/src/QMCDrivers/VMC/VMCBatched.cpp b/src/QMCDrivers/VMC/VMCBatched.cpp index dff6fa1d15..094a8aca8f 100644 --- a/src/QMCDrivers/VMC/VMCBatched.cpp +++ b/src/QMCDrivers/VMC/VMCBatched.cpp @@ -21,6 +21,7 @@ #include "MemoryUsage.h" #include "QMCWaveFunctions/TWFGrads.hpp" #include "TauParams.hpp" +#include "WalkerLogManager.h" namespace qmcplusplus { @@ -214,6 +215,10 @@ void VMCBatched::advanceWalkers(const StateForThread& sft, ScopedTimer est_timer(timers.estimators_timer); crowd.accumulate(step_context.get_random_gen()); } + + // collect walker logs + crowd.collectStepWalkerLog(sft.global_step); + // TODO: // check if all moves failed } @@ -304,6 +309,12 @@ bool VMCBatched::run() IndexType num_blocks = qmcdriver_input_.get_max_blocks(); //start the main estimator estimator_manager_->startDriverRun(); + //start walker log manager + wlog_manager_ = std::make_unique(walker_logs_input, allow_walker_logs, get_root_name(), myComm); + std::vector wlog_collectors; + for (auto& c: crowds_) + wlog_collectors.push_back(&c->getWalkerLogCollector()); + wlog_manager_->startRun(wlog_collectors); StateForThread vmc_state(qmcdriver_input_, vmcdriver_input_, *drift_modifier_, population_, steps_per_block_); @@ -356,6 +367,7 @@ bool VMCBatched::run() // this barrier fences all previous load imbalance. Avoid block 0 timing pollution. myComm->barrier(); + int global_step = 0; for (int block = 0; block < num_blocks; ++block) { { @@ -370,10 +382,12 @@ bool VMCBatched::run() for (auto& crowd : crowds_) crowd->startBlock(steps_per_block_); - for (int step = 0; step < steps_per_block_; ++step) + + for (int step = 0; step < steps_per_block_; ++step, ++global_step) { ScopedTimer local_timer(timers_.run_steps_timer); vmc_state.step = step; + vmc_state.global_step = global_step; crowd_task(crowds_.size(), runVMCStep, vmc_state, timers_, std::ref(step_contexts_), std::ref(crowds_)); if (collect_samples_) @@ -389,6 +403,7 @@ bool VMCBatched::run() if (qmcdriver_input_.get_measure_imbalance()) measureImbalance("Block " + std::to_string(block)); endBlock(); + wlog_manager_->writeBuffers(wlog_collectors); recordBlock(block); } @@ -435,6 +450,7 @@ bool VMCBatched::run() print_mem("VMCBatched ends", app_log()); estimator_manager_->stopDriverRun(); + wlog_manager_->stopRun(); return finalize(num_blocks, true); } diff --git a/src/QMCDrivers/VMC/VMCBatched.h b/src/QMCDrivers/VMC/VMCBatched.h index e2ff01111d..8c4cee5882 100644 --- a/src/QMCDrivers/VMC/VMCBatched.h +++ b/src/QMCDrivers/VMC/VMCBatched.h @@ -53,6 +53,7 @@ class VMCBatched : public QMCDriverNew IndexType recalculate_properties_period; const size_t steps_per_block; IndexType step = -1; + IndexType global_step = -1; bool is_recomputing_block = false; StateForThread(const QMCDriverInput& qmci, diff --git a/src/QMCDrivers/VMC/VMCUpdatePbyP.cpp b/src/QMCDrivers/VMC/VMCUpdatePbyP.cpp index fbce39d2ea..8c3f60fb4e 100644 --- a/src/QMCDrivers/VMC/VMCUpdatePbyP.cpp +++ b/src/QMCDrivers/VMC/VMCUpdatePbyP.cpp @@ -134,6 +134,8 @@ void VMCUpdatePbyP::advanceWalker(Walker_t& thisWalker, bool recompute) #if !defined(REMOVE_TRACEMANAGER) Traces->buffer_sample(W.current_step); #endif + if(wlog_collector) + wlog_collector->collect(thisWalker,W,Psi,H); if (!moved) ++nAllRejected; } diff --git a/src/QMCDrivers/WalkerLogCollector.cpp b/src/QMCDrivers/WalkerLogCollector.cpp index 63f41382d3..c0297ded23 100644 --- a/src/QMCDrivers/WalkerLogCollector.cpp +++ b/src/QMCDrivers/WalkerLogCollector.cpp @@ -41,7 +41,6 @@ void WalkerLogCollector::init() { properties_include = {"R2Accepted", "R2Proposed", "LocalEnergy", "LocalPotential", "Kinetic", "ElecElec", "ElecIon", "LocalECP", "NonLocalECP"}; - state.reset(); energy_index = -1; // empty walker steps and energy vectors for the MC block steps.resize(0); diff --git a/src/QMCDrivers/WalkerLogCollector.h b/src/QMCDrivers/WalkerLogCollector.h index 3b63652c56..73d92dbf24 100644 --- a/src/QMCDrivers/WalkerLogCollector.h +++ b/src/QMCDrivers/WalkerLogCollector.h @@ -31,23 +31,11 @@ using MCPWalker = Walker; struct WalkerLogState { /// whether logs are active in the current driver - bool logs_active; + bool logs_active = false; /// period between MC steps for data collection - int step_period; + int step_period = 1; /// controls verbosity of log file writes - bool verbose; - - WalkerLogState() - { - reset(); - step_period = 1; - } - - inline void reset() - { - logs_active = false; - verbose = false; - } + bool verbose = false; }; diff --git a/src/QMCDrivers/WalkerLogManager.cpp b/src/QMCDrivers/WalkerLogManager.cpp index c4583b374b..b78d6eaf7a 100644 --- a/src/QMCDrivers/WalkerLogManager.cpp +++ b/src/QMCDrivers/WalkerLogManager.cpp @@ -20,7 +20,6 @@ namespace qmcplusplus WalkerLogManager::WalkerLogManager(WalkerLogInput& inp, bool allow_logs, std::string series_root, Communicate* comm) { - state.reset(); communicator = comm; file_root = series_root; bool driver_allows_logs = allow_logs; // driver allows logs or not diff --git a/src/QMCHamiltonians/OperatorBase.cpp b/src/QMCHamiltonians/OperatorBase.cpp index 8f7dc68d38..a7701abefc 100644 --- a/src/QMCHamiltonians/OperatorBase.cpp +++ b/src/QMCHamiltonians/OperatorBase.cpp @@ -268,7 +268,6 @@ void OperatorBase::deleteTraceQuantities() have_required_traces_ = false; request_.reset(); } - #endif ////// PROTECTED FUNCTIONS diff --git a/tests/scripts/check_wlogs.py b/tests/scripts/check_wlogs.py new file mode 100755 index 0000000000..bf4401483a --- /dev/null +++ b/tests/scripts/check_wlogs.py @@ -0,0 +1,1235 @@ +#! /usr/bin/env python3 + +# Performs consistency checks between traces.h5 and scalar.dat/stat.h5/dmc.dat files +# Jaron Krogel/ORNL + +# Type the following to view documentation for command line inputs: +# >check_wlogs.py -h + +# For usage examples, type: +# >check_wlogs.py -x + +# check_traces.py packages obj and HDFreader classes from Nexus. +# Note that h5py is required (which depends on numpy). +# This script is compatible with both Python 2 and 3. + +import os +import sys +from copy import deepcopy +import numpy as np +import h5py +from optparse import OptionParser + +# Returns failure error code to OS. +# Explicitly prints 'fail' after an optional message. +def test_fail(): + print('\n\nTest status: fail') + sys.exit(1) +#end def test_fail + + +# Returns success error code to OS. +# Explicitly prints 'pass' after an optional message. +def test_pass(): + print('\n\nTest status: pass') + sys.exit(0) +#end def test_pass + + + +###################################################################### +# from generic.py +###################################################################### + +logfile = sys.stdout + +def log(msg,n=0,indent=' '): + if not isinstance(msg,str): + msg = str(msg) + #end if + if n>0: + indent = n*indent + msg=indent+msg.replace('\n','\n'+indent) + #end if + logfile.write(msg+'\n') +#end def log + + +def error(msg,header=None,n=0): + post_header=' error:' + if header is None: + header = post_header.lstrip() + else: + header += post_header + #end if + log('\n '+header,n=n) + log(msg.rstrip(),n=n) + log(' exiting.\n') + test_fail() +#end def error + + + +class object_interface(object): + _logfile = sys.stdout + + def __len__(self): + return len(self.__dict__) + #end def __len__ + + def __contains__(self,name): + return name in self.__dict__ + #end def + + def __getitem__(self,name): + return self.__dict__[name] + #end def __getitem__ + + def __setitem__(self,name,value): + self.__dict__[name]=value + #end def __setitem__ + + def __delitem__(self,name): + del self.__dict__[name] + #end def __delitem__ + + def __iter__(self): + for item in self.__dict__: + yield self.__dict__[item] + #end for + #end def __iter__ + + def __repr__(self): + s='' + for k in sorted(self.keys()): + if not isinstance(k,str) or k[0]!='_': + v=self.__dict__[k] + if hasattr(v,'__class__'): + s+=' {0:<20} {1:<20}\n'.format(str(k),v.__class__.__name__) + else: + s+=' {0:<20} {1:<20}\n'.format(str(k),type(v)) + #end if + #end if + #end for + return s + #end def __repr__ + + def __str__(self,nindent=1): + pad = ' ' + npad = nindent*pad + s='' + normal = [] + qable = [] + for k,v in self.items(): + if not isinstance(k,str) or k[0]!='_': + if isinstance(v,object_interface): + qable.append(k) + else: + normal.append(k) + #end if + #end if + #end for + normal = sorted(normal) + qable = sorted(qable) + indent = npad+18*' ' + for k in normal: + v = self[k] + vstr = str(v).replace('\n','\n'+indent) + s+=npad+'{0:<15} = '.format(str(k))+vstr+'\n' + #end for + for k in qable: + v = self[k] + s+=npad+str(k)+'\n' + s+=v.__str__(nindent+1) + if isinstance(k,str): + s+=npad+'end '+k+'\n' + #end if + #end for + return s + #end def __str__ + + def keys(self): + return self.__dict__.keys() + #end def keys + + def values(self): + return self.__dict__.values() + #end def values + + def items(self): + return self.__dict__.items() + #end def items + + def copy(self): + return deepcopy(self) + #end def copy + + def clear(self): + self.__dict__.clear() + #end def clear + + def log(self,*items,**kwargs): + log(*items,**kwargs) + #end def log + + def error(self,message,header=None,n=0): + if header is None: + header = self.__class__.__name__ + #end if + error(message,header,n=n) + #end def error +#end class object_interface + + + +class obj(object_interface): + def __init__(self,*vars,**kwargs): + for var in vars: + if isinstance(var,(dict,object_interface)): + for k,v in var.items(): + self[k] = v + #end for + else: + self[var] = None + #end if + #end for + for k,v in kwargs.items(): + self[k] = v + #end for + #end def __init__ + + def append(self,value): + self[len(self)] = value + #end def append + + def first(self): + return self[min(self.keys())] + #end def first +#end class obj + +###################################################################### +# end from generic.py +###################################################################### + + + +###################################################################### +# from developer.py +###################################################################### + +class DevBase(obj): + None +#end class DevBase + +###################################################################### +# end from developer.py +###################################################################### + + + + +###################################################################### +# from hdfreader.py +###################################################################### +import keyword +from inspect import getmembers + +class HDFglobals(DevBase): + view = False +#end class HDFglobals + + +class HDFgroup(DevBase): + def _escape_name(self,name): + if name in self._escape_names: + name=name+'_' + #end if + return name + #end def escape_name + + def _set_parent(self,parent): + self._parent=parent + return + #end def set_parent + + def _add_dataset(self,name,dataset): + self._datasets[name]=dataset + return + #end def add_dataset + + def _add_group(self,name,group): + group._name=name + self._groups[name]=group + return + #end def add_group + + def _contains_group(self,name): + return name in self._groups.keys() + #end def _contains_group + + def _contains_dataset(self,name): + return name in self._datasets.keys() + #end def _contains_dataset + + + def __init__(self): + self._name='' + self._parent=None + self._groups={}; + self._datasets={}; + self._group_counts={} + + self._escape_names=None + self._escape_names=set(dict(getmembers(self)).keys()) | set(keyword.kwlist) + return + #end def __init__ + + + def _remove_hidden(self,deep=True): + if '_parent' in self: + del self._parent + #end if + if deep: + for name,value in self.items(): + if isinstance(value,HDFgroup): + value._remove_hidden() + #end if + #end for + #end if + for name in list(self.keys()): + if name[0]=='_': + del self[name] + #end if + #end for + #end def _remove_hidden + + + # read in all data views (h5py datasets) into arrays + # useful for converting a single group read in view form to full arrays + def read_arrays(self): + self._remove_hidden() + for k,v in self.items(): + if isinstance(v,HDFgroup): + v.read_arrays() + else: + self[k] = np.array(v) + #end if + #end for + #end def read_arrays + + + def get_keys(self): + if '_groups' in self: + keys = list(self._groups.keys()) + else: + keys = list(self.keys()) + #end if + return keys + #end def get_keys +#end class HDFgroup + + + + +class HDFreader(DevBase): + + def __init__(self,fpath,verbose=False,view=False): + + HDFglobals.view = view + + if verbose: + print(' Initializing HDFreader') + #end if + + self.fpath=fpath + if verbose: + print(' loading h5 file') + #end if + + try: + self.hdf = h5py.File(fpath,'r') + except IOError: + self._success = False + self.hdf = obj(obj=obj()) + else: + self._success = True + #end if + + if verbose: + print(' converting h5 file to dynamic object') + #end if + + #convert the hdf 'dict' into a dynamic object + self.nlevels=1 + self.ilevel=0 + # Set the current hdf group + self.obj = HDFgroup() + self.cur=[self.obj] + self.hcur=[self.hdf] + + if self._success: + cur = self.cur[self.ilevel] + hcur = self.hcur[self.ilevel] + for kr,v in hcur.items(): + k=cur._escape_name(kr) + if isinstance(v, h5py.Dataset): + self.add_dataset(cur,k,v) + elif isinstance(v, h5py.Group): + self.add_group(hcur,cur,k,v) + else: + self.error('encountered invalid type: '+str(type(v))) + #end if + #end for + #end if + + if verbose: + print(' end HDFreader Initialization') + #end if + + return + #end def __init__ + + + def increment_level(self): + self.ilevel+=1 + self.nlevels = max(self.ilevel+1,self.nlevels) + if self.ilevel+1==self.nlevels: + self.cur.append(None) + self.hcur.append(None) + #end if + self.pad = self.ilevel*' ' + return + #end def increment_level + + def decrement_level(self): + self.ilevel-=1 + self.pad = self.ilevel*' ' + return + #end def decrement_level + + def add_dataset(self,cur,k,v): + if not HDFglobals.view: + cur[k] = np.array(v) + else: + cur[k] = v + #end if + cur._add_dataset(k,cur[k]) + return + #end def add_dataset + + def add_group(self,hcur,cur,k,v): + cur[k] = HDFgroup() + cur._add_group(k,cur[k]) + cur._groups[k]._parent = cur + self.increment_level() + self.cur[self.ilevel] = cur._groups[k] + self.hcur[self.ilevel] = hcur[k] + + cur = self.cur[self.ilevel] + hcur = self.hcur[self.ilevel] + for kr,v in hcur.items(): + k=cur._escape_name(kr) + if isinstance(v, h5py.Dataset): + self.add_dataset(cur,k,v) + elif isinstance(v, h5py.Group): + self.add_group(hcur,cur,k,v) + #end if + #end for + #end def add_group +#end class HDFreader + +###################################################################### +# end from hdfreader.py +###################################################################### + + + +# Represents QMCPACK data file. +# Used to read scalar.dat, stat.h5, dmc.dat, traces.h5 +class DataFile(DevBase): + + aliases = None + + def __init__(self,filepath=None,quantities=None): + self.data = None + self.filepath = filepath + self.quantities = None + if quantities is not None: + self.quantities = list(quantities) + #end if + if filepath is not None: + self.read(filepath) + if self.aliases is not None: + for name,alias in self.aliases.items(): + if name in self.data: + self.data[alias] = self.data[name] + del self.data[name] + #end if + #end for + #end if + if quantities is not None: + missing = set(quantities)-set(self.data.keys()) + if len(missing)>0: + self.error('some quantities are missing from file "{}"\nquantities present: {}\nquantities missing: {}'.format(self.filepath,sorted(self.data.keys()),sorted(missing))) + #end if + #end if + #end if + #end def __init__ + + def read(self,filepath): + None + #end def read +#end class DataFile + + +# Used to parse scalar.dat and dmc.dat files +class DatFile(DataFile): + def read(self,filepath): + lt = np.loadtxt(filepath) + if len(lt.shape)==1: + lt.shape = (1,len(lt)) + #end if + + data = lt[:,1:].transpose() + + fobj = open(filepath,'r') + variables = fobj.readline().split()[2:] + fobj.close() + + self.data = obj() + for i,vname in enumerate(variables): + self.data[vname]=data[i,:] + #end for + #end def read +#end class DatFile + + +# Parses scalar.dat +class ScalarDatFile(DatFile): + aliases = obj(BlockWeight='Weight') +#end class ScalarDat + + +# Parses dmc.dat +class DmcDatFile(DatFile): + None +#end class DmcDatFile + + + +# Parses scalar data from stat.h5 +class ScalarHDFFile(DataFile): + def read(self,filepath): + hr = HDFreader(filepath) + if not hr._success: + self.error('hdf file read failed\nfile path: '+filepath) + #end if + data = hr.obj + data._remove_hidden() + + self.data = obj() + for name,value in data.items(): + if 'value' in value: + self.data[name] = value.value.flatten() + #end if + #end for + #end def read +#end class ScalarHDFFile + + + +# Parses and organizes data from traces.h5. +# QMCPACK writes one traces.h5 for each MPI task. +# At every MC step, data from each walker is written to this file. +class TracesFileHDF(DataFile): + def __init__(self,filepath=None,blocks=None): + self.info = obj( + blocks = blocks, + particle_sums_valid = None, + ) + DataFile.__init__(self,filepath) + #end def __init__ + + + def read(self,filepath=None): + # Open the wlogs.h5 file + hr = HDFreader(filepath) + if not hr._success: + self.error('hdf file read failed\nfile path: '+filepath) + #end if + hdf = hr.obj + hdf._remove_hidden() + + # Translate from flat table structure to nested data structure. + # Do this for top level "int_data" and "real_data" HDF groups + for name,buffer in hdf.items(): + self.init_trace(name,buffer) + #end for + + # Sum trace data over walkers into per-step and per-block totals + self.accumulate_scalars() + #end def read + + + # Translate from serialized traces table format to fully dimensioned + # data resolved by physical quantity. + def init_trace(self,name,fbuffer): + aliases = obj( + walker_property_int = 'int_traces', + walker_property_real = 'real_traces', + ) + dname = 'scalars' + if name not in aliases.keys(): + return + #end if + trace = obj() + if 'data' in fbuffer: + # Wide data table + # Each row corresponds to a single step of a single walker. + # Each row contains serialized scalar (e.g. LocalEnergy) + # and array (e.g. electron coordinates) data. + ftrace = fbuffer.data + + # Number of rows (walkers*steps for single mpi task) + nrows = len(ftrace) + + # Serialization layout of each row is stored in "layout". + # Layout is separated into a few potential domains: + # scalar domain : scalar quantities such as LocalEnergy + # domain name is "scalars" + # electron domain: array quantities dimensioned like number of electrons (e.g. electron positions) + # domain name follows particleset (often "e") + # ion domain : array quantities dimensioned like number of ions + # domain name follows particleset (often "ion0") + # Get start and end row indices for each quantity + domain = obj() + for qname,fquantity in fbuffer.data_layout.items(): + q = obj() + for vname,value in fquantity.items(): + q[vname] = value + #end for + + # extract per quantity data across all walkers and steps + quantity = ftrace[:,q.index_start:q.index_end] + + # reshape from serialized to multidimensional data for the quantity + if q.unit_size==1: + shape = [nrows]+list(fquantity.shape[0:q.dimension]) + else: + shape = [nrows]+list(fquantity.shape[0:q.dimension])+[q.unit_size] + #end if + quantity.shape = tuple(shape) + #if len(fquantity.shape)==q.dimension: + # quantity.shape = tuple([nrows]+list(fquantity.shape)) + ##end if + domain[qname] = quantity + #end for + trace[dname] = domain + else: + self.error('traces are missing in file "{}"'.format(self.filepath)) + #end if + # rename "int_data" and "real_data" as "int_traces" and "real_traces" + self[aliases[name]] = trace + #end def init_trace + + + # Perform internal consistency check between per-walker single + # particle energies and per-walker total energies. + def check_particle_sums(self,tol): + t = self.real_traces + + # Determine quantities present as "scalars" (total values) and also per-particle + scalar_names = set(t.scalars.keys()) + other_names = [] + for dname,domain in t.items(): + if dname!='scalars': + other_names.extend(domain.keys()) + #end if + #end for + other_names = set(other_names) + sum_names = scalar_names & other_names + + # For each quantity, determine if the sum over particles matches the total + same = True + for qname in sum_names: + # Get total value for each quantity + q = t.scalars[qname] + + # Perform the sum over particles + qs = 0*q + for dname,domain in t.items(): + if dname!='scalars' and qname in domain: + tqs = domain[qname].sum(1) + if len(tqs.shape)==1: + qs[:,0] += tqs + else: + qs[:,0] += tqs[:,0] + #end if + #end if + #end for + + # Compare total and summed quantities + qsame = (abs(q-qs)0: + self.error('{} file check failed for series {}\ntraces file is missing some quantities\nquantities present: {}\nquantities missing: {}'.format(file_type,self.options.series,sorted(trace_names),sorted(missing))) + #end if + + scalars_valid = True + scalars = scalar_file.data + + # Sum traces data for each quantity across all traces.h5 files + summed_scalars = obj() + for qname in qnames: + summed_scalars[qname] = np.zeros(scalars[qname].shape) + #end for + wtot = np.zeros(summed_scalars.first().shape) + for trace_file in self.data: + # scalar.dat/stat.h5 are resolved per block + w = trace_file.scalars_by_block.Weight + wtot += w + for qname in qnames: + q = trace_file.scalars_by_block[qname] + if qname!='Weight': + summed_scalars[qname] += w*q + else: + summed_scalars[qname] += w + #end if + #end for + #end for + + # Compare summed trace data against scalar.dat/stat.h5 values + for qname in qnames: + qscalar = scalars[qname] + if qname!='Weight': + qb = summed_scalars[qname]/wtot + else: + qb = summed_scalars[qname] + #end if + match = abs(qb-qscalar)3} {: 16.12f} {: 16.12f} {: 16.12f}'.format(b,qfile,qtrace,qfile-qtrace),n=3) + #end if + #end for + #end if + scalars_valid &= all_match + #end for + + self.failed |= not scalars_valid + + return scalars_valid + #end def check_scalar_file + + + # Check aggregated traces data against dmc.dat + def check_dmc_dat(self,tol): + + # Some DMC steps are excluded due to a known bug in QMCPACK weights + dmc_steps_exclude = self.options.dmc_steps_exclude + + # Check that expected quantities are present + dmc_file = self.dmc_dat + qnames = dmc_file.quantities + trace_names = set(self.data[0].scalars_by_step.keys()) + missing = set(qnames)-trace_names + if len(missing)>0: + self.error('dmc.dat check failed for series {}\ntraces file is missing some quantities\nquantities present: {}\nquantities missing: {}'.format(self.options.series,sorted(trace_names),sorted(missing))) + #end if + weighted = set(['LocalEnergy']) + + dmc_valid = True + dmc = dmc_file.data + + # Sum traces data for each quantity across all traces.h5 files + summed_scalars = obj() + for qname in qnames: + summed_scalars[qname] = np.zeros(dmc[qname].shape) + #end for + wtot = np.zeros(summed_scalars.first().shape) + for trace_file in self.data: + # dmc.dat is resolved per step + w = trace_file.scalars_by_step.Weight + wtot += w + for qname in qnames: + q = trace_file.scalars_by_step[qname] + if qname in weighted: + summed_scalars[qname] += w*q + else: + summed_scalars[qname] += q + #end if + #end for + #end for + + # Compare summed trace data against dmc.dat values + for qname in qnames: + qdmc = dmc[qname] + if qname in weighted: + qb = summed_scalars[qname]/wtot + else: + qb = summed_scalars[qname] + #end if + match = abs(qb-qdmc)3} {: 16.12f} {: 16.12f} {: 16.12f}'.format(s,qfile,qtrace,qfile-qtrace),n=3) + #end if + #end for + #end if + if dmc_steps_exclude>0: + all_match = match[dmc_steps_exclude:].all() + #end if + dmc_valid &= all_match + #end for + + if dmc_steps_exclude>0: + log('\nExcluding first {} DMC steps from match check.'.format(dmc_steps_exclude),n=2) + #end if + + self.dmc_dat_valid = dmc_valid + self.pass_fail(dmc_valid,n=2) + + self.failed |= not dmc_valid + + return dmc_valid + #end def check_dmc_dat + + + # Print a brief message about pass/fail status of a subtest + def pass_fail(self,passed,n): + if passed: + self.log('\nCheck passed!',n=n) + else: + self.log('\nCheck failed!',n=n) + #end if + #end def pass_fail +#end class TracesAnalyzer + + + +examples = ''' + +''' + + + +if __name__=='__main__': + + # Define command line options + usage = '''usage: %prog [options] [path]''' + parser = OptionParser(usage=usage,add_help_option=False,version='%prog 0.1') + + parser.add_option('-h','--help',dest='help', + action='store_true',default=False, + help='Print help information and exit (default=%default).' + ) + parser.add_option('-x','--examples',dest='examples', + action='store_true',default=False, + help='Print usage examples and exit (default=%default).' + ) + parser.add_option('-p','--prefix',dest='prefix', + default='qmc', + help='Series number(s) to check (default=%default).' + ) + parser.add_option('-s','--series',dest='series', + default='None', + help='Series number(s) to check (default=%default).' + ) + parser.add_option('-m','--methods',dest='methods', + default='None', + help='QMC method for each series. Can be "vmc" or "dmc" for each series (default=%default).' + ) + parser.add_option('-q','--quantities',dest='quantities', + default='default', + help='QMC method for each series. Can be "vmc" or "dmc" for each series (default=%default).' + ) + parser.add_option('-n','--mpi',dest='mpi', + default='1', + help='Number of MPI tasks in the original QMCPACK run. This is also the number of traces.h5 files produced by a single VMC or DMC section (default=%default).' + ) + parser.add_option('--psum',dest='particle_sum', + action='store_true',default=False, + help='Check sums of single particle energies (default=%default).' + ) + parser.add_option('--pseudo',dest='pseudo', + action='store_true',default=True, + help='QMC calculation used pseudopotentials (default=%default).' + ) + parser.add_option('--dmc_steps_exclude',dest='dmc_steps_exclude', + default='0', + help='Exclude a number of DMC steps from being checked. This option is temporary and will be removed once a bug in the DMC weights for the first step is fixed (default=%default).' + ) + parser.add_option('--tol',dest='tolerance', + default='1e-8', + help='Tolerance to check (default=%default).' + ) + + opt,paths = parser.parse_args() + + options = obj(**opt.__dict__) + + # Process command line options + if options.help: + log('\n'+parser.format_help().strip()+'\n') + sys.exit(0) + #end if + + if options.examples: + log(examples) + sys.exit(0) + #end if + + tol = float(options.tolerance) + + if len(paths)==0: + options.path = './' + elif len(paths)==1: + options.path = paths[0] + else: + error('Only a single path is accepted as input.\nPaths provided:\n{}'.format(paths)) + #end if + if not os.path.exists(options.path): + error('Path to QMCPACK run does not exist.\nPath provided: {}'.format(options.path)) + elif os.path.isfile(options.path): + error('Path to QMCPACK run is actually a file.\nOnly directory paths are accepted.\nPath provided: {}'.format(options.path)) + #end if + + def process_list(slist,type=lambda x: x): + tokens = slist.strip('"').strip("'").replace(',',' ').split() + lst = [type(t) for t in tokens] + return lst + #end def process_list + + options.series = process_list(options.series,int) + options.methods = process_list(options.methods) + options.mpi = int(options.mpi) + options.dmc_steps_exclude = int(options.dmc_steps_exclude) + if options.quantities=='default': + options.quantities = None + else: + options.quantities = process_list(options.quantities) + #end if + + if len(options.series)!=len(options.methods): + error('"series" and "methods" must match in length.') + #end if + valid_methods = ['vmc','dmc'] + invalid = set(options.methods)-set(valid_methods) + if len(invalid)>0: + error('Invalid entries given for "methods".\nValid options are: {}\nYou provided: {}'.format(valid_methods,sorted(invalid))) + #end if + + valid_quantities = ''' + LocalEnergy Kinetic LocalPotential ElecElec ElecIon LocalECP NonLocalECP + '''.split() + if options.quantities is not None: + invalid = set(options.quantities)-set(valid_quantities) + if len(invalid)>0: + error('Invalid entries given for "quantities".\nValid options are: {}\nYou provided: {}'.format(valid_quantities,sorted(invalid))) + #end if + #end if + + + # Parse all files across all requested series and compare traces vs scalar/stat/dmc + + log('\nChecking match between traces and scalar/stat/dmc files\n') + + log('\nOptions provided:\n'+str(options).rstrip()) + + failed = False + + series_in = options.series + methods_in = options.methods + + del options.series + del options.methods + + # Loop over vmc/dmc series + for series,method in zip(series_in,methods_in): + + options.series = series + options.method = method + + log('\n\nChecking series {} method={}'.format(series,method)) + + # Read scalar.dat, stat.h5, dmc.dat, and *wlogs.h5 for the series + ta = TracesAnalyzer(options) + + # Check traces data against scalar/stat/dmc files + if method=='vmc': + log('\nChecking scalar.dat',n=1) + ta.check_scalar_dat(tol) + + log('\nChecking stat.h5',n=1) + ta.check_stat_h5(tol) + + elif method=='dmc': + log('\nSkipping checks of scalar.dat and stat.h5',n=1) + log('Statistics for these files are currently computed\n' + 'after branching. Since traces are written before \n' + 'branching, these files cannot be reconstructed \n' + 'from the traces.',n=2) + + log('\nChecking dmc.dat',n=1) + ta.check_dmc_dat(tol) + #end if + + failed |= ta.failed + #end for + + # Print final pass/fail message + if failed: + test_fail() + else: + test_pass() + #end if +#end if diff --git a/tests/solids/diamondC_1x1x1_pp/CMakeLists.txt b/tests/solids/diamondC_1x1x1_pp/CMakeLists.txt index 598d460206..16591dd222 100644 --- a/tests/solids/diamondC_1x1x1_pp/CMakeLists.txt +++ b/tests/solids/diamondC_1x1x1_pp/CMakeLists.txt @@ -1874,6 +1874,105 @@ if(add_traces_tests) -m 'vmc,dmc' --dmc_steps_exclude=1) + + simple_run_and_check( + deterministic-diamondC_1x1x1_pp-vmc-walkerlog_scalars + "${qmcpack_SOURCE_DIR}/tests/solids/diamondC_1x1x1_pp" + qmc_walkerlog_vmc_scalars.in.xml + 1 + 1 + check_wlogs.py + -p + qmc_wlog_vmc_scalars + -s + 0 + -m + vmc + --dmc_steps_exclude=1) + + simple_run_and_check( + deterministic-diamondC_1x1x1_pp-vmc-walkerlog_scalars + "${qmcpack_SOURCE_DIR}/tests/solids/diamondC_1x1x1_pp" + qmc_walkerlog_vmc_scalars.in.xml + 4 + 4 + check_wlogs.py + -p + qmc_wlog_vmc_scalars + -n + 4 + -s + 0 + -m + vmc + --dmc_steps_exclude=1) + + simple_run_and_check( + deterministic-diamondC_1x1x1_pp-dmc-walkerlog_scalars + "${qmcpack_SOURCE_DIR}/tests/solids/diamondC_1x1x1_pp" + qmc_walkerlog_dmc_scalars.in.xml + 4 + 4 + check_wlogs.py + -p + qmc_wlog_dmc_scalars + -n + 4 + -s + 1 + -m + dmc + --dmc_steps_exclude=1) + + simple_run_and_check( + deterministic-diamondC_1x1x1_pp-vmcbatch-walkerlog_scalars + "${qmcpack_SOURCE_DIR}/tests/solids/diamondC_1x1x1_pp" + qmc_walkerlog_vmcbatch_scalars.in.xml + 1 + 1 + check_wlogs.py + -p + qmc_wlog_vmcbatch_scalars + -s + 0 + -m + vmc + --dmc_steps_exclude=1) + + simple_run_and_check( + deterministic-diamondC_1x1x1_pp-vmcbatch-walkerlog_scalars + "${qmcpack_SOURCE_DIR}/tests/solids/diamondC_1x1x1_pp" + qmc_walkerlog_vmcbatch_scalars.in.xml + 4 + 4 + check_wlogs.py + -p + qmc_wlog_vmcbatch_scalars + -n + 4 + -s + 0 + -m + vmc + --dmc_steps_exclude=1) + + simple_run_and_check( + deterministic-diamondC_1x1x1_pp-dmcbatch-walkerlog_scalars + "${qmcpack_SOURCE_DIR}/tests/solids/diamondC_1x1x1_pp" + qmc_walkerlog_dmcbatch_scalars.in.xml + 4 + 4 + check_wlogs.py + -p + qmc_wlog_dmcbatch_scalars + -n + 4 + -s + 1 + -m + dmc + --dmc_steps_exclude=1) + endif() if(QMC_MIXED_PRECISION) diff --git a/tests/solids/diamondC_1x1x1_pp/qmc_walkerlog_dmc_scalars.in.xml b/tests/solids/diamondC_1x1x1_pp/qmc_walkerlog_dmc_scalars.in.xml new file mode 100644 index 0000000000..e73b6b8e92 --- /dev/null +++ b/tests/solids/diamondC_1x1x1_pp/qmc_walkerlog_dmc_scalars.in.xml @@ -0,0 +1,100 @@ + + + + + + + + + + 3.37316115 3.37316115 0.00000000 + 0.00000000 3.37316115 3.37316115 + 3.37316115 0.00000000 3.37316115 + + + p p p + + 15 + + + + -1 + 1.0 + + + -1 + 1.0 + + + + + 4 + 4 + 6 + 21894.7135906 + + 0.00000000 0.00000000 0.00000000 + 1.68658058 1.68658058 1.68658058 + + + + + + + + + + + + + + + + +-0.2032153051 -0.1625595974 -0.143124599 -0.1216434956 -0.09919771951 -0.07111729038 +-0.04445345869 -0.02135082917 + + + + + + +0.2797730287 0.2172604155 0.1656172964 0.1216984261 0.083995349 0.05302065936 +0.02915953995 0.0122402581 + + + + +0.4631099906 0.356399124 0.2587895287 0.1829298509 0.1233653291 0.07714708174 +0.04145899033 0.01690645936 + + + + + + + + + + + + + + + + 2 + 2 + 4 + 2 + 1 + 0.3 + + + + 2 + 4 + 2 + 0.01 + no + + diff --git a/tests/solids/diamondC_1x1x1_pp/qmc_walkerlog_dmcbatch_scalars.in.xml b/tests/solids/diamondC_1x1x1_pp/qmc_walkerlog_dmcbatch_scalars.in.xml new file mode 100644 index 0000000000..f7ea95fcb4 --- /dev/null +++ b/tests/solids/diamondC_1x1x1_pp/qmc_walkerlog_dmcbatch_scalars.in.xml @@ -0,0 +1,100 @@ + + + + + batched + + + + + + 3.37316115 3.37316115 0.00000000 + 0.00000000 3.37316115 3.37316115 + 3.37316115 0.00000000 3.37316115 + + + p p p + + 15 + + + + -1 + 1.0 + + + -1 + 1.0 + + + + + 4 + 4 + 6 + 21894.7135906 + + 0.00000000 0.00000000 0.00000000 + 1.68658058 1.68658058 1.68658058 + + + + + + + + + + + + + + + + +-0.2032153051 -0.1625595974 -0.143124599 -0.1216434956 -0.09919771951 -0.07111729038 +-0.04445345869 -0.02135082917 + + + + + + +0.2797730287 0.2172604155 0.1656172964 0.1216984261 0.083995349 0.05302065936 +0.02915953995 0.0122402581 + + + + +0.4631099906 0.356399124 0.2587895287 0.1829298509 0.1233653291 0.07714708174 +0.04145899033 0.01690645936 + + + + + + + + + + + + + + + 2 + 2 + 4 + 2 + 1 + 0.3 + + + 2 + 2 + 4 + 2 + 0.01 + no + + diff --git a/tests/solids/diamondC_1x1x1_pp/qmc_walkerlog_vmc_scalars.in.xml b/tests/solids/diamondC_1x1x1_pp/qmc_walkerlog_vmc_scalars.in.xml new file mode 100644 index 0000000000..cccb03e6b9 --- /dev/null +++ b/tests/solids/diamondC_1x1x1_pp/qmc_walkerlog_vmc_scalars.in.xml @@ -0,0 +1,92 @@ + + + + + + + + + + 3.37316115 3.37316115 0.00000000 + 0.00000000 3.37316115 3.37316115 + 3.37316115 0.00000000 3.37316115 + + + p p p + + 15 + + + + -1 + 1.0 + + + -1 + 1.0 + + + + + 4 + 4 + 6 + 21894.7135906 + + 0.00000000 0.00000000 0.00000000 + 1.68658058 1.68658058 1.68658058 + + + + + + + + + + + + + + + + +-0.2032153051 -0.1625595974 -0.143124599 -0.1216434956 -0.09919771951 -0.07111729038 +-0.04445345869 -0.02135082917 + + + + + + +0.2797730287 0.2172604155 0.1656172964 0.1216984261 0.083995349 0.05302065936 +0.02915953995 0.0122402581 + + + + +0.4631099906 0.356399124 0.2587895287 0.1829298509 0.1233653291 0.07714708174 +0.04145899033 0.01690645936 + + + + + + + + + + + + + + + + 2 + 2 + 4 + 2 + 1 + 0.3 + + diff --git a/tests/solids/diamondC_1x1x1_pp/qmc_walkerlog_vmcbatch_scalars.in.xml b/tests/solids/diamondC_1x1x1_pp/qmc_walkerlog_vmcbatch_scalars.in.xml new file mode 100644 index 0000000000..c6fa42d513 --- /dev/null +++ b/tests/solids/diamondC_1x1x1_pp/qmc_walkerlog_vmcbatch_scalars.in.xml @@ -0,0 +1,92 @@ + + + + + batched + + + + + + 3.37316115 3.37316115 0.00000000 + 0.00000000 3.37316115 3.37316115 + 3.37316115 0.00000000 3.37316115 + + + p p p + + 15 + + + + -1 + 1.0 + + + -1 + 1.0 + + + + + 4 + 4 + 6 + 21894.7135906 + + 0.00000000 0.00000000 0.00000000 + 1.68658058 1.68658058 1.68658058 + + + + + + + + + + + + + + + + +-0.2032153051 -0.1625595974 -0.143124599 -0.1216434956 -0.09919771951 -0.07111729038 +-0.04445345869 -0.02135082917 + + + + + + +0.2797730287 0.2172604155 0.1656172964 0.1216984261 0.083995349 0.05302065936 +0.02915953995 0.0122402581 + + + + +0.4631099906 0.356399124 0.2587895287 0.1829298509 0.1233653291 0.07714708174 +0.04145899033 0.01690645936 + + + + + + + + + + + + + + + 2 + 2 + 4 + 2 + 1 + 0.3 + +