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
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
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
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)