Block Averaging Example¶
In this example, the block averaging approach to computing error bars is considered. First, please read the original method: https://doi.org/10.1063/1.457480. Then, also consider the discussion on block averages in Appendix D of Frenkel and Smit. Then, we’ll reproduce Frenkel and Smith’s case study 4 (page 98-100 and Figure 4.4).
[1]:
import sys
import unittest
import feasst as fst
class TestMonteCarlo4Block(unittest.TestCase):
def test_srsw(self, num_particles=108, density=0.8442, temperature=1.5, steps_per=1e5):
monte_carlo = fst.MonteCarlo()
# monte_carlo.set(fst.MakeRandomMT19937(fst.args({"seed": "1234"})))
monte_carlo.add(fst.MakeConfiguration(fst.args({
"cubic_box_length": str((num_particles/density)**(1./3.)),
"particle_type0": fst.install_dir() + "/forcefield/lj.fstprt",
"cutoff0": "2.5",
})))
monte_carlo.add(fst.MakePotential(fst.MakeLennardJones()))
monte_carlo.add(fst.MakePotential(fst.MakeLongRangeCorrections()))
monte_carlo.set(fst.MakeThermoParams(fst.args({"beta": str(1./temperature),
"chemical_potential": "1."})))
monte_carlo.set(fst.MakeMetropolis())
monte_carlo.add(fst.MakeTrialTranslate(fst.args({"weight": "1.", "tunable_param": "2."})))
monte_carlo.add(fst.MakeTrialAdd(fst.args({"particle_type": "0"})))
monte_carlo.run(fst.MakeRun(fst.args({"until_num_particles": str(num_particles)})))
monte_carlo.run(fst.MakeRemoveTrial(fst.args({"name": "TrialAdd"})))
monte_carlo.add(fst.MakeLogAndMovie(fst.args({
"steps_per" : str(steps_per),
"file_name": "movie",
"clear_file": "true"})))
monte_carlo.add(fst.MakeCheckEnergyAndTune(fst.args({"steps_per" : str(steps_per)})))
# equilibrate
monte_carlo.attempt(int(1e6))
# compute average using this script
energy = fst.MakeAccumulator()
# production
for _ in range(int(1e8)):
monte_carlo.attempt()
energy.accumulate(monte_carlo.criteria().current_energy())
print('average energy', energy.average())
for op in range(energy.max_block_operations()):
print(op, energy.block_stdev(op), energy.block_std_of_std(op))
#self.assertAlmostEqual(energy.block_stdev(13)/num_particles, 0.0012, delta=0.0004)
#self.assertAlmostEqual(energy.average()/num_particles, -4.4190, delta=3*energy.block_stdev(13)/num_particles)
If the test passes, the energy is within the tolerance of the SRSW value and the two ensemble average methods agreed.
[2]:
%time # Note: any line starting with % is only to be used with ipynb
unittest.main(argv=[''], verbosity=2, exit=False)
test_srsw (__main__.TestMonteCarlo4Block) ...
CPU times: user 3 µs, sys: 0 ns, total: 3 µs
Wall time: 7.15 µs
average energy -576.4376128069971
0 0.07510636040234885 0.04322275467550779
1 0.07359011506962478 0.04749864777552218
2 0.07344944697207455 0.0589605210359109
3 0.07239626945616733 0.06608570396503526
4 0.05376806537982441 0.0
5 0.0 0.0
ok
----------------------------------------------------------------------
Ran 1 test in 1757.834s
OK
[2]:
<unittest.main.TestProgram at 0x7f1b641185e0>
Did this tutorial work as expected? Did you find any inconsistencies or have any comments? Please contact us. Any feedback is appreciated!