Example #1
0
def get_fractional_positions_from_neighbor_list(
        structure: Structure, neighbor_list: List) -> List[Vector]:
    """
    Returns the fractional positions of the lattice sites in structure from
    a neighbor list.

    Parameters
    ----------
    structure
        input atomic structure
    neighbor_list
        list of lattice neighbors of the input structure
    """
    neighbor_positions = []
    fractional_positions = []
    lattice_site = LatticeSite(0, [0, 0, 0])

    for i in range(len(neighbor_list)):
        lattice_site.index = i
        position = structure.get_position(lattice_site)
        neighbor_positions.append(position)
        for neighbor in neighbor_list[i]:
            position = structure.get_position(neighbor)
            neighbor_positions.append(position)

    if len(neighbor_positions) > 0:
        fractional_positions = get_scaled_positions(
            np.array(neighbor_positions),
            structure.cell,
            wrap=False,
            pbc=structure.pbc)

    return fractional_positions
 def setUp(self):
     """Setup before each test."""
     self.icet_structure = Structure(positions=self.positions,
                                     chemical_symbols=self.chemical_symbols,
                                     cell=self.cell,
                                     pbc=[True, True, True])
     random.seed(113)
Example #3
0
def _get_lattice_site_matrix_of_equivalent_positions(
        structure: Structure,
        matrix_of_equivalent_positions: MatrixOfEquivalentPositions,
        fractional_position_tolerance: float,
        prune: bool = True) -> np.ndarray:
    """
    Returns a transformed permutation matrix with lattice sites as entries
    instead of fractional coordinates.

    Parameters
    ----------
    structure
        primitive atomic icet structure
    matrix_of_equivalent_positions
        permutation matrix with fractional coordinates format entries
    fractional_position_tolerance
        tolerance applied when evaluating distances in fractional coordinates
    prune
        if True the permutation matrix will be pruned

    Returns
    -------
    permutation matrix in a row major order with lattice site format entries
    """
    pm_frac = matrix_of_equivalent_positions.get_equivalent_positions()

    pm_lattice_sites = []
    for row in pm_frac:
        positions = _fractional_to_cartesian(row, structure.cell)
        lattice_sites = []
        if np.all(structure.pbc):
            lattice_sites = structure.find_lattice_sites_by_positions(
                positions=positions,
                fractional_position_tolerance=fractional_position_tolerance)
        else:
            for pos in positions:
                try:
                    lattice_site = structure.find_lattice_site_by_position(
                        position=pos,
                        fractional_position_tolerance=
                        fractional_position_tolerance)
                except RuntimeError:
                    continue
                lattice_sites.append(lattice_site)
        if lattice_sites is not None:
            pm_lattice_sites.append(lattice_sites)
        else:
            logger.warning('Unable to transform any element in a column of the'
                           ' fractional permutation matrix to lattice site')
    if prune:
        logger.debug('Size of columns of the permutation matrix before'
                     ' pruning {}'.format(len(pm_lattice_sites)))

        pm_lattice_sites = _prune_matrix_of_equivalent_positions(
            pm_lattice_sites)

        logger.debug('Size of columns of the permutation matrix after'
                     ' pruning {}'.format(len(pm_lattice_sites)))

    return pm_lattice_sites
    def get_cluster_vector(self, structure: Atoms) -> np.ndarray:
        """
        Returns the cluster vector for a structure.

        Parameters
        ----------
        structure
            atomic configuration

        Returns
        -------
        the cluster vector
        """
        if not isinstance(structure, Atoms):
            raise TypeError('Input structure must be an ASE Atoms object')

        try:
            cv = _ClusterSpace.get_cluster_vector(
                self,
                structure=Structure.from_atoms(structure),
                fractional_position_tolerance=self.fractional_position_tolerance)
        except Exception as e:
            self.assert_structure_compatibility(structure)
            raise(e)
        return cv
Example #5
0
 def __init__(self, *args, **kwargs):
     super(TestGroundStateFinderZeroParameter,
           self).__init__(*args, **kwargs)
     self.chemical_symbols = ['Ag', 'Au']
     self.cutoffs = [4.3]
     self.structure_prim = bulk(self.chemical_symbols[1], a=4.0)
     self.cs = ClusterSpace(self.structure_prim, self.cutoffs,
                            self.chemical_symbols)
     nonzero_ce = ClusterExpansion(self.cs, [0, 0, 0.1, -0.02])
     lolg = LocalOrbitListGenerator(
         self.cs.orbit_list, Structure.from_atoms(self.structure_prim),
         self.cs.fractional_position_tolerance)
     full_orbit_list = lolg.generate_full_orbit_list()
     binary_parameters_zero = transform_parameters(self.structure_prim,
                                                   full_orbit_list,
                                                   nonzero_ce.parameters)
     binary_parameters_zero[1] = 0
     A = get_transformation_matrix(self.structure_prim, full_orbit_list)
     Ainv = np.linalg.inv(A)
     zero_parameters = np.dot(Ainv, binary_parameters_zero)
     self.ce = ClusterExpansion(self.cs, zero_parameters)
     self.all_possible_structures = []
     self.supercell = self.structure_prim.repeat(2)
     for i in range(len(self.supercell)):
         structure = self.supercell.copy()
         structure.symbols[i] = self.chemical_symbols[0]
         self.all_possible_structures.append(structure)
Example #6
0
def matrix_of_equivalent_positions_from_structure(structure: Atoms,
                                                  cutoff: float,
                                                  position_tolerance: float,
                                                  symprec: float,
                                                  find_primitive: bool = True) \
        -> Tuple[np.ndarray, Structure, List]:
    """Sets up a list of permutation maps from an Atoms object.

    Parameters
    ----------
    structure
        input structure
    cutoff
        cutoff radius
    find_primitive
        if True the symmetries of the primitive structure will be employed
    symprec
        tolerance imposed when analyzing the symmetry using spglib
    position_tolerance
        tolerance applied when comparing positions in Cartesian coordinates

    Returns
    -------
    The tuple that is returned comprises the permutation matrix, the
    primitive structure, and the neighbor list.
    """

    structure = structure.copy()
    structure_prim = structure
    if find_primitive:
        structure_prim = get_primitive_structure(structure, symprec=symprec)
    logger.debug('Size of primitive structure: {}'.format(len(structure_prim)))

    # get symmetry information
    structure_as_tuple = ase_atoms_to_spglib_cell(structure_prim)
    symmetry = spglib.get_symmetry(structure_as_tuple, symprec=symprec)
    translations = symmetry['translations']
    rotations = symmetry['rotations']

    # set up a permutation map object
    matrix_of_equivalent_positions = MatrixOfEquivalentPositions(
        translations, rotations)

    # create neighbor_lists from the different cutoffs
    prim_icet_structure = Structure.from_atoms(structure_prim)

    neighbor_list = get_neighbor_lists(
        prim_icet_structure, [cutoff],
        position_tolerance=position_tolerance)[0]

    # get fractional positions for neighbor_list
    frac_positions = get_fractional_positions_from_neighbor_list(
        prim_icet_structure, neighbor_list)

    logger.debug('Number of fractional positions: {}'.format(
        len(frac_positions)))
    if frac_positions is not None:
        matrix_of_equivalent_positions.build(frac_positions)

    return matrix_of_equivalent_positions, prim_icet_structure, neighbor_list
Example #7
0
    def test_neighbors_non_pbc(self):
        """
        Tests indices and offset of neighborlist for a
        non-pbc structure under the same cutoff as above.
        """
        structure = self.structure.copy()
        structure.pbc = [True, True, False]
        structure.center(4.0, axis=[2])

        neighbors = get_neighbor_lists(
            structure=Structure.from_atoms(structure), cutoffs=[self.cutoff])

        indices = [ngb.index for ngb in neighbors[0][0]]
        offsets = [ngb.unitcell_offset for ngb in neighbors[0][0]]

        self.ase_nl.update(structure)
        ase_indices, ase_offsets = self.ase_nl.get_neighbors(0)

        for index in indices:
            self.assertIn(index, ase_indices)

        for offset in offsets:
            self.assertIn(offset, ase_offsets)

        self.assertLess(len(indices), len(self.indices))
        self.assertLess(len(offsets), len(self.offsets))
Example #8
0
    def __init__(self,
                 cluster_space,
                 structure: Atoms,
                 interval: int = None,
                 max_orbit: int = None) -> None:
        super().__init__(interval=interval,
                         return_type=dict,
                         tag='ClusterCountObserver')

        self._cluster_space = cluster_space
        local_orbit_list_generator = LocalOrbitListGenerator(
            orbit_list=cluster_space.orbit_list,
            structure=Structure.from_atoms(structure),
            fractional_position_tolerance=cluster_space.
            fractional_position_tolerance)

        self._full_orbit_list = local_orbit_list_generator.generate_full_orbit_list(
        )
        self._cluster_counts_cpp = _ClusterCounts()

        if max_orbit is None:
            self._max_orbit = len(self._full_orbit_list)
        else:
            self._max_orbit = max_orbit

        self._cluster_keys = []  # type: List[Orbit]
        for i, orbit in enumerate(self._full_orbit_list.orbits):
            cluster = orbit.representative_cluster
            cluster.tag = i
            self._cluster_keys.append(cluster)

        self._empty_counts = self._get_empty_counts()
 def __init__(self, orbit_list: OrbitList, structure: Atoms,
              fractional_position_tolerance: float):
     self._orbit_list = orbit_list
     self._structure = Structure.from_atoms(structure)
     # call (base) C++ constructor
     _ClusterCounts.__init__(self)
     self.cluster_counts = self._count_clusters(
         fractional_position_tolerance=fractional_position_tolerance)
    def test_structure_to_atoms(self):
        """Tests icet Structure-to-ASE Atoms conversion."""
        ase_structure = Structure.to_atoms(self.icet_structure)
        for ase_pos, icet_pos in zip(ase_structure.positions,
                                     self.icet_structure.positions):
            self.assertListEqual(ase_pos.tolist(), icet_pos.tolist())

        chem_symbols = ase_structure.get_chemical_symbols()
        self.assertListEqual(chem_symbols, ['Ag', 'Ag'])
    def test_structure_from_atoms(self):
        """Tests ASE Atoms-to-icet Structure conversion."""
        icet_structure = Structure.from_atoms(self.ase_atoms)
        for icet_pos, ase_pos in zip(icet_structure.positions,
                                     self.ase_atoms.positions):
            self.assertListEqual(icet_pos.tolist(), ase_pos.tolist())

        chem_symbols = icet_structure.get_chemical_symbols()
        self.assertListEqual(chem_symbols, ['Ag', 'Ag'])
Example #12
0
    def __init__(self, *args, **kwargs):
        super(TestOrbitList, self).__init__(*args, **kwargs)
        self.cutoffs = [4.2]
        self.symprec = 1e-5
        self.position_tolerance = 1e-5
        self.fractional_position_tolerance = 1e-6
        self.structure = bulk('Ag', 'sc', a=4.09)

        # representative clusters for testing
        # for singlet
        self.cluster_singlet = Cluster(
            Structure.from_atoms(self.structure),
            [LatticeSite(0, [0, 0, 0])])
        # for pair
        lattice_sites = [LatticeSite(0, [i, 0, 0]) for i in range(3)]
        self.cluster_pair = Cluster(Structure.from_atoms(self.structure),
                                    [lattice_sites[0], lattice_sites[1]],
                                    True)
Example #13
0
    def __init__(self, *args, **kwargs):
        super(TestNeighborList, self).__init__(*args, **kwargs)

        self.structure = bulk('Ni', 'hcp', a=1.0).repeat([3, 3, 1])
        self.cutoff = 1.4
        self.position_tolerance = 1e-5
        self.icet_structure = Structure.from_atoms(self.structure)
        self.ase_nl = ASENeighborList(len(self.structure) * [self.cutoff / 2],
                                      skin=1e-8,
                                      bothways=True,
                                      self_interaction=False)
        self.ase_nl.update(self.structure)
        self.ase_indices, self.ase_offsets = self.ase_nl.get_neighbors(0)
Example #14
0
    def __init__(self, allowed_species: List[List[str]],
                 primitive_structure: Atoms, structure: Atoms,
                 fractional_position_tolerance: float):
        self._structure = structure
        # sorted unique sites, this basically decides A, B, C... sublattices
        active_lattices = sorted(
            set([
                tuple(sorted(symbols)) for symbols in allowed_species
                if len(symbols) > 1
            ]))
        inactive_lattices = sorted(
            set([
                tuple(sorted(symbols)) for symbols in allowed_species
                if len(symbols) == 1
            ]))
        self._allowed_species = active_lattices + inactive_lattices

        n = int(np.sqrt(len(self._allowed_species))) + 1
        symbols = [
            ''.join(p) for r in range(1, n + 1)
            for p in product(ascii_uppercase, repeat=r)
        ]

        cpp_prim_structure = Structure.from_atoms(primitive_structure)
        self._sublattices = []
        sublattice_to_indices = [[] for _ in range(len(self._allowed_species))]
        for index, position in enumerate(structure.positions):
            lattice_site = cpp_prim_structure.find_lattice_site_by_position(
                position=position,
                fractional_position_tolerance=fractional_position_tolerance)

            # Get allowed species on this site
            species = allowed_species[lattice_site.index]

            # Get what sublattice those species correspond to
            sublattice = self._allowed_species.index(tuple(sorted(species)))

            sublattice_to_indices[sublattice].append(index)

        for symbol, species, indices in zip(symbols, self._allowed_species,
                                            sublattice_to_indices):
            sublattice = Sublattice(chemical_symbols=species,
                                    indices=indices,
                                    symbol=symbol)
            self._sublattices.append(sublattice)

        # Map lattice index to sublattice index
        self._index_to_sublattice = {}
        for k, sublattice in enumerate(self):
            for index in sublattice.indices:
                self._index_to_sublattice[index] = k
    def test_find_lattice_site_by_position_with_tolerance(self):
        """Tests the find lattice site by position method
           by varying the tolerance
           """
        atoms = bulk('Al', crystalstructure='hcp', a=3).repeat(2)

        icet_structure = Structure.from_atoms(atoms)

        def _test_lattice_site_find(tol, noise, index):
            for i in range(3):
                position = atoms.positions[index]
                position[i] += noise
                ls = icet_structure.find_lattice_site_by_position(
                    position, tol)
                self.assertEqual(ls.index, index)

                position = atoms.positions[index]
                position[i] -= noise
                ls = icet_structure.find_lattice_site_by_position(
                    position, tol)
                self.assertEqual(ls.index, index)

        # First with noise smaller thant tol
        tol = 1e-5
        noise = 5e-6
        for index in range(len(atoms)):
            _test_lattice_site_find(tol, noise, index)

        # Increase tolerance and force a fail
        tol = 1e-5
        noise = 5e-5
        for index in range(len(atoms)):
            with self.assertRaises(Exception) as context:
                _test_lattice_site_find(tol, noise, index)
            self.assertIn('Failed to find site by position',
                          str(context.exception))

        # Large noise  but larger tol
        tol = 1e-3
        noise = 5e-4
        for index in range(len(atoms)):
            _test_lattice_site_find(tol, noise, index)

        # Large tol but larger noise
        tol = 1e-3
        noise = 5e-3
        for index in range(len(atoms)):
            with self.assertRaises(Exception) as context:
                _test_lattice_site_find(tol, noise, index)
            self.assertIn('Failed to find site by position',
                          str(context.exception))
Example #16
0
 def __init__(self, *args, **kwargs):
     super(TestClusterCounts, self).__init__(*args, **kwargs)
     self.structure = bulk('Ni', 'hcp', a=2.0).repeat([2, 1, 1])
     self.structure_prim = bulk('Ni', 'hcp', a=2.0)
     self.structure.set_chemical_symbols('NiFeNi2')
     self.icet_structure = Structure.from_atoms(self.structure)
     self.cutoffs = [2.2]
     self.symprec = 1e-5
     self.position_tolerance = 1e-5
     self.fractional_position_tolerance = 1e-6
     self.orbit_list = OrbitList(self.structure_prim, self.cutoffs,
                                 self.symprec, self.position_tolerance,
                                 self.fractional_position_tolerance)
     self.orbit_list.sort(self.position_tolerance)
Example #17
0
    def _set_allowed_species(self, cluster_space: ClusterSpace,
                             structure: Atoms):
        """
        Set the allowed species for the selected sites in the Atoms object

        Parameters
        ----------
        cluster_space
            Cluster space implicitly defining allowed species
        structure
            Specific supercell (consistent with cluster_space) whose
            allowed species are to be determined
        """

        primitive_structure = Structure.from_atoms(
            cluster_space.primitive_structure)
        chemical_symbols = cluster_space.get_chemical_symbols()

        if len(chemical_symbols) == 1:
            # If the allowed species are the same for all sites no loop is
            # required
            allowed_species = {
                site: chemical_symbols[0]
                for site in self._sites.keys()
            }
        else:
            # Loop over the lattice sites to find the allowed species
            allowed_species = {}
            for site, indices in self._sites.items():
                allowed_species[site] = None
                positions = structure.positions[np.array(indices)]
                lattice_sites = primitive_structure.find_lattice_sites_by_positions(
                    positions=positions,
                    fractional_position_tolerance=cluster_space.
                    fractional_position_tolerance)
                for l, lattice_site in enumerate(lattice_sites):
                    species = chemical_symbols[lattice_site.index]
                    # check that the allowed species are equal for all sites
                    if allowed_species[site] is not None and \
                            species != allowed_species[site]:
                        raise Exception("The allowed species {} for the site"
                                        " with index {} differs from the"
                                        " result {} for the previous index"
                                        " ({})!".format(
                                            species, indices[l],
                                            allowed_species[site],
                                            indices[l - 1]))
                    allowed_species[site] = species

        self._allowed_species = allowed_species
    def test_get_local_cluster_vector(self):
        """Tests the get local clustervector method."""

        cpp_calc = _ClusterExpansionCalculator(
            self.cs, Structure.from_atoms(self.structure),
            self.cs.fractional_position_tolerance)

        index = 4
        cpp_calc.get_local_cluster_vector(self.structure.get_atomic_numbers(),
                                          index, [])

        self.structure[index].symbol = 'Ge'

        cpp_calc.get_local_cluster_vector(self.structure.get_atomic_numbers(),
                                          index, [])
Example #19
0
    def setUp(self):
        """Instantiates class before each test."""
        structure = Structure.from_atoms(bulk('Al'))
        lattice_site_for_cluster = [
            LatticeSite(0, [i, 0, 0]) for i in range(3)
        ]

        self.pair_cluster = Cluster(
            structure,
            [lattice_site_for_cluster[0], lattice_site_for_cluster[1]], True)
        self.triplet_cluster = Cluster(structure, lattice_site_for_cluster,
                                       True)

        self.orbit_pair = Orbit(self.pair_cluster)
        self.orbit_triplet = Orbit(self.triplet_cluster)
    def __init__(self, *args, **kwargs):
        super(TestMatrixOfEquivalentPositions, self).__init__(*args, **kwargs)

        self.position_tolerance = 1e-6
        self.symprec = 1e-6
        self.fractional_position_tolerance = 1e-7
        self.structure = bulk('Ni', 'hcp', a=3.0).repeat([2, 2, 1])
        self.cutoff = 5.0
        self.structure_prim = get_primitive_structure(self.structure)
        icet_structure_prim = Structure.from_atoms(self.structure_prim)
        neighbor_list = get_neighbor_lists(
            self.structure_prim,
            cutoffs=[self.cutoff],
            position_tolerance=self.position_tolerance)[0]
        self.frac_positions = get_fractional_positions_from_neighbor_list(
            icet_structure_prim, neighbor_list)
Example #21
0
    def get_supercell_orbit_list(self, structure: Atoms,
                                 fractional_position_tolerance: float):
        """
        Returns an orbit list for a supercell structure.

        Parameters
        ----------
        structure
            supercell atomic structure
        fractional_position_tolerance : float
            tolerance applied when comparing positions in fractional coordinates
        """
        lolg = LocalOrbitListGenerator(
            self,
            structure=Structure.from_atoms(structure),
            fractional_position_tolerance=fractional_position_tolerance)
        supercell_orbit_list = lolg.generate_full_orbit_list()
        return supercell_orbit_list
Example #22
0
    def _generate_counts(self, structure: Atoms) -> None:
        """Counts the occurrence of different clusters and stores this
        information in a pandas dataframe.

        Parameters
        ----------
        structure
            input atomic structure.
        """
        self._cluster_counts_cpp.count_orbit_list(
            Structure.from_atoms(structure), self._full_orbit_list, True, True,
            self._max_orbit)

        # Getting the empty counts sometimes constitutes a large part of the total time.
        # Thus copy a previously constructed dictionary.
        # Since Cluster is not picklable, we need to do a slightly awkward manual copy.
        empty_counts = {
            cluster: copy.deepcopy(item)
            for cluster, item in self._empty_counts.items()
        }
        pandas_rows = []

        # std::unordered_map<Cluster, std::map<std::vector<int>, int>>
        cluster_counts = self._cluster_counts_cpp.get_cluster_counts()

        for cluster_key, chemical_number_counts_dict in cluster_counts.items():

            for chemical_symbols in empty_counts[cluster_key].keys():

                count = chemical_number_counts_dict.get(chemical_symbols, 0)
                pandas_row = {}
                pandas_row['dc_tag'] = '{}_{}'.format(
                    cluster_key.tag, '_'.join(chemical_symbols))
                pandas_row['occupation'] = chemical_symbols
                pandas_row['cluster_count'] = count
                pandas_row['orbit_index'] = cluster_key.tag
                pandas_row['order'] = len(cluster_key)
                pandas_row['radius'] = cluster_key.radius
                pandas_rows.append(pandas_row)
        self.count_frame = pd.DataFrame(pandas_rows)
        self._cluster_counts_cpp.reset()
    def test_find_lattice_site_by_position_hard(self):
        """
        Tests finding lattice site by position, hard version tests against hcp,
        many atoms in the basis AND pbc = [True, True, False] !
        1. Create a bunch of lattice sites all with index 0 and
        integer unitcell offsets
        2. convert these to x,y,z positions. Nothing strange so far
        3. Find lattice site from the position and assert that it should
           be equivalent to the original lattice site.
        """
        ase_atoms = self.ase_atoms.repeat([3, 5, 5])

        # Set pbc false in Z-direction and add vacuum
        ase_atoms.pbc = [True, True, False]
        ase_atoms.center(30, axis=[2])
        icet_structure = Structure.from_atoms(ase_atoms)
        noise_position = []

        lattice_sites = []
        unit_cell_range = 100
        for j in range(500):
            offset = [
                random.randint(-unit_cell_range, unit_cell_range)
                for i in range(3)
            ]
            offset[2] = 0
            index = random.randint(0, len(ase_atoms) - 1)
            noise_position.append(
                [self.noise * random.uniform(-1, 1) for i in range(3)])

            lattice_sites.append(LatticeSite(index, offset))

        positions = []
        for i, site in enumerate(lattice_sites):
            pos = icet_structure.get_position(site)
            pos += np.array(noise_position[i])
            positions.append(pos)
        for site, pos in zip(lattice_sites, positions):
            found_site = icet_structure.find_lattice_site_by_position(
                pos, self.fractional_position_tolerance)
            self.assertEqual(site, found_site)
Example #24
0
    def test_mbnl_cubic_non_pbc(self):
        """
        Tests that corners sites in a large cubic cell have
        only three neighbors in many-body neighbor list.
        """
        structure = bulk('Al', 'sc', a=4.0).repeat(4)
        structure.set_pbc(False)

        neighbor_lists = get_neighbor_lists(Structure.from_atoms(structure),
                                            self.cutoffs,
                                            self.position_tolerance)

        mbnl = ManyBodyNeighborList()
        # atomic indices located at the corner of structure
        corner_sites = [0, 3, 12, 15, 48, 51, 60, 63]
        for index in corner_sites:
            lattice_neighbor = mbnl.build(neighbor_lists, index, True)
            # check pairs
            self.assertEqual(len(lattice_neighbor[1][1]), 3)
            # not neighbors besides above pairs
            with self.assertRaises(IndexError):
                lattice_neighbor[2]
Example #25
0
    def test_mbnl_non_pbc(self):
        """Tests many-body neighbor list for non-pbc structure."""
        structure = self.structure.copy()
        structure.set_pbc([False])
        neighbor_lists = get_neighbor_lists(Structure.from_atoms(structure),
                                            self.cutoffs,
                                            self.position_tolerance)

        mbnl = ManyBodyNeighborList()

        target = [([LatticeSite(0, [0, 0, 0])], []),
                  ([LatticeSite(0, [0, 0, 0])], [
                      LatticeSite(1, [0, 0, 0]),
                      LatticeSite(2, [0, 0, 0]),
                      LatticeSite(4, [0, 0, 0]),
                      LatticeSite(5, [0, 0, 0]),
                      LatticeSite(6, [0, 0, 0])
                  ]),
                  ([LatticeSite(0, [0, 0, 0]),
                    LatticeSite(1, [0, 0, 0])], [
                        LatticeSite(2, [0, 0, 0]),
                        LatticeSite(4, [0, 0, 0]),
                        LatticeSite(5, [0, 0, 0]),
                        LatticeSite(6, [0, 0, 0])
                    ]),
                  ([LatticeSite(0, [0, 0, 0]),
                    LatticeSite(2, [0, 0, 0])], [LatticeSite(6, [0, 0, 0])]),
                  ([LatticeSite(0, [0, 0, 0]),
                    LatticeSite(4, [0, 0, 0])],
                   [LatticeSite(5, [0, 0, 0]),
                    LatticeSite(6, [0, 0, 0])]),
                  ([LatticeSite(0, [0, 0, 0]),
                    LatticeSite(5, [0, 0, 0])], [LatticeSite(6, [0, 0, 0])])]

        neighbors_non_pbc = mbnl.build(neighbor_lists, 0, False)

        for k, latt_neighbors in enumerate(neighbors_non_pbc):
            self.assertEqual(target[k], latt_neighbors)
Example #26
0
def _from_python(ase_structure: Atoms,
                 lattice_sites: List[LatticeSite],
                 cluster_index: int = -1):
    """
    Constructs a cluster from an ASE Atoms object and Python lattice sites.

    Parameters
    ----------
    ase_structure
        structure as ASE Atoms object
    lattice_sites
        lattice site objects
    cluster_index
        index used to identify cluster
    """

    structure = Structure.from_atoms(ase_structure)

    lattice_sites_cpp = [
        LatticeSite(ls.index, ls.unitcell_offset) for ls in lattice_sites
    ]

    return Cluster(structure, lattice_sites_cpp, cluster_index)
    def test_find_lattice_site_by_position_medium(self):
        """
        Tests finding lattice site by position, medium version
        tests against hcp and user more than one atom in the basis
        1. Create a bunch of lattice sites all with index 0 and
        integer unitcell offsets
        2. convert these to x,y,z positions. Nothing strange so far
        3. Find lattice site from the position and assert that it should
           be equivalent to the original lattice site.
        """
        ase_atoms = self.ase_atoms.repeat([3, 2, 5])

        icet_structure = Structure.from_atoms(ase_atoms)
        lattice_sites = []
        unit_cell_range = 1000
        noise_position = []

        for j in range(5000):
            offset = [
                random.randint(-unit_cell_range, unit_cell_range)
                for i in range(3)
            ]
            index = random.randint(0, len(ase_atoms) - 1)
            noise_position.append(
                [self.noise * random.uniform(-1, 1) for i in range(3)])
            lattice_sites.append(LatticeSite(index, offset))

        positions = []
        for i, site in enumerate(lattice_sites):
            pos = icet_structure.get_position(site)
            pos = pos + np.array(noise_position[i])
            positions.append(pos)
        for site, pos in zip(lattice_sites, positions):
            found_site = icet_structure.find_lattice_site_by_position(
                pos, self.fractional_position_tolerance)

            self.assertEqual(site, found_site)
Example #28
0
import numpy as np
from icet.core.structure import Structure
from ase.db import connect
from ase.neighborlist import NeighborList as ASENeighborList
"""
Testing the calculation of distances with offsets
TODO:
    Delete this after edit unittest/test_structure
"""
""" Fetch structures from database """
db = connect('structures_for_testing.db')
for row in db.select():
    structure = row.toatoms()
    nl = ASENeighborList(len(structure) * [2.6], self_interaction=False)
    nl.update(structure)
    for index in range(len(structure)):
        indices, offsets = nl.get_neighbors(index)
        for i, offset in zip(indices, offsets):
            dvec = structure.positions[index] - structure.positions[i]
            dvec -= np.dot(offset, structure.cell)
            dist_ase = np.linalg.norm(dvec)
            dist_struct = Structure.from_atoms(structure).get_distance(
                index, i, [0, 0, 0], offset)
            msg = 'Testing distance calculator failed'
            msg += ' for structure {}'.format(row.tag)
            assert dist_ase - dist_struct < 1e-8, msg
class TestStructure(unittest.TestCase):
    """Container for test of the module functionality."""
    def __init__(self, *args, **kwargs):
        super(TestStructure, self).__init__(*args, **kwargs)
        self.ase_atoms = bulk('Ag', 'hcp', a=2.0)
        self.noise = 1e-6
        self.fractional_position_tolerance = 2e-6
        self.positions = [[0., 0., 0.], [0., 1.15470054, 1.63299316]]
        self.chemical_symbols = ['Ag', 'Ag']
        self.cell = [[2., 0., 0.], [-1., 1.73205081, 0.], [0., 0., 3.26598632]]

    def shortDescription(self):
        """Silences unittest from printing the docstrings in test cases."""
        return None

    def setUp(self):
        """Setup before each test."""
        self.icet_structure = Structure(positions=self.positions,
                                        chemical_symbols=self.chemical_symbols,
                                        cell=self.cell,
                                        pbc=[True, True, True])
        random.seed(113)

    def test_positions(self):
        """Tests positions of atoms in structure."""
        for i, vec in enumerate(self.icet_structure.positions):
            self.assertListEqual(vec.tolist(), self.positions[i])
        new_positions = [[0., 0., 0.001], [0., 1.15470054, 1.63299316]]
        self.icet_structure.positions = new_positions
        retval = self.icet_structure.positions
        for i, vec in enumerate(retval):
            self.assertListEqual(vec.tolist(), new_positions[i])

    def test_chemical_symbols(self):
        """Tests chemical symbols of atoms in structure."""
        self.assertListEqual(self.icet_structure.chemical_symbols,
                             self.chemical_symbols)

    def test_atomic_numbers(self):
        """Tests atomic numbers."""
        self.assertListEqual(self.icet_structure.atomic_numbers, [47, 47])

    def test_cell(self):
        """Tests cell."""
        for i, vec in enumerate(self.icet_structure.cell):
            self.assertListEqual(vec.tolist(), self.cell[i])
        new_cell = [[2., 0., 0.], [-1., 2., 0.], [0., 0., 4.]]
        self.icet_structure.cell = new_cell
        retval = self.icet_structure.cell
        for i, vec in enumerate(retval):
            self.assertListEqual(vec.tolist(), new_cell[i])

    def test_pbc(self):
        """Tests periodic boundary conditions."""
        self.assertListEqual(self.icet_structure.pbc, [True, True, True])
        self.icet_structure.pbc = [True, True, False]
        retval = self.icet_structure.pbc
        self.assertListEqual(retval, [True, True, False])

    def test_unique_sites(self):
        """Tests unique sites."""
        self.assertListEqual(self.icet_structure.unique_sites, [0, 0])

    def test_set_and_get_chemical_symbols(self):
        """Tests set and get chemical symbols."""
        new_chemical_symbols = ['Au', 'Au']
        self.icet_structure.set_chemical_symbols(new_chemical_symbols)
        retval = self.icet_structure.get_chemical_symbols()
        self.assertListEqual(retval, new_chemical_symbols)

    def test_set_and_get_atomic_numbers(self):
        """Tests set and get atomic numbers."""
        self.icet_structure.set_atomic_numbers([48, 47])
        retval = self.icet_structure.get_atomic_numbers()
        self.assertListEqual(retval, [48, 47])

    def test_set_and_get_unique_sites(self):
        """Tests set and get unique sites."""
        self.icet_structure.set_unique_sites([0, 1])
        retval = self.icet_structure.get_unique_sites()
        self.assertListEqual(retval, [0, 1])

    def test_get_position(self):
        """Tests get_position functionality."""
        retval = self.icet_structure.get_position(LatticeSite(1, [0, 0, 0]))
        self.assertListEqual(retval.tolist(), self.positions[1])

    def test_get_distance(self):
        """Tests get_distance functionality."""
        retval = self.icet_structure.get_distance(0, 1, [0., 0., 0.],
                                                  [0., 0., 0.])

        target = self.icet_structure.get_distance(0, 1)
        self.assertAlmostEqual(retval, target)

    def test_find_lattice_site_by_position_with_tolerance(self):
        """Tests the find lattice site by position method
           by varying the tolerance
           """
        atoms = bulk('Al', crystalstructure='hcp', a=3).repeat(2)

        icet_structure = Structure.from_atoms(atoms)

        def _test_lattice_site_find(tol, noise, index):
            for i in range(3):
                position = atoms.positions[index]
                position[i] += noise
                ls = icet_structure.find_lattice_site_by_position(
                    position, tol)
                self.assertEqual(ls.index, index)

                position = atoms.positions[index]
                position[i] -= noise
                ls = icet_structure.find_lattice_site_by_position(
                    position, tol)
                self.assertEqual(ls.index, index)

        # First with noise smaller thant tol
        tol = 1e-5
        noise = 5e-6
        for index in range(len(atoms)):
            _test_lattice_site_find(tol, noise, index)

        # Increase tolerance and force a fail
        tol = 1e-5
        noise = 5e-5
        for index in range(len(atoms)):
            with self.assertRaises(Exception) as context:
                _test_lattice_site_find(tol, noise, index)
            self.assertIn('Failed to find site by position',
                          str(context.exception))

        # Large noise  but larger tol
        tol = 1e-3
        noise = 5e-4
        for index in range(len(atoms)):
            _test_lattice_site_find(tol, noise, index)

        # Large tol but larger noise
        tol = 1e-3
        noise = 5e-3
        for index in range(len(atoms)):
            with self.assertRaises(Exception) as context:
                _test_lattice_site_find(tol, noise, index)
            self.assertIn('Failed to find site by position',
                          str(context.exception))

    def test_find_lattice_site_by_position_simple(self):
        """
        Tests finding lattice site by position, simple version using
        only one atom cell.

        1. Create a bunch of lattice sites all with index 0 and
        integer unitcell offsets
        2. convert these to x,y,z positions. Nothing strange so far
        3. Find lattice site from the position and assert that it should
           be equivalent to the original lattice site.
        """
        lattice_sites = []
        noise_position = []
        unit_cell_range = 1000
        for j in range(5000):
            offset = [
                random.randint(-unit_cell_range, unit_cell_range)
                for i in range(3)
            ]
            noise_position.append(
                [self.noise * random.uniform(-1, 1) for i in range(3)])
            lattice_sites.append(LatticeSite(0, offset))

        positions = []
        for i, site in enumerate(lattice_sites):
            # Get position with a little noise
            pos = self.icet_structure.get_position(site)
            pos = pos + np.array(noise_position[i])
            positions.append(pos)
        for site, pos in zip(lattice_sites, positions):
            found_site = self.icet_structure.find_lattice_site_by_position(
                pos, self.fractional_position_tolerance)
            self.assertEqual(site, found_site)

    def test_find_lattice_site_by_position_medium(self):
        """
        Tests finding lattice site by position, medium version
        tests against hcp and user more than one atom in the basis
        1. Create a bunch of lattice sites all with index 0 and
        integer unitcell offsets
        2. convert these to x,y,z positions. Nothing strange so far
        3. Find lattice site from the position and assert that it should
           be equivalent to the original lattice site.
        """
        ase_atoms = self.ase_atoms.repeat([3, 2, 5])

        icet_structure = Structure.from_atoms(ase_atoms)
        lattice_sites = []
        unit_cell_range = 1000
        noise_position = []

        for j in range(5000):
            offset = [
                random.randint(-unit_cell_range, unit_cell_range)
                for i in range(3)
            ]
            index = random.randint(0, len(ase_atoms) - 1)
            noise_position.append(
                [self.noise * random.uniform(-1, 1) for i in range(3)])
            lattice_sites.append(LatticeSite(index, offset))

        positions = []
        for i, site in enumerate(lattice_sites):
            pos = icet_structure.get_position(site)
            pos = pos + np.array(noise_position[i])
            positions.append(pos)
        for site, pos in zip(lattice_sites, positions):
            found_site = icet_structure.find_lattice_site_by_position(
                pos, self.fractional_position_tolerance)

            self.assertEqual(site, found_site)

    def test_find_lattice_site_by_position_hard(self):
        """
        Tests finding lattice site by position, hard version tests against hcp,
        many atoms in the basis AND pbc = [True, True, False] !
        1. Create a bunch of lattice sites all with index 0 and
        integer unitcell offsets
        2. convert these to x,y,z positions. Nothing strange so far
        3. Find lattice site from the position and assert that it should
           be equivalent to the original lattice site.
        """
        ase_atoms = self.ase_atoms.repeat([3, 5, 5])

        # Set pbc false in Z-direction and add vacuum
        ase_atoms.pbc = [True, True, False]
        ase_atoms.center(30, axis=[2])
        icet_structure = Structure.from_atoms(ase_atoms)
        noise_position = []

        lattice_sites = []
        unit_cell_range = 100
        for j in range(500):
            offset = [
                random.randint(-unit_cell_range, unit_cell_range)
                for i in range(3)
            ]
            offset[2] = 0
            index = random.randint(0, len(ase_atoms) - 1)
            noise_position.append(
                [self.noise * random.uniform(-1, 1) for i in range(3)])

            lattice_sites.append(LatticeSite(index, offset))

        positions = []
        for i, site in enumerate(lattice_sites):
            pos = icet_structure.get_position(site)
            pos += np.array(noise_position[i])
            positions.append(pos)
        for site, pos in zip(lattice_sites, positions):
            found_site = icet_structure.find_lattice_site_by_position(
                pos, self.fractional_position_tolerance)
            self.assertEqual(site, found_site)

    def test_structure_from_atoms(self):
        """Tests ASE Atoms-to-icet Structure conversion."""
        icet_structure = Structure.from_atoms(self.ase_atoms)
        for icet_pos, ase_pos in zip(icet_structure.positions,
                                     self.ase_atoms.positions):
            self.assertListEqual(icet_pos.tolist(), ase_pos.tolist())

        chem_symbols = icet_structure.get_chemical_symbols()
        self.assertListEqual(chem_symbols, ['Ag', 'Ag'])

    def test_structure_to_atoms(self):
        """Tests icet Structure-to-ASE Atoms conversion."""
        ase_structure = Structure.to_atoms(self.icet_structure)
        for ase_pos, icet_pos in zip(ase_structure.positions,
                                     self.icet_structure.positions):
            self.assertListEqual(ase_pos.tolist(), icet_pos.tolist())

        chem_symbols = ase_structure.get_chemical_symbols()
        self.assertListEqual(chem_symbols, ['Ag', 'Ag'])

    def test_repr_function(self):
        """Tests string representation."""
        retval = self.icet_structure.__repr__()
        target = """
Cell:
[[ 2.          0.          0.        ]
 [-1.          1.73205081  0.        ]
 [ 0.          0.          3.26598632]]

Element and positions:
Ag  [0.0  0.0  0.0]
Ag  [0.0  1.15470054  1.63299316]
"""
        self.assertEqual(strip_surrounding_spaces(retval),
                         strip_surrounding_spaces(target))
Example #30
0
 def setUp(self):
     """Instantiates class before each test."""
     self.mbnl = ManyBodyNeighborList()
     structure = Structure.from_atoms(self.structure)
     self.neighbor_lists = get_neighbor_lists(structure, self.cutoffs,
                                              self.position_tolerance)