Exemple #1
0
    def benzene_from_parts(self):
        ch = mb.load(get_fn('ch.mol2'))
        ch.name = 'CH'
        mb.translate(ch, -ch[0].pos)       
        ch.add(mb.Port(anchor=ch[0], separation=0.07), 'a')
        mb.rotate_around_z(ch['a'], 120.0 * (np.pi/180.0))

        ch.add(mb.Port(anchor=ch[0], separation=0.07), 'b')
        mb.rotate_around_z(ch['b'], -120.0 * (np.pi/180.0))
        ch_copy = mb.clone(ch)

        benzene = mb.Compound(name='Benzene')
        benzene.add(ch)
        current = ch

        for _ in range(5):
            ch_new = mb.clone(ch_copy)
            mb.force_overlap(move_this=ch_new,
                             from_positions=ch_new['a'],
                             to_positions=current['b'])
            current = ch_new
            benzene.add(ch_new)

        carbons = [p for p in benzene.particles_by_name('C')]
        benzene.add_bond((carbons[0],carbons[-1]))

        return benzene
Exemple #2
0
    def apply(self, compound, orientation='', compound_port=''):
        """Arrange copies of a Compound as specified by the Pattern.

        Parameters
        ----------
        compound
        orientation

        Returns
        -------

        """
        compounds = list()
        if self.orientations.get(orientation):
            for port in self.orientations[orientation]:
                new_compound = clone(compound)
                new_port = new_compound.labels[compound_port]
                equivalence_transform(new_compound, new_port['up'], port['up'])

                compounds.append(new_compound)
        else:
            for point in self.points:
                new_compound = clone(compound)
                translate(new_compound, point)

                compounds.append(new_compound)
        return compounds
Exemple #3
0
    def apply_to_compound(self, guest, guest_port_name='down', host=None,
                          backfill=None, backfill_port_name='up'):
        """Attach copies of a guest Compound to Ports on a host Compound.

        Parameters
        ----------
        guest
        guest_port_name
        host
        backfill
        backfill_port_name

        Returns
        -------

        """
        n_ports = len(host.available_ports())
        assert n_ports >= self.points.shape[0], "Not enough ports for pattern."

        assert_port_exists(guest_port_name, guest)
        box = host.boundingbox
        pattern = self.points * box.lengths + box.mins

        port_positions = np.empty(shape=(n_ports, 3))
        port_list = list()
        for port_idx, port in enumerate(host.available_ports()):
            port_positions[port_idx, :] = port['up']['middle'].pos
            port_list.append(port)

        used_ports = set()  # Keep track of used ports for backfilling.
        guests = []
        for point in pattern:
            closest_point_idx = np.argmin(host.min_periodic_distance(point, port_positions))
            closest_port = port_list[closest_point_idx]
            used_ports.add(closest_port)

            # Attach the guest to the closest port.
            new_guest = clone(guest)
            equivalence_transform(new_guest, new_guest.labels[guest_port_name], closest_port)
            guests.append(new_guest)

            # Move the port as far away as possible (simpler than removing it).
            # There may well be a more elegant/efficient way of doing this.
            port_positions[closest_point_idx, :] = np.array([np.inf, np.inf, np.inf])

        backfills = []
        if backfill:
            assert_port_exists(backfill_port_name, backfill)
            # Attach the backfilling Compound to unused ports.
            for port in port_list:
                if port not in used_ports:
                    new_backfill = clone(backfill)
                    # Might make sense to have a backfill_port_name option...
                    equivalence_transform(
                        new_backfill, new_backfill.labels[backfill_port_name], port)
                    backfills.append(new_backfill)
        return guests, backfills
Exemple #4
0
    def test_rigid_with_subcompounds5(self, rigid_benzene):
        rigid_benzene2 = mb.clone(rigid_benzene)
        double = mb.Compound(subcompounds=[rigid_benzene, rigid_benzene2])
        double2 = mb.clone(double)
        compound = mb.Compound(subcompounds=[double, double2])

        assert compound.max_rigid_id is 3
        assert len(list(compound.rigid_particles())) == 48
        for rigid_id in range(4):
            assert len(list(compound.rigid_particles(rigid_id=rigid_id))) == 12
Exemple #5
0
    def __init__(self, proto, port_labels=("up", "down"), n=2):
        if n < 1:
            raise Exception('n must be 1 or more')
        super(Polymer, self).__init__()

        for label in port_labels:
            assert_port_exists(label, proto)

        last_part = None
        for _ in range(n):
            this_part = clone(proto)
            self.add(this_part, 'monomer[$]')
            if last_part is None:
                first_part = this_part
            else:
                # Transform this part, such that it's bottom port is rotated
                # and translated to the last part's top port.


                equivalence_transform(this_part, this_part.labels[port_labels[1]],
                                      last_part.labels[port_labels[0]])
            last_part = this_part

        # Hoist the last part's top port to be the top port of the polymer.
        self.add(last_part.labels[port_labels[0]], port_labels[0], containment=False)

        # Hoist the first part's bottom port to be the bottom port of the polymer.
        self.add(first_part.labels[port_labels[1]], port_labels[1], containment=False)
Exemple #6
0
    def test_bond_graph(self, ch3):
        compound = mb.Compound()
        compound.add(ch3)
        assert compound.n_bonds == 3
        assert all(compound.bond_graph.has_node(particle)
                   for particle in ch3.particles())

        ch3_nobonds = mb.clone(ch3)
        for bond in ch3_nobonds.bonds():
            ch3_nobonds.remove_bond(bond)
        compound.add(ch3_nobonds)
        assert compound.n_bonds == 3
        assert not any(compound.bond_graph.has_node(particle)
                       for particle in ch3_nobonds.particles())

        carbons = list(compound.particles_by_name('C'))
        compound.add_bond((carbons[0], carbons[1]))
        assert compound.n_bonds == 4
        assert all(compound.bond_graph.has_node(particle)
                   for particle in carbons)
        assert any(compound.bond_graph.has_node(particle)
                   for particle in ch3_nobonds.particles())

        compound.remove_bond((carbons[0], carbons[1]))
        assert not any(compound.bond_graph.has_node(particle)
                       for particle in ch3_nobonds.particles())
 def test_different_translate_tos_not_origin(self, methane):
     shifted = mb.clone(methane)
     np.random.seed(0)
     point = np.random.rand(3)
     shifted.translate_to(point)
     x = mb.coordinate_transform._translate_to(methane.xyz, point)
     assert np.array_equal(shifted.xyz, x)
Exemple #8
0
    def test_create_semi_rigid_bodies_hierarchy(self, benzene_from_parts):
        n_benzenes = 10
        filled = mb.fill_box(benzene_from_parts,
                             n_compounds=n_benzenes,
                             box=[0, 0, 0, 4, 4, 4])
        filled.name = 'Benzene box'
        filled2 = mb.clone(filled)
        compound = mb.Compound(subcompounds=[filled, filled2])

        compound.label_rigid_bodies(discrete_bodies='Benzene box')
        assert compound.max_rigid_id == 1
        assert filled.max_rigid_id == 0
        assert filled2.max_rigid_id == 1
        assert len(list(compound.rigid_particles())) == n_benzenes * 2 * 12

        compound.unlabel_rigid_bodies()
        compound.label_rigid_bodies(discrete_bodies='Benzene', rigid_particles='C')
        assert compound.max_rigid_id == (n_benzenes*2) - 1
        assert filled.max_rigid_id == n_benzenes - 1
        assert filled2.max_rigid_id == (n_benzenes*2) - 1
        assert len(list(compound.rigid_particles())) == n_benzenes * 2 * 6
        assert len(list(filled.rigid_particles())) == n_benzenes * 6
        assert len(list(filled2.rigid_particles())) == n_benzenes * 6

        compound.unlabel_rigid_bodies()
        compound.label_rigid_bodies(discrete_bodies='CH')
        assert compound.max_rigid_id == (n_benzenes*2*6) - 1
        assert filled.max_rigid_id == (n_benzenes*6) - 1
        assert filled2.max_rigid_id == (n_benzenes*2*6) - 1
        assert len(list(compound.rigid_particles())) == n_benzenes * 2 * 12
        assert len(list(filled.rigid_particles())) == n_benzenes * 12
        assert len(list(filled2.rigid_particles())) == n_benzenes * 12
Exemple #9
0
    def test_resnames_mdtraj(self, h2o, ethane):
        system = mb.Compound([h2o, mb.clone(h2o), ethane])
        traj = system.to_trajectory(residues=['Ethane', 'H2O'])
        residues = list(traj.top.residues)
        assert traj.n_residues == 3
        assert residues[0].name == 'H2O'
        assert residues[1].name == 'H2O'
        assert residues[2].name == 'Ethane'

        traj = system.to_trajectory(residues='Ethane')
        residues = list(traj.top.residues)
        assert traj.n_residues == 2
        assert residues[0].name == 'RES'
        assert residues[1].name == 'Ethane'

        traj = system.to_trajectory(residues=['Ethane'])
        residues = list(traj.top.residues)
        assert traj.n_residues == 2
        assert residues[0].name == 'RES'
        assert residues[1].name == 'Ethane'

        traj = system.to_trajectory()
        residues = list(traj.top.residues)
        assert traj.n_residues == 1
        assert residues[0].name == 'RES'
Exemple #10
0
    def test_resnames_parmed(self, h2o, ethane):
        system = mb.Compound([h2o, mb.clone(h2o), ethane])
        struct = system.to_parmed(residues=['Ethane', 'H2O'])
        assert len(struct.residues) == 3
        assert struct.residues[0].name == 'H2O'
        assert struct.residues[1].name == 'H2O'
        assert struct.residues[2].name == 'Ethane'
        assert sum(len(res.atoms) for res in struct.residues) == len(struct.atoms)

        struct = system.to_parmed(residues=['Ethane', 'H2O'])
        assert len(struct.residues) == 3
        assert struct.residues[0].name == 'H2O'
        assert struct.residues[1].name == 'H2O'
        assert struct.residues[2].name == 'Ethane'
        assert sum(len(res.atoms) for res in struct.residues) == len(struct.atoms)

        struct = system.to_parmed(residues='Ethane')
        assert len(struct.residues) == 2
        assert struct.residues[0].name == 'RES'
        assert struct.residues[1].name == 'Ethane'
        assert sum(len(res.atoms) for res in struct.residues) == len(struct.atoms)

        struct = system.to_parmed()
        assert len(struct.residues) == 1
        assert struct.residues[0].name == 'RES'
        assert sum(len(res.atoms) for res in struct.residues) == len(struct.atoms)
Exemple #11
0
 def _connect_and_reconnect(chf, bond_vector):
     first = mb.clone(chf)
     second = mb.clone(chf)
     first.add(mb.Port(anchor=first[0], orientation=bond_vector,
         separation=0.075), label='up')
     second.add(mb.Port(anchor=second[0], orientation=-bond_vector,
         separation=0.075), label='down')
     c2h2f2 = mb.Compound(subcompounds=(first, second))
     mb.force_overlap(first, first['up'], second['down'])
     fccf_dihedral_init = calc_dihedral(first[2].pos, first[0].pos,
         second[0].pos, second[2].pos)
     c2h2f2.remove_bond((first[0], second[0]))
     mb.force_overlap(first, first['port[0]'], second['port[0]'])
     fccf_dihedral_final = calc_dihedral(first[2].pos, first[0].pos,
         second[0].pos, second[2].pos)
     return fccf_dihedral_init, fccf_dihedral_final
Exemple #12
0
def solvate(solute, solvent, n_solvent, box, overlap=0.2, seed=12345):
    """Solvate a compound in a box of solvent using packmol.

    Parameters
    ----------
    solute : mb.Compound
    solvent : mb.Compound
    n_solvent : int
    box : mb.Box
    overlap : float

    Returns
    -------
    solvated : mb.Compound

    """
    if not PACKMOL:
        raise IOError("Packmol not found")

    box = _validate_box(box)
    if not isinstance(solvent, (list, set)):
        solvent = [solvent]
    if not isinstance(n_solvent, (list, set)):
        n_solvent = [n_solvent]

    # In angstroms for packmol.
    box_mins = box.mins * 10
    box_maxs = box.maxs * 10
    overlap *= 10
    center_solute = (box_maxs + box_mins) / 2

    # Build the input file for each compound and call packmol.
    solvated_pdb = tempfile.mkstemp(suffix='.pdb')[1]
    solute_pdb = tempfile.mkstemp(suffix='.pdb')[1]
    solute.save(solute_pdb, overwrite=True)
    input_text = (PACKMOL_HEADER.format(overlap, solvated_pdb, seed) +
                  PACKMOL_SOLUTE.format(solute_pdb, *center_solute))

    for solv, m_solvent in zip(solvent, n_solvent):
        m_solvent = int(m_solvent)
        solvent_pdb = tempfile.mkstemp(suffix='.pdb')[1]
        solv.save(solvent_pdb, overwrite=True)
        input_text += PACKMOL_BOX.format(solvent_pdb, m_solvent,
                           box_mins[0], box_mins[1], box_mins[2],
                           box_maxs[0], box_maxs[1], box_maxs[2])

    proc = Popen(PACKMOL, stdin=PIPE, stdout=PIPE, stderr=PIPE, universal_newlines=True)
    out, err = proc.communicate(input=input_text)
    if err:
        _packmol_error(out, err)

    # Create the topology and update the coordinates.
    solvated = Compound()
    solvated.add(solute)
    for solv, m_solvent in zip(solvent, n_solvent):
        for _ in range(m_solvent):
            solvated.add(clone(solv))
    solvated.update_coordinates(solvated_pdb)
    return solvated
Exemple #13
0
 def test_remove_bond_add_ports(self, hydrogen):
     h_clone = mb.clone(hydrogen)
     h2 = mb.Compound(subcompounds=(hydrogen, h_clone))
     mb.force_overlap(h_clone, h_clone['up'], hydrogen['up'])
     h2.remove_bond((h2[0], h2[1]))
     assert len(h2.all_ports()) == 2
     assert len(hydrogen.all_ports()) == 1
     assert len(h_clone.all_ports()) == 1
Exemple #14
0
def fill_box(compound, n_compounds, box, overlap=0.2, seed=12345):
    """Fill a box with a compound using packmol.

    Parameters
    ----------
    compound : mb.Compound or list of mb.Compound
    n_compounds : int or list of int
    box : mb.Box
    overlap : float

    Returns
    -------
    filled : mb.Compound

    """
    if not PACKMOL:
        msg = "Packmol not found."
        if sys.platform.startswith("win"):
            msg = (msg + " If packmol is already installed, make sure that the "
                         "packmol.exe is on the path.")
        raise IOError(msg)

    box = _validate_box(box)
    if not isinstance(compound, (list, set)):
        compound = [compound]
    if not isinstance(n_compounds, (list, set)):
        n_compounds = [n_compounds]

    # In angstroms for packmol.
    box_mins = box.mins * 10
    box_maxs = box.maxs * 10
    overlap *= 10

    # Build the input file for each compound and call packmol.
    filled_pdb = tempfile.mkstemp(suffix='.pdb')[1]
    input_text = PACKMOL_HEADER.format(overlap, filled_pdb, seed)

    for comp, m_compounds in zip(compound, n_compounds):
        m_compounds = int(m_compounds)
        compound_pdb = tempfile.mkstemp(suffix='.pdb')[1]
        comp.save(compound_pdb, overwrite=True)
        input_text += PACKMOL_BOX.format(compound_pdb, m_compounds,
                           box_mins[0], box_mins[1], box_mins[2],
                           box_maxs[0], box_maxs[1], box_maxs[2])

    proc = Popen(PACKMOL, stdin=PIPE, stdout=PIPE, stderr=PIPE, universal_newlines=True)
    out, err = proc.communicate(input=input_text)
    if err:
        _packmol_error(out, err)

    # Create the topology and update the coordinates.
    filled = Compound()
    for comp, m_compounds in zip(compound, n_compounds):
        for _ in range(m_compounds):
            filled.add(clone(comp))
    filled.update_coordinates(filled_pdb)
    return filled
Exemple #15
0
            def __init__(self):
                super(Hexane, self).__init__()

                self.add(propyl, 'propyl1')
                self.add(mb.clone(propyl), 'propyl2')

                mb.force_overlap(self['propyl1'],
                                 self['propyl1']['down'],
                                 self['propyl2']['down'])
Exemple #16
0
    def test_rigid_with_subcompounds2(self, rigid_benzene):
        rigid_benzene2 = mb.clone(rigid_benzene)
        compound = mb.Compound(subcompounds=[rigid_benzene, rigid_benzene2])

        assert compound.max_rigid_id is 1
        assert rigid_benzene.max_rigid_id is 0
        assert rigid_benzene2.max_rigid_id is 1
        assert len(list(compound.rigid_particles())) == 24
        assert len(list(compound.rigid_particles(rigid_id=0))) == 12
        assert len(list(compound.rigid_particles(rigid_id=1))) == 12
Exemple #17
0
 def __init__(self):
     super(MonoLJ, self).__init__()
     lj_proto = mb.Particle(name='LJ', pos=[0, 0, 0])
     
     pattern = mb.Grid3DPattern(5, 5, 5)
     pattern.scale(5)
     
     for pos in pattern:
         lj_particle = clone(lj_proto)
         lj_particle.translate(pos)
         self.add(lj_particle)
Exemple #18
0
    def test_build_from_single_particle(self):
        compound = mb.Compound()
        compound.rigid_id = 0
        atom = mb.Compound(name='atom')
        atom.rigid_id = 0
        atom2 = mb.clone(atom)
        compound.add([atom, atom2], reset_rigid_ids=False)

        assert compound.contains_rigid == True
        assert compound.rigid_id is None
        assert compound.max_rigid_id is 0
        assert len(list(compound.rigid_particles())) == 2
Exemple #19
0
def solvate(solute, solvent, n_solvent, box, overlap=0.2, seed=12345):
    """Solvate a compound in a box of solvent using packmol.

    Parameters
    ----------
    solute : mb.Compound
    solvent : mb.Compound
    n_solvent : int
    box : mb.Box
    overlap : float

    Returns
    -------
    solvated : mb.Compound

    """
    if not PACKMOL:
        raise IOError("Packmol not found")

    if isinstance(box, (list, tuple)):
        box = Box(lengths=box)

    n_solvent = int(n_solvent)

    solute_pdb = tempfile.mkstemp(suffix='.pdb')[1]
    solute.save(solute_pdb, overwrite=True)
    solvent_pdb = tempfile.mkstemp(suffix='.pdb')[1]
    solvent.save(solvent_pdb, overwrite=True)
    solvated_pdb = tempfile.mkstemp(suffix='.pdb')[1]

    # In angstroms for packmol.
    box_lengths = box.lengths * 10
    overlap *= 10
    # center_solute = (-solute.center) * 10
    center_solute = box_lengths/2

    # Build the input file and call packmol.
    input_text = (PACKMOL_HEADER.format(overlap, solvated_pdb, seed) +
                  PACKMOL_SOLUTE.format(solute_pdb, *center_solute) +
                  PACKMOL_BOX.format(solvent_pdb, n_solvent, *box_lengths))

    proc = Popen(PACKMOL, stdin=PIPE, stdout=PIPE, stderr=PIPE, universal_newlines=True)
    out, err = proc.communicate(input=input_text)
    if err:
        _packmol_error(out, err)

    # Create the topology and update the coordinates.
    solvated = Compound()
    solvated.add(solute)
    for _ in range(n_solvent):
        solvated.add(clone(solvent))
    solvated.update_coordinates(solvated_pdb)
    return solvated
Exemple #20
0
    def test_chainnames_mdtraj(self, h2o, ethane):
        system = mb.Compound([h2o, mb.clone(h2o), ethane])
        traj = system.to_trajectory(chains=['Ethane', 'H2O'])
        assert traj.n_chains == 3

        traj = system.to_trajectory(chains='Ethane')
        assert traj.n_chains == 2

        traj = system.to_trajectory(chains=['Ethane'])
        assert traj.n_chains == 2

        traj = system.to_trajectory()
        assert traj.n_chains == 1
Exemple #21
0
    def test_create_semi_rigid_bodies_filled_no_increment(self, benzene_from_parts):
        n_benzenes = 10
        filled = mb.fill_box(benzene_from_parts,
                             n_compounds=n_benzenes,
                             box=[0, 0, 0, 4, 4, 4])
        filled.label_rigid_bodies(discrete_bodies='Benzene', rigid_particles='C')
        filled2 = mb.clone(filled)
        filled.add(filled2, reset_rigid_ids=False)

        assert filled.max_rigid_id == n_benzenes - 1
        assert len(list(filled.rigid_particles())) == n_benzenes * 2 * 6
        for rigid_id in range(n_benzenes):
            assert len(list(filled.rigid_particles(rigid_id=rigid_id))) == 12
Exemple #22
0
    def test_rigid_from_parts2(self, rigid_ch):
        rigid_ch_copy = mb.clone(rigid_ch)
        benzene = mb.Compound()
        benzene.add(rigid_ch_copy, reset_rigid_ids=False)
        current = rigid_ch_copy

        for _ in range(5):
            ch_new = mb.clone(rigid_ch)
            mb.force_overlap(move_this=ch_new,
                             from_positions=ch_new['a'],
                             to_positions=current['b'])
            current = ch_new
            benzene.add(ch_new, reset_rigid_ids=False)

        carbons = [p for p in benzene.particles_by_name('C')]
        benzene.add_bond((carbons[0],carbons[-1]))

        assert benzene.contains_rigid is True
        assert benzene.rigid_id is None
        assert benzene.max_rigid_id is 0
        assert benzene.children[0].contains_rigid == True
        assert benzene.children[0].rigid_id is None
        assert len(list(benzene.rigid_particles(rigid_id=0))) == 12
Exemple #23
0
def fill_box(compound, n_compounds, box, overlap=0.2, seed=12345):
    """Fill a box with a compound using packmol.

    Parameters
    ----------
    compound : mb.Compound
    n_compounds : int
    box : mb.Box
    overlap : float

    Returns
    -------
    filled : mb.Compound

    """
    if not PACKMOL:
        msg = "Packmol not found."
        if sys.platform.startswith("win"):
            msg = (msg + " If packmol is already installed, make sure that the "
                         "packmol.exe is on the path.")
        raise IOError(msg)

    if isinstance(box, (list, tuple)):
        box = Box(lengths=box)

    n_compounds = int(n_compounds)
    compound_pdb = tempfile.mkstemp(suffix='.pdb')[1]
    compound.save(compound_pdb, overwrite=True)
    filled_pdb = tempfile.mkstemp(suffix='.pdb')[1]

    # In angstroms for packmol.
    box_lengths = box.lengths * 10
    overlap *= 10

    # Build the input file and call packmol.
    input_text = (PACKMOL_HEADER.format(overlap, filled_pdb, seed) +
                  PACKMOL_BOX.format(compound_pdb, n_compounds, *box_lengths))


    proc = Popen(PACKMOL, stdin=PIPE, stdout=PIPE, stderr=PIPE, universal_newlines=True)
    out, err = proc.communicate(input=input_text)
    if err:
        _packmol_error(out, err)

    # Create the topology and update the coordinates.
    filled = Compound()
    for _ in range(n_compounds):
        filled.add(clone(compound))
    filled.update_coordinates(filled_pdb)
    return filled
Exemple #24
0
    def __init__(self, anchor=None):
        super(Port, self).__init__(name='Port', port_particle=True)
        self.anchor = anchor

        up = Compound(name='subport', port_particle=True)
        up.add(Particle(name='G', pos=[0, 0, 0], port_particle=True), 'middle')
        up.add(Particle(name='G', pos=[0, 0.02, 0], port_particle=True), 'top')
        up.add(Particle(name='G', pos=[-0.02, -0.01, 0], port_particle=True), 'left')
        up.add(Particle(name='G', pos=[0.0, -0.02, 0.01], port_particle=True), 'right')

        down = clone(up)

        rotate_around_z(down, np.pi)

        self.add(up, 'up')
        self.add(down, 'down')
Exemple #25
0
    def test_rigid_with_subcompounds4(self, benzene):
        benzene.label_rigid_bodies(rigid_particles='C')
        benzene2 = mb.clone(benzene)
        compound = mb.Compound(subcompounds=[benzene, benzene2])

        assert compound.contains_rigid is True
        assert compound.rigid_id is None
        assert compound.max_rigid_id is 1
        assert benzene.contains_rigid is True
        assert benzene.rigid_id is None
        assert benzene.max_rigid_id is 0
        assert benzene2.contains_rigid is True
        assert benzene2.rigid_id is None
        assert benzene2.max_rigid_id is 1
        assert len(list(compound.rigid_particles())) == 12
        assert len(list(compound.rigid_particles(rigid_id=0))) == 6
        assert len(list(compound.rigid_particles(rigid_id=1))) == 6
Exemple #26
0
    def test_increment_rigid_id(self, rigid_benzene):
        compound = mb.Compound()
        rigid_benzene2 = mb.clone(rigid_benzene)
        compound.add(rigid_benzene)
        compound.add(rigid_benzene2)

        assert rigid_benzene.contains_rigid is True
        assert rigid_benzene.rigid_id is None
        assert rigid_benzene.max_rigid_id is 0
        assert rigid_benzene2.contains_rigid is True
        assert rigid_benzene2.rigid_id is None
        assert rigid_benzene2.max_rigid_id is 1
        assert compound.contains_rigid is True
        assert compound.rigid_id is None
        assert compound.max_rigid_id is 1
        assert len(list(compound.rigid_particles(rigid_id=0))) == 12
        assert len(list(compound.rigid_particles(rigid_id=1))) == 12
Exemple #27
0
    def __init__(self):
        super(TnpBox, self).__init__()

        tnp_proto = Tnp(ball_radius=5, n_chains=5, chain_length=8)

        pattern = mb.Grid3DPattern(3, 3, 3)
        pattern.scale(100)

        rnd = random.Random()
        rnd.seed(1928)

        for pos in pattern:
            tnp = clone(tnp_proto)
            mb.rotate_around_x(tnp, rnd.uniform(0, 2 * pi))
            mb.rotate_around_y(tnp, rnd.uniform(0, 2 * pi))
            mb.rotate_around_z(tnp, rnd.uniform(0, 2 * pi))
            mb.translate(tnp, pos)
            self.add(tnp)
Exemple #28
0
    def test_update_coords_update_ports(self, ch2):
        distances = np.round([ch2.min_periodic_distance(port.pos, ch2[0].pos)
                              for port in ch2.referenced_ports()], 5)
        orientations = np.round([port.pos - port.anchor.pos
                                 for port in ch2.referenced_ports()], 5)

        ch2_clone = mb.clone(ch2)
        ch2_clone[0].pos += [1, 1, 1]
        ch2_clone.save('ch2-shift.pdb')

        ch2.update_coordinates('ch2-shift.pdb')
        updated_distances = np.round([ch2.min_periodic_distance(port.pos, ch2[0].pos)
                                      for port in ch2.referenced_ports()], 5)
        updated_orientations = np.round([port.pos - port.anchor.pos
                                         for port in ch2.referenced_ports()], 5)

        assert np.array_equal(distances, updated_distances)
        assert np.array_equal(orientations, updated_orientations)
Exemple #29
0
    def test_intermol_conversion2(self, ethane, h2o):
        # 2 distinct Ethane objects.
        compound = mb.Compound([ethane, mb.clone(ethane), h2o])

        molecule_types = [type(ethane), type(h2o)]
        intermol_system = compound.to_intermol(molecule_types=molecule_types)
        assert len(intermol_system.molecule_types) == 2
        assert 'Ethane' in intermol_system.molecule_types
        assert 'H2O' in intermol_system.molecule_types
        assert len(intermol_system.molecule_types['Ethane'].bonds) == 7
        assert len(intermol_system.molecule_types['H2O'].bonds) == 2

        assert len(intermol_system.molecule_types['Ethane'].molecules) == 2
        ethanes = list(intermol_system.molecule_types['Ethane'].molecules)
        assert len(ethanes[0].atoms) == len(ethanes[1].atoms) == 8

        assert len(intermol_system.molecule_types['H2O'].molecules) == 1
        h2os = list(intermol_system.molecule_types['H2O'].molecules)
        assert len(h2os[0].atoms) == 3
Exemple #30
0
    def test_increment_rigid_id_partial(self, benzene):
        compound = mb.Compound()
        benzene.label_rigid_bodies(rigid_particles='C')
        benzene2 = mb.clone(benzene)
        compound.add(benzene)
        compound.add(benzene2)

        assert benzene.contains_rigid is True
        assert benzene.rigid_id is None
        assert benzene.max_rigid_id is 0
        assert benzene2.contains_rigid is True
        assert benzene2.rigid_id is None
        assert benzene2.max_rigid_id is 1
        assert compound.contains_rigid is True
        assert compound.rigid_id is None
        assert compound.max_rigid_id is 1
        assert len(list(compound.rigid_particles())) == 12
        assert len(list(compound.rigid_particles(rigid_id=0))) == 6
        assert len(list(compound.rigid_particles(rigid_id=1))) == 6
Exemple #31
0
def run_md_main(molecule, functional, project_name, dire, temperature,
                box_length, number_of_molecules, simulation_time, CUTOFF,
                SCF_tolerence, basis_set, ensemble, timestep, thermostat):

    current_molecule = mb.clone(molecule)
    current_molecule = current_molecule.to_parmed()
    atom_list, mass_list, total_mass = info_molecule(current_molecule)
    unique_atom_list = remove_duplicate(atom_list)
    num_atoms = len(atom_list)
    num_unique_atoms = len(unique_atom_list)
    total_atoms = num_atoms * number_of_molecules
    string = "tail -{} {}-pos-1.xyz > {}.xyz".format(total_atoms,
                                                     project_name + "pre",
                                                     project_name)
    subprocess.call(string, shell=True)

    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'

    #we need to decide time_step
    if timestep == None:
        lightest = min(mass_list)

        if lightest < 1.5:
            time_step = 0.5
        elif (lightest >= 1.5) and (lightest < 40):
            time_step = 1
        if lightest >= 40:
            time_step = 1.5
    steps = round(simulation_time * 1000 / time_step)
    mySim = sim.SIM()

    mySim.GLOBAL.RUN_TYPE = "MD"
    mySim.GLOBAL.PROJECT = project_name
    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 = 2
    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 = steps
    mySim.MOTION.MD.TIMESTEP = time_step
    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-main-changeLog.out")
    mySim.write_errorLog()
    mySim.write_inputFile(fn='md-main.inp')
Exemple #32
0
def md_files(instance):
    molecules = instance.molecules
    functional = instance.functional
    box = instance.box
    cutoff = instance.cutoff
    scf_tolerance = instance.scf_tolerance
    basis_set = instance.basis_set
    basis_set_filename = instance.basis_set_filename
    potential_filename = instance.potential_filename
    fixed_list = instance.fixed_list
    periodicity = instance.periodicity
    simulation_time = instance.simulation_time
    time_step = instance.time_step
    ensemble = instance.ensemble
    project_name = instance.project_name
    temperature = instance.temperature
    pressure = instance.pressure
    n_molecules = instance.n_molecules
    thermostat = instance.thermostat
    traj_type = instance.traj_type
    traj_freq = instance.traj_freq
    seed = instance.seed
    input_filename = instance.input_filename
    output_filename = instance.output_filename

    filled_box = mb.packing.fill_box(compound=molecules,
                                     n_compounds=n_molecules,
                                     box=box)
    initial_coord_file = project_name + ".xyz"
    filled_box.save(initial_coord_file, overwrite='True')
    with open(initial_coord_file, 'r') as fin:
        data = fin.read().splitlines(True)
    with open(initial_coord_file, 'w') as fout:
        fout.writelines(data[2:])  #deleting first two lines
    print('MD initial structure saved as {}'.format(initial_coord_file))

    atom_list = []
    mass_list = []
    for i in range(len(molecules)):
        current_molecule = mb.clone(molecules[i])
        current_molecule_pmd = current_molecule.to_parmed()
        x, y = info_molecule(current_molecule_pmd)
        atom_list.extend(x)
        mass_list.extend(y)
    unique_atom_list = remove_duplicate(atom_list)
    num_atoms = len(atom_list)
    num_unique_atoms = len(unique_atom_list)
    unique_atom_list.sort()

    mySim = sim.SIM()
    #setting defaults

    n_steps = int(simulation_time / time_step)
    mySim.GLOBAL.RUN_TYPE = "MD"
    mySim.GLOBAL.PROJECT_NAME = project_name
    mySim.GLOBAL.PRINT_LEVEL = "LOW"
    mySim.GLOBAL.SEED = seed

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

    mySim.FORCE_EVAL.DFT.BASIS_SET_FILE_NAME = basis_set_filename
    mySim.FORCE_EVAL.DFT.POTENTIAL_FILE_NAME = potential_filename
    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-7
    mySim.FORCE_EVAL.DFT.QS.EXTRAPOLATION = 'ASPC'
    mySim.FORCE_EVAL.DFT.POISSON.PERIODIC = periodicity
    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 = 30
    mySim.FORCE_EVAL.DFT.SCF.EPS_SCF = scf_tolerance

    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 = 8

    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 == [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[
                unique_atom_list[i]]
        mySim.FORCE_EVAL.SUBSYS.KIND[i + 1].POTENTIAL = potential(
            unique_atom_list[i], functional)

    mySim.FORCE_EVAL.SUBSYS.CELL.ABC = '{a} {b} {c}'.format(
        a=10 * box.lengths[0], b=10 * box.lengths[1], c=10 * box.lengths[2])
    mySim.FORCE_EVAL.SUBSYS.CELL.ALPHA_BETA_GAMMA = '{a} {b} {c}'.format(
        a=box.angles[0], b=box.angles[1], c=box.angles[2])

    #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 = n_steps
    mySim.MOTION.MD.TIMESTEP = time_step

    if temperature_ensemble(ensemble):
        mySim.MOTION.MD.TEMPERATURE = temperature
        mySim.MOTION.MD.THERMOSTAT.TYPE = thermostat

        mySim.MOTION.MD.THERMOSTAT.REGION = "MASSIVE"
        mySim.MOTION.MD.THERMOSTAT.NOSE.LENGTH = 5
        mySim.MOTION.MD.THERMOSTAT.NOSE.YOSHIDA = 3
        mySim.MOTION.MD.THERMOSTAT.NOSE.TIMECON = 1000.0
        mySim.MOTION.MD.THERMOSTAT.NOSE.MTS = 2

    if pressure_ensemble(ensemble):

        mySim.MOTION.MD.BAROSTAT.PRESSURE = pressure
        if pressure == None:
            print('you need to define pressure')
    if fixed_list is not None:

        mySim.MOTION.CONSTRAINT.FIXED_ATOMS.LIST = fixed_list
        mySim.MOTION.MD.THERMOSTAT.REGION = "GLOBAL"

    if periodicity == 'NONE':
        mySim.FORCE_EVAL.DFT.POISSON.PERIODIC = 'NONE'
        mySim.FORCE_EVAL.DFT.POISSON.POISSON_SOLVER = 'WAVELET'
    if not is_cubic(box) and periodicity == 'NONE':
        print(
            'The box should be cubic for non-periodic calculations and the box must be around 15 times the size of the molecule'
        )

    mySim.MOTION.PRINT.STRESS.SECTION_PARAMETERS = 'OFF'
    mySim.MOTION.PRINT.TRAJECTORY.EACH.MD = traj_freq
    mySim.MOTION.PRINT.TRAJECTORY.FORMAT = traj_type
    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-changeLog.out")
    mySim.write_errorLog()
    mySim.write_inputFile(fn=input_filename)
    print('MD input file saved as {}'.format(input_filename))
Exemple #33
0
    def __init__(self, lipids, ref_atoms, n_lipids_x=10, n_lipids_y=10,
                 area_per_lipid=1.0, lipid_box=None, spacing_z=None,
                 solvent=None, solvent_per_lipid=None, n_solvent=None,
                 solvent_density=None, solvent_mass=None, tilt=0,
                 random_seed=12345, mirror=True):

        super(Bilayer, self).__init__()

        # Santitize inputs
        i = 0
        while i < len(lipids):
            if lipids[i][1] == 0:
                lipids.remove(i)
            else:
                i += 1

        if sum([lipid[1] for lipid in lipids]) != 1.0:
            raise ValueError('Lipid fractions do not add up to 1.')
        assert len(ref_atoms) == len(lipids)

        self.lipids = lipids
        self.ref_atoms = ref_atoms
        self._lipid_box = lipid_box

        # 2D Lipid locations
        self.n_lipids_x = n_lipids_x
        self.n_lipids_y = n_lipids_y
        self.apl = area_per_lipid
        self.n_lipids_per_layer = self.n_lipids_x * self.n_lipids_y
        self.pattern = mb.Grid2DPattern(n_lipids_x, n_lipids_y)
        self.pattern.scale(np.sqrt(self.apl * self.n_lipids_per_layer))

        # Z-orientation parameters
        self.tilt = tilt
        if spacing_z:
            self.spacing = spacing_z
        else:
            self.spacing = max([lipid[0].boundingbox.lengths[2]
                for lipid in self.lipids]) * np.cos(self.tilt)

        # Solvent parameters
        if solvent:
            self.solvent = solvent
            if solvent_per_lipid != None:
                self.n_solvent = (self.n_lipids_x *
                                  self.n_lipids_y *
                                  2 * solvent_per_lipid)
            elif n_solvent != None:
                self.n_solvent = n_solvent
            else:
                raise ValueError("Requires either n_solvent_per_lipid ",
                                    "or n_solvent arguments")

        # Other parameters
        self.random_seed = random_seed
        self.mirror = mirror

        # Initialize variables and containers for lipids and solvent
        self.lipid_components = mb.Compound()
        self.solvent_components = mb.Compound()
        self._number_of_each_lipid_per_layer = []

        # Assemble the lipid layers
        seed(self.random_seed)
        self.tilt_about = [random(), random(), 0]
        top_layer, top_lipid_labels = self.create_layer()
        self.lipid_components.add(top_layer)
        if self.mirror == True:
            bottom_layer, bottom_lipid_labels = self.create_layer(
                    lipid_indices=top_lipid_labels,
                    flip_orientation=True)
        else:
            bottom_layer, bottom_lipid_labels = self.create_layer(
                                                    flip_orientation=True)
        bottom_layer.translate([0, 0, 0])
        self.lipid_components.add(bottom_layer)
        self.lipid_components.translate_to([0, 0, 0])

        # Assemble solvent components
        solvent_top = self.solvate(solvent_mass, solvent_density)
        solvent_bot = mb.clone(solvent_top)
        solvent_top.translate_to(
            [0, 0, self.spacing + 0.5 * solvent_top.boundingbox.lengths[2]]
            )
        solvent_bot.translate_to(
            [0, 0, -self.spacing - 0.5 * solvent_top.boundingbox.lengths[2]]
            )
        self.solvent_components.add(solvent_top)
        self.solvent_components.add(solvent_bot)

        # Add all compounds
        self.add(self.lipid_components)
        self.add(self.solvent_components)
Exemple #34
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.

        Exceptions Raised
        -----------------
        ValueError : incorrect x,y, or z values.
        TypeError : incorrect type for basis vector

        Call Restrictions
        -----------------
        Called after constructor by user.

        """

        error_dict = {0: 'X', 1: 'Y', 2: 'Z'}

        # Make sure neither x, y, z input is None
        if None in [x, y, z]:
            raise ValueError('Attempt to replicate None times. '
                             'None is not an acceptable replication '
                             'amount, 1 is the default.')

        # Try to convert x, y, and z to int, raise a ValueError if fail
        try:
            x = int(x)
            y = int(y)
            z = int(z)
        except (ValueError, TypeError):
            raise ValueError('Cannot convert replication amounts into '
                             'integers. x= {}, y= {}, z= {} needs to '
                             'be an int.'.format(x, y, z))

        for replication_amount, index in zip([x, y, z], range(3)):
            if replication_amount < 1:
                raise ValueError(
                    'Incorrect populate value: {} : {} is < 1. '.format(
                        error_dict[index], replication_amount))

        if ((isinstance(compound_dict, dict)) or (compound_dict is None)):
            pass
        else:
            raise TypeError('Compound dictionary is not of type 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 mbuild.Compound.'.format(
                                        key_id, err_type))
        # set periodicity
        ret_lattice.periodicity = np.asarray([a * x, b * y, c * z],
                                             dtype=np.float64)
        warn('Periodicity of non-rectangular lattices are not valid with '
             'default boxes. Only rectangular lattices are valid '
             'at this time.')

        # 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.

        return ret_lattice
Exemple #35
0
from __future__ import division

import numpy as np

import mbuild as mb

from atools.patterns.random_hemisphere_pattern import RandomHemispherePattern


class TipPattern(RandomHemispherePattern):
    def __init__(self, chain_density, tip_radius, seed=12345):

        area = 2 * np.pi * tip_radius**2
        n = int(round(area * chain_density))

        super(TipPattern, self).__init__(n=n, seed=seed, scale=tip_radius)

if __name__ == "__main__":
    pattern = TipPattern(chain_density=2.0, tip_radius=2.0)

    lj_proto = mb.Compound(name='LJ')
    lj_box = mb.Compound()
    for pos in pattern:
        lj_particle = mb.clone(lj_proto)
        lj_particle.translate(pos)
        lj_box.add(lj_particle)
    lj_box.save('tip-pattern.xyz', overwrite=True)
Exemple #36
0
    def apply_to_compound(self,
                          guest,
                          guest_port_name='down',
                          host=None,
                          backfill=None,
                          backfill_port_name='up',
                          scale=True):
        """Attach copies of a guest Compound to Ports on a host Compound.

        Parameters
        ----------
        guest : mb.Compound
            The Compound prototype to be applied to the host Compound
        guest_port_name : str, optional, default='down'
            The name of the port located on `guest` to attach to the host
        host : mb.Compound, optional, default=None
            A Compound with available ports to add copies of `guest` to
        backfill : mb.Compound, optional, default=None
            A Compound to add to the remaining available ports on `host`
            after clones of `guest` have been added for each point in the
            pattern
        backfill_port_name : str, optional, default='up'
            The name of the port located on `backfill` to attach to the host
        scale : bool, optional, default=True
            Scale the points in the pattern to the lengths of the `host`'s
            `boundingbox` and shift them by the `boundingbox`'s mins

        Returns
        -------
        guests : list of mb.Compound
            List of inserted guest compounds on host compound
        backfills : list of mb.Compound
            List of inserted backfill compounds on host compound

        """

        n_ports = len(host.available_ports())
        assert n_ports >= self.points.shape[0], "Not enough ports for pattern."
        assert_port_exists(guest_port_name, guest)
        box = host.boundingbox
        if scale:
            self.scale(box.lengths)
            self.points += box.mins
        pattern = self.points
        port_positions = np.empty(shape=(n_ports, 3))
        port_list = list()
        for port_idx, port in enumerate(host.available_ports()):
            port_positions[port_idx, :] = port['up']['middle'].pos
            port_list.append(port)
        used_ports = set()  # Keep track of used ports for backfilling.
        guests = []
        for point in pattern:
            closest_point_idx = np.argmin(
                host.min_periodic_distance(point, port_positions))
            closest_port = port_list[closest_point_idx]
            used_ports.add(closest_port)

            # Attach the guest to the closest port.
            new_guest = clone(guest)
            force_overlap(new_guest, new_guest.labels[guest_port_name],
                          closest_port)
            guests.append(new_guest)

            # Move the port as far away as possible (simpler than removing it).
            # There may well be a more elegant/efficient way of doing this.
            port_positions[closest_point_idx, :] = np.array(
                [np.inf, np.inf, np.inf])
        backfills = []
        if backfill:
            assert_port_exists(backfill_port_name, backfill)
            # Attach the backfilling Compound to unused ports.
            for port in port_list:
                if port not in used_ports:
                    new_backfill = clone(backfill)
                    # Might make sense to have a backfill_port_name option...
                    force_overlap(new_backfill,
                                  new_backfill.labels[backfill_port_name],
                                  port)
                    backfills.append(new_backfill)
        return guests, backfills
    def test_spin_x_eq(self, sixpoints):
        compound2 = mb.clone(sixpoints)
        sixpoints.spin(np.pi * 1.23456789, np.asarray([1.0, 0.0, 0.0]))

        compound2.spin(np.pi * 1.23456789, around=np.asarray([1, 0, 0]))
        assert (np.allclose(compound2.xyz, sixpoints.xyz, atol=1e-16))
Exemple #38
0
def solvate(
    solute,
    solvent,
    n_solvent,
    box,
    overlap=0.2,
    seed=12345,
    sidemax=100.0,
    edge=0.2,
    fix_orientation=False,
    temp_file=None,
    update_port_locations=False,
):
    """Solvate a compound in a box of solvent using PACKMOL.

    Parameters
    ----------
    solute : mb.Compound
        Compound to be placed in a box and solvated.
    solvent : mb.Compound
        Compound to solvate the box.
    n_solvent : int
        Number of solvents to be put in box.
    box : mb.Box
        Box to be filled by compounds.
    overlap : float, units nm, default=0.2
        Minimum separation between atoms of different molecules.
    seed : int, default=12345
        Random seed to be passed to PACKMOL.
    sidemax : float, optional, default=100.0
        Needed to build an initial approximation of the molecule distribution in
        PACKMOL. All system coordinates must fit with in +/- sidemax, so
        increase sidemax accordingly to your final box size
    edge : float, units nm, default=0.2
        Buffer at the edge of the box to not place molecules. This is necessary
        in some systems because PACKMOL does not account for periodic boundary
        conditions in its optimization.
    fix_orientation : bool
        Specify if solvent should not be rotated when filling box,
        default=False.
    temp_file : str, default=None
        File name to write PACKMOL raw output to.
    update_port_locations : bool, default=False
        After packing, port locations can be updated, but since compounds can be
        rotated, port orientation may be incorrect.

    Returns
    -------
    solvated : mb.Compound
    """
    # check that the user has the PACKMOL binary on their PATH
    _check_packmol(PACKMOL)

    (box, min_tmp, max_tmp) = _validate_box(box)
    if not isinstance(solvent, (list, set)):
        solvent = [solvent]
    if not isinstance(n_solvent, (list, set)):
        n_solvent = [n_solvent]
    if not isinstance(fix_orientation, (list, set)):
        fix_orientation = [fix_orientation] * len(solvent)

    if len(solvent) != len(n_solvent):
        raise ValueError(
            "`n_solvent` and `n_solvent` must be of equal length.")

    # In angstroms for packmol.
    box_mins = np.asarray(min_tmp) * 10
    box_maxs = np.asarray(max_tmp) * 10
    overlap *= 10
    center_solute = (box_maxs + box_mins) / 2

    # Apply edge buffer
    box_maxs = np.subtract(box_maxs, edge * 10)
    box_mins = np.add(box_mins, edge * 10)
    # Build the input file for each compound and call packmol.
    solvated_xyz = _new_xyz_file()
    solute_xyz = _new_xyz_file()

    # generate list of temp files for the solvents
    solvent_xyz_list = list()
    try:
        solute.save(solute_xyz.name, overwrite=True)
        input_text = PACKMOL_HEADER.format(
            overlap, solvated_xyz.name, seed,
            sidemax * 10) + PACKMOL_SOLUTE.format(solute_xyz.name,
                                                  *center_solute.tolist())

        for (solv, m_solvent, rotate) in zip(solvent, n_solvent,
                                             fix_orientation):
            m_solvent = int(m_solvent)
            solvent_xyz = _new_xyz_file()
            solvent_xyz_list.append(solvent_xyz)

            solv.save(solvent_xyz.name, overwrite=True)
            input_text += PACKMOL_BOX.format(
                solvent_xyz.name,
                m_solvent,
                box_mins[0],
                box_mins[1],
                box_mins[2],
                box_maxs[0],
                box_maxs[1],
                box_maxs[2],
                PACKMOL_CONSTRAIN if rotate else "",
            )
        _run_packmol(input_text, solvated_xyz, temp_file)

        # Create the topology and update the coordinates.
        solvated = Compound()
        solvated.add(clone(solute))
        solvated = _create_topology(solvated, solvent, n_solvent)
        solvated.update_coordinates(
            solvated_xyz.name, update_port_locations=update_port_locations)

    finally:
        for file_handle in solvent_xyz_list:
            file_handle.close()
            os.unlink(file_handle.name)
        solvated_xyz.close()
        solute_xyz.close()
        os.unlink(solvated_xyz.name)
        os.unlink(solute_xyz.name)
    return solvated
    def __init__(self,
                 radius=2,
                 angle=90.0,
                 fluid=None,
                 density=None,
                 lattice=None,
                 lattice_compound=None,
                 x=None,
                 y=None):

        super(Droplet, self).__init__()

        if fluid is None:
            raise ValueError('Fluid droplet compounds must be specified')
        if density is None:
            raise ValueError('Fluid density must be specified (units kg/m^3)')

        if x:
            if x < radius * 4:
                raise ValueError(
                    'Dimension x of sheet must be at least radius * 4')
            elif x > 100:
                raise ValueError(
                    'Dimension x of sheet must be less than 100 nm')
        else:
            x = radius * 4

        if y:
            if y < radius * 4:
                raise ValueError(
                    'Dimension y of sheet must be at least radius * 4')
            elif y > 100:
                raise ValueError(
                    'Dimension y of sheet must be less than 100 nm')
        else:
            y = radius * 4

        # Default to graphene lattice
        if lattice is None:

            if lattice_compound is not None:
                raise ValueError(
                    'If Lattice is None, defaults to a Graphene surface. ' +
                    'In this case, do not specify lattice_compound.')

            lattice_compound = mbuild.Compound(name='C')
            lattice_spacing = [0.2456, 0.2456, 0.335]
            angles = [90.0, 90.0, 120.0]
            carbon_locations = [[0, 0, 0], [2 / 3, 1 / 3, 0]]
            basis = {lattice_compound.name: carbon_locations}
            lattice = mbuild.Lattice(lattice_spacing=lattice_spacing,
                                     angles=angles,
                                     lattice_points=basis)
            compound_dict = {lattice_compound.name: lattice_compound}

            factor = np.cos(np.pi / 6)  # fixes non-cubic lattice
            # Estimate the number of lattice repeat units
            replicate = [int(x / 0.2456), int(y / 0.2456) * (1 / factor)]

            lat = lattice.populate(compound_dict=compound_dict,
                                   x=replicate[0],
                                   y=replicate[1],
                                   z=3)

            for particle in lat.particles():
                if particle.xyz[0][0] < 0:
                    particle.xyz[0][0] += lat.periodicity[0]
            lat.periodicity[1] *= factor

        else:
            if lattice_compound is None:
                raise ValueError('Lattice compounds must be specified')

            if not np.all(lattice.angles == 90.0):
                raise ValueError(
                    'Currently, only cubic lattices are supported. ' +
                    'If using Graphene, do not pass in a Lattice.')

            compound_dict = {lattice_compound.name: lattice_compound}
            lat = lattice.populate(compound_dict=compound_dict,
                                   x=int(x / lattice.lattice_spacing[0]),
                                   y=int(y / lattice.lattice_spacing[1]),
                                   z=int(1.5 / lattice.lattice_spacing[2]))

        sheet = mbuild.clone(lat)
        self.surface_height = np.max(sheet.xyz, axis=0)[2]
        coords = list(sheet.periodicity)

        height = get_height(radius, angle)
        sphere_coords = [coords[0] / 2, coords[1] / 2, radius, radius]
        sphere = mbuild.fill_sphere(compound=fluid,
                                    sphere=sphere_coords,
                                    density=density)

        to_remove = []
        for child in sphere.children:
            for atom_coords in child.xyz:
                if height > radius:
                    if atom_coords[2] < height - radius:
                        to_remove += child
                        break
                else:
                    if atom_coords[2] < height:
                        to_remove += child
                        break

        sphere.remove(to_remove)

        sheet.name = 'LAT'
        sphere.name = 'FLD'
        sphere.xyz -= [0, 0, np.min(sphere.xyz, axis=0)[2]]
        sphere.xyz += [0, 0, self.surface_height + 0.3]

        self.add(sheet)
        self.add(sphere)
        self.periodicity[0] = sheet.periodicity[0]
        self.periodicity[1] = sheet.periodicity[1]
        self.periodicity[2] = radius * 5
Exemple #40
0
 def _add_backfill(self, backfill, backfill_port_name):
     for port in self['surface'].available_ports():
         backfill_clone = mb.clone(backfill)
         mb.force_overlap(backfill_clone,
                          backfill_clone[backfill_port_name], port)
         self.add(backfill_clone)
    def __init__(self, chain_length, internal_group, locations,
                 terminal_group):
        super(Alkylsilane, self).__init__()

        module = __import__('atools.lib.moieties.one_port.' + terminal_group)
        class_ = getattr(module.lib.moieties.one_port, terminal_group.title())
        tgroup = class_()

        hmodule = __import__('atools.lib.moieties.multiple_ports.' +
                             internal_group)
        hclass_ = getattr(hmodule.lib.moieties.multiple_ports,
                          internal_group.title())
        hgroup = hclass_()

        # Determine alkane segments
        if isinstance(locations, int):
            locations = [locations]
        locations.sort()

        silane = Silane()
        self.add(silane, 'silane')
        self.add(silane['down'], 'down', containment=False)

        if 0 in locations:
            '''
            self.add(hgroup, 'hgroup')
            mb.force_overlap(self['silane'], self['silane']['up'], 
                             self['hgroup']['down'])
            '''
            current_segment = silane
        else:
            first_length = locations[0]
            first_segment = Alkane(first_length,
                                   cap_front=False,
                                   cap_end=False)
            self.add(first_segment, 'bottom_chain')
            mb.force_overlap(self['silane'], self['silane']['up'],
                             self['bottom_chain']['down'])
            current_segment = first_segment

        c_remove = 0
        if internal_group in ['amide', 'hemiacetal']:
            c_remove += 1

        for i, loc in enumerate(locations[1:]):
            hgroup_clone = mb.clone(hgroup)
            self.add(hgroup_clone, 'hgroup{}'.format(i + 1))
            mb.force_overlap(self['hgroup{}'.format(i + 1)],
                             self['hgroup{}'.format(i + 1)]['down'],
                             current_segment['up'])
            current_segment = hgroup_clone
            length = loc - locations[i] - 1 - c_remove
            if length > 0:
                segment = Alkane(length, cap_front=False, cap_end=False)
                self.add(segment, 'internal_chain{}'.format(i + 1))
                current_segment = segment
                mb.force_overlap(
                    self['internal_chain{}'.format(i + 1)],
                    self['internal_chain{}'.format(i + 1)]['down'],
                    self['hgroup{}'.format(i + 1)]['up'])

        self.add(hgroup, 'hgroup')
        mb.force_overlap(self['hgroup'], self['hgroup']['down'],
                         current_segment['up'])

        last_length = chain_length - locations[-1] - 1 - c_remove
        if last_length:
            last_segment = Alkane(last_length, cap_front=False, cap_end=False)
            self.add(last_segment, 'top_chain')
            mb.force_overlap(self['top_chain'], self['top_chain']['down'],
                             self['hgroup']['up'])
        else:
            hydrogen = H()
            self.add(hydrogen, 'H-cap')
            mb.force_overlap(self['H-cap'], self['H-cap']['up'],
                             self['hgroup']['up'])

        self.add(tgroup, 'terminal_group')
        mb.force_overlap(self['terminal_group'],
                         self['terminal_group']['down'],
                         self['top_chain']['up'])
Exemple #42
0
def fill_region(compound, n_compounds, region, overlap=0.2,
                seed=12345, edge=0.2, fix_orientation=False, temp_file=None):
    """Fill a region of a box with a compound using packmol.

    Parameters
    ----------
    compound : mb.Compound or list of mb.Compound
        Compound or list of compounds to be put in region.
    n_compounds : int or list of int
        Number of compounds to be put in region.
    region : mb.Box or list of mb.Box
        Region to be filled by compounds.
    overlap : float, units nm, default=0.2
        Minimum separation between atoms of different molecules.
    seed : int, default=12345
        Random seed to be passed to PACKMOL.
    edge : float, units nm, default=0.2
        Buffer at the edge of the region to not place molecules. This is
        necessary in some systems because PACKMOL does not account for
        periodic boundary conditions in its optimization.
    fix_orientation : bool or list of bools
        Specify that compounds should not be rotated when filling the box,
        default=False.
    temp_file : str, default=None
        File name to write PACKMOL's raw output to.

    Returns
    -------
    filled : mb.Compound

    If using mulitple regions and compounds, the nth value in each list are used in order.
    For example, if the third compound will be put in the third region using the third value in n_compounds.
    """
    _check_packmol(PACKMOL)

    if not isinstance(compound, (list, set)):
        compound = [compound]
    if not isinstance(n_compounds, (list, set)):
        n_compounds = [n_compounds]
    if not isinstance(fix_orientation, (list, set)):
        fix_orientation = [fix_orientation]*len(compound)

    if compound is not None and n_compounds is not None:
        if len(compound) != len(n_compounds):
            msg = ("`compound` and `n_compounds` must be of equal length.")
            raise ValueError(msg)
    if compound is not None:
        if len(compound) != len(fix_orientation):
            msg = ("`compound`, `n_compounds`, and `fix_orientation` must be of equal length.")
            raise ValueError(msg)


    # See if region is a single region or list
    if isinstance(region, Box): # Cannot iterate over boxes
        region = [region]
    elif not any(isinstance(reg, (list, set, Box)) for reg in region):
        region = [region]
    region = [_validate_box(reg) for reg in region]

    # In angstroms for packmol.
    overlap *= 10

    # Build the input file and call packmol.
    filled_pdb = tempfile.mkstemp(suffix='.pdb')[1]
    input_text = PACKMOL_HEADER.format(overlap, filled_pdb, seed)

    for comp, m_compounds, reg, rotate in zip(compound, n_compounds, region, fix_orientation):
        m_compounds = int(m_compounds)
        compound_pdb = tempfile.mkstemp(suffix='.pdb')[1]
        comp.save(compound_pdb, overwrite=True)
        reg_mins = reg.mins * 10
        reg_maxs = reg.maxs * 10
        reg_maxs -= edge * 10 # Apply edge buffer
        input_text += PACKMOL_BOX.format(compound_pdb, m_compounds,
                                        reg_mins[0], reg_mins[1], reg_mins[2],
                                        reg_maxs[0], reg_maxs[1], reg_maxs[2],
                                        PACKMOL_CONSTRAIN if rotate else "")

    _run_packmol(input_text, filled_pdb, temp_file)

    # Create the topology and update the coordinates.
    filled = Compound()
    for comp, m_compounds in zip(compound, n_compounds):
        for _ in range(m_compounds):
            filled.add(clone(comp))
    filled.update_coordinates(filled_pdb)
    return filled
Exemple #43
0
 def test_init_with_subcompounds3(self, ethane, h2o):
     compound = mb.Compound([ethane, [h2o, mb.clone(h2o)]])
     assert compound.n_particles == 8 + 2 * 3
     assert compound.n_bonds == 7 + 2 * 2
Exemple #44
0
def fill_box(compound, n_compounds=None, box=None, density=None, overlap=0.2,
             seed=12345, edge=0.2, compound_ratio=None,
             aspect_ratio=None, fix_orientation=False, temp_file=None):
    """Fill a box with a compound using packmol.

    Two arguments of `n_compounds, box, and density` must be specified.

    If `n_compounds` and `box` are not None, the specified number of
    n_compounds will be inserted into a box of the specified size.

    If `n_compounds` and `density` are not None, the corresponding box
    size will be calculated internally. In this case, `n_compounds`
    must be an int and not a list of int.

    If `box` and `density` are not None, the corresponding number of
    compounds will be calculated internally.

    For the cases in which `box` is not specified but generated internally,
    the default behavior is to calculate a cubic box. Optionally,
    `aspect_ratio` can be passed to generate a non-cubic box.

    Parameters
    ----------
    compound : mb.Compound or list of mb.Compound
        Compound or list of compounds to be put in box.
    n_compounds : int or list of int
        Number of compounds to be put in box.
    box : mb.Box
        Box to be filled by compounds.
    density : float, units kg/m^3, default=None
        Target density for the system in macroscale units. If not None, one of
        `n_compounds` or `box`, but not both, must be specified.
    overlap : float, units nm, default=0.2
        Minimum separation between atoms of different molecules.
    seed : int, default=12345
        Random seed to be passed to PACKMOL.
    edge : float, units nm, default=0.2
        Buffer at the edge of the box to not place molecules. This is necessary
        in some systems because PACKMOL does not account for periodic boundary
        conditions in its optimization.
    compound_ratio : list, default=None
        Ratio of number of each compound to be put in box. Only used in the
        case of `density` and `box` having been specified, `n_compounds` not
        specified, and more than one `compound`.
    aspect_ratio : list of float
        If a non-cubic box is desired, the ratio of box lengths in the x, y,
        and z directions.
    fix_orientation : bool or list of bools
        Specify that compounds should not be rotated when filling the box,
        default=False.
    temp_file : str, default=None
        File name to write PACKMOL's raw output to.

    Returns
    -------
    filled : mb.Compound

    """
    _check_packmol(PACKMOL)

    arg_count = 3 - [n_compounds, box, density].count(None)
    if arg_count != 2:
        msg = ("Exactly 2 of `n_compounds`, `box`, and `density` "
            "must be specified. {} were given.".format(arg_count))
        raise ValueError(msg)

    if box is not None:
        box = _validate_box(box)
    if not isinstance(compound, (list, set)):
        compound = [compound]
    if n_compounds is not None and not isinstance(n_compounds, (list, set)):
        n_compounds = [n_compounds]
    if not isinstance(fix_orientation, (list, set)):
        fix_orientation = [fix_orientation]*len(compound)

    if compound is not None and n_compounds is not None:
        if len(compound) != len(n_compounds):
            msg = ("`compound` and `n_compounds` must be of equal length.")
            raise ValueError(msg)

    if compound is not None:
        if len(compound) != len(fix_orientation):
            msg = ("`compound`, `n_compounds`, and `fix_orientation` must be of equal length.")
            raise ValueError(msg)


    if density is not None:
        if box is None and n_compounds is not None:
            total_mass = np.sum([n*np.sum([a.mass for a in c.to_parmed().atoms])
                for c,n in zip(compound, n_compounds)])
            # Conversion from (amu/(kg/m^3))**(1/3) to nm
            L = (total_mass/density)**(1/3)*1.1841763
            if aspect_ratio is None:
                box = _validate_box(Box(3*[L]))
            else:
                L *= np.prod(aspect_ratio) ** (-1/3)
                box = _validate_box(Box([val*L for val in aspect_ratio]))
        if n_compounds is None and box is not None:
            if len(compound) == 1:
                compound_mass = np.sum([a.mass for a in compound[0].to_parmed().atoms])
                # Conversion from kg/m^3 / amu * nm^3 to dimensionless units
                n_compounds = [int(density/compound_mass*np.prod(box.lengths)*.60224)]
            else:
                if compound_ratio is None:
                    msg = ("Determing `n_compounds` from `density` and `box` "
                           "for systems with more than one compound type requires"
                           "`compound_ratio`")
                    raise ValueError(msg)
                if len(compound) != len(compound_ratio):
                    msg = ("Length of `compound_ratio` must equal length of "
                           "`compound`")
                    raise ValueError(msg)
                prototype_mass = 0
                for c, r in zip(compound, compound_ratio):
                    prototype_mass += r * np.sum([a.mass for a in c.to_parmed().atoms])
                # Conversion from kg/m^3 / amu * nm^3 to dimensionless units
                n_prototypes = int(density/prototype_mass*np.prod(box.lengths)*.60224)
                n_compounds = list()
                for c in compound_ratio:
                    n_compounds.append(int(n_prototypes * c))

    # In angstroms for packmol.
    box_mins = box.mins * 10
    box_maxs = box.maxs * 10
    overlap *= 10

    # Apply edge buffer
    box_maxs -= edge * 10

    # Build the input file for each compound and call packmol.
    filled_pdb = tempfile.mkstemp(suffix='.pdb')[1]
    input_text = PACKMOL_HEADER.format(overlap, filled_pdb, seed)

    for comp, m_compounds, rotate in zip(compound, n_compounds, fix_orientation):
        m_compounds = int(m_compounds)
        compound_pdb = tempfile.mkstemp(suffix='.pdb')[1]
        comp.save(compound_pdb, overwrite=True)
        input_text += PACKMOL_BOX.format(compound_pdb, m_compounds,
                           box_mins[0], box_mins[1], box_mins[2],
                           box_maxs[0], box_maxs[1], box_maxs[2],
                           PACKMOL_CONSTRAIN if rotate else "")

    _run_packmol(input_text, filled_pdb, temp_file)

    # Create the topology and update the coordinates.
    filled = Compound()
    for comp, m_compounds in zip(compound, n_compounds):
        for _ in range(m_compounds):
            filled.add(clone(comp))
    filled.update_coordinates(filled_pdb)
    filled.periodicity = np.asarray(box.lengths, dtype=np.float32)
    return filled
Exemple #45
0
                             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:
        graphene.add(mb.clone(child))

water_pmd = spce.apply(water, residues='SOL')
ions_pmd = jc.apply(ions, residues=['Na', 'Cl'])
pore_pmd = c_ff.apply(graphene)

# #### Now we will combine the two paramterezed ParmEd structures and save them as `gro` and `top` files

# In[ ]:

system = water_pmd + pore_pmd + ions_pmd
system.box[:3] = box.maxs * 10.0
Exemple #46
0
 def test_add_label_exists(self, ethane, h2o):
     ethane.add(h2o, label='water')
     with pytest.raises(MBuildError):
         ethane.add(mb.clone(h2o), label='water')
Exemple #47
0
    def _visualize_py3dmol(self,
                           show_ports=False,
                           color_scheme={},
                           show_atomistic=False,
                           scale=1.0):
        """
        Visualize the Compound using py3Dmol.
        Allows for visualization of a Compound within a Jupyter Notebook.
        Modified to show atomistic elements (translucent) with larger CG beads.

        Parameters
        ----------
        show_ports : bool, optional, default=False
            Visualize Ports in addition to Particles
        color_scheme : dict, optional
            Specify coloring for non-elemental particles
            keys are strings of the particle names
            values are strings of the colors
            i.e. {'_CGBEAD': 'blue'}
        show_atomistic : show the atomistic structure stored in CG_Compound.atomistic

        Returns
        ------
        view : py3Dmol.view
        """
        py3Dmol = import_("py3Dmol")

        atom_names = []

        if self.atomistic is not None and show_atomistic:
            atomistic = mb.clone(self.atomistic)
            for particle in atomistic.particles():
                if not particle.name:
                    particle.name = "UNK"
                else:
                    if (particle.name != 'Compound') and (particle.name !=
                                                          'CG_Compound'):
                        atom_names.append(particle.name)

        coarse = mb.clone(self)
        modified_color_scheme = {}
        for name, color in color_scheme.items():
            # Py3dmol does some element string conversions,
            # first character is as-is, rest of the characters are lowercase
            new_name = name[0] + name[1:].lower()
            modified_color_scheme[new_name] = color
            modified_color_scheme[name] = color

        cg_names = []
        for particle in coarse.particles():
            if not particle.name:
                particle.name = "UNK"
            else:
                if (particle.name != 'Compound') and (particle.name !=
                                                      'CG_Compound'):
                    cg_names.append(particle.name)

        tmp_dir = tempfile.mkdtemp()

        view = py3Dmol.view()

        if atom_names:
            atomistic.save(
                os.path.join(tmp_dir, "atomistic_tmp.mol2"),
                show_ports=show_ports,
                overwrite=True,
            )

            # atomistic
            with open(os.path.join(tmp_dir, "atomistic_tmp.mol2"), "r") as f:
                view.addModel(f.read(), "mol2", keepH=True)

            if cg_names:
                opacity = 0.6
            else:
                opacity = 1.0

            view.setStyle({
                "stick": {
                    "radius": 0.2 * scale,
                    "opacity": opacity,
                    "color": "grey"
                },
                "sphere": {
                    "scale": 0.3 * scale,
                    "opacity": opacity,
                    "colorscheme": modified_color_scheme,
                },
            })

        # coarse
        if cg_names:
            coarse.save(
                os.path.join(tmp_dir, "coarse_tmp.mol2"),
                show_ports=show_ports,
                overwrite=True,
            )
            with open(os.path.join(tmp_dir, "coarse_tmp.mol2"), "r") as f:
                view.addModel(f.read(), "mol2", keepH=True)

            if self.atomistic is None:
                scale = 0.3 * scale
            else:
                scale = 0.7 * scale

            view.setStyle(
                {"atom": cg_names},
                {
                    "stick": {
                        "radius": 0.2 * scale,
                        "opacity": 1,
                        "color": "grey"
                    },
                    "sphere": {
                        "scale": scale,
                        "opacity": 1,
                        "colorscheme": modified_color_scheme,
                    },
                },
            )

        view.zoomTo()

        return view
Exemple #48
0
        top_lipids.append([lipid_molecule, lipid_offset])
        bot_lipids.append([lipid_molecule, lipid_offset])
        index += 1

if len(bot_lipids) != n_lipid:
    sys.exit('Error setting up system components')

# Generate bottom layer randomly
bot_layer = mb.Compound()
for i in range(n_x):
    for j in range(n_y):
        # Randomly select a lipid that has not yet been selected
        random_lipid = np.random.randint(0, len(bot_lipids))
        # Create the mbuild Molecule for this lipid
        molecule_i = bot_lipids.pop(random_lipid)
        molecule_to_add = mb.clone(molecule_i[0])
        # Apply tilt angle
        mb.spin_y(molecule_to_add, tilt_angle)
        # Apply z_offset
        z_offset = molecule_i[1]
        #z_offset = 0
        # Apply APL and z_offset to identify the position for the molecule in the grid
        position = [i * spacing, j * spacing, z_offset]
        mb.translate(molecule_to_add, position)
        # Add the new molecule to the layer
        bot_layer.add(molecule_to_add)

# Generate the top layer of lipids randomly
top_layer = mb.Compound()
for i in range(n_x):
    for j in range(n_y):
Exemple #49
0
 def _clone(self, clone_of=None, root_container=None):
     newone = super(Port, self)._clone(clone_of, root_container)
     newone.anchor = clone(self.anchor, clone_of, root_container)
     newone.used = self.used
     return newone
Exemple #50
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.

        Exceptions Raised
        -----------------
        ValueError : incorrect x,y, or z values.
        TypeError : incorrect type for basis vector

        Call Restrictions
        -----------------
        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 of type 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 mbuild.Compound.'
                                    .format(key_id, err_type))
        # set periodicity, currently assuming rectangular system
        if not np.all(np.allclose(self.angles, [90.0, 90.0, 90.0])):
            warn('Periodicity of non-rectangular lattices are not valid with '
                 'default boxes. Only rectangular lattices are valid '
                 'at this time.')
        ret_lattice.periodicity = np.asarray([a * x, b * y, c * z], dtype=np.float64)

        # 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.

        return ret_lattice
Exemple #51
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')
Exemple #52
0
    def _add_chemisorbed_chains(self, chain, spacing, n_chemisorbed, n_chains,
                                chain_port_name, verbose):
        """Attach chains to the surface...
        """
        available_sites = np.array(self['surface'].available_ports())
        if n_chemisorbed and n_chains and n_chains < n_chemisorbed:
            raise Exception(
                'Cannot specify `n_chains` less than `n_chemisorbed`!')

        added_chains = 0
        while len(available_sites) > 0:
            if ((n_chemisorbed and added_chains == n_chemisorbed)
                    or (n_chains and added_chains == n_chains)):
                available_sites = []
            else:
                binding_site = random.choice(available_sites)
                new_chain = mb.clone(chain)
                self.crosslink_graph.add_node(
                    new_chain.available_ports()[0].anchor,
                    pos=(binding_site.pos[0], binding_site.pos[1]),
                    surface_bound=True)
                si = list(new_chain.particles_by_name('Si'))[0]
                self.add(new_chain, 'chemisorbed_chain[$]')
                mb.force_overlap(new_chain, new_chain[chain_port_name],
                                 binding_site)
                available_sites = [
                    site for site in available_sites
                    if (site != binding_site and self.min_periodic_distance(
                        np.array([site.pos[0], site.pos[1], 0]),
                        np.array([binding_site.pos[0], binding_site.pos[1], 0
                                  ])) > spacing)
                ]
                added_chains += 1
                if verbose:
                    print('Added chemisorbed chain {}'
                          ''.format(len(self['chemisorbed_chain'])))
                    print('{} available sites remaining'.format(
                        len(available_sites)))

        if n_chemisorbed and added_chains < n_chemisorbed:
            print(
                'Maximum number of chemisorbed chains without overlaps has been '
                'reached! However, additional chains will be added to satisfy '
                'n_chemisorbed requirement.')
            while added_chains < n_chemisorbed:
                available_sites = np.array(
                    [site for site in self['surface'].available_ports()])
                chain_locations = np.array(
                    [chain.pos for chain in self['chemisorbed_chain']])
                chain_locations[:, 2] = 0
                min_dists = []
                for site in available_sites:
                    min_dist = np.min([
                        self.min_periodic_distance(
                            [site.pos[0], site.pos[1], 0.0], loc)
                        for loc in chain_locations
                    ])
                    min_dists.append(min_dist)
                binding_site = available_sites[np.argmax(min_dists)]
                new_chain = mb.clone(chain)
                self.crosslink_graph.add_node(
                    new_chain.available_ports()[0].anchor,
                    pos=(binding_site.pos[0], binding_site.pos[1]),
                    surface_bound=True)
                si = list(new_chain.particles_by_name('Si'))[0]
                self.add(new_chain, 'chemisorbed_chain[$]')
                mb.force_overlap(new_chain, new_chain[chain_port_name],
                                 binding_site)
                added_chains += 1
                if verbose:
                    print('Added chemisorbed chain {}'
                          ''.format(len(self['chemisorbed_chain'])))
 def test_spin_z_eq(self, sixpoints):
     compound2 = mb.clone(sixpoints)
     sixpoints.spin(np.pi * 1.23456789, np.asarray([0.0, 0.0, 1.0]))
     spin_z(compound2, np.pi * 1.23456789)
     assert (np.allclose(compound2.xyz, sixpoints.xyz, atol=1e-16))
Exemple #54
0
    def _add_crosslinked_chains(self, chain, spacing, n_chains,
                                chain_port_name, verbose):
        """Add crosslinked chains... """
        # Add hydroxyl to prototype for crosslinked chain
        chain.spin(np.pi / 2, [1, 0, 0])
        hydroxyl = Hydroxyl()
        mb.force_overlap(hydroxyl, hydroxyl['down'], chain[chain_port_name])
        chain.add(hydroxyl)

        surface_level = max(self['surface'].xyz[:, 2])

        chains_in_monolayer = len(self['chemisorbed_chain'])
        complete = False
        while not complete:
            vertices = self._get_voronoi_vertices()

            # Determine locations of chains already in the monolayer
            chemisorbed_chain_locations = np.array(
                [chain.pos for chain in self['chemisorbed_chain']])
            if 'crosslinked_chain' in self.labels:
                crosslinked_chain_locations = np.array(
                    [chain.pos for chain in self['crosslinked_chain']])
            try:
                chain_locations = np.vstack(
                    (chemisorbed_chain_locations, crosslinked_chain_locations))
            except UnboundLocalError:
                chain_locations = chemisorbed_chain_locations
            chain_locations[:, 2] = 0
            dists = []
            for vertex in vertices:
                min_dist = np.min([
                    self.min_periodic_distance([vertex[0], vertex[1], 0.0],
                                               loc) for loc in chain_locations
                ])
                dists.append(min_dist)
            '''
            Add crosslinked chain to monolayer if:
                1. n_chains is specified and chains_in_monolayer < n_chains
                2. n_chains is not specified and np.max(dists) > spacing
            '''
            if ((n_chains and chains_in_monolayer < n_chains)
                    or (not n_chains and np.max(dists) > spacing)):
                site_2d = vertices[np.argmax(dists)]
                site = np.array([site_2d[0], site_2d[1], 0.0])

                failed_attempts = 0
                new_chain = mb.clone(chain)
                new_chain.translate_to(site)
                new_chain.translate([
                    0.0, 0.0, surface_level +
                    (new_chain.pos[2] - min(new_chain.xyz[:, 2])) + 0.15
                ])
                self.add(new_chain, 'crosslinked_chain[$]')
                new_chain_si = list(new_chain.particles_by_name('Si'))[0]
                self.crosslink_graph.add_node(new_chain_si,
                                              pos=(site[0], site[1]),
                                              surface_bound=False)
                chains_in_monolayer = len(self['crosslinked_chain']) + \
                    len(self['chemisorbed_chain'])
                if np.max(dists) <= spacing:
                    print(
                        'Added chain would be closer to a neighboring chain than '
                        'the specified `spacing` ({}). Chain will be added to '
                        'meet `n_chains` requirement.'.format(spacing))
                if verbose:
                    print('Added crosslinked chain {} ({} total chains)'
                          ''.format(len(self['crosslinked_chain']),
                                    chains_in_monolayer))
            else:
                complete = True
Exemple #55
0
def solvate(solute, solvent, n_solvent, box, overlap=0.2,
            seed=12345, edge=0.2, fix_orientation=False, temp_file=None):
    """Solvate a compound in a box of solvent using packmol.

    Parameters
    ----------
    solute : mb.Compound
        Compound to be placed in a box and solvated.
    solvent : mb.Compound
        Compound to solvate the box.
    n_solvent : int
        Number of solvents to be put in box.
    box : mb.Box
        Box to be filled by compounds.
    overlap : float, units nm, default=0.2
        Minimum separation between atoms of different molecules.
    seed : int, default=12345
        Random seed to be passed to PACKMOL.
    edge : float, units nm, default=0.2
        Buffer at the edge of the box to not place molecules. This is necessary
        in some systems because PACKMOL does not account for periodic boundary
        conditions in its optimization.
    fix_orientation : bool
        Specify if solvent should not be rotated when filling box,
        default=False.
    temp_file : str, default=None
        File name to write PACKMOL's raw output to.

    Returns
    -------
    solvated : mb.Compound

    """
    _check_packmol(PACKMOL)

    box = _validate_box(box)
    if not isinstance(solvent, (list, set)):
        solvent = [solvent]
    if not isinstance(n_solvent, (list, set)):
        n_solvent = [n_solvent]
    if not isinstance(fix_orientation, (list, set)):
        fix_orientation = [fix_orientation] * len(solvent)

    if len(solvent) != len(n_solvent):
        msg = ("`n_solvent` and `n_solvent` must be of equal length.")
        raise ValueError(msg)


    # In angstroms for packmol.
    box_mins = box.mins * 10
    box_maxs = box.maxs * 10
    overlap *= 10
    center_solute = (box_maxs + box_mins) / 2

    # Apply edge buffer
    box_maxs -= edge * 10

    # Build the input file for each compound and call packmol.
    solvated_pdb = tempfile.mkstemp(suffix='.pdb')[1]
    solute_pdb = tempfile.mkstemp(suffix='.pdb')[1]
    solute.save(solute_pdb, overwrite=True)
    input_text = (PACKMOL_HEADER.format(overlap, solvated_pdb, seed) +
                  PACKMOL_SOLUTE.format(solute_pdb, *center_solute))

    for solv, m_solvent, rotate in zip(solvent, n_solvent, fix_orientation):
        m_solvent = int(m_solvent)
        solvent_pdb = tempfile.mkstemp(suffix='.pdb')[1]
        solv.save(solvent_pdb, overwrite=True)
        input_text += PACKMOL_BOX.format(solvent_pdb, m_solvent,
                           box_mins[0], box_mins[1], box_mins[2],
                           box_maxs[0], box_maxs[1], box_maxs[2],
                           PACKMOL_CONSTRAIN if rotate else "")
    _run_packmol(input_text, solvated_pdb, temp_file)

    # Create the topology and update the coordinates.
    solvated = Compound()
    solvated.add(solute)
    for solv, m_solvent in zip(solvent, n_solvent):
        for _ in range(m_solvent):
            solvated.add(clone(solv))
    solvated.update_coordinates(solvated_pdb)
    return solvated
 def test_equivalence_transform_deprectation_warning(self, ch2):
     ch22 = mb.clone(ch2)
     with pytest.warns(DeprecationWarning):
         mb.equivalence_transform(ch22,
                                  from_positions=ch22['up'],
                                  to_positions=ch2['down'])
Exemple #57
0
 def test_add_existing_parent(self, ethane, h2o):
     water_in_water = mb.clone(h2o)
     h2o.add(water_in_water)
     with pytest.raises(MBuildError):
         ethane.add(water_in_water)
 def test_different_translates(self, methane):
     shifted = mb.clone(methane)
     shifted.translate([5, 4, 3])
     shifted_methane_coords = mb.coordinate_transform._translate(
         methane.xyz, [5, 4, 3])
     assert np.array_equal(shifted_methane_coords, shifted.xyz)
Exemple #59
0
 def test_clone_outside_containment(self, ch2, ch3):
     compound = mb.Compound()
     compound.add(ch2)
     mb.force_overlap(ch3, ch3['up'], ch2['up'])
     with pytest.raises(MBuildError):
         ch3_clone = mb.clone(ch3)
 def test_different_translate_tos_origin(self, methane):
     shifted = mb.clone(methane)
     shifted.translate_to([0, 0, 0])
     x = mb.coordinate_transform._translate_to(methane.xyz, [0, 0, 0])
     assert np.array_equal(shifted.xyz, x)