Esempio n. 1
0
    def make_snapshot(particle_types=['A'], a=1, n=7, r=0):
        """Make a snapshot with particles in a fcc structure.

        Args:
            particle_types: List of particle type names
            a: Lattice constant
            n: Number of unit cells along each box edge
            r: Amount to randomly perturb particles in x,y,z

        Place particles in a fcc structure. The box is cubic with a side length
        of ``n * a``. There will be ``4 * n**3`` particles in the snapshot.
        """
        s = Snapshot(device.communicator)

        if s.communicator.rank == 0:
            # make one unit cell
            s.configuration.box = [a, a, a, 0, 0, 0]
            s.particles.N = 4
            s.particles.types = particle_types
            s.particles.position[:] = [
                [0, 0, 0],
                [0, a / 2, a / 2],
                [a / 2, 0, a / 2],
                [a / 2, a / 2, 0],
            ]
            # and replicate it
            s.replicate(n, n, n)

        # perturb the positions
        if r > 0:
            shift = numpy.random.uniform(-r, r, size=(s.particles.N, 3))
            s.particles.position[:] += shift

        return s
Esempio n. 2
0
    def create_state_from_gsd(self, filename, frame=-1):
        """Create the simulation state from a GSD file.

        Args:
            filename (str): GSD file to read

            frame (int): Index of the frame to read from the file. Negative
                values index back from the last frame in the file.
        """
        if self.state is not None:
            raise RuntimeError("Cannot initialize more than once\n")
        filename = _hoomd.mpi_bcast_str(filename, self.device._cpp_exec_conf)
        # Grab snapshot and timestep
        reader = _hoomd.GSDReader(self.device._cpp_exec_conf, filename,
                                  abs(frame), frame < 0)
        snapshot = Snapshot._from_cpp_snapshot(reader.getSnapshot(),
                                               self.device.communicator)

        step = reader.getTimeStep() if self.timestep is None else self.timestep
        self._state = State(self, snapshot)

        reader.clearSnapshot()
        # Store System and Reader for Operations
        self._cpp_sys = _hoomd.System(self.state._cpp_sys_def, step)
        self._init_communicator()
        self.operations._store_reader(reader)
Esempio n. 3
0
    def snapshot(self):
        r"""hoomd.Snapshot: All data of a simulation's current microstate.

        `State.snapshot` should be used when all of a simulation's state
        information is desired in a single object. When accessed, data across
        all MPI ranks and from GPUs is gathered on the root MPI rank's memory.
        When accessing data in MPI simulations, it is recommended to use a
        ``if snapshot.exists:`` conditional to prevent attempting to access data
        on a non-root rank.

        This property can be set to replace the system state with the given
        `hoomd.Snapshot` object.  Example use cases in which a simulation's
        state may be reset from a snapshot include Monte Carlo schemes
        implemented at the Python script level, where the current snapshot is
        passed to the Monte Carlo simulation before being passed back after
        running some Monte Carlo steps.

        Warning:
            Using `State.snapshot` multiple times will gather data across MPI
            ranks and GPUs every time. If the snapshot is needed for more than
            one use, it is recommended to store it in a variable.

        Note:
            Setting or getting a snapshot is an order :math:`O(N_{particles}
            + N_{bonds} + \ldots)` operation.
        """
        cpp_snapshot = self._cpp_sys_def.takeSnapshot_double()
        return Snapshot._from_cpp_snapshot(cpp_snapshot,
                                           self._simulation.device.communicator)
Esempio n. 4
0
def test_from_gsd_snapshot_populated(s, device):
    if s.exists:
        s.configuration.box = [10, 12, 7, 0.1, 0.4, 0.2]
        for section in ('particles', 'bonds', 'angles', 'dihedrals',
                        'impropers', 'pairs'):
            setattr(getattr(s, section), 'N', 5)
            setattr(getattr(s, section), 'types', ['A', 'B'])

        for prop in ('angmom', 'body', 'charge', 'diameter', 'image', 'mass',
                     'moment_inertia', 'orientation', 'position', 'typeid',
                     'velocity'):
            attr = getattr(s.particles, prop)
            if attr.dtype == numpy.float64:
                attr[:] = numpy.random.rand(*attr.shape)
            else:
                attr[:] = numpy.random.randint(3, size=attr.shape)

        for section in ('bonds', 'angles', 'dihedrals', 'impropers', 'pairs'):
            for prop in ('group', 'typeid'):
                attr = getattr(getattr(s, section), prop)
                attr[:] = numpy.random.randint(3, size=attr.shape)

        s.constraints.N = 3
        for prop in ('group', 'value'):
            attr = getattr(s.constraints, prop)
            if attr.dtype == numpy.float64:
                attr[:] = numpy.random.rand(*attr.shape)
            else:
                attr[:] = numpy.random.randint(3, size=attr.shape)

    gsd_snap = make_gsd_snapshot(s)
    hoomd_snap = Snapshot.from_gsd_snapshot(gsd_snap, device.communicator)
    assert_equivalent_snapshots(gsd_snap, hoomd_snap)
Esempio n. 5
0
    def get_snapshot(self):
        """Make a copy of the simulation current state.

        `State.get_snapshot` makes a copy of the simulation state and
        makes it available in a single object. `State.set_snapshot` resets
        the internal state to that in the given snapshot. Use these methods
        to implement techniques like hybrid MD/MC or umbrella sampling where
        entire system configurations need to be reset to a previous one after a
        rejected move.

        Note:
            Data across all MPI ranks and from GPUs is gathered on the root MPI
            rank's memory. When accessing data in MPI simulations, use a ``if
            snapshot.communicator.rank == 0:`` conditional to access data arrays
            only on the root rank.

        Note:
            `State.get_snapshot` is an order :math:`O(N_{particles} + N_{bonds}
            + \\ldots)` operation.

        See Also:
            `set_snapshot`

        Returns:
            hoomd.Snapshot: The current simulation state
        """
        cpp_snapshot = self._cpp_sys_def.takeSnapshot_double()
        return Snapshot._from_cpp_snapshot(
            cpp_snapshot, self._simulation.device.communicator)
Esempio n. 6
0
    def make_snapshot(particle_types=['A'], dimensions=3, a=1, n=7, r=0):
        s = Snapshot(device.communicator)

        if s.exists:
            box = [n * a, n * a, n * a, 0, 0, 0]
            if dimensions == 2:
                box[2] = 0
            s.configuration.box = box

            s.particles.N = n**dimensions
            s.particles.types = particle_types

            # create the lattice
            range_ = numpy.arange(-n / 2, n / 2)
            if dimensions == 2:
                pos = list(itertools.product(range_, range_, [0]))
            else:
                pos = list(itertools.product(range_, repeat=3))
            pos = numpy.array(pos) * a
            pos[:, 0] += a / 2
            pos[:, 1] += a / 2
            if dimensions == 3:
                pos[:, 2] += a / 2

            # perturb the positions
            if r > 0:
                shift = numpy.random.uniform(-r, r, size=(s.particles.N, 3))
                if dimensions == 2:
                    shift[:, 2] = 0
                pos += shift

            s.particles.position[:] = pos

        return s
Esempio n. 7
0
    def make_snapshot(particle_types=['A'], dimensions=3, d=1, L=20):
        """Make the snapshot.

        Args:
            particle_types: List of particle type names
            dimensions: Number of dimensions (2 or 3)
            d: Distance apart to place particles
            L: Box length

        The two particles are placed at (-d/2, 0, 0) and (d/2,0,0). When,
        dimensions==3, the box is L by L by L. When dimensions==2, the box is
        L by L by 0.
        """
        s = Snapshot(device.communicator)
        N = 2

        if s.communicator.rank == 0:
            box = [L, L, L, 0, 0, 0]
            if dimensions == 2:
                box[2] = 0
            s.configuration.box = box
            s.particles.N = N
            # shift particle positions slightly in z so MPI tests pass
            s.particles.position[:] = [[-d / 2, 0, .1], [d / 2, 0, .1]]
            s.particles.types = particle_types
            if dimensions == 2:
                box[2] = 0
                s.particles.position[:] = [[-d / 2, 0.1, 0], [d / 2, 0.1, 0]]

        return s
Esempio n. 8
0
    def create_state_from_snapshot(self, snapshot):
        """Create the simulations state from a `Snapshot`.

        Args:
            snapshot (Snapshot or gsd.hoomd.Snapshot): Snapshot to initialize
                the state from. A `gsd.hoomd.Snapshot` will first be
                converted to a `hoomd.Snapshot`.


        When `timestep` is `None` before calling, `create_state_from_snapshot`
        sets `timestep` to 0.
        """
        if self.state is not None:
            raise RuntimeError("Cannot initialize more than once\n")

        if isinstance(snapshot, Snapshot):
            # snapshot is hoomd.Snapshot
            self._state = State(self, snapshot)
        elif _match_class_path(snapshot, 'gsd.hoomd.Snapshot'):
            # snapshot is gsd.hoomd.Snapshot
            snapshot = Snapshot.from_gsd_snapshot(snapshot,
                                                  self._device.communicator)
            self._state = State(self, snapshot)
        else:
            raise TypeError(
                "Snapshot must be a hoomd.Snapshot or gsd.hoomd.Snapshot.")

        step = 0
        if self.timestep is not None:
            step = self.timestep

        self._init_system(step)
Esempio n. 9
0
 def filter_snapshot(n=10, particle_types=['A']):
     s = Snapshot(device.communicator)
     if s.communicator.rank == 0:
         s.configuration.box = [20, 20, 20, 0, 0, 0]
         s.particles.N = n
         s.particles.position[:] = np.random.uniform(-10, 10, size=(n, 3))
         s.particles.types = particle_types
     return s
Esempio n. 10
0
    def create_state_from_snapshot(self,
                                   snapshot,
                                   domain_decomposition=(None, None, None)):
        """Create the simulation state from a `Snapshot`.

        Args:
            snapshot (Snapshot or gsd.hoomd.Snapshot): Snapshot to initialize
                the state from. A `gsd.hoomd.Snapshot` will first be
                converted to a `hoomd.Snapshot`.

            domain_decomposition (tuple): Choose how to distribute the state
                across MPI ranks with domain decomposition. Provide a tuple
                of 3 integers indicating the number of evenly spaced domains in
                the x, y, and z directions (e.g. ``(8,4,2)``). Provide a tuple
                of 3 lists of floats to set the fraction of the simulation box
                to include in each domain. The sum of each list of floats must
                be 1.0 (e.g. ``([0.25, 0.75], [0.2, 0.8], [1.0])``).

        When `timestep` is `None` before calling, `create_state_from_snapshot`
        sets `timestep` to 0.

        Note:
            Set any or all of the ``domain_decomposition`` tuple elements to
            `None` and `create_state_from_gsd` will select a value that
            minimizes the surface area between the domains (e.g.
            ``(2,None,None)``). The domains are spaced evenly along each
            automatically selected direction. The default value of ``(None,
            None, None)`` will automatically select the number of domains in all
            directions.

        See Also:
            `State.get_snapshot`

            `State.set_snapshot`
        """
        if self._state is not None:
            raise RuntimeError("Cannot initialize more than once\n")

        if isinstance(snapshot, Snapshot):
            # snapshot is hoomd.Snapshot
            self._state = State(self, snapshot, domain_decomposition)
        elif _match_class_path(snapshot, 'gsd.hoomd.Snapshot'):
            # snapshot is gsd.hoomd.Snapshot
            snapshot = Snapshot.from_gsd_snapshot(snapshot,
                                                  self._device.communicator)
            self._state = State(self, snapshot, domain_decomposition)
        else:
            raise TypeError(
                "Snapshot must be a hoomd.Snapshot or gsd.hoomd.Snapshot.")

        step = 0
        if self.timestep is not None:
            step = self.timestep

        self._init_system(step)
Esempio n. 11
0
    def make_snapshot(particle_types=['A'], dimensions=3, a=1, n=7, r=0):
        """Make the snapshot.

        Args:
            particle_types: List of particle type names
            dimensions: Number of dimensions (2 or 3)
            a: Lattice constant
            n: Number of particles along each box edge. Pass a tuple for
                different lengths in each dimension.
            r: Fraction of `a` to randomly perturb particles

        Place particles on a simple cubic (dimensions==3) or square
        (dimensions==2) lattice. The box is cubic (or square) with a side length
        of `n * a`.

        Set `r` to randomly perturb particles a small amount off their lattice
        positions. This is useful in MD simulation testing so that forces do not
        cancel out by symmetry.
        """
        if isinstance(n, int):
            n = (n, ) * dimensions
            if dimensions == 2:
                n += (1, )

        s = Snapshot(device.communicator)

        if s.communicator.rank == 0:
            box = [n[0] * a, n[1] * a, n[2] * a, 0, 0, 0]
            if dimensions == 2:
                box[2] = 0
            s.configuration.box = box

            s.particles.N = numpy.product(n)
            s.particles.types = particle_types

            if any(nx == 0 for nx in n):
                return s

            # create the lattice
            ranges = [numpy.arange(-nx / 2, nx / 2) for nx in n]
            x, y, z = numpy.meshgrid(*ranges)
            lattice_position = numpy.vstack(
                (x.flatten(), y.flatten(), z.flatten())).T
            pos = (lattice_position + 0.5) * a
            if dimensions == 2:
                pos[:, 2] = 0
            # perturb the positions
            if r > 0:
                shift = numpy.random.uniform(-r, r, size=(s.particles.N, 3))
                if dimensions == 2:
                    shift[:, 2] = 0
                pos += shift
            s.particles.position[:] = pos

        return s
Esempio n. 12
0
    def make_snapshot(particle_types=['A'], dimensions=3, a=1, n=7, r=0):
        """Make the snapshot.

        Args:
            particle_types: List of particle type names
            dimensions: Number of dimensions (2 or 3)
            a: Lattice constant
            n: Number of particles along each box edge
            r: Fraction of `a` to randomly perturb particles

        Place particles on a simple cubic (dimensions==3) or square
        (dimensions==2) lattice. The box is cubic (or square) with a side length
        of `n * a`.

        Set `r` to randomly perturb particles a small amount off their lattice
        positions. This is useful in MD simulation testing so that forces do not
        cancel out by symmetry.
        """
        s = Snapshot(device.communicator)

        if s.communicator.rank == 0:
            box = [n * a, n * a, n * a, 0, 0, 0]
            if dimensions == 2:
                box[2] = 0
            s.configuration.box = box

            s.particles.N = n**dimensions
            s.particles.types = particle_types

            # create the lattice
            if n > 0:
                range_ = numpy.arange(-n / 2, n / 2)
                if dimensions == 2:
                    pos = list(itertools.product(range_, range_, [0]))
                else:
                    pos = list(itertools.product(range_, repeat=3))
                pos = numpy.array(pos) * a
                pos[:, 0] += a / 2
                pos[:, 1] += a / 2
                if dimensions == 3:
                    pos[:, 2] += a / 2

                # perturb the positions
                if r > 0:
                    shift = numpy.random.uniform(-r,
                                                 r,
                                                 size=(s.particles.N, 3))
                    if dimensions == 2:
                        shift[:, 2] = 0
                    pos += shift

                s.particles.position[:] = pos

        return s
Esempio n. 13
0
    def make_snapshot(particle_types=['A'], dimensions=3, d=1, L=20):
        s = Snapshot(device.communicator)
        N = 2

        if s.exists:
            box = [L, L, L, 0, 0, 0]
            if dimensions == 2:
                box[2] = 1
            s.configuration.box = box
            s.configuration.dimensions = dimensions
            s.particles.N = N
            # shift particle positions slightly in z so MPI tests pass
            s.particles.position[:] = [[-d / 2, 0, .1], [d / 2, 0, .1]]
            s.particles.types = particle_types

        return s
Esempio n. 14
0
    def create_state_from_gsd(self,
                              filename,
                              frame=-1,
                              domain_decomposition=(None, None, None)):
        """Create the simulation state from a GSD file.

        Args:
            filename (str): GSD file to read

            frame (int): Index of the frame to read from the file. Negative
                values index back from the last frame in the file.

            domain_decomposition (tuple): Choose how to distribute the state
                across MPI ranks with domain decomposition. Provide a tuple
                of 3 integers indicating the number of evenly spaced domains in
                the x, y, and z directions (e.g. ``(8,4,2)``). Provide a tuple
                of 3 lists of floats to set the fraction of the simulation box
                to include in each domain. The sum of each list of floats must
                be 1.0 (e.g. ``([0.25, 0.75], [0.2, 0.8], [1.0])``).

        When `timestep` is `None` before calling, `create_state_from_gsd`
        sets `timestep` to the value in the selected GSD frame in the file.

        Note:
            Set any or all of the ``domain_decomposition`` tuple elements to
            `None` and `create_state_from_gsd` will select a value that
            minimizes the surface area between the domains (e.g.
            ``(2,None,None)``). The domains are spaced evenly along each
            automatically selected direction. The default value of ``(None,
            None, None)`` will automatically select the number of domains in all
            directions.
        """
        if self._state is not None:
            raise RuntimeError("Cannot initialize more than once\n")
        filename = _hoomd.mpi_bcast_str(filename, self.device._cpp_exec_conf)
        # Grab snapshot and timestep
        reader = _hoomd.GSDReader(self.device._cpp_exec_conf, filename,
                                  abs(frame), frame < 0)
        snapshot = Snapshot._from_cpp_snapshot(reader.getSnapshot(),
                                               self.device.communicator)

        step = reader.getTimeStep() if self.timestep is None else self.timestep
        self._state = State(self, snapshot, domain_decomposition)

        reader.clearSnapshot()

        self._init_system(step)
Esempio n. 15
0
    def make_snapshot(particle_types=['A'],
                      dimensions=3,
                      position=(0, 0, 0),
                      orientation=(1, 0, 0, 0),
                      L=20):
        """Make the snapshot.

        Args:
            particle_types: List of particle type names
            dimensions: Number of dimensions (2 or 3)
            position: Position to place the particle
            orientation: Orientation quaternion to assign to the particle
            L: Box length

        The arguments position and orientation define the position and
        orientation of the particle.  When dimensions==3, the box is a cubic box
        with dimensions L by L by L. When dimensions==2, the box is a square box
        with dimensions L by L by 0.
        """
        s = Snapshot(device.communicator)
        N = 1

        if dimensions == 2 and position[2] != 0:
            raise ValueError(
                'z component of position must be zero for 2D simulation.')

        if s.communicator.rank == 0:
            box = [L, L, L, 0, 0, 0]
            if dimensions == 2:
                box[2] = 0
            s.configuration.box = box
            s.particles.N = N
            # shift particle positions slightly in z so MPI tests pass
            s.particles.position[0] = position
            s.particles.orientation[0] = orientation
            s.particles.types = particle_types
        return s
Esempio n. 16
0
def test_from_gsd_snapshot_empty(s, device):
    gsd_snap = make_gsd_snapshot(s)
    hoomd_snap = Snapshot.from_gsd_snapshot(gsd_snap, device.communicator)
    assert_equivalent_snapshots(gsd_snap, hoomd_snap)
Esempio n. 17
0
def snap(device):
    s = Snapshot(device.communicator)
    N = 1000

    if s.exists:
        s.configuration.box = [20, 20, 20, 0, 0, 0]

        s.particles.N = N
        s.particles.position[:] = numpy.random.uniform(-10, 10, size=(N, 3))
        s.particles.velocity[:] = numpy.random.uniform(-1, 1, size=(N, 3))
        s.particles.typeid[:] = numpy.random.randint(0, 3, size=N)
        s.particles.mass[:] = numpy.random.uniform(1, 2, size=N)
        s.particles.charge[:] = numpy.random.uniform(-2, 2, size=N)
        s.particles.image[:] = numpy.random.randint(-8, 8, size=(N, 3))
        s.particles.orientation[:] = numpy.random.uniform(-1, 1, size=(N, 4))
        s.particles.moment_inertia[:] = numpy.random.uniform(1, 5, size=(N, 3))
        s.particles.angmom[:] = numpy.random.uniform(-1, 1, size=(N, 4))
        s.particles.types = ['A', 'B', 'C', 'D']

        s.bonds.N = N - 1
        for i in range(s.bonds.N):
            s.bonds.group[i, :] = [i, i + 1]

        s.bonds.typeid[:] = numpy.random.randint(0, 3, size=s.bonds.N)
        s.bonds.types = ['bondA', 'bondB', 'bondC', 'bondD']

        s.angles.N = N - 2
        for i in range(s.angles.N):
            s.angles.group[i, :] = [i, i + 1, i + 2]

        s.angles.typeid[:] = numpy.random.randint(0, 3, size=s.angles.N)
        s.angles.types = ['angleA', 'angleB', 'angleC', 'angleD']

        s.dihedrals.N = N - 3
        for i in range(s.dihedrals.N):
            s.dihedrals.group[i, :] = [i, i + 1, i + 2, i + 3]

        s.dihedrals.typeid[:] = numpy.random.randint(0, 3, size=s.dihedrals.N)
        s.dihedrals.types = [
            'dihedralA', 'dihedralB', 'dihedralC', 'dihedralD'
        ]

        s.impropers.N = N - 3
        for i in range(s.impropers.N):
            s.impropers.group[i, :] = [i, i + 1, i + 2, i + 3]

        s.impropers.typeid[:] = numpy.random.randint(0, 3, size=s.impropers.N)
        s.impropers.types = [
            'improperA', 'improperB', 'improperC', 'improperD'
        ]

        s.pairs.N = N - 1
        for i in range(s.pairs.N):
            s.pairs.group[i, :] = [i, i + 1]

        s.pairs.typeid[:] = numpy.random.randint(0, 3, size=s.pairs.N)
        s.pairs.types = ['pairA', 'pairB', 'pairC', 'pairD']

        s.constraints.N = N - 1
        for i in range(s.constraints.N):
            s.constraints.group[i, :] = [i, i + 1]

        s.constraints.value[:] = numpy.random.uniform(1,
                                                      10,
                                                      size=s.constraints.N)

    return s
Esempio n. 18
0
def s():
    return Snapshot()