def test_joins3_user_group(self): from aiida.orm.user import User from aiida.orm.querybuilder import QueryBuilder # Create another user new_email = "[email protected]" user = self.backend.users.create(email=new_email) user.store() # Create a group that belongs to that user from aiida.orm.group import Group group = Group(name="node_group") group.user = user group.store() # Search for the group of the user qb = QueryBuilder() qb.append(User, tag='user', filters={'id': {'==': user.id}}) qb.append(Group, belongs_to='user', filters={'id': {'==': group.id}}) self.assertEquals( qb.count(), 1, "The expected group that belongs to " "the selected user was not found.") # Search for the user that owns a group qb = QueryBuilder() qb.append(Group, tag='group', filters={'id': {'==': group.id}}) qb.append(User, owner_of='group', filters={'id': {'==': user.id}}) self.assertEquals( qb.count(), 1, "The expected user that owns the " "selected group was not found.")
def create_cif_data(cls): """Create CifData object.""" with tempfile.NamedTemporaryFile(mode='w+') as fhandle: filename = fhandle.name fhandle.write(cls.valid_sample_cif_str) fhandle.flush() a_cif = CifData(file=filename, source={ 'version': '1234', 'db_name': 'COD', 'id': '0000001' }) a_cif.store() g_ne = Group(label='non_empty_group') g_ne.store() g_ne.add_nodes(a_cif) g_e = Group(label='empty_group') g_e.store() cls.cif = a_cif return { DummyVerdiDataListable.NODE_ID_STR: a_cif.id, DummyVerdiDataListable.NON_EMPTY_GROUP_ID_STR: g_ne.id, DummyVerdiDataListable.EMPTY_GROUP_ID_STR: g_e.id }
def add_to_group(node): try: g = Group.get_from_string('examples') except NotExistent: g = Group(name='examples') g.store() g.add_nodes(node)
def get_group(): try: g = Group.get_from_string('examples') except NotExistent: g = Group(name='examples') g.store() return g
def create_trajectory_data(): """Create TrajectoryData object with two arrays.""" traj = TrajectoryData() # I create sample data stepids = np.array([60, 70]) times = stepids * 0.01 cells = np.array([[[ 2., 0., 0., ], [ 0., 2., 0., ], [ 0., 0., 2., ]], [[ 3., 0., 0., ], [ 0., 3., 0., ], [ 0., 0., 3., ]]]) symbols = ['H', 'O', 'C'] positions = np.array([[[0., 0., 0.], [0.5, 0.5, 0.5], [1.5, 1.5, 1.5]], [[0., 0., 0.], [0.5, 0.5, 0.5], [1.5, 1.5, 1.5]]]) velocities = np.array([[[0., 0., 0.], [0., 0., 0.], [0., 0., 0.]], [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [-0.5, -0.5, -0.5]]]) # I set the node traj.set_trajectory( stepids=stepids, cells=cells, symbols=symbols, positions=positions, times=times, velocities=velocities ) traj.store() # Create 2 groups and add the data to one of them g_ne = Group(label='non_empty_group') g_ne.store() g_ne.add_nodes(traj) g_e = Group(label='empty_group') g_e.store() return { DummyVerdiDataListable.NODE_ID_STR: traj.id, DummyVerdiDataListable.NON_EMPTY_GROUP_ID_STR: g_ne.id, DummyVerdiDataListable.EMPTY_GROUP_ID_STR: g_e.id }
def create_structure_bands(): """Create bands structure object.""" alat = 4. # angstrom cell = [ [ alat, 0., 0., ], [ 0., alat, 0., ], [ 0., 0., alat, ], ] strct = StructureData(cell=cell) strct.append_atom(position=(0., 0., 0.), symbols='Fe') strct.append_atom(position=(alat / 2., alat / 2., alat / 2.), symbols='O') strct.store() @calcfunction def connect_structure_bands(strct): # pylint: disable=unused-argument alat = 4. cell = np.array([ [alat, 0., 0.], [0., alat, 0.], [0., 0., alat], ]) kpnts = KpointsData() kpnts.set_cell(cell) kpnts.set_kpoints([[0., 0., 0.], [0.1, 0.1, 0.1]]) bands = BandsData() bands.set_kpointsdata(kpnts) bands.set_bands([[1.0, 2.0], [3.0, 4.0]]) return bands bands = connect_structure_bands(strct) # Create 2 groups and add the data to one of them g_ne = Group(label='non_empty_group') g_ne.store() g_ne.add_nodes(bands) g_e = Group(label='empty_group') g_e.store() return { DummyVerdiDataListable.NODE_ID_STR: bands.id, DummyVerdiDataListable.NON_EMPTY_GROUP_ID_STR: g_ne.id, DummyVerdiDataListable.EMPTY_GROUP_ID_STR: g_e.id }
def create_structure_bands(): alat = 4. # angstrom cell = [ [ alat, 0., 0., ], [ 0., alat, 0., ], [ 0., 0., alat, ], ] s = StructureData(cell=cell) s.append_atom(position=(0., 0., 0.), symbols='Fe') s.append_atom(position=(alat / 2., alat / 2., alat / 2.), symbols='O') s.store() @calcfunction def connect_structure_bands(structure): alat = 4. cell = np.array([ [alat, 0., 0.], [0., alat, 0.], [0., 0., alat], ]) k = KpointsData() k.set_cell(cell) k.set_kpoints([[0., 0., 0.], [0.1, 0.1, 0.1]]) b = BandsData() b.set_kpointsdata(k) b.set_bands([[1.0, 2.0], [3.0, 4.0]]) return b b = connect_structure_bands(s) # Create 2 groups and add the data to one of them g_ne = Group(label='non_empty_group') g_ne.store() g_ne.add_nodes(b) g_e = Group(label='empty_group') g_e.store() return { TestVerdiDataListable.NODE_ID_STR: b.id, TestVerdiDataListable.NON_EMPTY_GROUP_ID_STR: g_ne.id, TestVerdiDataListable.EMPTY_GROUP_ID_STR: g_e.id }
def create_structure_data(): """Create StructureData object.""" alat = 4. # angstrom cell = [ [ alat, 0., 0., ], [ 0., alat, 0., ], [ 0., 0., alat, ], ] # BaTiO3 cubic structure struc = StructureData(cell=cell) struc.append_atom(position=(0., 0., 0.), symbols='Ba') struc.append_atom(position=(alat / 2., alat / 2., alat / 2.), symbols='Ti') struc.append_atom(position=(alat / 2., alat / 2., 0.), symbols='O') struc.append_atom(position=(alat / 2., 0., alat / 2.), symbols='O') struc.append_atom(position=(0., alat / 2., alat / 2.), symbols='O') struc.store() # Create 2 groups and add the data to one of them g_ne = Group(label='non_empty_group') g_ne.store() g_ne.add_nodes(struc) g_e = Group(label='empty_group') g_e.store() return { DummyVerdiDataListable.NODE_ID_STR: struc.id, DummyVerdiDataListable.NON_EMPTY_GROUP_ID_STR: g_ne.id, DummyVerdiDataListable.EMPTY_GROUP_ID_STR: g_e.id }
def upload_basisset_family(cls, folder, group_name, group_description, stop_if_existing=True, extension=".basis", dry_run=False): """ Upload a set of Basis Set files in a given group. :param folder: a path containing all Basis Set files to be added. Only files ending in the set extension (case-insensitive) are considered. :param group_name: the name of the group to create. If it exists and is non-empty, a UniquenessError is raised. :param group_description: a string to be set as the group description. Overwrites previous descriptions, if the group was existing. :param stop_if_existing: if True, check for the md5 of the files and, if the file already exists in the DB, raises a MultipleObjectsError. If False, simply adds the existing BasisSetData node to the group. :param extension: the filename extension to look for :param dry_run: If True, do not change the database. """ from aiida.common import aiidalogger from aiida.orm import Group from aiida.common.exceptions import UniquenessError, NotExistent from aiida_crystal17.aiida_compatability import get_automatic_user automatic_user = get_automatic_user() if not os.path.isdir(folder): raise ValueError("folder must be a directory") # only files, and only those ending with specified exension; # go to the real file if it is a symlink files = [ os.path.realpath(os.path.join(folder, i)) for i in os.listdir(folder) if os.path.isfile(os.path.join(folder, i)) and i.lower().endswith(extension) ] nfiles = len(files) try: group = Group.get(name=group_name, type_string=BASISGROUP_TYPE) group_created = False except NotExistent: group = Group(name=group_name, type_string=BASISGROUP_TYPE, user=automatic_user) group_created = True if group.user.email != automatic_user.email: raise UniquenessError( "There is already a BasisFamily group with name {}" ", but it belongs to user {}, therefore you " "cannot modify it".format(group_name, group.user.email)) # Always update description, even if the group already existed group.description = group_description # NOTE: GROUP SAVED ONLY AFTER CHECKS OF UNICITY basis_and_created = _retrieve_basis_sets(files, stop_if_existing) # check whether basisset are unique per element elements = [(i[0].element, i[0].md5sum) for i in basis_and_created] # If group already exists, check also that I am not inserting more than # once the same element if not group_created: for aiida_n in group.nodes: # Skip non-basis sets if not isinstance(aiida_n, BasisSetData): continue elements.append((aiida_n.element, aiida_n.md5sum)) elements = set( elements) # Discard elements with the same MD5, that would # not be stored twice elements_names = [e[0] for e in elements] if not len(elements_names) == len(set(elements_names)): duplicates = set( [x for x in elements_names if elements_names.count(x) > 1]) duplicates_string = ", ".join(i for i in duplicates) raise UniquenessError( "More than one Basis found for the elements: " + duplicates_string + ".") # At this point, save the group, if still unstored if group_created and not dry_run: group.store() # save the basis set in the database, and add them to group for basisset, created in basis_and_created: if created: if not dry_run: basisset.store() aiidalogger.debug("New node {0} created for file {1}".format( # pylint: disable=logging-format-interpolation basisset.uuid, basisset.filename)) else: aiidalogger.debug("Reusing node {0} for file {1}".format( # pylint: disable=logging-format-interpolation basisset.uuid, basisset.filename)) # Add elements to the group all together if not dry_run: group.add_nodes(basis for basis, created in basis_and_created) nuploaded = len([_ for _, created in basis_and_created if created]) return nfiles, nuploaded
def upload_psf_family(folder, group_name, group_description, stop_if_existing=True): """ Upload a set of PSF files in a given group. :param folder: a path containing all PSF files to be added. Only files ending in .PSF (case-insensitive) are considered. :param group_name: the name of the group to create. If it exists and is non-empty, a UniquenessError is raised. :param group_description: a string to be set as the group description. Overwrites previous descriptions, if the group was existing. :param stop_if_existing: if True, check for the md5 of the files and, if the file already exists in the DB, raises a MultipleObjectsError. If False, simply adds the existing PsfData node to the group. """ import os import aiida.common from aiida.common import aiidalogger from aiida.orm import Group from aiida.common.exceptions import UniquenessError, NotExistent from aiida.backends.utils import get_automatic_user from aiida.orm.querybuilder import QueryBuilder if not os.path.isdir(folder): raise ValueError("folder must be a directory") # only files, and only those ending with .psf or .PSF; # go to the real file if it is a symlink files = [ os.path.realpath(os.path.join(folder, i)) for i in os.listdir(folder) if os.path.isfile(os.path.join(folder, i)) and i.lower().endswith('.psf') ] nfiles = len(files) try: group = Group.get(name=group_name, type_string=PSFGROUP_TYPE) group_created = False except NotExistent: group = Group(name=group_name, type_string=PSFGROUP_TYPE, user=get_automatic_user()) group_created = True if group.user != get_automatic_user(): raise UniquenessError("There is already a PsfFamily group with name {}" ", but it belongs to user {}, therefore you " "cannot modify it".format( group_name, group.user.email)) # Always update description, even if the group already existed group.description = group_description # NOTE: GROUP SAVED ONLY AFTER CHECKS OF UNICITY pseudo_and_created = [] for f in files: md5sum = aiida.common.utils.md5_file(f) qb = QueryBuilder() qb.append(PsfData, filters={'attributes.md5': {'==': md5sum}}) existing_psf = qb.first() #existing_psf = PsfData.query(dbattributes__key="md5", # dbattributes__tval = md5sum) if existing_psf is None: # return the psfdata instances, not stored pseudo, created = PsfData.get_or_create(f, use_first=True, store_psf=False) # to check whether only one psf per element exists # NOTE: actually, created has the meaning of "to_be_created" pseudo_and_created.append((pseudo, created)) else: if stop_if_existing: raise ValueError("A PSF with identical MD5 to " " {} cannot be added with stop_if_existing" "".format(f)) existing_psf = existing_psf[0] pseudo_and_created.append((existing_psf, False)) # check whether pseudo are unique per element elements = [(i[0].element, i[0].md5sum) for i in pseudo_and_created] # If group already exists, check also that I am not inserting more than # once the same element if not group_created: for aiida_n in group.nodes: # Skip non-pseudos if not isinstance(aiida_n, PsfData): continue elements.append((aiida_n.element, aiida_n.md5sum)) elements = set(elements) # Discard elements with the same MD5, that would # not be stored twice elements_names = [e[0] for e in elements] if not len(elements_names) == len(set(elements_names)): duplicates = set( [x for x in elements_names if elements_names.count(x) > 1]) duplicates_string = ", ".join(i for i in duplicates) raise UniquenessError("More than one PSF found for the elements: " + duplicates_string + ".") # At this point, save the group, if still unstored if group_created: group.store() # save the psf in the database, and add them to group for pseudo, created in pseudo_and_created: if created: pseudo.store() aiidalogger.debug("New node {} created for file {}".format( pseudo.uuid, pseudo.filename)) else: aiidalogger.debug("Reusing node {} for file {}".format( pseudo.uuid, pseudo.filename)) # Add elements to the group all togetehr group.add_nodes(pseudo for pseudo, created in pseudo_and_created) nuploaded = len([_ for _, created in pseudo_and_created if created]) return nfiles, nuploaded
class TbmodelWorkflow(Workflow): ''' AiiDA workflow to get tight binding model of a material using VASP and wannier90. Necessary steps are: * selfconsistent run with few kpoints * nonselfconsistent run with lwannier90 * lwannier90 run with projections block * wannier.x run with hr_plot = True ''' def __init__(self, **kwargs): super(TbmodelWorkflow, self).__init__(**kwargs) self.group = None try: self.group = Group.get_from_string('tbmodel') except NotExistent: self.group = Group(name='tbmodel') self.group.store() def get_calc_maker(self): ''' return an VaspMaker instance. ''' from aiida.orm import Code params = self.get_parameters() maker = VaspMaker(structure=params['structure']) maker.add_settings(icharg=0, istart=0, lorbit=11, lsorbit=True, sigma=0.05, ismear=0, gga='PE', gga_compat=False) maker.code = Code.get_from_string(params['vasp']) # ~ maker.computer = maker.code.get_computer() maker.label = params.get('name') return maker @Workflow.step def start(self): ''' prepare, store and attach the selfconsistent run to get the charge density. ''' params = self.get_parameters() maker = VaspMaker(structure=params['structure'], calc_cls='vasp.scf') maker.rewrite_settings(**params['settings']) kp = params['kpmesh'] maker.kpoints.set_kpoints_mesh(kp) maker.code = Code.get_from_string(params['vasp']) maker.queue = params['queue'] maker.resources['num_machines'] = 4 maker.resources['num_mpiprocs_per_machine'] = 2 maker.label = params.get('name') + ': sc run' calc = maker.new() calc.description = '{}: selfconsistent run'.format(params.get('name')) calc.store_all() calc.set_extras({'experiment': 'tight-binding'}) self.group.add_nodes(calc) self.attach_calculation(calc) self.append_to_report( '{}: starting selfconsistent run, PK={}, uuid={}'.format( params.get('name'), calc.pk, calc.uuid)) self.add_attributes({'scstep': {'pk': calc.pk, 'uuid': calc.uuid}}) self.next(self.winrun) @Workflow.step def winrun(self): ''' prepare, store and attach the non-selfconsistent run to get the wannier input file ''' params = self.get_parameters() # get chgcar from previous step scstep = self.get_attributes()['scstep'] prev = self.get_step_calculations(self.start) sccalc = prev.get(uuid=scstep['uuid']) self.append_to_report('{}: retrieved sc step calculation'.format( params.get('name'))) # set up band structure step maker = VaspMaker(calc_cls='vasp.nscf', continue_from=sccalc) maker.add_settings(lwannier90=True, icharg=11) maker.label = params.get('name') + ': win run' calc = maker.new() calc.description = '{}: win run'.format(params.get('name')) calc.store_all() calc.set_extras({'experiment': 'tight-binding'}) self.group.add_nodes(calc) self.attach_calculation(calc) self.append_to_report('{}: starting win run, PK={}, uuid={}'.format( params.get('name'), calc.pk, calc.uuid)) self.add_attributes({'winstep': {'pk': calc.pk, 'uuid': calc.uuid}}) self.next(self.amnrun) @Workflow.step def amnrun(self): params = self.get_parameters() winstep = self.get_attributes()['winstep'] prev = self.get_step_calculations(self.winrun) wincalc = prev.get(uuid=winstep['uuid']) self.append_to_report('{}: retrieved nscf calculation'.format( params.get('name'))) maker = VaspMaker(calc_cls='vasp.amn', copy_from=wincalc) maker.wannier_settings = wincalc.out.wannier_settings.copy() # ~ maker.wannier_data = wincalc.out.wannier_data num_bands = maker.wannier_settings.get_dict()['num_wann'] maker.wannier_settings.update_dict({'num_bands': num_bands}) maker.wannier_settings.update_dict(params['win']) maker.label = params.get('name') + ': amn run' calc = maker.new() calc.description = '{}: amn run'.format(params.get('name')) calc.store_all() calc.set_extras({'experiment': 'tight-binding'}) self.group.add_nodes(calc) self.attach_calculation(calc) self.append_to_report('{}: starting amn run, PK={}, uuid={}'.format( params.get('name'), calc.pk, calc.uuid)) self.add_attributes({'amnstep': {'pk': calc.pk, 'uuid': calc.uuid}}) self.next(self.wannrun) @Workflow.step def wannrun(self): params = self.get_parameters() amnstep = self.get_attributes()['amnstep'] prev = self.get_step_calculations(self.amnrun) amncalc = prev.get(uuid=amnstep['uuid']) self.append_to_report('{}: retrieved amn calculation'.format( params.get('name'))) calc = CalculationFactory('vasp.wannier')() code = Code.get_from_string(params['wannier_x']) calc.use_code(code) calc.set_computer(code.get_computer()) calc.use_settings(amncalc.inp.wannier_settings) calc.use_data(amncalc.out.wannier_data) calc.label = params.get('name') + ': wannier run' calc.set_resources({'num_machines': 1}) calc.set_queue_name(amncalc.get_queue_name()) calc.description = calc.label calc.store_all() calc.set_extras({'experiment': 'tight-binding'}) self.group.add_nodes(calc) self.attach_calculation(calc) self.add_result('wannier_run', calc) self.append_to_report( '{}: starting wannier run, PK={}, uuid={}'.format( params.get('name'), calc.pk, calc.uuid)) self.add_attributes({'wannstep': {'pk': calc.pk, 'uuid': calc.uuid}}) self.next(self.exit)