예제 #1
0
system.add(bot_layer)
systembox = system._gen_box()

# Bilayer needs to be shifted to fit inside the box for gromacs (can't have any negative coordinates)
mb.translate(system, [
    np.abs(systembox.mins[0]),
    np.abs(systembox.mins[1]),
    np.abs(systembox.mins[2])
])

# Shrink the x and y dimensions of the box to prevent packmol from shoving atoms in weird locations
cross_area = (n_x * spacing - 1) * (n_y * spacing - 1)
leaflet_water_z = n_solvent_per_layer * 2.66602458e-2 / cross_area
# Redefine the box to account for shifted coordinates and add extra space in z-direcction
smallbox = mb.Box(
    mins=[0, 0, systembox.mins[2] - leaflet_water_z],
    maxs=[n_x * spacing, n_y * spacing, systembox.maxs[2] + leaflet_water_z])
# The solvate box will have a reduced cross-sectional area to prevent waters in strange locations
solvatebox = mb.Box(
    mins=[0.5, 0.5, smallbox.mins[2]],
    maxs=[smallbox.maxs[0] - 0.5, smallbox.maxs[1] - 0.5, smallbox.maxs[2]])

# Solvate system
system = mb.solvate(system, H2O(), 2 * n_solvent_per_layer, solvatebox)

# Bilayer needs to be shifted to fit inside the box for gromacs (can't have any negative coordinates)
mb.translate(system, [
    np.abs(smallbox.mins[0]),
    np.abs(smallbox.mins[1]),
    np.abs(smallbox.mins[2])
])
예제 #2
0
 def test_save_box(self, ethane):
     box = mb.Box(lengths=np.array([2.0, 2.0, 2.0]))
     ethane.save(filename='ethane-box.lammps', forcefield_name='oplsaa', box=box)
예제 #3
0
파일: test_box.py 프로젝트: whitehml/mbuild
 def test_init_angles(self):
     box = mb.Box(mins=np.zeros(3),
                  maxs=np.ones(3),
                  angles=[40.0, 50.0, 60.0])
     assert np.array_equal(box.angles, [40.0, 50.0, 60.0])
예제 #4
0
class TestLattice(BaseTest):
    """
    Unit Tests for Lattice class functionality.
    """

    @pytest.mark.parametrize("spacing",
                             [
                                ([1, 1, 1]),
                                ([0.1, 0.1, 0.1]),
                                (['1', '1', '1']),
                                (['1', 0.1, '0.1'])
                             ]
                             )
    def test_spacing_success(self, spacing):
        spacing = np.asarray(spacing, dtype=np.float64)
        spacing = np.reshape(spacing, (3,))
        test_lattice = mb.Lattice(lattice_spacing=spacing)
        np.testing.assert_allclose(spacing, test_lattice.lattice_spacing,
                                   rtol=1e-7, atol=0, equal_nan=True)

    @pytest.mark.parametrize("dim, spacing",
                             [
                                (3, [1, 1, 1]),
                                (3, [1, 1, 0]),
                                (3, [1, 0, 0])
                             ])
    def test_dimension_set(self, dim, spacing):
        test_lattice = mb.Lattice(lattice_spacing=spacing)
        assert test_lattice.dimension == dim

    @pytest.mark.parametrize("spacing",
                             [
                                ([1]),
                                (1),
                                ([1, 1]),
                                ([-1, 1, 1]),
                                ([1, 1, 1, 1]),
                                ([1, 'a']),
                                (None),
                                ([]),
                                ([None, None, None]),
                             ])
    def test_spacing_incorrect(self, spacing):
        with pytest.raises(ValueError):
            mb.Lattice(lattice_spacing=spacing)

    @pytest.mark.parametrize("spacing",
                             [
                                ([0.1, 0.1, 0.1]),
                                ([1, 2, 3]),
                                (['1', '2', '3']),
                                ([1, 2, '3']),
                                ([1, 0, 0]),
                                ([1, 1, 0])
                             ]
                             )
    def test_spacing_correct(self, spacing):
        mb.Lattice(lattice_spacing=spacing)

    @pytest.mark.parametrize("vectors",
                             [
                                ([[1, 2], [0, 1, 0], [0, 0, 1]]),
                                ([[1, 0, 0], [0, 1, 0], [0, 1, 0]]),
                                (np.identity(4, dtype=np.float64)),
                                ([[1, 2, 3], [3, 2, 1], [2, 1, 3]])
                             ])
    def test_incorrect_lattice_vectors(self, vectors):
        with pytest.raises(ValueError):
            mb.Lattice(lattice_spacing=[1, 1, 1], lattice_vectors=vectors)

    @pytest.mark.parametrize("vectors",
                             [
                                ([[1, 0, 0], [0, 1, 0], [0, 0, 1]]),
                                ([[1, 0, 0], [-0.5, 0.85, 0], [0, 0, 1]])
                             ])
    def test_correct_lattice_vectors(self, vectors):
        mb.Lattice(lattice_spacing=[1, 1, 1], lattice_vectors=vectors)

    def test_overdefinied_inputs(self):
        space = [1, 1, 1]
        vectors = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
        angles = [90, 90, 90]
        with pytest.raises(ValueError):
            mb.Lattice(lattice_spacing=space, lattice_vectors=vectors,
                       angles=angles)

    @pytest.mark.parametrize("the_type",
                             [
                                 (list()),
                                 (tuple()),
                                 (str()),
                                 ([])
                             ]
                             )
    def test_lattice_points_input_type(self, the_type):
        with pytest.raises(TypeError):
            mb.Lattice(lattice_spacing=[1, 1, 1], lattice_points=the_type)

    @pytest.mark.parametrize("incorrect",
                             [
                                 ({'A' : [[.2, .3, .2, .1]]}),
                                 ({'A' : [[None]]}),
                                 ({'A' : [[.2, .3, None]]}),
                                 ({'A' : [[.2, .3, -.5]]}),
                                 ({'A' : [[.2, .3, 1]]}),
                                 ({'A' : [[.2, .3, .1], [.2, .3, .1]]})
                             ]
                             )
    def test_lattice_points_input_type(self, incorrect):
        with pytest.raises(ValueError):
            mb.Lattice(lattice_spacing=[1, 1, 1], lattice_points=incorrect)

    @pytest.mark.parametrize("angles",
                             [
                                ([150, 150, 150]),
                                ([90, 90, -90]),
                                ([90, 90, 180]),
                                ([90, 90, 0]),
                                ([90, 90, 90, 90]),
                                ([97, 3, 120])
                             ]
                             )
    def test_improper_angles(self, angles):
        with pytest.raises(ValueError):
            mb.Lattice(lattice_spacing=[1, 1, 1], angles=angles)

    @pytest.mark.parametrize("vectors, angles",
                             [
                                ([[1, 0, 0], [0, 1, 0], [0, 0, 1]],
                                    [90, 90, 90]),
                                ([[1.0, 0.0, 0.0],
                                  [-0.45399049973954675, 0.8910065241883679, 0.0],
                                  [-0.034899496702500955, -0.037369475398893195, 0.9986919181801381]],
                                    [91, 92, 117])
                             ]
                             )
    def test_proper_angles(self, vectors, angles):
        testlattice = mb.Lattice(lattice_spacing=[1, 1, 1],
                                 lattice_vectors=vectors)
        np.testing.assert_allclose(testlattice.angles,
                                   np.asarray(angles, dtype=np.float64),
                                   rtol=1e-05, atol=1e-08, equal_nan=False)

    @pytest.mark.parametrize("x, y, z",
                             [
                                (None, 1, 0),
                                (1, None, 1),
                                (1, 1, None),
                                (-1, 1, 1),
                                (1, -1, 1),
                                (1, 1, -1),
                                (1, 1, np.NaN)
                              ])
    def test_incorrect_populate_inputs(self, x, y, z):
        with pytest.raises(ValueError):
            test_lattice = mb.Lattice(lattice_spacing=[1, 1, 1])
            test_lattice.populate(compound_dict={'id':mb.Compound()},
                                  x=x, y=y, z=z)

    @pytest.mark.parametrize("my_type",
                             [
                                ([]),
                                (()),
                                (np.array),
                                (np.ndarray)
                            ]
                            )
    def test_populate_basis_type_incorrect(self, my_type):
        test_lattice = mb.Lattice(lattice_spacing=[1, 1, 1])
        with pytest.raises(TypeError):
            test_lattice.populate(compound_dict=my_type)

    @pytest.mark.parametrize("not_compound",
                             [
                                    (1),
                                    (mb.Box(lengths=[1, 1, 1])),
                                    ("aLattice")
                             ]
                             )
    def test_populate_not_compound(self, not_compound):
        test_lattice = mb.Lattice(lattice_spacing=[1, 1, 1])
        particle_dict = {'id': not_compound}
        with pytest.raises(TypeError):
            test_lattice.populate(compound_dict=particle_dict)

    def test_proper_populate(self):
        values_to_check = [[0, 0, 0], [1, 0, 0], [0, 1, 0], [0, 0, 1],
                           [1, 1, 0], [0, 1, 1], [1, 0, 1], [1, 1, 1]]
        test_lattice = mb.Lattice(lattice_spacing=[1, 1, 1],
                                  angles=[90, 90, 90])

        new_compound = test_lattice.populate(x=2, y=2, z=2)

        values_to_check = np.asarray(values_to_check, dtype=np.float64)

        is_true = []
        for pos1 in np.split(values_to_check, 8, axis=0):
            for pos2 in np.split(new_compound.xyz, 8, axis=0):
                if np.allclose(pos1, pos2):
                    is_true.append(True)

        assert len(is_true) == len(values_to_check)

    def test_set_periodicity(self):
        lattice = mb.Lattice(lattice_spacing=[1, 1, 1], angles=[90, 90, 90],
                             lattice_points={'A' : [[0, 0, 0]]})

        compound_test = lattice.populate(compound_dict={'A' : mb.Compound()},
                                         x=2, y=5, z=9)

        replication=[2, 5, 9]
        np.testing.assert_allclose(compound_test.periodicity,
                                   np.asarray([x*y for x,y in zip(replication, lattice.lattice_spacing)]))
예제 #5
0
def main():
    # Create a water molecule with the spce geometry
    water = spce_water
    ff = foyer.Forcefield(get_ff("pore-spce-jc.xml"))
    water_typed = ff.apply(water)

    # Define conditions
    temperature = 298.0 * u.K
    # Define a range of (shifted) chemical potentials
    mus_adsorbate = np.arange(-58, -42, 2) * u.Unit("kJ/mol")

    # Define custom_args that are the same for all pure phase simulations
    custom_args = {
        "cutoff_style": "cut",
        "charge_style": "ewald",
        "rcut_min": 0.5 * u.angstrom,
        "vdw_cutoff": 9.0 * u.angstrom,
        "prop_freq": 10,
        "angle_style": ["fixed"],
    }

    for mu_adsorbate in mus_adsorbate:
        print(f"\nRun simulation: T = {temperature}, mu = {mu_adsorbate}\n")
        dirname = f"T_{temperature:0.1f}_mu_{mu_adsorbate:.1f}".replace(
            " ", "_"
        ).replace(
            "/", "-"
        )
        if not os.path.isdir(dirname):
            os.mkdir(dirname)
        else:
            pass
        with temporary_cd(dirname):
            # Box size depends on chemical potential
            # Test simulations show mu' = -48 kJ/mol; p ~ 0.01 bar
            # Employ IG law to estimate remaining box sizes; target 40 waters
            mu_0 = -48 * u.kJ/u.mol
            p_0 = 0.01 * u.bar
            n_water_target = 40
            p_ig = p_0 * np.exp((mu_adsorbate-mu_0)/(u.kb * temperature))
            vol = n_water_target * u.kb * temperature / p_ig
            boxl = (vol**(1./3.)).to_value("nm")
            custom_args["charge_cutoff"] = 0.25 * boxl * u.nm

            species_list = [water_typed]
            box_list = [mbuild.Box([boxl, boxl, boxl])]
            system = mc.System(
                box_list, species_list,
            )
            moveset = mc.MoveSet("gcmc", species_list)
            moveset.prob_regrow = 0.0
            moveset.prob_translate = 0.3
            moveset.prob_rotate = 0.3
            moveset.prob_insert = 0.2

            mc.run(
                system=system,
                moveset=moveset,
                run_type="equil",
                run_length=500000,
                temperature=temperature,
                run_name="equil",
                chemical_potentials=[mu_adsorbate],
                **custom_args,
            )

            mc.restart(
                system=system,
                moveset=moveset,
                run_type="prod",
                run_length=1000000,
                temperature=temperature,
                run_name="prod",
                restart_name="equil",
                chemical_potentials=[mu_adsorbate],
                **custom_args,
            )
예제 #6
0
def equilibrate_liqbox(job):
    "Equilibrate the liquid box"

    import os
    import errno
    import mbuild
    import foyer
    import mosdef_cassandra as mc

    ff = foyer.Forcefield(job.fn("ff.xml"))

    # Load the compound and apply the ff
    compound = mbuild.load("C(F)(F)C(F)(F)F", smiles=True)
    compound_ff = ff.apply(compound)

    # Create box list and species list
    boxl = job.doc.liqboxl
    box = mbuild.Box(lengths=[boxl, boxl, boxl])

    box_list = [box]
    species_list = [compound_ff]

    mols_to_add = [[job.sp.N_liq]]

    system = mc.System(box_list, species_list, mols_to_add=mols_to_add)

    # Create a new moves object
    moves = mc.Moves("npt", species_list)

    # Edit the volume move probability to be more reasonable
    orig_prob_volume = moves.prob_volume
    new_prob_volume = 1.0 / job.sp.N_liq
    moves.prob_volume = new_prob_volume

    moves.prob_translate = (moves.prob_translate + orig_prob_volume -
                            new_prob_volume)

    # Define thermo output props
    thermo_props = [
        "energy_total",
        "pressure",
        "volume",
        "nmols",
        "mass_density",
    ]

    # Define custom args
    custom_args = {
        "run_name": "equil",
        "charge_style": "ewald",
        "rcut_min": 1.0,
        "vdw_cutoff": 12.0,
        "units": "sweeps",
        "steps_per_sweep": job.sp.N_liq,
        "coord_freq": 500,
        "prop_freq": 10,
        "properties": thermo_props,
    }

    # Move into the job dir and start doing things
    with job:
        liq_dir = "liqbox-equil"
        try:
            os.mkdir(liq_dir)
        except OSError as e:
            if e.errno != errno.EEXIST:
                raise
        os.chdir(liq_dir)
        # Run equilibration
        mc.run(system=system,
               moves=moves,
               run_type="equilibration",
               run_length=job.sp.nsteps_liqeq,
               temperature=job.sp.T,
               pressure=job.sp.P,
               **custom_args)
예제 #7
0
 def box(self):
     box = mbuild.Box(lengths=[5.0, 5.0, 5.0])
     return box
예제 #8
0
 def test_angles_setter(self):
     box = mb.Box(mins=np.zeros(3), maxs=np.ones(3), angles=90 * np.ones(3))
     box.angles = np.array([60.0, 120.0, 60.0])
     assert (box.angles == np.array([60.0, 120.0, 60.0])).all()
예제 #9
0
 def test_save_triclinic_box(self, ethane):
     box = mb.Box(lengths=np.array([2.0, 2.0, 2.0]), angles=[60, 70, 80])
     ethane.save(filename='triclinic-box.lammps',
                 forcefield_name='oplsaa',
                 box=box)
예제 #10
0
 def test_bad_args(self):
     with pytest.raises(ValueError):
         mb.Box(maxs=[4, 4, 4])
예제 #11
0
 def test_lengths_setter(self):
     box = mb.Box(mins=np.zeros(3), maxs=np.ones(3))
     box.lengths = 2 * np.ones(3)
     assert (box.lengths == 2 * np.ones(3)).all()
     assert (box.maxs - box.mins == 2 * np.ones(3)).all()
예제 #12
0
 def test_save_box(self, ethane):
     box = mb.Box(lengths=np.array([2.0, 2.0, 2.0]))
     ethane.save(filename='ethane-box.hoomdxml', box=box)
예제 #13
0
    def populate(self, compound_dict=None, x=1, y=1, z=1):
        """Expand lattice and create compound from lattice.

        Expands lattice based on user input. The user must also
        pass in a dictionary that contains the keys that exist in the
        basis_dict. The corresponding Compound will be the full lattice
        returned to the user.

        If no dictionary is passed to the user, Dummy Compounds will be used.

        Parameters
        ----------
        x : int, optional, default=1
            How many iterations in the x direction.
        y : int, optional, default=1
            How many iterations in the y direction.
        z : int, optional, default=1
            How many iterations in the z direction.
        compound_dict : dictionary, optional, default=None
            Link between basis_dict and Compounds.

        Raises
        ------
        ValueError
            incorrect x,y, or z values.
        TypeError
            incorrect type for basis vector

        Notes
        -----
        Called after constructor by user.
        """
        x, y, z = self._sanitize_populate_args(x=x, y=y, z=z)

        if (isinstance(compound_dict, dict)) or (compound_dict is None):
            pass
        else:
            raise TypeError(
                "Compound dictionary is not a dict. {} was passed.".format(
                    type(compound_dict)))

        cell = defaultdict(list)
        [a, b, c] = self.lattice_spacing

        transform_mat = self.lattice_vectors
        # Unit vectors
        transform_mat = np.asarray(transform_mat, dtype=np.float64)
        transform_mat = np.reshape(transform_mat, newshape=(3, 3))
        norms = np.linalg.norm(transform_mat, axis=1)

        # Normalized vectors for change of basis
        unit_vecs = np.divide(transform_mat.transpose(), norms)

        # Generate new coordinates
        for key, locations in self.lattice_points.items():
            for coords in locations:
                for replication in it.product(range(x), range(y), range(z)):
                    new_coords = np.asarray(coords, dtype=np.float64)
                    new_coords = np.reshape(new_coords, (1, 3), order="C")

                    new_coords[0][0] = new_coords[0][0] + replication[0]
                    new_coords[0][1] = new_coords[0][1] + replication[1]
                    new_coords[0][2] = new_coords[0][2] + replication[2]

                    # Change of basis to cartesian
                    new_coords = np.dot(unit_vecs, new_coords.transpose())

                    new_coords[0] = new_coords[0] * a
                    new_coords[1] = new_coords[1] * b
                    new_coords[2] = new_coords[2] * c
                    new_coords = np.reshape(new_coords, (1, 3), order="C")

                    tuple_of_coords = tuple(new_coords.flatten())
                    cell[key].append(tuple_of_coords)

        ret_lattice = mb.Compound()

        # Create (clone) a mb.Compound for the newly generate positions
        if compound_dict is None:
            for key_id, all_pos in cell.items():
                particle = mb.Compound(name=key_id, pos=[0, 0, 0])
                for pos in all_pos:
                    particle_to_add = mb.clone(particle)
                    particle_to_add.translate_to(list(pos))
                    ret_lattice.add(particle_to_add)
        else:
            for key_id, all_pos in cell.items():
                if isinstance(compound_dict[key_id], mb.Compound):
                    compound_to_move = compound_dict[key_id]
                    for pos in all_pos:
                        tmp_comp = mb.clone(compound_to_move)
                        tmp_comp.translate_to(list(pos))
                        ret_lattice.add(tmp_comp)
                else:
                    err_type = type(compound_dict.get(key_id))
                    raise TypeError(
                        "Invalid type in provided Compound dictionary. For key "
                        "{}, type: {} was provided, not Compound.".format(
                            key_id, err_type))
        # Create mbuild.box
        ret_lattice.box = mb.Box(lengths=[a * x, b * y, c * z],
                                 angles=self.angles)

        # if coordinates are below a certain threshold, set to 0
        tolerance = 1e-12
        ret_lattice.xyz_with_ports[
            ret_lattice.xyz_with_ports <= tolerance] = 0.0

        return ret_lattice
예제 #14
0
def main():
    # Create a CG methane, load and apply ff
    methane = mbuild.Compound(name="_CH4")
    ff_path = resource_filename(
        "mc_examples",
        "realistic_workflows/zeolite_adsorption/resources/ffxml/adsorbates.xml",
    )
    ff_ads = foyer.Forcefield(ff_path)
    methane_ff = ff_ads.apply(methane)

    # Define a few keyword args that will be the
    # same for all fluid phase simulations
    custom_args = {
        "charge_style": "none",
        "vdw_cutoff": 14.0 * u.angstrom,
        "prop_freq": 10,
    }

    # Define temperatures and chemical potential values
    # for the single phase GCMC simulations
    temperatures = [298 * u.K, 309 * u.K, 350 * u.K]
    mus = np.arange(-49, -30, 3) * u.Unit("kJ/mol")

    # Loop over temperatures and mus and run simulations
    for temperature in temperatures:
        for mu in mus:

            # For each simulation -- first estimate
            # the box volume to target ~40 molecules
            n_methane_target = 40
            beta = 1.0 / (u.kb * temperature)
            mass = 16.04 * u.amu
            debroglie = np.sqrt(2 * np.pi * u.hbar**2 * beta / mass)
            vol = n_methane_target * debroglie**3 * np.exp(
                -beta.to("mol/kJ") * mu)
            boxl = (vol**(1.0 / 3.0)).to_value("nm")
            if boxl < 2.0 * custom_args["vdw_cutoff"].to_value("nm"):
                boxl = 2.0 * custom_args["vdw_cutoff"].to_value("nm")

            # Define the species list, box list, system, moveset
            # We start with an empty box
            species_list = [methane_ff]
            box_list = [mbuild.Box([boxl, boxl, boxl])]
            system = mc.System(box_list, species_list)
            moveset = mc.MoveSet("gcmc", species_list)

            # Create a new directory, temporary cd, and run
            # the equilibration and production simulations!
            print(f"\nRun simulation: T = {temperature}, mu = {mu}\n")
            dirname = f"fluid_T_{temperature:0.1f}_mu_{mu:.1f}".replace(
                " ", "_").replace("/", "-")
            if not os.path.isdir(dirname):
                os.mkdir(dirname)
            else:
                pass
            with temporary_cd(dirname):
                mc.run(
                    system=system,
                    moveset=moveset,
                    run_type="equil",
                    run_length=50000,
                    temperature=temperature,
                    run_name="equil",
                    chemical_potentials=[mu],
                    **custom_args,
                )

                mc.restart(
                    restart_from="equil",
                    run_name="prod",
                    run_type="prod",
                    total_run_length=400000,
                )
예제 #15
0
        pass

# #### Initialize system
# Here we call `GraphenePoreSolvent` to initialize a system with two graphene slit pores, 600 water molecules, and 200 ions

# In[ ]:

system = GraphenePoreSolvent(pore_depth=5,
                             side_dim=4,
                             n_sheets=3,
                             pore_width=1.5,
                             x_bulk=6,
                             solvent=[water, na, cl],
                             n_solvent=[5200, 400, 400])

box = mb.Box(system.periodicity)

# #### Separate molecules into different compounds
# Because we are going to apply multiple force fields, we need to separate the waters and graphene into separate mBuild compounds.  Calling `apply` will apply the forcefield to the compounds and convert them to parametrized ParmEd `Structures`

# In[ ]:

water = mb.Compound()
ions = mb.Compound()
graphene = mb.Compound()
for child in system.children:
    if child.name == 'SOL':
        water.add(mb.clone(child))
    elif child.name in ['Na', 'Cl']:
        ions.add(mb.clone(child))
    else:
예제 #16
0
def run_gemc(**custom_args):

    # Use mbuild to create molecules
    methane = mbuild.Compound(name="_CH4")

    # Create two empty mbuild.Box
    # (vapor = larger, liquid = smaller)
    liquid_box = mbuild.Box(lengths=[3.0, 3.0, 3.0])
    vapor_box = mbuild.Box(lengths=[4.0, 4.0, 4.0])

    # Load forcefields
    trappe = foyer.forcefields.load_TRAPPE_UA()

    # Use foyer to apply forcefields
    typed_methane = trappe.apply(methane)

    # Create box and species list
    box_list = [liquid_box, vapor_box]
    species_list = [typed_methane]

    mols_to_add = [[350], [100]]

    system = mc.System(box_list, species_list, mols_to_add=mols_to_add)
    moveset = mc.MoveSet("gemc", species_list)

    moveset.prob_volume = 0.010
    moveset.prob_swap = 0.11

    thermo_props = [
        "energy_total",
        "energy_intervdw",
        "pressure",
        "volume",
        "nmols",
        "mass_density",
    ]

    default_args = {
        "run_name": "equil",
        "charge_style": "none",
        "rcut_min": 2.0 * u.angstrom,
        "vdw_cutoff": 14.0 * u.angstrom,
        "units": "sweeps",
        "steps_per_sweep": 450,
        "coord_freq": 50,
        "prop_freq": 10,
        "properties": thermo_props,
    }

    # Combine default/custom args and override default
    custom_args = {**default_args, **custom_args}

    mc.run(
        system=system,
        moveset=moveset,
        run_type="equilibration",
        run_length=250,
        temperature=151.0 * u.K,
        **custom_args,
    )

    # Update run_name and restart_name
    custom_args["run_name"] = "prod"
    custom_args["restart_name"] = "equil"

    mc.restart(
        system=system,
        moveset=moveset,
        run_type="production",
        run_length=750,
        temperature=151.0 * u.K,
        **custom_args,
    )
예제 #17
0
def run_gemc(job):
    "Run gemc"

    import mbuild
    import foyer
    import mosdef_cassandra as mc

    ff = foyer.Forcefield(job.fn("ff.xml"))

    # Load the compound and apply the ff
    compound = mbuild.load("C(F)(F)C(F)(F)F", smiles=True)
    compound_ff = ff.apply(compound)

    # Create box list and species list
    boxl = job.doc.liqbox_final_dim  # saved in nm
    liq_box = mbuild.load(job.fn("liqbox.xyz"))
    liq_box.periodicity = [boxl, boxl, boxl]
    boxl = job.doc.vapboxl  # nm
    vap_box = mbuild.Box(lengths=[boxl, boxl, boxl])

    box_list = [liq_box, vap_box]
    species_list = [compound_ff]

    mols_in_boxes = [[job.sp.N_liq], [0]]
    mols_to_add = [[0], [job.sp.N_vap]]

    system = mc.System(
        box_list,
        species_list,
        mols_in_boxes=mols_in_boxes,
        mols_to_add=mols_to_add,
    )

    # Create a new moves object
    moves = mc.Moves("gemc", species_list)

    # Edit the volume and swap move probability to be more reasonable
    orig_prob_volume = moves.prob_volume
    orig_prob_swap = moves.prob_swap
    new_prob_volume = 1.0 / (job.sp.N_liq + job.sp.N_vap)
    new_prob_swap = 4.0 / 0.05 / (job.sp.N_liq + job.sp.N_vap)
    moves.prob_volume = new_prob_volume
    moves.prob_swap = new_prob_swap

    moves.prob_translate = (moves.prob_translate + orig_prob_volume -
                            new_prob_volume)
    moves.prob_translate = (moves.prob_translate + orig_prob_swap -
                            new_prob_swap)

    # Define thermo output props
    thermo_props = [
        "energy_total",
        "pressure",
        "volume",
        "nmols",
        "mass_density",
        "enthalpy",
    ]

    # Define custom args
    custom_args = {
        "run_name": "equil",
        "charge_style": "ewald",
        "rcut_min": 1.0,
        "charge_cutoff_box2": 25.0,
        "vdw_cutoff_box1": 12.0,
        "vdw_cutoff_box2": 25.0,
        "units": "sweeps",
        "steps_per_sweep": job.sp.N_liq + job.sp.N_vap,
        "coord_freq": 500,
        "prop_freq": 10,
        "properties": thermo_props,
    }

    # Move into the job dir and start doing things
    with job:
        # Run equilibration
        mc.run(system=system,
               moves=moves,
               run_type="equilibration",
               run_length=job.sp.nsteps_eq,
               temperature=job.sp.T,
               **custom_args)

        # Adjust custom args for production
        custom_args["run_name"] = "prod"
        custom_args["restart_name"] = "equil"

        # Run production
        mc.restart(system=system,
                   moves=moves,
                   run_type="production",
                   run_length=job.sp.nsteps_prod,
                   temperature=job.sp.T,
                   **custom_args)
예제 #18
0
 def test_parmed_box(self, h2o):
     compound = mb.Compound()
     compound.add(h2o)
     tilted_box = mb.Box(lengths=[2.0, 2.0, 2.0], angles=[60.0, 80.0, 100.0])
     structure = compound.to_parmed(box=tilted_box)
     assert all(structure.box == [20.0, 20.0, 20.0, 60.0, 80.0, 100.0])
예제 #19
0
def run_md_pre(molecule, functional, project_name, dire, temperature,
               box_length, number_of_molecules, simulation_time, CUTOFF,
               SCF_tolerence, basis_set, ensemble, timestep, thermostat,
               table):
    current_molecule = mb.clone(molecule)
    molecule_pmd = mb.clone(current_molecule)
    molecule_pmd = molecule_pmd.to_parmed()
    atom_list, mass_list, total_mass = info_molecule(molecule_pmd)
    unique_atom_list = remove_duplicate(atom_list)
    num_atoms = len(atom_list)
    num_unique_atoms = len(unique_atom_list)
    unique_atom_list.sort()
    box = mb.Box(lengths=[box_length, box_length, box_length])
    current_molecule.xyz = table
    print(number_of_molecules)
    box_of_molecule = mb.fill_box(compound=current_molecule,
                                  n_compounds=number_of_molecules,
                                  box=box)
    filename = project_name + ".xyz"
    box_of_molecule.save(filename, overwrite=True)
    with open(project_name + ".xyz", 'r') as fin:
        data = fin.read().splitlines(True)
    with open(project_name + ".xyz", 'w') as fout:
        fout.writelines(data[2:])

    if basis_set[0] == None:
        basis_set = basis_set * num_unique_atoms
    if thermostat == None:

        thermostat = 'NOSE'
    if CUTOFF == None:
        CUTOFF = 900
    if SCF_tolerence == None:
        SCF_tolerence = 1e-6
    if ensemble == None:
        ensemble = 'NVT'

    mySim = sim.SIM()

    mySim.GLOBAL.RUN_TYPE = "MD"
    mySim.GLOBAL.PROJECT = project_name + "pre"
    mySim.GLOBAL.PRINT_LEVEL = "LOW"

    #FORCE EVAL SECTION
    mySim.FORCE_EVAL.METHOD = 'QUICKSTEP'
    mySim.FORCE_EVAL.STRESS_TENSOR = 'ANALYTICAL'

    mySim.FORCE_EVAL.DFT.BASIS_SET_FILE_NAME = dire + 'BASIS_MOLOPT'
    mySim.FORCE_EVAL.DFT.POTENTIAL_FILE_NAME = dire + 'GTH_POTENTIALS'
    mySim.FORCE_EVAL.DFT.CHARGE = 0
    mySim.FORCE_EVAL.DFT.MULTIPLICITY = 1
    mySim.FORCE_EVAL.DFT.MGRID.CUTOFF = CUTOFF
    mySim.FORCE_EVAL.DFT.MGRID.REL_CUTOFF = 50
    mySim.FORCE_EVAL.DFT.MGRID.NGRIDS = 4
    mySim.FORCE_EVAL.DFT.QS.METHOD = 'GPW'
    mySim.FORCE_EVAL.DFT.QS.EPS_DEFAULT = 1E-8
    mySim.FORCE_EVAL.DFT.QS.EXTRAPOLATION = 'ASPC'
    mySim.FORCE_EVAL.DFT.POISSON.PERIODIC = "XYZ"
    mySim.FORCE_EVAL.DFT.PRINT.E_DENSITY_CUBE.SECTION_PARAMETERS = "OFF"
    mySim.FORCE_EVAL.DFT.SCF.SCF_GUESS = 'ATOMIC'
    mySim.FORCE_EVAL.DFT.SCF.MAX_SCF = 2
    mySim.FORCE_EVAL.DFT.SCF.EPS_SCF = SCF_tolerence

    mySim.FORCE_EVAL.DFT.SCF.OT.SECTION_PARAMETERS = ".TRUE."
    mySim.FORCE_EVAL.DFT.SCF.OT.PRECONDITIONER = "FULL_SINGLE_INVERSE"
    mySim.FORCE_EVAL.DFT.SCF.OT.MINIMIZER = "DIIS"
    mySim.FORCE_EVAL.DFT.SCF.OUTER_SCF.SECTION_PARAMETERS = '.TRUE.'

    mySim.FORCE_EVAL.DFT.SCF.OUTER_SCF.MAX_SCF = 10
    mySim.FORCE_EVAL.DFT.SCF.OUTER_SCF.EPS_SCF = 1e-6
    mySim.FORCE_EVAL.DFT.SCF.PRINT.RESTART.SECTION_PARAMETERS = 'OFF'
    mySim.FORCE_EVAL.DFT.SCF.PRINT.DM_RESTART_WRITE = '.TRUE.'

    mySim.FORCE_EVAL.DFT.XC.XC_FUNCTIONAL.SECTION_PARAMETERS = functional
    mySim.FORCE_EVAL.DFT.XC.VDW_POTENTIAL.POTENTIAL_TYPE = 'PAIR_POTENTIAL'
    mySim.FORCE_EVAL.DFT.XC.VDW_POTENTIAL.PAIR_POTENTIAL.TYPE = 'DFTD3'
    mySim.FORCE_EVAL.DFT.XC.VDW_POTENTIAL.PAIR_POTENTIAL.PARAMETER_FILE_NAME = 'dftd3.dat'
    mySim.FORCE_EVAL.DFT.XC.VDW_POTENTIAL.PAIR_POTENTIAL.REFERENCE_FUNCTIONAL = functional
    mySim.FORCE_EVAL.DFT.XC.VDW_POTENTIAL.PAIR_POTENTIAL.R_CUTOFF = 11

    mySim.FORCE_EVAL.SUBSYS.COORD.DEFAULT_KEYWORD = project_name + ".xyz"
    mySim.FORCE_EVAL.SUBSYS.init_atoms(num_atoms)

    for i in range(num_unique_atoms):
        mySim.FORCE_EVAL.SUBSYS.KIND[
            i + 1].SECTION_PARAMETERS = unique_atom_list[i]
        if basis_set[i] == None:

            mySim.FORCE_EVAL.SUBSYS.KIND[i + 1].BASIS_SET = basis_set_setter(
                unique_atom_list[i])
        else:
            mySim.FORCE_EVAL.SUBSYS.KIND[i + 1].BASIS_SET = basis_set[i]
        mySim.FORCE_EVAL.SUBSYS.KIND[i + 1].POTENTIAL = potential(
            unique_atom_list[i], functional)
    mySim.FORCE_EVAL.SUBSYS.CELL.ABC = '{L} {L} {L}'.format(L=10 * box_length)

    #MOTION SECTION
    mySim.MOTION.GEO_OPT.OPTIMIZER = 'BFGS'
    mySim.MOTION.GEO_OPT.MAX_ITER = 100
    mySim.MOTION.GEO_OPT.MAX_DR = 0.003

    mySim.MOTION.MD.ENSEMBLE = ensemble
    mySim.MOTION.MD.STEPS = 1
    mySim.MOTION.MD.TIMESTEP = 0.2

    mySim.MOTION.MD.TEMPERATURE = temperature
    mySim.MOTION.MD.THERMOSTAT.TYPE = thermostat
    mySim.MOTION.MD.THERMOSTAT.REGION = "MASSIVE"
    mySim.MOTION.MD.THERMOSTAT.NOSE.LENGTH = 3
    mySim.MOTION.MD.THERMOSTAT.NOSE.YOSHIDA = 3
    mySim.MOTION.MD.THERMOSTAT.NOSE.TIMECON = 1000.0
    mySim.MOTION.MD.THERMOSTAT.NOSE.MTS = 2

    #mySim.MOTION.MD.PRINT.ENERGY.EACH.MD = 20
    #mySim.MOTION.MD.PRINT.PROGRAM_RUN_INFO.EACH.MD = 20
    #mySim.MOTION.MD.AVERAGES.SECTION_PARAMETERS= ".falbmbjse."

    mySim.MOTION.PRINT.STRESS.SECTION_PARAMETERS = 'OFF'
    mySim.MOTION.PRINT.TRAJECTORY.EACH.MD = 1
    mySim.MOTION.PRINT.VELOCITIES.SECTION_PARAMETERS = 'OFF'
    mySim.MOTION.PRINT.FORCES.SECTION_PARAMETERS = "OFF"
    mySim.MOTION.PRINT.RESTART_HISTORY.SECTION_PARAMETERS = "ON"
    mySim.MOTION.PRINT.RESTART_HISTORY.EACH.MD = 500
    mySim.MOTION.PRINT.RESTART.SECTION_PARAMETERS = "ON"
    mySim.MOTION.PRINT.RESTART.BACKUP_COPIES = 3

    mySim.MOTION.PRINT.RESTART.EACH.MD = 1

    mySim.write_changeLog(fn="md-pre-changeLog.out")
    mySim.write_errorLog()
    mySim.write_inputFile(fn='md-pre.inp')
예제 #20
0
import mbuild as mb


class I2(mb.Compound):
    def __init__(self):
        super(I2, self).__init__()

        iodine1 = mb.Particle(pos=[0.0, 0.0, 0.0], name='I')
        iodine2 = mb.Particle(pos=[0.8, 0.0, 0.0], name='I')
        self.add([iodine2, iodine1])
        self.add_bond((iodine2, iodine1))


i2 = I2()
i2.energy_minimize(steps=100, algorithm='steep', forcefield='GAFF')

box = mb.Box(lengths=[1.5115, 1.5115, 1.5115])

box_of_i2 = mb.fill_box(compound=i2, n_compounds=n, box=box)
box_of_i2.energy_minimize(steps=1000, algorithm='md', forcefield='GAFF')
box_of_i2.save('iodine.xyz')
with open('iodine.xyz', 'r') as fin:
    data = fin.read().splitlines(True)
with open('iodine.xyz', 'w') as fout:
    fout.writelines(data[2:])
예제 #21
0
 def test_fill_box_density_n_compounds(self, h2o):
     filled = mb.fill_box(h2o,
                          density=1000,
                          box=mb.Box([3.1042931, 3.1042931, 3.1042931]))
     assert filled.n_particles == 3000
예제 #22
0
# Load the force field from foyer
ff = foyer.forcefields.load_OPLSAA()

# Create an ethane molecule from the SMILES string
ethane = mbuild.load("CC", smiles=True)

# Apply the force field
ethane_ff = ff.apply(ethane)

# Initial vapor box based IG law @ 250 K, 10 bar
N_vapor = 50
pressure = 10.0 * u.bar
temperature = 250 * u.K
vapor_volume = N_vapor * u.kb * temperature / pressure
box_length = (vapor_volume**(1. / 3.)).to_value(u.nm)
box = mbuild.Box([box_length, box_length, box_length])
vapor_box = mbuild.fill_box(ethane, n_compounds=N_vapor, box=box)

# Initial liquid box from existing configuration
liquid_box = mbuild.load("liqbox_equil.gro")
N_liquid = len([child for child in liquid_box.children])

# Create the System and MoveSet
box_list = [liquid_box, vapor_box]
species_list = [ethane_ff]
mols_in_boxes = [[N_liquid], [N_vapor]]

system = mc.System(
    box_list,
    species_list,
    mols_in_boxes=mols_in_boxes,
def specific_ff_to_residue(
    structure,
    forcefield_selection=None,
    residues=None,
    reorder_res_in_pdb_psf=False,
    boxes_for_simulation=1,
):
    """
    Takes the mbuild Compound or mbuild Box structure and applies the selected
    force field to the corresponding residue via foyer.
    Note: a residue is defined as a molecule in this case, so it is not
    designed for applying a force field to a protein.

    Parameters
    ----------
    structure: mbuild Compound object or mbuild Box object;
        The mBuild Compound object or mbuild Box object, which contains the molecules
        (or empty box) that will have the force field applied to them.
    forcefield_selection: str or dictionary, default=None
        Apply a forcefield to the output file by selecting a force field xml file with
        its path or by using the standard force field name provided the `foyer` package.
        Example dict for FF file: {'ETH' : 'oplsaa.xml', 'OCT': 'path_to file/trappe-ua.xml'}
        Example str for FF file: 'path_to file/trappe-ua.xml'
        Example dict for standard FF names : {'ETH' : 'oplsaa', 'OCT': 'trappe-ua'}
        Example str for standard FF names: 'trappe-ua'
        Example of a mixed dict with both : {'ETH' : 'oplsaa', 'OCT': 'path_to file/'trappe-ua.xml'}
    residues: list, [str, ..., str], default=None
        Labels of unique residues in the Compound. Residues are assigned by
        checking against Compound.name.  Only supply residue names as 4 characters
        strings, as the residue names are truncated to 4 characters to fit in the
        psf and pdb file.
    reorder_res_in_pdb_psf: bool, default=False
        This option provides the ability to reorder the residues/molecules from the original
        structure's order.  If True, the residues will be reordered as they appear in the residues
        variable.  If False, the order will be the same as entered in the original structure.
    boxes_for_simulation: int [1, 2], default = 1
        Gibbs (GEMC) or grand canonical (GCMC) ensembles are examples of where the boxes_for_simulation would be 2.
        Canonical (NVT) or isothermal–isobaric (NPT) ensembles are example with the boxes_for_simulation equal to 1.
        Note: the only valid options are 1 or 2.

    Returns
    -------
    list, [structure, coulomb14scalar_dict, lj14_scalar_dict, residues_applied_list]
        structure: parmed.Structure
            parmed structure with applied force field
        coulomb14scalar_dict: dict
            a dictionary with the 1,4-colombic scalars for each residue
                (i.e., a different force field could on each residue)
        lj14_scalar_dict: dict
            a dictionary with the 1,4-LJ scalars for each residue
            (i.e., a different force field could on each residue)
        residues_applied_list: list
            list of residues (i.e., list of stings).
            These are all the residues in which the force field actually applied

    Notes
    -----
    To write the NAMD/GOMC force field, pdb, psf, and force field
    (.inp) files, the residues and forcefields must be provided in
    a str or dictionary. If a dictionary is provided all residues must
    be specified to a force field if the boxes_for_simulation is equal to 1.

    Generating an empty box (i.e., pdb and psf files):
    Enter residues = [], but the accompanying structure must be an empty mb.Box.
    However, when doing this, the forcefield_selection must be supplied,
    or it will provide an error (i.e., forcefield_selection can not be equal to None).

    In this current FF/psf/pdb writer, a residue type is essentially a molecule type.
    Therefore, it can only correctly write systems where every bead/atom in the molecule
    has the same residue name, and the residue name is specific to that molecule type.
    For example: a protein molecule with many residue names is not currently supported,
    but is planned to be supported in the future.
    """

    if has_foyer:
        from foyer import Forcefield
        from foyer.forcefields import forcefields
    else:
        print_error_message = (
            "Package foyer is not installed. "
            "Please install it using conda install -c conda-forge foyer")
        raise ImportError(print_error_message)

    if not isinstance(structure, (Compound, mb.Box)):
        print_error_message = ("ERROR: The structure expected to be of type: "
                               "{} or {}, received: {}".format(
                                   type(Compound()),
                                   type(mb.Box(lengths=[1, 1, 1])),
                                   type(structure),
                               ))
        raise TypeError(print_error_message)

    print("forcefield_selection = " + str(forcefield_selection))
    if forcefield_selection is None:
        print_error_message = (
            "Please the force field selection (forcefield_selection) as a dictionary "
            "with all the residues specified to a force field "
            '-> Ex: {"Water" : "oplsaa", "OCT": "path/trappe-ua.xml"}, '
            "Note: the file path must be specified the force field file "
            "or by using the standard force field name provided the `foyer` package."
        )
        raise TypeError(print_error_message)

    elif forcefield_selection is not None and not isinstance(
            forcefield_selection, dict):
        print_error_message = (
            "The force field selection (forcefield_selection) "
            "is not a dictionary. Please enter a dictionary "
            "with all the residues specified to a force field "
            '-> Ex: {"Water" : "oplsaa", "OCT": "path/trappe-ua.xml"}, '
            "Note: the file path must be specified the force field file "
            "or by using the standard force field name provided the `foyer` package."
        )
        raise TypeError(print_error_message)

    if residues is None or not isinstance(residues, list):
        print_error_message = (
            "Please enter the residues in the Specific_FF_to_residue function."
        )
        raise TypeError(print_error_message)

    if not isinstance(reorder_res_in_pdb_psf, bool):
        print_error_message = (
            "Please enter the reorder_res_in_pdb_psf "
            "in the Specific_FF_to_residue function (i.e., True or False).")
        raise TypeError(print_error_message)

    print_error_message_for_boxes_for_simulatiion = (
        "ERROR: Please enter boxes_for_simulation equal "
        "the integer 1 or 2.")
    if not isinstance(boxes_for_simulation, int):
        raise TypeError(print_error_message_for_boxes_for_simulatiion)

    elif isinstance(boxes_for_simulation,
                    int) and boxes_for_simulation not in [
                        1,
                        2,
                    ]:
        raise ValueError(print_error_message_for_boxes_for_simulatiion)

    forcefield_keys_list = []
    if forcefield_selection is not None:
        for res in forcefield_selection.keys():
            forcefield_keys_list.append(res)
        ff_data = forcefield_selection

    if forcefield_keys_list == [] and len(residues) != 0:
        print_error_message = "The forcefield_selection variable are not provided, but there are residues provided."
        raise ValueError(print_error_message)

    elif forcefield_keys_list != [] and len(residues) == 0:
        print_error_message = (
            "The residues variable is an empty list but there are "
            "forcefield_selection variables provided.")
        raise ValueError(print_error_message)

    user_entered_ff_with_path_dict = (
        {}
    )  # True means user entered the path, False is a standard foyer FF with no path
    for z in range(0, len(forcefield_keys_list)):
        for res_i in range(0, len(residues)):
            if residues[res_i] == forcefield_keys_list[z]:
                if (os.path.splitext(ff_data[forcefield_keys_list[z]])[1]
                        == ".xml" and len(residues) != 0):
                    user_entered_ff_with_path_dict.update(
                        {residues[res_i]: True})
                elif (os.path.splitext(ff_data[forcefield_keys_list[z]])[1]
                      == "" and len(residues) != 0):
                    user_entered_ff_with_path_dict.update(
                        {residues[res_i]: False})
                else:
                    print_error_message = (
                        r"Please make sure you are entering the correct "
                        "foyer FF name and not a path to a FF file. "
                        "If you are entering a path to a FF file, "
                        "please use the forcefield_files variable with the "
                        "proper XML extension (.xml).")
                    raise ValueError(print_error_message)

    coulomb14scalar_dict = {}
    lj14_scalar_dict = {}
    for j in range(0, len(forcefield_keys_list)):
        residue_iteration = forcefield_keys_list[j]
        if user_entered_ff_with_path_dict[residue_iteration]:
            ff_for_residue_iteration = ff_data[residue_iteration]
            try:
                read_xlm_iteration = minidom.parse(ff_for_residue_iteration)

            except:
                print_error_message = (
                    "Please make sure you are entering the correct foyer FF path, "
                    "including the FF file name.xml "
                    "If you are using the pre-build FF files in foyer, "
                    "only use the string name without any extension.")
                raise ValueError(print_error_message)
        elif not user_entered_ff_with_path_dict[residue_iteration]:
            ff_for_residue_iteration = ff_data[residue_iteration]
            ff_names_path_iteration = (forcefields.get_ff_path()[0] + "/xml/" +
                                       ff_for_residue_iteration + ".xml")
            try:
                read_xlm_iteration = minidom.parse(ff_names_path_iteration)
            except:
                print_error_message = (
                    "Please make sure you are entering the correct foyer FF name, or the "
                    "correct file extension (i.e., .xml, if required).")
                raise ValueError(print_error_message)
        lj_coul_1_4_values = read_xlm_iteration.getElementsByTagName(
            "NonbondedForce")

        for Scalar in lj_coul_1_4_values:
            coulomb14scalar_dict.update({
                residue_iteration:
                float(Scalar.getAttribute("coulomb14scale"))
            })
            lj14_scalar_dict.update(
                {residue_iteration: float(Scalar.getAttribute("lj14scale"))})

    # Check to see if it is an empty mbuild.Compound and set intial atoms to 0
    # note empty mbuild.Compound will read 1 atoms but there is really noting there
    if isinstance(structure, Compound):
        if len(structure.children) == 0:
            # there are no real atoms in the Compound so the test fails. User should use mbuild.Box
            print_error_message = (
                "ERROR: If you are not providing an empty box, "
                "you need to specify the atoms/beads as children in the mb.Compound. "
                "If you are providing and empty box, please do so by specifying and "
                "mbuild Box ({})".format(type(mb.Box(lengths=[1, 1, 1]))))
            raise TypeError(print_error_message)
        else:
            initial_no_atoms = len(structure.to_parmed().atoms)

    # calculate the initial number of atoms for later comparison
    if isinstance(structure, mb.Box):
        lengths = structure.lengths
        angles = structure.angles

        structure = mb.Compound()
        structure.box = mb.Box(lengths=lengths, angles=angles)
        initial_no_atoms = 0

    # add the FF to the residues
    compound_box_infor = structure.to_parmed(residues=residues)
    new_structure = pmd.Structure()
    new_structure.box = compound_box_infor.box

    # prepare all compound and remove nested compounds
    no_layers_to_check_for_residues = 3

    print_error_message_all_res_not_specified = (
        "ERROR: All the residues are not specified, or "
        "the residues entered does not match the residues that "
        "were found and built for structure.")
    for j in range(0, no_layers_to_check_for_residues):
        new_compound_iter = mb.Compound()
        new_compound_iter.periodicity = structure.periodicity
        if structure.name in residues:
            if len(structure.children) == 0:
                warn(
                    "Warning: This residue is the atom, and is a single atom., "
                    + str(structure.name))
                new_compound_iter.add(mb.compound.clone(structure))

            elif len(structure.children) > 0:

                new_compound_iter.add(mb.compound.clone(structure))

        else:
            for child in structure.children:
                if len(child.children) == 0:
                    if child.name not in residues:
                        raise ValueError(
                            print_error_message_all_res_not_specified)

                    else:
                        new_compound_iter.add(mb.compound.clone(child))

                elif len(child.children) > 0:
                    if child.name in residues:
                        new_compound_iter.add(mb.compound.clone(child))
                    else:
                        for sub_child in child.children:
                            if sub_child.name in residues:
                                new_compound_iter.add(
                                    mb.compound.clone(sub_child))

                            else:
                                if len(sub_child.children) == 0 and (
                                        child.name not in residues):

                                    raise ValueError(
                                        print_error_message_all_res_not_specified
                                    )

        structure = new_compound_iter

    residues_applied_list = []
    residue_orig_order_list = []
    for child in structure.children:
        if child.name not in residue_orig_order_list:
            residue_orig_order_list.append(child.name)
    for res_reorder_iter in range(0, len(residues)):
        if residues[res_reorder_iter] not in residue_orig_order_list:
            text_to_print_1 = (
                "All the residues were not used from the forcefield_selection "
                "string or dictionary. There may be residues below other "
                "specified residues in the mbuild.Compound hierarchy. "
                "If so, all the highest listed residues pass down the force "
                "fields through the hierarchy. Alternatively, residues that "
                "are not in the structure may have been specified. ")
            text_to_print_2 = (
                "Note: This warning will appear if you are using the CHARMM pdb and psf writers "
                +
                "2 boxes, and the boxes do not contain all the residues in each box."
            )
            if boxes_for_simulation == 1:
                warn(text_to_print_1)
                raise ValueError(text_to_print_1)
            if boxes_for_simulation == 2:
                warn(text_to_print_1 + text_to_print_2)

    if not reorder_res_in_pdb_psf:
        residues = residue_orig_order_list
    elif reorder_res_in_pdb_psf:
        print(
            "INFO: the output file are being reordered in via the residues list's sequence."
        )

    for i in range(0, len(residues)):
        children_in_iteration = False
        new_compound_iteration = mb.Compound()
        new_compound_iter.periodicity = structure.periodicity
        new_structure_iteration = pmd.Structure()
        new_structure_iteration.box = compound_box_infor.box
        for child in structure.children:
            if ff_data.get(child.name) is None:
                print_error_message = "ERROR: All residues are not specified in the force_field dictionary"
                raise ValueError(print_error_message)

            if child.name == residues[i]:
                children_in_iteration = True
                new_compound_iteration.add(mb.compound.clone(child))

        if children_in_iteration:
            if user_entered_ff_with_path_dict[residues[i]]:
                ff_iteration = Forcefield(ff_data[residues[i]])
                residues_applied_list.append(residues[i])
            elif not user_entered_ff_with_path_dict[residues[i]]:
                ff_iteration = Forcefield(name=ff_data[residues[i]])
                residues_applied_list.append(residues[i])

            new_compound_iteration.box = None
            new_structure_iteration = ff_iteration.apply(
                new_compound_iteration, residues=[residues[i]])
            new_structure = new_structure + new_structure_iteration

    structure = new_structure

    # calculate the final number of atoms
    final_no_atoms = len(structure.atoms)

    if final_no_atoms != initial_no_atoms:
        print_error_message = (
            "ERROR: The initial number of atoms sent to the force field analysis is "
            "not the same as the final number of atoms analyzed. "
            "The initial number of atoms was {} and the final number of atoms was {}. "
            "Please ensure that all the residues names that are in the initial "
            "Compound are listed in the residues list "
            "(i.e., the residues variable).".format(initial_no_atoms,
                                                    final_no_atoms))
        raise ValueError(print_error_message)

    return [
        structure,
        coulomb14scalar_dict,
        lj14_scalar_dict,
        residues_applied_list,
    ]
예제 #24
0
def simulation_system(
        morphology,
        args):  # Corresponds with the create_morphology() function in rhaco
    # Get the crystal IDs because we're going to need them later so that HOOMD
    # knows not to integrate them.
    crystal_IDs = range(system.n_particles)
    # Now we can populate the box with reactant
    reactant_components, reactant_probs, reactant_masses = calculate_probabilities(
        args.reactant_composition, ratio_type='number')

    # Define the regions that the hydrocarbons can go in, so we don't end
    # up with them between layers
    box_top = mb.Box(mins=[
        -(args.crystal_x * args.dimensions[0]) / 2.0,
        -(args.crystal_y * args.dimensions[1]) / 2.0,
        args.crystal_separation / 20.0 + (args.crystal_z * args.dimensions[2])
    ],
                     maxs=[(args.crystal_x * args.dimensions[0]) / 2.0,
                           (args.crystal_y * args.dimensions[1]) / 2.0,
                           args.z_reactor_size / 2.0])
    box_bottom = mb.Box(mins=[
        -(args.crystal_x * args.dimensions[0]) / 2.0,
        -(args.crystal_y * args.dimensions[1]) / 2.0,
        -args.z_reactor_size / 2.0
    ],
                        maxs=[(args.crystal_x * args.dimensions[0]) / 2.0,
                              (args.crystal_y * args.dimensions[1]) / 2.0,
                              -args.crystal_separation / 20.0 -
                              (args.crystal_z * args.dimensions[2])])
    box_top_vol = np.prod(box_top.maxs - box_top.mins)
    box_bottom_vol = np.prod(box_bottom.maxs - box_bottom.mins)
    reactor_vol = box_top_vol + box_bottom_vol

    # No reactants given
    if (args.reactant_density is None):
        number_of_reactant_mols = 0
    elif (args.reactant_density is not None):
        # Work backwards to come up with how many reactant molecules are needed
        # to get the specified density.
        # Get the average mass for each molecule based on reactant probabilities
        mass_per_n = np.sum([
            reactant_masses[key] * reactant_probs[index]
            for index, key in enumerate(reactant_components)
        ])
        # Given the reactor volume and the specified reactant density, calculate
        # the total number of reactant molecules needed.
        # to convert from CGS (g/cm^{3} -> AMU/nm^{3})
        reactant_density_conv = args.reactant_density * G_TO_AMU / (CM_TO_NM**
                                                                    3)
        number_of_reactant_mols = int(reactant_density_conv * reactor_vol /
                                      mass_per_n)

        reactant_compounds = []
        n_compounds = []
        for compound_index, reactant_molecule in enumerate(
                reactant_components):
            reactant_compounds.append(mbuild_template(reactant_molecule))
            n_compounds.append(
                int(
                    np.round(
                        np.round(reactant_probs[compound_index] *
                                 number_of_reactant_mols) / 2.0)))
        reactant_top = mb.packing.fill_box(reactant_compounds,
                                           n_compounds,
                                           box_top,
                                           seed=np.random.randint(
                                               0, 2**31 - 1))
        reactant_bottom = mb.packing.fill_box(reactant_compounds,
                                              n_compounds,
                                              box_bottom,
                                              seed=np.random.randint(
                                                  0, 2**31 - 1))
        system.add(reactant_top)
        system.add(reactant_bottom)

    if "M1UnitCell.pdb" in args.template:
        # Check the separation of crystal and reactant that we will use later is
        # correct. Get the set of atom types that produce the crystal (and
        # don't include the base atom type, which we asusme to be oxygen).
        names = [
            particle.name
            for particle_ID, particle in enumerate(system.particles())
            if (particle_ID in crystal_IDs) and (particle.name != 'O')
        ]
        # Ensure that this is the same as the stoichiometry dictionary keys
        assert (np.array_equal(args.stoichiometry.keys(), set(names)))

    # Generate the morphology box based on the input parameters
    system_box = mb.Box(mins=[
        -(args.crystal_x * args.dimensions[0]) / 2.0,
        -(args.crystal_y * args.dimensions[1]) / 2.0,
        -args.z_reactor_size / 2.0
    ],
                        maxs=[(args.crystal_x * args.dimensions[0]) / 2.0,
                              (args.crystal_y * args.dimensions[1]) / 2.0,
                              args.z_reactor_size / 2.0])
    print("Morphology generated.")

    if (args.forcefield is None) or ((len(args.forcefield[0]) == 0) and
                                     (len(args.forcefield[1]) == 0)):
        print("Saving morphology...")
        system.save(output_file, overwrite=True, box=system_box)
        # Fix the images because mbuild doesn't set them correctly
        morphology = fix_images(output_file)
    else:
        print("Applying forcefield...")
예제 #25
0
class TestLattice(BaseTest):
    """
    Unit Tests for Lattice class functionality.
    """
    def test_dimension_default(self):
        space = [1, 1, 1]
        a_test = mb.Lattice(dimension=None, lattice_spacings=space)
        assert a_test.dimension == 3
        a_test = mb.Lattice(space, dimension='3')
        assert a_test.dimension == 3

    def test_dimension_1d(self):
        space = [
            1,
        ]
        a_test = mb.Lattice(space, dimension=1)
        assert a_test.dimension == 1

    def test_dimension_2d(self):
        space = [1, 1]
        a_test = mb.Lattice(space, dimension=2)
        assert a_test.dimension == 2

    def test_dimension_3d(self):
        space = [1, 1, 1]
        a_test = mb.Lattice(space, dimension=3.0)
        assert a_test.dimension == 3

    @pytest.mark.parametrize("dim, space", [(4, [1, 1, 1, 1]),
                                            (([1, 2, 3]), [1, 1, 1])])
    def test_invalid_dimensions(self, dim, space):
        with pytest.raises(Exception):
            test_lattice = mb.Lattice(space, dimension=dim)

    @pytest.mark.parametrize("spacing, vec_default, dimension",
                             [([
                                 1,
                             ], np.identity(1, dtype=float), 1),
                              ([1, 1], np.identity(2, dtype=float), 2),
                              ([1, 1, 1], np.identity(3, dtype=float), 3)])
    def test_lattice_vectors_default(self, spacing, vec_default, dimension):

        test_lattice = mb.Lattice(spacing,
                                  dimension=dimension,
                                  lattice_vectors=None)
        np.testing.assert_array_equal(vec_default,
                                      test_lattice.lattice_vectors)

    @pytest.mark.parametrize("spacing, invalid_shape, dim",
                             [([
                                 1,
                             ], np.identity(3, dtype=float), 1),
                              ([1, 1], np.identity(3, dtype=float), 2),
                              ([1, 1, 1], np.identity(2, dtype=float), 3)])
    def test_lattice_vectors_invalid_shape(self, spacing, invalid_shape, dim):
        with pytest.raises(ValueError):
            test_lattice = mb.Lattice(spacing,
                                      dimension=dim,
                                      lattice_vectors=invalid_shape)

    @pytest.mark.parametrize(
        "space, dim, colinear",
        [([1, 1], 2, [[1, 0], [3, 0]]),
         ([1, 1, 1], 3, [[1, 0, 0], [0, 1, 0], [2, 0, 0]])])
    def test_colinear_lattice_vectors(self, space, dim, colinear):
        vectors = np.asarray(colinear, dtype=None)
        with pytest.raises(ValueError):
            test_lattice = mb.Lattice(space,
                                      dimension=dim,
                                      lattice_vectors=vectors)

    @pytest.mark.parametrize(
        "spacing, dim, invalid",
        [([1, 1], 2, [[1, 2], [2, 1]]),
         ([1, 1, 1], 3, [[1, 2, 3], [3, 2, 1], [2, 1, 3]])])
    def test_handedness_lattice_vectors(self, spacing, dim, invalid):
        invalid_handed = np.asarray(invalid, dtype=float)
        with pytest.raises(ValueError):
            test_lattice = mb.Lattice(spacing,
                                      dimension=dim,
                                      lattice_vectors=invalid_handed)

    @pytest.mark.parametrize("dim, invalid_space",
                             [(3, ([.12], [.13], [.14])),
                              (3, ([0.12, 0.13, 0.14, 0.15]))])
    def test_lattice_spacings_dimension(self, dim, invalid_space):
        with pytest.raises(ValueError):
            spacing_test = mb.Lattice(invalid_space, dimension=dim)

    @pytest.mark.parametrize("dim , space_invalid", [(1, [0]), (1, [-0.14]),
                                                     (2, [.12, 0]),
                                                     (2, [.13, -.14]),
                                                     (3, [.12, 0, 0.13]),
                                                     (3, [.12, .13, -.14])])
    def test_lattice_spacings_negative_or_zero(self, dim, space_invalid):
        with pytest.raises(ValueError):
            zero_lattice = mb.Lattice(space_invalid, dimension=dim)

    def test_lattice_spacings_correct(self):
        correct_spacings = [0.12, 0.13, 0.14]
        input_spacings = [0.12, 0.13, 0.14]
        test_lattice = mb.Lattice(input_spacings)
        np.testing.assert_array_equal(test_lattice.lattice_spacings,
                                      correct_spacings)

    @pytest.mark.parametrize("space, correct, dim",
                             [([1.], 'default', 1), ([1., 1.], 'default', 2),
                              ([1., 1., 1.], 'default', 3)])
    def test_basis_atoms_default(self, space, correct, dim):
        test_lattice = mb.Lattice(space, dimension=dim)
        assert len(test_lattice.basis_atoms.keys()) == 1

        for key in test_lattice.basis_atoms.keys():
            assert key == correct

        correct_pos = [0. for x in range(dim)]
        np.testing.assert_array_equal(test_lattice.basis_atoms[correct][0],
                                      correct_pos)

    @pytest.mark.parametrize("space, dim, type", [([1, 1, 1], 3, list()),
                                                  ([1, 1, 1], 3, tuple()),
                                                  ([1, 1, 1], 3, str())])
    def test_basis_atoms_input_type(self, space, dim, type):
        with pytest.raises(TypeError):
            test_lat = mb.Lattice(space, dimension=dim, basis_atoms=type)

    @pytest.mark.parametrize(
        "space, dim, name, coords",
        [([1, 1, 1], 3, 'test', [[0, 0, 0, 0]]),
         ([1, 1, 1], 3, 'test', [[0, 0, 0], [0, 0, 0, 0]]),
         ([1, 1, 1], 3, 'test', [[0, 0], [0, 0, 0]]),
         ([1, 1, 1], 3, 'test', [[0, 0]])])
    def test_basis_atoms_input_size(self, space, dim, name, coords):
        basis = {name: coords}
        with pytest.raises(ValueError):
            test_lattice = mb.Lattice(space, dimension=dim, basis_atoms=basis)

    @pytest.mark.parametrize(
        "space, dim, name, coords",
        [([1, 1, 1], 3, 'test', [[0., 0., -.2]]),
         ([1, 1, 1], 3, 'test', [[0., 0., 0.], [0., 0., -.2]]),
         ([1, 1, 1], 3, 'test', [[0., 0., 1.2]]),
         ([1, 1, 1], 3, 'test', [[0., 0., 0.], [0., 0., 1.2]])])
    def test_basis_atoms_location(self, space, dim, name, coords):
        basis = {name: coords}
        with pytest.raises(ValueError):
            test_lattice = mb.Lattice(space, dimension=dim, basis_atoms=basis)

    @pytest.mark.parametrize(
        "space, dim, name, overlap",
        [([1, 1, 1], 3, 'test', [[0., 0., 0.], [0., 0., 0.]]),
         ([1, 1, 1], 3, 'test', [[0., .5, 0.], [0., .5, 0]])])
    def test_basis_overlap_1_tag(self, space, dim, name, overlap):
        basis = {name: overlap}
        with pytest.raises(ValueError):
            test_lattice = mb.Lattice(space, dimension=dim, basis_atoms=basis)

    def test_basis_atoms_overlap_2tags(self):
        dim = 3
        lat_space = [1., 1., 1.]
        overlap_diff_basis_repeat = {
            'test': [[0., 0., 0.]],
            'test2': [[.5, .5, .5], [0., 0., 0.]]
        }

        with pytest.raises(ValueError):
            test_lattice = mb.Lattice(lat_space,
                                      dimension=dim,
                                      basis_atoms=overlap_diff_basis_repeat)

    def test_overdefinied_inputs(self):
        dim = 3
        lat_space = [1., 1., 1.]
        angles = [90., 90., 90.]
        lattice_vec = [1, 1, 1]

        with pytest.raises(ValueError):
            test_lattice = mb.Lattice(lat_space,
                                      dimension=dim,
                                      angles=angles,
                                      lattice_vectors=lattice_vec)

    @pytest.mark.parametrize("dim, space, angles",
                             [(1, [1], [90]), (2, [1, 1], [90, 90]),
                              (3, [1, 1, 1], [90, 90]),
                              (2, [1, 1], [90, 90, 90]),
                              (3, [1, 1, 1], [90, 90, 90, 90])])
    def test_angle_invalid_size(self, dim, space, angles):
        with pytest.raises(ValueError):
            test_lattice = mb.Lattice(space, dimension=dim, angles=angles)

    @pytest.mark.parametrize("dim, space, angle",
                             [(2, [1, 1], [180]), (2, [1, 1], [0]),
                              (3, [1, 1, 1], [93, 70, 180]),
                              (3, [1, 1, 1], [93, 70, 0])])
    def test_angle_too_large_small(self, dim, space, angle):
        with pytest.raises(ValueError):
            test_lattice = mb.Lattice(space, dimension=dim, angles=angle)

    @pytest.mark.parametrize("dim, space, angle",
                             [(3, [1, 1, 1], [90, 90, 185]),
                              (3, [1, 1, 1], [-90, -90, -185])])
    def test_3d_sum_incorrect(self, dim, space, angle):
        with pytest.raises(ValueError):
            test_lattice = mb.Lattice(space, dimension=dim, angles=angle)

    @pytest.mark.parametrize("dim, space, angle",
                             [(3, [1, 1, 1], [60, 42, 105]),
                              (3, [1, 1, 1], [65, 120, 42])])
    def test_each_angle_sum_incorrect(self, dim, space, angle):
        with pytest.raises(ValueError):
            test_lattice = mb.Lattice(space, dimension=dim, angles=angle)

    @pytest.mark.parametrize("angle", [([0]), ([180]), ([181]), ([-181])])
    def test_angle_2d_incorrect(self, angle):
        dim = 2
        space = [1, 1]
        with pytest.raises(ValueError):
            test_lattice = mb.Lattice(space, dimension=dim, angles=angle)

    @pytest.mark.parametrize("spacing, dim, x, y, z",
                             [([1, 1, 1], 3, 0, 1, 1), ([1, 1, 1], 3, 1, 0, 1),
                              ([1, 1, 1], 3, 1, 1, 0),
                              ([1, 1, 1], 3, None, 1, 0),
                              ([1, 1, 1], 3, -1, -1, -1)])
    def test_populate_3d_incorrect_inputs(self, spacing, dim, x, y, z):
        test_lattice = mb.Lattice(spacing, dimension=dim)
        with pytest.raises(ValueError):
            test_lattice.populate(x=x, y=y, z=z)

    @pytest.mark.parametrize("spacing, dim, x, y", [([1, 1], 2, 0, 1),
                                                    ([1, 1], 2, 1, 0),
                                                    ([1, 1], 2, None, 0),
                                                    ([1, 1], 2, -1, -1)])
    def test_populate_2d_incorrect_inputs(self, spacing, dim, x, y):
        test_lattice = mb.Lattice(spacing, dimension=dim)
        with pytest.raises(ValueError):
            test_lattice.populate(x=x, y=y)

    @pytest.mark.parametrize("spacing, dim, x", [([1], 1, 0), ([1], 1, -1)])
    def test_populate_1d_incorrect_inputs(self, spacing, dim, x):
        test_lattice = mb.Lattice(spacing, dimension=dim)
        with pytest.raises(ValueError):
            test_lattice.populate(x=x)
            test_lattice.populate(y=x)
            test_lattice.populate(z=x)

    def test_populate_3d_default(self):
        test_lattice = mb.Lattice([1, 1, 1], dimension=3)
        a = test_lattice.populate()
        np.testing.assert_array_equal(a.xyz[0], [0., 0., 0.])

    def test_populate_2d_default(self):
        test_lattice = mb.Lattice([1, 1], dimension=2)
        a = test_lattice.populate()
        np.testing.assert_array_equal(a.xyz[0], [0., 0., 0.])

    def test_populate_1d_default(self):
        test_lattice = mb.Lattice([1], dimension=1)
        a = test_lattice.populate()
        np.testing.assert_array_equal(a.xyz[0], [0., 0., 0.])

    @pytest.mark.parametrize("my_type", [([]), (()), (np.array), (np.ndarray)])
    def test_populate_basis_type_incorrect(self, my_type):
        test_lattice = mb.Lattice([1, 1, 1], dimension=3)
        with pytest.raises(TypeError):
            test_lattice.populate(compound_dict=my_type)

    @pytest.mark.parametrize("not_compound", [(1), (mb.Box(lengths=[1, 1, 1])),
                                              ("aLattice")])
    def test_populate_not_compound(self, not_compound):
        test_lattice = mb.Lattice([1, 1, 1])
        particle_dict = {'default': not_compound}
        with pytest.raises(TypeError):
            test_lattice.populate(compound_dict=particle_dict)
예제 #26
0
def build_tam_emim_mxene(n_compounds,
                         composition,
                         periods,
                         chain_length=12,
                         displacement=1.1):
    """Build a MXene with TAM and EMIM in the interlayer

    Parameters
    ----------
    n_compounds : list
        List of [TAM, EMIM] compounds
    composition : dict
        Composition of MXene surface groups
    periods : list
        Periods of MXene crystal
    chain_length : int
        Chain length of TAM
    displacement : float
        Interlayer spacing (nm)
    """
    ti3c2 = build_structure(periods=periods,
                            composition=composition,
                            displacement=displacement,
                            lateral_shift=True,
                            atomtype=True)

    n_carbons = 'C' * chain_length
    aa = mb.load(f'{n_carbons}[N](C)(C)C', smiles=True)

    # Rename some carbons
    # CE = end carbon
    # CM = middle carbon
    # CB = branch carbon

    for idx, particle in enumerate(aa.particles()):
        if idx == 0:
            particle.name = 'C_E'
        if idx == chain_length / 2:
            particle.name = 'C_M'
        # TODO: Find way to get branch carbon index without
        # hardcoding
        if particle.name == 'N':
            n_index = idx
        try:
            if idx == n_index + 1:
                particle.name = 'C_B1'
            if idx == n_index + 2:
                particle.name = 'C_B2'
        except:
            continue

    emim = mb.load(get_il('emim'))
    emim.name = 'emim'

    aa.name = 'alkylam'

    lopes = get_ff('lopes')

    region1 = mb.Box(
        mins=[0, 0, (ti3c2.box[2] / 10 - 2 * displacement) / 2 + 0.15],
        maxs=[
            ti3c2.box[0] / 10, ti3c2.box[1] / 10,
            (ti3c2.box[2] / 10 - 2 * displacement) / 2 + displacement
        ])
    region2 = mb.Box(mins=[
        0, 0, (ti3c2.box[2] / 10 - 2 * displacement) + displacement + 0.15
    ],
                     maxs=[
                         ti3c2.box[0] / 10, ti3c2.box[1] / 10,
                         (ti3c2.box[2] / 10 - 2 * displacement) + 2 +
                         displacement
                     ])

    aa_1 = mb.fill_box(compound=[aa, emim],
                       n_compounds=n_compounds,
                       box=region1,
                       fix_orientation=True)

    aa_2 = mb.fill_box(compound=[aa, emim],
                       n_compounds=n_compounds,
                       box=region2,
                       fix_orientation=True)

    aa1PM = lopes.apply(aa_1,
                        residues=['alkylam', 'emim'],
                        assert_dihedral_params=False)
    aa2PM = lopes.apply(aa_2,
                        residues=['alkylam', 'emim'],
                        assert_dihedral_params=False)

    system = aa1PM + aa2PM + ti3c2
    system = _apply_nbfixes(system)
    system = collapse_atomtypes(system)
    change_charge(system, new_charge=0)
    system.box = ti3c2.box

    for atom in system.atoms:
        if atom.name == 'C_E':
            atom.name = 'CE'
        elif atom.name == 'C_M':
            atom.name = 'CM'
        elif atom.name == 'C_B1':
            atom.name = 'CB1'
        elif atom.name == 'C_B2':
            atom.name = 'CB2'

    system.save('ti3c2.gro', combine='all', overwrite=True)
    system.save('ti3c2.top', combine='all', overwrite=True)
    write_lammpsdata(system, 'data.mxene')
예제 #27
0
파일: test_box.py 프로젝트: whitehml/mbuild
 def test_init_bounds(self):
     box = mb.Box(mins=np.zeros(3), maxs=np.ones(3))
     assert np.array_equal(box.lengths, np.ones(3))
     assert np.array_equal(box.mins, np.zeros(3))
     assert np.array_equal(box.maxs, np.ones(3))
예제 #28
0
def build_alkylammonium_mxene(n_compounds,
                              composition,
                              periods,
                              chain_length=12,
                              displacement=1.1):
    ti3c2 = build_structure(periods=periods,
                            composition=composition,
                            displacement=displacement,
                            lateral_shift=True,
                            atomtype=True)

    n_carbons = 'C' * chain_length
    aa = mb.load(f'{n_carbons}[N](C)(C)C', smiles=True)

    # Rename some carbons
    # CE = end carbon
    # CM = middle carbon
    # CB = branch carbon

    for idx, particle in enumerate(aa.particles()):
        if idx == 0:
            particle.name = 'C_E'
        if idx == chain_length / 2:
            particle.name = 'C_M'
        # TODO: Find way to get branch carbon index without
        # hardcoding
        if particle.name == 'N':
            n_index = idx
        try:
            if idx == n_index + 1:
                particle.name = 'C_B1'
            if idx == n_index + 2:
                particle.name = 'C_B2'
        except:
            continue

    aa.name = 'alkylam'

    lopes = get_ff('lopes')

    region1 = mb.Box(
        mins=[0, 0, (ti3c2.box[2] / 10 - 2 * displacement) / 2 + 0.15],
        maxs=[
            ti3c2.box[0] / 10, ti3c2.box[1] / 10,
            (ti3c2.box[2] / 10 - 2 * displacement) / 2 + displacement
        ])
    region2 = mb.Box(mins=[
        0, 0, (ti3c2.box[2] / 10 - 2 * displacement) + displacement + 0.15
    ],
                     maxs=[
                         ti3c2.box[0] / 10, ti3c2.box[1] / 10,
                         (ti3c2.box[2] / 10 - 2 * displacement) + 2 +
                         displacement
                     ])

    aa_1 = mb.fill_box(compound=aa,
                       n_compounds=n_compounds,
                       box=region1,
                       fix_orientation=True)

    aa_2 = mb.fill_box(compound=aa,
                       n_compounds=n_compounds,
                       box=region2,
                       fix_orientation=True)

    aa1PM = lopes.apply(aa_1,
                        residues=['alkylam'],
                        assert_dihedral_params=False)
    aa2PM = lopes.apply(aa_2,
                        residues=['alkylam'],
                        assert_dihedral_params=False)

    system = aa1PM + aa2PM + ti3c2
    system = _apply_nbfixes(system)
    system = collapse_atomtypes(system)
    change_charge(system, new_charge=0)
    system.box = ti3c2.box
    for atom in system.atoms:
        if atom.name == 'C_E':
            atom.name = 'CE'
        elif atom.name == 'C_M':
            atom.name = 'CM'
        elif atom.name == 'C_B1':
            atom.name = 'CB1'
        elif atom.name == 'C_B2':
            atom.name = 'CB2'

    system.save('ti3c2.gro', combine='all', overwrite=True)
    system.save('ti3c2.top', combine='all', overwrite=True)
    write_lammpsdata(system, 'data.mxene')
예제 #29
0
파일: test_box.py 프로젝트: whitehml/mbuild
 def test_dtype(self):
     box = mb.Box(mins=np.zeros(3), maxs=np.ones(3))
     assert box.lengths.dtype == np.float64
     assert box.mins.dtype == np.float64
     assert box.maxs.dtype == np.float64
def test_box_to_lattfile():
    _box_to_lattfile(mb.Box([4, 4, 4]), 'lat.lat')