Example #1
0
def _expand_fc2(fc2_alm,
                supercell,
                pure_trans,
                rotations,
                symprec=1e-5,
                verbose=True):
    natom = supercell.get_number_of_atoms()
    fc2 = np.zeros((natom, natom, 3, 3), dtype='double', order='C')
    (fc_values, elem_indices) = fc2_alm
    first_atoms = np.unique(elem_indices[:, 0] // 3)

    for (fc, indices) in zip(fc_values, elem_indices):
        v1 = indices[0] // 3
        c1 = indices[0] % 3
        v2 = indices[1] // 3
        c2 = indices[1] % 3
        fc2[v1, v2, c1, c2] = fc

    lattice = np.array(supercell.get_cell().T, dtype='double', order='C')
    positions = supercell.get_scaled_positions()
    permutations = compute_all_sg_permutations(positions, rotations,
                                               pure_trans, lattice, symprec)
    distribute_force_constants(fc2, first_atoms, lattice, rotations,
                               permutations)

    return fc2
Example #2
0
 def _distribute(self):
     rotations = self._symmetry.get_symmetry_operations()['rotations']
     trans = self._symmetry.get_symmetry_operations()['translations']
     distribute_force_constants(self._fc2, range(self._num_atom),
                                self._unique_first_atom_nums, self._lattice,
                                self._positions, rotations, trans,
                                self._symprec)
Example #3
0
    def _calculate(self):
        unique_first_atom_nums = np.unique(
            [x['number'] for x in self._dataset['first_atoms']])

        for first_atom_num in unique_first_atom_nums:
            disp_triplets = []
            sets_of_forces = []
            for dataset_1st in self._dataset['first_atoms']:
                if first_atom_num != dataset_1st['number']:
                    continue
                d1 = dataset_1st['displacement']
                d3, f = self._collect_forces_and_disps(dataset_1st)
                disp_triplets.append(d3)
                sets_of_forces.append(f)

            self._fit(first_atom_num, disp_triplets, sets_of_forces)

        rotations = self._symmetry.get_symmetry_operations()['rotations']
        translations = self._symmetry.get_symmetry_operations()['translations']

        print "ditributing fc4..."
        distribute_fc4(self._fc4, unique_first_atom_nums, self._lattice,
                       self._positions, rotations, translations, self._symprec,
                       self._verbose)

        print "ditributing fc3..."
        distribute_fc3(self._fc3, unique_first_atom_nums, self._lattice,
                       self._positions, rotations, translations, self._symprec,
                       self._verbose)

        print "ditributing fc2..."
        distribute_force_constants(self._fc2, range(self._num_atom),
                                   unique_first_atom_nums, self._lattice,
                                   self._positions, rotations, translations,
                                   self._symprec)
Example #4
0
def get_constrained_fc2(supercell,
                        dataset_second_atoms,
                        atom1,
                        forces1,
                        reduced_site_sym,
                        symprec):
    """
    dataset_second_atoms: [{'number': 7,
                            'displacement': [],
                            'forces': []}, ...]
    """
    lattice = supercell.get_cell().T
    positions = supercell.get_scaled_positions()
    num_atom = supercell.get_number_of_atoms()

    fc2 = np.zeros((num_atom, num_atom, 3, 3), dtype='double')
    atom_list = np.unique([x['number'] for x in dataset_second_atoms])
    for atom2 in atom_list:
        disps2 = []
        sets_of_forces = []
        for disps_second in dataset_second_atoms:
            if atom2 != disps_second['number']:
                continue
            bond_sym = get_bond_symmetry(
                reduced_site_sym,
                lattice,
                positions,
                atom1,
                atom2,
                symprec)

            disps2.append(disps_second['displacement'])
            sets_of_forces.append(disps_second['forces'] - forces1)

        solve_force_constants(fc2,
                              atom2,
                              disps2,
                              sets_of_forces,
                              supercell,
                              bond_sym,
                              symprec)

    # Shift positions according to set atom1 is at origin
    pos_center = positions[atom1].copy()
    positions -= pos_center
    rotations = np.array(reduced_site_sym, dtype='intc', order='C')
    translations = np.zeros((len(reduced_site_sym), 3),
                            dtype='double', order='C')
    permutations = compute_all_sg_permutations(positions,
                                               rotations,
                                               translations,
                                               lattice,
                                               symprec)
    distribute_force_constants(fc2,
                               atom_list,
                               lattice,
                               rotations,
                               permutations)
    return fc2
Example #5
0
 def _distribute(self):
     rotations = self._symmetry.get_symmetry_operations()['rotations']
     trans = self._symmetry.get_symmetry_operations()['translations']
     distribute_force_constants(self._fc2,
                                range(self._num_atom),
                                self._unique_first_atom_nums,
                                self._lattice,
                                self._positions,
                                rotations,
                                trans,
                                self._symprec)
Example #6
0
def get_constrained_fc2(
    supercell,
    dataset_second_atoms,
    atom1,
    reduced_site_sym,
    translational_symmetry_type,
    is_permutation_symmetry,
    symprec,
):
    """
    dataset_second_atoms: [{'number': 7,
                            'displacement': [],
                            'delta_forces': []}, ...]
    """
    num_atom = supercell.get_number_of_atoms()
    fc2 = np.zeros((num_atom, num_atom, 3, 3), dtype="double")
    atom_list = np.unique([x["number"] for x in dataset_second_atoms])
    for atom2 in atom_list:
        disps2 = []
        sets_of_forces = []
        for disps_second in dataset_second_atoms:
            if atom2 != disps_second["number"]:
                continue
            bond_sym = get_bond_symmetry(reduced_site_sym, supercell.get_scaled_positions(), atom1, atom2, symprec)

            disps2.append(disps_second["displacement"])
            sets_of_forces.append(disps_second["delta_forces"])

        solve_force_constants(fc2, atom2, disps2, sets_of_forces, supercell, bond_sym, symprec)

    # Shift positions according to set atom1 is at origin
    lattice = supercell.get_cell().T
    positions = supercell.get_scaled_positions()
    pos_center = positions[atom1].copy()
    positions -= pos_center
    distribute_force_constants(
        fc2,
        range(num_atom),
        atom_list,
        lattice,
        positions,
        np.array(reduced_site_sym, dtype="intc", order="C"),
        np.zeros((len(reduced_site_sym), 3), dtype="double"),
        symprec,
    )

    if translational_symmetry_type:
        set_translational_invariance(fc2, translational_symmetry_type=translational_symmetry_type)

    if is_permutation_symmetry:
        set_permutation_symmetry(fc2)

    return fc2
Example #7
0
def distribute_force_constants_by_translations(fc, primitive, supercell):
    s2p = primitive.get_supercell_to_primitive_map()
    p2s = primitive.get_primitive_to_supercell_map()
    positions = supercell.get_scaled_positions()
    lattice = supercell.get_cell().T
    diff = positions - positions[p2s[0]]
    trans = np.array(diff[np.where(s2p == p2s[0])[0]],
                     dtype='double',
                     order='C')
    rotations = np.array([np.eye(3, dtype='intc')] * len(trans),
                         dtype='intc',
                         order='C')
    permutations = primitive.get_atomic_permutations()
    distribute_force_constants(fc, p2s, lattice, rotations, permutations)
Example #8
0
    def _calculate(self):
        unique_first_atom_nums = np.unique(
            [x['number'] for x in self._dataset['first_atoms']])

        for first_atom_num in unique_first_atom_nums:
            disp_triplets = []
            sets_of_forces = []
            for dataset_1st in self._dataset['first_atoms']:
                if first_atom_num != dataset_1st['number']:
                    continue
                d1 = dataset_1st['displacement']
                d3, f = self._collect_forces_and_disps(dataset_1st)
                disp_triplets.append(d3)
                sets_of_forces.append(f)

            self._fit(first_atom_num, disp_triplets, sets_of_forces)

        rotations = self._symmetry.get_symmetry_operations()['rotations']
        translations = self._symmetry.get_symmetry_operations()['translations']

        print "ditributing fc4..."
        distribute_fc4(self._fc4,
                       unique_first_atom_nums,
                       self._lattice,
                       self._positions,
                       rotations,
                       translations,
                       self._symprec,
                       self._verbose)

        print "ditributing fc3..."
        distribute_fc3(self._fc3,
                       unique_first_atom_nums,
                       self._lattice,
                       self._positions,
                       rotations,
                       translations,
                       self._symprec,
                       self._verbose)

        print "ditributing fc2..."
        distribute_force_constants(self._fc2,
                                   range(self._num_atom),
                                   unique_first_atom_nums,
                                   self._lattice,
                                   self._positions,
                                   rotations,
                                   translations,
                                   self._symprec)
Example #9
0
def distribute_force_constants_by_translations(fc, primitive, supercell):
    s2p = primitive.get_supercell_to_primitive_map()
    p2s = primitive.get_primitive_to_supercell_map()
    positions = supercell.get_scaled_positions()
    lattice = supercell.get_cell().T
    diff = positions - positions[p2s[0]]
    trans = np.array(diff[np.where(s2p == p2s[0])[0]],
                     dtype='double', order='C')
    rotations = np.array([np.eye(3, dtype='intc')] * len(trans),
                         dtype='intc', order='C')
    permutations = primitive.get_atomic_permutations()
    distribute_force_constants(fc,
                               p2s,
                               lattice,
                               rotations,
                               permutations)
Example #10
0
 def _distribute_force_constants(self):
     s2p = self._primitive.get_supercell_to_primitive_map()
     p2s = self._primitive.get_primitive_to_supercell_map()
     positions = self._supercell.get_scaled_positions()
     lattice = self._supercell.get_cell().T
     diff = positions - positions[p2s[0]]
     trans = np.array(diff[np.where(s2p == p2s[0])[0]],
                      dtype='double',
                      order='C')
     rotations = np.array([np.eye(3, dtype='intc')] * len(trans),
                          dtype='intc',
                          order='C')
     distribute_force_constants(
         self._force_constants,
         range(self._supercell.get_number_of_atoms()), p2s, lattice,
         positions, rotations, trans, 1e-5)
Example #11
0
def get_constrained_fc2(supercell, dataset_second_atoms, atom1,
                        reduced_site_sym, translational_symmetry_type,
                        is_permutation_symmetry, symprec):
    """
    dataset_second_atoms: [{'number': 7,
                            'displacement': [],
                            'delta_forces': []}, ...]
    """
    num_atom = supercell.get_number_of_atoms()
    fc2 = np.zeros((num_atom, num_atom, 3, 3), dtype='double')
    atom_list = np.unique([x['number'] for x in dataset_second_atoms])
    atom_list_done = []
    for atom2 in atom_list:
        disps2 = []
        sets_of_forces = []
        for disps_second in dataset_second_atoms:
            if atom2 != disps_second['number']:
                continue
            atom_list_done.append(atom2)
            bond_sym = get_bond_symmetry(reduced_site_sym,
                                         supercell.get_scaled_positions(),
                                         atom1, atom2, symprec)

            disps2.append(disps_second['displacement'])
            sets_of_forces.append(disps_second['delta_forces'])

        solve_force_constants(fc2, atom2, disps2, sets_of_forces, supercell,
                              bond_sym, symprec)

    # Shift positions according to set atom1 is at origin
    lattice = supercell.get_cell().T
    positions = supercell.get_scaled_positions()
    pos_center = positions[atom1].copy()
    positions -= pos_center
    distribute_force_constants(
        fc2, range(num_atom), atom_list_done, lattice, positions,
        np.array(reduced_site_sym, dtype='intc', order='C'),
        np.zeros((len(reduced_site_sym), 3), dtype='double'), symprec)

    if translational_symmetry_type:
        set_translational_invariance(
            fc2, translational_symmetry_type=translational_symmetry_type)

    if is_permutation_symmetry:
        set_permutation_symmetry(fc2)

    return fc2
Example #12
0
 def _distribute_force_constants(self):
     s2p = self._primitive.get_supercell_to_primitive_map()
     p2s = self._primitive.get_primitive_to_supercell_map()
     positions = self._supercell.get_scaled_positions()
     lattice = self._supercell.get_cell().T
     diff = positions - positions[p2s[0]]
     trans = np.array(diff[np.where(s2p == p2s[0])[0]],
                      dtype='double', order='C')
     rotations = np.array([np.eye(3, dtype='intc')] * len(trans),
                          dtype='intc', order='C')
     distribute_force_constants(self._force_constants,
                                range(self._supercell.get_number_of_atoms()),
                                p2s,
                                lattice,
                                positions,
                                rotations,
                                trans,
                                1e-5)
Example #13
0
    def _distribute_fc2(self, fc, s_indices, scell, natom):
        dim = self.dimension
        t = np.zeros((np.prod(dim), 3), dtype='double', order='C')
        r = np.zeros((np.prod(dim), 3, 3), dtype='intc', order='C')

        for i, (d3, d2, d1) in enumerate(np.ndindex(dim[::-1])):
            r[i] = np.identity(3, dtype='intc')
            t[i] = np.array([d1, d2, d3], dtype='double') / dim

        natom_s = scell.get_number_of_atoms()
        lattice = np.array(scell.get_cell().T, dtype='double', order='C')
        distribute_force_constants(fc,
                                   np.arange(natom, dtype='intc'),
                                   s_indices,
                                   lattice,
                                   scell.get_scaled_positions(),
                                   r,
                                   t,
                                   self._symprec)
Example #14
0
def _get_constrained_fc2(supercell, dataset_second_atoms, atom1, forces1,
                         reduced_site_sym, symprec):
    """Return fc2 under reduced (broken) site symmetry by first displacement.

    dataset_second_atoms: [{'number': 7,
                            'displacement': [],
                            'forces': []}, ...]

    """
    lattice = supercell.cell.T
    positions = supercell.scaled_positions
    num_atom = len(supercell)

    fc2 = np.zeros((num_atom, num_atom, 3, 3), dtype="double")
    atom_list = np.unique([x["number"] for x in dataset_second_atoms])
    for atom2 in atom_list:
        disps2 = []
        sets_of_forces = []
        for disps_second in dataset_second_atoms:
            if atom2 != disps_second["number"]:
                continue
            bond_sym = get_bond_symmetry(reduced_site_sym, lattice, positions,
                                         atom1, atom2, symprec)

            disps2.append(disps_second["displacement"])
            sets_of_forces.append(disps_second["forces"] - forces1)

        solve_force_constants(fc2, atom2, disps2, sets_of_forces, supercell,
                              bond_sym, symprec)

    # Shift positions according to set atom1 is at origin
    pos_center = positions[atom1].copy()
    positions -= pos_center
    rotations = np.array(reduced_site_sym, dtype="intc", order="C")
    translations = np.zeros((len(reduced_site_sym), 3),
                            dtype="double",
                            order="C")
    permutations = compute_all_sg_permutations(positions, rotations,
                                               translations, lattice, symprec)
    distribute_force_constants(fc2, atom_list, lattice, rotations,
                               permutations)
    return fc2
Example #15
0
def get_fc2(supercell, primitive, disp_dataset, atom_list=None, log_level=0):
    lattice = supercell.get_cell().T
    positions = supercell.get_scaled_positions()
    numbers = supercell.get_atomic_numbers()
    natom = len(numbers)
    disps, forces = _collect_disps_and_forces(disp_dataset)
    p2s_map = primitive.p2s_map
    p2p_map = primitive.p2p_map

    if log_level:
        print("-------------------------------"
              " ALM FC2 start "
              "------------------------------")
        print("ALM by T. Tadano, https://github.com/ttadano/ALM")
        if log_level == 1:
            print("Use -v option to watch detailed ALM log.")

    try:
        from alm import ALM
    except ImportError:
        raise ModuleNotFoundError("ALM python module was not found.")

    sys.stdout.flush()
    with ALM(lattice, positions, numbers) as alm:
        if log_level > 0:
            log_level_alm = log_level - 1
        else:
            log_level_alm = 0
        alm.set_verbosity(log_level_alm)
        alm.define(1)
        alm.set_displacement_and_force(disps, forces)
        alm.optimize()
        if (atom_list == p2s_map).all():
            fc2 = np.zeros((len(p2s_map), natom, 3, 3),
                           dtype='double',
                           order='C')
            for fc, indices in zip(*alm.get_fc(1, mode='origin')):
                v1, v2 = indices // 3
                c1, c2 = indices % 3
                fc2[p2p_map[v1], v2, c1, c2] = fc
        elif atom_list is None or (atom_list == np.range(natom)):
            fc2 = np.zeros((natom, natom, 3, 3), dtype='double', order='C')
            for fc, indices in zip(*alm.get_fc(1, mode='all')):
                v1, v2 = indices // 3
                c1, c2 = indices % 3
                fc2[v1, v2, c1, c2] = fc
        else:  # This case would not happen.
            fc2 = np.zeros((natom, natom, 3, 3), dtype='double', order='C')
            for fc, indices in zip(*alm.get_fc(1, mode='origin')):
                v1, v2 = indices // 3
                c1, c2 = indices % 3
                fc2[v1, v2, c1, c2] = fc
            N = natom // primitive.get_number_of_atoms()
            rotations = np.array([
                np.eye(3, dtype='intc'),
            ] * N,
                                 dtype='intc',
                                 order='C')
            distribute_force_constants(fc2,
                                       p2s_map,
                                       lattice,
                                       rotations,
                                       primitive.atomic_permutations,
                                       atom_list=atom_list)
            fc2 = np.array(fc2[atom_list], dtype='double', order='C')

    if log_level:
        print("--------------------------------"
              " ALM FC2 end "
              "-------------------------------")

    return fc2