def qt(input_file, tmax=-1.0, tmax_fraction=0.75, tsamples=60, func='logx', *input_files, **global_args): """Collective overlap correlation function""" global_args = _compat(global_args) func = _func_db[func] for th in _get_trajectories([input_file] + list(input_files), global_args): if tmax > 0: t_grid = [0.0] + func(th.timestep, tmax, tsamples) elif tmax_fraction > 0: t_grid = [0.0] + func(th.timestep, tmax_fraction * th.total_time, tsamples) else: t_grid = None pp.CollectiveOverlap( th, t_grid, norigins=global_args['norigins']).do(update=global_args['update']) ids = distinct_species(th[0].particle) if len(ids) > 1: Partial(pp.CollectiveOverlap, ids, th, t_grid, norigins=global_args['norigins']).do( update=global_args['update'])
def _default_rcut(th): """ Look for the first minimum in the partial g(r) """ from atooms.system.particle import distinct_species from atooms.postprocessing.partial import Partial from atooms.postprocessing import RadialDistributionFunction from .helpers import ifabsmm ids = distinct_species(th[0].particle) gr = Partial(RadialDistributionFunction, ids, th, dr=0.1) gr.do(update=False) rcut = {} for isp in ids: for jsp in ids: # First find absolute maximum _, m = ifabsmm(list(gr.partial[(isp, jsp)].grid), list(gr.partial[(isp, jsp)].value)) # Then look for first minimum after the maximum for i in range(len(gr.partial[(isp, jsp)].grid)): if gr.partial[(isp, jsp)].grid[i] >= m[0]: delta = gr.partial[(isp, jsp)].value[i+1] - gr.partial[(isp, jsp)].value[i] if delta >= 0: rcut[(isp, jsp)] = gr.partial[(isp, jsp)].grid[i] break return rcut
def vacf(input_file, tmax=-1.0, tmax_fraction=0.10, tsamples=30, func='linear', *input_files, **global_args): """Velocity autocorrelation function""" global_args = _compat(global_args) func = _func_db[func] for th in _get_trajectories([input_file] + list(input_files), global_args): if tmax > 0: t_grid = [0.0] + func(th.timestep, min(th.total_time, tmax), tsamples) elif tmax_fraction > 0: t_grid = [0.0] + func(th.timestep, tmax_fraction * th.total_time, tsamples) else: t_grid = None pp.VelocityAutocorrelation( th, t_grid, norigins=global_args['norigins']).do(update=global_args['update']) ids = distinct_species(th[0].particle) if len(ids) > 1: Partial(pp.VelocityAutocorrelation, ids, th, t_grid, norigins=global_args['norigins']).do( update=global_args['update'])
def alpha2(input_file, tmax=-1.0, tmax_fraction=0.75, tsamples=60, func='logx', *input_files, **global_args): """Non-Gaussian parameter""" global_args = _compat(global_args) func = _func_db[func] for th in _get_trajectories([input_file] + list(input_files), global_args): if tmax > 0: t_grid = [0.0] + func(th.timestep, tmax, tsamples) elif tmax_fraction > 0: t_grid = [0.0] + func(th.timestep, tmax_fraction * th.total_time, tsamples) else: t_grid = None pp.NonGaussianParameter( th, t_grid, norigins=global_args['norigins']).do(update=global_args['update']) ids = distinct_species(th[0].particle) if len(ids) > 1: Partial(pp.NonGaussianParameter, ids, th, t_grid, norigins=global_args['norigins']).do( update=global_args['update'])
def _setup_arrays_onebody(self): """ Setup list of numpy arrays for one-body correlations. We also take care of dumping the weight if needed, see `add_weight()`. """ if 'pos' in self.phasespace or 'vel' in self.phasespace or 'ids' in self.phasespace: ids = distinct_species(self.trajectory[0].particle) for s in progress(self.trajectory): # Apply filter if there is one if len(self._cbk) > 0: s = self._cbk[0](s, *self._cbk_args[0], **self._cbk_kwargs[0]) if 'pos' in self.phasespace: self._pos.append(s.dump('pos')) if 'vel' in self.phasespace: self._vel.append(s.dump('vel')) if 'ids' in self.phasespace: _ids = s.dump('species') _ids = numpy.array([ids.index(_) for _ in _ids], dtype=numpy.int32) self._ids.append(_ids) # Dump unfolded positions if requested if 'pos-unf' in self.phasespace: if self._unfolded is None: self._unfolded = Unfolded(self.trajectory, fixed_cm=self._fix_cm) for s in progress(self._unfolded): # Apply filter if there is one if len(self._cbk) > 0: s = self._cbk[0](s, *self._cbk_args[0], **self._cbk_kwargs[0]) self._pos_unf.append(s.dump('pos'))
def gr(input_file, dr=0.04, grandcanonical=False, ndim=-1, rmax=-1.0, *input_files, **global_args): """Radial distribution function""" global_args = _compat(global_args) if global_args['legacy']: backend = pp.RadialDistributionFunctionLegacy else: backend = pp.RadialDistributionFunction for th in _get_trajectories([input_file] + list(input_files), global_args): th._grandcanonical = grandcanonical cf = backend(th, dr=dr, rmax=rmax, norigins=global_args['norigins'], ndim=ndim) if global_args['filter'] is not None: cf = pp.Filter(cf, global_args['filter']) cf.do(update=global_args['update']) ids = distinct_species(th[0].particle) if len(ids) > 1 and not global_args['no_partial']: cf = Partial(backend, ids, th, dr=dr, rmax=rmax, norigins=global_args['norigins'], ndim=ndim) cf.do(update=global_args['update'])
def sk(input_file, nk=20, dk=0.1, kmin=-1.0, kmax=15.0, ksamples=30, kgrid=None, weight=None, weight_trajectory=None, weight_fluctuations=False, *input_files, **global_args): """ Structure factor """ from atooms.trajectory import TrajectoryXYZ global_args = _compat(global_args) if global_args['fast']: backend = pp.StructureFactorFast else: backend = pp.StructureFactorLegacy if kgrid is not None: kgrid = [float(_) for _ in kgrid.split(',')] for th in _get_trajectories([input_file] + list(input_files), global_args): cf = backend(th, kgrid=kgrid, norigins=global_args['norigins'], kmin=kmin, kmax=kmax, nk=nk, dk=dk, ksamples=ksamples) if global_args['filter'] is not None: cf = pp.Filter(cf, global_args['filter']) if weight_trajectory is not None: weight_trajectory = TrajectoryXYZ(weight_trajectory) cf.add_weight(trajectory=weight_trajectory, field=weight, fluctuations=weight_fluctuations) cf.do(update=global_args['update']) ids = distinct_species(th[0].particle) if len(ids) > 1 and not global_args['no_partial']: cf = Partial(backend, ids, th, kgrid=kgrid, norigins=global_args['norigins'], kmin=kmin, kmax=kmax, nk=nk, dk=dk, ksamples=ksamples) cf.add_weight(trajectory=weight_trajectory, field=weight, fluctuations=weight_fluctuations) cf.do(update=global_args['update'])
def write_sample(self, system, step): self.trajectory.create_group_safe('/trajectory') self.trajectory.create_group_safe('/trajectory/realtime') self.trajectory.create_group_safe('/trajectory/realtime/stepindex') self.trajectory.create_group_safe('/trajectory/realtime/sampleindex') frame = len(self.steps) + 1 csample = '/sample_%7.7i' % frame try: self.trajectory['/trajectory/realtime/stepindex' + csample] = [step] self.trajectory['/trajectory/realtime/sampleindex' + csample] = [frame] except RuntimeError: _log.error('error when writing step %s sample %s to file %s', step, frame, self.filename) raise if system.particle is not None: self.trajectory.create_group_safe('/trajectory/particle') if 'position' in self.fields: self.trajectory.create_group_safe( '/trajectory/particle/position') self.trajectory['/trajectory/particle/position' + csample] = [ p.position for p in system.particle ] if 'velocity' in self.fields: self.trajectory['/trajectory/particle/velocity' + csample] = [ p.velocity for p in system.particle ] self.trajectory.create_group_safe( '/trajectory/particle/velocity') if 'radius' in self.fields: self.trajectory.create_group_safe( '/trajectory/particle/radius') self.trajectory['/trajectory/particle/radius' + csample] = [p.radius for p in system.particle] if 'species' in self.fields: self.trajectory.create_group_safe( '/trajectory/particle/species') data = ['%-3s' % p.species for p in system.particle] self.trajectory['/trajectory/particle/species' + csample] = [_.encode() for _ in data] from atooms.system.particle import distinct_species ids = distinct_species(system.particle) self.trajectory['/trajectory/particle/ids' + csample] = [ 1 + ids.index(p.species) for p in system.particle ] if system.cell is not None: self.trajectory.create_group_safe('/trajectory/cell') if 'cell' in self.fields: self.trajectory.create_group_safe('/trajectory/cell/sidebox') self.trajectory['/trajectory/cell/sidebox' + csample] = system.cell.side
def fskt(input_file, tmax=-1.0, tmax_fraction=0.75, tsamples=60, kmin=7.0, kmax=8.0, ksamples=1, dk=0.1, nk=8, kgrid=None, func='logx', total=False, fix_cm=False, lookup_mb=64.0, *input_files, **global_args): """Self intermediate scattering function""" global_args = _compat(global_args) func = _func_db[func] if global_args['legacy']: backend = pp.SelfIntermediateScatteringLegacy else: backend = pp.SelfIntermediateScattering for th in _get_trajectories([input_file] + list(input_files), global_args): if tmax > 0: t_grid = [0.0] + func(th.timestep, tmax, tsamples) elif tmax_fraction > 0: t_grid = [0.0] + func(th.timestep, tmax_fraction * th.total_time, tsamples) else: t_grid = None if kgrid is not None: k_grid = [float(_) for _ in kgrid.split(',')] else: k_grid = linear_grid(kmin, kmax, ksamples) if total: backend(th, k_grid, t_grid, nk, dk=dk, norigins=global_args['norigins'], fix_cm=fix_cm, lookup_mb=lookup_mb).do(update=global_args['update']) ids = distinct_species(th[0].particle) if len(ids) > 1: Partial(backend, ids, th, k_grid, t_grid, nk, dk=dk, norigins=global_args['norigins'], fix_cm=fix_cm, lookup_mb=lookup_mb).do(update=global_args['update'])
def test_species(self): system = copy.copy(self.ref) npart = len(system.particle) for p in system.particle[0:10]: p.species = 'B' for p in system.particle[10:30]: p.species = 'C' from atooms.system.particle import composition, distinct_species self.assertEqual(distinct_species(system.particle), ['A', 'B', 'C']) self.assertEqual(system.distinct_species(), ['A', 'B', 'C']) self.assertEqual(composition(system.particle)['A'], npart - 30) self.assertEqual(composition(system.particle)['B'], 10) self.assertEqual(composition(system.particle)['C'], 20)
def _compute(self): from atooms.trajectory.decorators import change_species from atooms.postprocessing.realspace_wrap import compute from atooms.system.particle import distinct_species hist_all = [] hist_one = numpy.ndarray(len(self.grid), dtype=numpy.int32) origins = range(0, len(self.trajectory), self.skip) dtheta = self.grid[1] - self.grid[0] # Setup array of cutoff distances based on g(r) calculated for # the whole trajectory. # We store the cutoffs into a (nsp, nsp) array # where the index follows the alphabetic order of species names if self.rcut is None: rcut = _default_rcut(self.trajectory) ids = distinct_species(self.trajectory[0].particle) self.rcut = numpy.ndarray((len(ids), len(ids))) for species_pair in rcut: self.rcut[ids.index(species_pair[0]), ids.index(species_pair[1])] = rcut[species_pair] for isp in range(len(ids)): for jsp in range(len(ids)): self.analysis['cutoff distance {}-{}'.format(isp, jsp)] = self.rcut[isp, jsp] for i in progress(origins): system = self.trajectory[i] side = system.cell.side # this should not be affected by filters #system = change_species(system, 'F') # species are in fortran style #ids = numpy.array(system.dump('spe'), dtype=numpy.int32) nn = numpy.array(0, dtype=numpy.int32) neighbors = numpy.ndarray(50, dtype=numpy.int32) for idx in range(len(self._pos_0[i])): isp = self._ids_0[i][idx] compute.neighbors('C', side, self._pos_0[i][idx], self._pos_1[i].transpose(), self._ids_1[i], self.rcut[isp, :], nn, neighbors) #print idx, self._pos_1[i].shape, neighbors[0: nn], set(self._ids_1[i]) compute.bond_angle(self._pos_0[i][idx, :], self._pos_1[i].transpose(), neighbors[0: nn], side, dtheta, hist_one) hist_all.append(hist_one.copy()) # Normalization hist = numpy.sum(hist_all, axis=0) norm = float(numpy.sum(hist[:-1])) self.grid = (numpy.array(self.grid[:-1]) + numpy.array(self.grid[1:])) / 2.0 self.value = hist[:-1] / (norm * dtheta)
def write_sample(self, system, step): self._setup_format() sp = distinct_species(system.particle) self.trajectory.write("%d\n" % len(system.particle)) self.trajectory.write(self._comment(step, system)) ndim = len(system.particle[0].position) for p in system.particle: # We get the integer index corresponding to species Ex.: # if species are 'A', 'B' we get 0 and 1. Note that in # general getting the sample back via read_sample() will # not preserve the species. isp = sp.index(p.species) self.trajectory.write("{0} {1.position} {1.velocity}\n".format( isp, p))
def write_sample(self, system, step): sp = distinct_species(system.particle) self.trajectory.write("%d\n" % len(system.particle)) self.trajectory.write(self._comment(step, system)) ndim = len(system.particle[0].position) for p in system.particle: # We get the integer index corresponding to species Ex.: # if species are 'A', 'B' we get 0 and 1. Note that in # general getting the sample back via read_sample() will # not preserve the species. isp = sp.index(p.species) self.trajectory.write( ("%s" + ndim * " %.6f" + ndim * " %.6f " + "\n") % ((isp, ) + tuple(p.position) + tuple(p.velocity)))
def write_init(self, system): f = open(self.filename + '.inp', 'w') np = len(system.particle) L = system.cell.side species_db = distinct_species(system.particle) # LAMMPS header h = '\n' h += "{:d} atoms\n".format(np) h += "{:d} atom types\n".format(len(species_db)) h += "{:.{prec}f} {:.{prec}f} xlo xhi\n".format(-L[0] / 2, L[0] / 2, prec=self.precision) h += "{:.{prec}f} {:.{prec}f} ylo yhi\n".format(-L[1] / 2, L[1] / 2, prec=self.precision) h += "{:.{prec}f} {:.{prec}f} zlo zhi\n".format(-L[2] / 2, L[2] / 2, prec=self.precision) # LAMMPS body # Masses of species m = "\nMasses\n\n" for isp in range(len(species_db)): # Iterate over particles. Find instances of species and get masses for p in system.particle: if p.species == species_db[isp]: m += '{:d} {:{prec}f}\n'.format(isp + 1, p.mass, prec=self.precision) break # Atom coordinates r = "\nAtoms\n\n" v = "\nVelocities\n\n" for i, p in enumerate(system.particle): isp = species_db.index(p.species) + 1 r += '{:d} {:d} {:{prec}} {:{prec}} {:{prec}}\n'.format( i + 1, isp, *p.position, prec=self.precision) v += '{:d} {:{prec}} {:{prec}} {:{prec}}\n'.format( i + 1, *p.velocity, prec=self.precision) f.write(h) f.write(m) f.write(r) f.write(v) f.close()
def _comment(self, step, system): def first_of_species(system, species): for i, p in enumerate(system.particle): if p.species == species: return i raise ValueError('no species %d found in system' % species) sp = distinct_species(system.particle) mass = [ system.particle[first_of_species(system, isp)].mass for isp in sp ] hdr = 'ioformat=1 dt=%g timeStepIndex=%d boxLengths=' + \ '%.12f,%.12f,%.12f' + \ ' numTypes=%d mass=' + '%g,'*(len(sp)) + \ ' columns=type,x,y,z,vx,vy,vz\n' return hdr % tuple([self.timestep, step] + list(system.cell.side) + [len(sp)] + mass)
def _setup_arrays_twobody(self): """Setup list of numpy arrays for two-body correlations.""" if len(self._cbk) <= 1: self._setup_arrays_onebody() self._pos_0 = self._pos self._pos_1 = self._pos self._vel_0 = self._vel self._vel_1 = self._vel self._ids_0 = self._ids self._ids_1 = self._ids return if 'pos' in self.phasespace or 'vel' in self.phasespace or 'ids' in self.phasespace: ids = distinct_species(self.trajectory[0].particle) for s in progress(self.trajectory): s0 = self._cbk[0](s, *self._cbk_args[0], **self._cbk_kwargs[0]) s1 = self._cbk[1](s, *self._cbk_args[1], **self._cbk_kwargs[1]) if 'pos' in self.phasespace: self._pos_0.append(s0.dump('pos')) self._pos_1.append(s1.dump('pos')) if 'vel' in self.phasespace: self._vel_0.append(s0.dump('vel')) self._vel_1.append(s1.dump('vel')) if 'ids' in self.phasespace: _ids_0 = s0.dump('species') _ids_1 = s1.dump('species') _ids_0 = numpy.array([ids.index(_) for _ in _ids_0], dtype=numpy.int32) _ids_1 = numpy.array([ids.index(_) for _ in _ids_1], dtype=numpy.int32) self._ids_0.append(_ids_0) self._ids_1.append(_ids_1) # Dump unfolded positions if requested if 'pos-unf' in self.phasespace: for s in progress(Unfolded(self.trajectory)): s0 = self._cbk[0](s, *self._cbk_args[0], **self._cbk_kwargs[0]) s1 = self._cbk[1](s, *self._cbk_args[1], **self._cbk_kwargs[1]) self._pos_unf_0.append(s0.dump('pos')) self._pos_unf_1.append(s1.dump('pos'))
def fkt(input_file, tmax=-1.0, tmax_fraction=0.75, tsamples=60, kmin=7.0, kmax=7.0, ksamples=1, dk=0.1, nk=100, kgrid=None, func='logx', fix_cm=False, *input_files, **global_args): """Total intermediate scattering function""" global_args = _compat(global_args) func = _func_db[func] for th in _get_trajectories([input_file] + list(input_files), global_args): if tmax > 0: t_grid = [0.0] + func(th.timestep, tmax, tsamples) elif tmax_fraction > 0: t_grid = [0.0] + func(th.timestep, tmax_fraction * th.total_time, tsamples) else: t_grid = None if kgrid is not None: k_grid = [float(_) for _ in kgrid.split(',')] else: k_grid = linear_grid(kmin, kmax, ksamples) ids = distinct_species(th[0].particle) if len(ids) > 1: Partial(pp.IntermediateScattering, ids, th, k_grid, t_grid, norigins=global_args['norigins'], nk=nk, dk=dk, fix_cm=fix_cm).do(update=global_args['update'])
def chi4qs(input_file, tsamples=60, a=0.3, tmax=-1.0, func='logx', tmax_fraction=0.75, total=False, *input_files, **global_args): """Dynamic susceptibility of self overlap""" global_args = _compat(global_args) func = _func_db[func] if global_args['fast']: backend = pp.Chi4SelfOverlapOpti else: backend = pp.Chi4SelfOverlap for th in _get_trajectories([input_file] + list(input_files), global_args): if tmax > 0: t_grid = [0.0] + func(th.timestep, min(th.total_time, tmax), tsamples) elif tmax_fraction > 0: t_grid = [0.0] + func(th.timestep, tmax_fraction * th.total_time, tsamples) else: t_grid = None if total: backend(th, t_grid, a=a, norigins=global_args['norigins']).do( update=global_args['update']) ids = distinct_species(th[0].particle) if not total and len(ids) > 1: Partial(backend, ids, th, t_grid, a=a, norigins=global_args['norigins']).do( update=global_args['update'])
def msd(input_file, tmax=-1.0, tmax_fraction=0.75, tsamples=30, sigma=1.0, func='linear', rmsd_max=-1.0, fix_cm=False, *input_files, **global_args): """Mean square displacement""" func = _func_db[func] global_args = _compat(global_args) for th in _get_trajectories([input_file] + list(input_files), global_args): dt = th.timestep if tmax > 0: t_grid = [0.0] + func(dt, min(th.total_time, tmax), tsamples) elif tmax_fraction > 0: t_grid = [0.0] + func(dt, tmax_fraction * th.total_time, tsamples) else: t_grid = None ids = distinct_species(th[0].particle) pp.MeanSquareDisplacement( th, tgrid=t_grid, norigins=global_args['norigins'], sigma=sigma, rmax=rmsd_max, fix_cm=fix_cm).do(update=global_args['update']) if len(ids) > 1: Partial(pp.MeanSquareDisplacement, ids, th, tgrid=t_grid, norigins=global_args['norigins'], sigma=sigma, rmax=rmsd_max).do(update=global_args['update'])
def change_species(system, layout): """ Return a modified `system` with particle species changed according to `layout`. The possible values of `layout` are: - 'A': alphabetic, i.e. species are strings like 'A', 'B', ... - 'C': C-like, i.e. species are integers starting from 0 - 'F': F-like, i.e. species are integers starting from 1 If the current layout already matches the requested one, the system is returned unchanged. """ if layout not in ['A', 'C', 'F']: raise ValueError('species layout must be A, C, or F (not %s)' % layout) # Detect species layout (A=alphabetic, C=C style, F=fortran style) try: species = [int(p.species) for p in system.particle] except ValueError: # The species cannot be converted to int, thus layout is # alphabetical current_layout = 'A' else: min_sp = numpy.min(species) if min_sp == 0: current_layout = 'C' elif min_sp == 1: current_layout = 'F' else: raise ValueError('Numeric species should start from 0 or 1') # Do nothing if the layout is already ok if layout == current_layout: return system # Convert to new layout import string if layout == 'A': # We get the index of the species map: # - if current layout is F (min_sp=1), we subtract one. # - if current layout is C (min_sp=0), we do nothing species_map = string.ascii_uppercase for p in system.particle: p.species = species_map[int(p.species) - min_sp] else: # Output layout is numerical (C or F) from atooms.system.particle import distinct_species offset = 1 if layout == 'F' else 0 # Note that distinct_species is sorted alphabetically species_list = distinct_species(system.particle) if current_layout == 'A': for p in system.particle: p.species = str(species_list.index(p.species) + offset) else: # If layout=C, current_layout is F and we subtract 2*offset-1=-1 # If layout=F, current_layout is C and we add 2*offset-1=+1 for p in system.particle: p.species = str(int(p.species) + 2 * offset - 1) return system
def info(trajectory, keys=None): """Return a string with information about a `trajectory` instance.""" from atooms.system.particle import distinct_species, composition system = trajectory[0] if keys is None: # Default: full info txt = '' txt += 'path = %s\n' % trajectory.filename txt += 'format = %s\n' % trajectory.__class__ txt += 'frames = %s\n' % len(trajectory) txt += 'megabytes = %s\n' % ( os.path.getsize(trajectory.filename) / 1e6) txt += 'particles = %s\n' % len(system.particle) txt += 'species = %s\n' % ', '.join( distinct_species(system.particle)) txt += 'composition = %s\n' % dict( composition(system.particle)) txt += 'size dispersion = %s\n' % ( numpy.std([p.radius for p in system.particle]) / numpy.mean([p.radius for p in system.particle])) txt += 'density = %s\n' % round(system.density, 10) if system.cell is not None: txt += 'cell side = %s\n' % str(list( system.cell.side))[1:-1] txt += 'cell volume = %s\n' % system.cell.volume if len(trajectory) > 1: txt += 'steps = %s\n' % trajectory.steps[-1] txt += 'duration = %s\n' % trajectory.times[-1] txt += 'timestep = %s\n' % trajectory.timestep txt += 'block size = %s\n' % trajectory.block_size if trajectory.block_size == 1: txt += 'steps between frames = %s\n' % (trajectory.steps[1] - trajectory.steps[0]) txt += 'time between frames = %s\n' % (trajectory.times[1] - trajectory.times[0]) else: txt += 'block steps = %s\n' % trajectory.steps[ trajectory.block_size - 1] txt += 'block = %s\n' % ([ trajectory.steps[i] for i in range(trajectory.block_size) ]) txt += 'grandcanonical = %s' % trajectory.grandcanonical return txt else: # Selected infos. # TODO: of course, it would be cleaner to have a little class for that outs = [] for key in keys.split(','): if key == 'path': outs.append(trajectory.filename) elif key == 'format': outs.append(trajectory.__class__) elif key == 'frames': outs.append(len(trajectory)) elif key == 'megabytes': outs.append(os.path.getsize(trajectory.filename) / 1e6) elif key == 'particles': outs.append(len(system.particle)) elif key == 'species': outs.append(', '.join(distinct_species(system.particle))) elif key == 'composition': outs.append(dict(composition(system.particle))) elif key == 'cell density': outs.append(round(system.density, 10)) elif key == 'cell side': outs.append(str(list(system.cell.side))[1:-1]) elif key == 'cell volume': outs.append(system.cell.volume) elif key == 'steps': outs.append(trajectory.steps[-1]) elif key == 'duration': outs.append(trajectory.times[-1]) elif key == 'timestep': outs.append(trajectory.timestep) elif key == 'block size': outs.append(trajectory.block_size) elif key == 'steps between frames': outs.append(trajectory.steps[1] - trajectory.steps[0]) elif key == 'time between frames': outs.append(trajectory.times[1] - trajectory.times[0]) elif key == 'block steps': outs.append(trajectory.steps[trajectory.block_size - 1]) elif key == 'block': outs.append([ trajectory.steps[i] for i in range(trajectory.block_size) ]) elif key == 'grandcanonical': outs.append(trajectory.grandcanonical) txt = '' fmt = '%%-%ds : %%s\n' % (max([len(key) for key in keys.split(',')])) for key, out in zip(keys.split(','), outs): txt += fmt % (key, out) return txt.strip('\n')
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)
def write_init(self, system): from atooms.system.particle import distinct_species self.trajectory.create_group_safe('/initialstate') self.trajectory['DIMENSIONS'] = [3] self.trajectory['NAME_SYS'] = [b'Unknown'] self.trajectory['VERSION_TRJ'] = [b'1.2'] self.trajectory['VERSION_MD'] = [b'X.X.X'] # Particles group = '/initialstate/particle/' if system.particle is not None: self.trajectory.create_group_safe(group) particle = system.particle species = distinct_species(particle) particle_h5 = { 'number_of_species': [len(species)], 'number_of_particles': [len(particle)], 'identity': [species.index(p.species) + 1 for p in particle], 'element': [p.species.encode() for p in particle], 'mass': [p.mass for p in particle], 'radius': [p.radius for p in particle], 'position': [p.position for p in particle], 'velocity': [p.velocity for p in particle], } _write_datasets(self.trajectory, group, particle_h5) # Matrix group = '/initialstate/matrix/' if system.matrix is not None: self.trajectory.create_group_safe(group) matrix = system.matrix species = distinct_species(matrix) matrix_h5 = { 'type': [b''], 'id': [0], 'number_of_species': [len(species)], 'number_of_particles': [len(matrix)], 'identity': [species.index(p.species) + 1 for p in matrix], 'element': [p.species.encode() for p in matrix], 'mass': [p.mass for p in matrix], 'position': [p.position for p in matrix], } _write_datasets(self.trajectory, group, matrix_h5) # Cell group = '/initialstate/cell/' if system.cell is not None: self.trajectory.create_group_safe(group) self.trajectory[group + 'sidebox'] = system.cell.side # Thermostat group = '/initialstate/thermostat/' if system.thermostat is not None: self.trajectory.create_group_safe(group) self.trajectory[group + 'temperature'] = system.thermostat.temperature self.trajectory[group + 'type'] = system.thermostat.name self.trajectory[group + 'mass'] = system.thermostat.mass self.trajectory[ group + 'collision_period'] = system.thermostat.collision_period # Interaction if system.interaction is not None: if type(system.interaction) is list: raise TypeError('interaction must be list') self.trajectory.copy(system.interaction, '/initialstate/interaction/')