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
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
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
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
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
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())
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))))
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)
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
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))
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)
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
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
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
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
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.
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'