Coverage for examples/widoms_particle_insertion.py: 100%
27 statements
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-14 15:55 +0200
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-14 15:55 +0200
1""" Widom's particle insertion method for calculating the chemical potential
3In this example we use the Widom's particle insertion method
4to calculate the chemical potential of a Lennard-Jones fluid.
6The excess chemical potential, μᵉˣ, of a not to dense fluid can be computed as:
8 μᵉˣ = -kT ln 〈exp(-ΔU/kT)〉
10where ΔU is the energy difference between the system with and without a ghost particle.
11And 〈...〉 is an average for all possible positions of the ghost particle
12(sometimes writte as an integral over space).
13"""
15import numpy as np
17import gamdpy as gp
19# Setup configuration: FCC Lattice
20rho = 0.4 # Number density
21configuration = gp.Configuration(D=3)
22configuration.make_lattice(gp.unit_cells.FCC, cells=[8, 8, 8], rho=rho)
23configuration['m'] = 1.0
24configuration.randomize_velocities(temperature=2.0)
26# Setup pair potential: Single component 12-6 Lennard-Jones
27pair_func = gp.apply_shifted_potential_cutoff(gp.LJ_12_6_sigma_epsilon)
28sig, eps, cut = 1.0, 1.0, 2.5
29pair_pot = gp.PairPotential(pair_func, params=[sig, eps, cut], max_num_nbs=1000)
31# Setup integrator: NVT
32temperature = 1.0
33integrator = gp.integrators.NVT(temperature=temperature, tau=0.2, dt=0.005)
35# Setup runtime actions, i.e. actions performed during simulation of timeblocks
36runtime_actions = [gp.TrajectorySaver(),
37 gp.ScalarSaver(),
38 gp.MomentumReset(100)]
40# Setup Simulation
41sim = gp.Simulation(configuration, pair_pot, integrator, runtime_actions,
42 num_timeblocks=20, steps_per_timeblock=1024,
43 storage='memory')
45# Equilibrate the system
46sim.run()
48# Setup the Widom's particle insertion calculator
49num_ghost_particles = 500_000
50ghost_positions = np.random.rand(num_ghost_particles, configuration.D) * configuration.simbox.get_lengths()
51calc_widom = gp.CalculatorWidomInsertion(sim.configuration, pair_pot, temperature, ghost_positions)
52print('Production run:')
53for block in sim.run_timeblocks():
54 calc_widom.update()
55 print('.', end='', flush=True)
57calc_widom_data = calc_widom.read()
58print(f"\nExcess chemical potential: {calc_widom_data['chemical_potential']}")
60# Error estimation assuming that timeblocks are statistically independent
61mu = calc_widom_data['chemical_potential']
62sigma = np.std(calc_widom_data['chemical_potentials']) / np.sqrt(len(calc_widom_data['chemical_potentials']))
63print(f"95 % confidence interval: [{mu - 1.96*sigma}, {mu + 1.96*sigma}]")