def prepare_for_submission(self, folder): #create box.npy, coord.npy, force.npy, energy.npy and stress.npy (if present) mother_folder = None write_dict = self.inputs.param.get_dict() if not 'systems' in write_dict: write_dict['systems'] = ['raw'] if not 'set_prefix' in write_dict: write_dict['set_prefix'] = 'set' if not 'save_ckpt' in write_dict: write_dict['save_ckpt'] = 'model.ckpt' if not 'disp_file' in write_dict: write_dict['disp_file'] = 'lcurve.out' if 'restart_calculation_folder' in self.inputs: mother_folder = self.inputs.restart_calculation_folder symlink = [] copy_list = [] cmdline_params = [self.options.input_filename] if 'traj' in self.inputs: force = self.inputs.traj.get_array('forces') box = self.inputs.traj.get_array('cells') coord = self.inputs.traj.get_array('positions') energy = self.inputs.traj.get_array('scf_total_energy') #TODO: stress and scf_total_energy generic names for traj arrays nstep = force.shape[0] nfolders = int(nstep / int(self.inputs.nline_per_set)) for i in range(nfolders): startidx = i * int(self.inputs.nline_per_set) stopidx = (i + 1) * int( self.inputs.nline_per_set) if i + 1 < nfolders else nstep size = stopidx - startidx subfoldername = '{}/{}.{}'.format(write_dict['systems'][0], write_dict['set_prefix'], str(i).zfill(3)) subfolder = folder.get_subfolder(subfoldername, create=True) def save_sliced_arr(fname, arr): with subfolder.open(fname, mode='wb', encoding=None) as handle: np.save( handle, arr[startidx:stopidx].reshape(size, -1) if len(arr.shape) > 1 else arr[startidx:stopidx]) save_sliced_arr('box.npy', box) save_sliced_arr('coord.npy', coord) save_sliced_arr('energy.npy', energy) save_sliced_arr('force.npy', force) #write types of atoms def create_id(traj): l = [] sp = {} nidx = 0 for s in traj.symbols: idx = sp.setdefault(s, nidx) if idx == nidx: nidx = nidx + 1 l.append(idx) return l with folder.open(write_dict['systems'][0] + '/type.raw', 'w') as handle: np.savetxt(handle, create_id(self.inputs.traj)) elif mother_folder is not None: #make symlink for system in write_dict['systems']: symlink.append( (mother_folder.computer.uuid, mother_folder.get_remote_path() + '/' + system, system)) #copy checkpoint data copy_list.append( (mother_folder.computer.uuid, mother_folder.get_remote_path() + '/' + write_dict['save_ckpt'] + '*', '.')) write_dict['load_ckpt'] = write_dict['save_ckpt'] write_dict['restart'] = True #restart commandline option (the only one that is working for real?) cmdline_params.append('--restart={}'.format( write_dict['load_ckpt'])) else: #error: where is the data?? return self.exit_codes.ERROR_NO_TRAINING_DATA with folder.open(self.options.input_filename, 'w') as handle: json.dump(write_dict, handle) codeinfo = CodeInfo() codeinfo.code_uuid = self.inputs.code.uuid codeinfo.stdout_name = self.options.output_filename codeinfo.cmdline_params = cmdline_params calcinfo = CalcInfo() calcinfo.codes_info = [codeinfo] calcinfo.local_copy_list = [] calcinfo.remote_copy_list = copy_list calcinfo.remote_symlink_list = symlink #or self.metadata.options.output_filename? #calcinfo.retrieve_list = [ # (self.options.output_filename,'.',1), # (write_dict['save_ckpt']+'*','.',1), # (write_dict['disp_file'],'.',1) # ] calcinfo.retrieve_list = [ self.options.input_filename, self.options.output_filename, write_dict['save_ckpt'] + '*', write_dict['disp_file'] ] return calcinfo
def prepare_for_submission(self, folder): """ This is the routine to be called when you want to create the input files and related stuff with a plugin. :param folder: a aiida.common.folders.Folder subclass where the plugin should put all its files. """ # pylint: disable=too-many-locals,too-many-statements,too-many-branches from aiida.common.utils import validate_list_of_string_tuples from aiida.common.exceptions import ValidationError code = self.inputs.code template = self.inputs.template.get_dict() try: parameters = self.inputs.parameters.get_dict() except AttributeError: parameters = {} 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 exceptions.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 exc: raise exceptions.InputValidationError('invalid file_to_copy format: {}'.format(exc)) local_copy_list = [] remote_copy_list = [] for link_name, dest_rel_path in files_to_copy: try: fileobj = self.inputs.files[link_name] except AttributeError: raise exceptions.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, orm.SinglefileData): local_copy_list.append((fileobj.uuid, fileobj.filename, dest_rel_path)) elif isinstance(fileobj, orm.RemoteData): # can be a folder remote_copy_list.append((fileobj.computer.uuid, fileobj.get_remote_path(), dest_rel_path)) else: raise exceptions.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__)) if input_file_name is not None and not input_file_template: raise exceptions.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 exceptions.InputValidationError( 'If you ask for input_through_stdin you have to specify a input_file_name') input_content = input_file_template.format(**parameters) if input_file_name: folder.create_file_from_filelike(io.StringIO(input_content), input_file_name, 'w', encoding='utf8') 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.local_copy_list = local_copy_list calcinfo.remote_copy_list = remote_copy_list codeinfo = CodeInfo() codeinfo.cmdline_params = cmdline_params if input_through_stdin: 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!) """ local_copy_list = [] remote_copy_list = [] 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") # 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') parent_calc_folder = inputdict.pop(self.get_linkname('parent_folder'), None) if parent_calc_folder is not None: if not isinstance(parent_calc_folder, self._parent_folder_type): if not isinstance(self._parent_folder_type, tuple): possible_types = [self._parent_folder_type.__name__] else: possible_types = [ t.__name__ for t in self._parent_folder_type ] raise InputValidationError("parent_calc_folder, if specified," "must be of type {}".format( " or ".join(possible_types))) following_text = self._get_following_text(inputdict, settings) # Here, there should be no more parameters... if inputdict: raise InputValidationError("The following input data nodes are " "unrecognized: {}".format( inputdict.keys())) ############################## # END OF INITIAL INPUT CHECK # ############################## # I put the first-level keys as uppercase (i.e., namelist and card names) # and the second-level keys as lowercase # (deeper levels are unchanged) input_params = _uppercase_dict(parameters.get_dict(), dict_name='parameters') input_params = { k: _lowercase_dict(v, dict_name=k) for k, v in input_params.iteritems() } # set default values. NOTE: this is different from PW/CP for blocked in self._blocked_keywords: namelist = blocked[0].upper() key = blocked[1].lower() value = blocked[2] if namelist in input_params: if key in input_params[namelist]: raise InputValidationError( "You cannot specify explicitly the '{}' key in the '{}' " "namelist.".format(key, namelist)) # set to a default if not input_params[namelist]: input_params[namelist] = {} input_params[namelist][key] = value # =================== NAMELISTS AND CARDS ======================== try: namelists_toprint = settings_dict.pop('NAMELISTS') if not isinstance(namelists_toprint, list): raise InputValidationError( "The 'NAMELISTS' value, if specified in the settings input " "node, must be a list of strings") except KeyError: # list of namelists not specified; do automatic detection namelists_toprint = self._default_namelists input_filename = tempfolder.get_abs_path(self._INPUT_FILE_NAME) with open(input_filename, 'w') as infile: for namelist_name in namelists_toprint: infile.write("&{0}\n".format(namelist_name)) # namelist content; set to {} if not present, so that we leave an # empty namelist namelist = input_params.pop(namelist_name, {}) for k, v in sorted(namelist.iteritems()): infile.write(get_input_data_text(k, v)) infile.write("/\n") # Write remaning text now, if any infile.write(following_text) # Check for specified namelists that are not expected if input_params: raise InputValidationError( "The following namelists are specified in input_params, but are " "not valid namelists for the current type of calculation: " "{}".format(",".join(input_params.keys()))) # copy remote output dir, if specified if parent_calc_folder is not None: if isinstance(parent_calc_folder, RemoteData): parent_calc_out_subfolder = settings_dict.pop( 'PARENT_CALC_OUT_SUBFOLDER', self._INPUT_SUBFOLDER) remote_copy_list.append( (parent_calc_folder.get_computer().uuid, os.path.join(parent_calc_folder.get_remote_path(), parent_calc_out_subfolder), self._OUTPUT_SUBFOLDER)) elif isinstance(parent_calc_folder, FolderData): local_copy_list.append( (parent_calc_folder.get_abs_path(self._INPUT_SUBFOLDER), self._OUTPUT_SUBFOLDER)) elif isinstance(parent_calc_folder, SinglefileData): filename = parent_calc_folder.get_file_abs_path() local_copy_list.append((filename, os.path.basename(filename))) 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 codeinfo = CodeInfo() codeinfo.cmdline_params = settings_dict.pop('CMDLINE', []) codeinfo.stdin_name = self._INPUT_FILE_NAME codeinfo.stdout_name = self._OUTPUT_FILE_NAME codeinfo.code_uuid = code.uuid calcinfo.codes_info = [codeinfo] # Retrieve by default the output file and the xml file calcinfo.retrieve_list = [] calcinfo.retrieve_list.append(self._OUTPUT_FILE_NAME) settings_retrieve_list = settings_dict.pop('ADDITIONAL_RETRIEVE_LIST', []) calcinfo.retrieve_list += settings_retrieve_list calcinfo.retrieve_list += self._internal_retrieve_list calcinfo.retrieve_singlefile_list = self._retrieve_singlefile_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, or it is set to None 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): from aiida.orm.data.cif import CifData from aiida.orm.data.parameter import ParameterData from aiida_codtools.calculations 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 deposition") 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("No code found in input") parameters_dict = parameters.get_dict() deposit_file_rel = "deposit.cif" deposit_file_abs = tempfolder.get_abs_path(deposit_file_rel) shutil.copy(cif.get_file_abs_path(), deposit_file_abs) input_filename = tempfolder.get_abs_path(self._DEFAULT_INPUT_FILE) with open(input_filename, 'w') as f: f.write("{}\n".format(deposit_file_rel)) f.flush() config_file_abs = tempfolder.get_abs_path(self._CONFIG_FILE) with open(config_file_abs, 'w') as f: for k in self._config_keys: if k in parameters_dict.keys(): f.write("{}={}\n".format(k, parameters_dict.pop(k))) f.flush() commandline_params = self._default_commandline_params commandline_params.extend( commandline_params_from_dict(parameters_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): """ 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: raise InputValidationError("No parameters specified for this calculation") try: structure = inputdict.pop(self.get_linkname('structure')) except KeyError: raise InputValidationError("no structure is specified for this calculation") try: data_sets = inputdict.pop(self.get_linkname('data_sets')) except KeyError: raise InputValidationError("no data_set is specified for this calculation") try: code = inputdict.pop(self.get_linkname('code')) except KeyError: raise InputValidationError("no code is specified for this calculation") try: nac_data = inputdict.pop(self.get_linkname('nac_data')) except KeyError: nac_data = None ############################## # END OF INITIAL INPUT CHECK # ############################## # =================== prepare the python input files ===================== cell_txt = structure_to_poscar(structure) input_txt = parameters_to_input_file(parameters_data) force_sets_txt = get_FORCE_SETS_txt(data_sets) # For future use (not actually used, test only) if nac_data is not None: born_txt = get_BORN_txt(structure, parameters_data, nac_data) nac_filename = tempfolder.get_abs_path(self._INPUT_NAC) with open(nac_filename, 'w') as infile: infile.write(born_txt) # =========================== 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_sets_filename = tempfolder.get_abs_path(self._INPUT_FORCE_SETS) with open(force_sets_filename, 'w') as infile: infile.write(force_sets_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 = [] calcinfo.retrieve_list.append(self._OUTPUT_FILE_NAME) codeinfo = CodeInfo() codeinfo.cmdline_params = [self._INPUT_FILE_NAME, '--writefc'] codeinfo.code_uuid = code.uuid codeinfo.withmpi = False 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!) """ in_nodes = self._verify_inlinks(inputdict) params, structure, code, settings, local_copy_list, \ parent_calc_folder = in_nodes # write cp2k input file inp = Cp2kInput(params) inp.add_keyword("GLOBAL/PROJECT", self._PROJECT_NAME) if structure is not None: struct_fn = tempfolder.get_abs_path(self._COORDS_FILE_NAME) structure.export(struct_fn, fileformat="xyz") for i, a in enumerate('ABC'): val = '{:<15} {:<15} {:<15}'.format(*structure.cell[i]) inp.add_keyword('FORCE_EVAL/SUBSYS/CELL/' + a, val) topo = "FORCE_EVAL/SUBSYS/TOPOLOGY" inp.add_keyword(topo + "/COORD_FILE_NAME", self._COORDS_FILE_NAME) inp.add_keyword(topo + "/COORD_FILE_FORMAT", "XYZ") inp_fn = tempfolder.get_abs_path(self._INPUT_FILE_NAME) with open(inp_fn, "w") as f: f.write(inp.render()) # create code info codeinfo = CodeInfo() cmdline = settings.pop('cmdline', []) cmdline += ["-i", self._INPUT_FILE_NAME] codeinfo.cmdline_params = cmdline codeinfo.stdout_name = self._OUTPUT_FILE_NAME codeinfo.join_files = True codeinfo.code_uuid = code.uuid # create calc info calcinfo = CalcInfo() calcinfo.stdin_name = self._INPUT_FILE_NAME calcinfo.uuid = self.uuid calcinfo.cmdline_params = codeinfo.cmdline_params calcinfo.stdin_name = self._INPUT_FILE_NAME calcinfo.stdout_name = self._OUTPUT_FILE_NAME calcinfo.codes_info = [codeinfo] # file lists calcinfo.remote_symlink_list = [] calcinfo.local_copy_list = local_copy_list calcinfo.remote_copy_list = [] calcinfo.retrieve_list = [ self._OUTPUT_FILE_NAME, self._RESTART_FILE_NAME ] calcinfo.retrieve_list += settings.pop('additional_retrieve_list', []) # 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, self._PARENT_CALC_FOLDER_NAME) calcinfo.remote_symlink_list.append(symlink) # check for left over settings if settings: msg = "The following keys have been found " msg += "in the settings input node {}, ".format(self.pk) msg += "but were not understood: " + ",".join(settings.keys()) raise InputValidationError(msg) 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: 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, DiffParameters): raise InputValidationError("parameters not of type " "DiffParameters") try: file1 = inputdict.pop(self.get_linkname('file1')) except KeyError: raise InputValidationError("Missing file1") if not isinstance(file1, SinglefileData): raise InputValidationError("file1 not of type SinglefileData") try: file2 = inputdict.pop(self.get_linkname('file2')) except KeyError: raise InputValidationError("Missing file2") if not isinstance(file2, SinglefileData): raise InputValidationError("file2 not of type SinglefileData") if inputdict: raise ValidationError("Unknown inputs besides DiffParameters") # Prepare CodeInfo object for aiida codeinfo = CodeInfo() codeinfo.code_uuid = code.uuid codeinfo.cmdline_params = parameters.cmdline_params( file1_name=file1.filename, file2_name=file2.filename) codeinfo.stdout_name = self._OUTPUT_FILE_NAME # Prepare CalcInfo object for aiida calcinfo = CalcInfo() calcinfo.uuid = self.uuid calcinfo.local_copy_list = [] calcinfo.remote_copy_list = [] calcinfo.retrieve_list = [self._OUTPUT_FILE_NAME] calcinfo.local_copy_list = [ [file1.get_file_abs_path(), file1.filename], [file2.get_file_abs_path(), file2.filename], ] 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!) """ ### ------------------------------------------------------ ### Input check 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") try: parent_slab_folder = inputdict.pop( self.get_linkname('parent_slab_folder')) except KeyError: raise InputValidationError( "No parent_slab_folder specified for this calculation") if not isinstance(parent_slab_folder, RemoteData): raise InputValidationError( "parent_slab_folder is not of type RemoteData") try: parent_mol_folder = inputdict.pop( self.get_linkname('parent_mol_folder')) except KeyError: raise InputValidationError( "No parent_mol_folder specified for this calculation") if not isinstance(parent_mol_folder, RemoteData): raise InputValidationError( "parent_mol_folder is not of type RemoteData") try: settings = inputdict.pop(self.get_linkname('settings')) except KeyError: raise InputValidationError( "No settings specified for this calculation") if not isinstance(settings, ParameterData): raise InputValidationError("settings is not of type ParameterData") settings_dict = settings.get_dict() # Here, there should be no more parameters... if inputdict: raise InputValidationError("The following input data nodes are " "unrecognized: {}".format( inputdict.keys())) ### End of input check ### ------------------------------------------------------ # create code info codeinfo = CodeInfo() codeinfo.code_uuid = code.uuid cmdline = [] for key in parameters.dict: cmdline += [key] if parameters.dict[key] != '': if isinstance(parameters.dict[key], list): cmdline += parameters.dict[key] else: cmdline += [parameters.dict[key]] codeinfo.cmdline_params = cmdline # create calc info calcinfo = CalcInfo() calcinfo.uuid = self.uuid calcinfo.cmdline_params = codeinfo.cmdline_params calcinfo.codes_info = [codeinfo] # file lists calcinfo.remote_symlink_list = [] calcinfo.local_copy_list = [] calcinfo.remote_copy_list = [] calcinfo.retrieve_list = settings_dict.pop('additional_retrieve_list', []) # symlinks if parent_slab_folder is not None: comp_uuid = parent_slab_folder.get_computer().uuid remote_path = parent_slab_folder.get_remote_path() symlink = (comp_uuid, remote_path, "parent_slab_folder") calcinfo.remote_symlink_list.append(symlink) if parent_mol_folder is not None: comp_uuid = parent_mol_folder.get_computer().uuid remote_path = parent_mol_folder.get_remote_path() symlink = (comp_uuid, remote_path, "parent_mol_folder") calcinfo.remote_symlink_list.append(symlink) return calcinfo # EOF
def prepare_for_submission(self, folder): """ This is the routine to be called when you want to create the input files for the inpgen with the plug-in. :param folder: a aiida.common.folders.Folder subclass where the plugin should put all its files. """ local_copy_list = [] remote_copy_list = [] remote_symlink_list = [] # first check existence of structure and if 1D, 2D, 3D structure = self.inputs.structure # check existence of parameters (optional) if 'parameters' in self.inputs: parameters = self.inputs.parameters else: parameters = None if parameters is None: # use default parameters_dict = {} else: parameters_dict = _lowercase_dict(parameters.get_dict(), dict_name='parameters') code = self.inputs.code # check existence of settings (optional) if 'settings' in self.inputs: settings = self.inputs.settings else: settings = None if settings is None: settings_dict = {} else: settings_dict = settings.get_dict() # check for for allowed keys, ignore unknown keys but warn. for key in settings_dict.keys(): if key not in self._settings_keys: # TODO warning self.logger.info( 'settings dict key %s for Fleur calculation' 'not recognized, only %s are allowed.', key, str(self._settings_keys)) ####################################### #### WRITE ALL CARDS IN INPUT FILE #### with folder.open(self._INPUT_FILE_NAME, 'w') as input_file: write_inpgen_file_aiida_struct(structure, input_file, input_params=parameters_dict, settings=settings_dict) # create a JUDFT_WARN_ONLY file in the calculation folder with io.StringIO('/n') as handle: warn_only_filename = self._JUDFT_WARN_ONLY_INFO_FILE_NAME folder.create_file_from_filelike(handle, filename=warn_only_filename, mode='w') calcinfo = CalcInfo() calcinfo.uuid = self.uuid calcinfo.local_copy_list = local_copy_list calcinfo.remote_copy_list = remote_copy_list calcinfo.remote_symlink_list = remote_symlink_list # Retrieve per default only out file and inp.xml file? retrieve_list = [] retrieve_list.append(self._INPXML_FILE_NAME) retrieve_list.append(self._OUTPUT_FILE_NAME) retrieve_list.append(self._SHELLOUT_FILE_NAME) retrieve_list.append(self._ERROR_FILE_NAME) retrieve_list.append(self._STRUCT_FILE_NAME) retrieve_list.append(self._INPUT_FILE_NAME) # user specific retrieve add_retrieve = settings_dict.get('additional_retrieve_list', []) for file1 in add_retrieve: retrieve_list.append(file1) remove_retrieve = settings_dict.get('remove_from_retrieve_list', []) for file1 in remove_retrieve: if file1 in retrieve_list: retrieve_list.remove(file1) calcinfo.retrieve_list = [] for file1 in retrieve_list: calcinfo.retrieve_list.append(file1) codeinfo = CodeInfo() # , "-electronConfig"] # TODO? let the user decide -electronconfig? # We support different inpgen and fleur version via reading the version from the code node extras code_extras = code.extras code_version = code_extras.get('version', 32) if int(code_version) < 32: # run old inpgen cmdline_params = ['-explicit'] else: cmdline_params = [ '-explicit', '-inc', '+all', '-f', '{}'.format(self._INPUT_FILE_NAME) ] # user specific commandline_options for command in settings_dict.get('cmdline', []): cmdline_params.append(command) codeinfo.cmdline_params = (list(cmdline_params)) codeinfo.code_uuid = code.uuid codeinfo.stdin_name = self._INPUT_FILE_NAME codeinfo.stdout_name = self._SHELLOUT_FILE_NAME # shell output will be piped in file codeinfo.stderr_name = self._ERROR_FILE_NAME # std error too calcinfo.codes_info = [codeinfo] return calcinfo
def prepare_for_submission(self, folder): """ This is the routine to be called when you make a FLEUR calculation. This routine checks the inputs and modifies copy lists accordingly. The standard files to be copied are given here. :param folder: a aiida.common.folders.Folder subclass where the plugin should put all its files. """ local_copy_list = [] remote_copy_list = [] remote_symlink_list = [] mode_retrieved_filelist = [] filelist_tocopy_remote = [] settings_dict = {} has_fleurinp = False has_parent = False fleurinpgen = False copy_remotely = True with_hdf5 = False code = self.inputs.code codesdesc = code.description # TODO: ggf also check settings # In code description we write with what libs the code was compiled # we look for certain keywords in the description # also ggf, to be back comportable, the plugin should know the version number if codesdesc is not None: if 'hdf5' in codesdesc: with_hdf5 = True elif 'Hdf5' in codesdesc: with_hdf5 = True elif 'HDF5' in codesdesc: with_hdf5 = True else: with_hdf5 = False # a Fleur calc can be created from a fleurinpData alone # (then no parent is needed) all files are in the repo, but usually it is # a child of a inpgen calc or an other fleur calc (some or all files are # in a remote source). if the User has not changed something, the # calculation does not need theoretical a new FleurinpData it could use # the one from the parent, but the plug-in desgin is in a way that it has # to be there and it just copies files if changes occurred.. if 'fleurinpdata' in self.inputs: fleurinp = self.inputs.fleurinpdata else: fleurinp = None if fleurinp is None: has_fleurinp = False else: has_fleurinp = True if 'parent_folder' in self.inputs: parent_calc_folder = self.inputs.parent_folder else: parent_calc_folder = None if parent_calc_folder is None: has_parent = False if not has_fleurinp: raise InputValidationError( 'No parent calculation found and no fleurinp data ' 'given, need either one or both for a ' "'fleurcalculation'.") else: # extract parent calculation parent_calcs = parent_calc_folder.get_incoming( node_class=CalcJob).all() n_parents = len(parent_calcs) if n_parents != 1: raise UniquenessError( 'Input RemoteData is child of {} ' 'calculation{}, while it should have a single parent' ''.format(n_parents, '' if n_parents == 0 else 's')) parent_calc = parent_calcs[0].node parent_calc_class = parent_calc.process_class has_parent = True # check that it is a valid parent # self._check_valid_parent(parent_calc) # if inpgen calc do # check if folder from db given, or get folder from rep. # Parent calc does not has to be on the same computer. if parent_calc_class is FleurCalculation: new_comp = self.node.computer old_comp = parent_calc.computer if new_comp.uuid != old_comp.uuid: # don't copy files, copy files locally copy_remotely = False elif parent_calc_class is FleurinputgenCalculation: fleurinpgen = True new_comp = self.node.computer old_comp = parent_calc.computer if new_comp.uuid != old_comp.uuid: # don't copy files, copy files locally copy_remotely = False else: raise InputValidationError( "parent_calc, must be either an 'inpgen calculation' or" " a 'fleur calculation'.") # check existence of settings (optional) if 'settings' in self.inputs: settings = self.inputs.settings else: settings = None if settings is None: settings_dict = {} else: settings_dict = settings.get_dict() # check for for allowed keys, ignore unknown keys but warn. for key in settings_dict.keys(): if key not in self._settings_keys: self.logger.warning( 'settings dict key %s for Fleur calculation' 'not recognized, only %s are allowed.' '', key, str(self._settings_keys)) # TODO: Detailed check of FleurinpData # if certain files are there in fleurinpData # from where to copy # file copy stuff TODO check in fleur input if has_fleurinp: # add files belonging to fleurinp into local_copy_list allfiles = fleurinp.files for file1 in allfiles: local_copy_list.append((fleurinp.uuid, file1, file1)) modes = fleurinp.get_fleur_modes() # add files to mode_retrieved_filelist if modes['band']: mode_retrieved_filelist.append(self._BAND_FILE_NAME) mode_retrieved_filelist.append(self._BAND_GNU_FILE_NAME) if with_hdf5: mode_retrieved_filelist.append(self._BANDDOS_FILE_NAME) if modes['dos']: mode_retrieved_filelist.append(self._DOS_FILE_NAME) if with_hdf5: mode_retrieved_filelist.append(self._BANDDOS_FILE_NAME) if modes['relax']: # if l_f="T" retrieve relax.xml mode_retrieved_filelist.append(self._RELAX_FILE_NAME) if modes['ldau']: if with_hdf5: mode_retrieved_filelist.append( self._NMMPMAT_HDF5_FILE_NAME) else: mode_retrieved_filelist.append(self._NMMPMAT_FILE_NAME) if modes['greensf']: if with_hdf5: mode_retrieved_filelist.append( self._GREENSF_HDF5_FILE_NAME) if modes['cf_coeff']: if with_hdf5: mode_retrieved_filelist.append(self._CFDATA_HDF5_FILE_NAME) else: self.logger.warning( 'CF calculation without HDF5 not supported ' 'for automatic file retrieval.') if modes['force_theorem'] or modes['cf_coeff']: if 'remove_from_retrieve_list' not in settings_dict: settings_dict['remove_from_retrieve_list'] = [] if with_hdf5: settings_dict['remove_from_retrieve_list'].append( self._CDN_LAST_HDF5_FILE_NAME) else: settings_dict['remove_from_retrieve_list'].append( self._CDN1_FILE_NAME) # if noco, ldau, gw... # TODO: check from where it was copied, and copy files of its parent # if needed if has_parent: # copy necessary files # TODO: check first if file exist and throw a warning if not outfolder_uuid = parent_calc.outputs.retrieved.uuid self.logger.info('out folder path %s', outfolder_uuid) outfolder_filenames = [ x.name for x in parent_calc.outputs.retrieved.list_objects() ] has_nmmpmat_file = self._NMMPMAT_FILE_NAME in outfolder_filenames if (self._NMMPMAT_FILE_NAME in outfolder_filenames or \ self._NMMPMAT_HDF5_FILE_NAME in outfolder_filenames): if has_fleurinp: if 'n_mmp_mat' in fleurinp.files: self.logger.warning( 'Ignoring n_mmp_mat from fleurinp. ' 'There is already an n_mmp_mat file ' 'for the parent calculation') local_copy_list.remove( (fleurinp.uuid, 'n_mmp_mat', 'n_mmp_mat')) if fleurinpgen and (not has_fleurinp): for file1 in self._copy_filelist_inpgen: local_copy_list.append( (outfolder_uuid, os.path.join(file1), os.path.join(file1))) elif not fleurinpgen and (not has_fleurinp): # fleurCalc # need to copy inp.xml from the parent calc if with_hdf5: copylist = self._copy_scf_hdf elif has_nmmpmat_file: copylist = self._copy_scf_ldau_nohdf else: copylist = self._copy_scf for file1 in copylist: local_copy_list.append( (outfolder_uuid, file1[0], file1[1])) # TODO: get inp.xml from parent fleurinpdata; otherwise it will be doubled in rep elif fleurinpgen and has_fleurinp: # everything is taken care of pass elif not fleurinpgen and has_fleurinp: # inp.xml will be copied from fleurinp if with_hdf5: copylist = self._copy_scf_noinp_hdf elif has_nmmpmat_file: copylist = self._copy_scf_ldau_noinp_nohdf else: copylist = self._copy_scf_noinp for file1 in copylist: local_copy_list.append( (outfolder_uuid, file1[0], file1[1])) # TODO: not on same computer -> copy needed files from repository # if they are not there throw an error if copy_remotely: # on same computer. filelist_tocopy_remote = filelist_tocopy_remote + self._copy_filelist_scf_remote # from settings, user specified # TODO: check if list? for file1 in settings_dict.get('additional_remotecopy_list', []): filelist_tocopy_remote.append(file1) for file1 in settings_dict.get('remove_from_remotecopy_list', []): if file1 in filelist_tocopy_remote: filelist_tocopy_remote.remove(file1) for file1 in filelist_tocopy_remote: remote_copy_list.append( (parent_calc_folder.computer.uuid, os.path.join(parent_calc_folder.get_remote_path(), file1), self._get_output_folder)) self.logger.info('remote copy file list %s', str(remote_copy_list)) # create a JUDFT_WARN_ONLY file in the calculation folder with io.StringIO('/n') as handle: warn_only_filename = self._JUDFT_WARN_ONLY_INFO_FILE_NAME folder.create_file_from_filelike(handle, filename=warn_only_filename, mode='w') ########## MAKE CALCINFO ########### calcinfo = CalcInfo() calcinfo.uuid = self.uuid # Empty command line by default #cmdline_params = settings_dict.pop('CMDLINE', []) # calcinfo.cmdline_params = (list(cmdline_params) # + ["-in", self._INPUT_FILE_NAME]) self.logger.info('local copy file list %s', str(local_copy_list)) calcinfo.local_copy_list = local_copy_list calcinfo.remote_copy_list = remote_copy_list calcinfo.remote_symlink_list = remote_symlink_list # Retrieve by default the output file and the xml file retrieve_list = [] retrieve_list.append(self._OUTXML_FILE_NAME) if has_fleurinp: allfiles = fleurinp.files for file1 in allfiles: if file1.endswith('.xml'): retrieve_list.append(file1) else: retrieve_list.append(self._INPXML_FILE_NAME) retrieve_list.append(self._SHELLOUTPUT_FILE_NAME) retrieve_list.append(self._ERROR_FILE_NAME) retrieve_list.append(self._USAGE_FILE_NAME) # retrieve_list.append(self._TIME_INFO_FILE_NAME) # retrieve_list.append(self._OUT_FILE_NAME) if with_hdf5: retrieve_list.append(self._CDN_LAST_HDF5_FILE_NAME) else: retrieve_list.append(self._CDN1_FILE_NAME) for mode_file in mode_retrieved_filelist: if mode_file not in retrieve_list: retrieve_list.append(mode_file) self.logger.info('retrieve_list: %s', str(retrieve_list)) # user specific retrieve add_retrieve = settings_dict.get('additional_retrieve_list', []) self.logger.info('add_retrieve: %s', str(add_retrieve)) for file1 in add_retrieve: retrieve_list.append(file1) remove_retrieve = settings_dict.get('remove_from_retrieve_list', []) for file1 in remove_retrieve: if file1 in retrieve_list: retrieve_list.remove(file1) calcinfo.retrieve_list = [] for file1 in retrieve_list: calcinfo.retrieve_list.append(file1) codeinfo = CodeInfo() # should look like: codepath -xmlInput < inp.xml > shell.out 2>&1 walltime_sec = self.node.get_attribute('max_wallclock_seconds') cmdline_params = [] # , "-wtime", "{}".format(walltime_sec)]"-xml" cmdline_params.append('-minimalOutput') if with_hdf5: cmdline_params.append('-last_extra') cmdline_params.append('-no_send') if walltime_sec: walltime_min = int(max(1, walltime_sec / 60)) cmdline_params.append('-wtime') cmdline_params.append('{}'.format(int(walltime_min))) # user specific commandline_options for command in settings_dict.get('cmdline', []): cmdline_params.append(command) codeinfo.cmdline_params = list(cmdline_params) # + ["<", self._INPXML_FILE_NAME, # ">", self._SHELLOUTPUT_FILE_NAME, "2>&1"] codeinfo.code_uuid = code.uuid codeinfo.withmpi = self.node.get_attribute('withmpi') codeinfo.stdin_name = None # self._INPUT_FILE_NAME codeinfo.stdout_name = self._SHELLOUTPUT_FILE_NAME #codeinfo.join_files = True codeinfo.stderr_name = self._ERROR_FILE_NAME 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: code = inputdict.pop(self.get_linkname('code')) except KeyError: raise InputValidationError( "No code specified for this calculation") local_copy_list = [] remote_copy_list = [] remote_symlink_list = [] 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: qpoints = inputdict.pop(self.get_linkname('qpoints')) except KeyError: raise InputValidationError( "No qpoints specified for this calculation") if not isinstance(qpoints, KpointsData): raise InputValidationError("qpoints is not of type KpointsData") # Settings can be undefined, and defaults to an empty dictionary. # They will be used for any input that doen't fit elsewhere. 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') parent_calc_folder = inputdict.pop(self.get_linkname('parent_folder'), None) if parent_calc_folder is None: raise InputValidationError( "No parent calculation found, needed to " "compute phonons") # TODO: to be a PwCalculation is not sufficient: it could also be a nscf # calculation that is invalid for phonons if not isinstance(parent_calc_folder, RemoteData): raise InputValidationError("parent_calc_folder, if specified," "must be of type RemoteData") restart_flag = False # extract parent calculation parent_calcs = parent_calc_folder.get_inputs(node_type=JobCalculation) n_parents = len(parent_calcs) if n_parents != 1: raise UniquenessError("Input RemoteData is child of {} " "calculation{}, while it should have " "a single parent".format( n_parents, "" if n_parents == 0 else "s")) parent_calc = parent_calcs[0] # check that it is a valid parent self._check_valid_parent(parent_calc) if not isinstance(parent_calc, PwCalculation): restart_flag = True # Also, the parent calculation must be on the same computer new_comp = self.get_computer() old_comp = parent_calc.get_computer() if (not new_comp.uuid == old_comp.uuid): raise InputValidationError( "PhCalculation must be launched on the same computer" " of the parent: {}".format(old_comp.get_name())) # put by default, default_parent_output_folder = ./out try: default_parent_output_folder = parent_calc._OUTPUT_SUBFOLDER except AttributeError: try: default_parent_output_folder = parent_calc._get_output_folder() except AttributeError: raise InputValidationError("Parent of PhCalculation does not " "have a default output subfolder") #os.path.join( # parent_calc.OUTPUT_SUBFOLDER, # '{}.save'.format(parent_calc.PREFIX)) parent_calc_out_subfolder = settings_dict.pop( 'PARENT_CALC_OUT_SUBFOLDER', default_parent_output_folder) # Here, there should be no other inputs if inputdict: raise InputValidationError("The following input data nodes are " "unrecognized: {}".format( inputdict.keys())) ############################## # END OF INITIAL INPUT CHECK # ############################## # I put the first-level keys as uppercase (i.e., namelist and card names) # and the second-level keys as lowercase # (deeper levels are unchanged) input_params = _uppercase_dict(parameters.get_dict(), dict_name='parameters') input_params = { k: _lowercase_dict(v, dict_name=k) for k, v in input_params.iteritems() } prepare_for_d3 = settings_dict.pop('PREPARE_FOR_D3', False) if prepare_for_d3: self._blocked_keywords += [('INPUTPH', 'fildrho'), ('INPUTPH', 'drho_star%open'), ('INPUTPH', 'drho_star%ext'), ('INPUTPH', 'drho_star%dir')] # I remove unwanted elements (for the moment, instead, I stop; to change when # we setup a reasonable logging) for nl, flag in self._blocked_keywords: if nl in input_params: if flag in input_params[nl]: raise InputValidationError( "You cannot specify explicitly the '{}' flag in the '{}' " "namelist or card.".format(flag, nl)) # Set some variables (look out at the case! NAMELISTS should be uppercase, # internal flag names must be lowercase) if 'INPUTPH' not in input_params: raise InputValidationError( "No namelist INPUTPH found in input" ) # I cannot decide what to do in the calculation input_params['INPUTPH']['outdir'] = self._OUTPUT_SUBFOLDER input_params['INPUTPH']['iverbosity'] = 1 # in human language 1=high input_params['INPUTPH']['prefix'] = self._PREFIX input_params['INPUTPH'][ 'fildyn'] = self._OUTPUT_DYNAMICAL_MATRIX_PREFIX if prepare_for_d3: input_params['INPUTPH']['fildrho'] = self._DRHO_PREFIX input_params['INPUTPH']['drho_star%open'] = True input_params['INPUTPH']['drho_star%ext'] = self._DRHO_STAR_EXT input_params['INPUTPH']['drho_star%dir'] = self._FOLDER_DRHO # qpoints part try: mesh, offset = qpoints.get_kpoints_mesh() if any([i != 0. for i in offset]): raise NotImplementedError( "Computation of phonons on a mesh with" " non zero offset is not implemented, at the level of ph.x" ) input_params["INPUTPH"]["ldisp"] = True input_params["INPUTPH"]["nq1"] = mesh[0] input_params["INPUTPH"]["nq2"] = mesh[1] input_params["INPUTPH"]["nq3"] = mesh[2] postpend_text = None except AttributeError: # this is the case where no mesh was set. Maybe it's a list try: list_of_points = qpoints.get_kpoints(cartesian=True) except AttributeError as e: # In this case, there are no info on the qpoints at all raise InputValidationError( "Neither a qpoints mesh or a valid " "list of qpoints was found in input", e.message) # change to 2pi/a coordinates lattice_parameter = numpy.linalg.norm(qpoints.cell[0]) list_of_points *= lattice_parameter / (2. * numpy.pi) # add here the list of point coordinates if len(list_of_points) > 1: input_params["INPUTPH"]["qplot"] = True input_params["INPUTPH"]["ldisp"] = True postpend_text = "{}\n".format(len(list_of_points)) for points in list_of_points: postpend_text += "{} {} {} 1\n".format(*points) # Note: the weight is fixed to 1, because ph.x calls these # things weights but they are not such. If they are going to # exist with the meaning of weights, they will be supported else: input_params["INPUTPH"]["ldisp"] = False postpend_text = "" for points in list_of_points: postpend_text += "{} {} {}\n".format(*points) # =================== NAMELISTS ======================== # customized namelists, otherwise not present in the distributed ph code try: namelists_toprint = settings_dict.pop('NAMELISTS') if not isinstance(namelists_toprint, list): raise InputValidationError( "The 'NAMELISTS' value, if specified in the settings input " "node, must be a list of strings") except KeyError: # list of namelists not specified in the settings; do automatic detection namelists_toprint = self._compulsory_namelists input_filename = tempfolder.get_abs_path(self._INPUT_FILE_NAME) # create a folder for the dynamical matrices if not restart_flag: # if it is a restart, it will be copied over tempfolder.get_subfolder(self._FOLDER_DYNAMICAL_MATRIX, create=True) with open(input_filename, 'w') as infile: infile.write('AiiDA calculation\n') for namelist_name in namelists_toprint: infile.write("&{0}\n".format(namelist_name)) # namelist content; set to {} if not present, so that we leave an # empty namelist namelist = input_params.pop(namelist_name, {}) for k, v in sorted(namelist.iteritems()): infile.write(get_input_data_text(k, v)) infile.write("/\n") # add list of qpoints if required if postpend_text is not None: infile.write(postpend_text) #TODO: write nat_todo if input_params: raise InputValidationError( "The following namelists are specified in input_params, but are " "not valid namelists for the current type of calculation: " "{}".format(",".join(input_params.keys()))) # copy the parent scratch symlink = settings_dict.pop('PARENT_FOLDER_SYMLINK', _default_symlink_usage) # a boolean if symlink: # I create a symlink to each file/folder in the parent ./out tempfolder.get_subfolder(self._OUTPUT_SUBFOLDER, create=True) remote_symlink_list.append( (parent_calc_folder.get_computer().uuid, os.path.join(parent_calc_folder.get_remote_path(), parent_calc_out_subfolder, "*"), self._OUTPUT_SUBFOLDER)) # I also create a symlink for the ./pseudo folder # TODO: suppress this when the recover option of QE will be fixed # (bug when trying to find pseudo file) remote_symlink_list.append( (parent_calc_folder.get_computer().uuid, os.path.join(parent_calc_folder.get_remote_path(), self._get_pseudo_folder()), self._get_pseudo_folder())) #pass else: # here I copy the whole folder ./out remote_copy_list.append( (parent_calc_folder.get_computer().uuid, os.path.join(parent_calc_folder.get_remote_path(), parent_calc_out_subfolder), self._OUTPUT_SUBFOLDER)) # I also copy the ./pseudo folder # TODO: suppress this when the recover option of QE will be fixed # (bug when trying to find pseudo file) remote_copy_list.append( (parent_calc_folder.get_computer().uuid, os.path.join(parent_calc_folder.get_remote_path(), self._get_pseudo_folder()), self._get_pseudo_folder())) if restart_flag: # in this case, copy in addition also the dynamical matrices if symlink: remote_symlink_list.append( (parent_calc_folder.get_computer().uuid, os.path.join(parent_calc_folder.get_remote_path(), self._FOLDER_DYNAMICAL_MATRIX), self._FOLDER_DYNAMICAL_MATRIX)) else: # copy the dynamical matrices remote_copy_list.append( (parent_calc_folder.get_computer().uuid, os.path.join(parent_calc_folder.get_remote_path(), self._FOLDER_DYNAMICAL_MATRIX), '.')) # no need to copy the _ph0, since I copied already the whole ./out folder # 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() calcinfo.uuid = self.uuid # Empty command line by default cmdline_params = settings_dict.pop('CMDLINE', []) calcinfo.local_copy_list = local_copy_list calcinfo.remote_copy_list = remote_copy_list calcinfo.remote_symlink_list = remote_symlink_list codeinfo = CodeInfo() codeinfo.cmdline_params = (list(cmdline_params) + ["-in", self._INPUT_FILE_NAME]) codeinfo.stdout_name = self._OUTPUT_FILE_NAME codeinfo.code_uuid = code.uuid calcinfo.codes_info = [codeinfo] # 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(self._FOLDER_DYNAMICAL_MATRIX) calcinfo.retrieve_list.append( os.path.join(self._OUTPUT_SUBFOLDER, '_ph0', '{}.phsave'.format(self._PREFIX), self._OUTPUT_XML_TENSOR_FILE_NAME)) extra_retrieved = settings_dict.pop('ADDITIONAL_RETRIEVE_LIST', []) for extra in extra_retrieved: calcinfo.retrieve_list.append(extra) if settings_dict: 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 (without the Code!) """ local_copy_list = [] remote_copy_list = [] remote_symlink_list = [] 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: 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") if self._use_kpoints: 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") else: kpoints = None # 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") try: code = inputdict.pop(self.get_linkname('code')) except KeyError: raise InputValidationError("No code specified for this calculation") # Here, there should be no more parameters... if inputdict: raise InputValidationError("The following input data nodes are " "unrecognized: {}".format(inputdict.keys())) # Check structure, get species, check peudos kindnames = [k.name for k in 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) # 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]) ) ) input_filecontent, local_copy_pseudo_list = self._generate_PWCPinputdata(parameters,settings_dict,pseudos, structure,kpoints) local_copy_list += local_copy_pseudo_list input_filename = tempfolder.get_abs_path(self._INPUT_FILE_NAME) with open(input_filename, 'w') as infile: infile.write(input_filecontent) # 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._restart_copy_from), self._restart_copy_to )) else: # copy remote output dir, 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._restart_copy_from), self._restart_copy_to )) # 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') # Check if specific inputs for the ENVIRON module where specified environ_namelist = settings_dict.pop('ENVIRON', None) if environ_namelist is not None: if not isinstance(environ_namelist, dict): raise InputValidationError( "ENVIRON namelist should be specified as a dictionary") # We first add the environ flag to the command-line options (if not already present) try: if '-environ' not in settings_dict['CMDLINE']: settings_dict['CMDLINE'].append('-environ') except KeyError: settings_dict['CMDLINE'] = ['-environ'] # To create a mapping from the species to an incremental fortran 1-based index # we use the alphabetical order as in the inputdata generation mapping_species = {sp_name: (idx+1) for idx, sp_name in enumerate(sorted([kind.name for kind in structure.kinds]))} environ_input_filename = tempfolder.get_abs_path( self._ENVIRON_INPUT_FILE_NAME) with open(environ_input_filename, 'w') as environ_infile: environ_infile.write("&ENVIRON\n") for k, v in sorted(environ_namelist.iteritems()): environ_infile.write( get_input_data_text(k, v, mapping=mapping_species)) environ_infile.write("/\n") calcinfo = CalcInfo() calcinfo.uuid = self.uuid # Empty command line by default cmdline_params = settings_dict.pop('CMDLINE', []) # we commented calcinfo.stin_name and added it here in cmdline_params # in this way the mpirun ... pw.x ... < aiida.in # is replaced by mpirun ... pw.x ... -in aiida.in # in the scheduler, _get_run_line, if cmdline_params is empty, it # simply uses < calcinfo.stin_name calcinfo.cmdline_params = (list(cmdline_params) + ["-in", self._INPUT_FILE_NAME]) # calcinfo.stdin_name = self._INPUT_FILE_NAME # calcinfo.stdout_name = self._OUTPUT_FILE_NAME codeinfo = CodeInfo() codeinfo.cmdline_params = (list(cmdline_params) + ["-in", self._INPUT_FILE_NAME]) # calcinfo.stdin_name = self._INPUT_FILE_NAME codeinfo.stdout_name = self._OUTPUT_FILE_NAME codeinfo.code_uuid = code.uuid calcinfo.codes_info = [codeinfo] calcinfo.local_copy_list = local_copy_list calcinfo.remote_copy_list = remote_copy_list calcinfo.remote_symlink_list = remote_symlink_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(self._DATAFILE_XML) settings_retrieve_list = settings_dict.pop('ADDITIONAL_RETRIEVE_LIST', []) if settings_dict.pop('ALSO_BANDS', False): # To retrieve also the bands data settings_retrieve_list.append([os.path.join(self._OUTPUT_SUBFOLDER, self._PREFIX + '.save', 'K*[0-9]', 'eigenval*.xml'), '.', 2]) calcinfo.retrieve_list += settings_retrieve_list calcinfo.retrieve_list += self._internal_retrieve_list 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 pass if settings_dict: 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_inputdata_dict (without the Code!) """ local_copy_list = [] remote_copy_list = [] # Process the settings dictionary first # 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 to standardize the usage and # avoid ambiguities settings_dict = _uppercase_dict(settings.get_dict(), dict_name='settings') # Parameters 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") # Singlefile singlefile = inputdict.pop(self.get_linkname('singlefile'), None) if singlefile is not None: if not isinstance(singlefile, SinglefileData): raise InputValidationError("singlefile, if specified," "must be of type SinglefileData") # Parent calculation folder 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") # Code try: code = inputdict.pop(self.get_linkname('code')) except KeyError: raise InputValidationError( "No code specified for this calculation") # Here, there should be no more input data if inputdict: raise InputValidationError("The following input data nodes are " "unrecognized: {}".format( inputdict.keys())) ############################## # END OF INITIAL INPUT CHECK # ############################## input_params = parameters.get_dict() # = Preparation of input data ============================ input_filename = tempfolder.get_abs_path(self._INPUT_FILE_NAME) with open(input_filename, 'w') as infile: # Here print keys and values to file for k, v in sorted(input_params.iteritems()): infile.write(get_input_data_text(k, v)) # = Additional files ===================================== # Create the subfolder that will contain Gollum files tempfolder.get_subfolder(self._GFILES_SUBFOLDER, create=True) # Create the subfolder with the output data tempfolder.get_subfolder(self._OUTPUT_SUBFOLDER, create=True) if singlefile is not None: lfile = singlefile.get_file_abs_path().split("path/", 1)[1] local_copy_list.append((singlefile.get_file_abs_path(), os.path.join(self._GFILES_SUBFOLDER, lfile))) settings_local_copy_list = settings_dict.pop( 'ADDITIONAL_LOCAL_COPY_LIST', []) if settings_local_copy_list is not None: for k in settings_local_copy_list: lfile = k.split("/") lf = './' + lfile[len(lfile) - 1] local_copy_list.append((unicode(k), unicode(lf))) # = Parent calculation folder ============================ # The presence of a 'parent_calc_folder' input node signals # that we want to get something from there, as indicated in the # self._restart_copy_from attribute. In Gollum, partial.mat # # It will be copied to the current calculation's working folder 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._restart_copy_from), self._restart_copy_to)) # = Calculation information and parameters =============== calcinfo = CalcInfo() calcinfo.uuid = self.uuid cmdline_params = settings_dict.pop('CMDLINE', []) if cmdline_params: calcinfo.cmdline_params = list(cmdline_params) calcinfo.local_copy_list = local_copy_list calcinfo.remote_copy_list = remote_copy_list calcinfo.stdin_name = self._INPUT_FILE_NAME calcinfo.stdout_name = self._OUTPUT_FILE_NAME calcinfo.messages_name = self._MESSAGES_FILE_NAME calcinfo.oc_name = self._OC_FILE_NAME calcinfo.ou_name = self._OU_FILE_NAME calcinfo.od_name = self._OD_FILE_NAME calcinfo.tt_name = self._TT_FILE_NAME calcinfo.tu_name = self._TU_FILE_NAME calcinfo.td_name = self._TD_FILE_NAME # = Code information object ============================== codeinfo = CodeInfo() #codeinfo.cmdline_params = list(cmdline_params) codeinfo.cmdline_params = [cmdline_params] #codeinfo.stdin_name = self._INPUT_FILE_NAME codeinfo.stdout_name = self._OUTPUT_FILE_NAME codeinfo.messages_name = self._MESSAGES_FILE_NAME codeinfo.oc_name = self._OC_FILE_NAME codeinfo.ou_name = self._OU_FILE_NAME codeinfo.od_name = self._OD_FILE_NAME codeinfo.tt_name = self._TT_FILE_NAME codeinfo.tu_name = self._TU_FILE_NAME codeinfo.td_name = self._TD_FILE_NAME codeinfo.code_uuid = code.uuid calcinfo.codes_info = [codeinfo] # = Retrieve files ======================================= # Retrieve by default: the output file calcinfo.retrieve_list = [] calcinfo.retrieve_list.append(self._OUTPUT_FILE_NAME) calcinfo.retrieve_list.append(self._MESSAGES_FILE_NAME) calcinfo.retrieve_list.append(self._OC_FILE_NAME) calcinfo.retrieve_list.append(self._OU_FILE_NAME) calcinfo.retrieve_list.append(self._OD_FILE_NAME) calcinfo.retrieve_list.append(self._TT_FILE_NAME) calcinfo.retrieve_list.append(self._TU_FILE_NAME) calcinfo.retrieve_list.append(self._TD_FILE_NAME) # Any other files specified in the settings dictionary settings_retrieve_list = settings_dict.pop('ADDITIONAL_RETRIEVE_LIST', []) calcinfo.retrieve_list += settings_retrieve_list # = Copy additional remote files ========================= # Additional remote copy list for files like the EM or leads settings_remote_copy_list = settings_dict.pop( 'ADDITIONAL_REMOTE_COPY_LIST', []) calcinfo.remote_copy_list += settings_remote_copy_list if settings_remote_copy_list and parent_calc_folder is None: raise ValueError("The definition of a parent calculation folder " "is also needed when there is a remote copy list") for src_relative, dest_relative in settings_remote_copy_list: calcinfo.remote_copy_list.append([ parent_calc_folder.get_computer().uuid, src_relative, dest_relative ]) return calcinfo
def _prepare_for_submission(self, tempfolder, inputdict): """ This is the routine to be called when you make a fleur calculation Here should be checked if all the files are there to run fleur. And input files (inp.xml) can be modified. :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!) """ # from aiida.common.utils import get_unique_filename, get_suggestion local_copy_list = [] remote_copy_list = [] remote_symlink_list = [] mode_retrieved_filelist = [] #filelocal_copy_list = [] #filelist_tocopy = [] filelist_tocopy_remote = [] settings_dict = {} #fleur_calc = False #new_inp_file = False #ignore_mode = False has_fleurinp = False has_parent = False #restart_flag = False fleurinpgen = False copy_remotely = True ########################################## ############# INPUT CHECK ################ ########################################## try: code = inputdict.pop(self.get_linkname('code')) except KeyError: raise InputValidationError( "No code specified for this calculation") # a Fleur calc can be created from a fleurinpData alone #(then no parent is needed) all files are in the repo, but usually it is # a child of a inpgen calc or an other fleur calc (some or all files are # in a remote source). if the User has not changed something, the #calculation does not need theoretical a new FleurinpData it could use #the one from the parent, but the plug-in desgin is in a way that it has # to be there and it just copies files if changes occured.. fleurinp = inputdict.pop(self.get_linkname('fleurinpdata'), None) if fleurinp is None: #xml_inp_dict = {} has_fleurinp = False else: if not isinstance(fleurinp, FleurinpData): raise InputValidationError( "The FleurinpData node given is not of type FleurinpData.") has_fleurinp = True parent_calc_folder = inputdict.pop(self.get_linkname('parent_folder'), None) #print parent_calc_folder if parent_calc_folder is None: has_parent = False if not has_fleurinp: raise InputValidationError( "No parent calculation found and no fleurinp data " "given, need either one or both for a " "'fleurcalculation'.") else: # if not isinstance(parent_calc_folder, RemoteData): raise InputValidationError("parent_calc_folder, if specified," "must be of type RemoteData") # extract parent calculation parent_calcs = parent_calc_folder.get_inputs( node_type=JobCalculation) n_parents = len(parent_calcs) if n_parents != 1: raise UniquenessError( "Input RemoteData is child of {} " "calculation{}, while it should have a single parent" "".format(n_parents, "" if n_parents == 0 else "s")) parent_calc = parent_calcs[0] has_parent = True #print parent_calc # check that it is a valid parent #self._check_valid_parent(parent_calc) # if inpgen calc do # check if folder from db given, or get folder from rep. # Parent calc does not has to be on the same computer. if isinstance(parent_calc, FleurCalculation): new_comp = self.get_computer() old_comp = parent_calc.get_computer() if new_comp.uuid != old_comp.uuid: #dont copy files, copy files localy copy_remotely = False #raise InputValidationError( # "FleurCalculation must be launched on the same computer" # " of the parent: {}".format(old_comp.get_name())) elif isinstance(parent_calc, FleurinputgenCalculation): fleurinpgen = True new_comp = self.get_computer() old_comp = parent_calc.get_computer() if new_comp.uuid != old_comp.uuid: #dont copy files, copy files localy copy_remotely = False else: raise InputValidationError( "parent_calc, must be either an 'inpgen calculation' or" " a 'fleur calculation'.") # check existence of settings (optional) settings = inputdict.pop(self.get_linkname('settings'), None) #print('settings: {}'.format(settings)) if settings is None: settings_dict = {} else: if not isinstance(settings, ParameterData): raise InputValidationError( "settings, if specified, must be of " "type ParameterData") else: settings_dict = settings.get_dict() #check for for allowed keys, ignor unknown keys but warn. for key in settings_dict.keys(): if key not in self._settings_keys: #TODO warrning self.logger.info("settings dict key {} for Fleur calculation" "not reconized, only {} are allowed." "".format(key, self._settings_keys)) #print settings_dict # Here, there should be no other inputs if inputdict: raise InputValidationError("The following input data nodes are " "unrecognized: {}".format( inputdict.keys())) #TODO: Detailed check of FleurinpData # if certain files are there in fleurinpData. # from where to copy ############################## # END OF INITIAL INPUT CHECK # # file copy stuff TODO check in fleur input if has_fleurinp: self._DEFAULT_INPUT_FILE = fleurinp.get_file_abs_path( self._INPXML_FILE_NAME) #local_copy_list.append(( # fleurinp.get_file_abs_path(self._INPXML_FILE_NAME), # self._INPXML_FILE_NAME)) #copy ALL files from inp.xml allfiles = fleurinp.files for file1 in allfiles: local_copy_list.append( (fleurinp.get_file_abs_path(file1), file1)) modes = fleurinp.get_fleur_modes() # add files to mode_retrieved_filelist if modes['band']: mode_retrieved_filelist.append(self._BAND_FILE_NAME) mode_retrieved_filelist.append(self._BAND_GNU_FILE_NAME) if modes['dos']: mode_retrieved_filelist.append(self._DOS_FILE_NAME) if modes['forces']: print 'FORCES!!!' mode_retrieved_filelist.append(self._NEW_XMlINP_FILE_NAME) mode_retrieved_filelist.append(self._FORCE_FILE_NAME) if modes['ldau']: mode_retrieved_filelist.append(self._NMMPMAT_FILE_NAME) #if noco, ldau, gw... # TODO: check from where it was copied, and copy files of its parent # if needed #self.logger.info("@@@@@@@@@@@@@@@@@@@@@@@@has_parent {}".format(has_parent)) if has_parent: # copy the right files #TODO check first if file, exist and throw # warning, now this will throw an error outfolderpath = parent_calc.out.retrieved.folder.abspath self.logger.info("out folder path {}".format(outfolderpath)) #print outfolderpath if fleurinpgen and (not has_fleurinp): for file1 in self._copy_filelist_inpgen: local_copy_list.append( (os.path.join(outfolderpath, 'path', file1), os.path.join(file1))) elif not fleurinpgen and (not has_fleurinp): # fleurCalc for file1 in self._copy_filelist_scf: local_copy_list.append( (os.path.join(outfolderpath, 'path', file1), os.path.join(file1))) filelist_tocopy_remote = filelist_tocopy_remote # + self._copy_filelist_scf_remote #TODO get inp.xml from parent fleurinpdata, since otherwise it will be doubled in repo elif fleurinpgen and has_fleurinp: # everything is taken care of pass elif not fleurinpgen and has_fleurinp: # input file is already taken care of for file1 in self._copy_filelist_scf1: local_copy_list.append( (os.path.join(outfolderpath, 'path', file1), os.path.join(file1))) filelist_tocopy_remote = filelist_tocopy_remote # + self._copy_filelist_scf_remote # TODO not on same computer -> copy needed files from repository, # if they are not there, throw error if copy_remotely: # on same computer. #print('copy files remotely') # from fleurmodes if modes['pot8']: filelist_tocopy_remote = filelist_tocopy_remote + self._copy_filelist_scf_remote filelist_tocopy_remote.append(self._POT_FILE_NAME) # #filelist_tocopy_remote.append(self._POT2_FILE_NAME) elif modes['dos']: pass elif modes['band']: pass else: filelist_tocopy_remote = filelist_tocopy_remote + self._copy_filelist_scf_remote # from settings, user specified #TODO check if list? for file1 in settings_dict.get('additional_remotecopy_list', []): filelist_tocopy_remote.append(file1) for file1 in settings_dict.get('remove_from_remotecopy_list', []): if file1 in filelist_tocopy_remote: filelist_tocopy_remote.remove(file1) for file1 in filelist_tocopy_remote: remote_copy_list.append( (parent_calc_folder.get_computer().uuid, os.path.join(parent_calc_folder.get_remote_path(), file1), self._OUTPUT_FOLDER)) #print remote_copy_list #self.logger.info("remote copy file list {}".format(remote_copy_list)) ########## MAKE CALCINFO ########### calcinfo = CalcInfo() calcinfo.uuid = self.uuid # Empty command line by default #cmdline_params = settings_dict.pop('CMDLINE', []) #calcinfo.cmdline_params = (list(cmdline_params) # + ["-in", self._INPUT_FILE_NAME]) #print local_copy_list self.logger.info("local copy file list {}".format(local_copy_list)) calcinfo.local_copy_list = local_copy_list calcinfo.remote_copy_list = remote_copy_list #(remotemachinename, remoteabspath, relativedestpath) calcinfo.remote_symlink_list = remote_symlink_list #calcinfo.stdout_name = self._OUTPUT_FILE_NAME # Retrieve by default the output file and the xml file retrieve_list = [] retrieve_list.append(self._OUTXML_FILE_NAME) retrieve_list.append(self._INPXML_FILE_NAME) #calcinfo.retrieve_list.append(self._OUTPUT_FILE_NAME) retrieve_list.append(self._SHELLOUTPUT_FILE_NAME) retrieve_list.append(self._CDN1_FILE_NAME) retrieve_list.append(self._ERROR_FILE_NAME) #calcinfo.retrieve_list.append(self._TIME_INFO_FILE_NAME) retrieve_list.append(self._OUT_FILE_NAME) #calcinfo.retrieve_list.append(self._INP_FILE_NAME) #calcinfo.retrieve_list.append(self._ENPARA_FILE_NAME) #calcinfo.retrieve_list.append(self._SYMOUT_FILE_NAME) #calcinfo.retrieve_list.append(self._KPTS_FILE_NAME) # if certain things are modefied, flags set, #other files should be retrieved, example DOS.x... #print "mode_retrieved_filelist", repr(mode_retrieved_filelist) for mode_file in mode_retrieved_filelist: retrieve_list.append(mode_file) #print('retrieve_list: {}'.format(retrieve_list)) # user specific retrieve add_retrieve = settings_dict.get('additional_retrieve_list', []) #print('add_retrieve: {}'.format(add_retrieve)) for file1 in add_retrieve: retrieve_list.append(file1) remove_retrieve = settings_dict.get('remove_from_retrieve_list', []) for file1 in remove_retrieve: if file1 in retrieve_list: retrieve_list.remove(file1) calcinfo.retrieve_list = [] for file1 in retrieve_list: calcinfo.retrieve_list.append(file1) codeinfo = CodeInfo() # should look like: codepath -xmlInput < inp.xml > shell.out 2>&1 walltime_sec = self.get_max_wallclock_seconds() #self.logger.info("!!!!!!!!!!!!!!!!!!! walltime_sec : {}" # "".format(walltime_sec)) cmdline_params = ["-xml"] #, "-wtime", "{}".format(walltime_sec)] #walltime_sec = self.get_max_wallclock_seconds() #print('walltime: {}'.format(walltime_sec)) if walltime_sec: walltime_min = max(1, walltime_sec / 60) cmdline_params.append("-wtime") cmdline_params.append("{}".format(walltime_min)) # user specific commandline_options for command in settings_dict.get('cmdline', []): cmdline_params.append(command) codeinfo.cmdline_params = list(cmdline_params) # + ["<", self._INPXML_FILE_NAME, # ">", self._SHELLOUTPUT_FILE_NAME, "2>&1"] codeinfo.code_uuid = code.uuid codeinfo.withmpi = self.get_withmpi() codeinfo.stdin_name = self._INPUT_FILE_NAME codeinfo.stdout_name = self._SHELLOUTPUT_FILE_NAME #codeinfo.join_files = True codeinfo.stderr_name = self._ERROR_FILE_NAME calcinfo.codes_info = [codeinfo] ''' # not needed in new version if fleurinpgen:# execute twice, as long start density stop codeinfo1 = CodeInfo() cmdline_params = ["-xmlInput"] codeinfo1.cmdline_params = list(cmdline_params) # + ["<", self._INPUT_FILE_NAME])#, # ">",self._OUTPUT_FILE_NAME] codeinfo1.code_uuid = code.uuid codeinfo1.withmpi = self.get_withmpi() codeinfo1.stdin_name = self._INPUT_FILE_NAME codeinfo1.stdout_name = self._SHELLOUTPUT_FILE_NAME calcinfo.codes_info.append(codeinfo1) if settings_dict: 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): import numpy as np try: struct = inputdict.pop(self.get_linkname('structure')) except KeyError: raise InputValidationError("no structure is specified for this calculation") if not isinstance(struct, StructureData): raise InputValidationError("struct is not of type StructureData") try: code = inputdict.pop(self.get_linkname('code')) except KeyError: raise InputValidationError("no code is specified for this calculation") atoms = struct.get_ase() 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") par = parameters.get_dict() charge= par.pop('CHARGE', '0') cpus=par.pop ('CPUS','1') mult= par.pop(' MULTIPLICITY', '1') basis = par.pop('BASIS','6-31G') jobtype = par.pop('JOB_TYPE','SP') dft_d=par.pop('DFT_D','FALSE') total=par.pop('MEM_TOTAL', '7500') method=par.pop('METHOD', 'HF') convergence=par.pop('SCF_CONVERGENCE', 'Tight') title=par.pop('TITLE', 'A generic title') cycles=par.pop('SCF_MAX_CYCLES', '50') integral=par.pop('INTEGRAL','Integral(Grid=UltraFine)') # Note this default will generated a pruned a grid with 99,590 points unrestricted=par.pop('UNRESTRICTED', 'R') add_cell = par.pop('add_cell',False) input_filename = tempfolder.get_abs_path(self._DEFAULT_INPUT_FILE) with open(input_filename,'w') as f: f.write('%Mem={}mb\n'.format(total)) if method == 'PM6': f.write('#p {} {} \n'.format(method,jobtype)) else: f.write('#p {}{}/{} {} {} SCF={}\n'.format(unrestricted,method,basis,jobtype,integral,convergence)) if dft_d != 'FALSE': f.write('EmpiricalDispersion={}\n'.format(dft_d)) f.write('\n') f.write('{}\n'.format(title)) f.write('\n') f.write('{} {} \n'.format(charge,mult)) for i,atom_type in enumerate(atoms.get_chemical_symbols()): x='{0:.7f}'.format(float(atoms.get_positions()[i][0])) y='{0:.7f}'.format(float(atoms.get_positions()[i][1])) z='{0:.7f}'.format(float(atoms.get_positions()[i][2])) f.write(' {} {} {} {} \n'.format(atom_type,x,y,z)) f.write('\n') f.flush() self._default_commandline_params = [] 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.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): import numpy as np try: struct = inputdict.pop(self.get_linkname('structure')) except KeyError: raise InputValidationError( "no structure is specified for this calculation") if not isinstance(struct, StructureData): raise InputValidationError("struct is not of type StructureData") try: code = inputdict.pop(self.get_linkname('code')) except KeyError: raise InputValidationError( "no code is specified for this calculation") atoms = struct.get_ase() lat_lengths = [ (atoms.cell[0]**2).sum()**0.5, (atoms.cell[1]**2).sum()**0.5, (atoms.cell[2]**2).sum()**0.5, ] lat_angles = np.arccos([ np.vdot(atoms.cell[1], atoms.cell[2]) / lat_lengths[1] / lat_lengths[2], np.vdot(atoms.cell[0], atoms.cell[2]) / lat_lengths[0] / lat_lengths[2], np.vdot(atoms.cell[0], atoms.cell[1]) / lat_lengths[0] / lat_lengths[1], ]) / np.pi * 180 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") par = parameters.get_dict() abbreviation = par.pop('abbreviation', 'aiida_calc') title = par.pop('title', 'AiiDA NWChem calculation') basis = par.pop('basis', None) task = par.pop('task', 'scf') add_cell = par.pop('add_cell', True) if basis is None: basis = dict() for atom_type in set(atoms.get_chemical_symbols()): basis[atom_type] = 'library 6-31g' input_filename = tempfolder.get_abs_path(self._DEFAULT_INPUT_FILE) with open(input_filename, 'w') as f: f.write('start {}\ntitle "{}"\n\n'.format(abbreviation, title)) f.write('geometry units au\n') if add_cell: f.write(' system crystal\n') f.write(' lat_a {}\n lat_b {}\n lat_c {}\n'.format( *lat_lengths)) f.write(' alpha {}\n beta {}\n gamma {}\n'.format( *lat_angles)) f.write(' end\n') for i, atom_type in enumerate(atoms.get_chemical_symbols()): f.write(' {} {} {} {}\n'.format( atom_type, atoms.get_positions()[i][0], atoms.get_positions()[i][1], atoms.get_positions()[i][2])) f.write('end\nbasis\n') for atom_type, b in basis.iteritems(): f.write(' {} {}\n'.format(atom_type, b)) f.write('end\ntask {}\n'.format(task)) 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): inputs = dict(parameters=self.__prepare_parameters(inputdict), force_field=self.__prepare_force_field(inputdict), output=dict(population='progress.npy', append=False, best='best.yml'), structures=[]) species = inputs.get('force_field').get('species') copy_list = [(tempfolder.get_abs_path('aiida.yml'), '.')] tempfolder.get_subfolder('./data', create=True) formulas = {} for key in inputdict: if 'structure' in key: uuid = key.replace('structure_', '') pmg = inputdict.get(key).get_pymatgen() formula = pmg.formula.replace(' ', '') formulas.setdefault(formula, 0) filename = tempfolder.get_abs_path('./data/%s.%03d.npy' % (formula, formulas.get(formula))) formulas[formula] += 1 with open(filename, 'wb') as file: data = np.array([ ( species.index(str(site.specie)), 0 if isinstance(site.specie, Element) else site.specie.oxi_state, site.coords[0], site.coords[1], site.coords[2], forces[0], forces[1], forces[2] ) for site, forces in zip(pmg, inputdict.get('forces_%s' % uuid).get_array('forces')) ]) np.save(file, pmg.lattice.matrix) np.save(file, data) np.save(file, inputdict.get('energy_%s' % uuid).value) copy_list += [ (str(filename), './data') ] for formula, count in formulas.items(): inputs.get('structures').append(dict( format=str('./data/%s.%%03d.npy' % formula), range=[0, count] )) with open(tempfolder.get_abs_path('aiida.yml'), 'w') as f: f.write(yaml.dump(inputs)) calcinfo = CalcInfo() calcinfo.uuid = self.uuid calcinfo.local_copy_list = copy_list calcinfo.retrieve_list = [ 'progress.npy', 'best.yml' ] codeinfo = CodeInfo() codeinfo.code_uuid = inputdict.get('code').uuid codeinfo.cmdline_params = ['aiida.yml', 'genetic'] codeinfo.stdout_name = 'aiida.stdout' codeinfo.stderr_name = 'aiida.stderr' calcinfo.codes_info = [codeinfo] import os for root, dirnames, filenames in os.walk(tempfolder.abspath): print root, dirnames, filenames 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 = structure_to_poscar(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
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, ParameterData): raise InputValidationError("parameters not of type " "ParameterData") try: code = inputdict.pop(self.get_linkname('code')) except KeyError: raise InputValidationError("No code specified for this " "calculation") try: electronic_calc_folder = inputdict.pop('electronic_calc_folder', None) except: pass if inputdict: raise ValidationError("Unknown inputs besides ParameterData") # 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: infile.write(input_render(input_dict)) # Prepare CalcInfo to be returned to aiida calcinfo = CalcInfo() calcinfo.uuid = self.uuid calcinfo.local_copy_list = [] calcinfo.remote_copy_list = [] calcinfo.remote_symlink_list = [] calcinfo.retrieve_list = [ self._OUTPUT_FILE_NAME, [self._ADDITIONAL_RETRIEVE_LIST, '.',0] ] # Electronic calc folder if electronic_calc_folder is not None: if not isinstance(electronic_calc_folder, RemoteData): msg = "electronic_calc_folder type not RemoteData" raise InputValidationError(msg) comp_uuid = electronic_calc_folder.get_computer().uuid remote_path = electronic_calc_folder.get_remote_path()+'/'+'aiida-ELECTRON_DENSITY-1_0.cube' symlink = (comp_uuid, remote_path, 'valence_density.cube') calcinfo.remote_symlink_list.append(symlink) codeinfo = CodeInfo() codeinfo.cmdline_params = [] 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. """ settings = {} if "settings" in self.inputs: settings = self.inputs.settings.get_dict() # validate that the structures and observables have the same keys struct_keys = set(self.inputs.structures.keys()) observe_keys = set(self.inputs.observables.keys()) if struct_keys != observe_keys: raise InputValidationError( "The structures and observables do not match: {} != {}".format( struct_keys, observe_keys ) ) # validate number of fitting variables vs number of observables if len(observe_keys) < self.inputs.potential.number_of_variables: raise InputValidationError( "The number of observables supplied ({}) " "is less than the number of variables required to be fit ({})".format( len(observe_keys), self.inputs.potential.number_of_variables ) ) content_lines, snames = create_input_lines( self.inputs.potential, self.inputs.structures, self.inputs.observables, observables=self.create_observable_map(settings), delta=settings.get("gradient_delta", None), dump_file=self.metadata.options.output_dump_file_name, ) with tempfolder.open(self.metadata.options.input_file_name, "w") as f: f.write(six.ensure_text("\n".join(content_lines))) with tempfolder.open("structure_names.json", "w") as handle: handle.write(six.ensure_text(json.dumps(snames))) # 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.metadata.options.output_main_file_name, self.metadata.options.output_stderr_file_name, self.metadata.options.output_dump_file_name, ] calcinfo.retrieve_temporary_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_inputs_dict (with the Code!) """ import StringIO from aiida.orm.data.parameter import ParameterData 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: if not isinstance(parameters_node, ParameterData): raise InputValidationError("'parameters' data is not of type ParameterData") parameters = dict(parameters_node.iterattrs()) template_node = inputdict.pop('template', None) if template_node is None: raise InputValidationError("No 'template' input data") if not isinstance(template_node, ParameterData): raise InputValidationError("'template' data is not of type ParameterData") template = dict(template_node.iterattrs()) 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', []) 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.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) 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: potential_data = inputdict.pop(self.get_linkname('potential')) except KeyError: raise InputValidationError("No potential specified for this " "calculation") if not isinstance(potential_data, ParameterData): raise InputValidationError("potential 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: code = inputdict.pop(self.get_linkname('code')) except KeyError: raise InputValidationError("no code is specified for this calculation") ############################## # END OF INITIAL INPUT CHECK # ############################## # =================== prepare the python input files ===================== potential_object = LammpsPotential(potential_data, structure, potential_filename=self._INPUT_POTENTIAL) structure_txt = generate_LAMMPS_structure(structure) input_txt = generate_LAMMPS_input(potential_object, structure_file=self._INPUT_STRUCTURE, trajectory_file=self._OUTPUT_TRAJECTORY_FILE_NAME,) potential_txt = potential_object.get_potential_file() # =========================== dump to file ============================= input_filename = tempfolder.get_abs_path(self._INPUT_FILE_NAME) with open(input_filename, 'w') as infile: infile.write(input_txt) structure_filename = tempfolder.get_abs_path(self._INPUT_STRUCTURE) with open(structure_filename, 'w') as infile: infile.write(structure_txt) if potential_txt is not None: potential_filename = tempfolder.get_abs_path(self._INPUT_POTENTIAL) with open(potential_filename, 'w') as infile: infile.write(potential_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 = [] calcinfo.retrieve_list.append(self._OUTPUT_TRAJECTORY_FILE_NAME) calcinfo.retrieve_list.append(self._OUTPUT_FILE_NAME) codeinfo = CodeInfo() codeinfo.cmdline_params = ['-in', self._INPUT_FILE_NAME] codeinfo.code_uuid = code.uuid codeinfo.withmpi = False calcinfo.codes_info = [codeinfo] return calcinfo
def prepare_for_submission(self, tempfolder): """Create the input files from the input nodes passed to this instance of the `CalcJob`. :param tempfolder: an `aiida.common.folders.Folder` to temporarily write files on disk :return: `aiida.common.datastructures.CalcInfo` instance """ # Check inputdict parameters = self.inputs.parameters if 'structure' in self.inputs: structure = self.inputs.structure found_structure = True else: found_structure = False vca_structure = False if found_structure: # for VCA: check if input structure and parameter node define VCA structure vca_structure = vca_check(structure, parameters) code = self.inputs.code # check if a parent folder containing a potential file (out_potential) is given if 'parent_KKR' in self.inputs: parent_calc_folder = self.inputs.parent_KKR found_parent = True else: found_parent = False if found_parent: # check if parent is either Voronoi or previous KKR calculation overwrite_potential, parent_calc = self._check_valid_parent( parent_calc_folder) #cross check if no structure was given and extract structure from parent if found_structure and not vca_structure: raise InputValidationError( "parent_KKR and structure found in input. " "Can only use either parent_KKR or structure in input.") else: structure_remote_KKR, voro_parent = self.find_parent_structure( parent_calc) if not vca_structure: structure = structure_remote_KKR else: # check consistency of input vca structure and structure from remote KKR folder # TODO check consistency pass else: overwrite_potential = False if not found_structure: raise InputValidationError( "Neither structure nor parent_KKR specified for this " "calculation") # check if overwrite potential is given explicitly if 'potential_overwrite' in self.inputs: potfile_overwrite = self.inputs.potential_overwrite has_potfile_overwrite = True else: has_potfile_overwrite = False if has_potfile_overwrite: overwrite_potential = True if not found_structure: raise InputValidationError( "Input structure needed for this calculation " "(using 'potential_overwrite' input node)") ################################### # Check for 2D case twoDimcheck, msg = check_2Dinput_consistency(structure, parameters) if not twoDimcheck: raise InputValidationError(msg) # Prepare inputcard from Structure and input parameter data input_file = tempfolder.open(self._INPUT_FILE_NAME, u'w') try: use_alat_input = parameters.get_dict().get('use_input_alat', False) natom, nspin, newsosol, warnings_write_inputcard = generate_inputcard_from_structure( parameters, structure, input_file, isvoronoi=True, vca_structure=vca_structure, use_input_alat=use_alat_input) except ValueError as e: raise InputValidationError( "Input Dict not consistent: {}".format(e)) # Decide what files to copy local_copy_list = [] if overwrite_potential: # copy the right files #TODO check first if file, exists and throw # warning, now this will throw an error if found_parent and self._is_KkrCalc(parent_calc): outfolder = parent_calc.outputs.retrieved # copy from remote folder copylist = [parent_calc._OUT_POTENTIAL] elif has_potfile_overwrite: outfolder = potfile_overwrite # copy from potential sfd copylist = [potfile_overwrite.filename] else: copylist = [] for file1 in copylist: filename = file1 if (found_parent or has_potfile_overwrite) and file1 == copylist[0]: filename = self._POTENTIAL_IN_OVERWRITE local_copy_list.append((outfolder.uuid, file1, filename)) # Prepare CalcInfo to be returned to aiida calcinfo = CalcInfo() calcinfo.uuid = self.uuid calcinfo.local_copy_list = local_copy_list calcinfo.remote_copy_list = [] calcinfo.retrieve_list = [ self._OUTPUT_FILE_NAME, self._ATOMINFO, self._RADII, self._SHAPEFUN, self._VERTICES, self._INPUT_FILE_NAME ] # pass on overwrite potential if this was given in input # (KkrCalculation checks if this file is there and takes this file instead of _OUT_POTENTIAL_voronoi # if given) if overwrite_potential: calcinfo.retrieve_list += [self._POTENTIAL_IN_OVERWRITE] else: calcinfo.retrieve_list += [self._OUT_POTENTIAL_voronoi] codeinfo = CodeInfo() codeinfo.cmdline_params = [] codeinfo.stdout_name = self._OUTPUT_FILE_NAME codeinfo.code_uuid = code.uuid calcinfo.codes_info = [codeinfo] 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): _dbs_accepted = { 'gw0': 'ndb.QP', 'HF_and_locXC': 'ndb.HF_and_locXC', } local_copy_list = [] remote_copy_list = [] remote_symlink_list = [] # Settings can be undefined, and defaults to an empty dictionary. # They will be used for any input that doen't fit elsewhere. settings = self.inputs.settings.get_dict() initialise = settings.pop('INITIALISE', None) if initialise is not None: if not isinstance(initialise, bool): raise InputValidationError("INITIALISE must be " " a boolean") copy_save = settings.pop('COPY_SAVE', None) if copy_save is not None: if not isinstance(copy_save, bool): raise InputValidationError("COPY_SAVE must be " " a boolean") copy_dbs = settings.pop('COPY_DBS', None) if copy_dbs is not None: if not isinstance(copy_dbs, bool): raise InputValidationError("COPY_DBS must be " " a boolean") restart_yambo = settings.pop('RESTART_YAMBO', None) if restart_yambo is not None: if not isinstance(restart_yambo, bool): raise InputValidationError("RESTART_YAMBO must be " " a boolean") parameters = self.inputs.parameters if not initialise: if not isinstance(parameters, Dict): raise InputValidationError("parameters is not of type Dict") parent_calc_folder = self.inputs.parent_folder main_code = self.inputs.code preproc_code = self.inputs.preprocessing_code parent_calc = take_calc_from_remote(parent_calc_folder) if parent_calc.process_type == 'aiida.calculations:yambo.yambo': yambo_parent = True else: yambo_parent = False # flags for yambo interfaces try: precode_param_dict = self.inputs.precode_parameters except: precode_param_dict = Dict(dict={}) # check the precode parameters given in input input_cmdline = settings.pop('CMDLINE', None) import re precode_params_list = [ ] #['cd aiida.save'] ##.format(parent_calc_folder._PREFIX) pattern = re.compile(r"(^\-)([a-zA-Z])") for key, value in six.iteritems(precode_param_dict.get_dict()): if re.search(pattern, key) is not None: if key == '-O' or key == '-H' or key == '-h' or key == '-F': raise InputValidationError( "Precode flag {} is not allowed".format(str(key))) else: if precode_param_dict[key] is True: precode_params_list.append(str(key)) elif precode_param_dict[key] is False: pass else: precode_params_list.append('{}'.format(str(key))) precode_params_list.append('{}'.format(str(value))) else: raise InputValidationError( "Wrong format of precode_parameters") # Adding manual cmdline input (e.g. for DB fragmentation) if input_cmdline is not None: precode_params_list = precode_params_list + input_cmdline # TODO: check that remote data must be on the same computer ############################## # END OF INITIAL INPUT CHECK # ############################## if not initialise: ################################################### # Prepare yambo input file ################################################### params_dict = parameters.get_dict() # extract boolean keys boolean_dict = { k: v for k, v in six.iteritems(params_dict) if isinstance(v, bool) } params_dict = { k: v for k, v in six.iteritems(params_dict) if k not in list(boolean_dict.keys()) } # reorganize the dictionary and create a list of dictionaries with key, value and units parameters_list = [] for k, v in six.iteritems(params_dict): if "_units" in k: continue units_key = "{}_units".format(k) try: units = params_dict[units_key] except KeyError: units = None this_dict = {} this_dict['key'] = k this_dict['value'] = v this_dict['units'] = units parameters_list.append(this_dict) input_filename = tempfolder.get_abs_path( self.metadata.options.input_filename) with open(input_filename, 'w') as infile: infile.write(self.metadata.options.logostring) for k, v in six.iteritems(boolean_dict): if v: infile.write("{}\n".format(k)) for this_dict in parameters_list: key = this_dict['key'] value = this_dict['value'] units = this_dict['units'] if isinstance(value, list): value_string = '' try: for v in value: value_string += " | ".join([str(_) for _ in v ]) + " |\n" except: value_string += " | ".join([str(_) for _ in value ]) + " |\n" the_string = "% {}\n {}".format(key, value_string) the_string += "%" else: the_value = '"{}"'.format(value) if isinstance( value, six.string_types) else '{}'.format(value) the_string = "{} = {}".format(key, the_value) if units is not None: the_string += " {}".format(units) infile.write(the_string + "\n") ############################################ # set copy of the parent calculation ############################################ try: parent_calc = parent_calc_folder.get_incoming().all_nodes()[ -1] #to load the node from a workchain... except: parent_calc = parent_calc_folder.get_incoming().get_node_by_label( 'remote_folder') if yambo_parent: if copy_save: try: remote_copy_list.append( (parent_calc_folder.computer.uuid, parent_calc_folder.get_remote_path() + "/SAVE/", './SAVE/')) except: remote_copy_list.append( (parent_calc_folder.computer.uuid, parent_calc_folder.get_remote_path() + "out/aiida.save/SAVE/", './SAVE/')) else: try: remote_symlink_list.append( (parent_calc_folder.computer.uuid, parent_calc_folder.get_remote_path() + "/SAVE/", './SAVE/')) except: remote_symlink_list.append( (parent_calc_folder.computer.uuid, parent_calc_folder.get_remote_path() + "out/aiida.save/SAVE/", './SAVE/')) if copy_dbs: remote_copy_list.append( (parent_calc_folder.computer.uuid, parent_calc_folder.get_remote_path() + "/aiida.out/", './aiida.out/')) if restart_yambo: remote_symlink_list.append( (parent_calc_folder.computer.uuid, parent_calc_folder.get_remote_path() + "/aiida.out/", './aiida.out/')) else: remote_copy_list.append(( parent_calc_folder.computer.uuid, os.path.join(parent_calc_folder.get_remote_path(), PwCalculation._OUTPUT_SUBFOLDER, "aiida.save", "*"), ##.format(parent_calc_folder._PREFIX) ".")) ############################################ # set Calcinfo ############################################ calcinfo = CalcInfo() calcinfo.uuid = self.uuid calcinfo.local_copy_list = [] calcinfo.remote_copy_list = remote_copy_list calcinfo.remote_symlink_list = remote_symlink_list # Retrieve by default the output file and the xml file calcinfo.retrieve_list = [] calcinfo.retrieve_list.append('r*') calcinfo.retrieve_list.append('l*') calcinfo.retrieve_list.append('o*') calcinfo.retrieve_list.append('LOG/l*_CPU_1') calcinfo.retrieve_list.append('LOG/l*_CPU_2') calcinfo.retrieve_list.append('*stderr*') #standard errors extra_retrieved = [] if initialise: # extra_retrieved.append('SAVE/'+_dbs_accepted['ns.db1']) pass else: for dbs in _dbs_accepted.keys(): db = boolean_dict.pop(dbs, False) if db: extra_retrieved.append('aiida.out/' + _dbs_accepted[dbs]) additional = settings.pop('ADDITIONAL_RETRIEVE_LIST', []) if additional: extra_retrieved.append(additional) for extra in extra_retrieved: calcinfo.retrieve_list.append(extra) from aiida.common.datastructures import CodeRunMode, CodeInfo # c1 = interface dft codes and yambo (ex. p2y or a2y) c1 = CodeInfo() c1.withmpi = True c1.cmdline_params = precode_params_list # c2 = yambo initialization c2 = CodeInfo() c2.withmpi = True c2.cmdline_params = [] c2.code_uuid = main_code.uuid # if the parent calculation is a yambo calculation skip the interface (c1) and the initialization (c2) if yambo_parent: try: parent_settings = _uppercase_dict( parent_calc.inputs.settings.get_dict(), dict_name='parent settings') parent_initialise = parent_settings['INITIALISE'] except KeyError: parent_initialise = False c1 = None if not parent_initialise: c2 = None else: c1.cmdline_params = precode_params_list c1.code_uuid = preproc_code.uuid # c3 = yambo calculation c3 = CodeInfo() c3.withmpi = True #c3.withmpi = self.get_withmpi() c3.cmdline_params = [ "-F", self.metadata.options.input_filename, \ '-J', self.metadata.options.output_filename, \ ] c3.code_uuid = main_code.uuid if initialise: c2 = None c3 = None #logic of the execution #calcinfo.codes_info = [c1, c2, c3] if not yambo_parent else [c3] if yambo_parent: if not parent_initialise: calcinfo.codes_info = [c3] else: calcinfo.codes_info = [c2, c3] elif initialise: calcinfo.codes_info = [c1] else: calcinfo.codes_info = [c1, c2, c3] calcinfo.codes_run_mode = CodeRunMode.SERIAL if settings: raise InputValidationError( "The following keys have been found in " "the settings input node, but were not understood: {}".format( ",".join(list(settings.keys())))) return calcinfo