Ejemplo n.º 1
0
    def test_spce_xml(self):
        spce = ForceField(get_path('spce.xml'))

        assert len(spce.atom_types) == 2
        assert len(spce.bond_types) == 1
        assert len(spce.angle_types) == 1
        assert len(spce.dihedral_types) == 0

        # Store expected expressions in list
        ref_exprs = [sympy.sympify(expr) for expr in [
            "4*epsilon*((sigma/r)**12 - (sigma/r)**6)",
            "0.5 * k * (r-r_eq)**2",
            "0.5 * k * (theta-theta_eq)**2",
            ]
        ]

        assert allclose(spce.atom_types['opls_116'].charge, -0.8476 * u.elementary_charge)
        assert allclose(spce.atom_types['opls_117'].charge, 0.4238 * u.elementary_charge)

        assert sympy.simplify(spce.atom_types['opls_116'].expression - ref_exprs[0]) == 0
        assert sympy.simplify(spce.atom_types['opls_117'].expression - ref_exprs[0]) == 0
        assert sympy.simplify(spce.bond_types['opls_116~opls_117'].expression - ref_exprs[1]) == 0
        assert sympy.simplify(spce.angle_types['opls_117~opls_116~opls_117'].expression - ref_exprs[2]) == 0

        assert allclose(spce.atom_types['opls_116'].parameters['sigma'], 0.316557 * u.nm)
        assert allclose(spce.atom_types['opls_116'].parameters['epsilon'], 0.650194 * u.Unit('kJ/mol'))
        assert allclose(spce.atom_types['opls_117'].parameters['sigma'], 0.1 * u.nm)
        assert allclose(spce.atom_types['opls_117'].parameters['epsilon'], 0.0 * u.Unit('kJ/mol'))

        assert allclose(spce.bond_types['opls_116~opls_117'].parameters['r_eq'], 0.1 * u.nm)
        assert allclose(spce.bond_types['opls_116~opls_117'].parameters['k'], 345000.0 * u.Unit('kJ/(mol*nm**2)'))

        assert allclose(spce.angle_types['opls_117~opls_116~opls_117'].parameters['theta_eq'], 109.47 * u.degree)
        assert allclose(spce.angle_types['opls_117~opls_116~opls_117'].parameters['k'], 383.0 * u.Unit('kJ/mol/rad**2'))
Ejemplo n.º 2
0
 def test_new_atom_type(self, charge, mass):
     new_type = AtomType(name='mytype', charge=charge, mass=mass,
             parameters={'sigma': 1 * u.nm,
                 'epsilon': 10 * u.Unit('kcal / mol')},
             independent_variables={'r'})
     assert new_type.name == 'mytype'
     assert allclose(new_type.charge, charge)
     assert allclose(new_type.parameters['sigma'], 1 * u.nm)
     assert allclose(new_type.parameters['epsilon'], 10 * u.Unit('kcal / mol'))
     assert allclose(new_type.mass, mass)
Ejemplo n.º 3
0
    def test_read_gro(self):
        top = read_gro(get_fn('acn.gro'))

        assert top.name == 'ACN'
        assert top.n_sites == 6
        assert allclose(top.box.lengths, 4 * np.ones(3) * u.nm)

        top = read_gro(get_fn('350-waters.gro'))

        assert top.name == 'Generic title'
        assert top.n_sites == 1050
        assert allclose(top.box.lengths, 2.20866 * np.ones(3) * u.nm)
Ejemplo n.º 4
0
 def test_new_potential(self):
     new_potential = Potential(name='mypotential',
                               expression='a*x+b',
                               parameters={
                                   'a': 1.0 * u.g,
                                   'b': 1.0 * u.m
                               },
                               independent_variables={'x'})
     assert new_potential.name == 'mypotential'
     assert new_potential.expression == sympy.sympify('a*x+b')
     assert allclose(new_potential.parameters['a'], 1.0 * u.g)
     assert allclose(new_potential.parameters['b'], 1.0 * u.m)
     assert new_potential.independent_variables == {sympy.symbols('x')}
Ejemplo n.º 5
0
    def test_from_parmed_basic(self, angles):
        struc = pmd.load_file(get_fn('ethane.mol2'), structure=True)
        top = from_parmed(struc, refer_type=False)
        for site in top.sites:
            assert site.atom_type is None
        for connection in top.connections:
            assert connection.connection_type is None
        assert top.n_sites == 8
        assert top.n_bonds == 7

        assert top.box is not None
        lengths = u.nm * [0.714, 0.7938, 0.6646]
        assert allclose(top.box.lengths, lengths)
        assert allclose(top.box.angles, angles)
Ejemplo n.º 6
0
    def test_tip3p_force_field(self):
        water = ForceField(get_path('tip3p.xml'))
        assert len(water.atom_types) == 2
        assert len(water.bond_types) == 1
        assert len(water.angle_types) == 1
        assert len(water.dihedral_types) == 0

        # Store expected expressions in list
        ref_exprs = [sympy.sympify(expr) for expr in [
            "4*epsilon*((sigma/r)**12 - (sigma/r)**6)",
            "0.5 * k * (r-r_eq)**2",
            "0.5 * k * (theta-theta_eq)**2",
            ]
        ]

        assert water.atom_types['opls_111'].charge.value == -0.834
        assert water.atom_types['opls_112'].charge.value == 0.417

        assert sympy.simplify(water.atom_types['opls_111'].expression - ref_exprs[0]) == 0
        assert sympy.simplify(water.atom_types['opls_112'].expression - ref_exprs[0]) == 0
        assert sympy.simplify(water.bond_types['opls_111~opls_112'].expression - ref_exprs[1]) == 0
        assert sympy.simplify(water.angle_types['opls_112~opls_111~opls_112'].expression - ref_exprs[2]) == 0

        assert allclose(water.atom_types['opls_111'].parameters['sigma'], 0.315061 * u.nm)
        assert allclose(water.atom_types['opls_111'].parameters['epsilon'], 0.636386 * u.Unit('kJ/mol'))
        assert allclose(water.atom_types['opls_112'].parameters['sigma'], 1.0 * u.nm)
        assert allclose(water.atom_types['opls_112'].parameters['epsilon'], 0.0 * u.Unit('kJ/mol'))

        assert allclose(water.bond_types['opls_111~opls_112'].parameters['r_eq'], 0.09572 * u.nm)
        assert allclose(water.bond_types['opls_111~opls_112'].parameters['k'], 502416.0 * u.Unit('kJ/(mol*nm**2)'))

        assert allclose(water.angle_types['opls_112~opls_111~opls_112'].parameters['theta_eq'], 1.824218134 * u.radian)
        assert allclose(water.angle_types['opls_112~opls_111~opls_112'].parameters['k'], 682.02 * u.Unit('kJ/(mol*rad**2)'))
Ejemplo n.º 7
0
 def test_setters(self, charge, mass):
     new_type = AtomType(self)
     new_type.name = "SettingName"
     new_type.charge = -1.0 * charge
     new_type.mass = 1 * mass
     new_type.independent_variables = 'r'
     new_type.parameters = {'sigma': 1 * u.nm,
                            'epsilon': 10 * u.Unit('kcal / mol')}
     new_type.expression = 'r * sigma * epsilon'
     assert new_type.name == "SettingName"
     assert allclose(new_type.charge, -1.0 * charge)
     assert allclose(new_type.mass, 1 * mass)
     assert new_type.independent_variables == {sympy.symbols('r')}
     assert new_type.parameters == {'sigma': 1 * u.nm,
                                   'epsilon': 10 * u.Unit('kcal / mol')}
     assert new_type.expression == sympy.sympify('r * sigma * epsilon')
Ejemplo n.º 8
0
    def test_add_box(self):
        top = Topology()
        box = Box(2 * u.nm * np.ones(3))

        assert top.box is None
        top.box = box
        assert top.box is not None
        assert allclose(top.box.lengths, u.nm * 2 * np.ones(3))
Ejemplo n.º 9
0
    def test_carbon_force_field(self):
        carbon = ForceField(get_path('carbon.xml'))

        assert len(carbon.atom_types) == 1
        assert len(carbon.bond_types) == 1
        assert len(carbon.angle_types) == 1
        assert len(carbon.dihedral_types) == 1

        # Store expected expressions in list
        ref_exprs = [
            sympy.sympify(expr) for expr in [
                "4*epsilon*((sigma/r)**12 - (sigma/r)**6)",
                "0.5 * k * (r-r_eq)**2",
                "0.5 * k * (theta-theta_eq)**2",
                "k * (1 + cos(n * theta - theta_0))",
            ]
        ]

        assert carbon.atom_types['C'].charge.value == 0

        assert sympy.simplify(carbon.atom_types['C'].expression -
                              ref_exprs[0]) == 0
        assert sympy.simplify(carbon.bond_types['C~C'].expression -
                              ref_exprs[1]) == 0
        assert sympy.simplify(carbon.angle_types['C~C~C'].expression -
                              ref_exprs[2]) == 0
        assert sympy.simplify(carbon.dihedral_types['*~C~C~*'].expression -
                              ref_exprs[3]) == 0

        assert allclose(carbon.atom_types['C'].parameters['sigma'],
                        0.339966950842 * u.nm)
        assert allclose(carbon.atom_types['C'].parameters['epsilon'],
                        0.359824 * u.Unit('kJ/mol'))

        assert allclose(carbon.bond_types['C~C'].parameters['r_eq'],
                        0.1324 * u.nm)
        assert allclose(carbon.bond_types['C~C'].parameters['k'],
                        493460.96 * u.Unit('kJ/(mol*nm**2)'))

        assert allclose(carbon.angle_types['C~C~C'].parameters['theta_eq'],
                        2.12598556185 * u.radian)
        assert allclose(carbon.angle_types['C~C~C'].parameters['k'],
                        584.42112 * u.Unit('kJ/(mol*rad**2)'))

        assert allclose(carbon.dihedral_types['*~C~C~*'].parameters['k'],
                        27.8236 * u.Unit('kJ/mol'))
        assert allclose(carbon.dihedral_types['*~C~C~*'].parameters['n'],
                        2 * u.dimensionless)
        assert allclose(carbon.dihedral_types['*~C~C~*'].parameters['theta_0'],
                        np.pi * u.radian)
Ejemplo n.º 10
0
 def test_scaled_vectors(self):
     box = Box(lengths=u.unyt_array((2, 2, 2), u.nm),
               angles=u.degree * [40.0, 50.0, 60.0])
     vectors = box.get_vectors()
     test_vectors = np.array([[1, 0, 0], [0.5, 0.86603, 0],
                              [0.64278, 0.51344, 0.56852]])
     test_vectors = (test_vectors.T * box.lengths).T
     assert allclose(vectors, test_vectors, atol=u.nm * 1e-3)
     assert vectors.units == u.nm
Ejemplo n.º 11
0
    def test_full_io(self):
        original_top = read_xyz(get_fn('ethane.xyz'))

        write_xyz(original_top, 'full_conversion.xyz')
        new_top = read_xyz('full_conversion.xyz')

        assert original_top.n_sites == new_top.n_sites
        assert original_top.n_connections == new_top.n_connections
        assert allclose(original_top.positions, new_top.positions)
Ejemplo n.º 12
0
    def test_scaling_unit_vectors(self):
        box = Box(lengths=u.unyt_array((2, 2, 2), u.nm),
                  angles=u.degree * [40.0, 50.0, 60.0])
        u_vectors = box.get_unit_vectors()
        scaled_u_vectors = (u_vectors.T * box.lengths).T

        scaled_vectors = box.get_vectors()

        assert allclose(scaled_vectors, scaled_u_vectors, atol=u.nm * 1e-3)
        assert scaled_u_vectors.units == u.nm
Ejemplo n.º 13
0
    def test_from_parmed_parametrized_structure(self, angles):
        struc = pmd.load_file(get_fn('ethane.top'), xyz=get_fn('ethane.gro'))
        top = from_parmed(struc)
        assert top.n_sites == 8
        assert top.n_bonds == 7
        assert top.n_angles == 12
        assert top.n_connections == 19

        for site in top.sites:
            assert site.atom_type is not None
            assert site.charge is not None

        for connection in top.connections:
            assert connection.connection_type is not None

        assert top.box is not None
        lengths = u.nm * [0.714, 0.7938, 0.6646]
        assert allclose(top.box.lengths, lengths)
        assert allclose(top.box.angles, angles)
Ejemplo n.º 14
0
def write_lammpsdata(topology, filename, atom_style='full'):
    """Output a LAMMPS data file.

    Outputs a LAMMPS data file in the 'full' atom style format.
    Assumes use of 'real' units.
    See http://lammps.sandia.gov/doc/atom_style.html for more information on atom styles.

    Parameters
    ----------
    Topology : `Topology`
        A Topology Object
    filename : str
        Path of the output file
    atom_style : str, optional, default='full'
        Defines the style of atoms to be saved in a LAMMPS data file.
        The following atom styles are currently supported: 'full', 'atomic', 'charge', 'molecular'
        see http://lammps.sandia.gov/doc/atom_style.html for more information on atom styles.

    Notes
    -----
    See http://lammps.sandia.gov/doc/2001/data_format.html for a full description of the LAMMPS data format.  
    This is a work in progress, as only atoms, masses, and atom_type information can be written out.

    Some of this function has been adopted from `mdtraj`'s support of the LAMMPSTRJ trajectory format. 
    See https://github.com/mdtraj/mdtraj/blob/master/mdtraj/formats/lammpstrj.py for details.

    """
    if atom_style not in ['atomic', 'charge', 'molecular', 'full']:
        raise ValueError(
            'Atom style "{}" is invalid or is not currently supported'.format(
                atom_style))

    # TODO: Support various unit styles

    box = topology.box

    with open(filename, 'w') as data:
        data.write('{} written by topology at {}\n\n'.format(
            topology.name if topology.name is not None else '',
            str(datetime.datetime.now())))
        data.write('{:d} atoms\n'.format(topology.n_sites))
        if atom_style in ['full', 'molecular']:
            if topology.n_bonds != 0:
                data.write('{:d} bonds\n'.format(topology.n_bonds))
            else:
                data.write('0 bonds\n')
            if topology.n_angles != 0:
                data.write('{:d} angles\n'.format(topology.n_angles))
            else:
                data.write('0 angles\n')
            if topology.n_dihedrals != 0:
                data.write('{:d} dihedrals\n\n'.format(topology.n_dihedrals))
            else:
                data.write('0 dihedrals\n\n')

        data.write('\n{:d} atom types\n'.format(len(topology.atom_types)))
        data.write('{:d} bond types\n'.format(len(topology.bond_types)))
        data.write('{:d} angle types\n'.format(len(topology.angle_types)))
        data.write('{:d} dihedral types\n'.format(len(
            topology.dihedral_types)))

        data.write('\n')

        # Box data
        if allclose(box.angles, u.unyt_array([90, 90, 90], 'degree')):
            warnings.warn("Orthorhombic box detected")
            box.lengths.convert_to_units(u.angstrom)
            for i, dim in enumerate(['x', 'y', 'z']):
                data.write('{0:.6f} {1:.6f} {2}lo {2}hi\n'.format(
                    0, box.lengths.value[i], dim))
        else:
            warnings.warn("Non-orthorhombic box detected")
            box.lengths.convert_to_units(u.angstrom)
            box.angles.convert_to_units(u.radian)
            vectors = box.get_vectors()
            a, b, c = box.lengths
            alpha, beta, gamma = box.angles

            lx = a
            xy = b * np.cos(gamma)
            xz = c * np.cos(beta)
            ly = np.sqrt(b**2 - xy**2)
            yz = (b * c * np.cos(alpha) - xy * xz) / ly
            lz = np.sqrt(c**2 - xz**2 - yz**2)

            xhi = vectors[0][0]
            yhi = vectors[1][1]
            zhi = vectors[2][2]
            xy = vectors[1][0]
            xz = vectors[2][0]
            yz = vectors[2][1]
            xlo = u.unyt_array(0, xy.units)
            ylo = u.unyt_array(0, xy.units)
            zlo = u.unyt_array(0, xy.units)

            xlo_bound = xlo + u.unyt_array(np.min([0.0, xy, xz, xy + xz]),
                                           xy.units)
            xhi_bound = xhi + u.unyt_array(np.max([0.0, xy, xz, xy + xz]),
                                           xy.units)
            ylo_bound = ylo + u.unyt_array(np.min([0.0, yz]), xy.units)
            yhi_bound = yhi + u.unyt_array(np.max([0.0, yz]), xy.units)
            zlo_bound = zlo
            zhi_bound = zhi

            data.write('{0:.6f} {1:.6f} xlo xhi\n'.format(
                xlo_bound.value, xhi_bound.value))
            data.write('{0:.6f} {1:.6f} ylo yhi\n'.format(
                ylo_bound.value, yhi_bound.value))
            data.write('{0:.6f} {1:.6f} zlo zhi\n'.format(
                zlo_bound.value, zhi_bound.value))
            data.write('{0:.6f} {1:.6f} {2:.6f} xy xz yz\n'.format(
                xy.value, xz.value, yz.value))

        # TODO: Get a dictionary of indices and atom types
        if topology.is_typed():
            # Write out mass data
            data.write('\nMasses\n\n')
            for atom_type in topology.atom_types:
                data.write('{:d}\t{:.6f}\t# {}\n'.format(
                    topology.atom_types.index(atom_type) + 1,
                    atom_type.mass.in_units(u.g / u.mol).value,
                    atom_type.name))

            # TODO: Modified cross-interactions
            # Pair coefficients
            data.write('\nPair Coeffs # lj\n\n')
            for idx, param in enumerate(topology.atom_types):
                data.write('{}\t{:.5f}\t{:.5f}\n'.format(
                    idx + 1, param.parameters['epsilon'].in_units(
                        u.Unit('kcal/mol')).value,
                    param.parameters['sigma'].in_units(u.angstrom).value))

            if topology.bonds:
                data.write('\nBond Coeffs\n\n')
                for idx, bond_type in enumerate(topology.bond_types):
                    data.write('{}\t{:.5f}\t{:.5f}\n'.format(
                        idx + 1, bond_type.parameters['k'].in_units(
                            u.Unit('kcal/mol/angstrom**2')).value / 2,
                        bond_type.parameters['r_eq'].in_units(
                            u.Unit('angstrom')).value))

            if topology.angles:
                data.write('\nAngle Coeffs\n\n')
                for idx, angle_type in enumerate(topology.angle_types):
                    data.write('{}\t{:.5f}\t{:.5f}\n'.format(
                        idx + 1, angle_type.parameters['k'].in_units(
                            u.Unit('kcal/mol/radian**2')).value / 2,
                        angle_type.parameters['theta_eq'].in_units(
                            u.Unit('degree')).value))

            # TODO: Write out multiple dihedral styles
            if topology.dihedrals:
                data.write('\nDihedral Coeffs\n')
                for idx, dihedral_type in enumerate(topology.dihedral_types):
                    if dihedral_type.name == 'RyckaertBellemansTorsionPotential':
                        dihedral_type = convert_ryckaert_to_opls(dihedral_type)
                    data.write('{}\t{:.5f}\t{:5f}\t{:5f}\t{:.5f}\n'.format(
                        idx + 1, dihedral_type.parameters['k1'] / 2,
                        dihedral_type.parameters['k2'] / 2,
                        dihedral_type.parameters['k3'] / 2,
                        dihedral_type.parameters['k4'] / 2))

        # Atom data
        data.write('\nAtoms\n\n')
        if atom_style == 'atomic':
            atom_line = '{index:d}\t{type_index:d}\t{x:.6f}\t{y:.6f}\t{z:.6f}\n'
        elif atom_style == 'charge':
            atom_line = '{index:d}\t{type_index:d}\t{charge:.6f}\t{x:.6f}\t{y:.6f}\t{z:.6f}\n'
        elif atom_style == 'molecular':
            atom_line = '{index:d}\t{zero:d}\t{type_index:d}\t{x:.6f}\t{y:.6f}\t{z:.6f}\n'
        elif atom_style == 'full':
            atom_line = '{index:d}\t{zero:d}\t{type_index:d}\t{charge:.6f}\t{x:.6f}\t{y:.6f}\t{z:.6f}\n'

        for i, site in enumerate(topology.sites):
            data.write(
                atom_line.format(
                    index=topology.sites.index(site) + 1,
                    type_index=topology.atom_types.index(site.atom_type) + 1,
                    zero=0,
                    charge=site.charge.to(u.elementary_charge).value,
                    x=site.position[0].in_units(u.angstrom).value,
                    y=site.position[1].in_units(u.angstrom).value,
                    z=site.position[2].in_units(u.angstrom).value))

        if topology.bonds:
            data.write('\nBonds\n\n')
            for i, bond in enumerate(topology.bonds):
                data.write('{:d}\t{:d}\t{:d}\t{:d}\n'.format(
                    i + 1,
                    topology.bond_types.index(bond.connection_type) + 1,
                    topology.sites.index(bond.connection_members[0]) + 1,
                    topology.sites.index(bond.connection_members[1]) + 1))

        if topology.angles:
            data.write('\nAngles\n\n')
            for i, angle in enumerate(topology.angles):
                data.write('{:d}\t{:d}\t{:d}\t{:d}\t{:d}\n'.format(
                    i + 1,
                    topology.angle_types.index(angle.connection_type) + 1,
                    topology.sites.index(angle.connection_members[0]) + 1,
                    topology.sites.index(angle.connection_members[1]) + 1,
                    topology.sites.index(angle.connection_members[2]) + 1))

        if topology.dihedrals:
            data.write('\nDihedrals\n\n')
            for i, dihedral in enumerate(topology.dihedrals):
                data.write('{:d}\t{:d}\t{:d}\t{:d}\t{:d}\t{:d}\n'.format(
                    i + 1,
                    topology.dihedral_types.index(dihedral.connection_type) +
                    1,
                    topology.sites.index(dihedral.connection_members[0]) + 1,
                    topology.sites.index(dihedral.connection_members[1]) + 1,
                    topology.sites.index(dihedral.connection_members[2]) + 1,
                    topology.sites.index(dihedral.connection_members[3]) + 1))
Ejemplo n.º 15
0
 def test_pass_box_bounding(self, ethane):
     ethane.periodicity = [0, 0, 0]
     top = from_mbuild(ethane)
     assert allclose(top.box.lengths,
                     (ethane.boundingbox.lengths + [0.5, 0.5, 0.5]) * u.nm)
Ejemplo n.º 16
0
 def test_pass_box_periodicity(self, ethane):
     ethane.periodicity = [2, 2, 2]
     top = from_mbuild(ethane)
     assert allclose(top.box.lengths, [2, 2, 2] * u.nm)
Ejemplo n.º 17
0
    def test_pass_box(self, ethane):
        mb_box = Box(lengths=[3, 3, 3])

        top = from_mbuild(ethane, box=mb_box)
        assert allclose(top.box.lengths, [3, 3, 3] * u.nm)
Ejemplo n.º 18
0
    def test_ethylene_forcefield(self):
        ethylene = ForceField(get_path('ethylene.xml'))

        assert len(ethylene.atom_types) == 2
        assert len(ethylene.bond_types) == 2
        assert len(ethylene.angle_types) == 2
        assert len(ethylene.dihedral_types) == 1

        # Store expected expressions in list
        ref_exprs = [
            sympy.sympify(expr) for expr in [
                "4*epsilon*((sigma/r)**12 - (sigma/r)**6)",
                "0.5 * k * (r-r_eq)**2", "0.5 * k * (theta-theta_eq)**2",
                "c_0 + c_1 * cos(psi) + c_2 * cos(psi)**2 + c_3 * cos(psi)**3 + c_4 * cos(psi)**4 + c_5 * cos(psi)**5"
            ]
        ]

        assert allclose(ethylene.atom_types['opls_143'].charge,
                        -0.23 * u.elementary_charge)
        assert allclose(ethylene.atom_types['opls_144'].charge,
                        0.115 * u.elementary_charge)

        assert sympy.simplify(ethylene.atom_types['opls_143'].expression -
                              ref_exprs[0]) == 0
        assert sympy.simplify(ethylene.atom_types['opls_144'].expression -
                              ref_exprs[0]) == 0
        assert sympy.simplify(
            ethylene.bond_types['opls_143~opls_144'].expression -
            ref_exprs[1]) == 0
        assert sympy.simplify(
            ethylene.angle_types['opls_144~opls_143~opls_144'].expression -
            ref_exprs[2]) == 0
        assert sympy.simplify(
            ethylene.dihedral_types['opls_144~opls_143~opls_143~opls_144'].
            expression - ref_exprs[3]) == 0
        assert allclose(ethylene.atom_types['opls_143'].parameters['sigma'],
                        0.317984 * u.nm)
        assert allclose(ethylene.atom_types['opls_143'].parameters['epsilon'],
                        0.355 * u.Unit('kJ/mol'))
        assert allclose(ethylene.atom_types['opls_144'].parameters['sigma'],
                        0.12552 * u.nm)
        assert allclose(ethylene.atom_types['opls_144'].parameters['epsilon'],
                        0.242 * u.Unit('kJ/mol'))

        assert allclose(
            ethylene.bond_types['opls_143~opls_143'].parameters['r_eq'],
            0.134 * u.nm)
        assert allclose(
            ethylene.bond_types['opls_143~opls_144'].parameters['k'],
            284512.0 * u.Unit('kJ/(mol*nm**2)'))

        assert allclose(
            ethylene.angle_types['opls_143~opls_143~opls_144'].
            parameters['theta_eq'], 2.0943951 * u.rad)
        assert allclose(
            ethylene.angle_types['opls_144~opls_143~opls_144'].parameters['k'],
            292.88 * u.Unit('kJ/mol/rad**2'))
        assert allclose(
            ethylene.dihedral_types['opls_144~opls_143~opls_143~opls_144'].
            parameters['c_0'], 58.576 * u.Unit('kJ/mol'))
        assert allclose(
            ethylene.dihedral_types['opls_144~opls_143~opls_143~opls_144'].
            parameters['c_2'], -58.576 * u.Unit('kJ/mol'))
        assert allclose(
            ethylene.dihedral_types['opls_144~opls_143~opls_143~opls_144'].
            parameters['c_5'], 0.0 * u.Unit('kJ/mol'))
Ejemplo n.º 19
0
    def test_noble_mie_xml(self):
        ff = ForceField(get_path('noble_mie.xml'))
        templates = PotentialTemplateLibrary()
        ref_expr = templates['MiePotential'].expression

        assert len(ff.atom_types) == 4
        assert len(ff.bond_types) == 0
        assert len(ff.angle_types) == 0
        assert len(ff.dihedral_types) == 0

        for (name, atom_type) in ff.atom_types.items():
            assert sympy.simplify(atom_type.expression - ref_expr) == 0

        assert allclose(ff.atom_types['Ne'].parameters['epsilon'],
                        0.26855713 * u.Unit('kJ/mol'))
        assert allclose(ff.atom_types['Ne'].parameters['sigma'],
                        2.794 * u.Angstrom)
        assert allclose(ff.atom_types['Ne'].parameters['n'],
                        11 * u.dimensionless)
        assert allclose(ff.atom_types['Ne'].parameters['m'],
                        6 * u.dimensionless)
        assert ff.atom_types['Ne'].charge.value == 0

        assert allclose(ff.atom_types['Ar'].parameters['epsilon'],
                        1.01519583 * u.Unit('kJ/mol'))
        assert allclose(ff.atom_types['Ar'].parameters['sigma'],
                        3.405 * u.Angstrom)
        assert allclose(ff.atom_types['Ar'].parameters['n'],
                        13 * u.dimensionless)
        assert allclose(ff.atom_types['Ar'].parameters['m'],
                        6 * u.dimensionless)
        assert ff.atom_types['Ar'].charge.value == 0

        assert allclose(ff.atom_types['Kr'].parameters['epsilon'],
                        1.46417678 * u.Unit('kJ/mol'))
        assert allclose(ff.atom_types['Kr'].parameters['sigma'],
                        3.645 * u.Angstrom)
        assert allclose(ff.atom_types['Kr'].parameters['n'],
                        14 * u.dimensionless)
        assert allclose(ff.atom_types['Kr'].parameters['m'],
                        6 * u.dimensionless)
        assert ff.atom_types['Kr'].charge.value == 0

        assert allclose(ff.atom_types['Xe'].parameters['epsilon'],
                        2.02706587 * u.Unit('kJ/mol'))
        assert allclose(ff.atom_types['Xe'].parameters['sigma'],
                        3.964 * u.Angstrom)
        assert allclose(ff.atom_types['Xe'].parameters['n'],
                        14 * u.dimensionless)
        assert allclose(ff.atom_types['Xe'].parameters['m'],
                        6 * u.dimensionless)
        assert ff.atom_types['Xe'].charge.value == 0
Ejemplo n.º 20
0
def write_lammpsdata(topology, filename, atom_style='full'):
    """Output a LAMMPS data file.

    Outputs a LAMMPS data file in the 'full' atom style format.
    Assumes use of 'real' units.
    See http://lammps.sandia.gov/doc/atom_style.html for more information on atom styles.

    Parameters
    ----------
    Topology : `Topology`
        A Topology Object
    filename : str
        Path of the output file
    atom_style : str, optional, default='full'
        Defines the style of atoms to be saved in a LAMMPS data file.
        The following atom styles are currently supported: 'full', 'atomic', 'charge', 'molecular'
        see http://lammps.sandia.gov/doc/atom_style.html for more information on atom styles.

    Notes
    -----
    See http://lammps.sandia.gov/doc/2001/data_format.html for a full description of the LAMMPS data format.  
    This is a work in progress, as only atoms, masses, and atom_type information can be written out.

    Some of this function has been adopted from `mdtraj`'s support of the LAMMPSTRJ trajectory format. 
    See https://github.com/mdtraj/mdtraj/blob/master/mdtraj/formats/lammpstrj.py for details.

    """
    if atom_style not in ['atomic', 'charge', 'molecular', 'full']:
        raise ValueError(
            'Atom style "{}" is invalid or is not currently supported'.format(
                atom_style))

    xyz = list()
    types = list()
    for site in topology.sites:
        xyz.append([site.position[0], site.position[1], site.position[2]])
        types.append(site.atom_type.name)

    forcefield = True
    if topology.sites[0].atom_type.name in ['', None]:
        forcefield = False

    box = topology.box

    unique_types = list(set(types))
    unique_types.sort(key=natural_sort)

    # TODO: charges
    # TODO: bonds
    # TODO: Angles
    # TODO: Dihedrals

    # TODO: Figure out handling bond, angle, and dihedral indices

    # placeholder; change later
    bonds = 0
    angles = 0
    dihedrals = 0

    with open(filename, 'w') as data:
        data.write('{} written by topology at {}\n\n'.format(
            topology.name if topology.name is not None else '',
            str(datetime.datetime.now())))
        data.write('{:d} atoms\n'.format(len(topology.sites)))
        if atom_style in ['full', 'molecular']:
            if bonds != 0:
                data.write('{:} bonds\n'.format(len(bonds)))
            else:
                data.write('0 bonds\n')
            if angles != 0:
                data.write('{:} angles\n'.format(len(angles)))
            else:
                data.write('0 angles\n')
            if dihedrals != 0:
                data.write('{:} dihedrals\n\n'.format(len(dihedrals)))
            else:
                data.write('0 dihedrals\n\n')

        data.write('{:d} atom types\n'.format(len(set(types))))

        # TODO: Write out bonds, angles, and dihedrals

        data.write('\n')

        # Box data
        if allclose(box.angles, u.unyt_array([90, 90, 90], 'degree')):
            warnings.warn("Orthorhombic box detected")
            box.lengths.convert_to_units(u.angstrom)
            for i, dim in enumerate(['x', 'y', 'z']):
                data.write('{0:.6f} {1:.6f} {2}lo {2}hi\n'.format(
                    0, box.lengths.value[i], dim))
        else:
            warnings.warn("Non-orthorhombic box detected")
            box.lengths.convert_to_units(u.angstrom)
            box.angles.convert_to_units(u.radian)
            vectors = box.get_vectors()
            a, b, c = box.lengths
            alpha, beta, gamma = box.angles

            lx = a
            xy = b * np.cos(gamma)
            xz = c * np.cos(beta)
            ly = np.sqrt(b**2 - xy**2)
            yz = (b * c * np.cos(alpha) - xy * xz) / ly
            lz = np.sqrt(c**2 - xz**2 - yz**2)

            xhi = vectors[0][0]
            yhi = vectors[1][1]
            zhi = vectors[2][2]
            xy = vectors[1][0]
            xz = vectors[2][0]
            yz = vectors[2][1]
            xlo = u.unyt_array(0, xy.units)
            ylo = u.unyt_array(0, xy.units)
            zlo = u.unyt_array(0, xy.units)

            xlo_bound = xlo + u.unyt_array(np.min([0.0, xy, xz, xy + xz]),
                                           xy.units)
            xhi_bound = xhi + u.unyt_array(np.max([0.0, xy, xz, xy + xz]),
                                           xy.units)
            ylo_bound = ylo + u.unyt_array(np.min([0.0, yz]), xy.units)
            yhi_bound = yhi + u.unyt_array(np.max([0.0, yz]), xy.units)
            zlo_bound = zlo
            zhi_bound = zhi

            data.write('{0:.6f} {1:.6f} xlo xhi\n'.format(
                xlo_bound.value, xhi_bound.value))
            data.write('{0:.6f} {1:.6f} ylo yhi\n'.format(
                ylo_bound.value, yhi_bound.value))
            data.write('{0:.6f} {1:.6f} zlo zhi\n'.format(
                zlo_bound.value, zhi_bound.value))
            data.write('{0:.6f} {1:.6f} {2:.6f} xy xz yz\n'.format(
                xy.value, xz.value, yz.value))

        # Mass data
        masses = [site.atom_type.mass for site in topology.sites]
        mass_dict = dict([(unique_types.index(atom_type) + 1, mass)
                          for atom_type, mass in zip(types, masses)])

        data.write('\nMasses\n\n')
        for atom_type, mass in mass_dict.items():
            data.write('{:d}\t{:.6f}\t# {}\n'.format(
                atom_type,
                mass.in_units(u.g / u.mol).value, unique_types[atom_type - 1]))
        if forcefield:
            sigmas = [
                site.atom_type.parameters['sigma'] for site in topology.sites
            ]
            epsilons = [
                site.atom_type.parameters['epsilon'] for site in topology.sites
            ]
            sigma_dict = dict([(unique_types.index(atom_type) + 1, sigma)
                               for atom_type, sigma in zip(types, sigmas)])
            epsilon_dict = dict([
                (unique_types.index(atom_type) + 1, epsilon)
                for atom_type, epsilon in zip(types, epsilons)
            ])

            # TODO: Modified cross-interactions
            # Pair coefficients
            data.write('\nPair Coeffs # lj\n\n')
            for idx, epsilon in epsilon_dict.items():
                data.write('{}\t{:.5f}\t{:.5f}\n'.format(
                    idx,
                    epsilon.in_units(u.Unit('kcal/mol')).value,
                    sigma_dict[idx].in_units(u.angstrom).value))

        # TODO: Write out bond coefficients
        # TODO: Write out angle coefficients
        # TODO: Write out dihedral coefficients

        # Atom data
        data.write('\nAtoms\n\n')
        if atom_style == 'atomic':
            atom_line = '{index:d}\t{type_index:d}\t{x:.6f}\t{y:.6f}\t{z:.6f}\n'
        elif atom_style == 'charge':
            atom_line = '{index:d}\t{type_index:d}\t{charge:.6f}\t{x:.6f}\t{y:.6f}\t{z:.6f}\n'
        elif atom_style == 'molecular':
            atom_line = '{index:d}\t{zero:d}\t{type_index:d}\t{x:.6f}\t{y:.6f}\t{z:.6f}\n'
        elif atom_style == 'full':
            atom_line = '{index:d}\t{zero:d}\t{type_index:d}\t{charge:.6f}\t{x:.6f}\t{y:.6f}\t{z:.6f}\n'

        # TODO: Add back in correct 'type_index' and 'charge'
        #for i,coords in enumerate(xyz):
        #    data.write(atom_line.format(
        #        index=i+1,type_index=unique_types.index(types[i])+1,
        #        zero=0,charge=charges[i],
        #        x=coords[0],y=coords[1],z=coords[2]))

        for i, coords in enumerate(xyz):
            data.write(
                atom_line.format(
                    index=i + 1,
                    type_index=unique_types.index(types[i]) + 1,
                    zero=0,
                    charge=0,  # TODO: handle charges from atomtype and/or site
                    x=coords[0].in_units(u.angstrom).value,
                    y=coords[1].in_units(u.angstrom).value,
                    z=coords[2].in_units(u.angstrom).value))
Ejemplo n.º 21
0
def write_gro(top, filename):
    """Write a topology to a gro file.

    The Gromos87 (gro) format is a common plain text structure file used
    commonly with the GROMACS simulation engine.  This file contains the
    simulation box parameters, number of atoms, the residue and atom number for
    each atom, as well as their positions and velocities (velocity is
    optional).  This method takes a topology object and a filepath string or
    file object and saves a Gromos87 (gro) to disk.

    Parameters
    ----------
    top : gmso.core.topology
        The `topology` to write out to the gro file.
    filename : str or file object
        The location and name of file to save to disk.


    Notes
    -----
    Multiple residue assignment has not been added, each `site` will belong to
    the same resid of 1 currently.

    """

    top = _prepare_topology_to_gro(top)

    with open(filename, 'w') as out_file:
        out_file.write('{} written by topology at {}\n'.format(
            top.name if top.name is not None else '',
            str(datetime.datetime.now())))
        out_file.write('{:d}\n'.format(top.n_sites))
        for idx, site in enumerate(top.sites):
            warnings.warn(
                'Residue information is not currently '
                'stored or written to GRO files.', NotYetImplementedWarning)
            # TODO: assign residues
            res_id = 1
            res_name = 'X'
            atom_name = site.name
            atom_id = idx + 1
            out_file.write(
                '{0:5d}{1:5s}{2:5s}{3:5d}{4:8.3f}{5:8.3f}{6:8.3f}\n'.format(
                    res_id,
                    res_name,
                    atom_name,
                    atom_id,
                    site.position[0].in_units(u.nm).value,
                    site.position[1].in_units(u.nm).value,
                    site.position[2].in_units(u.nm).value,
                ))

        if allclose(top.box.angles,
                    u.degree * [90, 90, 90],
                    atol=0.1 * u.degree):
            out_file.write(' {:0.5f} {:0.5f} {:0.5f} \n'.format(
                top.box.lengths[0].in_units(u.nm).value.round(6),
                top.box.lengths[1].in_units(u.nm).value.round(6),
                top.box.lengths[2].in_units(u.nm).value.round(6),
            ))
        else:
            # TODO: Work around GROMACS's triclinic limitations #30
            vectors = top.box.get_vectors()
            out_file.write(
                ' {:0.5f} {:0.5f} {:0.5f} {:0.5f} {:0.5f} {:0.5f} {:0.5f} {:0.5f} {:0.5f} \n'
                .format(
                    vectors[0, 0].in_units(u.nm).value.round(6),
                    vectors[1, 1].in_units(u.nm).value.round(6),
                    vectors[2, 2].in_units(u.nm).value.round(6),
                    vectors[0, 1].in_units(u.nm).value.round(6),
                    vectors[0, 2].in_units(u.nm).value.round(6),
                    vectors[1, 0].in_units(u.nm).value.round(6),
                    vectors[1, 2].in_units(u.nm).value.round(6),
                    vectors[2, 0].in_units(u.nm).value.round(6),
                    vectors[2, 1].in_units(u.nm).value.round(6),
                ))