Example #1
0
    def __getitem__(self, i):
        if not self.initialised:
            if self is self.parent.hysteretic_connect:
                self.calc_connect_hysteretic(self.parent)
            else:
                self.calc_connect(self.parent)

        distance = farray(0.0)
        diff = fzeros(3)
        cosines = fzeros(3)
        shift = fzeros(3, dtype=np.int32)

        res = []
        if not get_fortran_indexing():
            i = i + 1  # convert to 1-based indexing

        for n in frange(self.n_neighbours(i)):
            j = self.neighbour(self.parent, i, n, distance, diff, cosines,
                               shift)
            if not get_fortran_indexing():
                j = j - 1
            res.append(NeighbourInfo(j, distance, diff, cosines, shift))

        if get_fortran_indexing():
            res = farray(res)  # to give 1-based indexing
        return res
Example #2
0
    def select(self, mask=None, list=None, orig_index=True):
        """Return a new :class:`Atoms` containing a subset of the atoms in this Atoms object

        One of either `mask` or `list` should be present.  If `mask`
        is given it should be a rank one array of length `self.n`. In
        this case atoms corresponding to true values in `mask` will be
        included in the result.  If `list` is present it should be an
        arry of list containing atom indices to include in the result.

        If `orig_index` is True (default), the new object will contain
        an ``orig_index`` property mapping the indices of the new atoms
        back to the original larger Atoms object.
        """
        if mask is not None:
            mask = farray(mask)
            out = self.__class__(n=mask.sum(),
                                 lattice=self.lattice,
                                 properties={},
                                 params={})
            _atoms.Atoms.select(out, self, mask=mask, orig_index=orig_index)
        elif list is not None:
            list = farray(list)
            out = self.__class__(n=len(list), lattice=self.lattice)
            _atoms.Atoms.select(out, self, list=list, orig_index=orig_index)
        else:
            raise ValueError('Either mask or list must be present.')
        return out
Example #3
0
def apply_cp2k_sort_order(at, rev_sort_index_filename='quip_rev_sort_index'):
    """Reorder atoms in `at` so that they match rev_sort_index read from file.

       Returns sort_index and rev_sort_index arrays."""

    fields = [int(x) for x in open(rev_sort_index_filename).read().split()]
    rev_sort_index = farray(fields, dtype=np.int32)
    rev_sort_index_copy = rev_sort_index.copy()
    sort_index = farray(frange(at.n), dtype=np.int32)
    insertion_sort(rev_sort_index_copy, sort_index)
    at.add_property('rev_sort_index', rev_sort_index)
    at.sort('rev_sort_index')

    return sort_index, rev_sort_index
Example #4
0
    def add_thermostat(self,
                       type,
                       T,
                       gamma=None,
                       Q=None,
                       tau=None,
                       tau_cell=None,
                       p=None,
                       NHL_tau=None,
                       NHL_mu=None,
                       massive=None):
        """
        Add a new thermostat to this Dynamics, and return its index.

        By default, all thermostats apply to the whole system. The
        'thermostat_region' property can be used to control which
        thermostats affect which atoms. It should be set to the index
        of the required thermostat for each atom.

        :param type: string or integer giving thermostat type. The following types are supported::
           ``THERMOSTAT_NONE``, ``THERMOSTAT_LANGEVIN``, ``THERMOSTAT_NOSE_HOOVER``, ``THERMOSTAT_NOSE_HOOVER_LANGEVIN``,
           ``THERMOSTAT_LANGEVIN_NPT``, ``THERMOSTAT_LANGEVIN_PR``, ``THERMOSTAT_NPH_ANDERSEN``, ``THERMOSTAT_NPH_PR``,
           ``THERMOSTAT_LANGEVIN_OU``, ``THERMOSTAT_LANGEVIN_NPT_NB``.
                   
        :param T:  target temperature for this thermostat, in K.

        :param gamma: decay constant, in units  of 1/fs

        :param tau:  time constant, in units of fs. tau == 1/gamma, and
                     only one of the two should be specified.

        :param tau_cell: time constant for the cell degrees of freedom
                         (for variable cell thermostats only).

        :param p:   target pressure (for variable cell thermostats)
                 
        :param NHL_tau:  time constant for Nose-Hoover-Langevein thermostats
                 
        :param NHL_mu:   thermostat mass Nose-Hoover-Langevin thermostats
                 
        :param massive:  set to True to enable massive Nose-Hoover-Langevin
        """

        type = _thermostat_types.get(type, type)
        new_index = self._ds.n_thermostat()
        region_i = farray(0, dtype=np.int32)

        self._ds.add_thermostat(type,
                                T,
                                gamma,
                                Q,
                                tau,
                                tau_cell,
                                p,
                                NHL_tau,
                                NHL_mu,
                                massive,
                                region_i=region_i)
        assert (new_index == int(region_i))
        return new_index
Example #5
0
def find_mapping(at_in, vectors, lattice_constant, tol=1e-4):
   """
   Find a mapping between pairs of atoms displaced by a given vector
   (or by one of a number of given vectors).
   """

   class FoundMapping:
      pass

   mapping = fzeros(at_in.n, dtype=np.int32)
   at = at_in.copy()

   # cutoff should be larger than all displacment vectors
   vlen = [farray(vector).norm()*lattice_constant for vector in vectors]
   at.set_cutoff(max(vlen)+0.5)
   print 'cutoff = ', at.cutoff
   at.calc_connect()

   for i in at.indices:
      try:
         for neighb in at.neighbours[i]:
            for vector in vectors:
               if ((neighb.diff/lattice_constant - vector)**2).sum() < tol:
                  print i, neighb.j, vector
                  mapping[i] = neighb.j
                  raise FoundMapping

         # corresponding atom is off the edge, so map atom onto itself
         print i, 'not found!'
         mapping[i] = i
      except FoundMapping:
         continue

   return mapping
Example #6
0
def get_bond_lengths(at):
    """Return a dictionary mapping tuples (Species1, Species2) to an farray of bond-lengths"""
    at.calc_connect()
    r_ij = farray(0.0)
    res = {}
    for i in frange(at.n):
        for n in frange(at.n_neighbours(i)):
            j = at.neighbour(i, n, distance=r_ij)
            print i, j, at.z[i], at.z[j], r_ij
            minij, maxij = min((i, j)), max((i, j))
            key = (at.species[minij].stripstrings(),
                   at.species[maxij].stripstrings())
            if not key in res: res[key] = []
            res[key].append(r_ij.astype(float))
    print res
    return dict((k, farray(v)) for (k, v) in res.iteritems())
Example #7
0
    def _indices(self):
        """Return array of atoms indices

        If global ``fortran_indexing`` is True, returns FortranArray containing
        numbers 1..self.n.  Otherwise, returns a standard numpuy array
        containing numbers in range 0..(self.n-1)."""

        if get_fortran_indexing():
            return farray(list(frange(len(self))))
        else:
            return np.array(list(range(len(self))))
Example #8
0
 def __getattr__(self, name):
     if self.netcdf_file is not None:
         try:
             return self.netcdf_file.__getattr__(name)
         except AttributeError:
             try:
                 a = self.netcdf_file.variables[name][:]
                 if get_fortran_indexing():
                     a = farray(a)
                 return a
             except KeyError:
                 raise AttributeError('Attribute %s not found' % name)
     else:
         raise AttributeError('Attribute %s not found' % name)
Example #9
0
def force_test(at, p, dx=1e-4):
    """
    Compare analyric and numeric forces for the Potential `p` with Atoms `at`

    Finite difference derivates are calculated by moving each atom by `dx`.
    """
    analytic_f = fzeros((3, at.n))
    p.calc(at, force=analytic_f)
    num_f = fzeros((3, at.n))
    ep, em = farray(0.0), farray(0.0)

    for i in frange(at.n):
        for j in (1, 2, 3):
            ap = at.copy()
            ap.pos[j, i] += dx
            p.calc(ap, energy=ep)
            print 'e+', j, i, ep
            ap.pos[j, i] -= 2.0 * dx
            p.calc(ap, energy=em)
            print 'e-', j, i, em
            num_f[j, i] = -(ep - em) / (2 * dx)

    return analytic_f, num_f, analytic_f - num_f
Example #10
0
def get_lattice_params(lattice):
    """
    Wrapper around Fortran :func:`get_lattice_params_`

    Returns parameters of `lattice` as 6-tuple (a,b,c,alpha,beta,gamma).
    """

    a, b, c, alpha, beta, gamma = (farray(0.), farray(0.), farray(0.),
                                   farray(0.), farray(0.), farray(0.))
    _atoms.get_lattice_params(lattice, a, b, c, alpha, beta, gamma)
    return tuple(float(x) for x in (a, b, c, alpha, beta, gamma))
Example #11
0
def unpack_reftraj_output_str_to_results(data):
    lines = data.strip().split('\n')
    nstep = int(lines[0])
    natoms = int(lines[1])
    energy = float(lines[2])
    force = farray(np.loadtxt(lines[3:-1])).T
    v6 = [float(v) for v in lines[-1].split()]
    virial = fzeros((3, 3))
    virial[1, 1], virial[2, 2], virial[3,
                                       3], virial[1,
                                                  2], virial[2,
                                                             3], virial[1,
                                                                        3] = v6
    virial[2, 1] = virial[1, 2]
    virial[3, 2] = virial[2, 3]
    virial[3, 1] = virial[1, 3]
    return (nstep, natoms, energy, force, virial)
Example #12
0
def find_atoms_within_cutoff(atoms, cutoff, d=0):
    tmp_atoms = Atoms(atoms, fortran_indexing=False)
    tmp_atoms.calc_connect()
    over = []
    rij = farray(0.0)
    for i in frange(len(tmp_atoms)):
        for n in frange(tmp_atoms.n_neighbours(i)):
            j = tmp_atoms.neighbour(i, n, distance=rij)
            # print j
            if rij < cutoff and i > j:
                if d == 0:
                    over.append(j - 1)
                else:
                    over.append(i - 1)

    # for i in range(len(atoms)): #python method, may be slower than fortran index?
    #     indices, offsets = tmp_atoms.neighbours.get_neighbors(i)
    #     for j, offset in zip(indices, offsets):
    #         diff=tmp_atoms.get_distance(i,j)
    # if diff < cutoff and i > j : #i>j is important for returning only one atom id
    #             over.append(j)
    return over
Example #13
0
def orthorhombic_slab(at,
                      tol=1e-5,
                      min_nrep=1,
                      max_nrep=5,
                      graphics=False,
                      rot=None,
                      periodicity=None,
                      vacuum=None,
                      shift=None,
                      verbose=True):
    """Try to construct an orthorhombic cell equivalent to the
       primitive cell `at`, using supercells up to at most `max_nrep`
       repeats. Symmetry must be exact within a tolerance of `tol`. If
       `rot` is not None, we first transform `at` by the rotation
       matrix `rot`. The optional argument `periodicity` can be used to
       fix the periodicity one or more directions. It should be a three
       component vector with value zero in the unconstrained
       directions. The vector `vacuum` can be used to add vacuum in one
       or more directions. `shift` is a three component vector which
       can be used to shift the positions in the final cell. """
    def atoms_near_plane(at, n, d, tol=1e-5):
        """Return a list of atoms within a distance `tol` of the plane defined by np.dot(n, at.pos) == d"""
        pd = np.dot(n, at.pos) - d
        return (abs(pd) < tol).nonzero()[0]

    def sort_by_distance(at, ref_atom, dir, candidates):
        """Return a copy of `candidates` sorted by perpendicular distance from `ref_atom` in direction `dir`"""
        distances_candidates = zip(
            [at.pos[dir, i] - at.pos[dir, ref_atom] for i in candidates],
            candidates)
        distances_candidates.sort()
        return [p for (d, p) in distances_candidates]

    def orthorhombic_box(at):
        """Return a copy of `at` in an orthorhombic box surrounded by vacuum"""
        at = at.copy()
        at.map_into_cell()
        at.set_lattice(
            [[2.0 * (at.pos[1, :].max() - at.pos[1, :].min()), 0.0, 0.0],
             [0.0, 2.0 * (at.pos[2, :].max() - at.pos[2, :].min()), 0.0],
             [0.0, 0.0, 2.0 * (at.pos[3, :].max() - at.pos[3, :].min())]],
            scale_positions=False)
        at.map_into_cell()
        return at

    def discard_outliers(at, indices, dirs, keep_fraction=0.5):
        """Return a copy of `indices` with the atoms with fractional coordinates along directions in `dirs`
           outside +/-`keep_fraction`/2 excluded. Lattice used is close fitting, `at.lattice`/2."""
        g = np.linalg.inv(at.lattice / 2)
        t = np.dot(g, at.pos[:, indices])
        return indices[np.logical_and(
            t[dirs, :] >= -keep_fraction / 2.0,
            t[dirs, :] < keep_fraction / 2.0).all(axis=1)]

    def check_candidate_plane(at,
                              ref_plane,
                              cand_plane,
                              dirs,
                              verbose=False,
                              label=''):
        """Check whether in-plane displacements of atoms listed in `ref_plane` match those of `cand_plane` in directions given by `dirs`"""

        # Which pair of planes has more atoms, reference or candidate?
        if len(ref_plane) < len(cand_plane):
            smaller = ref_plane
            larger = cand_plane
        else:
            smaller = cand_plane
            larger = ref_plane

        matches = {}
        for j in smaller:
            for k in larger:
                if at.z[k] == at.z[j] and abs(at.pos[dirs, k] -
                                              at.pos[dirs, j]).max() < tol:
                    matches[j] = k
                    break

        if verbose:
            print '   ', label, len(matches), '/', len(smaller), 'matches'

        return len(matches) == len(smaller)

    if rot is not None:
        at = transform(at, rot)

    xyz = fidentity(3)
    nrep = min_nrep - 1
    max_dist = fzeros(3)

    if periodicity is not None:
        periodicity = farray(periodicity)
        periodicity = dict(
            zip((periodicity != 0).nonzero()[0],
                periodicity[periodicity != 0]))
    else:
        periodicity = {}

    if verbose:
        for (dir, p) in periodicity.iteritems():
            print 'Periodicity in direction %d fixed at %f' % (dir, p)

    if graphics:
        import atomeye
        viewer = atomeye.AtomEyeViewer()

    while sorted(periodicity.keys()) != [1, 2, 3]:
        nrep += 1
        if nrep > max_nrep:
            raise ValueError('Maximum size of supercell (%d) exceeded' %
                             max_nrep)
        if verbose:
            print '\n\nSupercell %d' % nrep
        sup = supercell(at, nrep, nrep, nrep)
        box = orthorhombic_box(sup)
        box.pos[:] = box.pos - np.tile(box.pos.mean(axis=2), [box.n, 1]).T

        for dir in set([1, 2, 3]) - set(periodicity.keys()):

            if verbose:
                print '  Direction %d' % dir

            other_dirs = list(set([1, 2, 3]) - set([dir]))

            pos_index = zip(box.pos[dir, :], frange(box.n))
            pos_index.sort()

            # Find a pair of planes
            while pos_index:
                ref_pos1, ref_atom1 = pos_index.pop(0)

                # Find atom to define second plane
                while pos_index:
                    ref_pos2, ref_atom2 = pos_index.pop(0)
                    if abs(ref_pos2 - ref_pos1) > tol: break
                else:
                    continue

                ref_plane1 = atoms_near_plane(box, xyz[:, dir],
                                              box.pos[dir, ref_atom1], tol)
                ref_plane2 = atoms_near_plane(box, xyz[:, dir],
                                              box.pos[dir, ref_atom2], tol)

                # Only keep reference atoms in the centre of the cell
                ref_plane1 = discard_outliers(box, ref_plane1, other_dirs)
                ref_plane2 = discard_outliers(box, ref_plane2, other_dirs)

                if len(ref_plane1) > 2 and len(ref_plane2) > 2:
                    # Now we've got two planes, both with more than two atoms in them
                    break
            else:
                # Used up all atoms without finding two planes
                if verbose:
                    print '    No valid reference planes found.\n'
                continue

            if verbose:
                print '    Reference plane #1 through atom %d ' % ref_atom1
                print '    Reference plane #2 through atom %d at distance %r\n' % (
                    ref_atom2, ref_pos2 - ref_pos1)

            if graphics:
                highlight = fzeros(box.n)
                highlight[ref_plane1] = 1
                highlight[ref_plane2] = 2
                box.add_property('highlight', highlight, overwrite=True)
                viewer.show(box, 'highlight')
                viewer.wait()
                raw_input('continue')

            candidates = [
                i for i in frange(box.n)
                if box.pos[dir,
                           i] > box.pos[dir, ref_atom2] + max_dist[dir] + tol
            ]
            candidates = sort_by_distance(box, ref_atom1, dir, candidates)

            while candidates:
                cand1 = candidates.pop(0)

                max_dist[dir] = box.pos[dir, cand1] - box.pos[dir, ref_atom1]

                if verbose:
                    print '    Trying plane through atom %d distance %r' % (
                        cand1, max_dist[dir])

                cand_plane1 = atoms_near_plane(box, xyz[:, dir],
                                               box.pos[dir, cand1], tol)

                for cand2 in sort_by_distance(
                        box, ref_atom1, dir,
                        set(candidates) - set(cand_plane1)):
                    if abs((box.pos[dir, cand2] - box.pos[dir, cand1]) -
                           (box.pos[dir, ref_atom2] -
                            box.pos[dir, ref_atom1])) < tol:
                        if verbose:
                            print '    Found pair to plane, passing through atom %d distance %r ' % (
                                cand2,
                                box.pos[dir, cand2] - box.pos[dir, ref_atom1])
                        break
                else:
                    if verbose:
                        print '    Cannot find second candidate plane.\n'
                    candidates = sort_by_distance(
                        box, ref_atom1, dir,
                        set(candidates) - set(cand_plane1))
                    continue

                if graphics:
                    highlight[cand_plane1] = 3
                    box.highlight[:] = highlight
                    viewer.show(box, 'highlight')
                    viewer.wait()

                cand_plane2 = atoms_near_plane(box, xyz[:, dir],
                                               box.pos[dir, cand2], tol)

                if graphics:
                    highlight[cand_plane2] = 4
                    box.highlight[:] = highlight
                    viewer.show(box, 'highlight')
                    viewer.wait()

                    highlight[cand_plane1] = 0
                    highlight[cand_plane2] = 0

                # Remove cand_plane1 from list of candidates
                candidates = sort_by_distance(
                    box, ref_atom1, dir,
                    set(candidates) - set(cand_plane1))

                # Check ref_plane1 against cand_plane1 and ref_plane2 against cand_plane2 in directions
                # listed in other_dirs
                match1 = check_candidate_plane(box, ref_plane1, cand_plane1,
                                               other_dirs, verbose,
                                               'Plane #1:')
                match2 = check_candidate_plane(box, ref_plane2, cand_plane2,
                                               other_dirs, verbose,
                                               'Plane #2:')

                if match1 and match2:
                    periodicity[dir] = box.pos[dir, cand1] - box.pos[dir,
                                                                     ref_atom1]
                    if verbose:
                        print '\n  Periodicity in direction %d is %f\n' % (
                            dir, box.pos[dir, cand1] - box.pos[dir, ref_atom1])

                    if graphics:
                        highlight[cand_plane1] = 3
                        highlight[cand_plane2] = 3
                        box.highlight[:] = highlight
                        viewer.show(box, 'highlight')
                        viewer.wait()
                        raw_input('continue...')
                    break

                if graphics:
                    raw_input('continue...')
            else:
                # Failed to find match for direction dir
                continue

    # Finally, construct new cell by selecting atoms within first unit cell
    lattice = farray(np.diag([periodicity[1], periodicity[2], periodicity[3]]))
    g = np.linalg.inv(lattice)

    nrepx, nrepy, nrepz = fit_box_in_cell(periodicity[1], periodicity[2],
                                          periodicity[3], at.lattice)

    sup = supercell(at, nrepx, nrepy, nrepz)
    sup.map_into_cell()

    # small shift to avoid coincidental cell alignments
    delta = np.tile([0.01, 0.02, 0.03], [sup.n, 1]).T
    if shift is not None and vacuum is not None:
        delta = delta + np.tile(shift, [sup.n, 1]).T
    t = np.dot(g, sup.pos) + delta

    orthorhombic = sup.select(np.logical_and(t >= -0.5, t < 0.5).all(axis=1))

    if vacuum:
        lattice = farray(np.diag(lattice.diagonal() + vacuum))

    if shift is not None and vacuum is None:
        if verbose:
            print 'Shifting positions by %s' % np.dot(lattice, shift)
        orthorhombic.pos += np.tile(np.dot(lattice, shift),
                                    [orthorhombic.n, 1]).T

    orthorhombic.set_lattice(lattice, scale_positions=False)
    orthorhombic.map_into_cell()
    return orthorhombic
Example #14
0
def CP2KDirectoryReader(run_dir,
                        at_ref=None,
                        proj='quip',
                        calc_qm_charges=None,
                        calc_virial=False,
                        out_i=None,
                        qm_vacuum=6.0,
                        run_suffix='_extended',
                        format=None):
    if at_ref is None:
        filepot_xyz = os.path.join(run_dir, 'filepot.xyz')
        if not os.path.exists(filepot_xyz):
            # try looking up one level
            filepot_xyz = os.path.join(run_dir, '../filepot.xyz')

        if os.path.exists(filepot_xyz):
            at_ref = Atoms(filepot_xyz)
        else:
            at_ref = Atoms(os.path.join(run_dir, 'cp2k_output.out'),
                           format='cp2k_output')

    at = at_ref.copy()

    cp2k_output_filename, cp2k_output = read_text_file(
        os.path.join(run_dir, 'cp2k_output.out'))
    cp2k_params = CP2KInputHeader(
        os.path.join(run_dir, 'cp2k_input.inp.header'))
    at.params.update(cp2k_params)

    run_type = cp2k_run_type(cp2k_output=cp2k_output,
                             cp2k_input_header=cp2k_params)

    try:
        cluster_mark = getattr(at, 'cluster_mark' + run_suffix)
        qm_list_a = ((cluster_mark != HYBRID_NO_MARK).nonzero()[0]).astype(
            np.int32)
    except AttributeError:
        qm_list_a = fzeros(0, dtype=np.int32)

    if calc_qm_charges is None:
        calc_qm_charges = ''

    try:
        cur_qmmm_qm_abc = [
            float(cp2k_params['QMMM_ABC_X']),
            float(cp2k_params['QMMM_ABC_Y']),
            float(cp2k_params['QMMM_ABC_Z'])
        ]
    except KeyError:
        if 'QM_cell' + run_suffix in at.params:
            cur_qmmm_qm_abc = at.params['QM_cell' + run_suffix]
        else:
            cur_qmmm_qm_abc = qmmm_qm_abc(at, qm_list_a, qm_vacuum)

    quip_cp2k_at = Atoms(os.path.join(run_dir, 'quip_cp2k.xyz'))

    rev_sort_index_file = os.path.join(run_dir, '../quip_rev_sort_index')
    fields = [int(x) for x in open(rev_sort_index_file).read().split()]
    rev_sort_index = farray(fields, dtype=np.int32)
    #verbosity_push(PRINT_SILENT)
    cp2k_energy, cp2k_force = read_output(quip_cp2k_at, qm_list_a,
                                          cur_qmmm_qm_abc, run_dir, proj,
                                          calc_qm_charges, calc_virial, True,
                                          3, at.n, out_i)
    #verbosity_pop()

    qm_list = None
    if os.path.exists(os.path.join(run_dir, 'cp2k_input.qmmm_qm_kind')):
        qm_kind_grep_cmd = "grep MM_INDEX %s/cp2k_input.qmmm_qm_kind | awk '{print $2}'" % run_dir
        qm_list = [int(i) for i in os.popen(qm_kind_grep_cmd).read().split()]

    if qm_list is not None:
        if run_type == 'QMMM':
            reordering_index = getattr(at, 'reordering_index', None)

            at.add_property('qm', False, overwrite=True)
            if reordering_index is not None:
                qm_list = reordering_index[qm_list]
            at.qm[qm_list] = True
        elif run_type == 'QS':
            at.add_property('qm_orig_index', 0, overwrite=True)
            for i, qm_at in fenumerate(qm_list):
                at.qm_orig_index[i] = sort_index[qm_at]

    at.add_property('force', cp2k_force, overwrite=True)
    at.params['energy'] = cp2k_energy
    yield at
Example #15
0
def CP2KOutputReader(fh,
                     module=None,
                     type_map=None,
                     kind_map=None,
                     format=None):

    # mapping from run type to (default module index, list of available module)
    run_types = {
        'QS': ['QUICKSTEP'],
        'QMMM': ['FIST', 'QM/MM', 'QUICKSTEP'],
        'MM': ['FIST']
    }

    filename, lines = read_text_file(fh)
    run_type = cp2k_run_type(cp2k_output=lines)

    if type_map is None:
        type_map = {}
    if kind_map is None:
        kind_map = {}

    try:
        available_modules = run_types[run_type]
    except KeyError:
        raise ValueError('Unknown CP2K run type %s' % run_type)

    if module is None:
        module = available_modules[0]

    try:
        cell_index = available_modules.index(module)
    except ValueError:
        raise ValueError("Don't know how to read module %s from file %s" %
                         (module, filename))

    cell_lines = [
        i for i, line in enumerate(lines) if line.startswith(" CELL| Vector a")
    ]
    if cell_lines == []:
        raise ValueError("Cannot find cell in file %s" % filename)

    try:
        cell_line = cell_lines[cell_index]
    except IndexError:
        raise ValueError(
            "Cannot find cell with index %d in file %s for module %s" %
            (cell_index, filename, module))

    lattice = fzeros((3, 3))
    for i in [0, 1, 2]:
        lattice[:,
                i + 1] = [float(c) for c in lines[cell_line + i].split()[4:7]]

    try:
        start_line = lines.index(
            " MODULE %s:  ATOMIC COORDINATES IN angstrom\n" % module)
    except ValueError:
        raise ValueError(
            "Cannot find atomic positions for module %s in file %s" %
            (module, filename))

    kinds = []
    species = []
    Zs = []
    pos = []
    masses = []
    Zeffs = []
    types = []
    qeffs = []
    for line in lines[start_line + 4:]:
        if line.strip() == '':
            break
        if module == 'FIST':
            atom, kind, typ, x, y, z, qeff, mass = line.split()
            types.append(typ)
            Z = type_map.get(typ, 0)
            kind = int(kind)
            if Z == 0:
                Z = kind_map.get(kind, 0)
            Zs.append(Z)
            qeffs.append(float(qeff))
        else:
            atom, kind, sp, Z, x, y, z, Zeff, mass = line.split()
            species.append(sp)
            Zs.append(int(Z))
            Zeffs.append(float(Zeff))
        kinds.append(int(kind))
        pos.append([float(x), float(y), float(z)])
        masses.append(float(mass))

    at = Atoms(n=len(kinds), lattice=lattice)
    at.pos[...] = farray(pos).T
    at.set_atoms(Zs)
    at.add_property('mass', farray(masses) * MASSCONVERT)
    at.add_property('kind', kinds)
    if module == 'FIST':
        at.add_property('type', ' ' * TABLE_STRING_LENGTH)
        at.add_property('qm', False)
        at.qm[:] = (at.type.stripstrings()
                    == '_QM_') | (at.type.stripstrings() == '_LNK')
        at.type[...] = s2a(types, TABLE_STRING_LENGTH)
        at.add_property('qeff', qeffs)
    else:
        at.species[...] = s2a(species, TABLE_STRING_LENGTH)
        at.add_property('zeff', Zeffs)

    yield at
Example #16
0
def crack_make_seed_curved_front(slab, params):
   """Given a slab, introduce a 3D curved crack front."""

   orig_width = slab.params['OrigWidth']
   orig_height = slab.params['OrigHeight']
   orig_depth  = slab.params['OrigDepth']

   crack_length = params.crack_seed_length/orig_width
   crack_curvature = params.crack_curvature
   crack_depth = 1.0

   if params.crack_g > 0.:
      epsilon_max = crack_g_to_strain(params.crack_g,
                                     slab.YoungsModulus,
                                     slab.PoissonRatio_yx,
                                     orig_height)
   else:
      epsilon_max = params.crack_strain

   # ... then shift so coordinates are in ranges x=[0..a], y=[0..b], z=[0..c]
   slab.pos += np.tile(np.array([orig_width, orig_height, orig_depth])[:,np.newaxis]/2., slab.n)

   xlin = 0.5*crack_length*orig_width
   crack_center = farray([crack_length*orig_width, 0.5*orig_height, 0.])

   epsilon_min = 0.
   epsilon_local = 0.
   dy = 0.

   a = crack_curvature
   x1 = crack_length*orig_width
   x2 = x1 + crack_depth
   z1 = 0.
   z2 = orig_depth
   slope = (x2-x1)/(z2-z1)

   dymax = 0.5*epsilon_max*orig_height

   z = slab.pos[3,:]
   crack_x_center = crack_curvature*(z*z - z1*z1) + (slope-crack_curvature*(z2+z1))*(z-z1) + crack_center[1]
   ##slab.add_property('xc', crack_x_center, overwrite=True)

   dymin = abs(slab.pos[2,:]-crack_center[2])*epsilon_max

   dy = dymin
   dy[slab.pos[1,:] < xlin] = dymax
   mask = (slab.pos[1,:] > xlin) & (slab.pos[1,:] <= crack_x_center)
   ##slab.add_property('mask', mask, overwrite=True)
   dy[mask] = (dymax - dymin[mask])/(xlin - crack_x_center[mask])*abs(slab.pos[1,mask] - xlin) + dymax

   dy *= np.sign(slab.pos[2,:] - crack_center[2])
   ##slab.add_property('dy', dy, overwrite=True)
   slab.pos[2,:] += dy

   # Centre slab in cell
   slab.pos += np.tile((np.array([params.crack_vacuum_size/2.]*3) +
                        np.diag(slab.lattice)/2.)[:,np.newaxis], slab.n)
   slab.map_into_cell()

   slab.params['CrackPosx'] = crack_center[1] + params.crack_vacuum_size/2.
   slab.params['CrackPosy'] = crack_center[2] + params.crack_vacuum_size/2.
Example #17
0
        opt.range = slice(opt.range, opt.range + 1, +1)
    else:
        opt.range = slice(opt.range, opt.range - 1, -1)

for infile in infiles:
    basename = os.path.basename(os.path.splitext(infile)[0])

    configs = AtomsReader(infile,
                          start=opt.range.start,
                          stop=opt.range.stop,
                          step=opt.range.step)

    for frame, q0 in enumerate(configs):
        print 'Read %d atoms from file %s frame %d' % (q0.n, infile, frame)

        diameter = farray(0, dtype=np.int32)
        ring_sizes = range(1, opt.max_ring_size + 1)

        if opt.supercell is None:
            q = q0
        else:
            print 'Forming %d x %d x %d supercell' % tuple(opt.supercell)
            q = supercell(q0, opt.supercell[0], opt.supercell[1],
                          opt.supercell[2])
        q.map_into_cell()

        q.set_cutoff(opt.si_o_cutoff)
        q.calc_connect()

        if opt.tetra:
            print 'Converting topology from Si-O-Si to Si-Si'