示例#1
0
def test_short_simulation(tmp_path):
    system, pars = get_system('uio66')
    configuration = Configuration(system, pars)

    # conversion
    conversion = ExplicitConversion()
    openmm_seed = conversion.apply(configuration)
    system = openmm_seed.get_system() # necessary to create Simulation object
    topology, positions = configuration.create_topology()
    a, b, c = topology.getPeriodicBoxVectors()

    # instantiate simulation for each platform
    platforms = ['Reference', 'CPU', 'CUDA', 'OpenCL']
    for name in platforms:
        integrator = mm.LangevinMiddleIntegrator(
                300 * unit.kelvin, # temperature
                0.1 * unit.picosecond, # friction coefficient
                0.5 * unit.femtosecond, # step size
                )
        try:
            platform = mm.Platform.getPlatformByName(name)
        except mm.OpenMMException:
            continue
        simulation = mm.app.Simulation(
                topology,
                system,
                integrator,
                platform,
                )
        simulation.context.setPositions(positions)
        #simulation.context.setPeriodicBoxVectors(box[0], box[1], box[2])
        simulation.context.setPeriodicBoxVectors(a, b, c)
        simulation.step(20)
def test_update_properties(tmp_path):
    system, pars = get_system('mil53')
    configuration = Configuration(system, pars)

    config = configuration.write()
    config['yaff']['rcut'] = 15.0
    config['yaff']['interaction_radius'] = 15.0
    configuration.update_properties(config)
    assert configuration.rcut == 15.0
def test_initialize_nonperiodic(tmp_path):
    system, pars = get_system('alanine')
    configuration = Configuration(system, pars)
    configuration.log_system()

    # write defaults
    path_config = tmp_path / 'config.yml'
    config = configuration.write(path_config)
    with open(path_config, 'r') as f:
        content = f.read()
    assert content == """yaff: {}\n"""
示例#4
0
def save(cwd, input_files, file_formats):
    assert 'chk' in input_files
    assert 'txt' in input_files
    assert 'yml' in input_files
    configuration = Configuration.from_files(**input_files)

    logger.info('saving configured system in the following formats:')
    for file_format in file_formats:
        logger.info('\t\t' + file_format)
    logger.info(
        'If the system is periodic, its box vectors are stored in reduced form'
    )
    seed = configuration.create_seed()
    for file_format in file_formats:
        path_file = cwd / ('configured_system.' + file_format)
        if path_file.exists():
            path_file.unlink()
        if (file_format == 'xyz') or (file_format == 'h5'):
            seed.system.to_file(str(path_file))
        elif file_format == 'pdb':
            topology, positions = configuration.create_topology()
            path_pdb = cwd / 'topology.pdb'
            if path_pdb.exists():
                path_pdb.unlink()
            mm.app.PDBFile.writeFile(
                topology,
                positions * unit.angstrom,
                open(path_pdb, 'w+'),
                keepIds=True,
            )
示例#5
0
def initialize(cwd, input_files):
    assert 'chk' in input_files
    assert 'txt' in input_files
    path_yml = cwd / 'config.yml'
    if path_yml.exists():  # remove file if it exists
        path_yml.unlink()
    default_classes = [  # classes for which to initialize .yml keywords
        ExplicitConversion,
        SinglePointValidation,
        StressValidation,
    ]

    # initialize Configuration based on defaults; log
    configuration = Configuration.from_files(**input_files)
    configuration.log_system()
    configuration.log_config()
    logger.info('writing configuration file to')
    logger.info(str(path_yml))
    configuration.write(path_yml)
    for default in default_classes:
        default().write(path_yml)

    # add annotations to config file for clarity; this cannot be done using
    # pyyaml and therefore proceeds manually
    add_header_to_config(path_yml)
    configuration.annotate(path_yml)
    for default in default_classes:
        default().annotate(path_yml)
示例#6
0
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_from_files(tmp_path):
    system, pars = get_system('mil53')
    configuration = Configuration(system, pars)

    configuration.write(tmp_path / 'config.yml')
    system.to_file(str(tmp_path / 'system.chk'))
    with open(tmp_path / 'pars.txt', 'w+') as f:
        f.write(pars)

    path_system = tmp_path / 'system.chk'
    path_pars   = tmp_path / 'pars.txt'
    path_config = tmp_path / 'config.yml'
    configuration = Configuration.from_files(
            chk=path_system,
            txt=path_pars,
            yml=path_config,
            )
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,
            )
示例#9
0
def validate(cwd, input_files):
    assert 'chk' in input_files
    assert 'txt' in input_files
    assert 'yml' in input_files
    configuration = Configuration.from_files(**input_files)
    configuration.log_config()
    conversion = load_conversion(input_files['yml'])
    validations = load_validations(input_files['yml'])
    for validation in validations:
        validation.run(configuration, conversion)
示例#10
0
def test_check_compatibility():
    system, _ = get_system('lennardjones')
    conversion = ExplicitConversion()
    seed_kind = 'dispersion'

    # generate pars with unsupported prefix
    pars_unsupported = """
    BLAAA:UNIT SIGMA angstrom
    BLAAA:UNIT EPSILON kcalmol
    BLAAA:SCALE 1 1.0
    BLAAA:SCALE 2 1.0
    BLAAA:SCALE 3 1.0

    # ---------------------------------------------
    # KEY      ffatype  SIGMA  EPSILON  ONLYPAULI
    # ---------------------------------------------

    BLAAA:PARS      C     2.360   0.116      0"""

    with pytest.raises(AssertionError):
        configuration = Configuration(system, pars_unsupported)

    # generate pars with unsupported scaling
    pars_unsupported = """
    LJ:UNIT SIGMA angstrom
    LJ:UNIT EPSILON kcalmol
    LJ:SCALE 1 0.5
    LJ:SCALE 2 1.0
    LJ:SCALE 3 1.0

    # ---------------------------------------------
    # KEY      ffatype  SIGMA  EPSILON  ONLYPAULI
    # ---------------------------------------------

    LJ:PARS      C     2.360   0.116      0"""

    configuration = Configuration(system, pars_unsupported)
    with pytest.raises(AssertionError):
        seed_mm = conversion.apply(configuration, seed_kind=seed_kind)
示例#11
0
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_)
示例#12
0
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)
示例#13
0
def test_get_prefixes():
    system, pars = get_system('cau13')
    configuration = Configuration(system, pars)

    prefixes = configuration.get_prefixes('all')
    covalent_prefixes = configuration.get_prefixes('covalent')
    dispersion_prefixes = configuration.get_prefixes('dispersion')
    electrostatic_prefixes = configuration.get_prefixes('electrostatic')
    nonbonded_prefixes = configuration.get_prefixes('nonbonded')

    _ = dispersion_prefixes + electrostatic_prefixes
    assert tuple(sorted(_)) == tuple(sorted(nonbonded_prefixes))
    __ = covalent_prefixes + nonbonded_prefixes
    assert tuple(sorted(__)) == tuple(sorted(prefixes))
示例#14
0
def convert(cwd, input_files, seed_kind, full):
    assert 'chk' in input_files
    assert 'txt' in input_files
    assert 'yml' in input_files
    configuration = Configuration.from_files(**input_files)
    configuration.log_config()
    conversion = load_conversion(input_files['yml'])

    if conversion.kind == 'explicit':
        path_xml = cwd / 'system.xml'
        logger.info('saving OpenMM System object to ')
        logger.info(path_xml)
        openmm_seed = conversion.apply(configuration, seed_kind)
        openmm_seed.serialize_system(path_xml)
    elif conversion.kind == 'implicit':
        openmm_seed = conversion.apply(configuration, seed_kind)
        path_xml = cwd / 'ff.xml'
        logger.info('saving OpenMM ForceField object to ')
        logger.info(path_xml)
        openmm_seed.serialize_forcefield(path_xml)
        path_xml = cwd / 'system.xml'
        logger.info('saving OpenMM ForceField object to ')
        logger.info(path_xml)
        openmm_seed.serialize_system(path_xml)

    if full:  # write additional files
        topology, positions = configuration.create_topology()
        path_pdb = cwd / 'topology.pdb'
        if path_pdb.exists():
            path_pdb.unlink()
        mm.app.PDBFile.writeFile(
            topology,
            positions * unit.angstrom,
            open(path_pdb, 'w+'),
            keepIds=True,
        )
示例#15
0
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)
示例#16
0
def test_implicit_nonperiodic():
    system, pars = get_system('alanine')
    configuration = Configuration(system, pars)

    conversion = ImplicitConversion()
    seed_mm = conversion.apply(configuration, seed_kind='all')
示例#17
0
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)
示例#18
0
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,
            )