def test_create_seed_nonperiodic(): system, pars = get_system('alanine') configuration = Configuration(system, pars) seed_covalent = configuration.create_seed(kind='covalent') ff = yaff_generate(seed_covalent) energy_covalent = ff.compute() seed_dispersion = configuration.create_seed(kind='dispersion') ff = yaff_generate(seed_dispersion) energy_dispersion = ff.compute() seed_electrostatic = configuration.create_seed(kind='electrostatic') ff = yaff_generate(seed_electrostatic) energy_electrostatic = ff.compute() seed_nonbonded = configuration.create_seed(kind='nonbonded') ff = yaff_generate(seed_nonbonded) energy_nonbonded = ff.compute() seed_full = configuration.create_seed(kind='all') ff = yaff_generate(seed_full) energy_full = ff.compute() assert abs(energy_covalent) > 0.0 assert abs(energy_dispersion) > 0.0 assert abs(energy_electrostatic) > 0.0 np.testing.assert_almost_equal( energy_nonbonded, energy_dispersion + energy_electrostatic, ) np.testing.assert_almost_equal( energy_full, energy_covalent + energy_nonbonded, )
def test_create_seed_periodic(): system, pars = get_system('cau13') configuration = Configuration(system, pars) # change parameters randomly with pytest.raises(ValueError): # cell is too small configuration.supercell = [3, 1, 1] configuration.rcut = 12.0 assert configuration.interaction_radius == 12.0 # should change too configuration.switch_width = 5.0 configuration.tailcorrections = False seed_covalent = configuration.create_seed(kind='covalent') ff = yaff_generate(seed_covalent) energy_covalent = ff.compute() seed_dispersion = configuration.create_seed(kind='dispersion') ff = yaff_generate(seed_dispersion) energy_dispersion = ff.compute() seed_electrostatic = configuration.create_seed(kind='electrostatic') ff = yaff_generate(seed_electrostatic) energy_electrostatic = ff.compute() seed_nonbonded = configuration.create_seed(kind='nonbonded') ff = yaff_generate(seed_nonbonded) energy_nonbonded = ff.compute() seed_full = configuration.create_seed(kind='all') ff = yaff_generate(seed_full) energy_full = ff.compute() assert abs(energy_covalent) > 0.0 assert abs(energy_dispersion) > 0.0 assert abs(energy_electrostatic) > 0.0 np.testing.assert_almost_equal( energy_nonbonded, energy_dispersion + energy_electrostatic, ) np.testing.assert_almost_equal( energy_full, energy_covalent + energy_nonbonded, )
def test_save_load_pdb(tmp_path): system, pars = get_system('mil53') configuration = Configuration(system, pars) # YAFF and OpenMM use a different switching function. If it is disabled, # the results between both are identical up to 6 decimals configuration.switch_width = 0.0 # disable switching configuration.rcut = 10.0 # request cutoff of 10 angstorm configuration.interaction_radius = 11.0 #configuration.update_properties(configuration.write()) conversion = ExplicitConversion(pme_error_thres=5e-4) seed_mm = conversion.apply(configuration, seed_kind='all') seed_yaff = configuration.create_seed(kind='all') topology, pos = configuration.create_topology() box = seed_yaff.system.cell._get_rvecs() / molmod.units.angstrom wrapper_mm = OpenMMForceFieldWrapper.from_seed(seed_mm, 'Reference') wrapper_yaff = YaffForceFieldWrapper.from_seed(seed_yaff) assert wrapper_yaff.periodic # system should not be considered periodic assert wrapper_mm.periodic # system should not be considered periodic #positions = seed_yaff.system.pos.copy() / molmod.units.angstrom #rvecs = seed_yaff.system.cell._get_rvecs().copy() / molmod.units.angstrom e0, f0 = wrapper_mm.evaluate(pos, box, do_forces=True) e1, f1 = wrapper_yaff.evaluate(pos, box, do_forces=True) assert np.allclose(e0, e1, rtol=1e-3) path_pdb = tmp_path / 'top.pdb' mm.app.PDBFile.writeFile( topology, pos * unit.angstrom, open(path_pdb, 'w+'), keepIds=True, ) pdb = mm.app.PDBFile(str(path_pdb)) positions = pdb.getPositions(asNumpy=True).value_in_unit(unit.angstrom) a, b, c = pdb.getTopology().getPeriodicBoxVectors() rvecs = np.array([ a.value_in_unit(unit.angstrom), b.value_in_unit(unit.angstrom), c.value_in_unit(unit.angstrom) ]) e2, f2 = wrapper_mm.evaluate(positions, rvecs, do_forces=True) e3, f3 = wrapper_yaff.evaluate(positions, rvecs, do_forces=True) assert np.allclose(e2, e3, rtol=1e-3) assert np.allclose(e1, e3, rtol=1e-4) # rounding errors during saving pdb assert np.allclose(e0, e2, rtol=1e-4)
def test_nonperiodic(): systems = ['alanine'] platforms = ['Reference'] seed_kinds = ['covalent', 'dispersion', 'electrostatic'] tolerance = { ('Reference', 'covalent'): 1e-6, ('Reference', 'dispersion'): 1e-6, ('Reference', 'electrostatic'): 1e-6, #('Cuda', 'covalent'): 1e-5, #('Cuda', 'dispersion'): 1e-5, #('Cuda', 'electrostatic'): 1e-5, } nstates = 10 disp_ampl = 1.0 box_ampl = 1.0 for name in systems: for platform in platforms: for kind in seed_kinds: system, pars = get_system(name) configuration = Configuration(system, pars) tol = tolerance[(platform, kind)] conversion = ExplicitConversion() seed_mm = conversion.apply(configuration, seed_kind=kind) seed_yaff = configuration.create_seed(kind=kind) wrapper_mm = OpenMMForceFieldWrapper.from_seed( seed_mm, platform) wrapper_yaff = YaffForceFieldWrapper.from_seed(seed_yaff) assert not wrapper_yaff.periodic # system should not be considered periodic assert not wrapper_mm.periodic # system should not be considered periodic pos = seed_yaff.system.pos.copy() for i in range(nstates): dpos = np.random.uniform(-disp_ampl, disp_ampl, size=pos.shape) energy_mm, forces_mm = wrapper_mm.evaluate( (pos + dpos) / molmod.units.angstrom, ) energy, forces = wrapper_yaff.evaluate( (pos + dpos) / molmod.units.angstrom, ) assert_tol(energy, energy_mm, tol) assert_tol(forces, forces_mm, 10 * tol)
def test_wrapper_openmm_mic(): system, pars = get_system('mil53') configuration = Configuration(system, pars) kind = 'all' # YAFF and OpenMM use a different switching function. If it is disabled, # the results between both are identical up to 6 decimals configuration.switch_width = 0.0 # disable switching configuration.rcut = 10.0 # request cutoff of 10 angstorm configuration.cell_interaction_radius = 10.0 configuration.supercell = [2, 3, 5] configuration.update_properties(configuration.write()) conversion = ExplicitConversion(pme_error_thres=1e-5) seed_mm = conversion.apply(configuration, seed_kind=kind) wrapper = OpenMMForceFieldWrapper.from_seed(seed_mm, 'Reference') u = molmod.units.angstrom seed_yaff = configuration.create_seed(kind=kind) positions = seed_yaff.system.pos.copy() / u rvecs = seed_yaff.system.cell._get_rvecs().copy() / u e, _ = wrapper.evaluate(positions, rvecs, do_forces=True) # make random periodic displacements for i in range(5): coefficients = np.random.randint(-3, high=3, size=(3, 1)) atom = np.random.randint(0, high=seed_yaff.system.natom, size=(10,)) positions[atom, :] += np.sum(coefficients * rvecs, axis=0) e_ = wrapper.evaluate(positions, rvecs, do_forces=False) assert np.allclose(e, e_) # make random periodic displacements and rewrap coordinates for i in range(5): coefficients = np.random.randint(-3, high=3, size=(3, 1)) atom = np.random.randint(0, high=seed_yaff.system.natom, size=(10,)) positions[atom, :] += np.sum(coefficients * rvecs, axis=0) wrap_coordinates(positions, rvecs, rectangular=True) e_ = wrapper.evaluate(positions, rvecs, do_forces=False) assert np.allclose(e, e_)
def test_periodic(): systems = ['uio66', 'cau13', 'mil53', 'ppycof', 'cof5', 'mof5'] platforms = ['Reference'] seed_kinds = ['covalent', 'dispersion', 'electrostatic'] # systematic constant offset in dispersion energy for COFs, unclear why tolerance = { ('Reference', 'covalent'): 1e-6, # some MM3 terms have error 1e-7 ('Reference', 'dispersion'): 1e-2, # some MM3 terms have error 1e-3 ('Reference', 'electrostatic'): 1e-3, #('CUDA', 'covalent'): 1e-3, #('CUDA', 'dispersion'): 1e-3, #('CUDA', 'electrostatic'): 1e-3, } nstates = 5 disp_ampl = 0.3 box_ampl = 0.3 for name in systems: for platform in platforms: for kind in seed_kinds: system, pars = get_system(name) configuration = Configuration(system, pars) tol = tolerance[(platform, kind)] # YAFF and OpenMM use a different switching function. If it is disabled, # the results between both are identical up to 6 decimals configuration.switch_width = 0.0 # disable switching configuration.rcut = 13.0 # request cutoff of 13 angstorm configuration.interaction_radius = 15.0 configuration.update_properties(configuration.write()) conversion = ExplicitConversion(pme_error_thres=5e-4) seed_mm = conversion.apply(configuration, seed_kind=kind) seed_yaff = configuration.create_seed(kind=kind) wrapper_mm = OpenMMForceFieldWrapper.from_seed( seed_mm, platform) wrapper_yaff = YaffForceFieldWrapper.from_seed(seed_yaff) assert wrapper_yaff.periodic # system should not be considered periodic assert wrapper_mm.periodic # system should not be considered periodic pos = seed_yaff.system.pos.copy() rvecs = seed_yaff.system.cell._get_rvecs().copy() for i in range(nstates): dpos = np.random.uniform(-disp_ampl, disp_ampl, size=pos.shape) drvecs = np.random.uniform(-box_ampl, box_ampl, size=rvecs.shape) drvecs[0, 1] = 0 drvecs[0, 2] = 0 drvecs[1, 2] = 0 tmp = rvecs + drvecs reduce_box_vectors(tmp) energy_mm, forces_mm = wrapper_mm.evaluate( (pos + dpos) / molmod.units.angstrom, rvecs=tmp / molmod.units.angstrom, ) energy, forces = wrapper_yaff.evaluate( (pos + dpos) / molmod.units.angstrom, rvecs=tmp / molmod.units.angstrom, ) assert_tol(energy, energy_mm, tol) assert_tol(forces, forces_mm, 10 * tol)
def test_topology_templates(tmp_path): def check_consistency_system_topology(system, topology): assert system.natom == len(list(topology.atoms())) for i, atom in zip(range(system.natom), topology.atoms()): assert system.numbers[i] == atom.element._atomic_number assert system.bonds.shape[0] == len(list(topology.bonds())) bonds_tuples = [tuple(sorted(list(bond))) for bond in system.bonds] for bond in topology.bonds(): indices_top = tuple(sorted((bond[0].index, bond[1].index))) bonds_tuples.remove(indices_top) assert len(bonds_tuples) == 0 system, pars = get_system('methane') configuration = Configuration(system, pars, topology=None) assert len(configuration.templates) == 1 assert len(configuration.templates[0]) == 5 # five atoms for CH4 template nresidues = np.sum([len(r) for r in configuration.residues.values()]) supercell = [3, 1, 2] configuration.supercell = supercell top, _ = configuration.create_topology() assert len(list(top.residues())) == np.prod(supercell) * nresidues seed = configuration.create_seed() check_consistency_system_topology(seed.system, top) system, pars = get_system('uio66') configuration = Configuration(system, pars, topology=None) assert len(configuration.templates) == 1 assert len(configuration.templates[0]) == system.natom supercell = [2, 2, 2] configuration.supercell = supercell top, positions = configuration.create_topology() assert len(list(top.residues())) == np.prod(supercell) seed = configuration.create_seed() check_consistency_system_topology(seed.system, top) assert np.allclose(positions, seed.system.pos / molmod.units.angstrom) (system, topology), pars = get_system('polymer') configuration = Configuration(system, pars, topology=topology) assert len(configuration.templates) == 3 top, positions = configuration.create_topology() assert len(list(top.residues())) == len(list(topology.residues())) seed = configuration.create_seed() check_consistency_system_topology(seed.system, top) assert np.allclose(positions, seed.system.pos / molmod.units.angstrom) a, b, c = top.getPeriodicBoxVectors() box = np.array([ a.value_in_unit(unit.angstrom), b.value_in_unit(unit.angstrom), c.value_in_unit(unit.angstrom), ]) assert np.allclose(box, seed.system.cell._get_rvecs() / molmod.units.angstrom) # test nonperiodic system, pars = get_system('alanine') configuration = Configuration(system, pars) assert len(configuration.templates) == 1 top, positions = configuration.create_topology() seed = configuration.create_seed() check_consistency_system_topology(seed.system, top) assert np.allclose(positions, seed.system.pos / molmod.units.angstrom)