예제 #1
0
 def setUpClass(cls, *args, **kwargs):
     super().setUpClass(*args, **kwargs)
     cls.computer.configure()  # pylint: disable=no-member
     cls.remote_code = orm.Code(remote_computer_exec=(cls.computer,
                                                      '/bin/bash')).store()
     cls.local_code = orm.Code(local_executable='bash',
                               files=['/bin/bash']).store()
     cls.inputs = {
         'x': orm.Int(1),
         'y': orm.Int(2),
         'metadata': {
             'options': {}
         }
     }
예제 #2
0
def test_file_usage(fixture_sandbox, aiida_localhost, generate_calc_job):
    """Test a base template that uses two files."""

    file1_node = orm.SinglefileData(io.BytesIO(b'Content of file 1'))
    file2_node = orm.SinglefileData(io.BytesIO(b'Content of file 2'))

    # Check that the files are correctly copied to the copy list
    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={
            'files_to_copy': [('filenode1', 'file1.txt'), ('filenode2', 'file2.txt')],
        }),
        'files': {
            'filenode1': file1_node,
            'filenode2': file2_node
        }
    }

    calc_info = generate_calc_job(fixture_sandbox, entry_point_name, inputs)
    reference_copy_list = []
    for node_idname, target_path in inputs['template']['files_to_copy']:
        file_node = inputs['files'][node_idname]
        reference_copy_list.append((file_node.uuid, file_node.filename, target_path))

    assert sorted(calc_info.local_copy_list) == sorted(reference_copy_list)
예제 #3
0
def test_add_default(fixture_sandbox, aiida_localhost, generate_calc_job):
    """Test a default `ArithmeticAddCalculation`."""
    entry_point_name = 'arithmetic.add'
    inputs = {'x': orm.Int(1), 'y': orm.Int(2), 'code': orm.Code(remote_computer_exec=(aiida_localhost, '/bin/bash'))}

    calc_info = generate_calc_job(fixture_sandbox, entry_point_name, inputs)
    options = ArithmeticAddCalculation.spec().inputs['metadata']['options']

    # Check the attributes of the returned `CalcInfo`
    assert isinstance(calc_info, datastructures.CalcInfo)
    assert sorted(calc_info.retrieve_list) == sorted([options['output_filename'].default])

    codes_info = calc_info.codes_info
    assert isinstance(codes_info, list)
    assert len(codes_info) == 1

    code_info = codes_info[0]
    assert isinstance(code_info, datastructures.CodeInfo)
    assert code_info.code_uuid == inputs['code'].uuid
    assert code_info.stdin_name == options['input_filename'].default
    assert code_info.stdout_name == options['output_filename'].default

    with fixture_sandbox.open(options['input_filename'].default) as handle:
        input_written = handle.read()
        assert input_written == 'echo $(({} + {}))\n'.format(inputs['x'].value, inputs['y'].value)
예제 #4
0
    def test_code_list(self):
        """Test code list command."""
        # set up second code 'code2'
        try:
            code = orm.Code.get_from_string('code2')
        except NotExistent:
            code = orm.Code(
                input_plugin_name='templatereplacer',
                remote_computer_exec=[self.computer, '/remote/abs/path'],
            )
            code.label = 'code2'
            code.store()

        options = [
            '-A', '-a', '-o', '--input-plugin=arithmetic.add',
            f'--computer={self.computer.label}'
        ]
        result = self.cli_runner.invoke(code_list, options)
        self.assertIsNone(result.exception, result.output)
        self.assertTrue(
            str(self.code.pk) in result.output,
            'PK of first code should be included')
        self.assertTrue('code2' not in result.output,
                        'label of second code should not be included')
        self.assertTrue('comp' in result.output,
                        'computer name should be included')
        self.assertNotIn(result.output,
                         '# No codes found matching the specified criteria.')
예제 #5
0
    def setUpClass(cls):
        super().setUpClass()
        from aiida import orm

        cls.computer = orm.Computer(label='comp',
                                    hostname='localhost',
                                    transport_type='local',
                                    scheduler_type='direct',
                                    workdir='/tmp/aiida').store()

        cls.code = orm.Code(remote_computer_exec=(cls.computer,
                                                  '/bin/true')).store()
        cls.group = orm.Group(label='test_group').store()
        cls.node = orm.Data().store()

        # some of the export tests write in the current directory,
        # make sure it is writeable and we don't pollute the current one
        cls.old_cwd = os.getcwd()
        cls.cwd = tempfile.mkdtemp(__name__)
        os.chdir(cls.cwd)

        # Utility helper
        cls.fixture_archive = 'export/migrate'
        cls.newest_archive = f'export_v{EXPORT_VERSION}_simple.aiida'
        cls.penultimate_archive = 'export_v0.6_simple.aiida'
예제 #6
0
 def setUpClass(cls, *args, **kwargs):
     super(TestCalcJob, cls).setUpClass(*args, **kwargs)
     cls.remote_code = orm.Code(remote_computer_exec=(cls.computer,
                                                      '/bin/true')).store()
     cls.local_code = orm.Code(local_executable='true',
                               files=['/bin/true']).store()
     cls.inputs = {
         'x': orm.Int(1),
         'y': orm.Int(2),
         'metadata': {
             'options': {
                 'resources': {
                     'num_machines': 1,
                     'num_mpiprocs_per_machine': 1
                 },
             }
         }
     }
예제 #7
0
def silicon_builder(db_test_app):
    """Prepare a mock - ready calculation for silicon"""
    silicon = orm.StructureData()
    r_unit = 2.6954645
    silicon.set_cell(np.array([[1, 1, 0], [1, 0, 1], [0, 1, 1]]) * r_unit)
    silicon.append_atom(symbols=["Si"], position=[0, 0, 0])
    silicon.append_atom(symbols=["Si"], position=[r_unit * 0.5] * 3)
    silicon.label = "Si"
    silicon.description = "A silicon structure"
    param_dict = {
        # Notice that the keywords are group into two sub-dictionaries
        # just like you would do when preparing the inputs by hand
        "CELL": {
            "symmetry_generate": True,
            "snap_to_symmetry": True,
            # Pass a list of string to set a BLOCK inputs
            #"cell_constraints":
            #["0 0 0", "0 0 0"]
        },
        "PARAM": {
            "task": "singlepoint",
            "basis_precision": "medium",
            "fix_occupancy":
            True,  # Use bool type to make it easy for querying
            "opt_strategy": "memory",
            "num_dump_cycles": 0,
            "write_formatted_density": True
        }
    }
    # We need to create a Dict node that holds the dictionary
    param = orm.Dict(dict=param_dict)
    kpoints = orm.KpointsData()
    # Use gamma and 0.25, 0.25, 0.25
    kpoints.set_kpoints_mesh((4, 4, 4), offset=(0, 0, 0))
    c9 = OTFGData(otfg_entry="C9")
    CastepCalculation = CalculationFactory('castep.castep')
    code_path = check_output(['which', 'castep.mock'],
                             universal_newlines=True).strip()
    castep_mock = orm.Code((db_test_app.localhost, code_path),
                           input_plugin_name='castep.castep')

    builder = CastepCalculation.get_builder()
    builder.structure = silicon
    builder.parameters = param
    builder.kpoints = kpoints
    builder.code = castep_mock
    builder.pseudos = {'Si': c9}
    builder.metadata.options.withmpi = False
    builder.metadata.options.resources = {
        'num_machines': 1,
        'tot_num_mpiprocs': 2
    }
    builder.metadata.options.max_wallclock_seconds = 600
    builder.metadata.label = "Si SINGLEPOINT"
    builder.metadata.description = 'A Example CASTEP calculation for silicon'
    return builder
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']}))"
예제 #9
0
    def test_input_code(self, temp_dir):
        """
        This test checks that when a calculation is exported then the
        corresponding code is also exported. It also checks that the links
        are also in place after the import.
        """
        code_label = 'test_code1'

        code = orm.Code()
        code.set_remote_computer_exec((self.computer, '/bin/true'))
        code.label = code_label
        code.store()

        code_uuid = code.uuid

        calc = orm.CalcJobNode()
        calc.computer = self.computer
        calc.set_option('resources', {
            'num_machines': 1,
            'num_mpiprocs_per_machine': 1
        })

        calc.add_incoming(code, LinkType.INPUT_CALC, 'code')
        calc.store()
        calc.seal()
        links_count = 1

        export_links = get_all_node_links()

        export_file = os.path.join(temp_dir, 'export.aiida')
        export([calc], filename=export_file)

        self.clean_db()

        import_data(export_file)

        # Check that the code node is there
        self.assertEqual(orm.load_node(code_uuid).label, code_label)

        # Check that the link is in place
        import_links = get_all_node_links()
        self.assertListEqual(sorted(export_links), sorted(import_links))
        self.assertEqual(
            len(export_links), links_count,
            'Expected to find only one link from code to '
            'the calculation node before export. {} found.'.format(
                len(export_links)))
        self.assertEqual(
            len(import_links), links_count,
            'Expected to find only one link from code to '
            'the calculation node after import. {} found.'.format(
                len(import_links)))
예제 #10
0
    def test_provenance_exclude_list(self):
        """Test the functionality of the `CalcInfo.provenance_exclude_list` attribute."""
        import tempfile

        code = orm.Code(input_plugin_name='arithmetic.add',
                        remote_computer_exec=[self.computer,
                                              '/bin/true']).store()

        with tempfile.NamedTemporaryFile('w+') as handle:
            handle.write('dummy_content')
            handle.flush()
            file_one = orm.SinglefileData(file=handle.name)

        with tempfile.NamedTemporaryFile('w+') as handle:
            handle.write('dummy_content')
            handle.flush()
            file_two = orm.SinglefileData(file=handle.name)

        inputs = {
            'code':
            code,
            'files': {
                # Note the `FileCalcJob` will turn underscores in the key into forward slashes making a nested hierarchy
                'base_a_sub_one': file_one,
                'base_b_two': file_two,
            },
            'settings':
            orm.Dict(dict={'provenance_exclude_list': ['base/a/sub/one']}),
            'metadata': {
                'dry_run': True,
                'options': {
                    'resources': {
                        'num_machines': 1,
                        'num_mpiprocs_per_machine': 1
                    }
                }
            }
        }

        # We perform a `dry_run` because the calculation cannot actually run, however, the contents will still be
        # written to the node's repository so we can check it contains the expected contents.
        _, node = launch.run_get_node(FileCalcJob, **inputs)

        self.assertIn('folder', node.dry_run_info)

        # Verify that the folder (representing the node's repository) indeed do not contain the input files. Note,
        # however, that the directory hierarchy should be there, albeit empty
        self.assertIn('base', node.list_object_names())
        self.assertEqual(sorted(['b']),
                         sorted(node.list_object_names(os.path.join('base'))))
        self.assertEqual(['two'],
                         node.list_object_names(os.path.join('base', 'b')))
예제 #11
0
def test_leak_ssh_calcjob():
    """Test whether running a CalcJob over SSH leaks memory.

    Note: This relies on the 'slurm-ssh' computer being set up.
    """
    code = orm.Code(
        input_plugin_name='arithmetic.add',
        remote_computer_exec=[orm.load_computer('slurm-ssh'), '/bin/bash'])
    inputs = {'x': orm.Int(1), 'y': orm.Int(2), 'code': code}
    run_finished_ok(ArithmeticAddCalculation, **inputs)

    # check that no reference to the process is left in memory
    # some delay is necessary in order to allow for all callbacks to finish
    process_instances = get_instances(processes.Process, delay=0.2)
    assert not process_instances, f'Memory leak: process instances remain in memory: {process_instances}'
예제 #12
0
    def test_par_env_resources_computer(self):
        """Test launching a `CalcJob` an a computer with a scheduler using `ParEnvJobResource` as resources.

        Even though the computer defines a default number of MPI procs per machine, it should not raise when the
        scheduler that is defined does not actually support it, for example SGE or LSF.
        """
        inputs = deepcopy(self.inputs)
        computer = orm.Computer('sge_computer', 'localhost', 'desc', 'local', 'sge').store()
        computer.set_default_mpiprocs_per_machine(1)

        inputs['code'] = orm.Code(remote_computer_exec=(computer, '/bin/bash')).store()
        inputs['metadata']['options']['resources'] = {'parallel_env': 'environment', 'tot_num_mpiprocs': 10}

        # Just checking that instantiating does not raise, meaning the inputs were valid
        ArithmeticAddCalculation(inputs=inputs)
예제 #13
0
 def setUpClass(cls, *args, **kwargs):
     super().setUpClass(*args, **kwargs)
     import aiida
     files = [
         os.path.join(os.path.dirname(aiida.__file__), os.pardir, '.ci',
                      'add.sh')
     ]
     cls.computer.configure()  # pylint: disable=no-member
     cls.remote_code = orm.Code(remote_computer_exec=(cls.computer,
                                                      '/bin/true')).store()
     cls.local_code = orm.Code(local_executable='add.sh',
                               files=files).store()
     cls.inputs = {
         'x': orm.Int(1),
         'y': orm.Int(2),
         'metadata': {
             'options': {
                 'resources': {
                     'num_machines': 1,
                     'num_mpiprocs_per_machine': 1
                 },
             }
         }
     }
예제 #14
0
    def setUp(self):
        self.comp = orm.Computer.objects.get(name='comp')

        try:
            code = orm.Code.get_from_string('code')
        except NotExistent:
            code = orm.Code(
                input_plugin_name='arithmetic.add',
                remote_computer_exec=[self.comp, '/remote/abs/path'],
            )
            code.label = 'code'
            code.description = 'desc'
            code.store()
        self.code = code

        self.cli_runner = CliRunner()
예제 #15
0
    def setUp(self):
        try:
            code = orm.Code.get_from_string('code')
        except NotExistent:
            code = orm.Code(
                input_plugin_name='arithmetic.add',
                remote_computer_exec=[self.computer, '/remote/abs/path'],
            )
            code.label = 'code'
            code.description = 'desc'
            code.set_prepend_text('text to prepend')
            code.set_append_text('text to append')
            code.store()
        self.code = code

        self.cli_runner = CliRunner()
예제 #16
0
    def test_calcjob_dry_run_no_provenance(self):
        """Test that dry run with `store_provenance=False` still works for unstored inputs.

        The special thing about this test is that the unstored input nodes that will be used in the `local_copy_list`.
        This was broken as the code in `upload_calculation` assumed that the nodes could be loaded through their UUID
        which is not the case in the `store_provenance=False` mode with unstored nodes. Note that it also explicitly
        tests nested namespaces as that is a non-trivial case.
        """
        import os
        import tempfile

        code = orm.Code(input_plugin_name='arithmetic.add',
                        remote_computer_exec=[self.computer,
                                              '/bin/true']).store()

        with tempfile.NamedTemporaryFile('w+') as handle:
            handle.write('dummy_content')
            handle.flush()
            single_file = orm.SinglefileData(file=handle.name)
            file_one = orm.SinglefileData(file=handle.name)
            file_two = orm.SinglefileData(file=handle.name)

        inputs = {
            'code': code,
            'single_file': single_file,
            'files': {
                'file_one': file_one,
                'file_two': file_two,
            },
            'metadata': {
                'dry_run': True,
                'store_provenance': False,
                'options': {
                    'resources': {
                        'num_machines': 1,
                        'num_mpiprocs_per_machine': 1
                    }
                }
            }
        }

        _, node = launch.run_get_node(FileCalcJob, **inputs)
        self.assertIn('folder', node.dry_run_info)
        for filename in ['single_file', 'file_one', 'file_two']:
            self.assertIn(filename, os.listdir(node.dry_run_info['folder']))
예제 #17
0
    def test_launchers_dry_run_no_provenance(self):
        """Test the launchers in `dry_run` mode with `store_provenance=False`."""
        from aiida.plugins import CalculationFactory

        ArithmeticAddCalculation = CalculationFactory('arithmetic.add')  # pylint: disable=invalid-name

        code = orm.Code(input_plugin_name='arithmetic.add',
                        remote_computer_exec=[self.computer,
                                              '/bin/true']).store()

        inputs = {
            'code': code,
            'x': orm.Int(1),
            'y': orm.Int(1),
            'metadata': {
                'dry_run': True,
                'store_provenance': False,
                'options': {
                    'resources': {
                        'num_machines': 1,
                        'num_mpiprocs_per_machine': 1
                    }
                }
            }
        }

        result = launch.run(ArithmeticAddCalculation, **inputs)
        self.assertEqual(result, {})

        result, pk = launch.run_get_pk(ArithmeticAddCalculation, **inputs)
        self.assertEqual(result, {})
        self.assertIsNone(pk)

        result, node = launch.run_get_node(ArithmeticAddCalculation, **inputs)
        self.assertEqual(result, {})
        self.assertIsInstance(node, orm.CalcJobNode)
        self.assertFalse(node.is_stored)
        self.assertIsInstance(node.dry_run_info, dict)
        self.assertIn('folder', node.dry_run_info)
        self.assertIn('script_filename', node.dry_run_info)

        node = launch.submit(ArithmeticAddCalculation, **inputs)
        self.assertIsInstance(node, orm.CalcJobNode)
        self.assertFalse(node.is_stored)
예제 #18
0
    def test_launchers_dry_run(self):
        """All launchers should work with `dry_run=True`, even `submit` which forwards to `run`."""
        from aiida.plugins import CalculationFactory

        ArithmeticAddCalculation = CalculationFactory('arithmetic.add')  # pylint: disable=invalid-name

        code = orm.Code(input_plugin_name='arithmetic.add',
                        remote_computer_exec=[self.computer,
                                              '/bin/true']).store()

        inputs = {
            'code': code,
            'x': orm.Int(1),
            'y': orm.Int(1),
            'metadata': {
                'dry_run': True,
                'options': {
                    'resources': {
                        'num_machines': 1,
                        'num_mpiprocs_per_machine': 1
                    }
                }
            }
        }

        result = launch.run(ArithmeticAddCalculation, **inputs)
        self.assertEqual(result, {})

        result, pk = launch.run_get_pk(ArithmeticAddCalculation, **inputs)
        self.assertEqual(result, {})
        self.assertIsInstance(pk, int)

        result, node = launch.run_get_node(ArithmeticAddCalculation, **inputs)
        self.assertEqual(result, {})
        self.assertIsInstance(node, orm.CalcJobNode)
        self.assertIsInstance(node.dry_run_info, dict)
        self.assertIn('folder', node.dry_run_info)
        self.assertIn('script_filename', node.dry_run_info)

        node = launch.submit(ArithmeticAddCalculation, **inputs)
        self.assertIsInstance(node, orm.CalcJobNode)
예제 #19
0
    def test_code_type_change(self, temp_dir):
        """ Code type string changed
        Change: “code.Bool.” → “data.code.Code.”
        """
        # Create Code instance
        code = orm.Code()
        code.set_remote_computer_exec((self.computer, '/bin/true'))
        code.store()

        # Save uuid and type
        code_uuid = str(code.uuid)
        code_type = code.node_type

        # Assert correct type exists prior to export
        self.assertEqual(code_type, 'data.code.Code.')

        # Export node
        filename = os.path.join(temp_dir, 'export.aiida')
        export([code], filename=filename)

        # Clean the database and reimport
        self.clean_db()
        import_data(filename)

        # Retrieve Code node and make sure exactly 1 is retrieved
        builder = orm.QueryBuilder()
        builder.append(orm.Code, project=['uuid'])
        imported_code = builder.all()

        self.assertEqual(builder.count(), 1)

        # Check uuid is the same after import
        imported_code_uuid = str(imported_code[0][0])

        self.assertEqual(imported_code_uuid, code_uuid)

        # Check whether types are correctly imported
        imported_code_type = orm.load_node(imported_code_uuid).node_type

        self.assertEqual(imported_code_type, code_type)
예제 #20
0
    def test_that_solo_code_is_exported_correctly(self, temp_dir):
        """
        This test checks that when a calculation is exported then the
        corresponding code is also exported.
        """
        code_label = 'test_code1'

        code = orm.Code()
        code.set_remote_computer_exec((self.computer, '/bin/true'))
        code.label = code_label
        code.store()

        code_uuid = code.uuid

        export_file = os.path.join(temp_dir, 'export.aiida')
        export([code], filename=export_file)

        self.clean_db()

        import_data(export_file)

        self.assertEqual(orm.load_node(code_uuid).label, code_label)
예제 #21
0
    def test_code_get_builder(self):
        """Test that the `Code.get_builder` method returns a builder where the code is already set."""
        code = orm.Code()
        code.set_remote_computer_exec((self.computer, '/bin/true'))
        code.label = 'test_code'
        code.set_input_plugin_name('templatereplacer')
        code.store()

        # Check that I can get a builder
        builder = code.get_builder()
        self.assertEqual(builder.code.pk, code.pk)

        # Check that I can set the parameters
        builder.parameters = orm.Dict(dict={})

        # Check that it complains for an unknown input
        with self.assertRaises(AttributeError):
            builder.unknown_parameter = 3

        # Check that it complains if the type is not the correct one (for the templatereplacer, it should be a Dict)
        with self.assertRaises(ValueError):
            builder.parameters = orm.Int(3)
예제 #22
0
    def test_get_node_summary(self):
        """Test the `get_node_summary` utility."""
        from aiida.cmdline.utils.common import get_node_summary

        computer_label = self.computer.name  # pylint: disable=no-member

        code = orm.Code(
            input_plugin_name='arithmetic.add',
            remote_computer_exec=[self.computer, '/remote/abs/path'],
        )
        code.store()

        node = orm.CalculationNode()
        node.computer = self.computer
        node.add_incoming(code,
                          link_type=LinkType.INPUT_CALC,
                          link_label='code')
        node.store()

        summary = get_node_summary(node)
        self.assertIn(node.uuid, summary)
        self.assertIn(computer_label, summary)
예제 #23
0
def test_add_custom_filenames(fixture_sandbox, aiida_localhost, generate_calc_job):
    """Test an `ArithmeticAddCalculation` with non-default input and output filenames."""
    entry_point_name = 'arithmetic.add'
    input_filename = 'custom.in'
    output_filename = 'custom.out'
    inputs = {
        'x': orm.Int(1),
        'y': orm.Int(2),
        'code': orm.Code(remote_computer_exec=(aiida_localhost, '/bin/bash')),
        'metadata': {
            'options': {
                'input_filename': input_filename,
                'output_filename': output_filename,
            }
        }
    }

    calc_info = generate_calc_job(fixture_sandbox, entry_point_name, inputs)
    code_info = calc_info.codes_info[0]

    assert code_info.stdin_name == input_filename
    assert code_info.stdout_name == output_filename
    assert calc_info.retrieve_list == [output_filename]
예제 #24
0
    def test_cif_structure_roundtrip(self):
        from aiida.tools.dbexporters.tcod import export_cif, export_values
        from aiida.common.folders import SandboxFolder
        import tempfile

        with tempfile.NamedTemporaryFile(mode='w+') as tmpf:
            tmpf.write('''
                data_test
                _cell_length_a    10
                _cell_length_b    10
                _cell_length_c    10
                _cell_angle_alpha 90
                _cell_angle_beta  90
                _cell_angle_gamma 90
                loop_
                _atom_site_label
                _atom_site_fract_x
                _atom_site_fract_y
                _atom_site_fract_z
                C 0 0 0
                O 0.5 0.5 0.5
            ''')
            tmpf.flush()
            a = orm.CifData(filepath=tmpf.name)

        c = a.get_structure()
        c.store()
        pd = orm.Dict()

        code = orm.Code(local_executable='test.sh')
        with tempfile.NamedTemporaryFile(mode='w+') as tmpf:
            tmpf.write("#/bin/bash\n\necho test run\n")
            tmpf.flush()
            code.put_object_from_filelike(tmpf, 'test.sh')

        code.store()

        calc = orm.CalcJobNode(computer=self.computer)
        calc.set_option('resources', {
            'num_machines': 1,
            'num_mpiprocs_per_machine': 1
        })
        calc.add_incoming(code, LinkType.INPUT_CALC, "code")
        calc.set_option('environment_variables', {
            'PATH': '/dev/null',
            'USER': '******'
        })

        with tempfile.NamedTemporaryFile(mode='w+', prefix="Fe") as tmpf:
            tmpf.write("<UPF version=\"2.0.1\">\nelement=\"Fe\"\n")
            tmpf.flush()
            upf = orm.UpfData(filepath=tmpf.name)
            upf.store()
            calc.add_incoming(upf, LinkType.INPUT_CALC, "upf")

        with tempfile.NamedTemporaryFile(mode='w+') as tmpf:
            tmpf.write("data_test")
            tmpf.flush()
            cif = orm.CifData(filepath=tmpf.name)
            cif.store()
            calc.add_incoming(cif, LinkType.INPUT_CALC, "cif")

        with SandboxFolder() as fhandle:
            calc.put_object_from_tree(fhandle.abspath)
        calc.store()

        fd = orm.FolderData()
        with fd.open('_scheduler-stdout.txt', 'w') as fhandle:
            fhandle.write(u"standard output")

        with fd.open('_scheduler-stderr.txt', 'w') as fhandle:
            fhandle.write(u"standard error")

        fd.store()
        fd.add_incoming(calc, LinkType.CREATE, calc.link_label_retrieved)

        pd.add_incoming(calc, LinkType.CREATE, "create1")
        pd.store()

        with self.assertRaises(ValueError):
            export_cif(c, parameters=pd)

        c.add_incoming(calc, LinkType.CREATE, "create2")
        export_cif(c, parameters=pd)

        values = export_values(c, parameters=pd)
        values = values['0']

        self.assertEquals(values['_tcod_computation_environment'],
                          ['PATH=/dev/null\nUSER=unknown'])
        self.assertEquals(values['_tcod_computation_command'],
                          ['cd 1; ./_aiidasubmit.sh'])
예제 #25
0
    def setUpClass(cls, *args, **kwargs):
        super().setUpClass(*args, **kwargs)
        from aiida.common.links import LinkType
        from aiida.engine import ProcessState

        cls.computer = orm.Computer(name='comp',
                                    hostname='localhost',
                                    transport_type='local',
                                    scheduler_type='direct',
                                    workdir='/tmp/aiida').store()

        cls.code = orm.Code(remote_computer_exec=(cls.computer,
                                                  '/bin/true')).store()
        cls.group = orm.Group(label='test_group').store()
        cls.node = orm.Data().store()
        cls.calcs = []

        user = orm.User.objects.get_default()
        authinfo = orm.AuthInfo(computer=cls.computer, user=user)
        authinfo.store()

        process_class = CalculationFactory('templatereplacer')
        process_type = get_entry_point_string_from_class(
            process_class.__module__, process_class.__name__)

        # Create 5 CalcJobNodes (one for each CalculationState)
        for calculation_state in CalcJobState:

            calc = orm.CalcJobNode(computer=cls.computer,
                                   process_type=process_type)
            calc.set_option('resources', {
                'num_machines': 1,
                'num_mpiprocs_per_machine': 1
            })
            calc.store()

            calc.set_process_state(ProcessState.RUNNING)
            cls.calcs.append(calc)

            if calculation_state == CalcJobState.PARSING:
                cls.KEY_ONE = 'key_one'
                cls.KEY_TWO = 'key_two'
                cls.VAL_ONE = 'val_one'
                cls.VAL_TWO = 'val_two'

                output_parameters = orm.Dict(dict={
                    cls.KEY_ONE: cls.VAL_ONE,
                    cls.KEY_TWO: cls.VAL_TWO,
                }).store()

                output_parameters.add_incoming(calc, LinkType.CREATE,
                                               'output_parameters')

                # Create shortcut for easy dereferencing
                cls.result_job = calc

                # Add a single calc to a group
                cls.group.add_nodes([calc])

        # Create a single failed CalcJobNode
        cls.EXIT_STATUS = 100
        calc = orm.CalcJobNode(computer=cls.computer)
        calc.set_option('resources', {
            'num_machines': 1,
            'num_mpiprocs_per_machine': 1
        })
        calc.store()
        calc.set_exit_status(cls.EXIT_STATUS)
        calc.set_process_state(ProcessState.FINISHED)
        cls.calcs.append(calc)

        # Load the fixture containing a single ArithmeticAddCalculation node
        import_archive('calcjob/arithmetic.add.aiida')

        # Get the imported ArithmeticAddCalculation node
        ArithmeticAddCalculation = CalculationFactory('arithmetic.add')
        calculations = orm.QueryBuilder().append(
            ArithmeticAddCalculation).all()[0]
        cls.arithmetic_job = calculations[0]