Ejemplo n.º 1
0
    def test_dump_cbk(self):
        """
        Make sure that applying callbacks or changing the particle array
        size creates a new dump.
        """
        import numpy
        from atooms.system import Particle, System

        for view in [False, True]:
            p = [Particle(), Particle()]
            s = System(p)
            pos1 = s.dump("pos", view=view)

            def cbk(system):
                s = copy.copy(system)
                s.particle = [system.particle[0]]
                return s

            s = cbk(s)
            pos2 = s.dump('pos', view=view)
            self.assertEqual(pos1.shape, (2, 3))
            self.assertEqual(pos2.shape, (1, 3))
            # Grandcanonical
            s.particle.append(Particle())
            self.assertEqual(s.dump('pos', view=view).shape, (2, 3))
            # Reassign particle
            # Expected failure with view = True
            if not view:
                s.particle[0] = Particle(position=[1.0, 1.0, 1.0])
                self.assertEqual(s.dump('pos', view=view)[0][0], 1.0)
Ejemplo n.º 2
0
    def test_gyration(self):
        from atooms.system.particle import gyration_radius
        system = copy.copy(self.ref)

        # Ignore cell
        rg1 = gyration_radius(system.particle, method='N1')
        rg2 = gyration_radius(system.particle, method='N2')
        self.assertAlmostEqual(rg1, rg2)

        # With PBC all estimates are different but bounds must be ok
        rg1 = gyration_radius(system.particle, system.cell, method='min')
        rg2 = gyration_radius(system.particle, system.cell, method='N1')
        rg3 = gyration_radius(system.particle, system.cell, method='N2')
        self.assertLessEqual(rg1, rg2)
        self.assertLessEqual(rg3, rg2)

        # Equilateral triangle
        system.particle = [Particle(), Particle(), Particle()]
        system.particle[0].position = numpy.array([0.0, 0.0, 0.0])
        system.particle[1].position = numpy.array([1.0, 0.0, 0.0])
        system.particle[2].position = numpy.array([0.5, 0.5 * 3**0.5, 0])
        # Put the triangle across the cell
        system.particle[0].position -= 1.01 * system.cell.side / 2
        system.particle[1].position -= 1.01 * system.cell.side / 2
        system.particle[2].position -= 1.01 * system.cell.side / 2
        system.particle[0].fold(system.cell)
        system.particle[1].fold(system.cell)
        system.particle[2].fold(system.cell)
        rg1 = gyration_radius(system.particle, system.cell, method='min')
        rg2 = gyration_radius(system.particle, system.cell, method='N1')
        rg3 = gyration_radius(system.particle, system.cell, method='N2')
        self.assertAlmostEqual(rg1, 0.57735026919)
        self.assertAlmostEqual(rg2, 0.57735026919)
        self.assertAlmostEqual(rg3, 0.57735026919)
Ejemplo n.º 3
0
    def test_view(self):
        import numpy
        from atooms.system import Particle, System

        p = [Particle(), Particle()]
        s = System(p)
        pos = s.dump("pos", order='F', view=True)

        # Modify the dumped array in place preserves the view
        pos[:, 0] += 1.0
        self.assertTrue((p[0].position == pos[:, 0]).all())
        self.assertTrue(numpy.may_share_memory(p[0].position, pos[:, 0]))
        # Modify the position array in place preserves the view
        p[0].position *= 2
        self.assertTrue((p[0].position == pos[:, 0]).all())
        self.assertTrue(numpy.may_share_memory(p[0].position, pos[:, 0]))
        # Modify the position array in place preserves the view
        p[0].position[:] = p[0].position[:] + 4
        self.assertTrue((p[0].position == pos[:, 0]).all())
        self.assertTrue(numpy.may_share_memory(p[0].position, pos[:, 0]))
        pos[:, 0] = pos[:, 0] + 1.0
        self.assertTrue((p[0].position == pos[:, 0]).all())
        self.assertTrue(numpy.may_share_memory(p[0].position, pos[:, 0]))
        # Reassining the position will of course destroy the view
        p[0].position = p[0].position * 2
        self.assertFalse((p[0].position == pos[:, 0]).all())
        self.assertFalse(numpy.may_share_memory(p[0].position, pos[:, 0]))
Ejemplo n.º 4
0
 def test_decimate(self):
     from atooms.system import Particle, System
     from atooms.system.particle import composition, decimate
     p = [Particle(species='A')] * 20 + [Particle(species='B')] * 10
     pnew = decimate(p, 12)
     x = composition(pnew)
     self.assertEqual(x['A'], 8)
     self.assertEqual(x['B'], 4)
Ejemplo n.º 5
0
 def read_sample(self, frame):
     cfg, box, pos, typ, vel = self.__read_one(self.__f_frames[frame])
     if vel is None:
         particle = [Particle(species=t, position=numpy.array(p)) for p, t in zip(pos, typ)]
     else:
         particle = [Particle(species=t, position=numpy.array(p), velocity=numpy.array(v))
                     for p, t, v in zip(pos, typ, vel)]
     cell = Cell(numpy.array(box))
     return System(particle, cell)
Ejemplo n.º 6
0
def dump_config(filename,
                pos=None,
                diam=None,
                ptypes=None,
                box=None,
                compress=None):
    file_ext = os.path.splitext(filename)[1]
    cell = Cell(side=box)
    npart = pos.shape[0]

    particles = []
    for i in range(npart):
        p = Particle(species=ptypes[i],
                     position=pos[i, :] - box / 2.,
                     radius=diam[i] / 2.)
        particles.append(p)

    system = System(particle=particles, cell=cell)

    with Trajectory(filename, "w") as traj:
        # Step is always 0 for now.
        traj.write(system, 0)

    if file_ext == ".xyz":
        compress = True
    else:
        compress = False

    if compress:
        subprocess.run(["gzip", "-f", filename])
Ejemplo n.º 7
0
 def particle(self):
     # Warning n.1 : this is read only. If you change the particles, the
     # modification won't be propoagated to the RUMD objects.
     # One would have to create a new system.
     #
     # Warning n.2 : it ia assumed that particles are sorted by species.
     # since RUMD does not have accessors to particle types (why??)
     # and we can only access the number of particles of a given type.
     npart = self.sample.GetNumberOfParticles()
     pos = self.sample.GetPositions()
     vel = self.sample.GetVelocities()
     nsp = self.sample.GetNumberOfTypes()
     ima = self.sample.GetImages()
     mass = self.__get_mass()
     spe = numpy.ndarray(npart, dtype=int)
     ii = 0
     for i in range(nsp):
         ni = self.sample.GetNumberThisType(i)
         spe[ii: ii + ni] = i
         ii += ni
     p = [Particle(species=spe_i, mass=mass_i, position=pos_i,
                   velocity=vel_i) for spe_i, mass_i, pos_i, vel_i
          in zip(spe, mass, pos, vel)]
     for pi, i in zip(p, ima):
         pi.periodic_image = i
     return p
Ejemplo n.º 8
0
    def read_sample(self, frame):
        """ returns System instance. """
        snap = self.trajectory[frame]
        ndim = snap.configuration.dimensions

        # Convert typeid from [0, 0, 1, ...] to ['A', 'A', 'B', ...] when snap.particles.types = ['A', 'B']
        distinct_species = snap.particles.types
        distinct_typeids = list(range(len(distinct_species)))
        typeid_to_species = {}
        for i in distinct_typeids:
            typeid_to_species[i] = distinct_species[i]

        box = snap.configuration.box[:
                                     ndim]  # atooms does not handle sheared boxes.
        cell = Cell(side=box)

        N = snap.particles.position.shape[0]
        particles = []
        for i in range(N):
            p = Particle(mass=snap.particles.mass[i],
                         species=typeid_to_species[snap.particles.typeid[i]],
                         position=snap.particles.position[i, :ndim],
                         velocity=snap.particles.velocity[i, :ndim],
                         radius=snap.particles.diameter[i] / 2)
            particles.append(p)

        return System(particle=particles, cell=cell)
Ejemplo n.º 9
0
    def test_dump_species(self):
        """
        Make sure that changing species in the dump is reflected in the
        particle species and viceversa.
        """
        import numpy
        from atooms.system import Particle, System

        view = True
        p = [Particle(), Particle()]
        s = System(p)
        spe = s.dump("particle.species", view=True)
        spe[0] = 'B'
        self.assertEqual(spe[0], s.particle[0].species)
        # With this syntax, the numpy scalar preserves the view!
        # We should upgrade species to property and hide this inside
        s.particle[0].species[()] = 'C'
        self.assertEqual(spe[0], s.particle[0].species)
Ejemplo n.º 10
0
 def setUp(self):
     N = 100
     L = 10.0
     self.ref = System()
     self.ref.cell = Cell([L, L, L])
     self.ref.particle = []
     self.ref.thermostat = Thermostat(1.0)
     self.ref.barostat = Barostat(1.0)
     self.ref.reservoir = Reservoir(1.0)
     while len(self.ref.particle) <= N:
         pos = [(random.random() - 0.5) * L, (random.random() - 0.5) * L,
                (random.random() - 0.5) * L]
         self.ref.particle.append(Particle(position=pos))
Ejemplo n.º 11
0
    def test_view_clear(self):
        import numpy
        from atooms.system import Particle, System

        p = [Particle(), Particle()]
        s = System(p)

        # We check that particle positions are views on dump array
        pos = s.dump("pos", order='F', view=True)
        self.assertTrue((p[0].position == pos[:, 0]).all())
        self.assertTrue(numpy.may_share_memory(p[0].position, pos[:, 0]))

        # We should get the same dump array
        pos = s.dump("pos", order='F', view=True)
        self.assertTrue((p[0].position == pos[:, 0]).all())
        self.assertTrue(numpy.may_share_memory(p[0].position, pos[:, 0]))

        # We clear the dump array
        pos1 = s.dump("pos", order='F', view=True, clear=True)
        pos1 += 1
        self.assertFalse((p[0].position == pos[:, 0]).all())
        self.assertFalse(numpy.may_share_memory(p[0].position, pos[:, 0]))
Ejemplo n.º 12
0
 def test_overlap_random(self):
     # This test may fail from time to time
     from atooms.system.particle import collective_overlap
     N = 1000
     L = 5.0
     sys = [System(), System()]
     sys[0].cell = Cell([L, L, L])
     sys[1].cell = Cell([L, L, L])
     sys[0].particle = []
     sys[1].particle = []
     for _ in range(N):
         pos = [(random.random() - 0.5) * L, (random.random() - 0.5) * L,
                (random.random() - 0.5) * L]
         sys[0].particle.append(Particle(position=pos))
     for _ in range(N):
         pos = [(random.random() - 0.5) * L, (random.random() - 0.5) * L,
                (random.random() - 0.5) * L]
         sys[1].particle.append(Particle(position=pos))
     a = 0.3
     q_rand = ((a**3 * 4. / 3 * 3.1415) * N / sys[0].cell.volume)
     self.assertTrue(
         abs(q_rand - collective_overlap(sys[0].particle, sys[1].particle,
                                         a, sys[0].cell.side)) < 0.5)
Ejemplo n.º 13
0
    def read_sample(self, frame):
        # Read metadata of this frame
        meta = self._read_comment(frame)

        # Get number of particles
        self.trajectory.seek(self._index_header[frame])
        npart = int(self.trajectory.readline())

        # Read frame now
        self.trajectory.seek(self._index_frame[frame])
        particle = []
        for ipart in range(npart):
            p = Particle()
            data = self.trajectory.readline().split()
            i = 0
            for key, fmt, ndims in meta['Properties']:
                ndims = int(ndims)
                if key in self.alias:
                    key = self.alias[key]
                if ndims == 1:
                    if fmt == 'R':
                        setattr(p, key, float(data[i]))
                    elif fmt == 'I':
                        setattr(p, key, int(data[i]))
                    elif fmt == 'S':
                        setattr(p, key, data[i])
                    else:
                        raise ValueError('unknown format key')
                else:
                    if fmt == 'R':
                        setattr(
                            p, key,
                            numpy.array(data[i:i + ndims],
                                        dtype=numpy.float64))
                    elif fmt == 'I':
                        setattr(
                            p, key,
                            numpy.array(data[i:i + ndims], dtype=numpy.int64))
                    elif fmt == 'S':
                        setattr(p, key, numpy.array(data[i:i + ndims]))
                    else:
                        raise ValueError('unknown format key')
                i += ndims
            particle.append(p)

        side = meta["Lattice"]
        # TODO: remove hard coded
        cell = Cell([side[0], side[4], side[8]])
        return System(particle, cell)
Ejemplo n.º 14
0
    def read_sample(self, frame):
        """ returns System instance. """

        L = self.header[0]
        if self.ndim == 3:
            cell = Cell(side=[L, L, L])
        elif self.ndim == 2:
            cell = Cell(side=[L, L])

        N = self.data.shape[0]
        pos = self.data[:, :self.ndim]
        # Lerner group format has positions from [0, 1).
        pos = pos*L - L/2

        if self.velocity_present:
            # Next is the velocity, if it exists.
            vel = self.data[:, self.ndim:2*self.ndim]

        # # In 2D, we add a zero z-coordinate to be consistent with other formats.
        # if self.ndim == 3:
        #     # First ndim columns are always the position.
        # elif self.ndim == 2:
        #     new_pos = np.zeros((N, 3)).astype(float)
        #     new_pos[:, :self.ndim] = pos
        #     pos = new_pos
        #     if self.velocity_present:
        #         vel = np.zeros((N, 3)).astype(float)
        #         vel[:, :self.ndim] = self.data[:, self.ndim:2*self.ndim]

        particles = []
        for i in range(N):
            p = Particle()
            p.position = pos[i, :]
            if self.velocity_present:
                p.velocity = vel[i, :]
            if self.species_present and self.radius_present:
                p.species = str( int(self.data[i, -1]) )
                p.radius  = self.data[i, -2]
            elif self.radius_present:
                p.radius = self.data[i, -1]
            elif self.species_present:
                p.species = str( int(self.data[i, -1]) )

            particles.append(p)

        return System(particle=particles, cell=cell)
Ejemplo n.º 15
0
 def test_ovito(self):
     try:
         import ovito
     except ImportError:
         self.skipTest('missing ovito')
     N = 3
     L = 5.0
     system = System()
     system.cell = Cell([L, L, L])
     system.particle = []
     for _ in range(N):
         pos = (numpy.random.random(len(system.cell.side)) -
                0.5) * system.cell.side
         p = Particle(position=pos)
         system.particle.append(p)
     image = system.show('ovito')
Ejemplo n.º 16
0
    def read_sample(self, frame):
        meta = self._read_comment(frame)
        self.trajectory.seek(self._index_frame[frame])

        # Read particles
        particle = []
        for _ in range(meta['npart']):
            data = self.trajectory.readline().strip().split()
            species = data[0]
            r = numpy.array(data[1:4], dtype=float)
            particle.append(Particle(species=species, position=r))

        # Read cell
        try:
            side = meta['cell']
            self._cell = Cell(side)
        except KeyError:
            pass

        return System(particle, self._cell)
Ejemplo n.º 17
0
def unfold(system):
    # s = system
    # particle = system.particle
    # for i, p in enumerate(particle):
    #     p.position += p.periodic_image * s.cell.side
    # system.particle = particle
    # return s
    from atooms.system import System
    npart = system.sample.GetNumberOfParticles()
    pos = system.sample.GetPositions()
    nsp = system.sample.GetNumberOfTypes()
    ima = system.sample.GetImages()
    spe = numpy.ndarray(npart, dtype=int)
    ii = 0
    for i in range(nsp):
        ni = system.sample.GetNumberThisType(i)
        spe[ii: ii + ni] = i
        ii += ni
    particle = [Particle(species=spe_i, position=pos_i) for spe_i, pos_i in
                zip(spe, pos)]
    for p, i in zip(particle, ima):
        p.position += i * system.cell.side

    return System(particle=particle, cell=system.cell)
Ejemplo n.º 18
0
    def read_sample(self, frame):
        # Setup fields again, in case they have changed
        if self.__cache_fields != self.fields:
            self._setup_fields()
        # Read metadata of this frame
        meta = self._read_comment(frame)
        # Define read callbacks list before reading lines
        callbacks_read = []

        def _skip(p, data, meta):
            return data[1:]

        for key in self.fields:
            # If the key is associated to a explicit callback, go
            # for it. Otherwise we throw the field in an particle
            # attribute named key. If the key is None it means we skip
            # this column.
            if key is None:
                callbacks_read.append(_skip)
            elif key in self.callback_read:
                callbacks_read.append(self.callback_read[key])
            else:
                # Trick. We instantiate dynamically a fallback function
                # to avoid adding `key` to the other callbacks' interface
                namespace = {}
                exec(
                    """
from atooms.core.utils import tipify
def fallback(p, data, meta):
    p.__dict__['%s'] = tipify(data[0])
    return data[1:]
""" % key, namespace)
                callbacks_read.append(namespace['fallback'])

        # Read frame now
        self.trajectory.seek(self._index_frame[frame])
        particle = []
        for i in range(meta['npart']):
            p = Particle()
            # Note: we cannot optimize by shifting an index instead of
            # cropping lists all the time
            data = self.trajectory.readline().split()
            for cbk in callbacks_read:
                data = cbk(p, data, meta)
            particle.append(p)

        # Fix the masses.
        # We assume masses read from the header are sorted by species name.
        # The mass metadata must be adjusted to the given frame.
        if 'mass' in meta:
            if isinstance(meta['mass'], list) or isinstance(
                    meta['mass'], tuple):
                species = distinct_species(particle)
                # We must have as many mass entries as species
                if len(species) != len(meta['mass']):
                    raise ValueError('mass metadata issue %s, %s' %
                                     (species, meta['mass']))
                db = {}
                for key, value in zip(species, meta['mass']):
                    db[key] = value
                for p in particle:
                    p.mass = float(db[p.species])
            else:
                for p in particle:
                    p.mass = float(meta['mass'])

        # Add cell info
        if 'cell' in meta:
            cell = Cell(meta['cell'])
        else:
            cell = None

        return System(particle, cell)
Ejemplo n.º 19
0
    def read_init(self):
        # read particles
        group = self.trajectory['/initialstate/particle']
        n = self.trajectory['/initialstate/particle/number_of_particles'][0]
        rad = None
        for entry in group:
            # TODO: refactor this
            if entry == 'element':
                spe = group[entry][:]
            if entry == 'mass':
                mas = group[entry][:]
            if entry == 'position':
                pos = group[entry][:]
            if entry == 'velocity':
                vel = group[entry][:]
            if entry == 'radius':
                rad = group[entry][:]
        if rad is not None:
            particle = [
                Particle(species=spe[i].decode().strip(),
                         mass=mas[i],
                         position=pos[i, :],
                         velocity=vel[i, :],
                         radius=rad[i]) for i in range(n)
            ]
        else:
            particle = [
                Particle(species=spe[i].decode().strip(),
                         mass=mas[i],
                         position=pos[i, :],
                         velocity=vel[i, :]) for i in range(n)
            ]

        # read cell
        group = self.trajectory['/initialstate/cell']
        for entry in group:
            if entry == 'sidebox':
                sidebox = group[entry][:]
        cell = Cell(sidebox)

        # read interaction
        interaction = self.read_interaction()

        # build system
        self._system = System(particle, cell, interaction)

        # read matrix
        if 'matrix' in self.trajectory['/initialstate']:
            group = self.trajectory['/initialstate/matrix']
            for entry in group:
                if entry == 'element':
                    spe = group[entry][:]
                if entry == 'mass':
                    mas = group[entry][:]
                if entry == 'position':
                    pos = group[entry][:]
            matrix = [
                Particle(species=spe[i].decode().strip(),
                         mass=mas[i],
                         position=pos[i, :]) for i in range(len(spe))
            ]
            self._system.matrix = copy.deepcopy(matrix)

        return self._system
Ejemplo n.º 20
0
    def read_sample(self, frame, unfolded=False):
        # TODO: due to unfolded argument this differs from the base class method Can we drop this?
        # We must increase frame by 1 if we iterate over frames with len().
        # This is some convention to be fixed once and for all
        # TODO: read cell on the fly NPT
        keys = list(self.trajectory['/trajectory/realtime/stepindex'].keys())
        csample = '/' + keys[frame]
        # read particles
        group = self.trajectory['/trajectory/particle']
        if unfolded:
            if 'position_unfolded' not in group:
                raise NotImplementedError(
                    'cannot unfold like this, use decorator instead')
            else:
                # fix for unfolded positions that were not written at the first step
                # should be fixed once and for all in md.x
                if frame == 0:
                    pos = self.trajectory['/initialstate/particle/position'][:]
                else:
                    pos = group['position_unfolded' + csample][:]
        else:
            pos = group['position' + csample][:]

        try:
            vel = group['velocity' + csample][:]
        except:
            vel = numpy.zeros([len(pos), ndim])

        # Dynamic properties
        p = []
        for r, v in zip(pos, vel):
            p.append(Particle(position=r, velocity=v))

        # Static properties
        # TODO: optimize, this takes quite some additional time, almost x2
        for pi, r in zip(p, self._system.particle):
            pi.mass = r.mass
            pi.species = r.species
            pi.radius = r.radius

        # Try update radii. This must be done after setting defaults.
        try:
            r = group['radius' + csample][:]
            for i, pi in enumerate(p):
                pi.radius = r[i]
            if 'radius' not in self.fields:
                self.fields.append('radius')
        except KeyError:
            if 'radius' in self.fields:
                self.fields.remove('radius')

        # Try update species. This must be done after setting defaults.
        # TODO: refactor
        try:
            spe = group['species' + csample][:]
            for i, pi in enumerate(p):
                pi.species = spe[i].decode().strip()
            if 'species' not in self.fields:
                self.fields.append('species')
        except KeyError:
            if 'species' in self.fields:
                self.fields.remove('species')

        # Read cell
        group = self.trajectory['/trajectory/cell']
        side = group['sidebox' + csample][:]
        # This fixes an issue with some hdf5 trajectories that stored
        # cell as (1,3) array
        if len(side.shape) == 2:
            side = side[0]
        self._system.cell.side = side

        # Read also interaction.
        has_int = True
        try:
            group = self.trajectory['/trajectory/interaction']
        except:
            has_int = False

        if has_int:
            self._system.interaction.total_energy = group['energy' +
                                                          csample][0]
            self._system.interaction.total_virial = group['virial' +
                                                          csample][0]
            self._system.interaction.total_stress = group['stress' +
                                                          csample][:]

        return System(p, self._system.cell, self._system.interaction)