gamma=1e-3, max_displacement=0.01) i = 0 while system.analysis.min_dist() < min_dist and i < warm_n_times: print("minimization: {:+.2e}".format(system.analysis.energy()["total"])) system.integrator.run(warm_steps) i += 1 print("minimization: {:+.2e}".format(system.analysis.energy()["total"])) print() system.integrator.set_vv() # activate thermostat system.thermostat.set_langevin(kT=temperature, gamma=1.0, seed=42) widom = reaction_ensemble.WidomInsertion(temperature=temperature, seed=77) # add insertion reaction insertion_reaction_id = 0 widom.add_reaction(reactant_types=[], reactant_coefficients=[], product_types=[1, 2], product_coefficients=[1, 1], default_charges={ 1: -1, 2: +1 }) print(widom.get_status()) system.setup_type_map([0, 1, 2]) n_iterations = 100
class WidomInsertionTest(ut.TestCase): """Test the implementation of the widom insertion. The excess chemical potential is calculated for identical particles in a 20 cubed box with a single particle, interacting via a LJ-potential (cut-off at 5 sigma).""" N0 = 1 TEMPERATURE = 0.5 TYPE_HA = 0 CHARGE_HA = 0 LJ_EPS = 1.0 LJ_SIG = 1.0 LJ_CUT = 5 BOX_L = 2 * LJ_CUT LJ_SHIFT = lj_potential(LJ_CUT, LJ_EPS, LJ_SIG, LJ_CUT + 1, 0.0) radius = np.linspace(1e-10, LJ_CUT, 1000) # numerical integration for radii smaller than the cut-off in spherical # coordinates integrateUpToCutOff = 4 * np.pi * np.trapz(radius**2 * np.exp( -lj_potential(radius, LJ_EPS, LJ_SIG, LJ_CUT, LJ_SHIFT) / TEMPERATURE), x=radius) # numerical solution for V_lj=0 => corresponds to the volume (as exp(0)=1) integreateRest = (BOX_L**3 - 4.0 / 3.0 * np.pi * LJ_CUT**3) # calculate excess chemical potential of the system, see Frenkel Smith, # p 174. Note: He uses scaled coordinates, which is why we need to divide # by the box volume target_mu_ex = -TEMPERATURE * \ np.log((integrateUpToCutOff + integreateRest) / BOX_L**3) system = espressomd.System(box_l=np.ones(3) * BOX_L) system.cell_system.set_n_square() system.seed = system.cell_system.get_state()['n_nodes'] * [2] np.random.seed(69) # make reaction code fully deterministic system.cell_system.skin = 0.4 volume = np.prod(system.box_l) # cuboid box Widom = reaction_ensemble.WidomInsertion(temperature=TEMPERATURE, seed=1) def setUp(self): self.system.part.add(id=0, pos=0.5 * self.system.box_l, type=self.TYPE_HA) self.system.non_bonded_inter[self.TYPE_HA, self.TYPE_HA].lennard_jones.set_params( epsilon=self.LJ_EPS, sigma=self.LJ_SIG, cutoff=self.LJ_CUT, shift="auto") self.Widom.add_reaction(reactant_types=[], reactant_coefficients=[], product_types=[self.TYPE_HA], product_coefficients=[1], default_charges={self.TYPE_HA: self.CHARGE_HA}) def test_widom_insertion(self): system = WidomInsertionTest.system Widom = WidomInsertionTest.Widom target_mu_ex = WidomInsertionTest.target_mu_ex system.seed = system.cell_system.get_state()['n_nodes'] * [ np.random.randint(5) ] num_samples = 100000 for _ in range(num_samples): # 0 for insertion reaction Widom.measure_excess_chemical_potential(0) mu_ex = Widom.measure_excess_chemical_potential(0) deviation_mu_ex = abs(mu_ex[0] - target_mu_ex) # error self.assertLess( deviation_mu_ex - 1e-3, 0.0, msg= "\nExcess chemical potential for single LJ-particle computed via widom insertion gives a wrong value.\n" + " average mu_ex: " + str(mu_ex[0]) + " mu_ex_std_err: " + str(mu_ex[1]) + " target_mu_ex: " + str(target_mu_ex))
# Warmup Integration Loop act_min_dist = system.analysis.min_dist() i = 0 while (i < warm_n_times): print(i, "warmup") system.integrator.run(steps=warm_steps) i += 1 #Increase LJ cap lj_cap = lj_cap + 10 system.force_cap = lj_cap # remove force capping system.force_cap = 0 unimportant_K_diss = 0.0088 RE = reaction_ensemble.WidomInsertion( temperature=temperature, exclusion_radius=1.0) RE.add_reaction(gamma=unimportant_K_diss, reactant_types=[], reactant_coefficients=[], product_types=[ 1, 2], product_coefficients=[1, 1], default_charges={1: -1, 2: +1}) print(RE.get_status()) system.setup_type_map([0, 1, 2]) for i in range(10000): for j in range(30): RE.measure_excess_chemical_potential(0) # 0 for insertion reaction system.integrator.run(steps=2) system.integrator.run(steps=500) if(i % 100 == 0): print("mu_ex_pair", RE.measure_excess_chemical_potential(0)) #0 for insertion reaction print("HA", system.number_of_particles(type=0), "A-", system.number_of_particles(type=1), "H+", system.number_of_particles(type=2))