Example #1
0
def get_force_constants3(data_sets, structure, ph_settings):

    from phono3py.phonon3 import Phono3py
    from aiida_phonopy.common.utils import phonopy_atoms_from_structure

    # Generate phonopy phonon object
    phono3py = Phono3py(phonopy_atoms_from_structure(structure),
                        supercell_matrix=ph_settings.dict.supercell,
                        primitive_matrix=ph_settings.dict.primitive,
                        symprec=ph_settings.dict.symmetry_tolerance,
                        log_level=1)

    phono3py.produce_fc3(data_sets.get_forces3(),
                         displacement_dataset=data_sets.get_data_sets3(),
                         is_translational_symmetry=True,
                         is_permutation_symmetry=True,
                         is_permutation_symmetry_fc2=True)
    fc3 = phono3py.get_fc3()
    fc2 = phono3py.get_fc2()

    force_constants_2 = ForceConstantsData(data=fc2)
    force_constants_3 = ForceConstantsData(data=fc3)

    return {
        'force_constants_2order': force_constants_2,
        'force_constants_3order': force_constants_3
    }
Example #2
0
def get_thermal_properties(structure, ph_settings, force_constants_list):
    from phonopy import Phonopy
    from aiida_phonopy.common.utils import phonopy_atoms_from_structure

    free_energy_list = []
    entropy_list = []
    cv_list = []
    temperature = None
    for fc in force_constants_list:
        phonon = Phonopy(phonopy_atoms_from_structure(structure),
                         ph_settings.dict.supercell,
                         primitive_matrix=ph_settings.dict.primitive,
                         symprec=ph_settings.dict.symmetry_tolerance)

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

        phonon.set_force_constants(fc)
        phonon.set_mesh(ph_settings.dict.mesh,
                        is_eigenvectors=True,
                        is_mesh_symmetry=False)
        phonon.set_thermal_properties()
        temperature, free_energy, entropy, cv = phonon.get_thermal_properties()
        free_energy_list.append(np.array(free_energy) * normalization_factor)
        entropy_list.append(np.array(entropy) * normalization_factor)
        cv_list.append(np.array(cv) * normalization_factor)

    return np.array(free_energy_list), np.array(entropy_list).T, np.array(
        cv_list).T, temperature
Example #3
0
def get_random_displacements(structure, number_of_snapshots, temperature,
                             **data):
    displacements = []
    forces = []
    energies = []

    for i in range(len(data) // 2):
        forces.append(data['forces_%d' % (i + 1)].get_array('force_sets'))
        if 'energies' in data['forces_%d' % (i + 1)].get_arraynames():
            energies.append(data['forces_%d' % (i + 1)].get_array('energies'))
        phonon_setting_info = data['ph_info_%d' % (i + 1)]
        dataset = phonon_setting_info['displacement_dataset']
        disps, _ = get_displacements_and_forces(dataset)
        displacements.append(disps)
    d = np.concatenate(displacements, axis=0)
    f = np.concatenate(forces, axis=0)

    idx = None
    if len(energies) == len(forces) and 'include_ratio' in data:
        all_energies = np.concatenate(energies)
        if len(all_energies) == len(f):
            ratio = data['include_ratio'].value
            if 0 < ratio and ratio < 1:
                num_include = int(np.ceil(ratio * len(all_energies)))
                if num_include > len(all_energies):
                    num_include = len(all_energies)
                idx = np.argsort(all_energies)[:num_include]
                d = d[idx]
                f = f[idx]

    phonon_setting_info = data['ph_info_1']
    smat = phonon_setting_info['supercell_matrix']
    ph = phonopy.load(unitcell=phonopy_atoms_from_structure(structure),
                      supercell_matrix=smat,
                      primitive_matrix='auto')
    ph.dataset = {'displacements': d, 'forces': f}
    ph.produce_force_constants(fc_calculator='alm')

    _modify_force_constants(ph)

    if 'random_seed' in data:
        _random_seed = data['random_seed'].value
    else:
        _random_seed = None

    ph.generate_displacements(number_of_snapshots=number_of_snapshots.value,
                              random_seed=_random_seed,
                              temperature=temperature.value)

    ret_dict = {'displacement_dataset': Dict(dict=ph.dataset)}

    if idx is not None:
        array = DataFactory('array')()
        array.set_array('supercell_energies', all_energies)
        array.set_array('included_supercell_indices', idx)
        ret_dict['supercell_energies'] = array

    return ret_dict
def get_phonon(pk, pk_nac):
    n = load_node(pk)
    unitcell = phonopy_atoms_from_structure(n.inputs.structure)
    smat = n.outputs.phonon_setting_info['supercell_matrix']
    ph = Phonopy(unitcell, supercell_matrix=smat, primitive_matrix='auto')
    force_sets = n.outputs.force_sets.get_array('force_sets')
    dataset = n.outputs.phonon_setting_info['displacement_dataset']
    ph.dataset = dataset
    ph.forces = force_sets
    ph.nac_params = get_nac_params(pk_nac)

    return ph
Example #5
0
def get_phonopy_yaml_txt(structure,
                         settings,
                         supercell_matrix=None,
                         primitive_matrix=None,
                         calculator=None):
    unitcell = phonopy_atoms_from_structure(structure)
    ph = Phonopy(unitcell,
                 supercell_matrix=settings['supercell_matrix'],
                 primitive_matrix='auto',
                 calculator=calculator)
    phpy_yaml = PhonopyYaml()
    phpy_yaml.set_phonon_info(ph)

    return str(phpy_yaml)
Example #6
0
def create_supercells_with_displacements_using_phono3py(
        structure, ph_settings, cutoff):
    """
    Use phono3py to create the supercells with displacements to calculate the force constants by using
    finite displacements methodology

    :param structure: StructureData object
    :param phonopy_input: Dict object containing a dictionary with the data needed for phonopy
    :param cutoff: FloatData object containing the value of the cutoff for 3rd order FC in Angstroms (if 0 no cutoff is applied)
    :return: A set of StructureData Objects containing the supercells with displacements
    """
    from phono3py.phonon3 import Phono3py

    from aiida_phonopy.common.utils import phonopy_atoms_from_structure

    # Generate phonopy phonon object
    phono3py = Phono3py(phonopy_atoms_from_structure(structure),
                        supercell_matrix=ph_settings.dict.supercell,
                        primitive_matrix=ph_settings.dict.primitive,
                        symprec=ph_settings.dict.symmetry_tolerance,
                        log_level=1)

    if float(cutoff) == 0:
        cutoff = None
    else:
        cutoff = float(cutoff)

    phono3py.generate_displacements(distance=ph_settings.dict.distance,
                                    cutoff_pair_distance=cutoff)

    cells_with_disp = phono3py.get_supercells_with_displacements()

    # Transform cells to StructureData and set them ready to return
    data_sets = phono3py.get_displacement_dataset()
    data_sets_object = ForceSetsData(data_sets3=data_sets)

    disp_cells = {'data_sets': data_sets_object}
    for i, phonopy_supercell in enumerate(cells_with_disp):
        if phonopy_supercell is None:
            print('structure_{} cutoff skip'.format(i))
            continue
        supercell = StructureData(cell=phonopy_supercell.get_cell())
        for symbol, position in zip(phonopy_supercell.get_chemical_symbols(),
                                    phonopy_supercell.get_positions()):
            supercell.append_atom(position=position, symbols=symbol)
        disp_cells['structure_{}'.format(i)] = supercell

    return disp_cells
Example #7
0
def get_commensurate(structure, ph_settings):
    from phonopy import Phonopy
    from phonopy.harmonic.dynmat_to_fc import DynmatToForceConstants
    from aiida_phonopy.common.utils import phonopy_atoms_from_structure

    phonon = Phonopy(phonopy_atoms_from_structure(structure),
                     ph_settings.dict.supercell,
                     primitive_matrix=ph_settings.dict.primitive,
                     symprec=ph_settings.dict.symmetry_tolerance)

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

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

    return dynmat2fc, commensurate
Example #8
0
def get_phonon(structure, force_constants, ph_settings, nac_data=None):
    from phonopy import Phonopy
    from aiida_phonopy.common.utils import phonopy_atoms_from_structure

    phonon = Phonopy(phonopy_atoms_from_structure(structure),
                     ph_settings.dict.supercell,
                     primitive_matrix=ph_settings.dict.primitive,
                     symprec=ph_settings.dict.symmetry_tolerance)

    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
Example #9
0
def get_BORN_txt(nac_data, structure, symmetry_tolerance):
    """Returns a string of BORN file.

    nac_data : ArrayData
        Born effective charges and dielectric constants
    structure : StructureData
        This is assumed to be the primitive cell in workchain.
    symmetry_tolerance : float
        Symmetry tolerance.
    """

    from phonopy.file_IO import get_BORN_lines

    born_charges = nac_data.get_array('born_charges')
    epsilon = nac_data.get_array('epsilon')
    pcell = phonopy_atoms_from_structure(structure)
    lines = get_BORN_lines(pcell, born_charges, epsilon,
                           symprec=symmetry_tolerance)

    return "\n".join(lines)
Example #10
0
    def generate_displacements(self):
        label = 'force_constants_%d' % self.ctx.iteration
        fc_array = self.ctx[label].outputs.force_constants
        fc = fc_array.get_array('force_constants')
        phonon_setting_info = self.inputs.phonon_settings
        smat = phonon_setting_info['supercell_matrix']
        ph = Phonopy(phonopy_atoms_from_structure(self.inputs.structure),
                     supercell_matrix=smat,
                     primitive_matrix='auto')
        ph.force_constants = fc

        if 'random_seed' in self.inputs:
            random_seed = self.inputs.random_seed.value
        else:
            random_seed = None
        dataset = _generate_random_displacements(
            ph,
            self.inputs.number_of_snapshots.value,
            self.inputs.temperature.value,
            random_seed=random_seed)
        self.ctx.dataset = Dict(dict=dataset)
def bunch_phonons(pks,
                  pk_nac,
                  max_items=None,
                  include_ratio=None,
                  linear_decay=True):
    nodes = [load_node(pk) for pk in pks]
    displacements, forces, energies = _extract_dataset_from_db(
        [n.outputs.force_sets for n in nodes],
        [n.outputs.phonon_setting_info for n in nodes])
    d, f, e, idx = _create_dataset(displacements,
                                   forces,
                                   energies,
                                   max_items,
                                   include_ratio,
                                   linear_decay=linear_decay)
    unitcell = phonopy_atoms_from_structure(nodes[0].inputs.structure)
    smat = nodes[0].outputs.phonon_setting_info['supercell_matrix']
    ph = Phonopy(unitcell, supercell_matrix=smat, primitive_matrix='auto')
    ph.dataset = {'displacements': d, 'forces': f}
    ph.nac_params = get_nac_params(pk_nac)
    return ph
Example #12
0
def get_random_displacements(structure,
                             number_of_snapshots,
                             temperature,
                             phonon_setting_info,
                             dataset_for_fc,
                             random_seed=None):
    """Generate supercells with random displacemens

    The random displacements are generated from phonons and harmonic
    oscillator distribution function of canonical ensemble. The input
    phonons are calculated from force constants calculated from
    forces and displacemens of the supercell snapshots in previous
    phonon calculation steps.

    Returns
    -------
    dataset : Dict
        Displacement datasets to run force calculations.

    """

    # Calculate force constants by fitting using ALM
    smat = phonon_setting_info['supercell_matrix']
    ph = Phonopy(phonopy_atoms_from_structure(structure),
                 supercell_matrix=smat,
                 primitive_matrix='auto')
    d = dataset_for_fc.get_array('displacements')
    f = dataset_for_fc.get_array('forces')
    ph.dataset = {'displacements': d, 'forces': f}
    ph.produce_force_constants(fc_calculator='alm')

    if random_seed is not None:
        _random_seed = random_seed.value
    else:
        _random_seed = None
    dataset = _generate_random_displacements(ph,
                                             number_of_snapshots.value,
                                             temperature.value,
                                             random_seed=_random_seed)
    return Dict(dict=dataset)
Example #13
0
def dump_phonopy(pk):
    n = load_node(pk)
    unitcell = phonopy_atoms_from_structure(n.inputs.structure)
    smat = n.outputs.phonon_setting_info['supercell_matrix']
    ph = Phonopy(unitcell, smat, primitive_matrix='auto')
    force_sets = n.outputs.force_sets.get_array('force_sets')
    dataset = n.outputs.phonon_setting_info['displacement_dataset']
    ph.dataset = dataset
    ph.forces = force_sets
    if 'nac_params' in n.outputs:
        borns = n.outputs.nac_params.get_array('born_charges')
        epsilon = n.outputs.nac_params.get_array('epsilon')
        nac_params = {
            'born': borns,
            'factor': 14.399652,
            'dielectric': epsilon
        }
        ph.nac_params = nac_params

    # phonopy-params.yaml is written out.
    ph.save()
    print("phonopy_params.yaml was made for PK=%d" % pk)
Example #14
0
def get_grid_points(structure, parameters):

    from phono3py.phonon3 import Phono3py
    from phono3py.cui.triplets_info import get_coarse_ir_grid_points
    from aiida_phonopy.common.utils import phonopy_atoms_from_structure

    # Generate phonopy phonon object
    phono3py = Phono3py(phonopy_atoms_from_structure(structure),
                        supercell_matrix=parameters.dict.supercell,
                        primitive_matrix=parameters.dict.primitive,
                        symprec=parameters.dict.symmetry_tolerance,
                        log_level=1)

    primitive = phono3py.get_primitive()
    (ir_grid_points, grid_weights, bz_grid_address,
     grid_mapping_table) = get_coarse_ir_grid_points(primitive,
                                                     parameters.dict.mesh,
                                                     None,
                                                     None,
                                                     is_kappa_star=True,
                                                     symprec=1e-5)

    return ir_grid_points
Example #15
0
def get_disp_fc3_txt(structure, parameters_data, force_sets):
    from phono3py.file_IO import write_cell_yaml
    dataset = force_sets.get_datasets3()
    supercell = get_supercell(phonopy_atoms_from_structure(structure),
                              parameters_data.dict.supercell,
                              symprec=parameters_data.dict.symmetry_tolerance)

    w = StringIO.StringIO()
    w.write("natom: %d\n" % dataset['natom'])

    num_first = len(dataset['first_atoms'])
    w.write("num_first_displacements: %d\n" % num_first)
    if 'cutoff_distance' in dataset:
        w.write("cutoff_distance: %f\n" % dataset['cutoff_distance'])

    num_second = 0
    num_disp_files = 0
    for d1 in dataset['first_atoms']:
        num_disp_files += 1
        num_second += len(d1['second_atoms'])
        for d2 in d1['second_atoms']:
            if 'included' in d2:
                if d2['included']:
                    num_disp_files += 1
            else:
                num_disp_files += 1

    w.write("num_second_displacements: %d\n" % num_second)
    w.write("num_displacements_created: %d\n" % num_disp_files)

    w.write("first_atoms:\n")
    count1 = 1
    count2 = num_first + 1
    for disp1 in dataset['first_atoms']:
        disp_cart1 = disp1['displacement']
        w.write("- number: %5d\n" % (disp1['number'] + 1))
        w.write("  displacement:\n")
        w.write("    [%20.16f,%20.16f,%20.16f ] # %05d\n" %
                (disp_cart1[0], disp_cart1[1], disp_cart1[2], count1))
        w.write("  second_atoms:\n")
        count1 += 1

        included = None
        atom2 = -1
        for disp2 in disp1['second_atoms']:
            if atom2 != disp2['number']:
                atom2 = disp2['number']
                if 'included' in disp2:
                    included = disp2['included']
                pair_distance = disp2['pair_distance']
                w.write("  - number: %5d\n" % (atom2 + 1))
                w.write("    distance: %f\n" % pair_distance)
                if included is not None:
                    if included:
                        w.write("    included: %s\n" % "true")
                    else:
                        w.write("    included: %s\n" % "false")
                w.write("    displacements:\n")

            disp_cart2 = disp2['displacement']
            w.write("    - [%20.16f,%20.16f,%20.16f ] # %05d\n" %
                    (disp_cart2[0], disp_cart2[1], disp_cart2[2], count2))
            count2 += 1

    write_cell_yaml(w, supercell)
    w.seek(0)
    lines = w.read()
    w.close()
    return lines