def populate_restapi_database(clear_database_before_test): """Populates the database with a considerable set of nodes to test the restAPI""" # pylint: disable=unused-argument from aiida import orm struct_forcif = orm.StructureData().store() orm.StructureData().store() orm.StructureData().store() orm.Dict().store() orm.Dict().store() orm.CifData(ase=struct_forcif.get_ase()).store() orm.KpointsData().store() orm.FolderData().store() orm.CalcFunctionNode().store() orm.CalcJobNode().store() orm.CalcJobNode().store() orm.WorkFunctionNode().store() orm.WorkFunctionNode().store() orm.WorkChainNode().store()
def run_wannier(self): """ Run the Wannier90 calculation. """ wannier_inputs = self.exposed_inputs( Wannier90Calculation, namespace='wannier' ) wannier_parameters = wannier_inputs['parameters'].get_dict() wannier_parameters.setdefault('write_hr', True) wannier_parameters.setdefault('write_xyz', True) wannier_parameters.setdefault('use_ws_distance', True) self.report("Running Wannier90 calculation.") wannier_inputs['parameters'] = orm.Dict(dict=wannier_parameters) wannier_inputs['settings'] = orm.Dict( dict=ChainMap( wannier_inputs.get('settings', orm.Dict()).get_dict(), {"additional_retrieve_list": ['*.win']} ) ) return ToContext( wannier_calc=self.submit( Wannier90Calculation, structure=self.inputs.structure, **wannier_inputs ) )
def test_cell_with_spin(gen_instance, sto_calc_inputs): """Test input geneation with spins""" import aiida.orm as orm from aiida.common.exceptions import InputValidationError sto_calc_inputs.settings = orm.Dict(dict={'SPINS': [1, 1, 1, 1, 1]}) gen_instance.inputs = sto_calc_inputs gen_instance.prepare_inputs() positions = gen_instance.cell_file['POSITIONS_ABS'] for i in range(5): assert positions[i].endswith(" SPIN=1.000 ") # Test non-collinear spins sto_calc_inputs.settings = orm.Dict(dict={'SPINS': [[1., 1., 1.]] * 5}) gen_instance.prepare_inputs() positions = gen_instance.cell_file['POSITIONS_ABS'] for i in range(5): assert positions[i].endswith(" SPIN=( 1.000000 1.000000 1.000000 ) ") # Test spin consistency checks param = sto_calc_inputs.parameters.get_dict() param['PARAM']['spin'] = 1.0 # This is wrong sto_calc_inputs.parameters = orm.Dict(dict=param) with pytest.raises(InputValidationError): gen_instance.prepare_inputs() # Summation of spins for non-collinear spins param['PARAM']['spin'] = 3**(1 / 2) * 5 sto_calc_inputs.parameters = orm.Dict(dict=param) gen_instance.prepare_inputs()
def generate_sub_input(inputs, namespace, task): """ Generate inputs for tasks, merge those in the namespace from those given in the inputs """ if namespace in self.inputs: self.report( 'Taking input from the {} namespace'.format(namespace)) bands_inputs = AttributeDict( self.exposed_inputs(base_work, namespace=namespace)) else: bands_inputs = AttributeDict( {'calc': { 'parameters': orm.Dict(dict={'task': task}) }}) # Special treatment - combine the paramaters parameters = inputs.calc.parameters.get_dict() bands_parameters = bands_inputs.calc.parameters.get_dict() nested_update(parameters, bands_parameters) # Make sure the task name is correct nested_update(parameters, {'task': self._task_name}) # Update the SCF name space with those from the bands name space nested_update(inputs, bands_inputs) # Apply the new parameters inputs.calc.parameters = orm.Dict(dict=parameters) return inputs
def generate_inputs_default(): """Return only those inputs that the parser will expect to be there.""" a = 5.43 structure = orm.StructureData( cell=[[a / 2., a / 2., 0], [a / 2., 0, a / 2.], [0, a / 2., a / 2.]]) structure.append_atom(position=(0., 0., 0.), symbols='Si', name='Si1') structure.append_atom(position=(a / 4., a / 4., a / 4.), symbols='Si', name='Si2') structure.store() parameters = { 'CONTROL': { 'calculation': 'scf' }, 'SYSTEM': { 'ecutrho': 240.0, 'ecutwfc': 30.0 } } kpoints = orm.KpointsData() kpoints.set_cell_from_structure(structure) kpoints.set_kpoints_mesh_from_density(0.15) return AttributeDict({ 'structure': structure, 'kpoints': kpoints, 'parameters': orm.Dict(dict=parameters), 'settings': orm.Dict() })
def generate_inputs(): """Minimal input for pw2wannier90 calculations.""" basepath = os.path.dirname(os.path.abspath(__file__)) nnkp_filepath = os.path.join(basepath, 'fixtures', 'pw2wannier90', 'inputs', 'aiida.nnkp') parameters = { 'inputpp': { 'write_amn': False, 'write_mmn': False, 'write_unk': False, 'scdm_proj': True, 'scdm_entanglement': 'isolated', } } settings = {'ADDITIONAL_RETRIEVE_LIST': ['*.amn', '*.mmn', '*.eig']} # Since we don't actually run pw2wannier.x, we only pretend to have the output folder # of a parent pw.x calculation. The nnkp file, instead, is real. inputs = { 'parent_folder': orm.FolderData().store(), 'nnkp_file': orm.SinglefileData(file=nnkp_filepath).store(), 'parameters': orm.Dict(dict=parameters), 'settings': orm.Dict(dict=settings), } return AttributeDict(inputs)
def test_plot_fleur_multiple_wc_matplotlib(aiida_profile, read_dict_from_file): """test if plot fleur can visualize a multiple workchain output node, Fleur calcjob output nodes """ from matplotlib.axes import Axes aiida_path = os.path.dirname(aiida_fleur.__file__) out_node_path = os.path.join(aiida_path, '../tests/files/jsons/fleur_outputpara.json') out_node_scf_path = os.path.join( aiida_path, '../tests/files/jsons/fleur_output_scf_wc_para.json') out_node_eos_path = os.path.join( aiida_path, '../tests/files/jsons/fleur_output_eos_wc_para.json') fleur_outputnode = orm.Dict(dict=read_dict_from_file(out_node_path), label='output_para') p_calc = plot_fleur([fleur_outputnode, fleur_outputnode], show=False) assert isinstance(p_calc, list) assert p_calc[0] == [] # isinstance(p_scf[0], plt.figure) scf_output = orm.Dict(dict=read_dict_from_file(out_node_scf_path), label='output_scf_wc_para') p_scf = plot_fleur([scf_output, scf_output], show=False) assert isinstance(p_scf, list) # assert isinstance(p_scf[0][0], type(Axes)) # return 2 plots eos_output = orm.Dict(dict=read_dict_from_file(out_node_eos_path), label='output_eos_wc_para') p_eos = plot_fleur([eos_output, eos_output], show=False) assert isinstance(p_eos, list)
def test_plot_fleur_single_wc_bokeh(aiida_profile, read_dict_from_file): """test if plot fleur can visualize a single workchain with bokeh backend""" try: #bokeh is not a prerequisite of Aiida-Fleur, might become of masci-tools from bokeh.layouts import column # gridplot except ImportError: return aiida_path = os.path.dirname(aiida_fleur.__file__) out_node_path = os.path.join(aiida_path, '../tests/files/jsons/fleur_outputpara.json') out_node_scf_path = os.path.join( aiida_path, '../tests/files/jsons/fleur_output_scf_wc_para.json') out_node_eos_path = os.path.join( aiida_path, '../tests/files/jsons/fleur_output_eos_wc_para.json') fleur_outputnode = orm.Dict(dict=read_dict_from_file(out_node_path), label='output_para') p_calc = plot_fleur(fleur_outputnode, show=False, backend='bokeh') assert isinstance(p_calc, list) assert p_calc[0] is None # currently does not have a visualization scf_out = orm.Dict(dict=read_dict_from_file(out_node_scf_path), label='output_scf_wc_para') p_scf = plot_fleur(scf_out, show=False, backend='bokeh') assert isinstance(p_scf, list) assert isinstance(p_scf[0], type(column()))
def test_pw_ibrav_tol(fixture_sandbox, generate_calc_job, fixture_code, generate_kpoints_mesh, generate_upf_data): """Test that `IBRAV_TOLERANCE` controls the tolerance when checking cell consistency.""" entry_point_name = 'quantumespresso.pw' parameters = {'CONTROL': {'calculation': 'scf'}, 'SYSTEM': {'ecutrho': 240.0, 'ecutwfc': 30.0, 'ibrav': 2}} # The structure needs to be rotated in the same way QE does it for ibrav=2. param = 5.43 eps = 0.1 cell = [[-param / 2., eps, param / 2.], [-eps, param / 2. + eps, param / 2.], [-param / 2., param / 2., 0]] structure = orm.StructureData(cell=cell) structure.append_atom(position=(0., 0., 0.), symbols='Si', name='Si') structure.append_atom(position=(param / 4., param / 4., param / 4.), symbols='Si', name='Si') upf = generate_upf_data('Si') inputs = { 'code': fixture_code(entry_point_name), 'structure': structure, 'kpoints': generate_kpoints_mesh(2), 'parameters': orm.Dict(dict=parameters), 'pseudos': { 'Si': upf }, 'metadata': { 'options': get_default_options() }, } # Without adjusting the tolerance, the check fails. with pytest.raises(QEInputValidationError): generate_calc_job(fixture_sandbox, entry_point_name, inputs) # After adjusting the tolerance, the input validation no longer fails. inputs['settings'] = orm.Dict(dict={'ibrav_cell_tolerance': eps}) generate_calc_job(fixture_sandbox, entry_point_name, inputs)
def test_plot_fleur_single_wc_matplotlib(aiida_profile, read_dict_from_file): """test if plot fleur can visualize a workchain""" aiida_path = os.path.dirname(aiida_fleur.__file__) out_node_path = os.path.join(aiida_path, '../tests/files/jsons/fleur_outputpara.json') out_node_scf_path = os.path.join( aiida_path, '../tests/files/jsons/fleur_output_scf_wc_para.json') out_node_eos_path = os.path.join( aiida_path, '../tests/files/jsons/fleur_output_eos_wc_para.json') fleur_outputnode = orm.Dict(dict=read_dict_from_file(out_node_path), label='output_para') p_calc = plot_fleur(fleur_outputnode, show=False) assert isinstance(p_calc, list) assert p_calc[0] is None # isinstance(p_scf[0], plt.figure) scf_output = orm.Dict(dict=read_dict_from_file(out_node_scf_path), label='output_scf_wc_para') p_scf = plot_fleur(scf_output, show=False) assert isinstance(p_scf, list) # assert isinstance(p_scf[0], type(plt.axes)) # isinstance(p_scf[0], plt.figure) eos_output = orm.Dict(dict=read_dict_from_file(out_node_eos_path), label='output_eos_wc_para') p_eos = plot_fleur(eos_output, show=False) assert isinstance(p_eos, list)
def generate_inputs(): """Return a dictionary of inputs for a `CalcJobNode` fixture to be created.""" from aiida import orm inputs = {'parameters': orm.Dict(dict={}), 'settings': orm.Dict(dict={})} return inputs
def test_validate_instructions(): """Test the `TransferCalculation` validators.""" from aiida.calculations.transfer import validate_instructions instructions = orm.Dict(dict={}).store() result = validate_instructions(instructions, None) expected = ( '\n\nno indication of what to do in the instruction node:\n' f' > {instructions.uuid}\n' '(to store the files in the repository set retrieve_files=True,\n' 'to copy them to the specified folder on the remote computer,\n' 'set it to False)\n' ) assert result == expected instructions = orm.Dict(dict={'retrieve_files': 12}).store() result = validate_instructions(instructions, None) expected = ( 'entry for retrieve files inside of instruction node:\n' f' > {instructions.uuid}\n' 'must be either True or False; instead, it is:\n > 12\n' ) assert result == expected instructions = orm.Dict(dict={'retrieve_files': True}).store() result = validate_instructions(instructions, None) expected = ( 'no indication of which files to copy were found in the instruction node:\n' f' > {instructions.uuid}\n' 'Please include at least one of `local_files`, `remote_files`, or `symlink_files`.\n' 'These should be lists containing 3-tuples with the following format:\n' ' (source_node_key, source_relpath, target_relpath)\n' ) assert result == expected
def get_builder(self, structure, calc_engines, protocol, relaxation_type, threshold_forces=None, threshold_stress=None, **kwargs): """Return a process builder for the corresponding workchain class with inputs set according to the protocol. :param structure: the structure to be relaxed :param calc_engines: ... :param protocol: the protocol to use when determining the workchain inputs :param relaxation_type: the type of relaxation to perform, instance of `RelaxType` :param threshold_forces: target threshold for the forces in eV/Å. :param threshold_stress: target threshold for the stress in eV/Å^3. :param kwargs: any inputs that are specific to the plugin. :return: a `aiida.engine.processes.ProcessBuilder` instance ready to be submitted. """ # pylint: disable=too-many-locals from aiida_quantumespresso_epfl.common.protocol.pw import generate_inputs # pylint: disable=import-error code = calc_engines['relax']['code'] process_class = QuantumEspressoRelaxWorkChain._process_class # pylint: disable=protected-access pseudo_family = kwargs.pop('pseudo_family') builder = QuantumEspressoRelaxWorkChain.get_builder() inputs = generate_inputs(process_class, protocol, code, structure, pseudo_family, override={'relax': {}}) builder._update(inputs) # pylint: disable=protected-access if relaxation_type == RelaxType.ATOMS: relaxation_schema = 'relax' elif relaxation_type == RelaxType.ATOMS_CELL: relaxation_schema = 'vc-relax' else: raise ValueError('relaxation type `{}` is not supported'.format( relaxation_type.value)) builder.relaxation_scheme = orm.Str(relaxation_schema) if threshold_forces is not None: parameters = builder.base.parameters.get_dict() parameters.setdefault('CONTROL', {})['forc_conv_thr'] = threshold_forces builder.base.parameters = orm.Dict(dict=parameters) if threshold_stress is not None: parameters = builder.base.parameters.get_dict() parameters.setdefault('CELL', {})['press_conv_thr'] = threshold_stress builder.base.parameters = orm.Dict(dict=parameters) return builder
def submit_workchain(structure, daemon, protocol, parameters, pseudo_family, num_machines, num_mpiprocs_per_machine=4, set_2d_mesh=False): print("running dft band structure calculation for {}".format( structure.get_formula())) # Set custom pseudo modifiers = {'parameters': parameters} """ if pseudo_family is not None: from aiida_quantumespresso.utils.protocols.pw import _load_pseudo_metadata pseudo_data = _load_pseudo_metadata(pseudo_family) modifiers.update({'pseudo': 'custom', 'pseudo_data': pseudo_data}) """ # if pseudo_family is not None: # from aiida_quantumespresso.utils.pseudopotential import get_pseudos_from_structure # pseudo_data = get_pseudos_from_structure(structure, pseudo_family) # modifiers.update({'pseudo': 'custom', 'pseudo_data': pseudo_data}) # Submit the DFT bands workchain pwbands_workchain_parameters = { 'code': code, 'structure': structure, 'protocol': orm.Dict(dict={ 'name': protocol, 'modifiers': modifiers }), 'options': orm.Dict( dict={ 'resources': { 'num_machines': num_machines, 'num_mpiprocs_per_machine': num_mpiprocs_per_machine }, 'max_wallclock_seconds': 3600 * 5, 'withmpi': True, }), 'set_2d_mesh': orm.Bool(set_2d_mesh) } if pseudo_family is not None: pwbands_workchain_parameters['pseudo_family'] = orm.Str(pseudo_family) if daemon: dft_workchain = submit(PwBandStructureWorkChain, **pwbands_workchain_parameters) else: from aiida.engine import run_get_pk dft_workchain = run_get_pk(PwBandStructureWorkChain, **pwbands_workchain_parameters) return dft_workchain
def _generate_workchain_stm(): entry_point_code_siesta = 'siesta.siesta' entry_point_code = 'siesta.stm' entry_point_wc = 'siesta.stm' psml = generate_psml_data('Si') structure = generate_structure() params = generate_param().get_dict() params[ "%block local-density-of-states"] = "\n -9.6 -1.6 eV \n %endblock local-density-of-states" inputs = { 'code': fixture_code(entry_point_code_siesta), 'stm_code': fixture_code(entry_point_code), 'stm_mode': orm.Str("constant-height"), 'stm_spin': orm.Str("none"), 'stm_value': orm.Float(1), 'emin': orm.Float(-1), 'emax': orm.Float(1), 'structure': structure, 'kpoints': generate_kpoints_mesh(2), 'parameters': orm.Dict(dict=params), 'basis': generate_basis(), 'pseudos': { 'Si': psml, 'SiDiff': psml }, 'options': orm.Dict( dict={ 'resources': { 'num_machines': 1 }, 'max_wallclock_seconds': 1800, 'withmpi': False, }) } process = generate_workchain(entry_point_wc, inputs) return process
def _generate_inputs(parser_options=None): """Return only those inputs that the parser will expect to be there.""" inputs = { 'parameters': orm.Dict(dict={'PATH': { 'num_of_images': 3 }}), 'pw': { 'parameters': orm.Dict(dict={}), }, 'settings': orm.Dict(dict={'parser_options': parser_options}) } return AttributeDict(inputs)
def test_base_template(fixture_sandbox, aiida_localhost, generate_calc_job): """Test a base template that emulates the arithmetic add.""" entry_point_name = 'templatereplacer' inputs = { 'code': orm.Code(remote_computer_exec=(aiida_localhost, '/bin/bash')), 'metadata': { 'options': { 'resources': { 'num_machines': 1, 'tot_num_mpiprocs': 1 } } }, 'template': orm.Dict( dict={ 'input_file_template': 'echo $(({x} + {y}))', 'input_file_name': 'input.txt', 'cmdline_params': ['input.txt'], 'output_file_name': 'output.txt', }), 'parameters': orm.Dict(dict={ 'x': 1, 'y': 2 }), } # Check the attributes of the resulting `CalcInfo` calc_info = generate_calc_job(fixture_sandbox, entry_point_name, inputs) assert isinstance(calc_info, datastructures.CalcInfo) assert sorted(calc_info.retrieve_list) == sorted( [inputs['template']['output_file_name']]) # Check the integrity of the `codes_info` codes_info = calc_info.codes_info assert isinstance(codes_info, list) assert len(codes_info) == 1 # Check the attributes of the resulting `CodeInfo` code_info = codes_info[0] assert isinstance(code_info, datastructures.CodeInfo) assert code_info.code_uuid == inputs['code'].uuid assert code_info.stdout_name == inputs['template']['output_file_name'] assert sorted(code_info.cmdline_params) == sorted( inputs['template']['cmdline_params']) # Check the content of the generated script with fixture_sandbox.open(inputs['template']['input_file_name']) as handle: input_written = handle.read() assert input_written == f"echo $(({inputs['parameters']['x']} + {inputs['parameters']['y']}))"
def test_process(deepmd_code): """Test running a calculation note this does not test that the expected outputs are created of output parsing""" from aiida.plugins import DataFactory, CalculationFactory from aiida.engine import run # Prepare input parameters DiffParameters = DataFactory('deepmd') parameters = DiffParameters({'ignore-case': True}) from aiida.orm import SinglefileData file1 = SinglefileData( file=os.path.join(tests.TEST_DIR, "input_files", 'file1.txt')) file2 = SinglefileData( file=os.path.join(tests.TEST_DIR, "input_files", 'file2.txt')) # data_folder = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'input_folder') data_folder = orm.FolderData( tree=os.path.join(tests.TEST_DIR, "input_files")) # data_folder = './input_folder' # set up calculation inputs = { 'code': deepmd_code, 'model': orm.Dict(dict={}), 'learning_rate': orm.Dict(dict={}), 'loss': orm.Dict(dict={}), 'training': orm.Dict(dict={}), 'file': { 'box_raw': SinglefileData( file=os.path.join(tests.TEST_DIR, "input_files", 'file1.txt')), 'coord_raw': SinglefileData( file=os.path.join(tests.TEST_DIR, "input_files", 'file2.txt')) }, 'metadata': { 'dry_run': True, 'options': { 'max_wallclock_seconds': 30, 'resources': { 'num_machines': 1, 'num_mpiprocs_per_machine': 1 } }, }, } result = run(CalculationFactory('dptrain'), **inputs) computed_diff = result['deepmd'].get_content() assert 'content1' in computed_diff assert 'content2' in computed_diff
def generate_inputs_calculation( protocol: Dict, code: orm.Code, structure: orm.StructureData, otfg_family: OTFGGroup, override: Dict[str, Any] = None ) -> Dict[str, Any]: """Generate the inputs for the `CastepCalculation` for a given code, structure and pseudo potential family. :param protocol: the dictionary with protocol inputs. :param code: the code to use. :param structure: the input structure. :param otfg_family: the pseudo potential family. :param override: a dictionary to override specific inputs. :return: the fully defined input dictionary. """ from aiida_castep.calculations.helper import CastepHelper override = {} if not override else override.get('calc', {}) # This merge perserves the merged `parameters` in the override merged_calc = recursive_merge(protocol['calc'], override) # Create KpointData for CastepCalculation, the kpoints_spacing passed is # already in the AiiDA convention, e.g. with 2pi factor built into it. kpoints = orm.KpointsData() kpoints.set_cell_from_structure(structure) kpoints.set_kpoints_mesh_from_density(protocol['kpoints_spacing']) # For bare calculation level, we need to make sure the dictionary is not "flat" param = merged_calc['parameters'] # Remove incompatible options: cut_off_energy and basis_precisions can not be # both specified if 'cut_off_energy' in param: param.pop('basis_precision', None) helper = CastepHelper() param = helper.check_dict(param, auto_fix=True, allow_flat=True) dictionary = { 'structure': structure, 'kpoints': kpoints, 'code': code, 'parameters': orm.Dict(dict=param), 'pseudos': get_pseudos_from_structure(structure, otfg_family.label), 'metadata': merged_calc.get('metadata', {}) } # Add the settings input if present if 'settings' in merged_calc: dictionary['settings'] = orm.Dict(dict=merged_calc['settings']) return dictionary
def _generate_inputs(calculation_type='scf', settings=None, metadata=None): structure = generate_structure() parameters = {'CONTROL': {'calculation': calculation_type}} kpoints = orm.KpointsData() kpoints.set_cell_from_structure(structure) kpoints.set_kpoints_mesh_from_density(0.15) return AttributeDict({ 'structure': generate_structure(), 'kpoints': kpoints, 'parameters': orm.Dict(dict=parameters), 'settings': orm.Dict(dict=settings), 'metadata': metadata or {} })
def inputs(fixture_code, remote, parameters, settings): """Fixture: inputs for Z2packBaseWorkChain.""" from aiida_quantumespresso.utils.resources import get_default_options inputs = { 'code': fixture_code('quantumespresso.pw2gw'), 'parent_folder': remote, 'parameters': orm.Dict(dict=parameters), 'settings': orm.Dict(dict=settings), 'metadata': { 'options': get_default_options() } } return inputs
def run_scf(self): """ Run the SCF calculation step. """ self.report('Launching SCF calculation.') inputs = self.exposed_inputs(PwCalculation, namespace='scf') inputs['parameters'] = merge_nested_dict( orm.Dict(dict={'CONTROL': { 'calculation': 'scf' }}), inputs.get('parameters', orm.Dict())) return ToContext(scf=self.submit(PwCalculation, structure=self.inputs.structure, kpoints=self.inputs.kpoints_mesh, **inputs))
def run_calc(self): """ Run the QE calculation. """ self.report("Submitting pw.x bands calculation.") pw_inputs = self.exposed_inputs(PwCalculation, namespace='pw') pw_inputs['parameters'] = merge_nested_dict( orm.Dict(dict={'CONTROL': { 'calculation': 'bands' }}), pw_inputs.get('parameters', orm.Dict()) ) return ToContext(pw_calc=self.submit(PwCalculation, **pw_inputs))
def generate_inputs_relax(protocol: Dict, code: orm.Code, structure: orm.StructureData, otfg_family: OTFGGroup, override: Dict[str, Any] = None) -> Dict[str, Any]: """Generate the inputs for the `CastepRelaxWorkChain` for a given code, structure and pseudo potential family. :param protocol: the dictionary with protocol inputs. :param code: the code to use. :param structure: the input structure. :param otfg_family: the pseudo potential family. :param override: a dictionary to override specific inputs. :return: the fully defined input dictionary. """ protocol['base'] = generate_inputs_base(protocol['base'], code, structure, otfg_family, override.get('base', {})) merged = recursive_merge(protocol, override) # Remove inputs that should not be passed top-level merged['base'].pop('structure', None) calc = merged['base'].pop('calc') # Here we move the 'calc' up from the 'base' this is how the relax workchain accepts inputs dictionary = { 'base': merged['base'], 'calc': calc, 'structure': structure, 'relax_options': orm.Dict(dict=merged['relax_options']) } return dictionary
def _wrap_bare_dict_inputs(self, port_namespace, inputs): """Wrap bare dictionaries in `inputs` in a `Dict` node if dictated by the corresponding inputs portnamespace. :param port_namespace: a `PortNamespace` :param inputs: a dictionary of inputs intended for submission of the process :return: an attribute dictionary with all bare dictionaries wrapped in `Dict` if dictated by the port namespace """ from aiida.engine.processes import PortNamespace wrapped = {} for key, value in inputs.items(): if key not in port_namespace: wrapped[key] = value continue port = port_namespace[key] if isinstance(port, PortNamespace): wrapped[key] = self._wrap_bare_dict_inputs(port, value) elif port.valid_type == orm.Dict and isinstance(value, dict): wrapped[key] = orm.Dict(dict=value) else: wrapped[key] = value return AttributeDict(wrapped)
def generate_inputs_spinorbit(generate_calc_job_node, fixture_localhost, generate_structure, generate_kpoints_mesh): """Create the required inputs for the ``ProjwfcCalculation`` with lspinorb=.true.""" entry_point_name = 'quantumespresso.pw' inputs = { 'structure': generate_structure(), 'kpoints': generate_kpoints_mesh(4) } parent_calcjob = generate_calc_job_node(entry_point_name, fixture_localhost, 'default', inputs=inputs) params = orm.Dict( dict={ 'number_of_spin_components': 4, 'non_colinear_calculation': True, 'spin_orbit_calculation': True }) params.add_incoming(parent_calcjob, link_type=LinkType.CREATE, link_label='output_parameters') params.store() inputs = { 'parent_folder': parent_calcjob.outputs.remote_folder, } return AttributeDict(inputs)
def test_pw_wrong_ibrav(fixture_sandbox, generate_calc_job, fixture_code, generate_kpoints_mesh, generate_upf_data): """Test that a `PwCalculation` with an incorrect `ibrav` raises.""" entry_point_name = 'quantumespresso.pw' parameters = {'CONTROL': {'calculation': 'scf'}, 'SYSTEM': {'ecutrho': 240.0, 'ecutwfc': 30.0, 'ibrav': 2}} # Here we use the wrong order of unit cell vectors on purpose. param = 5.43 cell = [[0, param / 2., param / 2.], [-param / 2., 0, param / 2.], [-param / 2., param / 2., 0]] structure = orm.StructureData(cell=cell) structure.append_atom(position=(0., 0., 0.), symbols='Si', name='Si') structure.append_atom(position=(param / 4., param / 4., param / 4.), symbols='Si', name='Si') upf = generate_upf_data('Si') inputs = { 'code': fixture_code(entry_point_name), 'structure': structure, 'kpoints': generate_kpoints_mesh(2), 'parameters': orm.Dict(dict=parameters), 'pseudos': { 'Si': upf }, 'metadata': { 'options': get_default_options() } } with pytest.raises(QEInputValidationError): generate_calc_job(fixture_sandbox, entry_point_name, inputs)
def calculate_invariant_with_parities(dimensionality: orm.Int, scf_out_params: orm.Dict, par_data: orm.ArrayData) -> orm.Dict: """Calculate the z2 invariant from the parities using the output of a BandsxCalculation.""" dim = dimensionality.value parities = par_data.get_array('par') n_el = int(scf_out_params.get_dict()['number_of_electrons']) if dim == 2: x = 1 for p in parities: delta = 1 for i in range(0, n_el, 2): delta *= p[i] x *= delta if x == 1: res = {'nu': 0} elif x == -1: res = {'nu': 1} else: res = {'nu': -1} # raise exceptions.OutputParsingError( # 'Invalid result for z2 using parities') elif dim == 3: raise NotImplemented('dimensionality = 3 not implemented.') else: raise exceptions.InputValidationError( 'dimensionality must be either 2 or 3') return orm.Dict(dict=res)
def tags_and_magnetization(structure, magnetization_per_site): """Gather the same atoms with the same magnetization into one atomic kind.""" if magnetization_per_site: ase_structure = structure.get_ase() if len(magnetization_per_site) != len(ase_structure.numbers): raise ValueError( 'The size of `magnetization_per_site` is different from the number of atoms.' ) # Combine atom type with magnetizations. complex_symbols = [ f'{symbol}_{magn}' for symbol, magn in zip( ase_structure.get_chemical_symbols(), magnetization_per_site) ] # Assign a unique tag for every atom kind. combined = { symbol: tag + 1 for tag, symbol in enumerate(set(complex_symbols)) } # Assigning correct tags to every atom. tags = [combined[key] for key in complex_symbols] ase_structure.set_tags(tags) # Tag-magnetization correspondance. tags_correspondance = { str(value): float(key.split('_')[1]) for key, value in combined.items() } return StructureData(ase=ase_structure), orm.Dict( dict=tags_correspondance) return structure, None
def setup_parameters(self): """Set up the default input parameters required for the `PwBandsWorkChain`.""" ecutwfc = [] ecutrho = [] for kind in self.inputs.structure.get_kind_names(): try: dual = self.ctx.protocol['pseudo_data'][kind]['dual'] cutoff = self.ctx.protocol['pseudo_data'][kind]['cutoff'] cutrho = dual * cutoff ecutwfc.append(cutoff) ecutrho.append(cutrho) except KeyError: self.report('failed to retrieve the cutoff or dual factor for {}'.format(kind)) return self.exit_codes.ERROR_INVALID_INPUT_UNRECOGNIZED_KIND self.ctx.parameters = orm.Dict(dict={ 'CONTROL': { 'restart_mode': 'from_scratch', 'tstress': self.ctx.protocol['tstress'], 'tprnfor': self.ctx.protocol['tprnfor'], }, 'SYSTEM': { 'ecutwfc': max(ecutwfc), 'ecutrho': max(ecutrho), 'smearing': self.ctx.protocol['smearing'], 'degauss': self.ctx.protocol['degauss'], 'occupations': self.ctx.protocol['occupations'], }, 'ELECTRONS': { 'conv_thr': self.ctx.protocol['convergence_threshold_per_atom'] * len(self.inputs.structure.sites), } })