class QEStructure(): def __init__(self, qeConf): """the structure is initialized from PWSCF config file 'lattice' and 'structure' are automatically updated""" self.filename = qeConf.filename self.atomicSpecies = OrderedDict() self.formatString = '%# .8f %# .8f %# .8f' # optConstraints three 1/0 for each coordinate of each atom self.optConstraints = [] self.qeConf = qeConf #self.qeConf.parse() #self.setStructureFromQEInput() self.lattice = None self.structure = None self.nat = None self.ntyp = None def parseInput(self): self.setStructureFromQEInput() def parseOutput(self, pwscfOutputFile): self.setStructureFromPWOutput(pwscfOutputFile) # def _parseAtomicPositions(self, pwscfOut): # for n in range(self.nat): # words = pwscfOut[i + n + 1].split() # atomSymbol = words[0] # coords = [float(w) for w in words[1:4]] # constraint = [] # if len(words) > 4: # constraint = [int(c) for c in words[4:7]] # self.optConstraints.append(numpy.array(constraint, dtype = int)) # print numpy.array(coords[0:3])*a_0 # coords = self.lattice.matter().fractional(numpy.array(coords[0:3])*a_0) # self.structure.addNewAtom(atomSymbol, xyz = numpy.array(coords[0:3])) def setStructureFromPWOutput(self, pwscfOutputFile): """ Loads structure from PWSCF output file. If there was geometry optimization (relax or vc-relax), the structure will be reinitialized from the last step of the optimization """ file = open(pwscfOutputFile) pwscfOut = file.readlines() pseudoList = [] atomList = [] massList = [] self.atomicSpecies = OrderedDict() self.atomicPositionsType = 'alat' # parse beginning: for i, line in enumerate(pwscfOut): if 'lattice parameter (a_0)' in line: a_0 = float(line.split()[4]) if 'bravais-lattice index' in line: ibrav = int(line.split('=')[1]) if 'number of atoms/cell' in line: self.nat = int(line.split('=')[1]) if 'number of atomic types' in line: self.ntyp = int(line.split('=')[1]) if 'PseudoPot.' in line: pseudoList.append(line.split('read from file')[1].strip()) if 'atomic species valence mass pseudopotential' in line: for j in range(self.ntyp): atomList.append(pwscfOut[i+j+1].split()[0]) massList.append(float(pwscfOut[i+j+1].split()[2])) if 'crystal axes: (cart. coord. in units of a_0)' in line: latticeVectors = [[float(f)*a_0 for f in pwscfOut[i + 1].split()[3:6] ], [float(f)*a_0 for f in pwscfOut[i + 2].split()[3:6] ], [float(f)*a_0 for f in pwscfOut[i + 3].split()[3:6] ]] self.lattice = QELattice(ibrav = ibrav, base = latticeVectors) if 'site n. atom positions (a_0 units)' in line: self.structure = Structure(lattice = self.lattice.matter()) for n in range(self.nat): words = pwscfOut[i + n + 1].split() atomSymbol = words[1] coords = [float(w) for w in words[6:9]] constraint = [] self.optConstraints.append(numpy.array(constraint, dtype = int)) #print numpy.array(coords[0:3])*a_0 coords = self.lattice.matter().fractional(numpy.array(coords[0:3])*a_0) self.structure.addNewAtom(atomSymbol, xyz = numpy.array(coords[0:3])) for a, m, p in zip(atomList, massList, pseudoList): self.atomicSpecies[a] = AtomicSpecies(a, m, p) #print 'Input structure from output file: ', self.toString() #Parse end: # Find all geometry optimization steps posList = [i for i,line in enumerate(pwscfOut) if '! total energy' in line] lastSection = pwscfOut[posList[-1]:] for i, line in enumerate(lastSection): if 'CELL_PARAMETERS (alat)' in line: latticeVectors = [[float(f)*a_0 for f in lastSection[i + 1].split() ], [float(f)*a_0 for f in lastSection[i + 2].split() ], [float(f)*a_0 for f in lastSection[i + 3].split() ]] self.lattice = QELattice(ibrav = ibrav, base = latticeVectors) print self.lattice.matter().base if 'ATOMIC_POSITIONS (alat)' in line: self.structure = Structure(lattice = self.lattice.matter()) for n in range(self.nat): words = lastSection[i + n + 1].split() atomSymbol = words[0] coords = [float(w) for w in words[1:4]] constraint = [] if len(words) > 4: constraint = [int(c) for c in words[4:7]] self.optConstraints.append(numpy.array(constraint, dtype = int)) #print numpy.array(coords[0:3])*a_0 coords = self.lattice.matter().fractional(numpy.array(coords[0:3])*a_0) self.structure.addNewAtom(atomSymbol, xyz = numpy.array(coords[0:3])) #self.lattice.ibrav = ibrav #print 'Output structure from output file: ', self.toString() def setStructureFromQEInput(self): """ Loads structure from PWSCF config file""" self.atomicSpecies = OrderedDict() self.lattice = QELattice(qeConf = self.qeConf) self.structure = Structure(lattice = self.lattice.matter()) self.nat = int(self.qeConf.namelist('system').param('nat')) self.ntyp = int(self.qeConf.namelist('system').param('ntyp')) atomicLines = self.qeConf.card('atomic_positions').lines() self.atomicPositionsType = self.qeConf.card('atomic_positions').arg() if self.atomicPositionsType == 'bohr' or self.atomicPositionsType == 'angstrom': raise NotImplementedError if self.atomicPositionsType == None: self.atomicPositionsType = 'alat' for line in atomicLines: if '!' not in line: words = line.split() coords = [float(w) for w in words[1:4]] constraint = [] if len(words) > 4: constraint = [int(c) for c in words[4:7]] self.optConstraints.append(numpy.array(constraint, dtype = int)) atomSymbol = words[0] if self.atomicPositionsType == 'alat': coords = self.lattice.matter().fractional(numpy.array(coords[0:3])*self.lattice.a0) if self.atomicPositionsType == 'crystal': coords = numpy.array(coords[0:3]) self.structure.addNewAtom(atomSymbol, xyz = numpy.array(coords[0:3])) # parse mass ATOMIC_SPECIES section: atomicSpeciesLines = self.qeConf.card('atomic_species').lines() for line in atomicSpeciesLines: if '!' not in line: atomicSpeciesWords = line.split() element = atomicSpeciesWords[0] mass = float(atomicSpeciesWords[1]) ps = atomicSpeciesWords[2] self.atomicSpecies[element] = AtomicSpecies(element, mass, ps) def toString(self): s = self.lattice.toString() + '\n' if self.atomicPositionsType == 'alat': s = s + 'Atomic positions in units of lattice parametr "a":\n' if self.atomicPositionsType == 'crystal': s = s + 'Atomic positions in crystal coordinates:\n' for atom, constraint in zip(self.structure, self.optConstraints): if self.atomicPositionsType == 'alat': coords = self.lattice.matter().cartesian(atom.xyz)/self.lattice.a coords = self.formatString%(coords[0], coords[1], coords[2]) #coords = str(coords/self.lattice.a)[1:-1] else: if self.atomicPositionsType == 'crystal': #coords = str(atom.xyz)[1:-1] coords = self.formatString%(v[0], v[1], v[2])%(atom.xyz[0], atom.xyz[1], atom.xyz[2]) else: raise NonImplementedError s = s + '%-3s'%atom.element + ' ' + coords + ' ' \ + str(constraint)[1:-1] + '\n' s = s + '\n' for element, specie in self.atomicSpecies.items(): s = s + specie.toString() + '\n' return s def updatePWInput(self, qeConf = None): if qeConf == None: qeConf = self.qeConf self.lattice.updatePWInput(qeConf) qeConf.namelist('system').remove('ntyp') qeConf.namelist('system').remove('nat') qeConf.namelist('system').add('ntyp', self.ntyp) qeConf.namelist('system').add('nat', self.nat) if 'atomic_positions' in qeConf.cards: qeConf.removeCard('atomic_positions') qeConf.createCard('atomic_positions') qeConf.card('atomic_positions').setArg(self.atomicPositionsType) for atom, constraint in zip(self.structure, self.optConstraints): if self.atomicPositionsType == 'alat': coords = self.lattice.matter().cartesian(atom.xyz)/self.lattice.a coords = self.formatString%(coords[0], coords[1], coords[2]) else: if self.atomicPositionsType == 'crystal': #coords = str(atom.xyz)[1:-1] coords = self.formatString%(atom.xyz[0], atom.xyz[1], atom.xyz[2]) else: raise NonImplementedError line = '%-3s'%atom.element + ' ' + coords + ' ' + str(constraint)[1:-1] # line = atom.element + ' ' + coords + ' ' + str(constraint)[1:-1] qeConf.card('atomic_positions').addLine(line) # update ATOMIC_SPECIES card if 'atomic_species' in qeConf.cards: qeConf.removeCard('atomic_species') qeConf.createCard('atomic_species') for element, specie in self.atomicSpecies.items(): qeConf.card('atomic_species').addLine(specie.toString()) def save(self, fname = None): """Writes/updates structure into PW config file, if the file does not exist, new one will be created""" if fname != None: filename = fname self.lattice.save(filename) qeConf = QEInput(fname) qeConf.parse() else: filename = self.filename self.lattice.save(filename) qeConf = self.qeConf #qeConf.parse() self.updatePWInput(qeConf ) qeConf.save(filename) def diffpy(self): return self.structure
class QEStructure(): def __init__(self, qeConf): """the structure is initialized from PWSCF config file 'lattice' and 'structure' are automatically updated""" self.filename = qeConf.filename self.atomicSpecies = OrderedDict() self.formatString = '%# .8f %# .8f %# .8f' # optConstraints three 1/0 for each coordinate of each atom self.optConstraints = [] self.qeConf = qeConf self.lattice = QELattice() self.structure = Structure(lattice=self.lattice.diffpy()) self.nat = None self.ntyp = None def parseInput(self): self.setStructureFromQEInput() def parseOutput(self, pwscfOutputFile): self.setStructureFromPWOutput(pwscfOutputFile) def setStructureFromPWOutput(self, pwscfOutputFile): """ Loads structure from PWSCF output file. If there was geometry optimization (relax or vc-relax), the structure will be reinitialized from the last step of the optimization """ file = open(pwscfOutputFile) pwscfOut = file.readlines() pseudoList = [] atomList = [] massList = [] self.atomicSpecies = OrderedDict() self.atomicPositionsType = 'alat' # parse beginning: for i, line in enumerate(pwscfOut): if 'lattice parameter (a_0)' in line: a_0 = float(line.split()[4]) if 'bravais-lattice index' in line: ibrav = int(line.split('=')[1]) if 'number of atoms/cell' in line: self.nat = int(line.split('=')[1]) if 'number of atomic types' in line: self.ntyp = int(line.split('=')[1]) if 'PseudoPot.' in line: pseudoList.append(line.split('read from file')[1].strip()) if 'atomic species valence mass pseudopotential' in line: for j in range(self.ntyp): atomList.append(pwscfOut[i + j + 1].split()[0]) massList.append(float(pwscfOut[i + j + 1].split()[2])) if 'crystal axes: (cart. coord. in units of a_0)' in line: latticeVectors = [ [float(f) * a_0 for f in pwscfOut[i + 1].split()[3:6]], [float(f) * a_0 for f in pwscfOut[i + 2].split()[3:6]], [float(f) * a_0 for f in pwscfOut[i + 3].split()[3:6]] ] self.lattice.setLatticeFromQEVectors(ibrav, latticeVectors) if 'site n. atom positions (a_0 units)' in line: self.structure = Structure(lattice=self.lattice.diffpy()) for n in range(self.nat): words = pwscfOut[i + n + 1].split() atomSymbol = words[1] coords = [float(w) for w in words[6:9]] constraint = [] self.optConstraints.append( numpy.array(constraint, dtype=int)) #print numpy.array(coords[0:3])*a_0 coords = self.lattice.diffpy().fractional( numpy.array(coords[0:3]) * a_0) self.structure.addNewAtom(atomSymbol, xyz=numpy.array(coords[0:3])) for a, m, p in zip(atomList, massList, pseudoList): self.atomicSpecies[a] = AtomicSpecies(a, m, p) #print 'Input structure from output file: ', self.toString() #Parse end: # Find all geometry optimization steps posList = [ i for i, line in enumerate(pwscfOut) if '! total energy' in line ] lastSection = pwscfOut[posList[-1]:] for i, line in enumerate(lastSection): if 'CELL_PARAMETERS (alat)' in line: latticeVectors = [ [float(f) * a_0 for f in lastSection[i + 1].split()], [float(f) * a_0 for f in lastSection[i + 2].split()], [float(f) * a_0 for f in lastSection[i + 3].split()] ] self.lattice.setLatticeFromQEVectors(ibrav, latticeVectors) #self.lattice = QELattice(ibrav = ibrav, base = latticeVectors) print self.lattice.diffpy().base if 'ATOMIC_POSITIONS (alat)' in line: self.structure = Structure(lattice=self.lattice.diffpy()) for n in range(self.nat): words = lastSection[i + n + 1].split() atomSymbol = words[0] coords = [float(w) for w in words[1:4]] constraint = [] if len(words) > 4: constraint = [int(c) for c in words[4:7]] self.optConstraints.append( numpy.array(constraint, dtype=int)) coords = self.lattice.diffpy().fractional( numpy.array(coords[0:3]) * a_0) self.structure.addNewAtom(atomSymbol, xyz=numpy.array(coords[0:3])) def setStructureFromQEInput(self): """ Loads structure from PWSCF config file""" self.atomicSpecies = OrderedDict() self.lattice.setLatticeFromPWInput(self.qeConf) #self.lattice = QELattice(qeConf = self.qeConf) self.structure = Structure(lattice=self.lattice.diffpy()) self.nat = int(self.qeConf.namelist('system').param('nat')) self.ntyp = int(self.qeConf.namelist('system').param('ntyp')) atomicLines = self.qeConf.card('atomic_positions').lines() self.atomicPositionsType = self.qeConf.card('atomic_positions').arg() if self.atomicPositionsType == 'bohr' or self.atomicPositionsType == 'angstrom': raise NotImplementedError if self.atomicPositionsType == None: self.atomicPositionsType = 'alat' for line in atomicLines: if '!' not in line: words = line.split() coords = [float(w) for w in words[1:4]] constraint = [] if len(words) > 4: constraint = [int(c) for c in words[4:7]] self.optConstraints.append(numpy.array(constraint, dtype=int)) atomSymbol = words[0] if self.atomicPositionsType == 'alat': coords = self.lattice.diffpy().fractional( numpy.array(coords[0:3]) * self.lattice.a0) if self.atomicPositionsType == 'crystal': coords = numpy.array(coords[0:3]) self.structure.addNewAtom(atomSymbol, xyz=numpy.array(coords[0:3])) # parse mass ATOMIC_SPECIES section: atomicSpeciesLines = self.qeConf.card('atomic_species').lines() for line in atomicSpeciesLines: if '!' not in line: atomicSpeciesWords = line.split() element = atomicSpeciesWords[0] mass = float(atomicSpeciesWords[1]) ps = atomicSpeciesWords[2] self.atomicSpecies[element] = AtomicSpecies( element, mass, ps) def toString(self): s = self.lattice.toString() + '\n' if self.atomicPositionsType == 'alat': s = s + 'Atomic positions in units of lattice parametr "a":\n' if self.atomicPositionsType == 'crystal': s = s + 'Atomic positions in crystal coordinates:\n' for atom, constraint in zip(self.structure, self.optConstraints): if self.atomicPositionsType == 'alat': coords = self.lattice.diffpy().cartesian( atom.xyz) / self.lattice.a coords = self.formatString % (coords[0], coords[1], coords[2]) else: if self.atomicPositionsType == 'crystal': coords = self.formatString % (v[0], v[1], v[2]) % ( atom.xyz[0], atom.xyz[1], atom.xyz[2]) else: raise NonImplementedError s = s + '%-3s'%atom.element + ' ' + coords + ' ' \ + str(constraint)[1:-1] + '\n' s = s + '\n' for element, specie in self.atomicSpecies.items(): s = s + specie.toString() + '\n' return s def updatePWInput(self, qeConf=None): if qeConf == None: qeConf = self.qeConf self.lattice.updatePWInput(qeConf) qeConf.namelist('system').remove('ntyp') qeConf.namelist('system').remove('nat') qeConf.namelist('system').add('ntyp', self.ntyp) qeConf.namelist('system').add('nat', self.nat) if 'atomic_positions' in qeConf.cards: qeConf.removeCard('atomic_positions') qeConf.createCard('atomic_positions') qeConf.card('atomic_positions').setArg(self.atomicPositionsType) for atom, constraint in zip(self.structure, self.optConstraints): if self.atomicPositionsType == 'alat': coords = self.lattice.diffpy().cartesian( atom.xyz) / self.lattice.a coords = self.formatString % (coords[0], coords[1], coords[2]) else: if self.atomicPositionsType == 'crystal': coords = self.formatString % (atom.xyz[0], atom.xyz[1], atom.xyz[2]) else: raise NonImplementedError line = '%-3s' % atom.element + ' ' + coords + ' ' + str( constraint)[1:-1] qeConf.card('atomic_positions').addLine(line) # update ATOMIC_SPECIES card if 'atomic_species' in qeConf.cards: qeConf.removeCard('atomic_species') qeConf.createCard('atomic_species') for element, specie in self.atomicSpecies.items(): qeConf.card('atomic_species').addLine(specie.toString()) def save(self, fname=None): """Writes/updates structure into PW config file, if the file does not exist, new one will be created""" if fname != None: filename = fname self.lattice.save(filename) qeConf = QEInput(fname) qeConf.parse() else: filename = self.filename self.lattice.save(filename) qeConf = self.qeConf self.updatePWInput(qeConf) qeConf.save(filename) def diffpy(self): return self.structure
class QEStructure(): def __init__(self, qeConf): """the structure is initialized from PWSCF config file 'lattice' and 'structure' are automatically updated""" self.filename = qeConf.filename self.atomicSpecies = OrderedDict() self.formatString = '%# .8f %# .8f %# .8f' # optConstraints three 1/0 for each coordinate of each atom self.optConstraints = [] self.qeConf = qeConf self.lattice = QELattice() self.structure = Structure(lattice = self.lattice.diffpy()) self.nat = None self.ntyp = None self.atomicPositionsType = 'crystal' def atomLabels(self): labels = [] for l in self.atomicSpecies: labels.append(l) return labels def parseInput(self): self.setStructureFromQEInput() def parseOutput(self, pwscfOutputFile): self.setStructureFromPWOutput(pwscfOutputFile) def setStructureFromPWOutput(self, pwscfOutputFile): """ Loads structure from PWSCF output file. If there was geometry optimization (relax or vc-relax), the structure will be reinitialized from the last step of the optimization """ file = open(pwscfOutputFile) pwscfOut = file.readlines() pseudoList = [] atomList = [] massList = [] self.atomicSpecies = OrderedDict() self.atomicPositionsType = 'alat' # parse beginning: for i, line in enumerate(pwscfOut): if 'lattice parameter (a_0)' in line: a_0 = float(line.split()[4]) if 'bravais-lattice index' in line: ibrav = int(line.split('=')[1]) if 'number of atoms/cell' in line: self.nat = int(line.split('=')[1]) if 'number of atomic types' in line: self.ntyp = int(line.split('=')[1]) if 'PseudoPot.' in line: pseudoList.append(line.split('read from file')[1].strip()) if 'atomic species valence mass pseudopotential' in line: for j in range(self.ntyp): atomList.append(pwscfOut[i+j+1].split()[0]) massList.append(float(pwscfOut[i+j+1].split()[2])) if 'crystal axes: (cart. coord. in units of a_0)' in line: latticeVectors = [[float(f)*a_0 for f in pwscfOut[i + 1].split()[3:6] ], [float(f)*a_0 for f in pwscfOut[i + 2].split()[3:6] ], [float(f)*a_0 for f in pwscfOut[i + 3].split()[3:6] ]] self.lattice.setLatticeFromQEVectors(ibrav, latticeVectors) if 'site n. atom positions (a_0 units)' in line: self.structure = Structure(lattice = self.lattice.diffpy()) for n in range(self.nat): words = pwscfOut[i + n + 1].split() atomSymbol = words[1] coords = [float(w) for w in words[6:9]] constraint = [] self.optConstraints.append(numpy.array(constraint, dtype = int)) #print numpy.array(coords[0:3])*a_0 coords = self.lattice.diffpy().fractional(numpy.array(coords[0:3])*a_0) self.structure.addNewAtom(atomSymbol, xyz = numpy.array(coords[0:3])) for a, m, p in zip(atomList, massList, pseudoList): self.atomicSpecies[a] = AtomicSpecies(a, m, p) #print 'Input structure from output file: ', self.toString() #Parse end: # Find all geometry optimization steps posList = [i for i,line in enumerate(pwscfOut) if '! total energy' in line] lastSection = pwscfOut[posList[-1]:] for i, line in enumerate(lastSection): if 'CELL_PARAMETERS (alat)' in line: latticeVectors = [[float(f)*a_0 for f in lastSection[i + 1].split() ], [float(f)*a_0 for f in lastSection[i + 2].split() ], [float(f)*a_0 for f in lastSection[i + 3].split() ]] self.lattice.setLatticeFromQEVectors(ibrav, latticeVectors) #self.lattice = QELattice(ibrav = ibrav, base = latticeVectors) #print self.lattice.diffpy().base if 'ATOMIC_POSITIONS (alat)' in line: self.structure = Structure(lattice = self.lattice.diffpy()) for n in range(self.nat): words = lastSection[i + n + 1].split() atomSymbol = words[0] coords = [float(w) for w in words[1:4]] constraint = [] if len(words) > 4: constraint = [int(c) for c in words[4:7]] self.optConstraints.append(numpy.array(constraint, dtype = int)) coords = self.lattice.diffpy().fractional(numpy.array(coords[0:3])*a_0) self.structure.addNewAtom(atomSymbol, xyz = numpy.array(coords[0:3])) def setStructureFromQEInput(self): """ Loads structure from PWSCF config file""" self.atomicSpecies = OrderedDict() self.lattice.setLatticeFromPWInput(self.qeConf) #self.lattice = QELattice(qeConf = self.qeConf) self.structure = Structure(lattice = self.lattice.diffpy()) self.nat = self.ntyp = None self.filename = self.qeConf.filename self.optConstraints = [] if 'system' in self.qeConf.namelists: self.nat = int(self.qeConf.namelist('system').param('nat')) self.ntyp = int(self.qeConf.namelist('system').param('ntyp')) if 'atomic_positions' in self.qeConf.cards: atomicLines = self.qeConf.card('atomic_positions').lines() self.atomicPositionsType = self.qeConf.card('atomic_positions').arg() if self.atomicPositionsType == 'bohr' or self.atomicPositionsType == 'angstrom': raise NotImplementedError if self.atomicPositionsType == None: self.atomicPositionsType = 'alat' for line in atomicLines: if '!' not in line: words = line.split() coords = [float(w) for w in words[1:4]] constraint = [] if len(words) > 4: constraint = [int(c) for c in words[4:7]] self.optConstraints.append(numpy.array(constraint, dtype = int)) atomSymbol = words[0] if self.atomicPositionsType == 'alat': coords = self.lattice.diffpy().fractional(numpy.array(coords[0:3])*self.lattice.a0) if self.atomicPositionsType == 'crystal': coords = numpy.array(coords[0:3]) self.structure.addNewAtom(atomSymbol, xyz = numpy.array(coords[0:3])) # parse mass ATOMIC_SPECIES section: if 'atomic_species' in self.qeConf.cards: atomicSpeciesLines = self.qeConf.card('atomic_species').lines() for line in atomicSpeciesLines: if '!' not in line: if line.strip() != '': atomicSpeciesWords = line.split() element = atomicSpeciesWords[0] mass = 0 ps = '' if len(atomicSpeciesWords) > 1 : mass = float(atomicSpeciesWords[1]) if len(atomicSpeciesWords) > 2: ps = atomicSpeciesWords[2] self.atomicSpecies[element] = AtomicSpecies(element, mass, ps) def load(self, source, **args): task = { 'diffpy': self.setStructureFromDiffpyStructure } if source == 'diffpy': if 'ibrav' in args and args['ibrav'] != 0: task['diffpy'] = self.setReducedStructureFromDiffpyStructure task[source](**args) self.updatePWInput(qeConf = self.qeConf) def setStructureFromDiffpyStructure(self, structure, massList = [], psList = [], ibrav = 0): """ structure - diffpy.Structure object ibrav - Lattice index psList - list of strings with pseudopotential names diffpyStructure object will be modified with reduced atomic positions """ diffpyLattice = structure.lattice self.structure = structure #set lattice and convert to bohr units qeLattice = QELattice(ibrav = 0, a = 1.889725989, base = diffpyLattice.base) self.lattice = qeLattice self.lattice.type = 'generic cubic' atomNames = [] for a in structure: if self._element(a) not in atomNames: atomNames.append(self._element(a)) #print atomNames #print len(massList) for i, elem in enumerate(atomNames): if len(massList) - 1 < i: mass = 0 else: mass = massList[i] if len(psList) - 1 < i: ps = '' else: ps = psList[i] self.atomicSpecies[elem] = AtomicSpecies(elem, mass, ps) for atom in structure: self.optConstraints.append([]) # for i, atom in enumerate(structure): # elem = self._element(atom) # if len(massList) - 1 < i: # mass = 0 # else: # mass = massList[i] # if len(psList) - 1 < i: # ps = '' # else: # ps = psList[i] # self.atomicSpecies[elem] = AtomicSpecies(elem, mass, ps) # self.optConstraints.append([]) # for atom, mass, ps in zip(structure, massList, psList): # elem = self._element(atom) # self.atomicSpecies[elem] = AtomicSpecies(elem, mass, ps) # self.optConstraints.append([]) self.nat = len(structure) self.ntyp = len(self.atomicSpecies) def setReducedStructureFromDiffpyStructure(self, structure, ibrav, massList = [], psList = []): """ structure - diffpy.Structure object ibrav - Lattice index psList - list of strings with pseudopotential names diffpyStructure object will be modified with reduced atomic positions """ #self.atomicSpecies = OrderedDict() #self.optConstraints = [] #self.atomicPositionsType = 'crystal' diffpyLattice = structure.lattice a = diffpyLattice.a b = diffpyLattice.b c = diffpyLattice.c cAB = cosd(diffpyLattice.gamma) cBC = cosd(diffpyLattice.alpha) cAC = cosd(diffpyLattice.beta) qeLattice = QELattice(ibrav = ibrav, a = a, b = b, c = c, cBC = cBC, \ cAC = cAC, cAB = cAB) self.lattice = qeLattice # make a deep copy (does not wok now) #reducedStructure = Structure(diffpyStructure) reducedStructure = structure reducedStructure.placeInLattice(Lattice(base=qeLattice.diffpy().base)) # collect atoms that are at equivalent position to some previous atom duplicates = set([a1 for i0, a0 in enumerate(reducedStructure) for a1 in reducedStructure[i0+1:] if self._element(a0) == self._element(a1) and equalPositions(a0.xyz, a1.xyz, eps=1e-4)]) # Filter out duplicate atoms. Use slice assignment so that # reducedStructure is not replaced with a list. reducedStructure[:] = [a for a in reducedStructure if not a in duplicates] self.structure = reducedStructure atomNames = [] for a in reducedStructure: if self._element(a) not in atomNames: atomNames.append(self._element(a)) #print atomNames #print len(massList) for i, elem in enumerate(atomNames): if len(massList) - 1 < i: mass = 0 else: mass = massList[i] if len(psList) - 1 < i: ps = '' else: ps = psList[i] #print mass, ps # atomDict[a] = # for i, atom in enumerate(reducedStructure): # elem = self._element(atom) # if len(massList) - 1 < i: # mass = 0 # else: # mass = massList[i] # if len(psList) - 1 < i: # ps = '' # else: # ps = psList[i] self.atomicSpecies[elem] = AtomicSpecies(elem, mass, ps) for atom in reducedStructure: self.optConstraints.append([]) # convert to bohr units self.lattice.setLattice(ibrav, self.lattice.a*1.889725989, \ self.lattice.b*1.889725989, self.lattice.c*1.889725989) self.nat = len(reducedStructure) self.ntyp = len(self.atomicSpecies) # use rstrip to avoid duplicate line feed #print reducedStructure.writeStr(format='discus').rstrip() #print reducedStructure.writeStr(format='discus') #print reducedStructure.writeStr().rstrip() #print reducedStructure #self.lattice = setLatticeFromDiffpyLattice(structure.lattice, ibrav) # def toString(self): # s = self.lattice.toString() + '\n' # if self.atomicPositionsType == 'alat': # s = s + 'Atomic positions in units of lattice parametr "a":\n' # if self.atomicPositionsType == 'crystal': # s = s + 'Atomic positions in crystal coordinates:\n' # for atom, constraint in zip(self.structure, self.optConstraints): # if self.atomicPositionsType == 'alat': # coords = self.lattice.diffpy().cartesian(atom.xyz)/self.lattice.a # coords = self.formatString%(coords[0], coords[1], coords[2]) # else: # if self.atomicPositionsType == 'crystal': # coords = self.formatString%(atom.xyz[0], atom.xyz[1], atom.xyz[2]) # else: # raise NonImplementedError # s = s + '%-3s'%self._element(atom) + ' ' + coords + ' ' \ # + str(constraint)[1:-1] + '\n' # s = s + '\n' # for element, specie in self.atomicSpecies.items(): # s = s + specie.toString() + '\n' # return s def toString(self, string = None): if string != None: string = self.lattice.toString(string = string) qeConf = QEInput(config = string) qeConf.parse() else: if self.qeConf != None: qeConf = self.qeConf else: qeConf = QEInput(config = '') self.updatePWInput(qeConf) return qeConf.toString() def updatePWInput(self, qeConf = None): if qeConf == None: qeConf = self.qeConf self.lattice.updatePWInput(qeConf) if 'system' not in qeConf.namelists: qeConf.addNamelist('system') qeConf.namelist('system').remove('ntyp') qeConf.namelist('system').remove('nat') if self.ntyp != None: qeConf.namelist('system').add('ntyp', self.ntyp) if self.nat != None: qeConf.namelist('system').add('nat', self.nat) if len(qeConf.namelist('system').params) == 0: qeConf.removeNamelist('system') if 'atomic_positions' in qeConf.cards: qeConf.removeCard('atomic_positions') qeConf.createCard('atomic_positions') qeConf.card('atomic_positions').setArg(self.atomicPositionsType) for atom, constraint in zip(self.structure, self.optConstraints): if self.atomicPositionsType == 'alat': coords = self.lattice.diffpy().cartesian(atom.xyz)/self.lattice.a coords = self.formatString%(coords[0], coords[1], coords[2]) else: if self.atomicPositionsType == 'crystal': coords = self.formatString%(atom.xyz[0], atom.xyz[1], atom.xyz[2]) else: raise NonImplementedError line = '%-3s'%self._element(atom) + ' ' + coords + ' ' + str(constraint)[1:-1] qeConf.card('atomic_positions').addLine(line) if len(qeConf.card('atomic_positions').lines()) == 0: qeConf.removeCard('atomic_positions') # update ATOMIC_SPECIES card if 'atomic_species' in qeConf.cards: qeConf.removeCard('atomic_species') qeConf.createCard('atomic_species') for element, specie in self.atomicSpecies.items(): qeConf.card('atomic_species').addLine(specie.toString()) if len(qeConf.card('atomic_species').lines()) == 0: qeConf.removeCard('atomic_species') def save(self, fname = None): """Writes/updates structure into PW config file, if the file does not exist, new one will be created""" filename = fname if fname != None: self.lattice.save(filename) qeConf = QEInput(fname) qeConf.parse() else: filename = self.filename self.lattice.save(filename) qeConf = self.qeConf self.updatePWInput(qeConf) qeConf.save(filename) def diffpy(self): return self.structure def _element(self, atom): """ Is needed for suport both diffpy and matter classess """ if 'element' in dir(atom): return atom.element else: if 'symbol' in dir(atom): return atom.symbol else: raise