def prepare_for_submission(self, folder: Folder) -> CalcInfo: """Prepare the calculation for submission. :param folder: a temporary folder on the local file system. :returns: the `CalcInfo` instance """ echo_value = "fail" if self.node.get_option( "fail_calcjob") else "success" with folder.open(self.options.input_filename, "w", encoding="utf8") as handle: handle.write(f"sleep {self.inputs.time.value}\n") handle.write(f'echo "{echo_value}"\n') with folder.open(self.options.payload_filename, "wb") as handle: json.dump(self.inputs.payload.get_dict(), handle) codeinfo = CodeInfo() codeinfo.code_uuid = self.inputs.code.uuid codeinfo.stdin_name = self.options.input_filename codeinfo.stdout_name = self.options.output_filename calcinfo = CalcInfo() calcinfo.codes_info = [codeinfo] calcinfo.retrieve_list = [ self.options.output_filename, self.options.payload_filename, ] return calcinfo
def test_upload_local_copy_list(fixture_sandbox, aiida_localhost, aiida_local_code_factory): """Test the ``local_copy_list`` functionality in ``upload_calculation``. Specifically, verify that files in the ``local_copy_list`` do not end up in the repository of the node. """ from aiida.common.datastructures import CalcInfo, CodeInfo from aiida.orm import CalcJobNode, SinglefileData inputs = { 'file_a': SinglefileData(io.BytesIO(b'content_a')).store(), 'file_b': SinglefileData(io.BytesIO(b'content_b')).store(), } node = CalcJobNode(computer=aiida_localhost) node.store() code = aiida_local_code_factory('arithmetic.add', '/bin/bash').store() code_info = CodeInfo() code_info.code_uuid = code.uuid calc_info = CalcInfo() calc_info.uuid = node.uuid calc_info.codes_info = [code_info] calc_info.local_copy_list = [ (inputs['file_a'].uuid, inputs['file_a'].filename, './files/file_a'), (inputs['file_a'].uuid, inputs['file_a'].filename, './files/file_b'), ] with LocalTransport() as transport: execmanager.upload_calculation(node, transport, calc_info, fixture_sandbox) assert node.list_object_names() == []
def prepare_for_submission(self, folder: Folder) -> CalcInfo: """Prepare the calculation for submission. Convert the input nodes into the corresponding input files in the format that the code will expect. In addition, define and return a `CalcInfo` instance, which is a simple data structure that contains information for the engine, for example, on what files to copy to the remote machine, what files to retrieve once it has completed, specific scheduler settings and more. :param folder: a temporary folder on the local file system. :returns: the `CalcInfo` instance """ with folder.open(self.options.input_filename, 'w', encoding='utf8') as handle: handle.write('echo $(({x} + {y}))\n'.format(x=self.inputs.x.value, y=self.inputs.y.value)) codeinfo = CodeInfo() codeinfo.code_uuid = self.inputs.code.uuid codeinfo.stdin_name = self.options.input_filename codeinfo.stdout_name = self.options.output_filename calcinfo = CalcInfo() calcinfo.codes_info = [codeinfo] calcinfo.retrieve_list = [self.options.output_filename] return calcinfo
def _prepare_for_submission(self, tempfolder, inputdict): """ Writes the four minimum output files, INCAR, POSCAR, POTCAR, KPOINTS. Delegates the construction and writing / copying to write_<file> methods. That way, subclasses can use any form of input nodes and just have to implement the write_xxx method accordingly. Subclasses can extend by calling the super method and if neccessary modifying it's output CalcInfo before returning it. """ # write input files incar = tempfolder.get_abs_path('INCAR') structure = tempfolder.get_abs_path('POSCAR') potentials = tempfolder.get_abs_path('POTCAR') kpoints = tempfolder.get_abs_path('KPOINTS') self.verify_inputs(inputdict) self.write_incar(inputdict, incar) self.write_poscar(inputdict, structure) self.write_potcar(inputdict, potentials) self.write_kpoints(inputdict, kpoints) self.write_additional(tempfolder, inputdict) # calcinfo calcinfo = CalcInfo() calcinfo.uuid = self.uuid calcinfo.retrieve_list = self.max_retrieve_list() codeinfo = CodeInfo() codeinfo.code_uuid = self.get_code().uuid codeinfo.code_pk = self.get_code().pk calcinfo.codes_info = [codeinfo] return calcinfo
def prepare_for_submission(self, folder): source_nodes = self.inputs.source_nodes instructions = self.inputs.instructions.get_dict() local_files = instructions.get('local_files', []) remote_files = instructions.get('remote_files', []) symlink_files = instructions.get('symlink_files', []) retrieve_files = instructions.get('retrieve_files') calc_info = CalcInfo() calc_info.skip_submit = True calc_info.codes_info = [] calc_info.local_copy_list = [] calc_info.remote_copy_list = [] calc_info.remote_symlink_list = [] retrieve_paths = [] for source_label, source_relpath, target_relpath in local_files: source_node = source_nodes[source_label] retrieve_paths.append(target_relpath) calc_info.local_copy_list.append(( source_node.uuid, source_relpath, target_relpath, )) for source_label, source_relpath, target_relpath in remote_files: source_node = source_nodes[source_label] retrieve_paths.append(target_relpath) calc_info.remote_copy_list.append(( source_node.computer.uuid, os.path.join(source_node.get_remote_path(), source_relpath), target_relpath, )) for source_label, source_relpath, target_relpath in symlink_files: source_node = source_nodes[source_label] retrieve_paths.append(target_relpath) calc_info.remote_symlink_list.append(( source_node.computer.uuid, os.path.join(source_node.get_remote_path(), source_relpath), target_relpath, )) if retrieve_files: calc_info.retrieve_list = retrieve_paths else: calc_info.retrieve_list = [] return calc_info
def prepare_for_submission(self, folder): from aiida.common.datastructures import CalcInfo, CodeInfo local_copy_list = [(self.inputs.single_file.uuid, self.inputs.single_file.filename, 'single_file')] for name, node in self.inputs.files.items(): local_copy_list.append((node.uuid, node.filename, name)) codeinfo = CodeInfo() codeinfo.code_uuid = self.inputs.code.uuid calcinfo = CalcInfo() calcinfo.codes_info = [codeinfo] calcinfo.local_copy_list = local_copy_list return calcinfo
def prepare_for_submission(self, folder): from aiida.common.datastructures import CalcInfo, CodeInfo # Use nested path for the target filename, where the directory does not exist, to check that the engine will # create intermediate directories as needed. Regression test for #4350 local_copy_list = [(self.inputs.single_file.uuid, self.inputs.single_file.filename, 'path/single_file')] for name, node in self.inputs.files.items(): local_copy_list.append((node.uuid, node.filename, name)) codeinfo = CodeInfo() codeinfo.code_uuid = self.inputs.code.uuid calcinfo = CalcInfo() calcinfo.codes_info = [codeinfo] calcinfo.local_copy_list = local_copy_list return calcinfo
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 """ # Prepare CalcInfo to be returned to aiida calcinfo = CalcInfo() calcinfo.uuid = self.uuid calcinfo.local_copy_list = [ (self.inputs.file1.uuid, self.inputs.file1.filename, self.inputs.file1.filename), (self.inputs.file2.uuid, self.inputs.file2.filename, self.inputs.file2.filename), ] calcinfo.remote_copy_list = [] calcinfo.retrieve_list = [self._OUTPUT_FILE_NAME] codeinfo = CodeInfo() codeinfo.cmdline_params = self.inputs.parameters.cmdline_params( file1_name=self.inputs.file1.filename, file2_name=self.inputs.file2.filename) codeinfo.code_uuid = self.inputs.code.uuid codeinfo.withmpi = False codeinfo.stdout_name = self._OUTPUT_FILE_NAME calcinfo.codes_info = [codeinfo] return calcinfo
def _prepare_for_submission(self, tempfolder, inputdict): """ Create input files. :param tempfolder: aiida.common.folders.Folder subclass where the plugin should put all its files. :param inputdict: dictionary of the input nodes as they would be returned by get_inputs_dict """ parameters, code, structure, surface_sample = \ self._validate_inputs(inputdict) # Prepare CalcInfo to be returned to aiida calcinfo = CalcInfo() calcinfo.uuid = self.uuid calcinfo.local_copy_list = [ [structure.get_file_abs_path(), structure.filename], [surface_sample.get_file_abs_path(), surface_sample.filename], ] calcinfo.remote_copy_list = [] calcinfo.retrieve_list = parameters.output_files codeinfo = CodeInfo() # will call ./code.py in.json out.json codeinfo.cmdline_params = parameters.cmdline_params( structure_file_name=structure.filename, surface_sample_file_name=surface_sample.filename) codeinfo.code_uuid = code.uuid calcinfo.codes_info = [codeinfo] return calcinfo
def _prepare_for_submission(self, tempfolder, inputdict): from aiida.orm.calculation.job.codtools import commandline_params_from_dict import shutil try: cif = inputdict.pop(self.get_linkname('cif')) except KeyError: raise InputValidationError( "no CIF file is specified for this calculation") if not isinstance(cif, CifData): raise InputValidationError("cif is not of type CifData") parameters = inputdict.pop(self.get_linkname('parameters'), None) if parameters is None: parameters = ParameterData(dict={}) if not isinstance(parameters, ParameterData): raise InputValidationError( "parameters is not of type ParameterData") code = inputdict.pop(self.get_linkname('code'), None) if code is None: raise InputValidationError("Code not found in input") self._validate_resources(**self.get_resources()) input_filename = tempfolder.get_abs_path(self._DEFAULT_INPUT_FILE) shutil.copy(cif.get_file_abs_path(), input_filename) commandline_params = self._default_commandline_params commandline_params.extend( commandline_params_from_dict(parameters.get_dict())) calcinfo = CalcInfo() calcinfo.uuid = self.uuid # The command line parameters should be generated from 'parameters' calcinfo.local_copy_list = [] calcinfo.remote_copy_list = [] calcinfo.retrieve_list = [ self._DEFAULT_OUTPUT_FILE, self._DEFAULT_ERROR_FILE ] calcinfo.retrieve_singlefile_list = [] codeinfo = CodeInfo() codeinfo.cmdline_params = commandline_params codeinfo.stdin_name = self._DEFAULT_INPUT_FILE codeinfo.stdout_name = self._DEFAULT_OUTPUT_FILE codeinfo.stderr_name = self._DEFAULT_ERROR_FILE codeinfo.code_uuid = code.uuid calcinfo.codes_info = [codeinfo] return calcinfo
def _prepare_for_submission(self, tempfolder, inputdict): ''' write input files, set retrieve_list to all files starting with wannier90''' # inputfile destinations win_dst = tempfolder.get_abs_path('wannier90.win') fpath = tempfolder.get_abs_path('') # check inputs self.verify_inputs(inputdict) # write inputs self.write_win(inputdict, win_dst) self.write_wdat(inputdict, fpath) # create and return calcinfo calcinfo = CalcInfo() calcinfo.uuid = self.uuid calcinfo.retrieve_list = [['wannier90*', '.', 0]] codeinfo = CodeInfo() codeinfo.code_uuid = self.get_code().uuid codeinfo.code_pk = self.get_code().pk codeinfo.cmdline_params = ['wannier90'] codeinfo.withmpi = False calcinfo.codes_info = [codeinfo] return calcinfo
def prepare_for_submission(self, folder): from aiida.common.datastructures import CalcInfo, CodeInfo for key, node in self.inputs.files.items(): filepath = key.replace('_', os.sep) dirname = os.path.dirname(filepath) basename = os.path.basename(filepath) with node.open(mode='rb') as source: if dirname: subfolder = folder.get_subfolder(dirname, create=True) subfolder.create_file_from_filelike(source, basename) else: folder.create_file_from_filelike(source, filepath) codeinfo = CodeInfo() codeinfo.code_uuid = self.inputs.code.uuid calcinfo = CalcInfo() calcinfo.codes_info = [codeinfo] calcinfo.provenance_exclude_list = self.inputs.settings.get_attribute('provenance_exclude_list') return calcinfo
def prepare_for_submission(self, folder): """ This method is called prior to job submission with a set of calculation input nodes. The inputs will be validated and sanitized, after which the necessary input files will be written to disk in a temporary folder. A CalcInfo instance will be returned that contains lists of files that need to be copied to the remote machine before job submission, as well as file lists that are to be retrieved after job completion. :param folder: an aiida.common.folders.Folder to temporarily write files on disk :returns: CalcInfo instance """ input_x = self.inputs.x input_y = self.inputs.y input_code = self.inputs.code self.write_input_files(folder, input_x, input_y) retrieve_list = self.get_retrieve_list() local_copy_list = self.get_local_copy_list() remote_copy_list = self.get_remote_copy_list() codeinfo = CodeInfo() codeinfo.cmdline_params = ['-in', self.options.input_filename] codeinfo.stdout_name = self.options.output_filename codeinfo.code_uuid = input_code.uuid calcinfo = CalcInfo() calcinfo.codes_info = [codeinfo] calcinfo.retrieve_list = retrieve_list calcinfo.local_copy_list = local_copy_list calcinfo.remote_copy_list = remote_copy_list return calcinfo
def create_calc_info( self, tempfolder, local_copy_list=None, remote_copy_list=None, remote_symlink_list=None, retrieve_list=None, retrieve_temporary_list=None, ): """Prepare CalcInfo object for aiida, to describe how the computation will be executed and recovered """ # Prepare CodeInfo object for aiida, # describes how a code has to be executed codeinfo = CodeInfo() codeinfo.code_uuid = self.inputs.code.uuid if self.metadata.options.withmpi: # parallel versions of crystal (Pcrystal, Pproperties & MPPcrystal) # read data specifically from a file called INPUT if self.metadata.options.input_file_name != "INPUT": tempfolder.insert_path( os.path.join(tempfolder.abspath, self.metadata.options.input_file_name), dest_name="INPUT", ) else: codeinfo.stdin_name = self.metadata.options.input_file_name codeinfo.stdout_name = self.metadata.options.stdout_file_name # serial version output to stdout, but parallel version output to stderr! # so we join the files codeinfo.join_files = True codeinfo.cmdline_params = [] codeinfo.withmpi = self.metadata.options.withmpi # Prepare CalcInfo object for aiida calcinfo = CalcInfo() calcinfo.uuid = self.uuid calcinfo.codes_info = [codeinfo] calcinfo.local_copy_list = local_copy_list or [] calcinfo.remote_copy_list = remote_copy_list or [] calcinfo.remote_symlink_list = remote_symlink_list or [] calcinfo.retrieve_list = retrieve_list or [] calcinfo.retrieve_temporary_list = retrieve_temporary_list or [] return calcinfo
def prepare_for_submission(self, folder): """Write the input files that are required for the code to run. :param folder: an `~aiida.common.folders.Folder` to temporarily write files on disk :return: `~aiida.common.datastructures.CalcInfo` instance """ input_x = self.inputs.x input_y = self.inputs.y # Write the input file based on the inputs that were passed with folder.open(self.options.input_filename, 'w', encoding='utf8') as handle: handle.write(f'{input_x.value} {input_y.value}\n') codeinfo = CodeInfo() codeinfo.code_uuid = self.inputs.code.uuid codeinfo.stdout_name = self.options.output_filename codeinfo.cmdline_params = ['-in', self.options.input_filename] calcinfo = CalcInfo() calcinfo.codes_info = [codeinfo] calcinfo.local_copy_list = [] calcinfo.remote_copy_list = [] calcinfo.retrieve_list = [] return calcinfo
def _prepare_for_submission(self, tempfolder, inputdict): """ This is the routine to be called when you want to create the input files and related stuff with a plugin. :param tempfolder: a aiida.common.folders.Folder subclass where the plugin should put all its files. :param inputdict: a dictionary with the input nodes, as they would be returned by get_inputdata_dict (without the Code!) """ code, params, parent_calc_folder, atomtypes_file = self._verify_inlinks(inputdict) # --------------------------------------------------- # Write params.ini file params_fn = tempfolder.get_abs_path("params.ini") with open(params_fn, 'w') as f: for key, val in params.items(): line = str(key) + " " if isinstance(val, list): line += " ".join(str(v) for v in val) else: line += str(val) f.write(line + '\n') # --------------------------------------------------- # create code info codeinfo = CodeInfo() codeinfo.code_uuid = code.uuid codeinfo.withmpi = False # create calc info calcinfo = CalcInfo() calcinfo.uuid = self.uuid calcinfo.codes_info = [codeinfo] # file lists calcinfo.remote_symlink_list = [] calcinfo.local_copy_list = [(atomtypes_file.get_file_abs_path(), 'atomtypes.ini')] calcinfo.remote_copy_list = [] calcinfo.retrieve_list = ["*/*/*.npy"] # symlinks if parent_calc_folder is not None: comp_uuid = parent_calc_folder.get_computer().uuid remote_path = parent_calc_folder.get_remote_path() symlink = (comp_uuid, remote_path, "parent_calc_folder") calcinfo.remote_symlink_list.append(symlink) return calcinfo
def _prepare_for_submission(self, tempfolder, inputdict): """ This is the routine to be called when you want to create the input files and related stuff with a plugin. :param tempfolder: a aiida.common.folders.Folder subclass where the plugin should put all its files. :param inputdict: a dictionary with the input nodes, as they would be returned by get_inputs_dict (with the Code!) """ try: parameters = inputdict.pop(self.get_linkname('parameters')) except KeyError: raise InputValidationError("No parameters specified for this " "calculation") if not isinstance(parameters, ParameterData): raise InputValidationError("parameters is not of type " "ParameterData") try: code = inputdict.pop(self.get_linkname('code')) except KeyError: raise InputValidationError("No code specified for this " "calculation") if inputdict: raise ValidationError("Cannot add other nodes beside parameters") ############################## # END OF INITIAL INPUT CHECK # ############################## input_json = parameters.get_dict() # write all the input to a file input_filename = tempfolder.get_abs_path(self._INPUT_FILE_NAME) with open(input_filename, 'w') as infile: json.dump(input_json, infile) # ============================ calcinfo ================================ calcinfo = CalcInfo() calcinfo.uuid = self.uuid calcinfo.local_copy_list = [] calcinfo.remote_copy_list = [] calcinfo.retrieve_list = [self._OUTPUT_FILE_NAME] codeinfo = CodeInfo() codeinfo.cmdline_params = [ self._INPUT_FILE_NAME, self._OUTPUT_FILE_NAME ] codeinfo.code_uuid = code.uuid calcinfo.codes_info = [codeinfo] return calcinfo
def _prepare_for_submission(self, tempfolder, inputdict): try: parameters = inputdict.pop(self.get_linkname('parameters')) except KeyError: raise InputValidationError( "no parameters are specified for this calculation") if not isinstance(parameters, ParameterData): raise InputValidationError( "parameters is not of type ParameterData") if 'structure' in inputdict: struct = inputdict.pop(self.get_linkname('structure')) if not isinstance(struct, StructureData): raise InputValidationError( "structure is not of type StructureData") try: code = inputdict.pop(self.get_linkname('code')) except KeyError: raise InputValidationError( "no code is specified for this calculation") input_filename = tempfolder.get_abs_path(self._DEFAULT_INPUT_FILE) with open(input_filename, 'w') as f: f.write(_prepare_pymatgen_dict(parameters.get_dict(), struct)) f.flush() commandline_params = self._default_commandline_params calcinfo = CalcInfo() calcinfo.uuid = self.uuid calcinfo.local_copy_list = [] calcinfo.remote_copy_list = [] calcinfo.retrieve_list = [ self._DEFAULT_OUTPUT_FILE, self._DEFAULT_ERROR_FILE ] calcinfo.retrieve_singlefile_list = [] codeinfo = CodeInfo() codeinfo.cmdline_params = commandline_params codeinfo.stdout_name = self._DEFAULT_OUTPUT_FILE codeinfo.stderr_name = self._DEFAULT_ERROR_FILE codeinfo.code_uuid = code.uuid calcinfo.codes_info = [codeinfo] return calcinfo
def _prepare_for_submission(self, tempfolder, inputdict): """ Create input files. :param tempfolder: aiida.common.folders.Folder subclass where the plugin should put all its files. :param inputdict: dictionary of the input nodes as they would be returned by get_inputs_dict """ # Check inputdict try: parameters = inputdict.pop(self.get_linkname('parameters')) except KeyError: raise InputValidationError("No parameters specified for this " "calculation") if not isinstance(parameters, MultiplyParameters): raise InputValidationError("parameters not of type " "MultiplyParameters") try: code = inputdict.pop(self.get_linkname('code')) except KeyError: raise InputValidationError("No code specified for this " "calculation") if inputdict: raise ValidationError("Unknown inputs besides MultiplyParameters") # In this example, the input file is simply a json dict. # Adapt for your particular code! input_dict = parameters.get_dict() # Write input to file input_filename = tempfolder.get_abs_path(self._INPUT_FILE_NAME) with open(input_filename, 'w') as infile: json.dump(input_dict, infile) # Prepare CalcInfo to be returned to aiida calcinfo = CalcInfo() calcinfo.uuid = self.uuid calcinfo.local_copy_list = [] calcinfo.remote_copy_list = [] calcinfo.retrieve_list = [self._OUTPUT_FILE_NAME] codeinfo = CodeInfo() # will call ./code.py in.json out.json codeinfo.cmdline_params = [ self._INPUT_FILE_NAME, self._OUTPUT_FILE_NAME ] codeinfo.code_uuid = code.uuid calcinfo.codes_info = [codeinfo] return calcinfo
def prepare_for_submission(self, tempfolder): """ This is the routine to be called when you want to create the input files and related stuff with a plugin. :param tempfolder: an aiida.common.folders.Folder subclass where the plugin should put all its files. """ content = self.create_input( self.inputs.structure, self.inputs.potential, self.inputs.get("parameters", None), self.inputs.get("symmetry", None), ) if not isinstance(content, six.text_type): content = six.u(content) with tempfolder.open(self.metadata.options.input_file_name, "w") as f: f.write(content) # Prepare CodeInfo object for aiida, # describes how a code has to be executed code = self.inputs.code codeinfo = CodeInfo() codeinfo.code_uuid = code.uuid codeinfo.stdin_name = self.metadata.options.input_file_name codeinfo.stdout_name = self.metadata.options.output_main_file_name codeinfo.stderr_name = self.metadata.options.output_stderr_file_name codeinfo.withmpi = self.metadata.options.withmpi # Prepare CalcInfo object for aiida calcinfo = CalcInfo() calcinfo.uuid = self.uuid calcinfo.codes_info = [codeinfo] calcinfo.local_copy_list = [] calcinfo.remote_copy_list = [] calcinfo.retrieve_list = self.get_retrieve_list() calcinfo.retrieve_temporary_list = [] return calcinfo
def _prepare_for_submission(self, tempfolder, inputdict): calcinfo = CalcInfo() calcinfo.uuid = self.uuid calcinfo.remote_copy_list = [] calcinfo.retrieve_list = [] codeinfo = CodeInfo() codeinfo.cmdline_params = [] codeinfo.stdout_name = self._OUTPUT_FILE_NAME code = inputdict.pop(self.get_linkname('code')) codeinfo.code_uuid = code.uuid calcinfo.codes_info = [codeinfo] return calcinfo
def prepare_for_submission(self, folder): """Create the input files from the input nodes passed to this instance of the `CalcJob`. :param folder: an `aiida.common.folders.Folder` to temporarily write files on disk :return: `aiida.common.datastructures.CalcInfo` instance """ from aiida_qeq.data.qeq import DEFAULT_CONFIGURE_FILE_NAME, LOG_FILE_NAME try: configure = self.inputs.configure except AttributeError: configure = QeqParameters() # Prepare CodeInfo object for aiida codeinfo = CodeInfo() codeinfo.code_uuid = self.inputs.code.uuid codeinfo.cmdline_params = configure.cmdline_params(structure_file_name=self.inputs.structure.filename, param_file_name=self.inputs.parameters.filename) # trick: since we aren't changing metadata.options.scheduler_stdout, this file won't be fetched by the engine # (I don't know how to prohibit storing of the stdout otherwise) codeinfo.stdout_name = LOG_FILE_NAME # write configure.input file with io.StringIO(configure.configure_string) as handle: folder.create_file_from_filelike(handle, filename=DEFAULT_CONFIGURE_FILE_NAME, mode='w') # Prepare CalcInfo object for aiida calcinfo = CalcInfo() calcinfo.uuid = self.uuid calcinfo.local_copy_list = [ [self.inputs.structure.uuid, self.inputs.structure.filename, self.inputs.structure.filename], [self.inputs.parameters.uuid, self.inputs.parameters.filename, self.inputs.parameters.filename], ] calcinfo.remote_copy_list = [] calcinfo.retrieve_list = configure.output_files calcinfo.retrieve_temporary_list = [LOG_FILE_NAME] # check output for error reports calcinfo.codes_info = [codeinfo] return calcinfo
def _prepare_for_submission(self, tempfolder, inputdict): """ Create input files. :param tempfolder: aiida.common.folders.Folder subclass where the plugin should put all its files. :param inputdict: dictionary of the input nodes as they would be returned by get_inputs_dict """ parameters, code, distance_matrix, symlink = \ self._validate_inputs(inputdict) # Prepare CalcInfo to be returned to aiida calcinfo = CalcInfo() calcinfo.uuid = self.uuid calcinfo.remote_copy_list = [] calcinfo.retrieve_list = parameters.output_files codeinfo = CodeInfo() codeinfo.code_uuid = code.uuid if distance_matrix is not None: calcinfo.local_copy_list = [ [ distance_matrix.get_file_abs_path(), distance_matrix.filename ], ] codeinfo.cmdline_params = parameters.cmdline_params( distance_matrix_file_name=distance_matrix.filename) else: calcinfo.remote_symlink_list = [symlink] codeinfo.cmdline_params = parameters.cmdline_params( remote_folder_path=self._REMOTE_FOLDER_LINK) calcinfo.codes_info = [codeinfo] return calcinfo
def prepare_for_submission(self, folder): """Create the input files from the input nodes passed to this instance of the `CalcJob`. :param folder: an `aiida.common.folders.Folder` to temporarily write files on disk :return: `aiida.common.datastructures.CalcInfo` instance """ # Prepare CodeInfo object for aiida codeinfo = CodeInfo() codeinfo.code_uuid = self.inputs.code.uuid codeinfo.cmdline_params = self.inputs.parameters.cmdline_params( structure_file_name=self.inputs.structure.filename, ionization_file_name=self.inputs.ionization_data.filename, charge_file_name=self.inputs.charge_data.filename) codeinfo.stdout_name = self._LOG_FILE_NAME # Prepare CalcInfo object for aiida calcinfo = CalcInfo() calcinfo.uuid = self.uuid calcinfo.local_copy_list = [ [ self.inputs.structure.uuid, self.inputs.structure.filename, self.inputs.structure.filename ], [ self.inputs.ionization_data.uuid, self.inputs.ionization_data.filename, self.inputs.ionization_data.filename ], [ self.inputs.charge_data.uuid, self.inputs.charge_data.filename, self.inputs.charge_data.filename ], ] calcinfo.remote_copy_list = [] calcinfo.retrieve_list = self.inputs.parameters.output_files( self.inputs.structure.filename) calcinfo.codes_info = [codeinfo] return calcinfo
def _prepare_for_submission(self, tempfolder, inputdict): """ Create input files. :param tempfolder: aiida.common.folders.Folder subclass where the plugin should put all its files. :param inputdict: dictionary of the input nodes as they would be returned by get_inputs_dict """ parameters, code, structure, atomic_radii = \ self._validate_inputs(inputdict) # Prepare CalcInfo to be returned to aiida calcinfo = CalcInfo() calcinfo.uuid = self.uuid calcinfo.local_copy_list = [[ structure.get_file_abs_path(), structure.filename ]] if atomic_radii is not None: radii_file_name = atomic_radii.filename calcinfo.local_copy_list.append( [atomic_radii.get_file_abs_path(), radii_file_name]) else: radii_file_name = None calcinfo.remote_copy_list = [] calcinfo.retrieve_list = parameters.output_files codeinfo = CodeInfo() codeinfo.cmdline_params = parameters.cmdline_params( structure_file_name=structure.filename, radii_file_name=radii_file_name) codeinfo.code_uuid = code.uuid calcinfo.codes_info = [codeinfo] return calcinfo
def _prepare_for_submission(self, tempfolder, input_nodes_raw): """ This method is called prior to job submission with a set of calculation input nodes. The inputs will be validated and sanitized, after which the necessary input files will be written to disk in a temporary folder. A CalcInfo instance will be returned that contains lists of files that need to be copied to the remote machine before job submission, as well as file lists that are to be retrieved after job completion. :param tempfolder: an aiida.common.folders.Folder to temporarily write files on disk :param input_nodes_raw: a dictionary with the raw input nodes :returns: CalcInfo instance """ input_nodes = self.validate_input_nodes(input_nodes_raw) input_x = input_nodes[self.get_linkname('x')] input_y = input_nodes[self.get_linkname('y')] input_code = input_nodes[self.get_linkname('code')] self.write_input_files(tempfolder, input_x, input_y) retrieve_list = self.get_retrieve_list() local_copy_list = self.get_local_copy_list() remote_copy_list = self.get_remote_copy_list() codeinfo = CodeInfo() codeinfo.cmdline_params = ['-in', self._INPUT_FILE_NAME] codeinfo.stdout_name = self._OUTPUT_FILE_NAME codeinfo.code_uuid = input_code.uuid calcinfo = CalcInfo() calcinfo.uuid = self.uuid calcinfo.codes_info = [codeinfo] calcinfo.retrieve_list = retrieve_list calcinfo.local_copy_list = local_copy_list calcinfo.remote_copy_list = remote_copy_list return calcinfo
def _prepare_for_submission(self, tempfolder, inputdict): try: import pymatgen as pmg except: print 'import pymatgen as pmg failed' incar_file = tempfolder.get_abs_path('INCAR') incar_data = inputdict['settings'] incar_object = pmg.io.vasp.Incar.from_dict(incar_data.get_dict()) incar_object.write_file(incar_file) poscar_file = tempfolder.get_abs_path('POSCAR') poscar_data = inputdict['structure_in'] poscar_object = pmg.io.vasp.Poscar.from_dict(poscar_data.get_dict()) poscar_object.write_file(poscar_file) potcar_file = tempfolder.get_abs_path('POTCAR') potcar_data = inputdict['potentials_in'].get_file_abs_path() #~ potcar_object = pmg.io.vasp.Potcar.from_dict(potcar_data.get_dict()) #~ potcar_object.write_file(potcar_file) with open(potcar_data) as potcar_in: with open(potcar_file, 'w') as potcar_out: potcar_out.write(potcar_in.read()) kpoints_file = tempfolder.get_abs_path('KPOINTS') kpoints_data = inputdict['kpoints_in'] kpoints_object = pmg.io.vasp.Kpoints.from_dict(kpoints_data.get_dict()) kpoints_object.write_file(kpoints_file) calcinfo = CalcInfo() calcinfo.uuid = self.uuid calcinfo.local_copy_list = [] calcinfo.remote_copy_list = [] #~ calcinfo.stdin_name = self._INPUT_FILE_NAME #~ calcinfo.stdout_name = self._OUTPUT_FILE_NAME calcinfo.retrieve_list = [ 'CHG', 'CHGCAR', 'CONTCAR', 'DOSCAR', 'EIGENVAL', 'OSZICAR', 'OUTCAR', 'PCDAT', 'PROCAR', 'WAVECAR', 'XDATCAR', 'vasprun.xml' ] return calcinfo
def _prepare_for_submission(self, tempfolder, inputdict): settings = inputdict.pop(self.get_linkname('settings'), None) if settings is None: settings_dict = {} else: if not isinstance(settings, ParameterData): raise InputValidationError("settings, if specified, must be of " "type ParameterData") settings_dict = settings.get_dict() try: code = inputdict.pop(self.get_linkname('code')) except KeyError: raise InputValidationError("No code specified for this calculation") try: parameters = inputdict.pop(self.get_linkname('parameters')) except KeyError: raise InputValidationError("No parameters specified for this calculation") if not isinstance(parameters, ParameterData): raise InputValidationError("parameters is not of type ParameterData") calcinfo = CalcInfo() calcinfo.uuid = self.uuid # Empty command line by default cmdline_params = settings_dict.pop('CMDLINE', []) #calcinfo.stdin_name = self._INPUT_FILE_NAME #calcinfo.stdout_name = self._OUTPUT_FILE_NAME codeinfo = CodeInfo() codeinfo.cmdline_params = list(cmdline_params) ##calcinfo.stdin_name = self._INPUT_FILE_NAME codeinfo.stdout_name = self._OUTPUT_FILE_NAME codeinfo.code_uuid = code.uuid calcinfo.codes_info = [codeinfo] # #calcinfo.remote_copy_list = remote_copy_list #calcinfo.remote_symlink_list = remote_symlink_list calcinfo.local_copy_list = [] # Retrieve by default the output file and the xml file calcinfo.retrieve_list = [] calcinfo.retrieve_list.append(self._OUTPUT_FILE_NAME) calcinfo.retrieve_list.append("info.xml") #calcinfo.retrieve_list.append(self._DATAFILE_XML) #settings_retrieve_list = settings_dict.pop('ADDITIONAL_RETRIEVE_LIST', []) try: structure = inputdict.pop(self.get_linkname('structure')) except KeyError: raise InputValidationError("No structure specified for this calculation") if not isinstance(structure, StructureData): raise InputValidationError("structure is not of type StructureData") try: kpoints = inputdict.pop(self.get_linkname('kpoints')) except KeyError: raise InputValidationError("No kpoints specified for this calculation") if not isinstance(kpoints, KpointsData): raise InputValidationError("kpoints is not of type KpointsData") kmesh, koffset = kpoints.get_kpoints_mesh() lapw_basis_list = {} for link in inputdict.keys(): if link.startswith("lapwbasis_"): kindstring = link[len("lapwbasis_"):] lapw_basis_list[kindstring] = inputdict.pop(link) import xml.etree.ElementTree as ET root = ET.Element("input") ET.SubElement(root, "title").text = "input file created with AiiDA" struct = ET.SubElement(root, "structure", attrib={'speciespath' : './', 'autormt' : 'true'}) cryst = ET.SubElement(struct, "crystal", attrib={'scale' : '1.889725989'}) from numpy import matrix lat_vec = matrix(structure.cell) inv_lat_vec = lat_vec.T.I; for vector in structure.cell: ET.SubElement(cryst, "basevect").text = " ".join(['%18.10f'%e for e in vector]) for kind in structure.kinds: lapw_basis = lapw_basis_list[kind.symbol] calcinfo.local_copy_list.append((lapw_basis.get_file_abs_path(), lapw_basis.filename)) s = ET.SubElement(struct, "species", attrib={'speciesfile' : lapw_basis.filename}) for site in structure.sites: if site.kind_name == kind.name: pos_cart = matrix(site.position) pos_lat = inv_lat_vec * pos_cart.T ET.SubElement(s, "atom", attrib={'coord' : " ".join(['%18.10f'%e for e in pos_lat])}) parameters_dict = parameters.get_dict() groundstate_attrib = {} if 'groundstate' in parameters_dict: groundstate_attrib = parameters_dict['groundstate'] groundstate_attrib['ngridk'] = " ".join(['%i'%e for e in kmesh]) # ET.SubElement(root, "groundstate", attrib=groundstate_attrib) grnd = ET.SubElement(root, "groundstate", attrib=groundstate_attrib) solver_attrib = {} if 'solver' in parameters_dict: solver_attrib = parameters_dict['solver'] ET.SubElement(grnd, "solver", attrib=solver_attrib) sirius_attrib = {} if 'sirius' in parameters_dict: sirius_attrib = parameters_dict['sirius'] ET.SubElement(grnd, "sirius", attrib=sirius_attrib) libxc_attrib = {} if 'libxc' in parameters_dict: libxc_attrib = parameters_dict['libxc'] ET.SubElement(grnd, "libxc", attrib=libxc_attrib) tree = ET.ElementTree(root) tree.write(tempfolder.get_abs_path("input.xml")) return calcinfo
def _prepare_for_submission(self,tempfolder,inputdict): """ This is the routine to be called when you want to create the input files and related stuff with a plugin. :param tempfolder: a aiida.common.folders.Folder subclass where the plugin should put all its files. :param inputdict: a dictionary with the input nodes, as they would be returned by get_inputdata_dict (without the Code!) """ import numpy as np local_copy_list = [] remote_copy_list = [] remote_symlink_list = [] try: code = inputdict.pop(self.get_linkname('code')) except KeyError: raise InputValidationError("No code specified for this calculation") try: pw_parameters = inputdict.pop(self.get_linkname('pw_parameters')) except KeyError: raise InputValidationError("No PW parameters specified for this calculation") if not isinstance(pw_parameters, ParameterData): raise InputValidationError("PW parameters is not of type ParameterData") try: neb_parameters = inputdict.pop(self.get_linkname('neb_parameters')) except KeyError: raise InputValidationError("No NEB parameters specified for this calculation") if not isinstance(neb_parameters, ParameterData): raise InputValidationError("NEB parameters is not of type ParameterData") try: first_structure = inputdict.pop(self.get_linkname('first_structure')) except KeyError: raise InputValidationError("No initial structure specified for this calculation") if not isinstance(first_structure, StructureData): raise InputValidationError("Initial structure is not of type StructureData") try: last_structure = inputdict.pop(self.get_linkname('last_structure')) except KeyError: raise InputValidationError("No final structure specified for this calculation") if not isinstance(last_structure, StructureData): raise InputValidationError("Final structure is not of type StructureData") try: kpoints = inputdict.pop(self.get_linkname('kpoints')) except KeyError: raise InputValidationError("No kpoints specified for this calculation") if not isinstance(kpoints, KpointsData): raise InputValidationError("kpoints is not of type KpointsData") # Settings can be undefined, and defaults to an empty dictionary settings = inputdict.pop(self.get_linkname('settings'),None) if settings is None: settings_dict = {} else: if not isinstance(settings, ParameterData): raise InputValidationError("settings, if specified, must be of " "type ParameterData") # Settings converted to uppercase settings_dict = _uppercase_dict(settings.get_dict(), dict_name='settings') pseudos = {} # I create here a dictionary that associates each kind name to a pseudo for link in inputdict.keys(): if link.startswith(self._get_linkname_pseudo_prefix()): kindstring = link[len(self._get_linkname_pseudo_prefix()):] kinds = kindstring.split('_') the_pseudo = inputdict.pop(link) if not isinstance(the_pseudo, UpfData): raise InputValidationError("Pseudo for kind(s) {} is not of " "type UpfData".format(",".join(kinds))) for kind in kinds: if kind in pseudos: raise InputValidationError("Pseudo for kind {} passed " "more than one time".format(kind)) pseudos[kind] = the_pseudo parent_calc_folder = inputdict.pop(self.get_linkname('parent_folder'), None) if parent_calc_folder is not None: if not isinstance(parent_calc_folder, RemoteData): raise InputValidationError("parent_calc_folder, if specified, " "must be of type RemoteData") vdw_table = inputdict.pop(self.get_linkname('vdw_table'), None) if vdw_table is not None: if not isinstance(vdw_table, SinglefileData): raise InputValidationError("vdw_table, if specified, " "must be of type SinglefileData") # Here, there should be no more parameters... if inputdict: raise InputValidationError("The following input data nodes are " "unrecognized: {}".format(inputdict.keys())) # Check that the first and last image have the same cell if abs(np.array(first_structure.cell)- np.array(last_structure.cell)).max() > 1.e-4: raise InputValidationError("Different cell in the fist and last image") # Check that the first and last image have the same number of sites if len(first_structure.sites) != len(last_structure.sites): raise InputValidationError("Different number of sites in the fist and last image") # Check that sites in the initial and final structure have the same kinds if not first_structure.get_site_kindnames() == last_structure.get_site_kindnames(): raise InputValidationError("Mismatch between the kind names and/or oder between " "the first and final image") # Check structure, get species, check peudos kindnames = [k.name for k in first_structure.kinds] if set(kindnames) != set(pseudos.keys()): err_msg = ("Mismatch between the defined pseudos and the list of " "kinds of the structure. Pseudos: {}; kinds: {}".format( ",".join(pseudos.keys()), ",".join(list(kindnames)))) raise InputValidationError(err_msg) ############################## # END OF INITIAL INPUT CHECK # ############################## # I create the subfolder that will contain the pseudopotentials tempfolder.get_subfolder(self._PSEUDO_SUBFOLDER, create=True) # I create the subfolder with the output data (sometimes Quantum # Espresso codes crash if an empty folder is not already there tempfolder.get_subfolder(self._OUTPUT_SUBFOLDER, create=True) # We first prepare the NEB-specific input file input_filecontent = self._generate_NEBinputdata(neb_parameters,settings_dict) input_filename = tempfolder.get_abs_path(self._INPUT_FILE_NAME) with open(input_filename, 'w') as infile: infile.write(input_filecontent) # We now generate the PW input files for each input structure local_copy_pseudo_list = [] for i, structure in enumerate([first_structure, last_structure]): # We need to a pass a copy of the settings_dict for each structure this_settings_dict = copy.deepcopy(settings_dict) input_filecontent, this_local_copy_pseudo_list = self._generate_PWCPinputdata(pw_parameters,this_settings_dict, pseudos,structure,kpoints) local_copy_pseudo_list += this_local_copy_pseudo_list input_filename = tempfolder.get_abs_path('pw_{}.in'.format(i+1)) with open(input_filename, 'w') as infile: infile.write(input_filecontent) # We need to pop the settings that were used in the PW calculations for key in settings_dict.keys(): if key not in this_settings_dict.keys(): settings_dict.pop(key) # We avoid to copy twice the same pseudopotential to the same filename local_copy_pseudo_list = set(local_copy_pseudo_list) # We check that two different pseudopotentials are not copied # with the same name (otherwise the first is overwritten) if len(set([ pseudoname for local_path, pseudoname in local_copy_pseudo_list])) < len(local_copy_pseudo_list): raise InputValidationError("Same filename for two different pseudopotentials") local_copy_list += local_copy_pseudo_list # If present, add also the Van der Waals table to the pseudo dir # Note that the name of the table is not checked but should be the # one expected by QE. if vdw_table: local_copy_list.append( ( vdw_table.get_file_abs_path(), os.path.join(self._PSEUDO_SUBFOLDER, os.path.split(vdw_table.get_file_abs_path())[1]) ) ) # operations for restart symlink = settings_dict.pop('PARENT_FOLDER_SYMLINK', self._default_symlink_usage) # a boolean if symlink: if parent_calc_folder is not None: # I put the symlink to the old parent ./out folder remote_symlink_list.append( (parent_calc_folder.get_computer().uuid, os.path.join(parent_calc_folder.get_remote_path(), self._OUTPUT_SUBFOLDER,'*'), self._OUTPUT_SUBFOLDER )) # and to the old parent prefix.path remote_symlink_list.append( (parent_calc_folder.get_computer().uuid, os.path.join(parent_calc_folder.get_remote_path(), '{}.path'.format(self._PREFIX)), '{}.path'.format(self._PREFIX) )) else: # copy remote output dir and .path file, if specified if parent_calc_folder is not None: remote_copy_list.append( (parent_calc_folder.get_computer().uuid, os.path.join(parent_calc_folder.get_remote_path(), self._OUTPUT_SUBFOLDER,'*'), self._OUTPUT_SUBFOLDER )) # and to the old parent prefix.path remote_copy_list.append( (parent_calc_folder.get_computer().uuid, os.path.join(parent_calc_folder.get_remote_path(), '{}.path'.format(self._PREFIX)), '{}.path'.format(self._PREFIX) )) # here we may create an aiida.EXIT file create_exit_file = settings_dict.pop('ONLY_INITIALIZATION',False) if create_exit_file: exit_filename = tempfolder.get_abs_path( '{}.EXIT'.format(self._PREFIX)) with open(exit_filename,'w') as f: f.write('\n') calcinfo = CalcInfo() codeinfo=CodeInfo() calcinfo.uuid = self.uuid # Empty command line by default cmdline_params = settings_dict.pop('CMDLINE', []) # For the time-being we only have the initial and final image calcinfo.local_copy_list = local_copy_list calcinfo.remote_copy_list = remote_copy_list calcinfo.remote_symlink_list = remote_symlink_list # In neb calculations there is no input read from standard input!! codeinfo.cmdline_params = (["-input_images", "2"] + list(cmdline_params)) codeinfo.stdout_name = self._OUTPUT_FILE_NAME codeinfo.code_uuid = code.uuid calcinfo.codes_info = [codeinfo] # Retrieve by default the output file and ... calcinfo.retrieve_list = [] calcinfo.retrieve_list.append(self._OUTPUT_FILE_NAME) calcinfo.retrieve_list.append([os.path.join(self._OUTPUT_SUBFOLDER, self._PREFIX + '_*[0-9]', 'PW.out'), '.', 2]) calcinfo.retrieve_list.append([os.path.join(self._OUTPUT_SUBFOLDER, self._PREFIX + '_*[0-9]',self._PREFIX + '.save', self._DATAFILE_XML_BASENAME), '.', 3]) settings_retrieve_list = settings_dict.pop('ADDITIONAL_RETRIEVE_LIST', []) calcinfo.retrieve_list += settings_retrieve_list calcinfo.retrieve_list += self._internal_retrieve_list if settings_dict: try: Parserclass = self.get_parserclass() parser = Parserclass(self) parser_opts = parser.get_parser_settings_key() settings_dict.pop(parser_opts) except (KeyError, AttributeError): # the key parser_opts isn't inside the dictionary raise InputValidationError("The following keys have been found in " "the settings input node, but were not understood: {}".format( ",".join(settings_dict.keys()))) return calcinfo
def _prepare_for_submission(self, tempfolder, inputdict): """ This is the routine to be called when you want to create the input files and related stuff with a plugin. :param tempfolder: a aiida.common.folders.Folder subclass where the plugin should put all its files. :param inputdict: a dictionary with the input nodes, as they would be returned by get_inputs_dict (with the Code!) """ import StringIO from aiida.orm.data.singlefile import SinglefileData from aiida.orm.data.remote import RemoteData from aiida.common.utils import validate_list_of_string_tuples from aiida.common.exceptions import ValidationError parameters_node = inputdict.pop('parameters', None) if parameters_node is None: parameters = {} else: parameters = parameters_node.get_dict() template_node = inputdict.pop('template', None) template = template_node.get_dict() input_file_template = template.pop('input_file_template', '') input_file_name = template.pop('input_file_name', None) output_file_name = template.pop('output_file_name', None) cmdline_params_tmpl = template.pop('cmdline_params', []) input_through_stdin = template.pop('input_through_stdin', False) files_to_copy = template.pop('files_to_copy', []) retrieve_temporary_files = template.pop('retrieve_temporary_files', []) if template: raise InputValidationError( 'The following keys could not be used in the template node: {}' .format(template.keys())) try: validate_list_of_string_tuples(files_to_copy, tuple_length=2) except ValidationError as e: raise InputValidationError( "invalid file_to_copy format: {}".format(e.message)) local_copy_list = [] remote_copy_list = [] for link_name, dest_rel_path in files_to_copy: try: fileobj = inputdict.pop(link_name) except KeyError: raise InputValidationError( "You are asking to copy a file link {}, " "but there is no input link with such a name".format( link_name)) if isinstance(fileobj, SinglefileData): local_copy_list.append( (fileobj.get_file_abs_path(), dest_rel_path)) elif isinstance(fileobj, RemoteData): # can be a folder remote_copy_list.append( (fileobj.get_computer().uuid, fileobj.get_remote_path(), dest_rel_path)) else: raise InputValidationError( "If you ask to copy a file link {}, " "it must be either a SinglefileData or a RemoteData; it is instead of type {}" .format(link_name, fileobj.__class__.__name__)) code = inputdict.pop('code', None) if code is None: raise InputValidationError("No code in input") if len(inputdict) > 0: raise InputValidationError( "The input nodes with the following labels could not be " "used by the templatereplacer plugin: {}".format( inputdict.keys())) if input_file_name is not None and not input_file_template: raise InputValidationError( "If you give an input_file_name, you " "must also specify a input_file_template") if input_through_stdin and input_file_name is None: raise InputValidationError( "If you ask for input_through_stdin you have to " "specify a input_file_name") input_file = StringIO.StringIO( input_file_template.format(**parameters)) if input_file_name: tempfolder.create_file_from_filelike(input_file, input_file_name) else: if input_file_template: self.logger.warning( "No input file name passed, but a input file template is present" ) cmdline_params = [i.format(**parameters) for i in cmdline_params_tmpl] calcinfo = CalcInfo() calcinfo.retrieve_list = [] calcinfo.retrieve_temporary_list = [] calcinfo.uuid = self.uuid calcinfo.local_copy_list = local_copy_list calcinfo.remote_copy_list = remote_copy_list codeinfo = CodeInfo() codeinfo.cmdline_params = cmdline_params if input_through_stdin is not None: codeinfo.stdin_name = input_file_name if output_file_name: codeinfo.stdout_name = output_file_name calcinfo.retrieve_list.append(output_file_name) if retrieve_temporary_files: calcinfo.retrieve_temporary_list = retrieve_temporary_files codeinfo.code_uuid = code.uuid calcinfo.codes_info = [codeinfo] return calcinfo
def _prepare_for_submission(self, tempfolder, inputdict): """ This is the routine to be called when you want to create the input files and related stuff with a plugin. :param tempfolder: a aiida.common.folders.Folder subclass where the plugin should put all its files. :param inputdict: a dictionary with the input nodes, as they would be returned by get_inputdata_dict (without the Code!) """ try: parameters_data = inputdict.pop(self.get_linkname('parameters')) except KeyError: pass #raise InputValidationError("No parameters specified for this " # "calculation") if not isinstance(parameters_data, ParameterData): raise InputValidationError("parameters is not of type " "ParameterData") try: structure = inputdict.pop(self.get_linkname('structure')) except KeyError: raise InputValidationError( "no structure is specified for this calculation") try: trajectory = inputdict.pop(self.get_linkname('trajectory')) except KeyError: raise InputValidationError( "trajectory is specified for this calculation") try: force_constants = inputdict.pop( self.get_linkname('force_constants')) except KeyError: raise InputValidationError( "no force_constants is specified for this calculation") try: code = inputdict.pop(self.get_linkname('code')) except KeyError: raise InputValidationError( "no code is specified for this calculation") time_step = trajectory.get_times()[1] - trajectory.get_times()[0] ############################## # END OF INITIAL INPUT CHECK # ############################## # =================== prepare the python input files ===================== cell_txt = get_poscar_txt(structure) input_txt = parameters_to_input_file(parameters_data) force_constants_txt = get_FORCE_CONSTANTS_txt(force_constants) trajectory_txt = get_trajectory_txt(trajectory) # =========================== dump to file ============================= input_filename = tempfolder.get_abs_path(self._INPUT_FILE_NAME) with open(input_filename, 'w') as infile: infile.write(input_txt) cell_filename = tempfolder.get_abs_path(self._INPUT_CELL) with open(cell_filename, 'w') as infile: infile.write(cell_txt) force_constants_filename = tempfolder.get_abs_path( self._INPUT_FORCE_CONSTANTS) with open(force_constants_filename, 'w') as infile: infile.write(force_constants_txt) trajectory_filename = tempfolder.get_abs_path(self._INPUT_TRAJECTORY) with open(trajectory_filename, 'w') as infile: infile.write(trajectory_txt) # ============================ calcinfo ================================ local_copy_list = [] remote_copy_list = [] # additional_retrieve_list = settings_dict.pop("ADDITIONAL_RETRIEVE_LIST",[]) calcinfo = CalcInfo() calcinfo.uuid = self.uuid # Empty command line by default calcinfo.local_copy_list = local_copy_list calcinfo.remote_copy_list = remote_copy_list # Retrieve files calcinfo.retrieve_list = [ self._OUTPUT_FILE_NAME, self._OUTPUT_FORCE_CONSTANTS, self._OUTPUT_QUASIPARTICLES ] codeinfo = CodeInfo() codeinfo.cmdline_params = [ self._INPUT_FILE_NAME, self._INPUT_TRAJECTORY, '-ts', '{}'.format(time_step), '--silent', '-sfc', self._OUTPUT_FORCE_CONSTANTS, '-thm', # '--resolution 0.01', '-psm', '2', '--normalize_dos', '-sdata' ] if 'temperature' in parameters_data.get_dict(): codeinfo.cmdline_params.append('--temperature') codeinfo.cmdline_params.append('{}'.format( parameters_data.dict.temperature)) if 'md_commensurate' in parameters_data.get_dict(): if parameters_data.dict.md_commensurate: codeinfo.cmdline_params.append('--MD_commensurate') codeinfo.stdout_name = self._OUTPUT_FILE_NAME codeinfo.code_uuid = code.uuid codeinfo.withmpi = False calcinfo.codes_info = [codeinfo] return calcinfo