def _generate_inputdata(self, parameters: orm.Dict, pseudos, structure: orm.StructureData, kpoints: orm.KpointsData) -> ty.Tuple[str, list]: """Generate the input file content and list of pseudopotential files to copy. :param parameters: input parameters Dict :param pseudos: pseudopotential input namespace :param structure: input structure :param kpoints: input kpoints :returns: input file content, pseudopotential copy list """ local_copy_pseudo_list = [] # abipy has its own subclass of Pymatgen's `Structure`, so we use that pmg_structure = structure.get_pymatgen() abi_structure = AbiStructure.as_structure(pmg_structure) abi_structure = abi_structure.abi_sanitize(primitive=True) for kind in structure.get_kind_names(): pseudo = pseudos[kind] local_copy_pseudo_list.append((pseudo.uuid, pseudo.filename, f'{self._PSEUDO_SUBFOLDER}{pseudo.filename}')) # Pseudopotentials _must_ be listed in the same order as 'znucl' in the input file. # So, we need to get 'znucl' as abipy will write it then construct the appropriate 'pseudos' string. znucl = structure_to_abivars(abi_structure)['znucl'] ordered_pseudo_filenames = [pseudos[constants.elements[Z]['symbol']].filename for Z in znucl] pseudo_parameters = { 'pseudos': '"' + ', '.join(ordered_pseudo_filenames) + '"', 'pp_dirpath': f'"{self._PSEUDO_SUBFOLDER}"' } input_parameters = parameters.get_dict() # k-points are provided to abipy separately from the main input parameters, so we pop out # parameters related to the k-points shiftk = input_parameters.pop('shiftk', [0.0, 0.0, 0.0]) # NOTE: currently, only k-point mesh are supported, not k-point paths kpoints_mesh = kpoints.get_kpoints_mesh()[0] # use abipy to write the input file input_parameters = {**input_parameters, **pseudo_parameters} # give abipy the HGH_TABLE only so it won't error, but don't actually print these to file abi_input = AbinitInput( structure=abi_structure, pseudos=HGH_TABLE, abi_kwargs=input_parameters ) abi_input.set_kmesh( ngkpt=kpoints_mesh, shiftk=shiftk ) return abi_input.to_string(with_pseudos=False), local_copy_pseudo_list
def prepare_for_submission(self, folder): """ Create input files. :param folder: an `aiida.common.folders.Folder` where the plugin should temporarily place all files needed by the calculation. :return: `aiida.common.datastructures.CalcInfo` instance """ ### SETUP ### local_copy_list = [] ### INPUT CHECK ### # PSEUDOS for kind in self.inputs.structure.get_kind_names(): if kind not in self.inputs.pseudos: raise ValueError(f'no pseudo available for element {kind}') elif not isinstance(self.inputs.pseudos[kind], (Psp8Data, JthXmlData)): raise ValueError(f'pseudo for element {kind} is not of type Psp8Data or JthXmlData') # KPOINTS if 'ngkpt' in self.inputs.parameters.keys(): raise ValueError('`ngkpt` should not be specified in input parameters') if 'kptopt' in self.inputs.parameters.keys(): raise ValueError('`kptopt` should not be specified in input parameters') ### PREPARATION ### # PSEUDOS folder.get_subfolder(self._DEFAULT_PSEUDO_SUBFOLDER, create=True) for kind in self.inputs.structure.get_kind_names(): psp = self.inputs.pseudos[kind] local_copy_list.append((psp.uuid, psp.filename, self._DEFAULT_PSEUDO_SUBFOLDER + kind + '.psp8')) # KPOINTS kpoints_mesh = self.inputs.kpoints.get_kpoints_mesh()[0] ### INPUTS ### input_parameters = self.inputs.parameters.get_dict() shiftk = input_parameters.pop('shiftk', [0.0, 0.0, 0.0]) # TODO: There must be a better way to do this # maybe we can convert the PseudoPotential objects into pymatgen Pseudo objects? znucl = structure_to_abivars(self.inputs.structure.get_pymatgen())['znucl'] pseudo_parameters = { 'pseudos': '"' + ', '.join([Element.from_Z(Z).symbol + '.psp8' for Z in znucl]) + '"', 'pp_dirpath': '"' + self._DEFAULT_PSEUDO_SUBFOLDER + '"' } input_parameters = {**input_parameters, **pseudo_parameters} abin = AbinitInput( structure=self.inputs.structure.get_pymatgen(), pseudos=HGH_TABLE, abi_kwargs=input_parameters ) abin.set_kmesh( ngkpt=kpoints_mesh, shiftk=shiftk ) with io.open(folder.get_abs_path(self._DEFAULT_INPUT_FILE), mode='w', encoding='utf-8') as f: f.write(abin.to_string(with_pseudos=False)) ### CODE ### codeinfo = datastructures.CodeInfo() codeinfo.code_uuid = self.inputs.code.uuid codeinfo.cmdline_params = [self.options.input_filename] codeinfo.stdout_name = self.metadata.options.output_filename codeinfo.withmpi = self.inputs.metadata.options.withmpi ### CALC INFO ### calcinfo = datastructures.CalcInfo() calcinfo.codes_info = [codeinfo] calcinfo.stdin_name = self.options.input_filename calcinfo.stdout_name = self.options.output_filename calcinfo.retrieve_list = [self.metadata.options.output_filename] calcinfo.retrieve_list = [self._DEFAULT_OUTPUT_FILE, self._DEFAULT_GSR_FILE_NAME, self._DEFAULT_TRAJECT_FILE_NAME] calcinfo.remote_symlink_list = [] calcinfo.remote_copy_list = [] calcinfo.local_copy_list = local_copy_list if 'parent_calc_folder' in self.inputs: comp_uuid = self.inputs.parent_calc_folder.computer.uuid remote_path = self.inputs.parent_calc_folder.get_remote_path() copy_info = (comp_uuid, remote_path, self._DEFAULT_PARENT_CALC_FLDR_NAME) # If running on the same computer - make a symlink. if self.inputs.code.computer.uuid == comp_uuid: calcinfo.remote_symlink_list.append(copy_info) # If not - copy the folder. else: calcinfo.remote_copy_list.append(copy_info) return calcinfo