Esempio n. 1
0
 def test_pdf_primitive_vs_supercell(self):
     test_doc, success = res2dict(REAL_PATH + "data/KP_primitive.res",
                                  db=False)
     test_doc["text_id"] = ["primitive", "cell"]
     test_doc["lattice_cart"] = abc2cart(test_doc["lattice_abc"])
     test_doc["cell_volume"] = cart2volume(test_doc["lattice_cart"])
     supercell_doc, success = res2dict(REAL_PATH + "data/KP_supercell.res",
                                       db=False)
     supercell_doc["text_id"] = ["supercell", "cell"]
     supercell_doc["lattice_cart"] = abc2cart(supercell_doc["lattice_abc"])
     supercell_doc["cell_volume"] = cart2volume(
         supercell_doc["lattice_cart"])
     test_doc["pdf"] = PDF(test_doc,
                           dr=0.01,
                           low_mem=True,
                           rmax=10,
                           num_images="auto",
                           debug=DEBUG)
     supercell_doc["pdf"] = PDF(
         supercell_doc,
         dr=0.01,
         low_mem=True,
         rmax=10,
         num_images="auto",
         debug=DEBUG,
     )
     overlap = PDFOverlap(test_doc["pdf"], supercell_doc["pdf"])
     self.assertLessEqual(overlap.similarity_distance, 1e-3)
     self.assertGreaterEqual(overlap.similarity_distance, 0.0)
Esempio n. 2
0
    def test_spg_standardize(self):
        from matador.utils.cell_utils import standardize_doc_cell
        from matador.scrapers import cif2dict
        import glob

        doc, s = castep2dict(REAL_PATH +
                             "data/Na3Zn4-swap-ReOs-OQMD_759599.castep")
        std_doc = standardize_doc_cell(doc)
        dist = pdf_sim_dist(doc, std_doc)
        self.assertLess(dist, 0.01)

        fnames = glob.glob(REAL_PATH + "data/bs_test/*.res")
        for fname in fnames:
            doc, s = res2dict(fname, db=False)
            doc["cell_volume"] = cart2volume(doc["lattice_cart"])
            std_doc = standardize_doc_cell(doc)
            dist = pdf_sim_dist(doc, std_doc)
            self.assertLess(dist, 0.01)

        doc = Crystal(
            castep2dict(REAL_PATH +
                        "data/Na3Zn4-swap-ReOs-OQMD_759599.castep")[0])
        std_doc = standardize_doc_cell(doc)
        dist = pdf_sim_dist(doc, std_doc)
        self.assertLess(dist, 0.01)

        doc = Crystal(cif2dict(REAL_PATH + "data/cif_files/AgBiI.cif")[0])
        with self.assertRaises(RuntimeError):
            std_doc = standardize_doc_cell(doc)
Esempio n. 3
0
 def test_cart2abc(self):
     castep_fname = REAL_PATH + "data/Na3Zn4-swap-ReOs-OQMD_759599.castep"
     self.assertTrue(os.path.isfile(castep_fname))
     test_doc, s = castep2dict(castep_fname, db=True, verbosity=VERBOSITY)
     try:
         self.assertTrue(
             np.allclose(test_doc["lattice_abc"],
                         cart2abc(test_doc["lattice_cart"])),
             msg="Conversion cart2abc failed.",
         )
         self.assertTrue(
             np.allclose(
                 cart2abc(test_doc["lattice_cart"]),
                 cart2abc(abc2cart(test_doc["lattice_abc"])),
             ),
             msg="Conversion abc2cart failed.",
         )
         self.assertAlmostEqual(
             test_doc["cell_volume"],
             cart2volume(test_doc["lattice_cart"]),
             msg="Failed to calculate volume from lattice vectors.",
             places=5,
         )
         self.assertIsInstance(test_doc["lattice_abc"],
                               list,
                               msg="Failed abc numpy cast to list")
         self.assertIsInstance(
             test_doc["lattice_cart"],
             list,
             msg="Failed cartesian numpy cast to list",
         )
         cart_pos = frac2cart(test_doc["lattice_cart"],
                              test_doc["positions_frac"])
         back2frac = cart2frac(test_doc["lattice_cart"], cart_pos)
         np.testing.assert_array_almost_equal(back2frac,
                                              test_doc["positions_frac"])
     except AssertionError:
         print("cart:", test_doc["lattice_cart"],
               abc2cart(test_doc["lattice_abc"]))
         print("abc:", test_doc["lattice_abc"],
               cart2abc(test_doc["lattice_cart"]))
         print(
             "volume:",
             test_doc["cell_volume"],
             cart2volume(test_doc["lattice_cart"]),
         )
         raise AssertionError
Esempio n. 4
0
def pwout2dict(fname, **kwargs):
    """ Extract available information from pw.x .out file.

    Parameters:
        fname (str/list): filename or list of filenames to scrape as a
            QuantumEspresso pw.x output.

    """
    flines, fname = get_flines_extension_agnostic(fname, ["out", "in"])

    pwout = {}
    pwout['source'] = [fname]

    try:
        # grab file owner username
        from pwd import getpwuid
        pwout['user'] = getpwuid(stat(fname).st_uid).pw_name
    except Exception:
        pwout['user'] = '******'

    if 'CollCode' in fname:
        pwout['icsd'] = fname.split('CollCode')[-1]
    for ind, line in enumerate(reversed(flines)):
        ind = len(flines) - 1 - ind
        if 'cell_parameters' in line.lower() and 'angstrom' in line.lower(
        ) and 'lattice_cart' not in pwout:
            pwout['lattice_cart'] = []
            for j in range(3):
                line = flines[ind + j + 1].strip().split()
                pwout['lattice_cart'].append(list(map(float, line)))
            pwout['cell_volume'] = cart2volume(pwout['lattice_cart'])
        elif 'atomic_positions' in line.lower(
        ) and 'positions_frac' not in pwout:
            pwout['positions_frac'] = []
            pwout['atom_types'] = []
            j = 1
            while True:
                if 'End final coordinates' in flines[j + ind]:
                    break
                else:
                    try:
                        line = flines[j + ind].strip().split()
                        pwout['atom_types'].append(line[0])
                        pwout['positions_frac'].append(
                            list(map(float, line[1:5])))
                        j += 1
                    except Exception:
                        break
            pwout['num_atoms'] = len(pwout['atom_types'])
        elif 'final enthalpy' in line.lower() and 'enthalpy' not in pwout:
            pwout['enthalpy'] = RY_TO_EV * float(line.lower().split()[-2])
        elif 'total   stress' in line.lower() and 'pressure' not in pwout:
            pwout['pressure'] = KBAR_TO_GPA * float(line.lower().split()[-1])
        elif all(key in pwout for key in
                 ['enthalpy', 'pressure', 'lattice_cart', 'positions_frac']):
            break
    # get abc lattice
    pwout['lattice_abc'] = cart2abc(pwout['lattice_cart'])
    # calculate stoichiometry
    pwout['stoichiometry'] = defaultdict(float)
    for atom in pwout['atom_types']:
        if atom not in pwout['stoichiometry']:
            pwout['stoichiometry'][atom] = 0
        pwout['stoichiometry'][atom] += 1
    gcd_val = 0
    for atom in pwout['atom_types']:
        if gcd_val == 0:
            gcd_val = pwout['stoichiometry'][atom]
        else:
            gcd_val = gcd(pwout['stoichiometry'][atom], gcd_val)
    # convert stoichiometry to tuple for fryan
    temp_stoich = []
    for key, value in pwout['stoichiometry'].items():
        if float(value) / gcd_val % 1 != 0:
            temp_stoich.append([key, float(value) / gcd_val])
        else:
            temp_stoich.append([key, value / gcd_val])
    pwout['stoichiometry'] = temp_stoich
    atoms_per_fu = 0
    for elem in pwout['stoichiometry']:
        atoms_per_fu += elem[1]
    pwout['num_fu'] = len(pwout['atom_types']) / atoms_per_fu

    return pwout, True
Esempio n. 5
0
def cif2dict(fname, **kwargs):
    """ Extract available information from  .cif file and store as a
    dictionary. Raw cif data is stored under the `'_cif'` key. Symmetric
    sites are expanded by the symmetry operations and their occupancies
    are tracked.

    Parameters:
        fname (str/list): filename or list of filenames of .cif file(s)
            (with or without extension).

    Returns:
        (dict/str, bool): if successful, a dictionary containing scraped
            data and True, if not, then an error string and False.


    """

    flines, fname = get_flines_extension_agnostic(fname, "cif")

    doc = dict()
    cif_dict = _cif_parse_raw(flines)

    doc['_cif'] = cif_dict
    doc['source'] = [str(Path(fname).resolve())]

    doc['atom_types'] = []
    atom_labels = cif_dict.get("_atom_site_type_symbol", False)
    if not atom_labels:
        atom_labels = cif_dict.get("_atom_site_label", False)
    if not atom_labels:
        raise RuntimeError(f"Unable to find atom types in cif file {fname}.")

    for atom in atom_labels:
        symbol = ''
        for character in atom:
            if not character.isalpha():
                break
            else:
                symbol += character
        doc['atom_types'].append(symbol)

    doc['positions_frac'] = [list(map(lambda x: float(x.split('(')[0]), vector)) for vector in
                             zip(cif_dict['_atom_site_fract_x'],
                                 cif_dict['_atom_site_fract_y'],
                                 cif_dict['_atom_site_fract_z'])]

    if '_atom_site_occupancy' in cif_dict:
        doc['site_occupancy'] = [float(x.split('(')[0]) for x in cif_dict['_atom_site_occupancy']]
    else:
        doc['site_occupancy'] = [1.0 for _ in doc['positions_frac']]

    if '_atom_site_symmetry_multiplicity' in cif_dict:
        doc['site_multiplicity'] = [float(x.split('(')[0]) for x in cif_dict['_atom_site_symmetry_multiplicity']]
    else:
        doc['site_multiplicity'] = [1.0 for _ in doc['positions_frac']]

    doc['lattice_abc'] = [list(map(_cif_parse_float_with_errors,
                                   [cif_dict['_cell_length_a'],
                                    cif_dict['_cell_length_b'],
                                    cif_dict['_cell_length_c']])),
                          list(map(_cif_parse_float_with_errors,
                                   [cif_dict['_cell_angle_alpha'],
                                    cif_dict['_cell_angle_beta'],
                                    cif_dict['_cell_angle_gamma']]))]

    doc['lattice_cart'] = abc2cart(doc['lattice_abc'])
    doc['cell_volume'] = cart2volume(doc['lattice_cart'])
    doc['stoichiometry'] = _cif_disordered_stoichiometry(doc)
    doc['num_atoms'] = len(doc['positions_frac'])

    if '_space_group_symop_operation_xyz' in doc['_cif'] and '_symmetry_equiv_pos_as_xyz' not in doc['_cif']:
        doc["_cif"]["_symmetry_equiv_pos_as_xyz"] = doc["_cif"]["_space_group_symop_operation_xyz"]
    if '_symmetry_equiv_pos_as_xyz' in doc['_cif']:
        _cif_set_unreduced_sites(doc)

    try:
        doc['space_group'] = get_spacegroup_spg(doc, check_occ=False)
    except RuntimeError:
        pass

    return doc, True
Esempio n. 6
0
    def construct_structure_attributes(self, doc: Crystal):

        structure_attributes = {}
        # from optimade StructureResourceAttributes
        structure_attributes["elements"] = doc.elems
        structure_attributes["nelements"] = len(doc.elems)

        concentration = get_concentration(doc._data,
                                          elements=doc.elems,
                                          include_end=True)
        structure_attributes["elements_ratios"] = concentration
        structure_attributes["chemical_formula_descriptive"] = doc.formula
        structure_attributes["chemical_formula_reduced"] = doc.formula
        structure_attributes["chemical_formula_hill"] = None

        sorted_stoich = sorted(doc.stoichiometry,
                               key=lambda x: x[1],
                               reverse=True)
        gen = anonymous_element_generator()
        for ind, elem in enumerate(sorted_stoich):
            elem[0] = next(gen)

        structure_attributes[
            "chemical_formula_anonymous"] = get_formula_from_stoich(
                doc.stoichiometry,
                elements=[elem[0] for elem in sorted_stoich])
        structure_attributes["dimension_types"] = [1, 1, 1]
        structure_attributes["nperiodic_dimensions"] = 3
        structure_attributes["lattice_vectors"] = doc.lattice_cart
        structure_attributes["lattice_abc"] = doc.lattice_abc
        structure_attributes["cell_volume"] = cart2volume(doc.lattice_cart)
        structure_attributes["fractional_site_positions"] = doc.positions_frac
        structure_attributes["cartesian_site_positions"] = doc.positions_abs
        structure_attributes["nsites"] = doc.num_atoms
        structure_attributes["species_at_sites"] = doc.atom_types

        species = []
        for ind, atom in enumerate(doc.elems):
            species.append(
                Species(name=atom,
                        chemical_symbols=[atom],
                        concentration=[1.0]))

            structure_attributes["species"] = species
        structure_attributes["assemblies"] = None
        structure_attributes["structure_features"] = []

        # from optimade EntryResourceAttributes
        if "text_id" not in doc._data:
            structure_attributes["local_id"] = " ".join([
                self.wlines[random.randint(0, self.num_words - 1)].strip(),
                self.nlines[random.randint(0, self.num_nouns - 1)].strip(),
            ])
        else:
            structure_attributes["local_id"] = " ".join(doc._data["text_id"])
        structure_attributes["last_modified"] = datetime.datetime.now()
        if "_id" in doc._data:
            structure_attributes["immutable_id"] = str(doc._data["_id"])
        else:
            structure_attributes["immutable_id"] = str(
                bson.objectid.ObjectId())
        # if "date" in doc._data:
        # date = [int(val) for val in doc._data["date"].split("-")]
        # structure_attributes["date"] = datetime.date(
        # year=date[-1], month=date[1], day=date[0]
        # )

        # from matador extensions
        structure_attributes[
            "dft_parameters"] = self.construct_dft_hamiltonian(doc)
        structure_attributes["submitter"] = self.construct_submitter(doc)
        structure_attributes["thermodynamics"] = self.construct_thermodynamics(
            doc)
        structure_attributes["space_group"] = self.construct_spacegroup(doc)
        structure_attributes["calculator"] = self.construct_calculator(doc)

        structure_attributes["stress_tensor"] = doc._data.get("stress")
        structure_attributes["stress"] = doc._data["pressure"]
        structure_attributes["forces"] = doc._data.get("forces")
        structure_attributes["max_force_on_atom"] = doc._data.get(
            "max_force_on_atom")

        return MatadorStructureResourceAttributes(**structure_attributes)
Esempio n. 7
0
def random_slice(parent_seeds,
                 standardize=True,
                 supercell=True,
                 shift=True,
                 debug=False):
    """ Simple cut-and-splice crossover of two parents.

    The overall size of the child can vary between 0.5 and 1.5 the size of the
    parent structures. Both parent structures are cut and spliced along the
    same crystallographic axis.

    Parameters:

        parents (list(dict)) : parent structures to crossover,
        standardize (bool)   : use spglib to standardize parents pre-crossover,
        supercell (bool)     : make a random supercell to rescale parents,
        shift (bool)         : randomly shift atoms in parents to unbias.

    Returns:

        dict: newborn structure from parents.

    """
    parents = deepcopy(parent_seeds)
    child = dict()
    # child_size is a number between 0.5 and 2
    child_size = 0.5 + 1.5 * np.random.rand()
    # cut_val is a number between 0.25*child_size and 0.75*child_size
    # the slice position of one parent in fractional coordinates
    # (the other is (child_size-cut_val))
    cut_val = child_size * (0.25 + (np.random.rand() / 2.0))

    parent_densities = []
    for ind, parent in enumerate(parents):
        if "cell_volume" not in parent:
            parents[ind]["cell_volume"] = cart2volume(parent["lattice_cart"])
        parent_densities.append(parent["num_atoms"] / parent["cell_volume"])
    target_density = sum(parent_densities) / len(parent_densities)

    if standardize:
        parents = [standardize_doc_cell(parent) for parent in parents]

    if supercell:
        # check ratio of num atoms in parents and grow the smaller one
        parent_extent_ratio = parents[0]["cell_volume"] / parents[1][
            "cell_volume"]
        if debug:
            print(
                parent_extent_ratio,
                parents[0]["cell_volume"],
                "vs",
                parents[1]["cell_volume"],
            )
        if parent_extent_ratio < 1:
            supercell_factor = int(round(1 / parent_extent_ratio))
            supercell_target = 0
        elif parent_extent_ratio >= 1:
            supercell_factor = int(round(parent_extent_ratio))
            supercell_target = 1
        if debug:
            print(supercell_target, supercell_factor)
        supercell_vector = [1, 1, 1]
        if supercell_factor > 1:
            for ind in range(supercell_factor):
                min_lat_vec_abs = 1e10
                min_lat_vec_ind = -1
                for i in range(3):
                    lat_vec_abs = np.sum(
                        np.asarray(
                            parents[supercell_target]["lattice_cart"][i])**2)
                    if lat_vec_abs < min_lat_vec_abs:
                        min_lat_vec_abs = lat_vec_abs
                        min_lat_vec_ind = i
                supercell_vector[min_lat_vec_ind] += 1
        if debug:
            print("Making supercell of {} with {}".format(
                parents[supercell_target]["source"][0], supercell_vector))
        if supercell_vector != [1, 1, 1]:
            parents[supercell_target] = create_simple_supercell(
                parents[supercell_target], supercell_vector, standardize=False)
    child["positions_frac"] = []
    child["atom_types"] = []
    child["lattice_cart"] = cut_val * np.asarray(
        parents[0]["lattice_cart"]) + (child_size - cut_val) * np.asarray(
            parents[1]["lattice_cart"])
    child["lattice_cart"] = child["lattice_cart"].tolist()

    # choose slice axis
    axis = np.random.randint(low=0, high=3)
    for ind, parent in enumerate(parents):
        if shift:
            # apply same random shift to all atoms in parents
            shift_vec = np.random.rand(3)
            for idx, _ in enumerate(parent["positions_frac"]):
                for k in range(3):
                    parent["positions_frac"][idx][k] += shift_vec[k]
                    if parent["positions_frac"][idx][k] >= 1:
                        parent["positions_frac"][idx][k] -= 1
                    elif parent["positions_frac"][idx][k] < 0:
                        parent["positions_frac"][idx][k] += 1
        # slice parent
        for atom, pos in zip(parent["atom_types"], parent["positions_frac"]):
            if ind == (pos[axis] <= cut_val):
                child["positions_frac"].append(pos)
                child["atom_types"].append(atom)
    # check child is sensible
    child["mutations"] = ["crossover"]
    child["stoichiometry"] = get_stoich(child["atom_types"])
    child["num_atoms"] = len(child["atom_types"])

    if "cell_volume" not in child:
        child["cell_volume"] = cart2volume(child["lattice_cart"])
    number_density = child["num_atoms"] / child["cell_volume"]

    # rescale cell based on number density of parents
    new_scale = np.cbrt(number_density / target_density)
    child["lattice_abc"] = np.asarray(cart2abc(child["lattice_cart"]))
    child["lattice_abc"][0] *= new_scale
    child["lattice_abc"] = child["lattice_abc"].tolist()
    child["lattice_cart"] = abc2cart(child["lattice_abc"])
    child["cell_volume"] = cart2volume(child["lattice_cart"])
    child["positions_abs"] = frac2cart(child["lattice_cart"],
                                       child["positions_frac"])

    return child
Esempio n. 8
0
def check_feasible(mutant,
                   parents,
                   max_num_atoms,
                   structure_filter=None,
                   minsep_dict=None,
                   debug=False):
    """ Check if a mutated/newly-born cell is "feasible".
    Here, feasible means:

      * number density within 25% of pre-mutation/birth level,
      * no overlapping atoms, parameterised by minsep_dict,
      * cell angles between 50 and 130 degrees,
      * fewer than max_num_atoms in the cell,
      * ensure number of atomic types is maintained,
      * any custom filter is obeyed.

    Parameters:
        mutant (dict): matador doc containing new structure.
        parents (list(dict)): list of doc(s) containing parent structures.
        max_num_atoms (int): any structures with more than this many atoms will be filtered out.

    Keyword Arguments:
        structure_filter (callable): any function that takes a matador document and returns True or False.
        minsep_dict (dict): dictionary containing element-specific minimum separations, e.g.
            {('K', 'K'): 2.5, ('K', 'P'): 2.0}.

    Returns:
        bool: True if structure is feasible, else False.

    """
    # first check the structure filter
    if structure_filter is not None and not structure_filter(mutant):
        message = "Mutant with {} failed to pass the custom filter.".format(
            ", ".join(mutant["mutations"]))
        LOG.debug(message)
        if debug:
            print(message)
        return False
    # check number of atoms
    if "num_atoms" not in mutant or mutant["num_atoms"] != len(
            mutant["atom_types"]):
        mutant["num_atoms"] = len(mutant["atom_types"])
    if mutant["num_atoms"] > max_num_atoms:
        message = "Mutant with {} contained too many atoms ({} vs {}).".format(
            ", ".join(mutant["mutations"]), mutant["num_atoms"], max_num_atoms)
        LOG.debug(message)
        if debug:
            print(message)
        return False
    # check number density
    if "cell_volume" not in mutant:
        mutant["cell_volume"] = cart2volume(mutant["lattice_cart"])
    number_density = mutant["num_atoms"] / mutant["cell_volume"]
    parent_densities = []
    for ind, parent in enumerate(parents):
        if "cell_volume" not in parent:
            parents[ind]["cell_volume"] = cart2volume(parent["lattice_cart"])
        parent_densities.append(parent["num_atoms"] / parent["cell_volume"])
    target_density = sum(parent_densities) / len(parent_densities)
    if number_density > 1.5 * target_density or number_density < 0.5 * target_density:
        message = "Mutant with {} failed number density.".format(", ".join(
            mutant["mutations"]))
        LOG.debug(message)
        if debug:
            print(message)
        return False

    # now check element-agnostic minseps
    if not minseps_feasible(mutant, minsep_dict=minsep_dict, debug=debug):
        return False

    # check all cell angles are between 60 and 120.
    if "lattice_abc" not in mutant:
        mutant["lattice_abc"] = cart2abc(mutant["lattice_cart"])

    if min(mutant["lattice_abc"][1]) < 30:
        message = "Mutant with {} failed cell angle check.".format(", ".join(
            mutant["mutations"]))
        LOG.debug(message)
        if debug:
            print(message)
        return False

    if max(mutant["lattice_abc"][1]) > 120:
        message = "Mutant with {} failed cell angle check.".format(", ".join(
            mutant["mutations"]))
        LOG.debug(message)
        if debug:
            print(message)
        return False

    # check that we haven't deleted/transmuted all atoms of a certain type
    if len(set(mutant["atom_types"])) < len(set(parents[0]["atom_types"])):
        message = "Mutant with {} transmutation error.".format(", ".join(
            mutant["mutations"]))
        LOG.debug(message)
        if debug:
            print(message)
        return False
    return True
Esempio n. 9
0
 def volume(self):
     """ The cell volume in ų. """
     if not self._volume:
         self._volume = cell_utils.cart2volume(self._lattice_cart)
     return self._volume
Esempio n. 10
0
    def __init__(self, doc, lazy=False, **kwargs):
        """ Initialise parameters and run PDF (unless lazy=True).

        Parameters:

            doc (dict) : matador document to calculate PDF of

        Keyword Arguments:

            dr (float) : bin width for PDF (Angstrom) (DEFAULT: 0.01)
            gaussian_width (float) : width of Gaussian smearing (Angstrom) (DEFAULT: 0.01)
            num_images (int/str) : number of unit cell images include in PDF calculation (DEFAULT: 'auto')
            max_num_images (int) : cutoff number of unit cells before crashing (DEFAULT: 50)
            rmax (float) : maximum distance cutoff for PDF (Angstrom) (DEFAULT: 15)
            projected (bool) : optionally calculate the element-projected PDF
            standardize (bool) : standardize cell before calculating PDF
            lazy (bool) : if True, calculator is not called when initializing PDF object
            timing (bool) : if True, print the total time taken to calculate the PDF

        """

        prop_defaults = {
            'dr': 0.01,
            'gaussian_width': 0.1,
            'rmax': 15,
            'num_images': 'auto',
            'style': 'smear',
            'debug': False,
            'timing': False,
            'low_mem': False,
            'projected': True,
            'max_num_images': 50,
            'standardize': True
        }

        # read and store kwargs
        self.kwargs = prop_defaults
        self.kwargs.update(
            {key: kwargs[key]
             for key in kwargs if kwargs[key] is not None})

        # useful data for labelling
        self.spg = None
        structure = copy.deepcopy(doc)
        if self.kwargs.get('standardize'):
            structure = standardize_doc_cell(structure)
            self.spg = structure['space_group']
        self.stoichiometry = structure.get('stoichiometry',
                                           get_stoich(structure['atom_types']))

        # private variables
        self._num_images = self.kwargs.get('num_images')
        self._lattice = np.asarray(structure['lattice_cart'])
        self._poscart = np.asarray(
            frac2cart(structure['lattice_cart'],
                      structure['positions_frac'])).reshape(-1, 3)
        self._types = structure['atom_types']
        self._num_atoms = len(self._poscart)
        self._volume = cart2volume(self._lattice)
        self._image_vec = None

        # public variables
        self.rmax = self.kwargs.get('rmax')
        self.number_density = self._num_atoms / self._volume
        self.dr = self.kwargs.get('dr')
        self.r_space = None
        self.gr = None
        self.elem_gr = None

        self.label = None
        if self.kwargs.get('label'):
            self.label = self.kwargs["label"]
        elif 'text_id' in structure:
            self.label = ' '.join(structure['text_id'])

        if not lazy:
            if self.kwargs.get('timing'):
                start = time.time()
            self.calc_pdf()
            if self.kwargs.get('timing'):
                end = time.time()
                print('PDF calculated in {:.3f} s'.format(end - start))
Esempio n. 11
0
    def test_kpt_path(self):

        cell, s = castep2dict(REAL_PATH +
                              "data/Na3Zn4-swap-ReOs-OQMD_759599.castep")
        std_cell, path, seekpath_results = get_seekpath_kpoint_path(
            cell, spacing=0.01, debug=False)
        self.assertEqual(539, len(path))

        self.assertLess(pdf_sim_dist(cell, std_cell), 0.05)

        import glob
        from os import remove
        from matador.utils.cell_utils import frac2cart

        fnames = glob.glob(REAL_PATH + "data/bs_test/*.res")
        spacing = 0.01
        for fname in fnames:
            doc, s = res2dict(fname, db=False)
            doc["cell_volume"] = cart2volume(doc["lattice_cart"])

            std_doc, path, seekpath_results = get_seekpath_kpoint_path(
                doc, spacing=spacing, debug=False)
            seekpath_results_path = get_path(doc2spg(doc))

            rel_path = seekpath_results["explicit_kpoints_rel"]
            abs_path = seekpath_results["explicit_kpoints_abs"]

            cart_kpts = np.asarray(
                frac2cart(real2recip(std_doc["lattice_cart"]), path))
            diffs = np.zeros((len(cart_kpts[:-1])))
            np.testing.assert_array_almost_equal(cart_kpts, abs_path)
            np.testing.assert_array_almost_equal(path, rel_path)
            for ind, kpt in enumerate(cart_kpts[:-1]):
                diffs[ind] = np.sqrt(np.sum((kpt - cart_kpts[ind + 1])**2))
            self.assertLess(
                len(np.where(diffs > 1.1 * spacing)[0]),
                len(seekpath_results["explicit_segments"]),
            )

            if "flrys4-1x109" in fname:
                bs, s = bands2dict(fname.replace(".res", ".bands"))
                np.testing.assert_array_almost_equal(bs["kpoint_path"],
                                                     rel_path)
                np.testing.assert_array_almost_equal(bs["lattice_cart"],
                                                     std_doc["lattice_cart"])
            self.assertLess(
                len(np.where(diffs > 1.1 * spacing)[0]),
                len(seekpath_results["explicit_segments"]),
            )

            cell_path = fname.replace(".res", ".cell")
            doc2cell(std_doc, cell_path)
            new_doc, s = cell2dict(cell_path,
                                   lattice=True,
                                   positions=True,
                                   db=False)
            assert "positions_frac" in new_doc
            remove(cell_path)
            seekpath_new_results = get_path(doc2spg(new_doc))
            self.assertEqual(
                seekpath_new_results["bravais_lattice_extended"],
                seekpath_results_path["bravais_lattice_extended"],
            )

            dist = pdf_sim_dist(doc, std_doc)
            self.assertLess(dist, 0.01)
            dist = pdf_sim_dist(doc, new_doc)
            self.assertLess(dist, 0.01)