def break_symmetry(structure, atoms=['all'], site=[], pos=[], new_kinds_names={}, parameterData=None): """ This routine introduces different 'kind objects' in a structure and names them that inpgen will make different species/atomgroups out of them. If nothing specified breaks ALL symmetry (i.e. every atom gets their own kind) params: StructureData params: atoms: python list of symbols, exp: ['W', 'Be']. This would make for all Be and W atoms their own kinds. params: site: python list of integers, exp: [1, 4, 8]. This would create for atom 1, 4 and 8 their own kinds. params: pos: python list of tuples of 3, exp [(0.0, 0.0, -1.837927), ...]. This will create a new kind for the atom at that position. Be carefull the number given has to match EXACTLY the position in the structure. return: StructureData, a AiiDA crystal structure with new kind specification. """ # TODO proper input checks? from aiida.common.constants import elements as PeriodicTableElements _atomic_numbers = { data['symbol']: num for num, data in PeriodicTableElements.iteritems() } #get all atoms, get the symbol of the atom #if wanted make individual kind for that atom #kind names will be atomsymbol+number #create new structure with new kinds and atoms #Param = DataFactory('parameter') symbol_count = { } # Counts the atom symbol occurence to set id's and kind names right replace = [] # all atoms symbols ('W') to be replaced replace_siteN = [] # all site integers to be replaced replace_pos = [] #all the atom positions to be replaced new_parameterd = None struc = is_structure(structure) if not struc: print 'Error, no structure given' # throw error? cell = struc.cell pbc = struc.pbc sites = struc.sites #natoms = len(sites) new_structure = DataFactory('structure')(cell=cell, pbc=pbc) for sym in atoms: replace.append(sym) for position in pos: replace_pos.append(position) for atom in site: replace_siteN.append(atom) if parameterData: para = parameterData.get_dict() new_parameterd = dict(para) else: new_parameterd = {} for i, site in enumerate(sites): kind_name = site.kind_name pos = site.position kind = struc.get_kind(kind_name) symbol = kind.symbol replace_kind = False if symbol in replace or 'all' in replace: replace_kind = True if pos in replace_pos: replace_kind = True if i in replace_siteN: replace_kind = True if replace_kind: if symbol in symbol_count: symbol_count[symbol] = symbol_count[symbol] + 1 symbol_new_kinds_names = new_kinds_names.get(symbol, []) print(symbol_new_kinds_names) if symbol_new_kinds_names and ((len(symbol_new_kinds_names)) == symbol_count[symbol]): newkindname = symbol_new_kinds_names[symbol_count[symbol] - 1] else: newkindname = '{}{}'.format(symbol, symbol_count[symbol]) else: symbol_count[symbol] = 1 symbol_new_kinds_names = new_kinds_names.get(symbol, []) #print(symbol_new_kinds_names) if symbol_new_kinds_names and ((len(symbol_new_kinds_names)) == symbol_count[symbol]): newkindname = symbol_new_kinds_names[symbol_count[symbol] - 1] else: newkindname = '{}{}'.format(symbol, symbol_count[symbol]) #print(newkindname) new_kind = Kind(name=newkindname, symbols=symbol) new_structure.append_kind(new_kind) # now we have to add an atom list to parameterData with the corresponding id. if parameterData: id_a = symbol_count[ symbol] #'{}.{}'.format(charge, symbol_count[symbol]) #print 'id: {}'.format(id) for key, val in para.iteritems(): if 'atom' in key: if val.get('element', None) == symbol: if id_a and id_a == val.get('id', None): break # we assume the user is smart and provides a para node, # which incooperates the symmetry breaking already elif id_a: # != 1: # copy parameter of symbol and add id val_new = dict(val) # getting the charge over element might be risky charge = _atomic_numbers.get( (val.get('element'))) idp = '{}.{}'.format(charge, symbol_count[symbol]) idp = float("{0:.2f}".format(float(idp))) # dot cannot be stored in AiiDA dict... val_new.update({u'id': idp}) atomlistname = 'atom{}'.format(id_a) i = 0 while new_parameterd.get(atomlistname, {}): i = i + 1 atomlistname = 'atom{}'.format(id_a + i) symbol_new_kinds_names = new_kinds_names.get( symbol, []) #print(symbol_new_kinds_names) if symbol_new_kinds_names and ( (len(symbol_new_kinds_names)) == symbol_count[symbol]): species_name = symbol_new_kinds_names[ symbol_count[symbol] - 1] val_new.update({u'name': species_name}) new_parameterd[atomlistname] = val_new else: pass #TODO write basic parameter data node else: newkindname = kind_name if not kind_name in new_structure.get_kind_names(): new_structure.append_kind(kind) new_structure.append_site(Site(kind_name=newkindname, position=pos)) #print 'natoms: {}, nkinds: {}'.format(natoms, len(new_structure.get_kind_names())) if parameterData: para_new = ParameterData(dict=new_parameterd) else: para_new = None new_structure.label = structure.label new_structure.description = structure.description + 'more kinds, less sym' return new_structure, para_new
def supercell_nwf( inp_structure, n_a1, n_a2, n_a3 ): #, _label=u'supercell_wf', _description=u'WF, Creates a supercell of a crystal structure x(n1,n2,n3).'):# be carefull you have to use AiiDA datatypes... """ Creates a super cell from a StructureData node. Does NOT keeps the provanance in the database. :param StructureData, a StructureData node (pk, or uuid) :param scale: tuple of 3 AiiDA integers, number of cells in a1, a2, a3, or if cart =True in x,y,z :returns StructureData, Node with supercell """ #print('in create supercell') #test if structure: structure = is_structure(inp_structure) if not structure: #TODO: log something return None old_cell = structure.cell old_a1 = old_cell[0] old_a2 = old_cell[1] old_a3 = old_cell[2] old_sites = structure.sites old_pbc = structure.pbc na1 = int(n_a1) na2 = int(n_a2) na3 = int(n_a3) #new cell new_a1 = [i * na1 for i in old_a1] new_a2 = [i * na2 for i in old_a2] new_a3 = [i * na3 for i in old_a3] new_cell = [new_a1, new_a2, new_a3] new_structure = DataFactory('structure')(cell=new_cell, pbc=old_pbc) #insert atoms # first create all kinds old_kinds = structure.kinds for kind in old_kinds: new_structure.append_kind(kind) #scale n_a1 for site in old_sites: # get atom position kn = site.kind_name pos_o = site.position for j in range(na1): pos = [pos_o[i] + j * old_a1[i] for i in range(0, len(old_a1))] new_structure.append_site(Site(kind_name=kn, position=pos)) #scale n_a2 o_sites = new_structure.sites for site in o_sites: # get atom position kn = site.kind_name pos_o = site.position for j in range(1, na2): # j=0 these sites/atoms are already added pos = [pos_o[i] + j * old_a2[i] for i in range(0, len(old_a2))] new_structure.append_site(Site(kind_name=kn, position=pos)) #scale n_a3 o_sites = new_structure.sites for site in o_sites: # get atom position kn = site.kind_name pos_o = site.position for j in range(1, na3): # these sites/atoms are already added pos = [pos_o[i] + j * old_a3[i] for i in range(0, len(old_a3))] new_structure.append_site(Site(kind_name=kn, position=pos)) new_structure.label = 'supercell of {}'.format(formula) new_structure.description = '{}x{}x{} supercell of {}'.format( n_a1, n_a2, n_a3, inp_structure.get_formula()) return new_structure