Source code for core.pre_process

import numpy as np
from InterPhon.util import FilePath, File
from InterPhon.util import Symmetry2D
from InterPhon import error
from InterPhon.core.unit_cell import UnitCell
from InterPhon.core.super_cell import SuperCell
from InterPhon.core.pre_check import PreArgument


[docs]class PreProcess(object): """ Pre process class to control pre-process. After pre-process is successfully done, the files of displaced supercells and a pre-process record file (**pre_process.yaml**) will be generated. The information required in pre-process is stored in the instance variables of this class. The instance variables are set by the :class:`core.PreProcess.set_user_arg`, :class:`core.PreProcess.set_unit_cell`, and :class:`core.PreProcess.set_super_cell` methods. :param user_arg: Instance of PreArgument class :type user_arg: :class:`core.PreArgument` :param unit_cell: Instance of UnitCell class :type unit_cell: :class:`core.UnitCell` :param super_cell: Instance of SuperCell class :type super_cell: :class:`core.SuperCell` """ def __init__(self, user_arg=PreArgument(), unit_cell=UnitCell(), super_cell=SuperCell()): """ Constructor of PreProcess class. """ self.__user_arg = user_arg self.__unit_cell = unit_cell self.__super_cell = super_cell self.sym = Symmetry2D(self.unit_cell, self.super_cell, self.user_arg) @property def user_arg(self): return self.__user_arg @user_arg.setter def user_arg(self, _user_arg): if isinstance(_user_arg, PreArgument): self.__user_arg = _user_arg else: ValueError( "'{0}' should be the instance of <class 'InterPhon.core.pre_check.PreArgument'>".format(_user_arg)) @property def unit_cell(self): return self.__unit_cell @unit_cell.setter def unit_cell(self, _unit_cell): if isinstance(_unit_cell, UnitCell): self.__unit_cell = _unit_cell else: ValueError( "'{0}' should be the instance of <class 'InterPhon.core.unit_cell.UnitCell'>".format(_unit_cell)) @property def super_cell(self): return self.__super_cell @super_cell.setter def super_cell(self, _super_cell): if isinstance(_super_cell, SuperCell): self.__super_cell = _super_cell else: ValueError( "'{0}' should be the instance of <class 'InterPhon.core.super_cell.SuperCell'>".format(_super_cell))
[docs] def set_user_arg(self, dict_args: dict) -> None: """ Set a **PreArgument** instance from the information given by user. :param dict_args: Argument dictionary given by user :type dict_args: dict """ self.user_arg.set_user_argument(dict_args) self.user_arg.check_user_argument()
[docs] def set_unit_cell(self, in_file: FilePath, code_name: str = 'vasp') -> None: """ Set a **UnitCell** instance by reading input file of DFT programs. :param in_file: Path of DFT input file to read :type in_file: str :param code_name: Indicate a DFT program corresponding to the input file, defaults to vasp :type code_name: str """ self.unit_cell.read_unit_cell(in_file, code_name=code_name)
[docs] def set_super_cell(self, out_file: FilePath, comment: str = 'Supercell', write_file: bool = True, code_name: str = 'vasp') -> File: """ Set a **SuperCell** instance from the information stored in its **UnitCell** and **UserArgument** instances. :param out_file: Name of DFT input file to write :type out_file: str :param comment: Comment to be written in the DFT input file, defaults to Supercell :type comment: str :param write_file: Write (`True`) or not (`False`) the DFT input file from the information stored in its SuperCell instance, defaults to `True` :type write_file: bool :param code_name: Specification of the file-format by a DFT program, defaults to vasp :type code_name: str """ self.super_cell.set_super_cell(self.unit_cell, self.user_arg) self.super_cell.set_super_ind_true(self.unit_cell, self.user_arg) if write_file is True: self.super_cell.write_unit_cell(out_file, comment=comment, code_name=code_name)
[docs] def write_displace_cell(self, out_file: FilePath, code_name: str = 'vasp', sym_flag: bool = True) -> File: """ Write displaced supercell files in a format of DFT input file. :param out_file: Name of DFT input file to write :type out_file: str :param code_name: Specification of the file-format by a DFT program, defaults to vasp :type code_name: str :param sym_flag: Specify whether to use symmetry operation, defaults to `True` :type sym_flag: bool """ _dis_super_cell = self.super_cell _dis_super_cell.selective = False _current_position = self.super_cell.atom_cart.copy() _enlarge = 1 for ind, value in enumerate(self.user_arg.periodicity): if value: _enlarge = _enlarge * self.user_arg.enlargement[ind] _ind_pbc = self.user_arg.periodicity.nonzero()[0] if sym_flag: if _ind_pbc.shape[0] != 2: print('Caution:') print('Current version supports symmetry functionality only for 2D periodic systems.') print('"symmetry usage" is changed from "{0}" to "False".'.format(sym_flag)) sym_flag = False try: if sym_flag: self.sym = Symmetry2D(self.unit_cell, self.super_cell, self.user_arg) _, _, _ = self.sym.search_point_group() except error.Cannot_Search_Point_Group as e: print("look-up table: ", e.value) print(e) sym_flag = False if sym_flag: _, _, _, _ = self.sym.search_image_atom() self.sym.search_self_image_atom() self.sym.search_independent_displacement() self.sym.gen_additional_displacement() k = 0 for i, ind_T in enumerate(self.sym.require_atom): _dis_super_cell.atom_cart = _current_position.copy() _displace = [self.sym.independent_by_single_displacement_cart[i][0]] _additional_displace = self.sym.independent_additional_displacement_cart[i] if _additional_displace: _displace.extend(_additional_displace) for j, displace in enumerate(_displace): # Forward Displacement _dis_super_cell.atom_cart[_enlarge * self.unit_cell.atom_true[ind_T], 0:3] = \ _current_position[_enlarge * self.unit_cell.atom_true[ind_T], 0:3] + self.user_arg.displacement * displace _dis_super_cell.write_unit_cell(out_file + '-{0:0>4}'.format(2 * k + 1), comment='Forward Displacement', code_name=code_name) # Backward Displacement _dis_super_cell.atom_cart[_enlarge * self.unit_cell.atom_true[ind_T], 0:3] = \ _current_position[_enlarge * self.unit_cell.atom_true[ind_T], 0:3] - self.user_arg.displacement * displace _dis_super_cell.write_unit_cell(out_file + '-{0:0>4}'.format(2 * k + 2), comment='Backward Displacement', code_name=code_name) k += 1 else: for i, ind_T in enumerate(self.unit_cell.atom_true): _dis_super_cell.atom_cart = _current_position.copy() for j, displace in enumerate(np.eye(3, dtype=float)): # Forward Displacement _dis_super_cell.atom_cart[_enlarge * ind_T, 0:3] = \ _current_position[_enlarge * ind_T, 0:3] + self.user_arg.displacement * displace _dis_super_cell.write_unit_cell(out_file + '-{0:0>4}'.format(6 * i + 2 * j + 1), comment='Forward Displacement', code_name=code_name) # Backward Displacement _dis_super_cell.atom_cart[_enlarge * ind_T, 0:3] = \ _current_position[_enlarge * ind_T, 0:3] - self.user_arg.displacement * displace _dis_super_cell.write_unit_cell(out_file + '-{0:0>4}'.format(6 * i + 2 * j + 2), comment='Backward Displacement', code_name=code_name)
def __deepcopy__(self, memodict: dict = {}) -> object: import copy cls = self.__class__ result = cls.__new__(cls) memodict[id(self)] = result for key, value in self.__dict__.items(): setattr(result, key, copy.deepcopy(value, memodict)) return result