def test_create_from_folder_with_parameters(clear_db, filepath_pseudos,
                                            sssp_parameter_filepath):
    """Test the `SsspFamily.create_from_folder` class method when passing a file with pseudo metadata."""
    with pytest.raises(TypeError):
        SsspFamily.create_from_folder(filepath_pseudos,
                                      'SSSP',
                                      filepath_parameters={})

    # Test directly from filepath
    family = SsspFamily.create_from_folder(
        filepath_pseudos,
        'SSSP/1.0',
        filepath_parameters=sssp_parameter_filepath)
    assert isinstance(family, SsspFamily)
    assert family.is_stored

    parameters = family.get_parameters_node()
    assert parameters.family_uuid == family.uuid

    # Test from filelike object
    with open(sssp_parameter_filepath) as handle:
        family = SsspFamily.create_from_folder(filepath_pseudos,
                                               'SSSP/1.1',
                                               filepath_parameters=handle)
        assert isinstance(family, SsspFamily)
        assert family.is_stored

        parameters = family.get_parameters_node()
        assert parameters.family_uuid == family.uuid
def test_construct(clear_db):
    """Test the construction of `SsspFamily` works."""
    family = SsspFamily(label='SSSP').store()
    assert isinstance(family, SsspFamily)

    description = 'SSSP description'
    family = SsspFamily(label='SSSP/v1.1', description=description).store()
    assert isinstance(family, SsspFamily)
    assert family.description == description
def test_elements(clear_db, get_upf_data):
    """Test the `SsspFamily.elements` property."""
    upf_he = get_upf_data(element='He').store()
    upf_ne = get_upf_data(element='Ne').store()
    upf_ar = get_upf_data(element='Ar').store()
    family = SsspFamily(label='SSSP').store()

    family.add_nodes([upf_he, upf_ne, upf_ar])
    assert family.count() == 3
    assert sorted(family.elements) == ['Ar', 'He', 'Ne']
def test_load(clear_db):
    """Test that loading of a `SsspFamily` through `load_group` works."""
    family = SsspFamily(label='SSSP').store()
    assert isinstance(family, SsspFamily)

    loaded = orm.load_group(family.pk)
    assert isinstance(family, SsspFamily)
    assert loaded.uuid == family.uuid
    assert loaded.elements == family.elements
def test_create_from_folder(clear_db, filepath_pseudos):
    """Test the `SsspFamily.create_from_folder` class method."""
    label = 'SSSP'
    family = SsspFamily.create_from_folder(filepath_pseudos, label)

    assert isinstance(family, SsspFamily)
    assert family.is_stored
    assert family.count() == len(os.listdir(filepath_pseudos))
    assert sorted(family.elements) == sorted(
        [filename.rstrip('.upf') for filename in os.listdir(filepath_pseudos)])

    # Cannot create another family with the same label
    with pytest.raises(ValueError):
        SsspFamily.create_from_folder(filepath_pseudos, label)

    with pytest.raises(TypeError) as exception:
        SsspFamily.create_from_folder(filepath_pseudos, label, description=1)
    assert 'Got object of type' in str(exception.value)
def test_create_from_folder_invalid(clear_db, filepath_pseudos):
    """Test the `SsspFamily.create_from_folder` class method for invalid inputs."""
    label = 'SSSP'

    with tempfile.TemporaryDirectory() as dirpath:

        # Non-existing directory should raise
        with pytest.raises(ValueError) as exception:
            SsspFamily.create_from_folder(
                os.path.join(dirpath, 'non-existing'), label)

        assert 'is not a directory' in str(exception.value)
        assert SsspFamily.objects.count() == 0
        assert orm.UpfData.objects.count() == 0

        distutils.dir_util.copy_tree(filepath_pseudos, dirpath)

        # Copy an existing pseudo to test that duplicate elements are not allowed
        filename = os.listdir(dirpath)[0]
        filepath = os.path.join(dirpath, filename)
        shutil.copy(filepath, os.path.join(dirpath, filename[:-4] + '2.upf'))

        with pytest.raises(ValueError) as exception:
            SsspFamily.create_from_folder(dirpath, label)

        assert 'contains pseudo potentials with duplicate elements' in str(
            exception.value)
        assert SsspFamily.objects.count() == 0
        assert orm.UpfData.objects.count() == 0

        # Create an empty folder in the pseudo directory, which is not allowed
        dirpath_sub = os.path.join(dirpath, 'random_sub_folder')
        os.makedirs(dirpath_sub)

        with pytest.raises(ValueError) as exception:
            SsspFamily.create_from_folder(dirpath, label)

        assert 'contains at least one entry that is not a file' in str(
            exception.value)
        assert SsspFamily.objects.count() == 0
        assert orm.UpfData.objects.count() == 0
        os.rmdir(dirpath_sub)

        # Create a dummy file that does not have a valid UPF format
        with open(filepath, 'w') as handle:
            handle.write('invalid pseudo format')

        with pytest.raises(ValueError) as exception:
            SsspFamily.create_from_folder(dirpath, label)

        assert 'failed to parse' in str(exception.value)
        assert SsspFamily.objects.count() == 0
        assert orm.UpfData.objects.count() == 0
def test_validate_parameters(clear_db, create_sssp_family,
                             create_sssp_parameters):
    """Test the `SsspFamily.validate_parameters` class method."""
    family = create_sssp_family()
    parameters = create_sssp_parameters()
    metadata = parameters.get_metadata()

    SsspFamily.validate_parameters(list(family.nodes), parameters)

    # Incorrect filename
    incorrect = copy.deepcopy(metadata['Ar'])
    incorrect['filename'] = 'wrong_file_name'
    parameters.set_attribute('Ar', incorrect)

    with pytest.raises(ValueError) as exception:
        SsspFamily.validate_parameters(list(family.nodes), parameters)

    assert 'inconsistent `filename` for element `Ar`' in str(exception.value)

    # Incorrect md5
    incorrect = copy.deepcopy(metadata['Ar'])
    incorrect['md5'] = '123abc'
    parameters.set_attribute('Ar', incorrect)

    with pytest.raises(ValueError) as exception:
        SsspFamily.validate_parameters(list(family.nodes), parameters)

    assert 'inconsistent `md5` for element `Ar`' in str(exception.value)
def generate_inputs_calculation(
        protocol: Dict,
        code: orm.Code,
        structure: StructureData,
        sssp_family: SsspFamily,
        override: Dict[str, Any] = None) -> Dict[str, Any]:
    """Generate the inputs for the `PwCalculation` 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 sssp_family: the pseudo potential family.
    :param override: a dictionary to override specific inputs.
    :return: the fully defined input dictionary.
    """
    natoms = len(structure.sites)
    cutoffs = sssp_family.get_cutoffs(structure=structure)

    etot_conv_thr_per_atom = protocol.pop('etot_conv_thr_per_atom')
    conv_thr_per_atom = protocol.pop('conv_thr_per_atom')

    protocol['parameters']['CONTROL'][
        'etot_conv_thr'] = natoms * etot_conv_thr_per_atom
    protocol['parameters']['ELECTRONS'][
        'conv_thr'] = natoms * conv_thr_per_atom
    protocol['parameters']['SYSTEM']['ecutwfc'] = cutoffs[0]
    protocol['parameters']['SYSTEM']['ecutrho'] = cutoffs[1]

    merged = recursive_merge(protocol, override or {})

    dictionary = {
        'code': code,
        'structure': structure,
        'parameters': orm.Dict(dict=merged['parameters']),
        'pseudos': sssp_family.get_pseudos(structure=structure),
        'metadata': merged.get('metadata', {})
    }

    return dictionary
def test_get_pseudo(clear_db, get_upf_data):
    """Test the `SsspFamily.get_pseudo` property."""
    upf_he = get_upf_data(element='He').store()
    upf_ne = get_upf_data(element='Ne').store()
    upf_ar = get_upf_data(element='Ar').store()
    family = SsspFamily(label='SSSP').store()
    family.add_nodes([upf_he, upf_ne, upf_ar])

    with pytest.raises(ValueError) as exception:
        family.get_pseudo('X')

    assert 'family `{}` does not contain pseudo for element'.format(
        family.label) in str(exception.value)

    element = 'He'
    upf = family.get_pseudo(element)
    assert isinstance(upf, orm.UpfData)
    assert upf.element == element
Exemple #10
0
def create_family_from_archive(label,
                               filepath_archive,
                               filepath_metadata=None,
                               fmt=None):
    """Construct a new `SsspFamily` instance from a tar.gz archive.

    .. warning:: the archive should not contain any subdirectories, but just the pseudos in UPF format.

    :param label: the label for the new family
    :param filepath: absolute filepath to the .tar.gz archive containing the pseudo potentials.
    :param filepath: optional absolute filepath to the .json file containing the pseudo potentials metadata.
    :param fmt: the format of the archive, if not specified will attempt to guess based on extension of `filepath`
    :return: newly created `SsspFamily`
    :raises OSError: if the archive could not be unpacked or pseudos in it could not be parsed into a `SsspFamily`
    """
    import shutil
    import tempfile

    from aiida_sssp.groups import SsspFamily

    with tempfile.TemporaryDirectory() as dirpath:

        try:
            shutil.unpack_archive(filepath_archive, dirpath, format=fmt)
        except shutil.ReadError as exception:
            raise OSError('failed to unpack the archive `{}`: {}'.format(
                filepath_archive, exception))

        try:
            family = SsspFamily.create_from_folder(
                dirpath, label, filepath_parameters=filepath_metadata)
        except ValueError as exception:
            raise OSError('failed to parse pseudos from `{}`: {}'.format(
                dirpath, exception))

    return family
Exemple #11
0
def test_add_nodes(clear_db, get_upf_data):
    """Test the `SsspFamily.add_nodes` method."""
    upf_he = get_upf_data(element='He').store()
    upf_ne = get_upf_data(element='Ne').store()
    upf_ar = get_upf_data(element='Ar').store()
    family = SsspFamily(label='SSSP').store()

    with pytest.raises(TypeError):
        family.add_nodes(orm.Data().store())

    with pytest.raises(TypeError):
        family.add_nodes([orm.Data().store(), orm.Data().store()])

    with pytest.raises(TypeError):
        family.add_nodes([upf_ar, orm.Data().store()])

    assert family.count() == 0

    family.add_nodes(upf_he)
    assert family.count() == 1

    # Check that adding a duplicate element raises, and that no extra nodes have been added.
    with pytest.raises(ValueError):
        family.add_nodes([upf_ar, upf_he, upf_ne])
    assert family.count() == 1

    family.add_nodes([upf_ar, upf_ne])
    assert family.count() == 3
Exemple #12
0
 def factory(label='SSSP/1.1/PBE/efficiency',
             description='SSSP v1.1 PBE efficiency'):
     from aiida_sssp.groups import SsspFamily
     return SsspFamily.create_from_folder(filepath_pseudos, label,
                                          description)