class MagnetostaticsInteractionsTests(ut.TestCase): # Handle to espresso system system = espressomd.System() def setUp(self): self.system.box_l = 10, 10, 10 if not self.system.part.exists(0): self.system.part.add(id=0, pos=(0.1, 0.1, 0.1), dip=(1.3, 2.1, -6)) if not self.system.part.exists(1): self.system.part.add(id=1, pos=(0, 0, 0), dip=(7.3, 6.1, -4)) if "DP3M" in espressomd.features(): test_DP3M = generate_test_for_class( DipolarP3M, dict(prefactor=1.0, epsilon=0.0, inter=1000, mesh_off=[0.5, 0.5, 0.5], r_cut=2.4, mesh=[8, 8, 8], cao=1, alpha=12, accuracy=0.01)) if "DIPOLAR_DIRECT_SUM" in espressomd.features(): test_DdsCpu = generate_test_for_class(DipolarDirectSumCpu, dict(prefactor=3.4)) test_DdsRCpu = generate_test_for_class( DipolarDirectSumWithReplicaCpu, dict(prefactor=3.4, n_replica=2))
class ewald_GPU_test(ut.TestCase): if "ELECTROSTATICS" in espressomd.features( ) and "CUDA" in espressomd.features( ) and "EWALD_GPU" in espressomd.features(): from espressomd.electrostatics import EwaldGpu def runTest(self): es = espressomd.System() test_params = {} test_params["bjerrum_length"] = 2 test_params["num_kx"] = 2 test_params["num_ky"] = 2 test_params["num_kz"] = 2 test_params["K_max"] = 10 test_params["time_calc_steps"] = 100 test_params["rcut"] = 0.9 test_params["accuracy"] = 1e-1 test_params["precision"] = 1e-2 test_params["alpha"] = 3.5 ewald = EwaldGpu(**test_params) es.actors.add(ewald) self.assertTrue( params_match(test_params, ewald._get_params_from_es_core())) if __name__ == "__main__": print("Features: ", espressomd.features()) ut.main()
class ElectrostaticInteractionsTests(ut.TestCase): if "ELECTROSTATICS" in espressomd.features(): # Handle to espresso system system = espressomd.System() def setUp(self): self.system.box_l = 10, 10, 10 if not self.system.part.exists(0): self.system.part.add(id=0, pos=(2.0, 2.0, 2.0), q=1) if not self.system.part.exists(1): self.system.part.add(id=1, pos=(8.0, 8.0, 8.0), q=-1) print("ut.TestCase setUp") test_P3M = generate_test_for_class(system, P3M, dict(bjerrum_length=1.0, epsilon=0.0, inter=1000, mesh_off=[0.5, 0.5, 0.5], r_cut=2.4, mesh=[2, 2, 2], cao=1, alpha=12, accuracy=0.01, tune=False)) if "COULOMB_DEBYE_HUECKEL" in espressomd.features(): test_CDH = generate_test_for_class(system, CDH, dict(bjerrum_length=1.0, kappa=2.3, r_cut=2, r0=1, r1=1.9, eps_int=0.8, eps_ext=1, alpha=2))
class ElectrostaticInteractionsTests(ut.TestCase): def setup(self): self.system.box_l = 10, 10, 10 if not self.system.part.exists(0): self.system.part.add(id=0, pos=(0.0, 0.0, 0.0), q=1) if not self.system.part.exists(1): self.system.part.add(id=1, pos=(0.1, 0.1, 0.1), q=-1) test_P3M = generate_test_for_class( P3M, dict(bjerrum_length=1.0, epsilon=0.0, inter=1000, mesh_off=[0.5, 0.5, 0.5], r_cut=2.4, mesh=[2, 2, 2], cao=1, alpha=12, accuracy=0.01)) test_DH = generate_test_for_class( DH, dict(bjerrum_length=1.0, kappa=2.3, r_cut=2)) if "CDG" in espressomd.features(): test_CDH = generate_test_for_class( CDH, dict(bjerrum_length=1.0, kappa=2.3, r_cut=2, r0=1, r1=2, eps_int=0.8, eps_ext=1, alpha=2))
def check_dissipation(self, n): """ Check the dissipation relations: the simple viscous decelleration test. Parameters ---------- n : :obj:`int` Number of particles of the each type. There are 2 types. """ tol = 1.2E-3 for step in range(100): self.system.integrator.run(2) for i in range(n): for k in range(2): ind = i + k * n for j in range(3): # Note: velocity is defined in the lab frame of reference # while gamma_tr is defined in the body one. # Hence, only isotropic gamma_tran_p_validate could be # tested here. self.assertLess( abs(self.system.part[ind].v[j] - math.exp(-self.gamma_tran_p_validate[k, j] * self.system.time / self.mass)), tol) if "ROTATION" in espressomd.features(): self.assertLess( abs(self.system.part[ind].omega_body[j] - math.exp(-self.gamma_rot_p_validate[k, j] * self.system.time / self.J[j])), tol)
def test(self): if "ROTATION" in espressomd.features(): n_test_cases = 5 else: n_test_cases = 4 for i in range(n_test_cases): self.run_test_case(i)
def setUp(self): self.system.time = 0.0 self.system.part.clear() if "BROWNIAN_DYNAMICS" in espressomd.features(): self.system.thermostat.turn_off() # the default integrator is supposed implicitly self.system.integrator.set_nvt()
def test(self): if "CUDA" in espressomd.features(): system = espressomd.System(box_l=[1, 1, 1]) self.assertEqual(system.cuda_init_handle.device_list != {}, espressomd.gpu_available()) else: self.assertFalse(espressomd.gpu_available())
def fluctuation_dissipation_param_setup(self,n): """ Setup the parameters for the following fluctuation-dissipation test. Parameters ---------- n : :obj:`int` Number of particles of the each type. There are 2 types. """ ## Time self.es.time_step = 0.03 ## Space box = 10.0 self.es.box_l = box,box,box if espressomd.has_features(("PARTIAL_PERIODIC",)): self.es.periodicity = 0,0,0 ## NVT thermostat # Just some temperature range to cover by the test: self.kT = self.generate_scalar_ranged_rnd(0.3,5) # See the above comment regarding the gamma assignments. # Note: here & hereinafter specific variations in these ranges are related to # the test execution duration to achieve the required statistical averages faster. self.gamma_global = self.generate_vec_ranged_rnd(0.5,2.0/3.0) self.gamma_global_rot = self.generate_vec_ranged_rnd(0.2,20) # Per-particle parameters self.kT_p = 2.5,2.0 for k in range(2): self.gamma_tran_p[k, :] = self.generate_vec_ranged_rnd(0.4,10.0) self.gamma_rot_p[k, :] = self.generate_vec_ranged_rnd(0.2,20.0) ## Particles # As far as the problem characteristic time is t0 ~ mass / gamma # and the Langevin equation finite-difference approximation is stable # only for time_step << t0, it is needed to set the mass higher than # some minimal value according to the value min_mass_param. # Also, it is expected to test the large enough mass (max_mass_param). # It should be not very large, otherwise the thermalization will require # too much of the CPU time. min_mass_param = 0.2 max_mass_param = 7.0 self.mass = self.generate_scalar_ranged_rnd(min_mass_param,max_mass_param) self.J = self.generate_vec_ranged_rnd(min_mass_param,max_mass_param) for i in range(n): for k in range(2): ind = i + k * n part_pos = np.random.random(3) * box part_v = 0.0,0.0,0.0 part_omega_body = 0.0,0.0,0.0 self.es.part.add(rotation=(1,1,1), id=ind, mass=self.mass, rinertia=self.J, pos=part_pos, v=part_v) if "ROTATION" in espressomd.features(): self.es.part[ind].omega_body = part_omega_body
def rot_diffusion_param_setup(self, n): """ Setup the parameters for the rotational diffusion test check_rot_diffusion(). Parameters ---------- n : :obj:`int` Number of particles. """ # Time # The time step should be less than t0 ~ mass / gamma self.system.time_step = 3E-3 # Space box = 10.0 self.system.box_l = box, box, box if espressomd.has_features(("PARTIAL_PERIODIC", )): self.system.periodicity = 0, 0, 0 # NVT thermostat # Just some temperature range to cover by the test: self.kT = uniform(1.5, 6.5) # Note: here & hereinafter specific variations in the random parameter ranges are related to # the test execution duration to achieve the required statistical averages faster. # The friction gamma_global should be large enough in order to have the small enough D ~ kT / gamma and # to observe the details of the original rotational diffusion: the Perrin1936 (see the reference below) tests are visible # only when the diffusive rotation is ~pi due to the exponential temporal dependencies (see the equations referred in the check_rot_diffusion()). # Also, t0 ~ J / gamma should be small enough # in order to remove the small-time-scale diffusion effects which do not fit the Perrin1936's # tests which are based on the partial differential equation (eq. (68), Perrin1934) leading only to the simple # classical Einstein-Smoluchowski equations of the diffusion # in a contrast of the eq. (10.2.26) [N. Pottier, # https://doi.org/10.1007/s10955-010-0114-6 (2010)]. self.gamma_global = 1E2 * uniform(0.35, 1.05, (3)) # Particles # As far as the problem characteristic time is t0 ~ J / gamma # and the Langevin equation finite-difference approximation is stable # only for time_step << t0, it is needed to set the moment of inertia higher than # some minimal value. # Also, it is expected to test the large enough J. # It should be not very large, otherwise the thermalization will require # too much of the CPU time: the in silico time should clock over the # t0. self.J = uniform(1.5, 16.5, (3)) for ind in range(n): part_pos = np.random.random(3) * box self.system.part.add(rotation=(1, 1, 1), id=ind, rinertia=self.J, pos=part_pos) if "ROTATION" in espressomd.features(): self.system.part[ind].omega_body = 0.0, 0.0, 0.0
def check_dissipation(self): """ Check the dissipation relations: the simple viscous decelleration test. """ tol = 1.25E-4 for i in range(100): for k in range(2): for j in range(3): # Note: velocity is defined in the lab frame of reference # while gamma_tr is defined in the body one. # Hence, only isotropic gamma_tran_p_validate could be tested here. self.assertLess( abs(self.es.part[k].v[j] - math.exp(- self.gamma_tran_p_validate[k, j] * self.es.time / self.mass)), tol) if "ROTATION" in espressomd.features(): self.assertLess(abs( self.es.part[k].omega_body[j] - math.exp(- self.gamma_rot_p_validate[k, j] * self.es.time / self.J[j])), tol)
def set_particle_specific_gamma(self,n): """ Set the particle-specific gamma. Parameters ---------- n : :obj:`int` Number of particles of the each type. There are 2 types. """ for k in range(2): self.gamma_tran_p_validate[k, :] = self.gamma_tran_p[k, :] self.gamma_rot_p_validate[k, :] = self.gamma_rot_p[k, :] for i in range(n): ind = i + k * n self.es.part[ind].gamma = self.gamma_tran_p[k, :] if "ROTATION" in espressomd.features(): self.es.part[ind].gamma_rot = self.gamma_rot_p[k, :]
def test_configure_and_import(self): with tempfile.TemporaryDirectory() as temp_dir: path_in = pathlib.Path(temp_dir) / "sample.py" path_out = pathlib.Path(temp_dir) / "sample_test_processed.py" path_features = pathlib.Path(temp_dir) / "sample_impossible.py" # test importing a simple sample sys.argv.append("42") sys_argv_ref = list(sys.argv) path_in.write_text(""" import sys from argparse import ArgumentParser value = 42 argv = list(sys.argv) import espressomd.visualization """) sample, _ = iw.configure_and_import( path_in, move_to_script_dir=False, cmd_arguments=["TestCase"], gpu=False, script_suffix="test", value=43) self.assertEqual(sys.argv, sys_argv_ref) self.assertEqual(sample.argv, [path_in.name, "TestCase"]) self.assertTrue(path_out.exists(), f"File {path_out} not found") self.assertEqual(sample.value, 43) self.assertIn( "espressomd.visualization = unittest.mock.MagicMock()", path_out.read_text()) # test importing a sample that relies on features not compiled in inactive_features = espressomd.all_features() - set(espressomd.features()) if inactive_features: path_features.write_text(f""" import espressomd espressomd.assert_features({list(inactive_features)}) """) module, _ = iw.configure_and_import(path_features) self.assertIsInstance(module, ut.mock.MagicMock) # importing a valid sample is impossible after a failed import sample, _ = iw.configure_and_import( path_in, move_to_script_dir=True, script_suffix="test", cmd_arguments=["TestCase"], gpu=False, value=43) self.assertIsInstance(sample, ut.mock.MagicMock)
def run_test_case(self, test_case): seed(1) # Decelleration self.es.time_step = 0.007 self.es.part.clear() # gamma_tran/gamma_rot matrix: [2 types of particless] x [3 dimensions # X Y Z] gamma_tran = np.zeros((2, 3)) gamma_tr = np.zeros((2, 3)) gamma_rot = np.zeros((2, 3)) gamma_rot_validate = np.zeros((2, 3)) # The translational gamma isotropy is required here. See comments below. # Global gamma for tests without particle-specific gammas: # gamma_global = np.ones((3)) gamma_global = np.zeros((3)) gamma_global[0] = np.array((0.5 + np.random.random()) * 2.0 / 3.0) gamma_global[1] = gamma_global[0] gamma_global[2] = gamma_global[0] # Additional test case (5th) for the specific global rotational gamma set. gamma_global_rot = np.array((0.5 + np.random.random(3)) * 2.0 / 3.0) # Per-paricle values for the remaining decelleration tests: # Either translational friction isotropy is required # or both translational and rotational ones. # Otherwise these types of motion will interfere. # ..Let's test both cases depending on the particle index. gamma_tran[0, 0] = np.array(0.5 + np.random.random()) gamma_tran[0, 1] = gamma_tran[0, 0] gamma_tran[0, 2] = gamma_tran[0, 0] gamma_rot[0, :] = np.array((0.5 + random(3)) * 2.0 / 3.0) gamma_tran[1, 0] = np.array(0.5 + np.random.random()) gamma_tran[1, 1] = gamma_tran[1, 0] gamma_tran[1, 2] = gamma_tran[1, 0] gamma_rot[1, 0] = np.array((0.5 + np.random.random()) * 2.0 / 3.0) gamma_rot[1, 1] = gamma_rot[1, 0] gamma_rot[1, 2] = gamma_rot[1, 0] if test_case != 4: self.es.thermostat.set_langevin( kT=0.0, gamma=[ gamma_global[0], gamma_global[1], gamma_global[2]]) else: self.es.thermostat.set_langevin( kT=0.0, gamma=[ gamma_global[0], gamma_global[1], gamma_global[2]], gamma_rotation=[ gamma_global_rot[0], gamma_global_rot[1], gamma_global_rot[2]]) self.es.cell_system.skin = 5.0 mass = 12.74 J = [10.0, 10.0, 10.0] for i in range(len(self.es.part)): self.es.part[i].remove() for i in range(2): self.es.part.add(rotation=(1,1,1), pos=np.array([0.0, 0.0, 0.0]), id=i) self.es.part[i].v = np.array([1.0, 1.0, 1.0]) if "ROTATION" in espressomd.features(): self.es.part[i].omega_body = np.array([1.0, 1.0, 1.0]) self.es.part[i].mass = mass self.es.part[i].rinertia = np.array(J) print("\n") for k in range(2): if test_case == 0: if (k == 0): print("------------------------------------------------") print("Test " + str(test_case) + ": no particle specific values") print("------------------------------------------------") # No assignments are needed. if test_case == 1: if (k == 0): print("------------------------------------------------") print("Test " + str(test_case) + ": particle specific gamma but not temperature") print("------------------------------------------------") self.es.part[k].gamma = gamma_tran[k, :] if "ROTATION" in espressomd.features(): self.es.part[k].gamma_rot = gamma_rot[k, :] if test_case == 2: if (k == 0): print("------------------------------------------------") print("Test " + str(test_case) + ": particle specific temperature but not gamma") print("------------------------------------------------") self.es.part[k].temp = 0.0 if test_case == 3: if (k == 0): print("------------------------------------------------") print("Test " + str(test_case) + ": both particle specific gamma and temperature") print("------------------------------------------------") self.es.part[k].temp = 0.0 self.es.part[k].gamma = gamma_tran[k, :] if "ROTATION" in espressomd.features(): self.es.part[k].gamma_rot = gamma_rot[k, :] if test_case == 4: if (k == 0): print("------------------------------------------------") print("Test " + str(test_case) + ": no particle specific values.") print("Rotational specific global thermostat") print("------------------------------------------------") # No assignments are needed. if test_case == 1 or test_case == 3: gamma_tr = gamma_tran gamma_rot_validate = gamma_rot else: for k in range(2): gamma_tr[k, :] = gamma_global[:] if test_case != 4: gamma_rot_validate[k, :] = gamma_global[:] else: gamma_rot_validate[k, :] = gamma_global_rot[:] self.es.time = 0.0 tol = 1.25E-4 for i in range(100): for k in range(2): for j in range(3): # Note: velocity is defined in the lab frame of reference # while gamma_tr is defined in the body one. # Hence, only isotropic gamma_tr could be tested here. self.assertLess( abs(self.es.part[k].v[j] - math.exp(- gamma_tr[k, j] * self.es.time / mass)), tol) if "ROTATION" in espressomd.features(): self.assertLess(abs( self.es.part[k].omega_body[j] - math.exp(- gamma_rot_validate[k, j] * self.es.time / J[j])), tol) for i in range(len(self.es.part)): self.es.part[i].remove() # thermalization # Checks if every degree of freedom has 1/2 kT of energy, even when # mass and inertia tensor are active # 2 different langevin parameters for particles temp = np.array([2.5, 2.0]) D_tr = np.zeros((2, 3)) for k in range(2): gamma_tran[k, :] = np.array((0.4 + np.random.random(3)) * 10) gamma_rot[k, :] = np.array((0.2 + np.random.random(3)) * 20) box = 10.0 self.es.box_l = [box, box, box] if espressomd.has_features(("PARTIAL_PERIODIC",)): self.es.periodicity = 0, 0, 0 # Random temperature kT = (0.3 + np.random.random()) * 5 gamma_global = np.array((0.5 + np.random.random(3)) * 2.0 / 3.0) gamma_global_rot = np.array((0.2 + np.random.random(3)) * 20) if test_case == 2 or test_case == 3: halfkT = temp / 2.0 else: halfkT = np.array([kT, kT]) / 2.0 if test_case == 1 or test_case == 3: gamma_tr = gamma_tran else: for k in range(2): gamma_tr[k, :] = gamma_global[:] # translational diffusion for k in range(2): D_tr[k, :] = 2.0 * halfkT[k] / gamma_tr[k, :] if test_case != 4: self.es.thermostat.set_langevin( kT=kT, gamma=[ gamma_global[0], gamma_global[1], gamma_global[2]]) else: self.es.thermostat.set_langevin( kT=kT, gamma=[ gamma_global[0], gamma_global[1], gamma_global[2]], gamma_rotation=[ gamma_global_rot[0], gamma_global_rot[1], gamma_global_rot[2]]) # no need to rebuild Verlet lists, avoid it self.es.cell_system.skin = 5.0 self.es.time_step = 0.03 n = 200 mass = (0.2 + np.random.random()) * 7.0 J = np.array((0.2 + np.random.random(3)) * 7.0) for i in range(n): for k in range(2): ind = i + k * n part_pos = np.array(np.random.random(3) * box) part_v = np.array([0.0, 0.0, 0.0]) part_omega_body = np.array([0.0, 0.0, 0.0]) self.es.part.add(rotation=(1,1,1), id=ind, mass=mass, rinertia=J, pos=part_pos, v=part_v) if "ROTATION" in espressomd.features(): self.es.part[ind].omega_body = part_omega_body if test_case == 1: self.es.part[ind].gamma = gamma_tran[k, :] if "ROTATION" in espressomd.features(): self.es.part[ind].gamma_rot = gamma_rot[k, :] if test_case == 2: self.es.part[ind].temp = temp[k] if test_case == 3: self.es.part[ind].gamma = gamma_tran[k, :] if "ROTATION" in espressomd.features(): self.es.part[ind].gamma_rot = gamma_rot[k, :] self.es.part[ind].temp = temp[k] # Get rid of short range calculations if exclusions are on # if espressomd.has_features("EXCLUSIONS"): # matrices: [2 types of particless] x [3 dimensions X Y Z] # velocity^2, omega^2, position^2 v2 = np.zeros((2, 3)) o2 = np.zeros((2, 3)) dr2 = np.zeros((2, 3)) sigma2_tr = np.zeros((2)) dr_norm = np.zeros((2)) pos0 = np.zeros((2 * n, 3)) for p in range(n): for k in range(2): ind = p + k * n pos0[ind, :] = self.es.part[ind].pos dt0 = mass / gamma_tr loops = 200 print("Thermalizing...") therm_steps = 20 self.es.integrator.run(therm_steps) print("Measuring...") int_steps = 5 for i in range(loops): self.es.integrator.run(int_steps) # Get kinetic energy in each degree of freedom for all particles for p in range(n): for k in range(2): ind = p + k * n v = self.es.part[ind].v if "ROTATION" in espressomd.features(): o = self.es.part[ind].omega_body o2[k, :] = o2[k, :] + np.power(o[:], 2) pos = self.es.part[ind].pos v2[k, :] = v2[k, :] + np.power(v[:], 2) dr2[k, :] = np.power((pos[:] - pos0[ind, :]), 2) dt = (int_steps * (i + 1) + therm_steps) * \ self.es.time_step # translational diffusion variance: after a closed-form # integration of the Langevin EOM sigma2_tr[k] = 0.0 for j in range(3): sigma2_tr[k] = sigma2_tr[k] + D_tr[k, j] * (2.0 * dt + dt0[k, j] * (- 3.0 + 4.0 * math.exp(- dt / dt0[k, j]) - math.exp(- 2.0 * dt / dt0[k, j]))) dr_norm[k] = dr_norm[k] + \ (sum(dr2[k, :]) - sigma2_tr[k]) / sigma2_tr[k] tolerance = 0.15 Ev = 0.5 * mass * v2 / (n * loops) Eo = 0.5 * J * o2 / (n * loops) dv = np.zeros((2)) do = np.zeros((2)) do_vec = np.zeros((2, 3)) for k in range(2): dv[k] = sum(Ev[k, :]) / (3.0 * halfkT[k]) - 1.0 do[k] = sum(Eo[k, :]) / (3.0 * halfkT[k]) - 1.0 do_vec[k, :] = Eo[k, :] / halfkT[k] - 1.0 dr_norm = dr_norm / (n * loops) for k in range(2): print("\n") print("k = " + str(k)) print("mass = " + str(mass)) print("gamma_tr = {0} {1} {2}".format( gamma_tr[k, 0], gamma_tr[k, 1], gamma_tr[k, 2])) if test_case == 1 or test_case == 3: print("gamma_rot = {0} {1} {2}".format( gamma_rot[k, 0], gamma_rot[k, 1], gamma_rot[k, 2])) else: print("gamma_global = {0} {1} {2}".format( gamma_global[0], gamma_global[1], gamma_global[2])) print("Moment of inertia principal components: = " + str(J)) print("1/2 kT = " + str(halfkT[k])) print("Translational energy: {0} {1} {2}".format( Ev[k, 0], Ev[k, 1], Ev[k, 2])) print("Rotational energy: {0} {1} {2}".format( Eo[k, 0], Eo[k, 1], Eo[k, 2])) print("Deviation in translational energy: " + str(dv[k])) if "ROTATION" in espressomd.features(): print("Deviation in rotational energy: " + str(do[k])) print("Deviation in rotational energy per degrees of freedom: {0} {1} {2}".format( do_vec[k, 0], do_vec[k, 1], do_vec[k, 2])) print( "Deviation in translational diffusion: {0} ".format( dr_norm[k])) self.assertLessEqual( abs( dv[k]), tolerance, msg='Relative deviation in translational energy too large: {0}'.format( dv[k])) if "ROTATION" in espressomd.features(): self.assertLessEqual( abs( do[k]), tolerance, msg='Relative deviation in rotational energy too large: {0}'.format( do[k])) self.assertLessEqual(abs( do_vec[k, 0]), tolerance, msg='Relative deviation in rotational energy per the body axis X is too large: {0}'.format(do_vec[k, 0])) self.assertLessEqual(abs( do_vec[k, 1]), tolerance, msg='Relative deviation in rotational energy per the body axis Y is too large: {0}'.format(do_vec[k, 1])) self.assertLessEqual(abs( do_vec[k, 2]), tolerance, msg='Relative deviation in rotational energy per the body axis Z is too large: {0}'.format(do_vec[k, 2])) self.assertLessEqual( abs( dr_norm[k]), tolerance, msg='Relative deviation in translational diffusion is too large: {0}'.format( dr_norm[k]))
class RotDiffAniso(ut.TestCase): longMessage = True round_error_prec = 1E-14 # Handle for espresso system system = espressomd.System(box_l=[1.0, 1.0, 1.0]) system.cell_system.skin = 5.0 # The NVT thermostat parameters kT = 0.0 gamma_global = np.zeros((3)) # Particle properties J = [0.0, 0.0, 0.0] np.random.seed(4) def setUp(self): self.system.time = 0.0 self.system.part.clear() if "BROWNIAN_DYNAMICS" in espressomd.features(): self.system.thermostat.turn_off() # the default integrator is supposed implicitly self.system.integrator.set_nvt() def add_particles_setup(self, n): """ Adding particles according to the previously set parameters. Parameters ---------- n : :obj:`int` Number of particles. """ for ind in range(n): part_pos = np.random.random(3) * self.box self.system.part.add(rotation=(1, 1, 1), id=ind, pos=part_pos) self.system.part[ind].rinertia = self.J if espressomd.has_features("ROTATION"): self.system.part[ind].omega_body = [0.0, 0.0, 0.0] def set_anisotropic_param(self): """ Select parameters for anisotropic particles. """ # NVT thermostat # Note: here & hereinafter specific variations in the random parameter # ranges are related to the test execution duration to achieve the # required statistical averages faster. The friction gamma_global should # be large enough in order to have the small enough D ~ kT / gamma and # to observe the details of the original rotational diffusion: the # Perrin1936 (see the reference below) tests are visible only when the # diffusive rotation is ~pi due to the exponential temporal dependencies # (see the equations referred in the check_rot_diffusion()). # Also, t0 ~ J / gamma should be small enough in order to remove the # small-time-scale diffusion effects which do not fit the Perrin1936's # tests which are based on the partial differential equation # (eq. (68), Perrin1934) leading only to the simple classical # Einstein-Smoluchowski equations of the diffusion in a contrast of the # eq. (10.2.26) [N. Pottier, doi:10.1007/s10955-010-0114-6 (2010)]. self.gamma_global = 1E2 * np.random.uniform(0.35, 1.05, (3)) # Particles' properties # As far as the problem characteristic time is t0 ~ J / gamma # and the Langevin equation finite-difference approximation is stable # only for time_step << t0, it is needed to set the moment of inertia # higher than some minimal value. # Also, it is expected to test the large enough J. # It should be not very large, otherwise the thermalization will require # too much of the CPU time: the in silico time should clock over the # t0. self.J = np.random.uniform(1.5, 16.5, (3)) def set_isotropic_param(self): """ Select parameters for isotropic particles. Parameters ---------- """ # NVT thermostat # see the comments in set_anisotropic_param() self.gamma_global[0] = 1E2 * np.random.uniform(0.35, 1.05) self.gamma_global[1] = self.gamma_global[0] self.gamma_global[2] = self.gamma_global[0] # Particles' properties # see the comments in set_anisotropic_param() self.J[0] = np.random.uniform(1.5, 16.5) self.J[1] = self.J[0] self.J[2] = self.J[0] def rot_diffusion_param_setup(self): """ Setup the parameters for the rotational diffusion test check_rot_diffusion(). """ # Time # The time step should be less than t0 ~ mass / gamma self.system.time_step = 3E-3 # Space self.box = 10.0 self.system.box_l = 3 * [self.box] self.system.periodicity = [0, 0, 0] # NVT thermostat # Just some temperature range to cover by the test: self.kT = np.random.uniform(0.5, 1.5) def check_rot_diffusion(self, n): """ The rotational diffusion tests based on the reference work [Perrin, F. (1936) Journal de Physique et Le Radium, 7(1), 1-11. https://doi.org/10.1051/jphysrad:01936007010100] with a theoretical background of [Perrin, F. (1934) Journal de Physique et Le Radium, 5(10), 497-511. https://doi.org/10.1051/jphysrad:01934005010049700] Parameters ---------- n : :obj:`int` Number of particles. """ # Global diffusivity tensor in the body frame: D = self.kT / self.gamma_global # Thermalizing... therm_steps = 100 self.system.integrator.run(therm_steps) # Measuring... # Set the initial conditions according to the [Perrin1936], p.3. # The body angular velocity is rotated now, but there is only the # thermal velocity, hence, this does not impact the test and its # physical context. for ind in range(n): self.system.part[ind].quat = [1.0, 0.0, 0.0, 0.0] # Average direction cosines # Diagonal ones: dcosjj_validate = np.zeros((3)) dcosjj_dev = np.zeros((3)) # same to the power of 2 dcosjj2_validate = np.zeros((3)) dcosjj2_dev = np.zeros((3)) # The non-diagonal elements for 2 different tests: negative ("nn") and # positive ("pp") ones. dcosijpp_validate = np.ones((3, 3)) dcosijpp_dev = np.zeros((3, 3)) dcosijnn_validate = np.ones((3, 3)) dcosijnn_dev = np.zeros((3, 3)) # The non-diagonal elements to the power of 2 dcosij2_validate = np.ones((3, 3)) dcosij2_dev = np.zeros((3, 3)) self.system.time = 0.0 int_steps = 20 loops = 100 for _ in range(loops): self.system.integrator.run(steps=int_steps) dcosjj = np.zeros((3)) dcosjj2 = np.zeros((3)) dcosijpp = np.zeros((3, 3)) dcosijnn = np.zeros((3, 3)) dcosij2 = np.zeros((3, 3)) for ind in range(n): # Just a direction cosines functions averaging.. dir_cos = tests_common.rotation_matrix_quat(self.system, ind) for j in range(3): # the LHS of eq. (23) [Perrin1936]. dcosjj[j] += dir_cos[j, j] # the LHS of eq. (32) [Perrin1936]. dcosjj2[j] += dir_cos[j, j]**2.0 for i in range(3): if i != j: # the LHS of eq. (24) [Perrin1936]. dcosijpp[i, j] += dir_cos[i, i] * dir_cos[j, j] + \ dir_cos[i, j] * dir_cos[j, i] # the LHS of eq. (25) [Perrin1936]. dcosijnn[i, j] += dir_cos[i, i] * dir_cos[j, j] - \ dir_cos[i, j] * dir_cos[j, i] # the LHS of eq. (33) [Perrin1936]. dcosij2[i, j] += dir_cos[i, j]**2.0 dcosjj /= n dcosjj2 /= n dcosijpp /= n dcosijnn /= n dcosij2 /= n # Actual comparison. tolerance = 0.2 # Too small values of the direction cosines are out of interest # compare to 0..1 range. min_value = 0.14 # Eq. (23) [Perrin1936]. dcosjj_validate[0] = np.exp(-(D[1] + D[2]) * self.system.time) dcosjj_validate[1] = np.exp(-(D[0] + D[2]) * self.system.time) dcosjj_validate[2] = np.exp(-(D[0] + D[1]) * self.system.time) dcosjj_dev = np.absolute(dcosjj - dcosjj_validate) / dcosjj_validate for j in range(3): if np.absolute(dcosjj_validate[j]) < min_value: dcosjj_dev[j] = 0.0 # Eq. (24) [Perrin1936]. dcosijpp_validate[0, 1] = np.exp(-(4 * D[2] + D[1] + D[0]) * self.system.time) dcosijpp_validate[1, 0] = np.exp(-(4 * D[2] + D[1] + D[0]) * self.system.time) dcosijpp_validate[0, 2] = np.exp(-(4 * D[1] + D[2] + D[0]) * self.system.time) dcosijpp_validate[2, 0] = np.exp(-(4 * D[1] + D[2] + D[0]) * self.system.time) dcosijpp_validate[1, 2] = np.exp(-(4 * D[0] + D[2] + D[1]) * self.system.time) dcosijpp_validate[2, 1] = np.exp(-(4 * D[0] + D[2] + D[1]) * self.system.time) dcosijpp_dev = np.absolute(dcosijpp - dcosijpp_validate) / dcosijpp_validate for i in range(3): for j in range(3): if np.absolute(dcosijpp_validate[i, j]) < min_value: dcosijpp_dev[i, j] = 0.0 # Eq. (25) [Perrin1936]. dcosijnn_validate[0, 1] = np.exp(-(D[1] + D[0]) * self.system.time) dcosijnn_validate[1, 0] = np.exp(-(D[1] + D[0]) * self.system.time) dcosijnn_validate[0, 2] = np.exp(-(D[2] + D[0]) * self.system.time) dcosijnn_validate[2, 0] = np.exp(-(D[2] + D[0]) * self.system.time) dcosijnn_validate[1, 2] = np.exp(-(D[2] + D[1]) * self.system.time) dcosijnn_validate[2, 1] = np.exp(-(D[2] + D[1]) * self.system.time) dcosijnn_dev = np.absolute(dcosijnn - dcosijnn_validate) / dcosijnn_validate for i in range(3): for j in range(3): if np.absolute(dcosijnn_validate[i, j]) < min_value: dcosijnn_dev[i, j] = 0.0 # Eq. (30) [Perrin1936]. D0 = sum(D[:]) / 3.0 D1D1 = 0.0 for j in range(3): for i in range(3): if i != j: D1D1 += D[i] * D[j] D1D1 /= 6.0 # Technical workaround of a digital arithmetic issue for isotropic # particle if np.absolute( (D0**2 - D1D1) / (D0**2 + D1D1)) < self.round_error_prec: D1D1 *= (1.0 - 2.0 * self.round_error_prec) # Eq. (32) [Perrin1936]. dcosjj2_validate = 1. / 3. + (1. / 3.) * (1. + (D - D0) / (2. * np.sqrt(D0**2 - D1D1))) \ * np.exp(-6. * (D0 - np.sqrt(D0**2 - D1D1)) * self.system.time) \ + (1. / 3.) * (1. - (D - D0) / (2. * np.sqrt(D0**2 - D1D1))) \ * np.exp(-6. * (D0 + np.sqrt(D0**2 - D1D1)) * self.system.time) dcosjj2_dev = np.absolute(dcosjj2 - dcosjj2_validate) / dcosjj2_validate for j in range(3): if np.absolute(dcosjj2_validate[j]) < min_value: dcosjj2_dev[j] = 0.0 # Eq. (33) [Perrin1936]. dcosij2_validate[0, 1] = 1. / 3. - (1. / 6.) * (1. - (D[2] - D0) / (2. * np.sqrt(D0**2 - D1D1))) \ * np.exp(-6. * (D0 - np.sqrt(D0**2 - D1D1)) * self.system.time) \ - (1. / 6.) * (1. + (D[2] - D0) / (2. * np.sqrt(D0**2 - D1D1))) \ * np.exp(-6. * (D0 + np.sqrt(D0**2 - D1D1)) * self.system.time) dcosij2_validate[1, 0] = dcosij2_validate[0, 1] dcosij2_validate[0, 2] = 1. / 3. - (1. / 6.) * (1. - (D[1] - D0) / (2. * np.sqrt(D0**2 - D1D1))) \ * np.exp(-6. * (D0 - np.sqrt(D0**2 - D1D1)) * self.system.time) \ - (1. / 6.) * (1. + (D[1] - D0) / (2. * np.sqrt(D0**2 - D1D1))) \ * np.exp(-6. * (D0 + np.sqrt(D0**2 - D1D1)) * self.system.time) dcosij2_validate[2, 0] = dcosij2_validate[0, 2] dcosij2_validate[1, 2] = 1. / 3. - (1. / 6.) * (1. - (D[0] - D0) / (2. * np.sqrt(D0**2 - D1D1))) \ * np.exp(-6. * (D0 - np.sqrt(D0**2 - D1D1)) * self.system.time) \ - (1. / 6.) * (1. + (D[0] - D0) / (2. * np.sqrt(D0**2 - D1D1))) \ * np.exp(-6. * (D0 + np.sqrt(D0**2 - D1D1)) * self.system.time) dcosij2_validate[2, 1] = dcosij2_validate[1, 2] dcosij2_dev = np.absolute(dcosij2 - dcosij2_validate) / dcosij2_validate for i in range(3): for j in range(3): if np.absolute(dcosij2_validate[i, j]) < min_value: dcosij2_dev[i, j] = 0.0 for j in range(3): self.assertLessEqual( abs(dcosjj_dev[j]), tolerance, msg='Relative deviation dcosjj_dev[{0}] in a rotational ' 'diffusion is too large: {1}'.format(j, dcosjj_dev[j])) self.assertLessEqual( abs(dcosjj2_dev[j]), tolerance, msg='Relative deviation dcosjj2_dev[{0}] in a rotational ' 'diffusion is too large: {1}'.format(j, dcosjj2_dev[j])) for i in range(3): if i != j: self.assertLessEqual( abs(dcosijpp_dev[i, j]), tolerance, msg='Relative deviation dcosijpp_dev[{0},{1}] in a ' 'rotational diffusion is too large: {2}'.format( i, j, dcosijpp_dev[i, j])) self.assertLessEqual( abs(dcosijnn_dev[i, j]), tolerance, msg='Relative deviation dcosijnn_dev[{0},{1}] in a ' 'rotational diffusion is too large: {2}'.format( i, j, dcosijnn_dev[i, j])) self.assertLessEqual( abs(dcosij2_dev[i, j]), tolerance, msg='Relative deviation dcosij2_dev[{0},{1}] in a ' 'rotational diffusion is too large: {2}'.format( i, j, dcosij2_dev[i, j])) # Langevin Dynamics / Anisotropic def test_case_00(self): n = 800 self.rot_diffusion_param_setup() self.set_anisotropic_param() self.add_particles_setup(n) self.system.thermostat.set_langevin(kT=self.kT, gamma=self.gamma_global, seed=42) # Actual integration and validation run self.check_rot_diffusion(n) # Langevin Dynamics / Isotropic def test_case_01(self): n = 800 self.rot_diffusion_param_setup() self.set_isotropic_param() self.add_particles_setup(n) self.system.thermostat.set_langevin(kT=self.kT, gamma=self.gamma_global, seed=42) # Actual integration and validation run self.check_rot_diffusion(n) if "BROWNIAN_DYNAMICS" in espressomd.features(): # Brownian Dynamics / Isotropic def test_case_10(self): n = 800 self.system.thermostat.turn_off() self.rot_diffusion_param_setup() self.set_isotropic_param() self.add_particles_setup(n) self.system.thermostat.set_brownian(kT=self.kT, gamma=self.gamma_global, seed=42) self.system.integrator.set_brownian_dynamics() # Actual integration and validation run self.check_rot_diffusion(n)
# ESPResSo is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # # Tests particle property setters/getters from __future__ import print_function import espressomd import unittest as ut import numpy as np from tests_common import * if "ELECTROSTATICS" in espressomd.features() and "CUDA" in espressomd.features(): from espressomd.electrostatics import P3M_GPU class P3M_GPU_test(ut.TestCase): def runTest(self): es = espressomd.System() test_params = {} test_params["bjerrum_length"] = 2 test_params["cao"] = 2 test_params["inter"] = 3 test_params["r_cut"] = 0.9 test_params["accuracy"] = 1e-1 test_params["mesh"] = [10, 10, 10] test_params["epsilon"] = 20.0 test_params["mesh_off"] = [0.8, 0.8, 0.8] test_params["alpha"] = 1.1
# (at your option) any later version. # # ESPResSo is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # # Tests particle property setters/getters import espressomd import unittest as ut import numpy as np if "P3M_GPU" in espressomd.features(): from espressomd.electrostatics import P3M_GPU class P3M_GPU_test(ut.TestCase): es = espressomd.System() test_params = {} test_params["bjerrum_length"] = 2 test_params["cao"] = 2 test_params["inter"] = 3 test_params["r_cut"] = 0.9 test_params["accuracy"] = 1e-1 test_params["mesh"] = [10, 10, 10] test_params["epsilon"] = 20.0 test_params["mesh_off"] = [0.8, 0.8, 0.8] test_params["alpha"] = 1.1 test_params["tune"] = False
class ParticleProperties(ut.TestCase): # def __init__(self,particleId): # self.pid=particleId # the system which will be tested system = espressomd.System() # Particle id to work on pid = 17 # Error tolerance when comparing arrays/tuples... tol = 1E-9 def bondsMatch(self, inType, outType, inParams, outParams): """Check, if the bond type set and gotten back as well as the bond parameters set and gotten back match. Only check keys present in inParams. """ if inType != outType: return False for k in list(inParams.keys()): if k not in outParams: return False if outParams[k] != inParams[k]: return False return True def setUp(self): if not self.system.part.exists(self.pid): self.system.part.add(id=self.pid, pos=(0, 0, 0, 0)) def generateTestForBondParams(_bondId, _bondClass, _params): """Generates test cases for checking bond parameters set and gotten back from Es actually match. Only keys which are present in _params are checked 1st arg: Id of the bonded ia in Espresso to test on, i.e., 0,2,1... 2nd: Class of the bond potential to test, ie.e, FeneBond, HarmonicBond 3rd: Bond parameters as dictionary, i.e., {"k"=1.,"r_0"=0. """ bondId = _bondId bondClass = _bondClass params = _params def func(self): # This code is run at the execution of the generated function. # It will use the state of the variables in the outer function, # which was there, when the outer function was called self.system.bonded_inter[bondId] = bondClass(**params) outBond = self.system.bonded_inter[bondId] tnIn = bondClass(**params).type_number() tnOut = outBond.type_number() outParams = outBond.params self.assertTrue( self.bondsMatch(tnIn, tnOut, params, outParams), bondClass(**params).type_name() + ": value set and value gotten back differ for bond id " + str(bondId) + ": " + params.__str__() + " vs. " + outParams.__str__()) return func test_fene = generateTestForBondParams(0, FeneBond, { "r_0": 1.1, "k": 5.2, "d_r_max": 3. }) test_fene2 = generateTestForBondParams(1, FeneBond, { "r_0": 1.1, "k": 5.2, "d_r_max": 3. }) test_harmonic = generateTestForBondParams(0, HarmonicBond, { "r_0": 1.1, "k": 5.2 }) test_harmonic2 = generateTestForBondParams(0, HarmonicBond, { "r_0": 1.1, "k": 5.2, "r_cut": 1.3 }) if "ROTATION" in code_info.features(): test_harmonic_dumbbell = generateTestForBondParams( 0, HarmonicDumbbellBond, { "k1": 1.1, "k2": 2.2, "r_0": 1.5 }) test_harmonic_dumbbell2 = generateTestForBondParams( 0, HarmonicDumbbellBond, { "k1": 1.1, "k2": 2.2, "r_0": 1.5, "r_cut": 1.9 }) test_dihedral = generateTestForBondParams(0, Dihedral, { "mult": 3.0, "bend": 5.2, "phase": 3. }) if "BOND_ANGLE" in espressomd.features(): test_angle_harm = generateTestForBondParams(0, Angle_Harmonic, { "bend": 5.2, "phi0": 3.2 }) test_angle_cos = generateTestForBondParams(0, Angle_Cosine, { "bend": 5.2, "phi0": 3.2 }) test_angle_cossquare = generateTestForBondParams( 0, Angle_Cossquare, { "bend": 5.2, "phi0": 0. }) if "LENNARD_JONES" in espressomd.features(): test_subt_lj = generateTestForBondParams(0, Subt_Lj, { "k": 5.2, "r": 3.2 }) if "TABULATED" in espressomd.features(): test_tabulated = generateTestForBondParams(0, Tabulated, { "type": "distance", "filename": "lj1.tab" })
e_kin = e - e_pot print(" {} {} {} {}".format(time, e, e_pot, e_kin), file=f) def calc_temperature(system): E = system.analysis.energy()['total'] n_part = len(system.part) return 2. / 3. * E / n_part # check for necessary feature required_features = ["MASS", "TABULATED"] espressomd.assert_features(required_features) print("Program Information:\n{}\n".format(espressomd.features())) espresso_release = (espressomd.version.major(), espressomd.version.minor()) # set system properties: skin = 0.5 time_step = 0.002 friction = 5.0 int_steps = 900 eq_steps = 100 steps_per_int = 100 atomnumber, box, atompos = readgrofile('spce.gro') nm2Angstroem = 10 box_length = box * nm2Angstroem positions = atompos * nm2Angstroem mass = 18
class Non_bonded_interactionsTests(ut.TestCase): # def __init__(self,particleId): # self.pid=particleId # Handle to espresso system es = espressomd.System() def intersMatch(self, inType, outType, inParams, outParams): """Check, if the interaction type set and gotten back as well as the bond parameters set and gotten back match. Only check keys present in inParams. """ if inType != outType: print("Type mismatch:", inType, outType) return False for k in inParams.keys(): if k not in outParams: print(k, "missing from returned parameters") return False if outParams[k] != inParams[k]: print("Mismatch in parameter ", k, inParams[k], outParams[k]) return False return True def generateTestForNon_bonded_interaction(_partType1, _partType2, _interClass, _params, _interName): """Generates test cases for checking interaction parameters set and gotten back from Es actually match. Only keys which are present in _params are checked 1st and 2nd arg: Particle type ids to check on 3rd: Class of the interaction to test, ie.e, FeneBond, HarmonicBond 4th: Interaction parameters as dictionary, i.e., {"k"=1.,"r_0"=0. 5th: Name of the interaction property to set (i.e. "lennardJones") """ partType1 = _partType1 partType2 = _partType2 interClass = _interClass params = _params interName = _interName def func(self): # This code is run at the execution of the generated function. # It will use the state of the variables in the outer function, # which was there, when the outer function was called # Set parameters getattr(self.es.non_bonded_inter[partType1, partType2], interName).set_params(**params) # Read them out again outInter = getattr(self.es.non_bonded_inter[partType1, partType2], interName) outParams = outInter.get_params() self.assertTrue( self.intersMatch(interClass, type(outInter), params, outParams), interClass(**params).type_name() + ": value set and value gotten back differ for particle types " + str(partType1) + " and " + str(partType2) + ": " + params.__str__() + " vs. " + outParams.__str__()) return func test_lj1 = generateTestForNon_bonded_interaction( 0, 0, LennardJonesInteraction, { "epsilon": 1., "sigma": 2., "cutoff": 3., "shift": 4., "offset": 5., "min": 7. }, "lennard_jones") test_lj2 = generateTestForNon_bonded_interaction( 0, 0, LennardJonesInteraction, { "epsilon": 1.3, "sigma": 2.2, "cutoff": 3.4, "shift": 4.1, "offset": 5.1, "min": 7.1 }, "lennard_jones") test_lj3 = generateTestForNon_bonded_interaction( 0, 0, LennardJonesInteraction, { "epsilon": 1.3, "sigma": 2.2, "cutoff": 3.4, "shift": 4.1, "offset": 5.1, "min": 7.1 }, "lennard_jones") if "LENNARD_JONES_GENERIC" in espressomd.features(): test_ljgen1 = generateTestForNon_bonded_interaction( 0, 0, GenericLennardJonesInteraction, { "epsilon": 1., "sigma": 2., "cutoff": 3., "shift": 4., "offset": 5., "e1": 7, "e2": 8, "b1": 9., "b2": 10. }, "generic_lennard_jones") test_ljgen2 = generateTestForNon_bonded_interaction( 0, 0, GenericLennardJonesInteraction, { "epsilon": 1.1, "sigma": 2.1, "cutoff": 3.1, "shift": 4.1, "offset": 5.1, "e1": 71, "e2": 81, "b1": 9.1, "b2": 10.1 }, "generic_lennard_jones") test_ljgen3 = generateTestForNon_bonded_interaction( 0, 0, GenericLennardJonesInteraction, { "epsilon": 1.2, "sigma": 2.2, "cutoff": 3.2, "shift": 4.2, "offset": 5.2, "e1": 72, "e2": 82, "b1": 9.2, "b2": 10.2 }, "generic_lennard_jones") def test_forcecap(self): self.es.non_bonded_inter.set_force_cap(17.5) self.assertEqual(self.es.non_bonded_inter.get_force_cap(), 17.5)
def dissipation_param_setup(self, n): """ Setup the parameters for the following dissipation test. Parameters ---------- n : :obj:`int` Number of particles of the each type. There are 2 types. """ # Time self.system.time_step = 0.007 # Space box = 1.0 self.system.box_l = box, box, box if espressomd.has_features(("PARTIAL_PERIODIC", )): self.system.periodicity = 0, 0, 0 # NVT thermostat self.kT = 0.0 # The translational gamma isotropy is required here. # Global gamma for tests without particle-specific gammas. # # As far as the problem characteristic time is t0 ~ mass / gamma # and the Langevin equation finite-difference approximation is stable # only for time_step << t0, it is needed to set the gamma less than # some maximal value according to the value gamma_max. # Also, it cannot be very small (gamma_min), otherwise the thermalization will require # too much of the CPU time. Same: for all such gamma assignments throughout the test. # gamma_min = self.gamma_min gamma_max = self.gamma_max gamma_rnd = uniform(gamma_min, gamma_max) self.gamma_global = gamma_rnd, gamma_rnd, gamma_rnd # Additional test case for the specific global rotational gamma set. self.gamma_global_rot = uniform(gamma_min, gamma_max, 3) # Per-paricle values: self.kT_p = 0.0, 0.0 # Either translational friction isotropy is required # or both translational and rotational ones. # Otherwise these types of motion will interfere. # ..Let's test both cases depending on the particle index. self.gamma_tran_p[0, 0] = uniform(gamma_min, gamma_max) self.gamma_tran_p[0, 1] = self.gamma_tran_p[0, 0] self.gamma_tran_p[0, 2] = self.gamma_tran_p[0, 0] self.gamma_rot_p[0, :] = uniform(gamma_min, gamma_max, 3) self.gamma_tran_p[1, 0] = uniform(gamma_min, gamma_max) self.gamma_tran_p[1, 1] = self.gamma_tran_p[1, 0] self.gamma_tran_p[1, 2] = self.gamma_tran_p[1, 0] self.gamma_rot_p[1, 0] = uniform(gamma_min, gamma_max) self.gamma_rot_p[1, 1] = self.gamma_rot_p[1, 0] self.gamma_rot_p[1, 2] = self.gamma_rot_p[1, 0] # Particles self.mass = 12.74 self.J = 10.0, 10.0, 10.0 for i in range(n): for k in range(2): ind = i + k * n self.system.part.add(rotation=(1, 1, 1), pos=(0.0, 0.0, 0.0), id=ind) self.system.part[ind].v = 1.0, 1.0, 1.0 if "ROTATION" in espressomd.features(): self.system.part[ind].omega_body = 1.0, 1.0, 1.0 self.system.part[ind].mass = self.mass self.system.part[ind].rinertia = self.J
from __future__ import print_function import unittest as ut import numpy as np import espressomd if "ENGINE" in espressomd.features(): class SwimmerTest(ut.TestCase): def test(self): boxl = 12 sampsteps = 2000 tstep = 0.01 v_swim = 0.3 f_swim = 0.1 temp = 0.0 gamma = 1.0 pos_0 = np.array([boxl/2., boxl/2., 1.*boxl/3.]) pos_1 = np.array([boxl/2., boxl/2., 2.*boxl/3.]) def z_f(t,z0): return f_swim/gamma*(-1./gamma + t + (1./gamma)*np.exp(-gamma*t))+z0 def z_v(t,z0): return v_swim*(-1./gamma + t + (1./gamma)*np.exp(-gamma*t))+z0 S = espressomd.System() S.box_l = [boxl, boxl, boxl] S.cell_system.skin = 0.1
# # ESPResSo is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # # Tests particle property setters/getters import unittest as ut import espressomd import numpy as np from espressomd.interactions import LennardJonesInteraction if "LENNARD_JONES_GENERIC" in espressomd.features(): from espressomd.interactions import GenericLennardJonesInteraction class Non_bonded_interactionsTests(ut.TestCase): # def __init__(self,particleId): # self.pid=particleId # Handle to espresso system es = espressomd.System() def intersMatch(self, inType, outType, inParams, outParams): """Check, if the interaction type set and gotten back as well as the bond parameters set and gotten back match. Only check keys present in inParams. """
"genericLennardJones", ) test_ljgen3 = generateTestForNonBondedInteraction( 0, 0, GenericLennardJonesInteraction, { "epsilon": 1.2, "sigma": 2.2, "cutoff": 3.2, "shift": 4.2, "offset": 5.2, "e1": 72, "e2": 82, "b1": 9.2, "b2": 10.2, "lambda": 11.2, "delta": 12.2, }, "genericLennardJones", ) def test_forcecap(self): self.es.nonBondedInter.setForceCap(17.5) self.assertEqual(self.es.nonBondedInter.getForceCap(), 17.5) if __name__ == "__main__": print("Features: ", espressomd.features()) ut.main()
# # ESPResSo is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # # Tests particle property setters/getters import unittest as ut import espressomd import numpy as np from espressomd.interactions import LennardJonesInteraction if "LENNARD_JONES_GENERIC" in espressomd.features(): from espressomd.interactions import GenericLennardJonesInteraction class Non_bonded_interactionsTests(ut.TestCase): # def __init__(self,particleId): # self.pid=particleId # Handle to espresso system es = espressomd.System() def intersMatch(self, inType, outType, inParams, outParams): """Check, if the interaction type set and gotten back as well as the bond parameters set and gotten back match. Only check keys present in inParams. """ if inType != outType:
def dissipation_param_setup(self): """ Setup the parameters for the following dissipation test. """ ## Time self.es.time_step = 0.007 ## Space box = 1.0 self.es.box_l = box,box,box if espressomd.has_features(("PARTIAL_PERIODIC",)): self.es.periodicity = 0,0,0 ## NVT thermostat self.kT = 0.0 # The translational gamma isotropy is required here. # Global gamma for tests without particle-specific gammas. # # As far as the problem characteristic time is t0 ~ mass / gamma # and the Langevin equation finite-difference approximation is stable # only for time_step << t0, it is needed to set the gamma less than # some maximal value according to the value max_gamma_param. # Also, it cannot be very small (min_gamma_param), otherwise the thermalization will require # too much of the CPU time. Same: for all such gamma assignments throughout the test. # min_gamma_param = 0.5 max_gamma_param = 2.0/3.0 gamma_rnd = self.generate_scalar_ranged_rnd(min_gamma_param, max_gamma_param) self.gamma_global = gamma_rnd, gamma_rnd, gamma_rnd # Additional test case for the specific global rotational gamma set. self.gamma_global_rot = self.generate_vec_ranged_rnd(0.5,2.0/3.0) # Per-paricle values: self.kT_p = 0.0,0.0 # Either translational friction isotropy is required # or both translational and rotational ones. # Otherwise these types of motion will interfere. # ..Let's test both cases depending on the particle index. self.gamma_tran_p[0, 0] = self.generate_scalar_ranged_rnd(0.5,1.0) self.gamma_tran_p[0, 1] = self.gamma_tran_p[0, 0] self.gamma_tran_p[0, 2] = self.gamma_tran_p[0, 0] self.gamma_rot_p[0, :] = self.generate_vec_ranged_rnd(0.5,2.0/3.0) self.gamma_tran_p[1, 0] = self.generate_scalar_ranged_rnd(0.5,1.0) self.gamma_tran_p[1, 1] = self.gamma_tran_p[1, 0] self.gamma_tran_p[1, 2] = self.gamma_tran_p[1, 0] self.gamma_rot_p[1, 0] = self.generate_scalar_ranged_rnd(0.5,2.0/3.0) self.gamma_rot_p[1, 1] = self.gamma_rot_p[1, 0] self.gamma_rot_p[1, 2] = self.gamma_rot_p[1, 0] ## Particles self.mass = 12.74 self.J = 10.0,10.0,10.0 for i in range(2): self.es.part.add(rotation=(1,1,1), pos=(0.0,0.0,0.0), id=i) self.es.part[i].v = 1.0,1.0,1.0 if "ROTATION" in espressomd.features(): self.es.part[i].omega_body = 1.0,1.0,1.0 self.es.part[i].mass = self.mass self.es.part[i].rinertia = self.J
class ParticleProperties(ut.TestCase): # def __init__(self,particleId): # self.pid=particleId # Particle id to work on pid = 17 # Error tolerance when comparing arrays/tuples... tol = 1E-9 # Handle for espresso system es = espressomd.System() def arraysNearlyEqual(self, a, b): """Test, if the magnitude of the difference between two arrays is smaller than the tolerance""" # Check length if len(a) != len(b): return False # We have to use a loop, since we can't be sure, we're getting numpy arrays sum = 0. for i in range(len(a)): sum += abs(a[i] - b[i]) if sum > self.tol: return False return True def setUp(self): self.es.part[self.pid].pos = 0, 0, 0 self.es.bondedInter[0] = FeneBond(k=1, d_r_max=5) self.es.bondedInter[1] = FeneBond(k=1, d_r_max=5) def generateTestForVectorProperty(_propName, _value): """Generates test cases for vectorial particle properties such as position, velocity... 1st arg: name of the property (e.g., "pos"), 2nd array: value to be used for testing. Has to be numpy.array of floats """ # This is executed, when generateTestForVectorProperty() is called propName = _propName value = _value def func(self): # This code is run at the execution of the generated function. # It will use the state of the variables in the outer function, # which was there, when the outer function was called setattr(self.es.part[self.pid], propName, value) print(propName, value, getattr(self.es.part[self.pid], propName)) self.assertTrue( self.arraysNearlyEqual( getattr(self.es.part[self.pid], propName), value), propName + ": value set and value gotten back differ.") return func def generateTestForScalarProperty(_propName, _value): """Generates test cases for scalar particle properties such as type, mass, charge... 1st arg: name of the property (e.g., "type"), 2nd array: value to be used for testing. int or float """ # This is executed, when generateTestForVectorProperty() is called propName = _propName value = _value def func(self): # This code is run at the execution of the generated function. # It will use the state of the variables in the outer function, # which was there, when the outer function was called setattr(self.es.part[self.pid], propName, value) print(propName, value, getattr(self.es.part[self.pid], propName)) self.assertTrue( getattr(self.es.part[self.pid], propName) == value, propName + ": value set and value gotten back differ.") return func test_pos = generateTestForVectorProperty("pos", np.array([0.1, 0.2, 0.3])) test_v = generateTestForVectorProperty("v", np.array([0.2, 0.3, 0.4])) test_f = generateTestForVectorProperty("f", np.array([0.2, 0.3, 0.7])) test_type = generateTestForScalarProperty("type", int(3)) test_bonds_property = generateTestForScalarProperty( "bonds", ((0, 1), (1, 2))) if "MASS" in espressomd.features(): test_mass = generateTestForScalarProperty("mass", 1.3) if "ROTATION" in espressomd.features(): test_omega_lab = generateTestForVectorProperty("omega_lab", np.array([4., 2., 1.])) test_omega_body = generateTestForVectorProperty( "omega_body", np.array([4., 72., 1.])) test_torque_lab = generateTestForVectorProperty( "torque_lab", np.array([4., 72., 3.7])) # The tested value has to be nromalized! test_quat = generateTestForVectorProperty( "quat", np.array([0.5, 0.5, 0.5, 0.5])) # test_director=generateTestForVectorProperty("director",np.array([0.5,0.4,0.3])) if "ELECTROSTATICS" in espressomd.features(): test_charge = generateTestForScalarProperty("q", -19.7) if "DIPOLES" in espressomd.features(): test_dip = generateTestForVectorProperty("dip", np.array([0.5, -0.5, 3])) test_dipm = generateTestForScalarProperty("dipm", -9.7) if "VIRTUAL_SITES" in espressomd.features(): test_virtual = generateTestForScalarProperty("virtual", 1) if "VIRTUAL_SITES_RELATIVE" in espressomd.features(): test_zz_vs_relative = generateTestForScalarProperty( "vs_relative", ((0, 5.0)))
class CoulombCloudWall(ut.TestCase): """This compares p3m, p3m_gpu, scafacos_p3m and scafacos_p2nfft electrostatic forces and energy against stored data.""" S = espressomd.System() forces = {} tolerance = 1E-3 # Reference energy from p3m in the tcl test case reference_energy = 148.94229549 def setUp(self): self.S.box_l = (10, 10, 10) self.S.time_step = 0.01 self.S.skin = 0.4 # Clear actors that might be left from prev tests if len(self.S.actors): del self.S.actors[0] self.S.part.clear() data = np.genfromtxt("data/coulomb_cloud_wall_system.data") # Add particles to system and store reference forces in hash # Input format: id pos q f for particle in data: id = particle[0] pos = particle[1:4] q = particle[4] f = particle[5:] self.S.part.add(id=int(id), pos=pos, q=q) self.forces[id] = f def compare(self, method_name, energy=True): # Compare forces and energy now in the system to stored ones # Force force_abs_diff = 0. for p in self.S.part: force_abs_diff += abs(np.sqrt(sum((p.f - self.forces[p.id])**2))) force_abs_diff /= len(self.S.part) print method_name, "force difference", force_abs_diff # Energy if energy: energy_abs_diff = abs(self.S.analysis.energy( self.S)["total"] - self.reference_energy) print method_name, "energy difference", energy_abs_diff self.assertTrue(energy_abs_diff <= self.tolerance, "Absolte energy difference " + str(energy_abs_diff) + " too large for " + method_name) self.assertTrue(force_abs_diff <= self.tolerance, "Asbolute force difference " + str(force_abs_diff) + " too large for method " + method_name) # Tests for individual methods if "P3M" in espressomd.features(): def test_p3m(self): self.S.actors.add(P3M(bjerrum_length=1, r_cut=1.001, mesh=64, cao=7, alpha=2.70746, tune=False)) integrate(0) self.compare("p3m", energy=True) if "ELECTROSTATICS" in espressomd.features() and "CUDA" in espressomd.features(): def test_p3m_gpu(self): self.S.actors.add(P3M_GPU( bjerrum_length=1, r_cut=1.001, mesh=64, cao=7, alpha=2.70746, tune=False)) integrate(0) self.compare("p3m_gpu", energy=False) if "SCAFACOS" in espressomd.features(): if "p3m" in scafacos.available_methods(): def test_scafacos_p3m(self): self.S.actors.add(Scafacos(bjerrum_length=1, method_name="p3m", method_params={ "p3m_r_cut": 1.001, "p3m_grid": 64, "p3m_cao": 7, "p3m_alpha": 2.70746})) integrate(0) self.compare("scafacos_p3m", energy=True) if "p2nfft" in scafacos.available_methods(): def test_scafacos_p2nfft(self): self.S.actors.add(Scafacos(bjerrum_length=1, method_name="p2nfft", method_params={ "p2nfft_r_cut": 1.001, "tolerance_field": 1E-4})) integrate(0) self.compare("scafacos_p2nfft", energy=True) def test_zz_deactivation(self): # Is the energy 0, if no methods active self.assertTrue(self.S.analysis.energy(self.S)["total"] == 0.0)
import unittest as ut import numpy as np import espressomd from espressomd import thermostat from espressomd import integrate if "ENGINE" in espressomd.features(): class SwimmerTest(ut.TestCase): def test(self): boxl = 12 sampsteps = 2000 tstep = 0.01 v_swim = 0.3 f_swim = 0.1 temp = 0.0 gamma = 1.0 pos_0 = np.array([boxl / 2., boxl / 2., 1. * boxl / 3.]) pos_1 = np.array([boxl / 2., boxl / 2., 2. * boxl / 3.]) def z_f(t, z0): return f_swim / gamma * ( -1. / gamma + t + (1. / gamma) * np.exp(-gamma * t)) + z0 def z_v(t, z0): return v_swim * (-1. / gamma + t + (1. / gamma) * np.exp(-gamma * t)) + z0 S = espressomd.System()
self.s.part.add(id=0, pos=[0, 0, 0], type=0, q=+1.) self.s.part.add(id=1, pos=[1, 0, 0], type=0, q=-1.) # Small alpha means large short-range contribution self.s.actors.add(P3M(prefactor=1, r_cut=3.0, accuracy=1e-3, mesh=32, cao=7, alpha=0.1, tune=False)) # Only short-range part of the coulomb energy pair_energy = self.s.analysis.energy()[('coulomb', 0)] self.assertGreater(abs(pair_energy), 0.) self.s.integrator.run(0) pair_force = self.s.part[0].f[0] self.assertGreater(abs(pair_force), 0.) self.assertAlmostEqual(self.s.part[1].f[0], -pair_force, places=7) pair_pressure = self.s.analysis.pressure()[('coulomb', 0)] self.assertGreater(abs(pair_pressure), 0.) self.s.part[0].exclusions = [1] # Force and energy should not be changed by the exclusion self.s.integrator.run(0) self.assertAlmostEqual(self.s.part[0].f[0], pair_force, places=7) self.assertAlmostEqual(self.s.part[1].f[0], -pair_force, places=7) self.assertAlmostEqual(self.s.analysis.energy()[('coulomb', 0)], pair_energy, places=7) self.assertAlmostEqual(self.s.analysis.pressure()[('coulomb', 0)], pair_pressure, places=7) if __name__ == "__main__": print("Features: ", espressomd.features()) ut.main()
class CoulombCloudWall(ut.TestCase): if "ELECTROSTATICS" in espressomd.features(): """This compares p3m, p3m_gpu, scafacos_p3m and scafacos_p2nfft electrostatic forces and energy against stored data.""" S = espressomd.System(box_l=[1.0, 1.0, 1.0]) S.seed = S.cell_system.get_state()['n_nodes'] * [1234] np.random.seed(S.seed) forces = {} tolerance = 1E-3 # Reference energy from p3m in the tcl test case reference_energy = 2. * 148.94229549 def setUp(self): self.S.box_l = (10, 10, 20) self.S.time_step = 0.01 self.S.cell_system.skin = 0.4 # Clear actors that might be left from prev tests if self.S.actors: del self.S.actors[0] self.S.part.clear() data = np.genfromtxt( abspath("data/coulomb_cloud_wall_duplicated_system.data")) # Add particles to system and store reference forces in hash # Input format: id pos q f for particle in data: id = particle[0] pos = particle[1:4] q = particle[4] f = particle[5:] self.S.part.add(id=int(id), pos=pos, q=q) self.forces[id] = f def compare(self, method_name, energy=True): # Compare forces and energy now in the system to stored ones # Force force_abs_diff = 0. for p in self.S.part: force_abs_diff += abs( np.sqrt(sum((p.f - self.forces[p.id])**2))) force_abs_diff /= len(self.S.part) # Energy if energy: energy_abs_diff = abs(self.S.analysis.energy()["total"] - self.reference_energy) self.assertTrue( energy_abs_diff <= self.tolerance, "Absolute energy difference " + str(energy_abs_diff) + " too large for " + method_name) self.assertTrue( force_abs_diff <= self.tolerance, "Absolute force difference " + str(force_abs_diff) + " too large for method " + method_name) # Tests for individual methods if "P3M" in espressomd.features(): def test_p3m(self): self.S.actors.add( espressomd.electrostatics.P3M(prefactor=1, r_cut=1.001, accuracy=1e-3, mesh=[64, 64, 128], cao=7, alpha=2.70746, tune=False)) self.S.integrator.run(0) self.compare("p3m", energy=True) @ut.skipIf(not espressomd.gpu_available(), "No gpu") def test_p3m_gpu(self): if str(espressomd.cuda_init.CudaInitHandle().device_list[0] ) == "Device 687f": print("Test skipped on AMD GPU") return self.S.actors.add( espressomd.electrostatics.P3MGPU(prefactor=1, r_cut=1.001, accuracy=1e-3, mesh=[64, 64, 128], cao=7, alpha=2.70746, tune=False)) self.S.integrator.run(0) self.compare("p3m_gpu", energy=False) def test_zz_deactivation(self): # Is the energy 0, if no methods active self.assertTrue(self.S.analysis.energy()["total"] == 0.0)
# along with this program. If not, see <http://www.gnu.org/licenses/>. # """ This sample illustrates how particles of interest can be accessed via slicing. """ import espressomd from espressomd import thermostat import numpy as np print(""" ======================================================= = slice_input.py = ======================================================= Program Information:""") print(espressomd.features()) # System parameters ############################################################# box_l = 10.0 # Integration parameters ############################################################# system = espressomd.System(box_l=[box_l] * 3) system.set_random_state_PRNG() #system.seed = system.cell_system.get_state()['n_nodes'] * [1234] np.random.seed(seed=system.seed) system.time_step = 0.01
def check_fluctuation_dissipation(self,n): """ Check the fluctuation-dissipation relations: thermalization and diffusion properties. Parameters ---------- n : :obj:`int` Number of particles of the each type. There are 2 types. """ ## The thermalization and diffusion test # Checks if every degree of freedom has 1/2 kT of energy, even when # mass and inertia tensor are active # Check the factual translational diffusion. # # matrices: [2 types of particless] x [3 dimensions X Y Z] # velocity^2, omega^2, position^2 v2 = np.zeros((2, 3)) o2 = np.zeros((2, 3)) dr2 = np.zeros((2, 3)) # Variance to compare with: sigma2_tr = np.zeros((2)) # Comparable variance: dr_norm = np.zeros((2)) pos0 = np.zeros((2 * n, 3)) for p in range(n): for k in range(2): ind = p + k * n pos0[ind, :] = self.es.part[ind].pos dt0 = self.mass / self.gamma_tran_p_validate loops = 250 print("Thermalizing...") therm_steps = 20 self.es.integrator.run(therm_steps) print("Measuring...") int_steps = 5 for i in range(loops): self.es.integrator.run(int_steps) # Get kinetic energy in each degree of freedom for all particles for p in range(n): for k in range(2): ind = p + k * n v = self.es.part[ind].v if "ROTATION" in espressomd.features(): o = self.es.part[ind].omega_body o2[k, :] = o2[k, :] + np.power(o[:], 2) pos = self.es.part[ind].pos v2[k, :] = v2[k, :] + np.power(v[:], 2) dr2[k, :] = np.power((pos[:] - pos0[ind, :]), 2) dt = (int_steps * (i + 1) + therm_steps) * \ self.es.time_step # translational diffusion variance: after a closed-form # integration of the Langevin EOM; # ref. the eq. (10.2.26) N. Pottier, https://doi.org/10.1007/s10955-010-0114-6 (2010) # after simple transformations and the dimensional model matching (cf. eq. (10.1.1) there): sigma2_tr[k] = 0.0 for j in range(3): sigma2_tr[k] += self.D_tran_p_validate[k, j] * (2.0 * dt + dt0[k, j] * (- 3.0 + 4.0 * math.exp(- dt / dt0[k, j]) - math.exp(- 2.0 * dt / dt0[k, j]))) dr_norm[k] += (sum(dr2[k, :]) - sigma2_tr[k]) / sigma2_tr[k] tolerance = 0.15 Ev = 0.5 * self.mass * v2 / (n * loops) Eo = 0.5 * self.J * o2 / (n * loops) dv = np.zeros((2)) do = np.zeros((2)) do_vec = np.zeros((2, 3)) for k in range(2): dv[k] = sum(Ev[k, :]) / (3.0 * self.halfkT_p_validate[k]) - 1.0 do[k] = sum(Eo[k, :]) / (3.0 * self.halfkT_p_validate[k]) - 1.0 do_vec[k, :] = Eo[k, :] / self.halfkT_p_validate[k] - 1.0 dr_norm /= (n * loops) for k in range(2): print("\n") print("k = " + str(k)) self.assertLessEqual( abs( dv[k]), tolerance, msg='Relative deviation in translational energy too large: {0}'.format( dv[k])) if "ROTATION" in espressomd.features(): self.assertLessEqual( abs( do[k]), tolerance, msg='Relative deviation in rotational energy too large: {0}'.format( do[k])) self.assertLessEqual(abs( do_vec[k, 0]), tolerance, msg='Relative deviation in rotational energy per the body axis X is too large: {0}'.format(do_vec[k, 0])) self.assertLessEqual(abs( do_vec[k, 1]), tolerance, msg='Relative deviation in rotational energy per the body axis Y is too large: {0}'.format(do_vec[k, 1])) self.assertLessEqual(abs( do_vec[k, 2]), tolerance, msg='Relative deviation in rotational energy per the body axis Z is too large: {0}'.format(do_vec[k, 2])) self.assertLessEqual( abs( dr_norm[k]), tolerance, msg='Relative deviation in translational diffusion is too large: {0}'.format( dr_norm[k]))