Пример #1
0
 def set_permutation_symmetry(self):
     if self._fc2 is not None:
         set_permutation_symmetry(self._fc2)
     if self._fc3 is not None:
         set_permutation_symmetry_fc3(self._fc3)
Пример #2
0
def _get_constrained_fc3(supercell, displacements, reduced_site_sym,
                         translational_symmetry_type, is_permutation_symmetry,
                         symprec, verbose):
    """
    Two displacements and force constants calculation (e.g. DFPT)

        displacements = {'number': 3,
                         'displacement': [0.01, 0.00, 0.01]
                         'second_atoms': [{'number': 7,
                                           'displacement': [],
                                           'delta_fc2': }]}

    Three displacements and force calculation

        displacements = {'number': 3,
                         'displacement': [0.01, 0.00, 0.01]
                         'second_atoms': [{'number': 7,
                                           'displacement': [],
                                           'third_atoms': ... }]}
           third_atoms is like:
                         'third_atoms': [{'number': 56,
                                          'displacement': [],
                                          'delta_forces': ... }]}
    """
    num_atom = supercell.get_number_of_atoms()
    atom1 = displacements['number']
    disp1 = displacements['displacement']
    delta_fc3 = np.zeros((num_atom, num_atom, num_atom, 3, 3, 3),
                         dtype='double')

    if 'delta_forces' in displacements['second_atoms'][0]:
        fc2_with_one_disp = get_constrained_fc2(
            supercell, displacements['second_atoms'], atom1, reduced_site_sym,
            translational_symmetry_type, is_permutation_symmetry, symprec)

    atom_list = np.unique([x['number'] for x in displacements['second_atoms']])
    for atom2 in atom_list:
        bond_sym = get_bond_symmetry(reduced_site_sym,
                                     supercell.get_scaled_positions(), atom1,
                                     atom2, symprec)
        disps2 = []
        delta_fc2s = []
        for disps_second in displacements['second_atoms']:
            if atom2 != disps_second['number']:
                continue
            disps2.append(disps_second['displacement'])

            if 'delta_fc2' in disps_second:
                delta_fc2s.append(disps_second['delta_fc2'])
            else:
                direction = np.dot(disps_second['displacement'],
                                   np.linalg.inv(supercell.get_cell()))
                reduced_bond_sym = get_reduced_site_symmetry(
                    bond_sym, direction, symprec)

                delta_fc2s.append(
                    get_delta_fc2(disps_second['third_atoms'], atom2,
                                  fc2_with_one_disp, supercell,
                                  reduced_bond_sym,
                                  translational_symmetry_type,
                                  is_permutation_symmetry, symprec))

            if verbose > 1:
                print("Second displacements for fc4[ %d, %d, x, x ]" %
                      (atom1 + 1, atom2 + 1))
                for i, v in enumerate(disps2):
                    print "  [%7.4f %7.4f %7.4f]" % tuple(v)

        solve_fc3(delta_fc3,
                  atom2,
                  supercell,
                  bond_sym,
                  disps2,
                  delta_fc2s,
                  symprec=symprec,
                  verbose=False)

    # 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

    if verbose:
        print "Expanding delta fc3"

    distribute_fc3(delta_fc3,
                   atom_list,
                   lattice,
                   positions,
                   np.array(reduced_site_sym, dtype='intc', order='C'),
                   np.zeros((len(reduced_site_sym), 3), dtype='double'),
                   symprec,
                   verbose=verbose)

    if translational_symmetry_type > 0:
        set_translational_invariance_fc3_per_index(delta_fc3)

    if is_permutation_symmetry:
        set_permutation_symmetry_fc3(delta_fc3)

    return delta_fc3
Пример #3
0
 def set_permutation_symmetry(self):
     if self._fc2 is not None:
         set_permutation_symmetry(self._fc2)
     if self._fc3 is not None:
         set_permutation_symmetry_fc3(self._fc3)
Пример #4
0
def _get_constrained_fc3(supercell,
                         displacements,
                         reduced_site_sym,
                         is_translational_symmetry,
                         is_permutation_symmetry,
                         symprec,
                         verbose):
    """
    Two displacements and force constants calculation (e.g. DFPT)

        displacements = {'number': 3,
                         'displacement': [0.01, 0.00, 0.01]
                         'second_atoms': [{'number': 7,
                                           'displacement': [],
                                           'delta_fc2': }]}

    Three displacements and force calculation

        displacements = {'number': 3,
                         'displacement': [0.01, 0.00, 0.01]
                         'second_atoms': [{'number': 7,
                                           'displacement': [],
                                           'third_atoms': ... }]}
           third_atoms is like:
                         'third_atoms': [{'number': 56,
                                          'displacement': [],
                                          'delta_forces': ... }]}
    """
    num_atom = supercell.get_number_of_atoms()
    atom1 = displacements['number']
    disp1 = displacements['displacement']
    fc3 = np.zeros((num_atom, num_atom, num_atom, 3, 3, 3), dtype='double')
    atom_list_done = []

    if 'delta_forces' in displacements['second_atoms'][0]:
        fc2_with_one_disp = get_constrained_fc2(supercell,
                                                displacements['second_atoms'],
                                                atom1,
                                                reduced_site_sym,
                                                is_translational_symmetry,
                                                is_permutation_symmetry,
                                                symprec)
    
    atom_list = np.unique([x['number'] for x in displacements['second_atoms']])
    for atom2 in atom_list:
        disps2 = []
        delta_fc2s = []
        for disps_second in displacements['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'])

            if 'delta_fc2' in disps_second:
                delta_fc2s.append(disps_second['delta_fc2'])
            else:
                direction = np.dot(disps_second['displacement'],
                                   np.linalg.inv(supercell.get_cell()))
                reduced_bond_sym = get_reduced_site_symmetry(
                    bond_sym, direction, symprec)

                delta_fc2s.append(get_delta_fc2(
                        disps_second['third_atoms'],
                        atom2,
                        fc2_with_one_disp,
                        supercell,
                        reduced_bond_sym,
                        is_translational_symmetry,
                        is_permutation_symmetry,
                        symprec))
    
            if verbose > 1:
                print ("Second displacements for fc4[ %d, %d, x, x ]" %
                       (atom1 + 1, atom2 + 1))
                for i, v in enumerate(disps2):
                    print "  [%7.4f %7.4f %7.4f]" % tuple(v)

            solve_fc3(fc3,
                      atom2,
                      supercell,
                      bond_sym,
                      disps2,
                      delta_fc2s,
                      symprec=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

    if verbose:
        print "(Copying delta fc3...)"
    distribute_fc3(fc3,
                   atom_list_done,
                   lattice,
                   positions,
                   np.intc(reduced_site_sym).copy(),
                   np.zeros((len(reduced_site_sym), 3), dtype='double'),
                   symprec,
                   verbose)

    if is_translational_symmetry:
        set_translational_invariance_fc3_per_index(fc3)

    if is_permutation_symmetry:
        set_permutation_symmetry_fc3(fc3)

    return fc3