VMC program architecture
VMC is organized as a small executable around a reusable simulation library.
main() owns configuration, parameter optimization, concurrent production
tasks, result aggregation, and terminal/file setup. Each Simulation owns the
state and components needed for one sampling stream.
Control flow
Section titled “Control flow”main() | +-- Config::from_file("config.cfg") +-- JastrowOptimizer::optimize() short Simulation::run() calls for candidate b +-- open output/vmc.bin +-- launch Num_Threads asynchronous production tasks | | | +-- Simulation::run() initialize_positions -> warmup -> measure | +-- write_init/frame/done [task 0 only] | +-- aggregate task summaries +-- print final measurementsThe per-phase internals of Simulation::run() (warmup and measurement steps) are
described under One simulation stream below.
The optimizer finishes before production tasks are launched. Its candidate
evaluations create Simulation objects without output writers, so optimizer
trajectories are not written to vmc.bin.
Component map
Section titled “Component map”| Component | Responsibility | Primary source |
|---|---|---|
main() | Load configuration, optimize b, seed and launch production tasks, aggregate results, write terminal summary | src/main.cpp |
Config | Parse keys, supply defaults, validate selected values, compute step counts and initial proposal size | src/config/config.hpp |
JastrowOptimizer | Scan candidate b values with short simulations and select a result | src/optimizer/jastrow_optimizer.cu |
Simulation | Own one particle configuration and run initialization, warmup, and measurement | src/simulation/simulation.cu, .cuh |
Particles | Store positions and wavefunction derivative arrays in aligned structure-of-arrays memory | src/particles/particles.cuh |
WaveFunction | Combine the plane-wave Slater component and Padé–Jastrow component; maintain derivative caches | src/wavefunction/wavefunction.cu, .cuh |
SlaterPlaneWave | Build plane-wave determinant rows, compute determinant ratios, and update/restore cached state | src/slater_plane_wave/ |
JastrowPade | Evaluate the Jastrow term, move delta, and derivatives | src/jastrow_pade/ |
EnergyTracker | Maintain real- and reciprocal-space interaction state and evaluate kinetic plus potential energy | src/energy_tracking/energy_tracking.cu, .cuh |
BlockingAnalysis | Form block means and estimate a standard error | src/blocking_analysis/blocking_analysis.cpp, .hpp |
WalkerRNG | Choose particles, uniform acceptance values, and proposed displacements | src/utilities/random.cuh |
OutputWriter | Abstract init/frame/done records; binary implementation serializes task 0 | src/output_writer/output_writer.cpp, .hpp |
One simulation stream
Section titled “One simulation stream”Initialization
Section titled “Initialization”The Simulation constructor creates its particles, wavefunction, blocking
analysis, energy tracker, optional output writer, and RNG. initialize_positions()
draws coordinates uniformly inside the box until the evaluated log wavefunction
is finite, then initializes the energy tracker’s structure factors and real- and
reciprocal-space terms.
Warmup
Section titled “Warmup”warmup() performs Num_Particles × Warmup_Sweeps proposed moves. After each
particle-sized batch it adjusts the proposal step size toward a 50% acceptance
target. Warmup moves update simulation state but are not sent to the energy
blocks or output writer.
Calling this phase “equilibration” expresses its intended role; the code does not prove that a selected warmup length is sufficient for every configuration. [general-VMC-knowledge]
Measurement
Section titled “Measurement”For each of Num_Particles × Measure_Sweeps steps, measure():
- Proposes and accepts or rejects one particle move.
- Updates wavefunction derivatives when necessary.
- Evaluates total energy.
- Adds the energy to the running mean and blocking analysis.
- Writes a frame when an output writer is attached.
The returned MeasurementSummary contains a mean energy, an optional standard
error, and an acceptance fraction.
Move path
Section titled “Move path”metropolis_step() selects one particle and proposes displacements in all three
coordinates. Coordinates are wrapped into [0, box_length). It calculates the
Slater determinant ratio and change in the Jastrow value, then compares the
corresponding log probability ratio with a uniform random draw.
On acceptance, it commits the Slater update and incrementally updates the interaction-energy state. On rejection, it restores the cached Slater row and old coordinates.
Energy and statistics path
Section titled “Energy and statistics path”The wavefunction derivative arrays feed EnergyTracker::kinetic_energy().
EnergyTracker::potential_energy() adds cached real-space and reciprocal-space
terms to correction and background terms. eval_total_energy() returns their
sum.
Every measured energy enters BlockingAnalysis. A standard error becomes
available after two complete blocks. In main(), production-task means are
averaged; available task errors are combined as
sqrt(sum(task_error²)) / Num_Threads.
This describes the implemented arithmetic. The assumptions required for that quantity to be a reliable uncertainty belong in the missing method/statistics documentation.
Concurrency and output ownership
Section titled “Concurrency and output ownership”Num_Threads controls the number of std::async(std::launch::async, ...)
production tasks. The master RNG generates a separate seed value for each task.
The code does not use MPI.
Only task 0 receives BinOutputWriter; therefore:
output/vmc.binis a single task’s sequence of frames.- The final terminal energy and acceptance rate aggregate all tasks.
- The file does not contain the final cross-task aggregate.
Separate seeds show that the tasks are intended as distinct sampling streams; statistical independence is an assumption rather than something control flow alone can prove. [assumption]
CPU and CUDA implementations
Section titled “CPU and CUDA implementations”CMake builds the same library sources in one of two modes:
- With CUDA disabled,
.cufiles are compiled as C++ and take their CPU paths. - With CUDA enabled and a CUDA compiler available, CMake defines
VMC_CUDA_BACKENDand links CUDA runtime, cuSOLVER, and cuBLAS.
The selected backend and numeric precision are compile-time properties, not runtime CLI options.
Source of truth
Section titled “Source of truth”Start with src/main.cpp and src/simulation/simulation.cu, then follow the
component paths in the table above. Build-time backend selection is in
CMakeLists.txt.