def gen_mol_sp(self, pmgmol, charge, wdir): config = load_yaml_config('lateng_hse_d3bj_sp') boxs = boxstructure(pmgmol) boxs._charge = charge vasp_set = DictSet(boxs, config, use_structure_charge=True, user_kpoints_settings=onekpoints) vasp_set.write_input(wdir)
def slabs_to_file(list_of_slabs, structure, make_fols, make_input_files, config_dict, fmt, name, **save_slabs_kwargs): """ Saves the slabs to file, optionally creates input files. The function can take any relevant keyword argument for DictSet. Args: list_of_slabs (`list`): a list of slab dictionaries made with either of surfaxe.generation get_slab functions structure (`str`): Filename of bulk structure file in any format supported by pymatgen. make_fols (`bool`): Makes folders for each termination and slab/vacuum thickness combinations containing structure files. * ``True``: A Miller index folder is created, in which folders named slab_vac_index are created to which the relevant structure files are saved. E.g. for a (0,0,1) slab of index 1 with a slab thickness of 20 Å and vacuum thickness of 30 Å the folder structure would be: ``001/20_30_1/POSCAR`` * ``False``: The indexed structure files are put in a folder named after the bulk formula. E.g. for a (0,0,1) MgO slab of index 1 with a slab thickness of 20 Å and vacuum thickness of 30 Å the folder structure would be: ``MgO/POSCAR_001_20_30_1.vasp`` make_input_files (`bool`): Makes INCAR, POTCAR and KPOINTS files in each folder. If ``make_input_files`` is ``True`` but ``make_files`` or ``save_slabs`` is ``False``, files will be saved to folders regardless. This only works with VASP input files, other formats are not yet supported. Defaults to ``False``. config_dict (`dict` or `str`): Specifies the dictionary used for the generation of the input files. fmt (`str`, optional): The format of the output files. Options include 'cif', 'poscar', 'cssr', 'json', not case sensitive. Defaults to 'poscar'. name (`str`, optional): The name of the surface slab structure file created. Case sensitive. Defaults to 'POSCAR' Returns: None, saves surface slabs to file """ bulk_name = structure.composition.reduced_formula if make_fols or make_input_files: for slab in list_of_slabs: os.makedirs(os.path.join( os.getcwd(), r'{}/{}/{}_{}_{}'.format(bulk_name, slab['hkl'], slab['slab_thickness'], slab['vac_thickness'], slab['slab_index'])), exist_ok=True) # Makes all input files (KPOINTS, POTCAR, INCAR) based on the config # dictionary if make_input_files: # soft check if potcar directory is set potcars = _check_psp_dir() if potcars: cd = _load_config_dict(config_dict) vis = DictSet(slab['slab'], cd, **save_slabs_kwargs) vis.write_input(r'{}/{}/{}_{}_{}'.format( bulk_name, slab['hkl'], slab['slab_thickness'], slab['vac_thickness'], slab['slab_index'])) # only make the folders with structure files in them else: slab['slab'].to(fmt=fmt, filename=r'{}/{}/{}_{}_{}/{}'.format( bulk_name, slab['hkl'], slab['slab_thickness'], slab['vac_thickness'], slab['slab_index'], name)) warnings.formatwarning = _custom_formatwarning warnings.warn( 'POTCAR directory not set up in pymatgen, only ' 'POSCARs were generated ') # Just makes the folders with structure files in them else: slab['slab'].to(fmt=fmt, filename=r'{}/{}/{}_{}_{}/{}'.format( bulk_name, slab['hkl'], slab['slab_thickness'], slab['vac_thickness'], slab['slab_index'], name)) # Makes name_hkl_slab_vac_index files in the bulk_name folder else: suffix = 'vasp' if fmt.lower() != 'poscar': suffix = fmt.lower() os.makedirs(os.path.join(os.getcwd(), r'{}'.format(bulk_name)), exist_ok=True) for slab in list_of_slabs: slab['slab'].to(fmt=fmt, filename=r'{}/{}_{}_{}_{}_{}.{}'.format( bulk_name, name, slab['hkl'], slab['slab_thickness'], slab['vac_thickness'], slab['slab_index'], suffix))
def get_all_slabs(structure=None, max_index=None, thicknesses=None, vacuums=None, make_fols=False, make_input_files=False, max_size=500, ox_states=None, is_symmetric=True, lll_reduce=True, center_slab=True, config_dict=PBEsol_slab_config, potcar_functional='PBE', update_incar=None, update_potcar=None, update_kpoints=None, **kwargs): """ Generates all unique slabs with specified maximum Miller index, minimum slab and vacuum thicknesses. It includes all combinations for multiple zero dipole symmetric terminations for the same Miller index. Note that using this method of slab generation will results in different slab index numbers as in the `get_one_hkl_slabs` - the slabs identified are the same, the index varies based on the position in the list of generated slabs. Args: structure: filename of structure file, takes all pymatgen-supported formats. max_index (int): maximum Miller index to be considered thicknesses (list): minimum size of the slab in angstroms. vacuums (list): minimum size of the vacuum in angstroms. make_fols (bool): makes folders containing POSCARs; default=False make_input_files (bool): makes INCAR, POTCAR and KPOINTS files in each of the folders; if True but make_fols is False it will make the folders regardless; default=False. max_size (int): the maximum number of atoms in the slab for the size warning; default=500. ox_states (list or dict): add oxidation states either by sites i.e. [3, 2, 2, 1, -2, -2, -2, -2] or by element i.e. {'Fe': 3, 'O':-2}; default=None which adds oxidation states by guess is_symmetric (bool): whether or not the slabs cleaved should have inversion symmetry. Needs to be False for slabs cleaved from a non-centrosymmetric bulk; default=True lll_reduce (bool): whether or not the slabs will be orthogonalized; default=True. center_slab (bool): position of the slab in the unit cell, if True the slab is centered with equal amounts of vacuum above and below; default=True config_dict (dict): specifies the dictionary used for generation of input files; default=PBEsol_slab_config potcar_functional (str): The functional used for POTCAR generation; default='PBE' update_incar (dict): overrides default INCAR settings; default=None update_kpoints (dict or kpoints object): overrides default kpoints settings, if supplied as dict should be as {'reciprocal_density': 100}; default=None update_potcar (dict): overrides default POTCAR settings; default=None Returns: POSCAR_hkl_slab_vac_index.vasp or hkl/slab_vac_index folders with POSCARs or hkl/slab_vac_index with all input files """ # Check all neccessary input parameters are present if not any([structure, max_index, thicknesses, vacuums]): raise ValueError('One or more of the required arguments (structure, ' 'max_index, thicknesses, vacuums) were not supplied.') # Import bulk relaxed structure, add oxidation states for slab dipole # calculations struc = Structure.from_file(structure) bulk_name = struc.formula.replace(" ", "") struc = oxidation_states(struc, ox_states=ox_states) # Iterate through vacuums and thicknessses provisional = [] for vacuum in vacuums: for thickness in thicknesses: all_slabs = generate_all_slabs(struc, max_index=max_index, min_slab_size=thickness, min_vacuum_size=vacuum, lll_reduce=lll_reduce, center_slab=center_slab, **kwargs) for i, slab in enumerate(all_slabs): # Get all the zero-dipole slabs with inversion symmetry if is_symmetric: if (slab.is_polar() == False) and (slab.is_symmetric() == True): provisional.append({ 'hkl': ''.join(map(str, slab.miller_index)), 'slab_t': thickness, 'vac_t': vacuum, 's_index': i, 'slab': slab }) # Get all the zero-dipole slabs wihtout inversion symmetry else: if not slab.is_polar(): provisional.append({ 'hkl': ''.join(map(str, slab.miller_index)), 'slab_t': thickness, 'vac_t': vacuum, 's_index': i, 'slab': slab }) # Iterate though provisional slabs to extract the unique slabs unique_list, unique_list_of_dicts, repeat, large = ([] for i in range(4)) for slab in provisional: if slab['slab'] not in unique_list: unique_list.append(slab['slab']) unique_list_of_dicts.append(slab) # For large slab size warning atoms = len(slab['slab'].atomic_numbers) if atoms > max_size: large.append('{}_{}_{}_{}'.format(slab['hkl'], slab['slab_t'], slab['vac_t'], slab['s_index'])) # For repeat slabs warning else: repeat.append('{}_{}_{}_{}'.format(slab['hkl'], slab['slab_t'], slab['vac_t'], slab['s_index'])) # Warnings for large and repeated slabs if repeat: warnings.formatwarning = custom_formatwarning warnings.warn( 'Not all combinations of hkl or slab/vac thicknesses ' 'were generated because of repeat structures. ' 'The repeat slabs are: ' + ', '.join(map(str, repeat))) if large: warnings.formatwarning = custom_formatwarning warnings.warn('Some generated slabs exceed the max size specified.' ' Slabs that exceed the max size are: ' + ', '.join(map(str, large))) # Makes folders hkl/slab_vac_index, if only make_input_files is true the # folders will also be made automatically. if make_fols or make_input_files: for slab in unique_list_of_dicts: os.makedirs(os.path.join( os.getcwd(), r'{}/{}_{}_{}'.format(slab['hkl'], slab['slab_t'], slab['vac_t'], slab['s_index'])), exist_ok=True) # Makes all VASP input files (KPOINTS, POTCAR, INCAR) based on the # config dictionary if make_input_files: vis = DictSet(structure=slab['slab'], config_dict=config_dict, potcar_functional=potcar_functional, user_incar_settings=update_incar, user_potcar_settings=update_potcar, user_kpoints_settings=update_kpoints, **kwargs) vis.write_input( os.path.join( os.getcwd(), r'{}/{}_{}_{}'.format(slab['hkl'], slab['slab_t'], slab['vac_t'], slab['s_index']))) # Makes the folders with POSCARs else: slab['slab'].to(fmt='poscar', filename=r'{}/{}_{}_{}/POSCAR'.format( slab['hkl'], slab['slab_t'], slab['vac_t'], slab['s_index'])) # Omits folders, makes POSCAR_hkl_slab_vac_index files in folder bulk_name else: os.makedirs(os.path.join(os.getcwd(), r'{}'.format(bulk_name)), exist_ok=True) for slab in unique_list_of_dicts: slab['slab'].to(fmt='poscar', filename='{}/POSCAR_{}_{}_{}_{}.vasp'.format( bulk_name, slab['hkl'], slab['slab_t'], slab['vac_t'], slab['s_index']))
def gen_pbc_sp(self, wdir, nelect): config = load_yaml_config('lateng_hse_d3bj_sp') config['INCAR']['NELECT'] = nelect vasp_set = DictSet(self.structure, config) vasp_set.write_input(wdir)