def run(pos, nbrs):

	num_atoms = len(pos)
	result = np.zeros(num_atoms, int)
	strains = np.zeros(num_atoms).astype(np.double)
	rmsds = np.zeros(num_atoms).astype(np.double)

	if 1:
		for i in range(num_atoms):

			positions = np.concatenate(([pos[i]], pos[nbrs[i][:18]]))
			(struct, alloy, rmsd, scale, rot, F, F_res, P, U, lattice_constant) = ptmmodule.index_structure(positions, calculate_strains=1, topological_ordering=1)
			if 0 and struct == 0 and all([e > 1000 for e in nbrs[i]]):
				print nbrs[i]
				print positions
				positions -= pos[i]
				plot_points(positions[:15])
			#(struct, alloy, rmsd, scale, rot, lattice_constant) = ptmmodule.index_structure(positions)
			#if struct == 2:
			#	vm, r = calc_fcc_strain(F, F_res, P, U, positions[:13])
			#	strains[i] = vm
			result[i] = struct
			rmsds[i] = rmsd

	indices = np.where(rmsds < 0.12)[0]
	kept = np.bincount(result[indices])
	kept[0] += num_atoms - len(indices)
	print "rmsd < 0.12:", kept, sum(kept)

	return result, rmsds
	indices = np.where(result == 2)[0]
	plt.hist(strains[indices], bins=200)
	plt.show()
Ejemplo n.º 2
0
def PTM(atoms, target_structures=None, calculate_strains=False, cutoff=10.0):
    """Run Complex Hull Analysis on an Atoms object.

    Parameters:
    atoms: The atoms object

    target_structures=None: A tuple of structures to be investigated.
        It defaults to ('sc', 'fcc', 'hcp', 'ico', 'bcc').
        It MUST be a tuple, not a list or other sequence (bug?).
    
    calculate_strains=False: Set to True to calculate strains.

    cutoff: A cutoff used for the neighborlist.  Must be large enough that all
        nearest neighbors are returned (second-nearest for BCC).  Using a too
        large value may impact performance, but not results.
        
    Returns:
    (structures, alloytypes, rmsds, scales, rotations, [strains])
    Each of these are a NumPy array of the same length as the number of atoms.
    For each atom, the data returned is

    structures[i]: The local crystal structure around atom i, if any.
         0 = none; 1 = SC; 2 = FCC; 3 = HCP; 4 = Icosahedral; 5 = BCC.

    alloytypes[i]: The alloy structure identified.
         0 = unidentified; 1 = pure element; 2 = L1_0;
         3 = L1_2 majority atom; 4 = L1_2 minority atom.
         (0 is returned if structures[i] != 2 or if no known alloy structure
         is recognized)

    rmsds[i]: The RMSD error in the fitting to the template, or INF if
         no structure was identified.

    scales[i]: The average distance to the nearest neighbors for
         structures 1-4; or the average distance to nearest and
         next-nearest neighbors for structure 5 (BCC); or INF if no
         structure was identified.

    rotations[i]: The rotation of the crystal lattice, expressed as a
         unit quaternion.  If no structure was found, the illegal
         value (0, 0, 0, 0) is returned.

    strains[i] (only returned if calculate_strains=True).  The strain
         tensor as a symmetric 3x3 matrix.  The trace of the matrix is
         1.0, since a hydrostatic component of the strain cannot be
         determined without a-priori knowledge of the reference
         lattice parameter.  If such knowledge is available, the
         hydrostatic component of the strain can be calculated from
         scales[i].

    """

    numnb = 18  # Plus central atom
    nblist = asap3.FullNeighborList(cutoff, atoms)
    structures = np.zeros(len(atoms), int)
    alloys = np.zeros(len(atoms), int)
    rmsds = np.zeros(len(atoms))
    scales = np.zeros(len(atoms))
    rotations = np.zeros((len(atoms), 4))
    if calculate_strains:
        strains = np.zeros((len(atoms), 3, 3))
    z_all = atoms.get_atomic_numbers()
    for i in range(len(atoms)):
        indices, relative_positions, sqdist = nblist.get_neighbors(i)
        assert(len(indices) >= numnb)
        nearest = np.argsort(sqdist)[:numnb]
        positions = np.zeros((numnb+1,3))
        positions[1:] = relative_positions[nearest]

        z = np.zeros(numnb+1, np.int32)
        z[0] = z_all[i]
        z[1:] = z_all[indices[nearest]]
        data = ptmmodule.index_structure(positions, z, 
                                         calculate_strains=calculate_strains,
                                         topological_ordering=True)
        # data = (struct, alloy, rmsd, scale, rotation)
        structures[i], alloys[i], rmsds[i], scales[i] = data[:4]
        if structures[i]:
            rotations[i] = data[4]
            if calculate_strains:
                strains[i] = data[7]
    if calculate_strains:
        return structures, alloys, rmsds, scales, rotations, strains
    else:
        return structures, alloys, rmsds, scales, rotations