Пример #1
0
def obtain_eigenvectors_from_phonopy(structure, q_vector, NAC=False):

    #   Checking data
    force_atoms_file = structure.get_force_set().item(0)["natom"]
    force_atoms_input = np.product(np.diagonal(structure.get_super_cell_phonon())) * structure.get_number_of_atoms()

    if force_atoms_file != force_atoms_input:
        print("Error: FORCE_SETS file does not match with SUPERCELL MATRIX")
        exit()

    #   Preparing the bulk type object
    bulk = PhonopyAtoms(
        symbols=structure.get_atomic_types(),
        scaled_positions=structure.get_scaled_positions(),
        cell=structure.get_cell().T,
    )

    phonon = Phonopy(
        bulk,
        structure.get_super_cell_phonon(),
        primitive_matrix=structure.get_primitive_matrix(),
        is_auto_displacements=False,
    )

    # Non Analytical Corrections (NAC) from Phonopy [Frequencies only, eigenvectors no affected by this option]
    if NAC:
        print("Phonopy warning: Using Non Analytical Corrections")
        get_is_symmetry = True  # from phonopy:   settings.get_is_symmetry()
        primitive = phonon.get_primitive()
        nac_params = parse_BORN(primitive, get_is_symmetry)
        phonon.set_nac_params(nac_params=nac_params)

    phonon.set_displacement_dataset(copy.deepcopy(structure.get_force_set()))
    phonon.produce_force_constants()

    frequencies, eigenvectors = phonon.get_frequencies_with_eigenvectors(q_vector)

    # Making sure eigenvectors are orthonormal (can be omitted)
    if True:
        eigenvectors = eigenvectors_normalization(eigenvectors)
        print("Testing eigenvectors orthonormality")
        np.set_printoptions(precision=3, suppress=True)
        print(np.dot(eigenvectors.T, np.ma.conjugate(eigenvectors)).real)
        np.set_printoptions(suppress=False)

    # Arranging eigenvectors by atoms and dimensions
    number_of_dimensions = structure.get_number_of_dimensions()
    number_of_primitive_atoms = structure.get_number_of_primitive_atoms()

    arranged_ev = np.array(
        [
            [
                [eigenvectors[j * number_of_dimensions + k, i] for k in range(number_of_dimensions)]
                for j in range(number_of_primitive_atoms)
            ]
            for i in range(number_of_primitive_atoms * number_of_dimensions)
        ]
    )

    return arranged_ev, frequencies
Пример #2
0
 def _get_phonon(self):
     cell = read_vasp(os.path.join(data_dir, "..", "POSCAR_NaCl"))
     phonon = Phonopy(cell,
                      np.diag([2, 2, 2]),
                      primitive_matrix=[[0, 0.5, 0.5], [0.5, 0, 0.5],
                                        [0.5, 0.5, 0]])
     filename = os.path.join(data_dir, "..", "FORCE_SETS_NaCl")
     force_sets = parse_FORCE_SETS(filename=filename)
     phonon.set_displacement_dataset(force_sets)
     phonon.produce_force_constants()
     filename_born = os.path.join(data_dir, "..", "BORN_NaCl")
     nac_params = parse_BORN(phonon.get_primitive(), filename=filename_born)
     phonon.set_nac_params(nac_params)
     return phonon
Пример #3
0
def phonopy_commensurate_shifts_inline(**kwargs):
    from phonopy.structure.atoms import Atoms as PhonopyAtoms
    from phonopy import Phonopy
    from phonopy.harmonic.dynmat_to_fc import get_commensurate_points, DynmatToForceConstants

    structure = kwargs.pop('structure')
    phonopy_input = kwargs.pop('phonopy_input').get_dict()
    force_constants = kwargs.pop('force_constants').get_array('force_constants')
    r_force_constants = kwargs.pop('r_force_constants').get_array('force_constants')


    # Generate phonopy phonon object
    bulk = PhonopyAtoms(symbols=[site.kind_name for site in structure.sites],
                        positions=[site.position for site in structure.sites],
                        cell=structure.cell)

    phonon = Phonopy(bulk,
                     phonopy_input['supercell'],
                     primitive_matrix=phonopy_input['primitive'],
                     distance=phonopy_input['distance'])

    primitive = phonon.get_primitive()
    supercell = phonon.get_supercell()


    phonon.set_force_constants(force_constants)

    dynmat2fc = DynmatToForceConstants(primitive, supercell)
    com_points = dynmat2fc.get_commensurate_points()

    phonon.set_qpoints_phonon(com_points,
                              is_eigenvectors=True)
    frequencies_h = phonon.get_qpoints_phonon()[0]


    phonon.set_force_constants(r_force_constants)

    phonon.set_qpoints_phonon(com_points,
                              is_eigenvectors=True)
    frequencies_r = phonon.get_qpoints_phonon()[0]

    shifts = frequencies_r - frequencies_h

    # Stores DOS data in DB as a workflow result
    commensurate = ArrayData()
    commensurate.set_array('qpoints', com_points)
    commensurate.set_array('shifts', shifts)

    return {'commensurate': commensurate}
    def get_rand_FCM(self, asum=15, force=10):
        """
        Generate a symmeterized force constant matrix from an unsymmeterized matrix
        that has no unstable modes and also obeys the acoustic sum rule through an
        iterative procedure

        Args:
            force (float): maximum force constant
            asum (int): number of iterations to attempt to obey the acoustic sum
                rule

        Return:
            NxNx3x3 np.array representing the force constant matrix

        """

        numsites = len(self.structure.sites)
        structure = pymatgen.io.phonopy.get_phonopy_structure(self.structure)
        pnstruc = Phonopy(structure, np.eye(3), np.eye(3))

        dyn = self.get_unstable_FCM(force)
        dyn = self.get_stable_FCM(dyn)

        dyn = np.reshape(dyn, (numsites, 3, numsites, 3)).swapaxes(1, 2)

        dynmass = np.zeros([len(self.structure), len(self.structure), 3, 3])
        masses = []
        for j in range(numsites):
            masses.append(self.structure.sites[j].specie.atomic_mass)
        dynmass = np.zeros([numsites, numsites, 3, 3])
        for m in range(numsites):
            for n in range(numsites):
                dynmass[m][n] = dyn[m][n] * np.sqrt(masses[m]) * np.sqrt(
                    masses[n])

        supercell = pnstruc.get_supercell()
        primitive = pnstruc.get_primitive()

        converter = dyntofc.DynmatToForceConstants(primitive, supercell)

        dyn = np.reshape(np.swapaxes(dynmass, 1, 2),
                         (numsites * 3, numsites * 3))

        converter.set_dynamical_matrices(dynmat=[dyn])

        converter.run()
        fc = converter.get_force_constants()

        return fc
Пример #5
0
 def _get_phonon_NaCl(self):
     cell = read_vasp(os.path.join(data_dir, "..", "POSCAR_NaCl"))
     phonon = Phonopy(cell,
                      np.diag([2, 2, 2]),
                      primitive_matrix=[[0, 0.5, 0.5],
                                        [0.5, 0, 0.5],
                                        [0.5, 0.5, 0]])
     filename = os.path.join(data_dir, "..", "FORCE_SETS_NaCl")
     force_sets = parse_FORCE_SETS(filename=filename)
     phonon.set_displacement_dataset(force_sets)
     phonon.produce_force_constants()
     filename_born = os.path.join(data_dir, "..", "BORN_NaCl")
     nac_params = parse_BORN(phonon.get_primitive(), filename=filename_born)
     phonon.set_nac_params(nac_params)
     return phonon
Пример #6
0
    def _get_phonon(self, cell):
        phonon = Phonopy(cell,
                         np.diag([2, 2, 2]),
                         primitive_matrix=[[0, 0.5, 0.5],
                                           [0.5, 0, 0.5],
                                           [0.5, 0.5, 0]])
        filename = os.path.join(data_dir, "../FORCE_SETS_NaCl")
        force_sets = parse_FORCE_SETS(filename=filename)
        phonon.set_displacement_dataset(force_sets)
        phonon.produce_force_constants()
        filename_born = os.path.join(data_dir, "../BORN_NaCl")
        nac_params = parse_BORN(phonon.get_primitive(), filename=filename_born)
        nac_params['method'] = 'wang'
        phonon.set_nac_params(nac_params)

        return phonon
Пример #7
0
def get_commensurate(structure, ph_settings):
    from phonopy import Phonopy
    from phonopy.harmonic.dynmat_to_fc import DynmatToForceConstants
    from aiida_phonopy.workchains.phonon import phonopy_bulk_from_structure

    phonon = Phonopy(phonopy_bulk_from_structure(structure),
                     ph_settings.dict.supercell,
                     primitive_matrix=ph_settings.dict.primitive,
                     symprec=ph_settings.dict.symmetry_precision)

    primitive = phonon.get_primitive()
    supercell = phonon.get_supercell()

    dynmat2fc = DynmatToForceConstants(primitive, supercell)
    commensurate = dynmat2fc.get_commensurate_points()

    return dynmat2fc, commensurate
Пример #8
0
def get_phonon(structure, force_constants, ph_settings, nac_data=None):
    from phonopy import Phonopy
    from aiida_phonopy.workchains.phonon import phonopy_bulk_from_structure

    phonon = Phonopy(phonopy_bulk_from_structure(structure),
                     ph_settings.dict.supercell,
                     primitive_matrix=ph_settings.dict.primitive,
                     symprec=ph_settings.dict.symmetry_precision)

    if force_constants is not None:
        phonon.set_force_constants(force_constants.get_data())

    if nac_data is not None:
            primitive = phonon.get_primitive()
            nac_parameters = nac_data.get_born_parameters_phonopy(primitive_cell=primitive.get_cell())
            phonon.set_nac_params(nac_parameters)

    return phonon
def get_initialized_phononopy_instance(initial_structure,
                                       phonopy_inputs,
                                       force_constants_path=None,
                                       born_path=None):
    """
	Initializes and returns a valid Phonopy instance and with displacements internally generated.

	If force_constants_path is specified, the phonopy instance is initialized with the force constants at the given path.
	If the born_path is specified, the born file at this path is used to initialize the nac parameters of the phonopy instance, but
	only if the nac key has a value of true in the phonopy_inputs dictionary.

	phonopy_inputs should be a dictionary that looks like:

	phonopy_inputs_dictionary = {
		'supercell_dimensions': [2, 2, 2],
		'symprec': 0.001,
		'displacement_distance': 0.01,
		'nac': True
		...
	}
	"""

    unit_cell_phonopy_structure = convert_structure_to_phonopy_atoms(
        initial_structure)
    supercell_dimensions_matrix = np.diag(
        phonopy_inputs['supercell_dimensions'])

    phonon = Phonopy(unitcell=unit_cell_phonopy_structure,
                     supercell_matrix=supercell_dimensions_matrix,
                     symprec=phonopy_inputs['symprec'])
    phonon.generate_displacements(
        distance=phonopy_inputs['displacement_distance'])

    if force_constants_path != None:
        force_constants = parse_FORCE_CONSTANTS(filename=force_constants_path)
        phonon.set_force_constants(force_constants)

    if born_path != None and (phonopy_inputs.has_key('nac')
                              and phonopy_inputs['nac']):
        nac_params = parse_BORN(phonon.get_primitive(), filename=born_path)
        phonon.set_nac_params(nac_params)

    return phonon
Пример #10
0
def get_primitive(structure, ph_settings):
    from phonopy import Phonopy

    phonon = Phonopy(
        phonopy_atoms_from_structure(structure),
        supercell_matrix=ph_settings.get_dict()['supercell_matrix'],
        primitive_matrix=ph_settings.get_dict()['primitive_matrix'],
        symprec=ph_settings.get_dict()['symmetry_tolerance'])
    primitive_phonopy = phonon.get_primitive()

    primitive_cell = primitive_phonopy.get_cell()
    symbols = primitive_phonopy.get_chemical_symbols()
    positions = primitive_phonopy.get_positions()

    primitive_structure = DataFactory('structure')(cell=primitive_cell)
    for symbol, position in zip(symbols, positions):
        primitive_structure.append_atom(position=position, symbols=symbol)

    return {'primitive_structure': primitive_structure}
Пример #11
0
def get_primitive(structure, ph_settings):

    from phonopy import Phonopy

    phonon = Phonopy(phonopy_bulk_from_structure(structure),
                     supercell_matrix=ph_settings.dict.supercell,
                     primitive_matrix=ph_settings.dict.primitive,
                     symprec=ph_settings.dict.symmetry_precision)

    primitive_phonopy = phonon.get_primitive()

    primitive_cell = primitive_phonopy.get_cell()
    symbols = primitive_phonopy.get_chemical_symbols()
    positions = primitive_phonopy.get_positions()

    primitive_structure = StructureData(cell=primitive_cell)
    for symbol, position in zip(symbols, positions):
        primitive_structure.append_atom(position=position, symbols=symbol)

    return {'primitive_structure': primitive_structure}
Пример #12
0
def parse_partial_DOS(filename, structure, parameters):
    partial_dos = np.loadtxt(filename)

    from phonopy.structure.atoms import Atoms as PhonopyAtoms
    from phonopy import Phonopy

    bulk = PhonopyAtoms(symbols=[site.kind_name for site in structure.sites],
                        positions=[site.position for site in structure.sites],
                        cell=structure.cell)

    phonon = Phonopy(bulk,
                     supercell_matrix=parameters.dict.supercell,
                     primitive_matrix=parameters.dict.primitive,
                     symprec=parameters.dict.symmetry_precision)

    dos = PhononDosData(frequencies=partial_dos.T[0],
                        dos=np.sum(partial_dos[:, 1:], axis=1),
                        partial_dos=partial_dos[:, 1:].T,
                        atom_labels=phonon.get_primitive().get_chemical_symbols())

    return dos
Пример #13
0
def get_commensurate_points(structure, phonopy_input):

    from phonopy.structure.atoms import Atoms as PhonopyAtoms
    from phonopy.harmonic.dynmat_to_fc import DynmatToForceConstants
    from phonopy import Phonopy

    # Generate phonopy phonon object
    bulk = PhonopyAtoms(symbols=[site.kind_name for site in structure.sites],
                        positions=[site.position for site in structure.sites],
                        cell=structure.cell)

    phonon = Phonopy(bulk,
                     phonopy_input['supercell'],
                     primitive_matrix=phonopy_input['primitive'],
                     distance=phonopy_input['distance'],
                     symprec=phonopy_input['symmetry_precision'])

    primitive = phonon.get_primitive()
    supercell = phonon.get_supercell()

    dynmat2fc = DynmatToForceConstants(primitive, supercell)
    com_points = dynmat2fc.get_commensurate_points()

    return com_points
Пример #14
0
def obtain_phonon_dispersion_spectra(structure, bands_ranges, NAC=False, band_resolution=30):

    print("Calculating phonon dispersion spectra...")
    bulk = PhonopyAtoms(
        symbols=structure.get_atomic_types(),
        scaled_positions=structure.get_scaled_positions(),
        cell=structure.get_cell().T,
    )

    phonon = Phonopy(
        bulk,
        structure.get_super_cell_phonon(),
        primitive_matrix=structure.get_primitive_matrix(),
        is_auto_displacements=False,
    )

    if NAC:
        print("Phonopy warning: Using Non Analitical Corrections")
        print("BORN file is needed to do this")
        get_is_symmetry = True  # sfrom phonopy:   settings.get_is_symmetry()
        primitive = phonon.get_primitive()
        nac_params = parse_BORN(primitive, get_is_symmetry)
        phonon.set_nac_params(nac_params=nac_params)

    phonon.set_displacement_dataset(copy.deepcopy(structure.get_force_set()))
    phonon.produce_force_constants()

    bands = []
    for q_start, q_end in bands_ranges:
        band = []
        for i in range(band_resolution + 1):
            band.append(np.array(q_start) + (np.array(q_end) - np.array(q_start)) / band_resolution * i)
        bands.append(band)
    phonon.set_band_structure(bands)

    return phonon.get_band_structure()
Пример #15
0
#                                           [0.5, 0.5, 0.5],
#                                           [0.5, 0, 0],
#                                           [0, 0.5, 0],
#                                           [0, 0, 0.5]])

phonon = Phonopy(unitcell, [[2, 0, 0], [0, 2, 0], [0, 0, 2]],
                 primitive_matrix=[[0, 0.5, 0.5], [0.5, 0, 0.5], [0.5, 0.5,
                                                                  0]])

symmetry = phonon.get_symmetry()
print "Space group:", symmetry.get_international_table()

force_sets = parse_FORCE_SETS()
phonon.set_displacement_dataset(force_sets)
phonon.produce_force_constants()
primitive = phonon.get_primitive()

# Born effective charges and dielectric constants are read from BORN file.
nac_params = parse_BORN(primitive, filename="BORN")
# Or it can be of course given by hand as follows:
# born = [[[1.08703, 0, 0],
#          [0, 1.08703, 0],
#          [0, 0, 1.08703]],
#         [[-1.08672, 0, 0],
#          [0, -1.08672, 0],
#          [0, 0, -1.08672]]]
# epsilon = [[2.43533967, 0, 0],
#            [0, 2.43533967, 0],
#            [0, 0, 2.43533967]]
# factors = 14.400
# nac_params = {'born': born,
Пример #16
0
def BuildForceConstants(lattice_vectors, atom_types, atom_pos, q_pts, freqs, eigs, sc_dim, freq_units = 'thz', atom_mass = None, file_path = r"FORCE_CONSTANTS"):
    """
    Use the Phonopy API to take a set of frequencies and eigenvectors, construct a dynamical matrix, transform to a set of force constants, and write out a Phonopy FORCE_CONSTANTS file.

    Args:
        lattice_vectors -- 3x3 matrix containing the lattice vectors
        atom_types -- list of atomic symbols
        atom_pos -- list of atomic positions ** in fractional coordinates **
        q_pts -- list of q-point coordinates
        freqs -- n_q sets of Frequencies
        eigs -- n_q sets of eigenvectors
        sc_dim -- (equivalent) supercell dimension for preparing force constants
        freq_units -- units of freqs ('thz' or 'inv_cm' -- default: 'thz')
        atom_mass -- (optional) list of atomic masses (default: taken from Phonopy internal database)
        file_path -- path to FORCE_CONSTANTS file to write (default: FORCE_CONSTANTS)
    """

    # Check input.

    _CheckStructure(lattice_vectors, atom_types, atom_pos, atom_mass)

    for param in q_pts, freqs, eigs, sc_dim:
        assert param is not None

    dim_1, dim_2 = np.shape(q_pts)

    assert dim_1 > 0 and dim_2 == 3

    n_at = len(atom_types)

    n_q = dim_1
    n_b = 3 * n_at

    dim_1, dim_2 = np.shape(freqs)

    assert dim_1 == n_q and dim_2 == n_b

    dim_1, dim_2, dim_3, dim_4 = np.shape(eigs)

    assert dim_1 == n_q and dim_2 == n_b and dim_3 == n_at and dim_4 == 3

    dim_1, = np.shape(sc_dim)

    assert dim_1 == 3

    # Obtain a frequency conversion factor to "VASP units".

    freq_conv_factor = None

    if freq_units == 'thz':
        freq_conv_factor = VaspToTHz
    elif freq_units == 'inv_cm':
        freq_conv_factor = VaspToCm

    if freq_conv_factor is None:
        raise Exception("Error: Unknown freq_units '{0}'.".format(freq_units))

    # Create a Phonopy-format structure.

    structure = PhonopyAtoms(
        symbols = atom_types, masses = atom_mass, scaled_positions = atom_pos, cell = lattice_vectors
        )

    # Convert supercell expansion to a supercell matrix.

    dim_1, dim_2, dim_3 = sc_dim

    if dim_1 != dim_2 != dim_2 != 1:
        warnings.warn("The dynamical matrix -> force constants transform has only been tested at the Gamma point; please report issues to the developer.", RuntimeWarning)

    sc_matrix = [[dim_1, 0, 0], [0, dim_2, 0], [0, 0, dim_3]]

    # Use the main Phonopy object to obtain the primitive cell and supercell.

    calculator = Phonopy(structure, sc_matrix)

    primitive = calculator.get_primitive();
    supercell = calculator.get_supercell();

    # Use the DynmatToForceConstants object to convert frequencies/eigenvectors -> dynamical matrices -> force constants.

    dynmat_to_fc = DynmatToForceConstants(primitive, supercell)

    commensurate_points = dynmat_to_fc.get_commensurate_points()

    # If an input code does not use crystal symmetry or outputs data at all q-points in a sampling mesh, data may be provided for more q-points than there are commensurate points.
    # However, for most codes this would be an odd situation -> issue a warning.

    if len(commensurate_points) != n_q:
        warnings.warn("The number of entries in the q_pts list does not equal the number of commensurate points expected for the supplied supercell matrix.", RuntimeWarning)

    # Map commensurate points in Phonopy setup to q-points in input data.

    map_indices = []

    for qx_1, qy_1, qz_1 in commensurate_points:
        map_index = None

        for i, (qx_2, qy_2, qz_2) in enumerate(q_pts):
            if math.fabs(qx_2 - qx_1) < _SymPrec and math.fabs(qy_2 - qy_1) < _SymPrec and math.fabs(qz_2 - qz_1) < _SymPrec:
                map_index = i
                break

        if map_index is None:
            raise Exception("Error: Expected q = ({0: >6.3f}, {1: >6.3f}, {2: >6.3f}) in the q_pts list (this may be a bug; please report to the developer).".format(qx_1, qy_1, qz_1))

        # Sanity check.

        assert map_index not in map_indices

        map_indices.append(map_index)

    # Arrange the frequencies and eigenvectors to the layout required by Phonopy.

    freq_sets, eig_sets = [], []

    for index in map_indices:
        freq_sets.append(
            [freq / freq_conv_factor for freq in freqs[index]]
            )

        eig = eigs[index]

        # Eigenvectors need to be a 3Nx3N matrix in the format:
        # 1_x -> [ m_1, ..., m_3N ]
        # 1_y -> [ m_1, ..., m_3N ]
        # ...
        # N_z -> [ m_1, ..., m_3N ]

        eig_rows = []

        for i in range(0, n_at):
            for j in range(0, 3):
                eig_row = []

                for k in range(0, n_b):
                    eig_row.append(eig[k][i][j])

                eig_rows.append(eig_row)

        eig_sets.append(eig_rows)

    freq_sets = np.array(freq_sets, dtype = np.float64)
    eig_sets = np.array(eig_sets, dtype = np.complex128)

    # Use the DynmatToForceConstants object to build the dynamical matrices, reverse transform to the force constants, and write a Phonopy FORCE_CONSTANTS file.

    dynmat_to_fc.set_dynamical_matrices(freq_sets, eig_sets)

    dynmat_to_fc.run()

    write_FORCE_CONSTANTS(
        dynmat_to_fc.get_force_constants(), filename = file_path
        )
Пример #17
0
-1.9721233333333332 0 0 0 -1.9721233333333332 0 0 0 -1.9721233333333332"""

#
# initial settings
#
cell = read_vasp_from_strings(poscar_str)
phonon = Phonopy(cell, np.diag([2, 2, 2]))
force_sets = parse_FORCE_SETS_from_strings(force_sets_str,
                                           cell.get_number_of_atoms() * 8)
phonon.set_force_sets(force_sets)
phonon.set_post_process(primitive_matrix=[[0, 0.5, 0.5],
                                          [0.5, 0, 0.5],
                                          [0.5, 0.5, 0]],
                        is_nac=True)
born_params = parse_BORN_from_strings(born_str,
                                      phonon.get_primitive())
phonon.set_nac_params(born_params)                                      

print phonon.get_symmetry().get_international_table()
primitive = phonon.get_primitive()
reclat = np.linalg.inv(primitive.get_cell())
print reclat

ndiv = 100
band = get_band([0.0, 0.0, 0.0], [0.5, 0.5, 0.0], ndiv)
bands = [band]
phonon.set_band_structure(bands)

#
# Run1
#
Пример #18
0
def get_properties_from_phonopy(**kwargs):
    """
    Calculate DOS and thermal properties using phonopy (locally)
    :param structure: StructureData Object
    :param ph_settings: Parametersdata object containing a dictionary with the data needed to run phonopy:
            supercells matrix, primitive matrix and q-points mesh.
    :param force_constants: (optional)ForceConstantsData object containing the 2nd order force constants
    :param force_sets: (optional) ForceSetsData object containing the phonopy force sets
    :param nac: (optional) ArrayData object from a single point calculation data containing dielectric tensor and Born charges
    :return: phonon band structure, force constants, thermal properties and DOS
    """

    structure = kwargs.pop('structure')
    ph_settings = kwargs.pop('ph_settings')
    bands = kwargs.pop('bands')

    from phonopy import Phonopy

    phonon = Phonopy(phonopy_bulk_from_structure(structure),
                     supercell_matrix=ph_settings.dict.supercell,
                     primitive_matrix=ph_settings.dict.primitive,
                     symprec=ph_settings.dict.symmetry_precision)

    if 'force_constants' in kwargs:
        force_constants = kwargs.pop('force_constants')
        phonon.set_force_constants(force_constants.get_data())

    else:
        force_sets = kwargs.pop('force_sets')
        phonon.set_displacement_dataset(force_sets.get_force_sets())
        phonon.produce_force_constants()
        force_constants = ForceConstantsData(data=phonon.get_force_constants())

    if 'nac_data' in kwargs:
        print('use born charges')
        nac_data = kwargs.pop('nac_data')
        primitive = phonon.get_primitive()
        nac_parameters = nac_data.get_born_parameters_phonopy(
            primitive_cell=primitive.get_cell())
        phonon.set_nac_params(nac_parameters)

    # Normalization factor primitive to unit cell
    normalization_factor = phonon.unitcell.get_number_of_atoms(
    ) / phonon.primitive.get_number_of_atoms()

    # DOS
    phonon.set_mesh(ph_settings.dict.mesh,
                    is_eigenvectors=True,
                    is_mesh_symmetry=False)
    phonon.set_total_DOS(tetrahedron_method=True)
    phonon.set_partial_DOS(tetrahedron_method=True)

    total_dos = phonon.get_total_DOS()
    partial_dos = phonon.get_partial_DOS()
    dos = PhononDosData(
        frequencies=total_dos[0],
        dos=total_dos[1] * normalization_factor,
        partial_dos=np.array(partial_dos[1]) * normalization_factor,
        atom_labels=np.array(phonon.primitive.get_chemical_symbols()))

    # THERMAL PROPERTIES (per primtive cell)
    phonon.set_thermal_properties()
    t, free_energy, entropy, cv = phonon.get_thermal_properties()

    # Stores thermal properties (per unit cell) data in DB as a workflow result
    thermal_properties = ArrayData()
    thermal_properties.set_array('temperature', t)
    thermal_properties.set_array('free_energy',
                                 free_energy * normalization_factor)
    thermal_properties.set_array('entropy', entropy * normalization_factor)
    thermal_properties.set_array('heat_capacity', cv * normalization_factor)

    # BAND STRUCTURE
    phonon.set_band_structure(bands.get_bands())
    band_structure = BandStructureData(bands=bands.get_bands(),
                                       labels=bands.get_labels(),
                                       unitcell=bands.get_unitcell())

    band_structure.set_band_structure_phonopy(phonon.get_band_structure())
    return {
        'thermal_properties': thermal_properties,
        'dos': dos,
        'band_structure': band_structure,
        'force_constants': force_constants
    }
Пример #19
0
def get_phonon_tb(
    # phonopy_atoms=[],
    atoms=[],
    fc=[],
    out_file="phonopyTB_hr.dat",
    distance_to_A=1.0,
    scell=np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]),
    factor=VaspToTHz,
    symprec=1e-05,
    displacement_distance=0.01,
):
    """Generate phonon TB Hamiltonia, along with WannierHamn."""
    # Forked from Wannier-tools
    unitcell = atoms.phonopy_converter()
    # unitcell = phonopy_atoms
    prim_mat = np.array(PhonopyInputs(atoms).prim_axis().split("=")[1].split(),
                        dtype="float").reshape(3, 3)
    # print("cell", unitcell.cell)
    num_atom = unitcell.get_number_of_atoms()
    num_satom = determinant(scell) * num_atom
    if fc.shape[0] != num_satom:
        print("Check Force constant matrix.")
    phonon = Phonopy(
        unitcell,
        scell,
        primitive_matrix=prim_mat,
        factor=factor,
        dynamical_matrix_decimals=None,
        force_constants_decimals=None,
        symprec=symprec,
        is_symmetry=True,
        use_lapack_solver=False,
        log_level=1,
    )

    supercell = phonon.get_supercell()
    primitive = phonon.get_primitive()
    # Set force constants
    phonon.set_force_constants(fc)
    phonon._set_dynamical_matrix()
    dmat = phonon._dynamical_matrix
    # rescale fcmat by THZ**2
    fcmat = dmat._force_constants * factor**2  # FORCE_CONSTANTS
    # fcmat = dmat._force_constants * factor ** 2  # FORCE_CONSTANTS
    smallest_vectors = dmat._smallest_vectors
    # mass = dmat._mass
    mass = dmat._pcell.get_masses()
    print("mass=", mass)
    multi = dmat._multiplicity
    reduced_bases = get_reduced_bases(supercell.get_cell(), symprec)
    positions = np.dot(supercell.get_positions(), np.linalg.inv(reduced_bases))
    # for pos in positions: pos -= np.rint(pos)
    relative_scale = np.dot(reduced_bases, np.linalg.inv(primitive.get_cell()))
    super_pos = np.zeros((num_satom, 3), dtype=np.float64)
    for i in range(num_satom):
        super_pos[i] = np.dot(positions[i], relative_scale)
    p2s_map = dmat._p2s_map = primitive.get_primitive_to_supercell_map()
    s2p_map = dmat._s2p_map = primitive.get_supercell_to_primitive_map()
    num_satom = supercell.get_number_of_atoms()
    num_patom = primitive.get_number_of_atoms()
    get_phonon_hr(
        fcmat,
        smallest_vectors,
        mass,
        multi,
        super_pos,
        p2s_map,
        s2p_map,
        num_satom,
        num_patom,
        out_file,
    )
    print("phonopy_TB.dat generated! ")
class AtomicContributionsCalculator:
    def __init__(self,
                 PoscarName='POSCAR',
                 ForceConstants=False,
                 ForceFileName='FORCE_SETS',
                 BornFileName='BORN',
                 supercell=[[1, 0, 0], [0, 1, 0], [0, 0, 1]],
                 nac=False,
                 symprec=1e-5,
                 masses=[],
                 primitive=[[1, 0, 0], [0, 1, 0], [0, 0, 1]],
                 degeneracy_tolerance=1e-4,
                 factor=VaspToCm,
                 q=[0, 0, 0]):
        """Class that calculates contributions of each atom to the phonon modes at Gamma
            Args:
            PoscarName (str): name of the POSCAR that was used for the phonon calculation
            BornFileName (str): name of the file with BORN charges (formatted with outcar-born)
            ForceConstants (boolean): If True, ForceConstants are read in. If False, forces are read in.
            ForceFileName (str): name of the file including force constants or forces
            supercell (list of lists): reads in supercell
            nac (boolean): If true, NAC is applied. (please be careful if you give a primitive cell. NAC should then be calculated for primitive cell)
            symprec (float): contains symprec tag as used in Phonopy
            masses (list): Masses in this list are used instead of the ones prepared in Phonopy. Useful for isotopes.
            primitive (list of lists): contains rotational matrix to arrive at primitive cell
            factor (float): VaspToCm or VaspToTHz or VaspToEv
            q (list of int): q point for the plot. So far only Gamma works

        """

        self.__unitcell = read_vasp(PoscarName)
        self.__supercell = supercell
        self.__phonon = Phonopy(self.__unitcell,
                                supercell_matrix=self.__supercell,
                                primitive_matrix=primitive,
                                factor=factor,
                                symprec=symprec)
        self.__natoms = self.__phonon.get_primitive().get_number_of_atoms()
        self.__symbols = self.__phonon.get_primitive().get_chemical_symbols()
        self.__factor = factor
        # If different masses are supplied
        if masses:
            self.__phonon.set_masses(masses)
        self.__masses = self.__phonon.get_primitive().get_masses()

        # Forces or Force Constants
        if not ForceConstants:
            self.__set_ForcesSets(filename=ForceFileName, phonon=self.__phonon)

        if ForceConstants:
            self.__set_ForceConstants(filename=ForceFileName,
                                      phonon=self.__phonon)

        # Apply NAC Correction
        if nac:
            BORN_file = parse_BORN(self.__phonon.get_primitive(),
                                   filename=BornFileName)
            self.__BORN_CHARGES = BORN_file['born']
            self.__phonon.set_nac_params(BORN_file)

        # frequencies and eigenvectors at Gamma
        self._frequencies, self._eigvecs = self.__phonon.get_frequencies_with_eigenvectors(
            q)

        self.__NumberOfBands = len(self._frequencies)

        # Nicer format of the eigenvector file
        self.__FormatEigenvectors()

        # Get Contributions
        self.__set_Contributions()
        self.__set_Contributions_withoutmassweight()

        # irrepsobject
        try:
            self.__set_IRLabels(phonon=self.__phonon,
                                degeneracy_tolerance=degeneracy_tolerance,
                                factor=factor,
                                q=q,
                                symprec=symprec)
        except:
            print(
                "Cannot assign IR labels. Play around with symprec, degeneracy_tolerance. The point group could not be implemented."
            )
            self.__freqlist = {}
            for i in range(0, len(self._frequencies)):
                self.__freqlist[i] = i

    def show_primitivecell(self):
        """
        shows primitive cell used for the plots and evaluations on screen
        """
        print(self.__phonon.get_primitive())

    def __set_ForcesSets(self, filename, phonon):
        """
        sets forces

        """

        force_sets = parse_FORCE_SETS(filename=filename)
        phonon.set_displacement_dataset(force_sets)
        phonon.produce_force_constants()

    def __set_ForceConstants(self, filename, phonon):
        """
        sets force constants
        """
        force_constants = parse_FORCE_CONSTANTS(filename=filename)
        phonon.set_force_constants(force_constants)

    def __set_IRLabels(self, phonon, degeneracy_tolerance, factor, q, symprec):
        """
        sets list of irreducible labels and list of frequencies without degeneracy
        """
        # phonon.set_dynamical_matrix()
        self.__Irrep = IrReps(dynamical_matrix=phonon._dynamical_matrix,
                              q=q,
                              is_little_cogroup=False,
                              nac_q_direction=None,
                              factor=factor,
                              symprec=symprec,
                              degeneracy_tolerance=degeneracy_tolerance)
        self.__Irrep.run()
        self._IRLabels = self.__Irrep._get_ir_labels()
        self.__ListOfModesWithDegeneracy = self.__Irrep._get_degenerate_sets()
        self.__freqlist = {}
        for band in range(len(self.__ListOfModesWithDegeneracy)):
            self.__freqlist[band] = self.__ListOfModesWithDegeneracy[band][0]

    def __FormatEigenvectors(self):
        """
        Formats eigenvectors to a dictionary: the first argument is the number of bands, the second the number of atoms, the third the Cartesian coordinate
        """

        self._EigFormat = {}
        for alpha in range(self.__NumberOfBands):
            laufer = 0
            for beta in range(self.__natoms):
                for xyz in range(0, 3):
                    self._EigFormat[beta, alpha,
                                    xyz] = self._eigvecs[laufer][alpha]
                    laufer = laufer + 1

    def _Eigenvector(self, atom, band, xoryorz):
        """
        Gives a certain eigenvector corresponding to one specific atom, band and Cartesian coordinate

        args:
            atom (int) : number of the atoms (same order as in POSCAR)
            band (int) : number of the frequency (ordered by energy)
            xoryorz (int): Cartesian coordinate of the eigenvector


        """

        return np.real(self._EigFormat[atom, band, xoryorz])

    def __massEig(self, atom, band, xoryorz):
        """
        Gives a certain eigenvector divided by sqrt(mass of the atom) corresponding to one specific atom, band and Cartesian coordinate

        args:
            atom (int) : number of the atoms (same order as in POSCAR)
            band (int) : number of the frequency (ordered by energy)
            xoryorz (int): Cartesian coordinate of the eigenvector


        """

        return self._Eigenvector(atom, band, xoryorz) / np.sqrt(
            self.__masses[atom])

    def __set_Contributions(self):
        """
        Calculate contribution of each atom to modes"
        """
        self._PercentageAtom = {}
        for freq in range(len(self._frequencies)):
            for atom in range(self.__natoms):
                sum = 0
                for alpha in range(3):
                    sum = sum + abs(
                        self._Eigenvector(atom, freq, alpha) *
                        self._Eigenvector(atom, freq, alpha))
                self._PercentageAtom[freq, atom] = sum

    def __get_Contributions(self, band, atom):
        """
        Gives contribution of specific atom to modes with certain frequency
        args:
            band (int): number of the frequency (ordered by energy)
        """
        return self._PercentageAtom[band, atom]

    def __set_Contributions_withoutmassweight(self):
        """
        Calculate contribution of each atom to modes
        Here, eigenvectors divided by sqrt(mass of the atom) are used for the calculation
        """
        self.__PercentageAtom_massweight = {}
        atomssum = {}
        saver = {}
        for freq in range(len(self._frequencies)):
            atomssum[freq] = 0
            for atom in range(self.__natoms):
                sum = 0
                for alpha in range(3):
                    sum = sum + abs(
                        self.__massEig(atom, freq, alpha) *
                        self.__massEig(atom, freq, alpha))
                atomssum[freq] = atomssum[freq] + sum

                # Hier muss noch was hin, damit rechnung richtig wird
                saver[freq, atom] = sum

        for freq in range(len(self._frequencies)):
            for atom in range(self.__natoms):
                self.__PercentageAtom_massweight[
                    freq, atom] = saver[freq, atom] / atomssum[freq]

    def __get_Contributions_withoutmassweight(self, band, atom):
        """
        Gives contribution of specific atom to modes with certain frequency
        Here, eigenvectors divided by sqrt(mass of the atom) are used for the calculation

        args:
                   band (int): number of the frequency (ordered by energy)
        """
        return self.__PercentageAtom_massweight[band, atom]

    def write_file(self, filename="Contributions.txt"):
        """
        Writes contributions of each atom in file

        args:

            filename (str): filename
        """
        file = open(filename, 'w')
        file.write('Frequency Contributions \n')
        for freq in range(len(self._frequencies)):
            file.write('%s ' % (self._frequencies[freq]))
            for atom in range(self.__natoms):
                file.write('%s ' % (self.__get_Contributions(freq, atom)))
            file.write('\n ')

        file.close()

    def plot(self,
             atomgroups,
             colorofgroups,
             legendforgroups,
             freqstart=[],
             freqend=[],
             freqlist=[],
             labelsforfreq=[],
             filename="Plot.eps",
             transmodes=True,
             massincluded=True):
        """
        Plots contributions of atoms/several atoms to modes with certain frequencies (freqlist starts at 1 here)

        args:
            atomgroups (list of list of ints): list that groups atoms, atom numbers start at 1
            colorofgroups (list of str): list that matches a color to each group of atoms
            legendforgroups (list of str): list that gives a legend for each group of atoms
            freqstart (float): min frequency of plot in cm-1
            freqend (float): max frequency of plot in cm-1
            freqlist (list of int): list of frequencies that will be plotted; if no list is given all frequencies in the range from freqstart to freqend are plotted, list begins at 1
            labelsforfreq (list of str): list of labels (str) for each frequency
            filename (str): filename for the plot
            transmodes (boolean): if transmode is true than translational modes are shown
            massincluded (boolean): if false, uses eigenvector divided by sqrt(mass of the atom) for the calculation instead of the eigenvector
        """

        p = {}
        summe = {}
        try:
            if labelsforfreq == []:
                labelsforfreq = self._IRLabels
        except:
            print("")

        if freqlist == []:
            freqlist = self.__freqlist

        else:

            for freq in range(len(freqlist)):
                freqlist[freq] = freqlist[freq] - 1

        newfreqlist = []
        newlabelsforfreq = []
        for freq in range(len(freqlist)):
            if not transmodes:
                if not freqlist[freq] in [0, 1, 2]:
                    newfreqlist.append(freqlist[freq])
                    try:
                        newlabelsforfreq.append(labelsforfreq[freq])
                    except:
                        newlabelsforfreq.append('')

            else:
                newfreqlist.append(freqlist[freq])
                try:
                    newlabelsforfreq.append(labelsforfreq[freq])
                except:
                    newlabelsforfreq.append('')

        self._plot(atomgroups=atomgroups,
                   colorofgroups=colorofgroups,
                   legendforgroups=legendforgroups,
                   freqstart=freqstart,
                   freqend=freqend,
                   freqlist=newfreqlist,
                   labelsforfreq=newlabelsforfreq,
                   filename=filename,
                   massincluded=massincluded)

    def _plot(self,
              atomgroups,
              colorofgroups,
              legendforgroups,
              freqstart=[],
              freqend=[],
              freqlist=[],
              labelsforfreq=[],
              filename="Plot.eps",
              massincluded=True):
        """
        Plots contributions of atoms/several atoms to modes with certain frequencies (freqlist starts at 0 here)

        args:
            atomgroups (list of list of ints): list that groups atoms, atom numbers start at 1
            colorofgroups (list of str): list that matches a color to each group of atoms
            legendforgroups (list of str): list that gives a legend for each group of atoms
            freqstart (float): min frequency of plot in cm-1
            freqend (float): max frequency of plot in cm-1
            freqlist (list of int): list of frequencies that will be plotted; this freqlist starts at 0
            labelsforfreq (list of str): list of labels (str) for each frequency
            filename (str): filename for the plot
            massincluded (boolean): if false, uses eigenvector divided by sqrt(mass of the atom) for the calculation instead of the eigenvector
        """
        # setting of some parameters in matplotlib: http://matplotlib.org/users/customizing.html
        mpl.rcParams["savefig.directory"] = os.chdir(os.getcwd())
        mpl.rcParams["savefig.format"] = 'eps'

        fig, ax1 = plt.subplots()
        p = {}
        summe = {}

        for group in range(len(atomgroups)):
            color1 = colorofgroups[group]
            Entry = {}
            for freq in range(len(freqlist)):
                Entry[freq] = 0
            for number in atomgroups[group]:
                # set the first atom to 0
                atom = int(number) - 1
                for freq in range(len(freqlist)):
                    if massincluded:
                        Entry[freq] = Entry[freq] + self.__get_Contributions(
                            freqlist[freq], atom)
                    else:
                        Entry[freq] = Entry[
                            freq] + self.__get_Contributions_withoutmassweight(
                                freqlist[freq], atom)
                    if group == 0:
                        summe[freq] = 0

            # plot bar chart
            p[group] = ax1.barh(np.arange(len(freqlist)),
                                list(Entry.values()),
                                left=list(summe.values()),
                                color=color1,
                                edgecolor="black",
                                height=1,
                                label=legendforgroups[group])
            # needed for "left" in the bar chart plot
            for freq in range(len(freqlist)):
                if group == 0:
                    summe[freq] = Entry[freq]
                else:
                    summe[freq] = summe[freq] + Entry[freq]
        labeling = {}
        for freq in range(len(freqlist)):
            labeling[freq] = round(self._frequencies[freqlist[freq]], 1)
        # details for the plot
        plt.rc("font", size=8)
        ax1.set_yticklabels(list(labeling.values()))
        ax1.set_yticks(np.arange(0.0, len(self._frequencies) + 0.0))
        ax2 = ax1.twinx()
        ax2.set_yticklabels(labelsforfreq)
        ax2.set_yticks(np.arange(0.0, len(self._frequencies) + 0.0))
        # start and end of the yrange
        start, end = self.__get_freqbordersforplot(freqstart, freqend,
                                                   freqlist)
        ax1.set_ylim(start - 0.5, end - 0.5)
        ax2.set_ylim(start - 0.5, end - 0.5)
        ax1.set_xlim(0.0, 1.0)
        ax1.set_xlabel('Contribution of Atoms to Modes')
        if self.__factor == VaspToCm:
            ax1.set_ylabel('Wavenumber (cm$^{-1}$)')
        elif self.__factor == VaspToTHz:
            ax1.set_ylabel('Frequency (THz)')
        elif self.__factor == VaspToEv:
            ax1.set_ylabel('Frequency (eV)')
        else:
            ax1.set_ylabel('Frequency')
        ax1.legend(bbox_to_anchor=(0, 1.02, 1, 0.2),
                   loc="lower left",
                   mode="expand",
                   borderaxespad=0,
                   ncol=len(atomgroups))

        plt.savefig(filename, bbox_inches="tight")

        plt.show()

    def __get_freqbordersforplot(self, freqstart, freqend, freqlist):
        if freqstart == []:
            start = 0.0
        else:
            for freq in range(len(freqlist)):
                if self._frequencies[freqlist[freq]] > freqstart:
                    start = freq
                    break
                else:
                    start = len(freqlist)
        if freqend == []:
            end = len(freqlist)
        else:
            for freq in range(len(freqlist) - 1, 0, -1):
                if self._frequencies[freqlist[freq]] < freqend:
                    end = freq + 1
                    break
                else:
                    end = len(freqlist)

        return start, end

    def plot_irred(self,
                   atomgroups,
                   colorofgroups,
                   legendforgroups,
                   transmodes=False,
                   irreps=[],
                   filename="Plot.eps",
                   freqstart=[],
                   freqend=[],
                   massincluded=True):
        """
        Plots contributions of atoms/several atoms to modes with certain irreducible representations (selected by Mulliken symbol)
        args:
            atomgroups (list of list of ints): list that groups atoms, atom numbers start at 1
            colorofgroups (list of str): list that matches a color to each group of atoms
            legendforgroups (list of str): list that gives a legend for each group of atoms
            transmodes (boolean): translational modes are included if true
            irreps (list of str): list that includes the irreducible modes that are plotted
            filename (str): filename for the plot
            massincluded (boolean): if false, uses eigenvector divided by sqrt(mass of the atom) for the calculation instead of the eigenvector
        """

        freqlist = []
        labelsforfreq = []
        for band in range(len(self.__freqlist)):
            if self._IRLabels[band] in irreps:
                if not transmodes:
                    if not self.__freqlist[band] in [0, 1, 2]:
                        freqlist.append(self.__freqlist[band])
                        labelsforfreq.append(self._IRLabels[band])
                else:
                    freqlist.append(self.__freqlist[band])
                    labelsforfreq.append(self._IRLabels[band])

        self._plot(atomgroups=atomgroups,
                   colorofgroups=colorofgroups,
                   legendforgroups=legendforgroups,
                   filename=filename,
                   freqlist=freqlist,
                   labelsforfreq=labelsforfreq,
                   freqstart=freqstart,
                   freqend=freqend,
                   massincluded=massincluded)
Пример #21
0
class IR:
    def __init__(self, PoscarName='POSCAR', BornFileName='BORN', ForceConstants=False, ForceFileName='FORCE_SETS',
                 supercell=[[1, 0, 0], [0, 1, 0], [0, 0, 1]]
                 , nac=False, symprec=1e-5, masses=[], primitive=[[1, 0, 0], [0, 1, 0], [0, 0, 1]],
                 degeneracy_tolerance=1e-5):
        """
        Class for calculating the IR spectra in the dipole approximation according to:
        P. Giannozzi and S. Baroni, J. Chem. Phys. 100, 8537 (1994).
        and
        D. Karhanek, T. Bucko, J. Hafner, J. Phys.: Condens. Matter 22 265006 (2010).


        This class was also carefully compared to the results of the script by D. Karhanek available at http://homepage.univie.ac.at/david.karhanek/downloads.html

        args:
            PoscarNamse (str): name of the POSCAR that was used for the phonon calculation
            BornFileName (str): name of the file with BORN charges (formatted with outcar-born)
            ForceConstants (boolean): If True, ForceConstants are read in. If False, forces are read in.
            ForceFileName (str): name of the file including force constants or forces
            supercell (list of lists): reads in supercell
            nac (boolean): If true, NAC is applied.
            symprec (float): contains symprec tag as used in Phonopy
            masses (list): Masses in this list are used instead of the ones prepared in Phonopy. Useful for isotopes.
            primitive (list of lists): contains rotational matrix to arrive at primitive cell
            degeneracy_tolerance (float): tolerance for degenerate modes
        """

        self.__unitcell = read_vasp(PoscarName)
        self.__supercell = supercell
        self.__phonon = Phonopy(self.__unitcell, supercell_matrix=self.__supercell, primitive_matrix=primitive,
                                factor=VaspToCm, symprec=symprec)
        self.__natoms = self.__phonon.get_primitive().get_number_of_atoms()
        self._degeneracy_tolerance = degeneracy_tolerance
        # If different masses are supplied
        if not ForceConstants:
            self.__force_sets = parse_FORCE_SETS(filename=ForceFileName)
            self.__phonon.set_displacement_dataset(self.__force_sets)
            self.__phonon.produce_force_constants()

        if ForceConstants:
            force_constants = parse_FORCE_CONSTANTS(filename=ForceFileName)
            self.__phonon.set_force_constants(force_constants)


        if masses:
            self.__phonon._build_supercell()
            self.__phonon._build_primitive_cell()
            # if ForceConstants:
            #     force_constants = parse_FORCE_CONSTANTS(filename=ForceFileName)
            #     self.__phonon.set_force_constants(force_constants)
            self.__phonon.set_masses(masses)

        self.__masses = self.__phonon.get_primitive().get_masses()
        # Forces or Force Constants

        # Read in BORN file
        BORN_file = parse_BORN(self.__phonon.get_primitive(), filename=BornFileName)
       
        self.__BORN_CHARGES = BORN_file['born']

        # Apply NAC Correction
        if nac:
            self.__phonon.set_nac_params(BORN_file)
        self._frequencies, self._eigvecs = self.__phonon.get_frequencies_with_eigenvectors([0, 0, 0])

        self.__NumberOfBands = len(self._frequencies)

        # Nicer format of the eigenvector file
        self.__FormatEigenvectors()

        # Get dipole approximation of the intensitiess
        self.__set_intensities()

    def __FormatEigenvectors(self):
        """
        Formats eigenvectors to a dictionary: the first argument is the number of bands, the second the number of atoms, the third the Cartesian coordinate
        """

        self._EigFormat = {}
        for alpha in range(self.__NumberOfBands):
            laufer = 0
            for beta in range(self.__natoms):
                for xyz in range(0, 3):
                    self._EigFormat[beta, alpha, xyz] = self._eigvecs[laufer][alpha]
                    laufer = laufer + 1

    def _Eigenvector(self, atom, band, xoryorz):
        """
        Gives a certain eigenvector corresponding to one specific atom, band and Cartesian coordinate

        args:
            atom (int) : number of the atoms (same order as in POSCAR)
            band (int) : number of the frequency (ordered by energy)
            xoryorz (int): Cartesian coordinate of the eigenvector


        """

        return np.real(self._EigFormat[atom, band, xoryorz])

    def __massEig(self, atom, band, xoryorz):
        """
        Gives a certain eigenvector divided by sqrt(mass of the atom) corresponding to one specific atom, band and Cartesian coordinate

        args:
            atom (int) : number of the atoms (same order as in POSCAR)
            band (int) : number of the frequency (ordered by energy)
            xoryorz (int): Cartesian coordinate of the eigenvector


        """

        return self._Eigenvector(atom, band, xoryorz) / np.sqrt(self.__masses[atom])

    def __set_intensities(self):
        """
        Calculates the oscillator strenghts according to "P. Giannozzi and S. Baroni, J. Chem. Phys. 100, 8537 (1994)."
        """

        Intensity = {}
        for freq in range(len(self._frequencies)):
            Intensity[freq] = 0
            for alpha in range(3):
                sum = 0
                for l in range(self.__natoms):
                    for beta in range(3):
                        sum = sum + self.__BORN_CHARGES[l, alpha, beta] * self.__massEig(l, freq, beta)
                Intensity[freq] = Intensity[freq] + np.power(np.absolute(sum), 2)

        # get degenerate modes
        freqlist_deg = get_degenerate_sets(self._frequencies, cutoff=self._degeneracy_tolerance)

        ReformatIntensity = []
        for i in Intensity:
            ReformatIntensity.append(Intensity[i])

        # if degenerate modes exist:
        if (len(freqlist_deg) < len(self._frequencies)):

            Intensity_deg = {}
            for sets in range(len(freqlist_deg)):
                Intensity_deg[sets] = 0
                for band in range(len(freqlist_deg[sets])):
                    Intensity_deg[sets] = Intensity_deg[sets] + ReformatIntensity[freqlist_deg[sets][band]]

            ReformatIntensity = []
            for i in range(len(Intensity_deg)):
                ReformatIntensity.append(Intensity_deg[i])

            Freq = []
            for band in range(len(freqlist_deg)):
                Freq.append(self._frequencies[freqlist_deg[band][0]])

            self.__frequencies_deg = np.array(Freq)

        else:
            self.__frequencies_deg = self._frequencies

        self.__Intensity = np.array(ReformatIntensity)

    def get_intensities(self):
        """
        returns calculated oscillator strengths as a numpy array
        """

        return self.__Intensity

    def get_frequencies(self):
        """
        returns frequencies as a numpy array
        """

        return self.__frequencies_deg

    def get_spectrum(self):
        """
        returns spectrum as a dict of numpy arrays
        """

        """
        Degeneracy should be treated for the Oscillator strengths

        """

        spectrum = {'Frequencies': self.get_frequencies(), 'Intensities': self.get_intensities()}
        return spectrum

    # only gaussian broadening so far
    def get_gaussiansmearedspectrum(self, sigma):
        """
        returns a spectrum with gaussian-smeared intensities

        args:
            sigma (float): smearing
        """

        #unsmearedspectrum = self.get_spectrum()
        frequencies = self.get_frequencies()
        Intensity = self.get_intensities()
        rangex = np.linspace(0, np.nanmax(frequencies) + 50, num=int(np.nanmax(frequencies) + 50) * 100)
        y = np.zeros(int(np.nanmax(frequencies) + 50) * 100)
        for i in range(len(frequencies)):
            y = y + self.__gaussiansmearing(rangex, frequencies[i], Intensity[i], sigma)
        smearedspectrum = {'Frequencies': rangex, 'Intensities': y}
        return smearedspectrum

    def __gaussiansmearing(self, rangex, frequency, Intensity, sigma):
        """
        applies gaussian smearing to a range of x values, a certain frequency, a given intensity

        args:
            rangex (ndarray): Which values are in your spectrum
            frequency (float): frequency corresponding to the intensity that will be smeared
            Intensity (float): Intensity that will be smeared
            sigma (float): value for the smearing

        """

        y = np.zeros(rangex.size)
        y = Intensity * np.exp(-np.power((rangex - frequency), 2) / (2 * np.power(sigma, 2))) * np.power(
            np.sqrt(2 * np.pi) * sigma, -1)
        return y

    def write_spectrum(self, filename, type='yaml'):
        """
        writes oscillator strenghts to file

        args:
            filename(str): Filename
            type(str): either txt or yaml
        """
        #TODO: csv
        spectrum = self.get_spectrum()
        if type == 'txt':
            self.__write_file(filename, spectrum)
        elif type == 'yaml':
            self.__write_file_yaml(filename, spectrum)

    def write_gaussiansmearedspectrum(self, filename, sigma, type='txt'):
        """
        writes smeared oscillator strenghts to file

        args:
            filename(str): Filename
            sigma(float): smearing of the spectrum
            type(str): either txt or yaml
        """
        #TODO csv
        spectrum = self.get_gaussiansmearedspectrum(sigma)
        if type == 'txt':
            self.__write_file(filename, spectrum)
        elif type == 'yaml':
            self.__write_file_yaml(filename, spectrum)

    def __write_file(self, filename, spectrum):
        """
        writes dict for any spectrum into txt file

        args:
            filename(str): Filename
            spectrum (dict): Includes nparray for 'Frequencies'
             and 'Intensities'

        """

        Freq = np.array(spectrum['Frequencies'].tolist())
        Intens = np.array(spectrum['Intensities'].tolist())
        file = open(filename, 'w')
        file.write('Frequency (cm-1) Oscillator Strengths \n')
        for i in range(len(Freq)):
            file.write('%s %s \n' % (Freq[i], Intens[i]))
        file.close()

    def __write_file_yaml(self, filename, spectrum):
        """
        writes dict for any spectrum into yaml file

        args:
                filename(str): Filename
                spectrum (dict): Includes nparray for 'Frequencies'
                and 'Intensities'

        """
        Freq = np.array(spectrum['Frequencies'].tolist())
        Intens = np.array(spectrum['Intensities'].tolist())
        file = open(filename, 'w')
        file.write('Frequency: \n')
        for i in range(len(Freq)):
            file.write('- %s \n' % (Freq[i]))
        file.write('Oscillator Strengths: \n')
        for i in range(len(Intens)):
            file.write('- %s \n' % (Intens[i]))
        file.close()

    def plot_spectrum(self, filename):
        """
        Plots frequencies in cm-1 and oscillator strengths
        args:
            filename(str): name of the file
        """
        spectrum = self.get_spectrum()
        plt.stem(spectrum['Frequencies'].tolist(), spectrum['Intensities'].tolist(), markerfmt=' ')
        plt.xlabel('Wave number (cm$^{-1}$)')
        plt.ylabel('Oscillator Strengths')
        plt.savefig(filename)
        plt.show()

    def plot_gaussiansmearedspectrum(self, filename, sigma):
        """
        Plots frequencies in cm-1 and smeared oscillator strengths
        args:
            filename(str): name of the file
            sigma(float): smearing
        """
        spectrum = self.get_gaussiansmearedspectrum(sigma)
        plt.plot(spectrum['Frequencies'].tolist(), spectrum['Intensities'].tolist())
        plt.xlabel('Wave number (cm$^{-1}$)')
        plt.ylabel('Oscillator Strengths')
        plt.savefig(filename)
        plt.show()
Пример #22
0
def ir_intensity_phonopy(
    run_dir=".",
    vasprun="vasprun.xml",
    BornFileName="BORN",
    PoscarName="POSCAR",
    ForceConstantsName="FORCE_CONSTANTS",
    supercell=[[1, 0, 0], [0, 1, 0], [0, 0, 1]],
    nac=True,
    symprec=1e-5,
    primitive=[[1, 0, 0], [0, 1, 0], [0, 0, 1]],
    degeneracy_tolerance=1e-5,
    vector=[0, 0, 0],
    smoothen=False,
):
    """Calculate IR intensity using DFPT and phonopy."""
    from phonopy import Phonopy
    from phonopy.interface.vasp import read_vasp
    from phonopy.file_IO import (
        parse_BORN,
        parse_FORCE_CONSTANTS,
    )
    import shutil
    from phonopy.units import VaspToCm

    # from phonopy.phonon.degeneracy import (
    #    degenerate_sets as get_degenerate_sets,
    # )
    # adapted from https://github.com/JaGeo/IR
    # TODO: Make directory indepndent
    cwd = os.getcwd()
    print("Directory:", cwd)
    os.chdir(run_dir)
    if not os.path.exists(vasprun):
        shutil.copy2(vasprun, "vasprun.xml")
    cmd = str("phonopy --fc vasprun.xml")
    os.system(cmd)
    born_file = os.path.join(os.getcwd(), BornFileName)
    cmd = str("phonopy-vasp-born >  ") + str(born_file)
    os.system(cmd)
    from jarvis.io.vasp.outputs import Vasprun

    v = Vasprun(vasprun)
    strt = v.all_structures[0]
    strt.write_poscar(PoscarName)
    unitcell = read_vasp(PoscarName)
    phonon = Phonopy(
        unitcell,
        supercell_matrix=supercell,
        primitive_matrix=primitive,
        factor=VaspToCm,
        symprec=symprec,
    )
    natoms = phonon.get_primitive().get_number_of_atoms()
    force_constants = parse_FORCE_CONSTANTS(filename=ForceConstantsName)
    phonon.set_force_constants(force_constants)
    masses = phonon.get_primitive().get_masses()
    phonon.set_masses(masses)
    BORN_file = parse_BORN(phonon.get_primitive(), filename=BornFileName)
    BORN_CHARGES = BORN_file["born"]
    # print ('born_charges2',BORN_CHARGES)
    if nac:
        phonon.set_nac_params(BORN_file)
    frequencies, eigvecs = phonon.get_frequencies_with_eigenvectors(vector)
    # frequencies=VaspToTHz*frequencies/VaspToCm
    # x, y = ir_intensity(
    #    phonon_eigenvectors=np.real(eigvecs),
    #    phonon_eigenvalues=frequencies,
    #    masses=masses, #np.ones(len(masses)),
    #    born_charges=born_charges,
    #    smoothen=smoothen,
    # )
    NumberOfBands = len(frequencies)
    EigFormat = {}
    for alpha in range(NumberOfBands):
        laufer = 0
        for beta in range(natoms):
            for xyz in range(0, 3):
                EigFormat[beta, alpha, xyz] = eigvecs[laufer][alpha]
                laufer = laufer + 1
    Intensity = {}
    intensities = []
    for freq in range(len(frequencies)):
        Intensity[freq] = 0
        tmp = 0
        for alpha in range(3):
            asum = 0
            for n in range(natoms):
                for beta in range(3):
                    asum = asum + BORN_CHARGES[n, alpha, beta] * np.real(
                        EigFormat[n, freq, beta]
                    ) / np.sqrt(masses[n])
                    tmp += asum
            Intensity[freq] = Intensity[freq] + np.power(np.absolute(asum), 2)
        intensities.append(Intensity[freq])
    os.chdir(cwd)
    return frequencies, intensities
Пример #23
0
def phonopy_merge(**kwargs):
    from phonopy.structure.atoms import Atoms as PhonopyAtoms
    from phonopy import Phonopy
    from phonopy.units import VaspToTHz
    from phonopy.harmonic.dynmat_to_fc import get_commensurate_points, DynmatToForceConstants

    structure = kwargs.pop('structure')
    phonopy_input = kwargs.pop('phonopy_input').get_dict()

    harmonic = kwargs.pop('harmonic')
    renormalized = kwargs.pop('renormalized')

    eigenvectors = harmonic.get_array('eigenvectors')
    frequencies = harmonic.get_array('frequencies')
    shifts = renormalized.get_array('shifts')


    # Generate phonopy phonon object
    bulk = PhonopyAtoms(symbols=[site.kind_name for site in structure.sites],
                        positions=[site.position for site in structure.sites],
                        cell=structure.cell)

    phonon = Phonopy(bulk,
                     phonopy_input['supercell'],
                     primitive_matrix=phonopy_input['primitive'],
                     distance=phonopy_input['distance'])

    primitive = phonon.get_primitive()
    supercell = phonon.get_supercell()



    total_frequencies = frequencies + shifts

    dynmat2fc = DynmatToForceConstants(primitive, supercell)
    dynmat2fc.set_dynamical_matrices(total_frequencies / VaspToTHz, eigenvectors)
    dynmat2fc.run()

    total_force_constants = dynmat2fc.get_force_constants()

    # Stores DOS data in DB as a workflow result
    total_data = ArrayData()
    total_data.set_array('force_constants', total_force_constants)

    return {'final_results': total_data}



    # Start script here

    # Workflow phonon (at given volume)
    wf = load_workflow(431)
    parameters = wf.get_parameters()
    results = wf.get_results()

    inline_params = {'structure': results['final_structure'],
                     'phonopy_input': parameters['phonopy_input'],
                     'force_constants': results['force_constants']}

    harmonic = phonopy_commensurate_inline(**inline_params)



    # At reference volume (at T = 0)
    wf = load_workflow(432)
    parameters = wf.get_parameters()
    results_r = wf.get_results()
    results_h = wf.get_results()


    inline_params = {'structure': results_h['final_structure'],
                     'phonopy_input': parameters['phonopy_input'],
                     'force_constants': results_h['force_constants'],
                     'r_force_constants': results_r['r_force_constants']}


    renormalized = phonopy_commensurate_shifts_inline(**inline_params)





    inline_params = {'structure': results_h['final_structure'],
                     'phonopy_input': parameters['phonopy_input'],
                     'harmonic': harmonic,
                     'renormalized': renormalized}

    total = phonopy_merge(**inline_params)

    print total

    inline_params = {'structure': results_h['final_structure'],
                     'phonopy_input': parameters['phonopy_input'],
                     'force_constants': total['force_constants']}

    results = phonopy_calculation_inline(**inline_params)[1]

    band = results['band_structure']


    # Phonon Band structure plot
    plot_data(results['band_structure'])
Пример #24
0
    Scells_quippy.append(scell_qp)

# calculate forces and convert to phonopy force_sets
force_gap_scells = api_q.calc_force_sets_GAP(gp_xml_file, Scells_quippy)

#parse force set and calc force constants
phonon_scell.set_forces(force_gap_scells)
PhonIO.write_FORCE_SETS(phonon_scell.get_displacement_dataset()
                        )  # write forces & displacements to FORCE_SET
force_set = PhonIO.parse_FORCE_SETS()  # parse force_sets
phonon_scell.set_displacement_dataset(
    force_set)  # force_set is a list of forces and displacements

if NAC == True:
    nac_params = PhonIO.get_born_parameters(
        open("BORN"), phonon_scell.get_primitive(),
        phonon_scell.get_primitive_symmetry())
    if nac_params['factor'] == None:
        physical_units = get_default_physical_units(interface_mode)
        nac_params['factor'] = physical_units['nac_factor']
    phonon_scell._nac_params = nac_params

phonon_scell.produce_force_constants()
phonon_scell.symmetrize_force_constants()
api_ph.write_ShengBTE_FC2(phonon_scell.get_force_constants(),
                          filename='FORCE_CONSTANTS_2ND')
# phonopy 2.7 changed format, ShengBTE won't read, use the file in api_qpv to write.

# calc and plot bandstructure
bands = api_ph.qpoints_Band_paths(Qpoints, Band_points)
phonon_scell.set_band_structure(bands,
Пример #25
0
phonon = Phonopy(unitcell,
                 [[2, 0, 0],
                  [0, 2, 0],
                  [0, 0, 2]],
                 primitive_matrix=[[0, 0.5, 0.5],
                                   [0.5, 0, 0.5],
                                   [0.5, 0.5, 0]])

symmetry = phonon.get_symmetry()
print "Space group:", symmetry.get_international_table()

force_sets = parse_FORCE_SETS()
phonon.set_displacement_dataset(force_sets)
phonon.produce_force_constants()
primitive = phonon.get_primitive()

# Born effective charges and dielectric constants are read from BORN file.
nac_params = parse_BORN(primitive, filename="BORN")
# Or it can be of course given by hand as follows:
# born = [[[1.08703, 0, 0],
#          [0, 1.08703, 0],
#          [0, 0, 1.08703]],
#         [[-1.08672, 0, 0],
#          [0, -1.08672, 0],
#          [0, 0, -1.08672]]]
# epsilon = [[2.43533967, 0, 0],
#            [0, 2.43533967, 0],
#            [0, 0, 2.43533967]]
# factors = 14.400
# nac_params = {'born': born,
Пример #26
0
print "Space group:", symmetry.get_international_table()

# Read and convert forces and displacements
force_sets = parse_FORCE_SETS(cell.get_number_of_atoms() * 4)
# Sets of forces have to be set before phonon.set_post_process or
# at phonon.set_post_process(..., sets_of_forces=sets_of_forces, ...).
phonon.set_force_sets(force_sets)

# To activate non-analytical term correction.
phonon.set_post_process(primitive_matrix=[[2./3, -1./3, -1./3],
                                          [1./3, 1./3, -2./3],
                                          [1./3, 1./3, 1./3]])

# Parameters for non-analytical term correction can be set
# also after phonon.set_post_process
born = parse_BORN(phonon.get_primitive())
phonon.set_nac_params(born)

# Example to obtain dynamical matrix
dmat = phonon.get_dynamical_matrix_at_q([0,0,0])
print dmat

# Example of band structure calculation
bands = []
q_start = np.array([1./3, 1./3, 0])
q_end = np.array([0, 0, 0])
band = []
for i in range(51):
    band.append(q_start + (q_end - q_start) / 50 * i)
bands.append(band)
Пример #27
0
# Initialize phonon. Supercell matrix has to have the shape of (3, 3)
phonon = Phonopy(cell,
                 np.diag([2, 2, 1]),
                 primitive_matrix=[[2. / 3, -1. / 3, -1. / 3],
                                   [1. / 3, 1. / 3, -2. / 3],
                                   [1. / 3, 1. / 3, 1. / 3]])

symmetry = phonon.get_symmetry()
print "Space group:", symmetry.get_international_table()

force_sets = parse_FORCE_SETS()
phonon.set_displacement_dataset(force_sets)
phonon.produce_force_constants()

born = parse_BORN(phonon.get_primitive())
phonon.set_nac_params(born)

# Example to obtain dynamical matrix
dmat = phonon.get_dynamical_matrix_at_q([0, 0, 0])
print dmat

# Example of band structure calculation
bands = []
q_start = np.array([1. / 3, 1. / 3, 0])
q_end = np.array([0, 0, 0])
band = []
for i in range(51):
    band.append(q_start + (q_end - q_start) / 50 * i)
bands.append(band)
class thermal_conductivity():
    def __init__(self, primitive_cell, super_cell):
        self.primitive_cell = primitive_cell
        self.super_cell = super_cell

    def input_files(self, path_POSCAR, path_FORCECONSTANT):
        bulk = read_vasp(path_POSCAR)
        self.phonon = Phonopy(bulk,
                              self.super_cell,
                              primitive_matrix=self.primitive_cell)
        force_constants = file_IO.parse_FORCE_CONSTANTS(path_FORCECONSTANT)
        self.phonon.set_force_constants(force_constants)
        return self.phonon

    def set_mesh(self, mesh):
        self.phonon.set_mesh(mesh, is_eigenvectors=True)

    def set_point_defect_parameter(self, fi, defect_mass, defect_fc_ratio):

        self.mass = self.phonon.get_primitive().get_masses().sum(
        ) / self.phonon.get_primitive().get_number_of_atoms()
        self.cellvol = self.phonon.get_primitive().get_volume()
        self.mass_fc_factor = self.cellvol * 10**-30 / 2.0 / 4 / np.pi * (
            fi *
            ((self.mass - defect_mass) / self.mass + 2 * defect_fc_ratio)**2)

    def kappa_separate(self, gamma, thetaD, T, P=1, m=3, n=1):
        """
        nkpts: number of phonon k-points
        frequencies: list of eigenvalue-arrays as output by phonopy
        vgroup: group velocities
        T: temperature in K

        following parameters from Eq (70) in Tritt book, p.14
        P: proportionality factor of Umklapp scattering rate, defualt 1
        mass: mass in amu (average mass of unitcell)
        gamma: Gruneisen parameter, unitless
        thetaD: Debye temperature of relevance (acoustic modes) 283K for Mo3Sb7
        m = 3 by default
        n = 1 by default
        cellvol: unit cell volume in A^3
        """

        T = float(T)
        #self.phonon.set_mesh(mesh, is_eigenvectors=True)
        #self.mass = self.phonon.get_primitive().get_masses().sum()/self.phonon.get_primitive().get_number_of_atoms()
        self.cellvol = self.phonon.get_primitive().get_volume()
        self.qpoints, self.weigths, self.frequencies, self.eigvecs = self.phonon.get_mesh(
        )

        nkpts = self.frequencies.shape[0]
        numbranches = self.frequencies.shape[1]

        self.group_velocity = np.zeros((nkpts, numbranches, 3))
        for i in range(len(self.qpoints)):
            self.group_velocity[i, :, :] = self.phonon.get_group_velocity_at_q(
                self.qpoints[i])

        inv_nor_Um = np.zeros((nkpts, numbranches))
        inv_point_defect_mass_fc = np.zeros((nkpts, numbranches))
        inv_tau_total = np.zeros((nkpts, numbranches))

        kappa_Um = np.zeros((nkpts, numbranches))
        kappa_point_defect_mass_fc = np.zeros((nkpts, numbranches))
        kappa_total = np.zeros((nkpts, numbranches))
        self.kappaten = np.zeros((nkpts, numbranches, 3, 3))

        v_group = np.zeros((nkpts, numbranches))
        capacity = np.zeros((nkpts, numbranches))

        for i in range(nkpts):
            for j in range(numbranches):
                nu = self.frequencies[i][
                    j]  # frequency (in Thz) of current mode
                velocity = self.group_velocity[
                    i, j, :]  # cartesian vector of group velocity
                v_group = (velocity[0]**2 + velocity[1]**2 +
                           velocity[2]**2)**(0.5) * THztoA
                capacity[i, j] = mode_cv(
                    T, nu * THzToEv) * eV2Joule / (self.cellvol * Ang2meter**3)

                # tau inverse phonon-phonon, inverse lifetime
                inv_nor_Um[i, j] = P * hbar * gamma**2 / (
                    self.mass * amu) / v_group**2 * (T**n) / thetaD * (
                        2 * np.pi * THz * nu)**2 * np.exp(
                            (-1.0) * thetaD / m / T)

                # tau inverse point defect, inverse lifetime
                inv_point_defect_mass_fc[i, j] = (self.mass_fc_factor) * (
                    2 * np.pi * THz * nu)**4 / v_group**3

                # tau inverst, inverse lifetime
                inv_tau_total[
                    i, j] = inv_nor_Um[i, j] + inv_point_defect_mass_fc[i, j]

                kappa_total[
                    i,
                    j] = (1.0 / 3.0) * self.weigths[i] * v_group**2 * capacity[
                        i,
                        j] / inv_tau_total[i,
                                           j]  # 1/3 is for isotropic condition
                kappa_Um[
                    i,
                    j] = (1.0 / 3.0) * self.weigths[i] * v_group**2 * capacity[
                        i, j] / inv_nor_Um[i,
                                           j]  # 1/3 is for isotropic condition
                kappa_point_defect_mass_fc[
                    i,
                    j] = (1.0 / 3.0) * self.weigths[i] * v_group**2 * capacity[
                        i, j] / inv_point_defect_mass_fc[
                            i, j]  # 1/3 is for isotropic condition
                self.kappaten[i, j, :, :] = self.weigths[i] * np.outer(
                    velocity,
                    velocity) * THztoA**2 * capacity[i, j] / inv_tau_total[i,
                                                                           j]
        #print(np.sum(inv_nor_Um, axis =1))
        #print(np.sum(inv_point_defect_mass_fc, axis =1))
        #print(np.sum(inv_tau_total, axis =1))
        self.tau = np.concatenate(
            (inv_nor_Um, inv_point_defect_mass_fc, inv_tau_total), axis=1)
        self.kappa = [
            kappa_Um.sum() / self.weigths.sum(),
            kappa_point_defect_mass_fc.sum() / self.weigths.sum(),
            kappa_total.sum() / self.weigths.sum()
        ]
        return self.tau, self.kappa, self.kappaten