Illustration of quadratic (top) and affine invariant (bottom) moves in a confining channel (dashed lines). For the quadratic move, two helper points rj and rk are employed to move walker i. Conversely, for the affine move, only one additional point rj is used and walker i may thus not travel as far in a single step in a curved channel. | Autocorrelation function (panel a) and error bar from blocking analysis (panel b) of affine and quadratic MC calculations. In panel (c), we compare the Monte Carlo error bar and the time it take the ensemble to travel around the ring. Compared the affine method (blue), our QMC method (red and green points) requires a travel time approximately half as long and leads to error bars half as large. |
Date |
File description | Download link |
08-10-23 | We report five novel ensemble Monte Carlo moves in a new manuscript that was just accepted for publication in Comp. Phys. Comm. Our updated source code was uploaded to Zenodo and is available here: | qmc_08-10-23.tar.gz |
03-08-23 | Code submitted along with accepted version of our manuscript. We added code to sample the 2d Rosenbrock function. | qmc_03-08-23.tar.gz |
07-03-22 | Submitted along with initial manuscript submission to ApJ. | qmc_07-03-22.tar.gz |
Array1 <S> s = SetUpNStates(nWalkers); // Set up nWalkers different states of type S
for(int iBlock=0; i<nBlocks; iBlock++) { // loop over blocks
for(int iStep=0; i<nStepsPerBlock; iStep++) { // loop over steps
for(int i=0; i<nWalkers; i++) { // try moving every walker once per step
int j,k;
SelectTwoOtherWalkersAtRandom(i,j,k);
const double tj = -1.0;
const double tk = +1.0;
const double ti = SampleT(a); // sample t space
const double tNew = SampleT(a); // sample t space one more time
const double wi = LagrangeInterpolation(tNew,ti,tj,tk);
const double wj = LagrangeInterpolation(tNew,tj,tk,ti);
const double wk = LagrangeInterpolation(tNew,tk,ti,tj);
S sNew = s[0]; // Create new state by coping over an existing one.
for(int d=0; d<nDim; d++) {
sNew[d] = wi*s[i][d] + wj*s[j][d]+ wk*s[k][d]; // set nDim parameters of new state
}
if (sNew.Valid()) { // check if state sNew is valid before calling Evaluate()
sNew.Evaluate(); // Sets the energy sNew.y which defines the state's probability = exp(-y/temp)
double dy = sNew.y - s[i].y; // difference in energy between new and old state
double prob = pow(fabs(wi),nDim) * exp(-dy/temp); // Note |wi|^nDim and Boltzmann factors
bool accept = (prob>Random()); // Random() returns a single random number between 0 and 1.
if (accept) {
for(int d=0; d<nDim; d++) {
s[i][d] = sNew[d]; // copy over state sNew
}
s[i].y = sNew.y; // copy also its energy
}
}
} // look over all walkers
ComputeDifferentEnsembleAverages(s);
} // end of loop over steps
PrintEndOfBlockStatement();
} // end of loop over blocks
PrintEndOfRunStatement();
(4) Execution: Run test of harmonic potential in tcsh
set index = 58
set T = 0.01
set n = 6
set a = 1.5
harm -affine n=$n a=$a T=${T} nBlocks=100000 > affine${index}_${T}_${n}_${a}.txt &
harm -qmc n=$n a=$a T=${T} nBlocks=100000 > qmcLin${index}_${T}_${n}_${a}.txt &
harm -qmc -Gaussian n=$n a=$a T=${T} nBlocks=100000 > qmcGau${index}_${T}_${n}_${a}.txt &
# Compare the output with the following results. The MC average of energy, E, should be close to 0.5*n*T = 0.03
grep "Fraction= 0.9" *58_*.txt
affine58_0.01_6_1.5.txt: Fraction= 0.9 n= 90000 E= 0.03000173 +- 0.00001369
qmcGau58_0.01_6_1.5.txt: Fraction= 0.9 n= 90000 E= 0.03003602 +- 0.00001169
qmcLin58_0.01_6_1.5.txt: Fraction= 0.9 n= 90000 E= 0.02999435 +- 0.00001152
(5) Execution: Perform calculations for the ring potential, again with tcsh
machine:~/QMC_source_code_03-08-23> tcsh
set index = 57
set T = 0.01
set n = 6
set a = 1.5
set m = 6
set R = 1.0
ring -low -affine m=$m n=$n a=$a T=${T} R=${R} nBlocks=100000 > affine${index}_${T}_${n}_${m}_${a}_${R}.txt &
ring -low -qmc m=$m n=$n a=$a T=${T} R=${R} nBlocks=100000 > qmcLin${index}_${T}_${n}_${m}_${a}_${R}.txt &
ring -low -qmc -Gaussian m=$m n=$n a=$a T=${T} R=${R} nBlocks=100000 > qmcGau${index}_${T}_${n}_${m}_${a}_${R}.txt &
# Compare the output with the following. The MC averages will not agree perfectly.
machine:~/QMC_source_code_03-08-23> grep "Fraction= 0.9" *57_*.txt
affine57_0.01_6_6_1.5_1.0.txt: Fraction= 0.9 n= 90000 E= -0.00031481 +- 0.00007970
qmcGau57_0.01_6_6_1.5_1.0.txt: Fraction= 0.9 n= 90000 E= -0.00030795 +- 0.00004486
qmcLin57_0.01_6_6_1.5_1.0.txt: Fraction= 0.9 n= 90000 E= -0.00026504 +- 0.00003554
(6) Execution: To evaluate the performance of our modified walk moves, we recommend sampling the Rosenbrock density
machine:~/CMS_MC_test_03-08-23a> tcsh
set index = 199
set T = 1.0
foreach nWalkers (3 4 5 6 8 10 20)
set para = "T=$T nStepsPerBlock=1000 nBlocks=100000 nWalkers=${nWalkers}"
foreach nMovers (3 4 5 6 10)
foreach a (1.2 1.5 2.0 3.0)
rosen -walk $para nMovers=$nMovers a=$a > walk${index}_${nWalkers}_${nMovers}_${a}.txt &
end
end
end
(7) Concluding remarks At the moment, we do not have a Python version of our QMC code but it is high on our to-do list. |