Esempio n. 1
0
    def test_cart2frac(self):
        lattice_cart = [[2, 0, 0], [0, 2, 0], [0, 0, 2]]
        positions_abs = [1, 1, 1]
        self.assertEqual(cart2frac(lattice_cart, positions_abs),
                         [0.5, 0.5, 0.5])

        lattice_cart = [[2, 0, 0], [0, 2, 0], [0, 0, 2]]
        positions_abs = [[1, 1, 1]]
        self.assertEqual(cart2frac(lattice_cart, positions_abs),
                         [[0.5, 0.5, 0.5]])

        lattice_cart = [[2, 0, 0], [0, 2, 0], [0, 0, 2]]
        positions_abs = [[2, 2, 2], [1, 1, 1]]
        self.assertEqual(cart2frac(lattice_cart, positions_abs),
                         [[1, 1, 1], [0.5, 0.5, 0.5]])
Esempio n. 2
0
 def positions_frac(self):
     """ Return list of fractional positions. """
     from matador.utils.cell_utils import cart2frac
     if 'positions_frac' not in self._data:
         self._data['positions_frac'] = cart2frac(self.cell.lattice_cart,
                                                  self.positions_abs)
     return self._data['positions_frac']
Esempio n. 3
0
def optimade_to_basic_cif(structure):
    """ A simple CIF creator that is enough to trick ChemDoodle. """

    cif_string = ""
    lattice_abc = cart2abc(structure.attributes.lattice_vectors)
    positions_frac = cart2frac(
        structure.attributes.lattice_vectors,
        structure.attributes.cartesian_site_positions,
    )
    cif_string += f"_cell_length_a {lattice_abc[0][0]}\n"
    cif_string += f"_cell_length_b {lattice_abc[0][1]}\n"
    cif_string += f"_cell_length_c {lattice_abc[0][2]}\n"
    cif_string += f"_cell_angle_alpha {lattice_abc[1][0]}\n"
    cif_string += f"_cell_angle_beta {lattice_abc[1][1]}\n"
    cif_string += f"_cell_angle_gamma {lattice_abc[1][2]}\n"
    cif_string += "loop_\n"
    cif_string += "_atom_site_label\n"
    cif_string += "_atom_site_symbol\n"
    cif_string += "_atom_site_fract_x\n"
    cif_string += "_atom_site_fract_y\n"
    cif_string += "_atom_site_fract_z\n"

    for atom, pos in zip(structure.attributes.species_at_sites, positions_frac):
        cif_string += f"{atom} {atom} {pos[0]} {pos[1]} {pos[2]}\n"

    return cif_string
Esempio n. 4
0
 def test_conversion_transitivity(self):
     """ Test that cart2frac(frac2cart(A)) == A. """
     castep_fname = REAL_PATH + "data/Na3Zn4-swap-ReOs-OQMD_759599.castep"
     test_doc, s = castep2dict(castep_fname, db=True, verbosity=VERBOSITY)
     lattice_cart = test_doc["lattice_cart"]
     positions_frac = test_doc["positions_frac"]
     np.testing.assert_almost_equal(
         cart2frac(lattice_cart, frac2cart(lattice_cart, positions_frac)),
         positions_frac,
         decimal=10,
     )
Esempio n. 5
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. 6
0
 def set_position(self, position, units):
     if len(position) != 3 or not all(
             isinstance(p, (float, int)) for p in position):
         raise RuntimeError(
             'CrystalSite position has wrong shape: {}'.format(position))
     if not hasattr(self, '_coords'):
         self._coords = dict()
     if units == 'fractional':
         self._coords['fractional'] = wrap_frac_coords(
             [float(pos) for pos in position], remove=False)
     elif units == 'cartesian':
         self._coords['fractional'] = wrap_frac_coords(cart2frac(
             self.lattice, self.coords),
                                                       remove=False)
     else:
         raise RuntimeError(
             'Unit system {} not understood, expecting `fractional`/`cartesian`'
             .format(units))
Esempio n. 7
0
    def relax(self):
        from ase.optimize import LBFGS

        cached = sys.__stdout__
        try:
            optimizer = LBFGS(self.ucf)
            optimizer.logfile = None
            optimised = optimizer.run(fmax=0.05, steps=100)
        except Exception:
            optimised = False

        self.doc["optimised"] = bool(optimised)
        self.doc["positions_abs"] = self.atoms.get_positions().tolist()
        self.doc["lattice_cart"] = self.atoms.get_cell().tolist()
        self.doc["lattice_abc"] = cart2abc(self.doc["lattice_cart"])
        self.doc["positions_frac"] = cart2frac(self.doc["lattice_cart"],
                                               self.doc["positions_abs"])
        self.doc["enthalpy_per_atom"] = float(self.calc.results["energy"] /
                                              len(self.doc["atom_types"]))
        self.doc["enthalpy"] = float(self.calc.results["energy"])
        self.queue.put(self.doc)
        sys.stdout = cached
Esempio n. 8
0
def magres2dict(fname, **kwargs):
    """ Extract available information from .magres file. Assumes units of
    Angstrom and ppm for relevant quantities.
    """
    magres = defaultdict(list)
    flines, fname = get_flines_extension_agnostic(fname, "magres")
    magres['source'] = [fname]

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

    magres['magres_units'] = dict()
    for line_no, line in enumerate(flines):
        line = line.lower().strip()
        if line in ['<atoms>', '[atoms]']:
            i = 1
            while flines[line_no +
                         i].strip().lower() not in ['</atoms>', '[/atoms]']:
                split_line = flines[line_no + i].split()
                if not split_line:
                    i += 1
                    continue
                if i > len(flines):
                    raise RuntimeError("Something went wrong in reader loop")
                if split_line[0] == 'units':
                    magres['magres_units'][split_line[1]] = split_line[2]
                elif 'lattice' in split_line:
                    lattice = split_line[1:]
                    for j in range(3):
                        magres['lattice_cart'].append([
                            float(elem) for elem in lattice[j * 3:(j + 1) * 3]
                        ])
                    magres['lattice_abc'] = cart2abc(magres['lattice_cart'])
                elif 'atom' in split_line:
                    atom = split_line
                    magres['atom_types'].append(atom[1])
                    magres['positions_abs'].append(
                        [float(elem) for elem in atom[-3:]])
                i += 1
            break

    if "atom_types" in magres:
        magres['num_atoms'] = len(magres['atom_types'])
        magres['positions_frac'] = cart2frac(magres['lattice_cart'],
                                             magres['positions_abs'])
        magres['stoichiometry'] = get_stoich(magres['atom_types'])

    for line_no, line in enumerate(flines):
        line = line.lower().strip()
        if line in ['<magres>', '[magres]']:
            i = 1
            while flines[line_no +
                         i].strip().lower() not in ['</magres>', '[/magres]']:
                split_line = flines[line_no + i].split()
                if not split_line:
                    i += 1
                    continue
                if i > len(flines):
                    raise RuntimeError("Something went wrong in reader loop")
                if split_line[0] == 'units':
                    magres['magres_units'][split_line[1]] = split_line[2]
                elif 'sus' in split_line:
                    magres["susceptibility_tensor"] = np.array(
                        [float(val) for val in split_line[1:]]).reshape(3, 3)

                elif 'ms' in split_line:
                    ms = np.array([float(val)
                                   for val in split_line[3:]]).reshape(3, 3)
                    s_iso = np.trace(ms) / 3

                    # find eigenvalues of symmetric part of shielding and order them to calc anisotropy eta
                    symmetric_shielding = _symmetrise_tensor(ms)
                    s_yy, s_xx, s_zz = _get_haeberlen_eigs(symmetric_shielding)
                    s_aniso = s_zz - (s_xx + s_yy) / 2.0
                    asymm = (s_yy - s_xx) / (s_zz - s_iso)

                    # convert from reduced anistropy to CSA
                    magres["magnetic_shielding_tensors"].append(ms)
                    magres["chemical_shielding_isos"].append(s_iso)
                    magres["chemical_shift_anisos"].append(s_aniso)
                    magres["chemical_shift_asymmetries"].append(asymm)

                elif "efg" in split_line:
                    efg = np.array([float(val)
                                    for val in split_line[3:]]).reshape(3, 3)
                    species = split_line[1]

                    eigs = _get_haeberlen_eigs(efg)
                    v_zz, eta = eigs[2], (eigs[0] - eigs[1]) / eigs[2]

                    # calculate C_Q in MHz
                    quadrupole_moment = ELECTRIC_QUADRUPOLE_MOMENTS.get(
                        species, 1.0)

                    C_Q = ((ELECTRON_CHARGE * v_zz * quadrupole_moment *
                            EFG_AU_TO_SI * BARN_TO_M2) /
                           (PLANCK_CONSTANT * 1e6))

                    magres["electric_field_gradient"].append(efg)
                    magres["quadrupolar_couplings"].append(C_Q)
                    magres["quadrupolar_asymmetries"].append(eta)

                i += 1

    for line_no, line in enumerate(flines):
        line = line.lower().strip()
        if line in ['<calculation>', '[calculation]']:
            i = 1
            while flines[line_no + i].strip().lower() not in [
                    '</calculation>', '[/calculation]'
            ]:
                if i > len(flines):
                    raise RuntimeError("Something went wrong in reader loop")
                # space important as it excludes other calc_code_x variables
                if 'calc_code ' in flines[line_no + i]:
                    magres['calculator'] = flines[line_no + i].split()[1]
                if 'calc_code_version' in flines[line_no + i]:
                    magres['calculator_version'] = flines[line_no +
                                                          i].split()[1]
                i += 1

    return dict(magres), True
Esempio n. 9
0
def magres2dict(fname, **kwargs):
    """ Extract available information from .magres file. Assumes units of
    Angstrom and ppm for relevant quantities.
    """
    magres = defaultdict(list)
    flines, fname = get_flines_extension_agnostic(fname, "magres")
    magres['source'] = [fname]

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

    magres['magres_units'] = dict()
    for line_no, line in enumerate(flines):
        line = line.lower().strip()
        if line in ['<atoms>', '[atoms]']:
            i = 1
            while flines[line_no +
                         i].strip().lower() not in ['</atoms>', '[/atoms]']:
                split_line = flines[line_no + i].split()
                if not split_line:
                    i += 1
                    continue
                if i > len(flines):
                    raise RuntimeError("Something went wrong in reader loop")
                if split_line[0] == 'units':
                    magres['magres_units'][split_line[1]] = split_line[2]
                elif 'lattice' in flines[line_no + i]:
                    lattice = flines[line_no + i].split()[1:]
                    for j in range(3):
                        magres['lattice_cart'].append([
                            float(elem) for elem in lattice[j * 3:(j + 1) * 3]
                        ])
                    magres['lattice_abc'] = cart2abc(magres['lattice_cart'])
                elif 'atom' in flines[line_no + i]:
                    atom = flines[line_no + i].split()
                    magres['atom_types'].append(atom[1])
                    magres['positions_abs'].append(
                        [float(elem) for elem in atom[-3:]])
                i += 1
            break

    magres['num_atoms'] = len(magres['atom_types'])
    magres['positions_frac'] = cart2frac(magres['lattice_cart'],
                                         magres['positions_abs'])
    magres['stoichiometry'] = get_stoich(magres['atom_types'])

    for line_no, line in enumerate(flines):
        line = line.lower().strip()
        if line in ['<magres>', '[magres]']:
            i = 1
            while flines[line_no +
                         i].strip().lower() not in ['</magres>', '[/magres]']:
                split_line = flines[line_no + i].split()
                if not split_line:
                    i += 1
                    continue
                if i > len(flines):
                    raise RuntimeError("Something went wrong in reader loop")
                if split_line[0] == 'units':
                    magres['magres_units'][split_line[1]] = split_line[2]
                elif 'sus' in flines[line_no + i]:
                    sus = flines[line_no + i].split()[1:]
                    for j in range(3):
                        magres['susceptibility_tensor'].append(
                            [float(val) for val in sus[3 * j:3 * (j + 1)]])
                elif 'ms' in flines[line_no + i]:
                    ms = flines[line_no + i].split()[3:]
                    magres['magnetic_shielding_tensors'].append([])
                    for j in range(3):
                        magres['magnetic_shielding_tensors'][-1].append(
                            [float(val) for val in ms[3 * j:3 * (j + 1)]])
                    magres['chemical_shielding_isos'].append(0)
                    magres['chemical_shift_anisos'].append(0)
                    magres['chemical_shift_asymmetries'].append(0)
                    for j in range(3):
                        magres['chemical_shielding_isos'][-1] += magres[
                            'magnetic_shielding_tensors'][-1][j][j] / 3

                    # find eigenvalues of symmetric part of shielding and order them to calc anisotropy eta
                    symmetric_shielding = (
                        0.5 *
                        (magres['magnetic_shielding_tensors'][-1] + np.asarray(
                            magres['magnetic_shielding_tensors'][-1]).T))
                    eig_vals, eig_vecs = np.linalg.eig(symmetric_shielding)
                    eig_vals, eig_vecs = zip(
                        *sorted(zip(eig_vals, eig_vecs),
                                key=lambda eig: abs(eig[0] - magres[
                                    'chemical_shielding_isos'][-1])))
                    # Haeberlen convention: |s_zz - s_iso| >= |s_xx - s_iso| >= |s_yy - s_iso|
                    s_yy, s_xx, s_zz = eig_vals
                    s_iso = magres['chemical_shielding_isos'][-1]
                    # convert from reduced anistropy to CSA
                    magres['chemical_shift_anisos'][-1] = s_zz - (s_xx +
                                                                  s_yy) / 2.0
                    magres['chemical_shift_asymmetries'][-1] = (
                        s_yy - s_xx) / (s_zz - s_iso)
                i += 1

    for line_no, line in enumerate(flines):
        line = line.lower().strip()
        if line in ['<calculation>', '[calculation]']:
            i = 1
            while flines[line_no + i].strip().lower() not in [
                    '</calculation>', '[/calculation]'
            ]:
                if i > len(flines):
                    raise RuntimeError("Something went wrong in reader loop")
                # space important as it excludes other calc_code_x variables
                if 'calc_code ' in flines[line_no + i]:
                    magres['calculator'] = flines[line_no + i].split()[1]
                if 'calc_code_version' in flines[line_no + i]:
                    magres['calculator_version'] = flines[line_no +
                                                          i].split()[1]
                i += 1

    return magres, True