diff --git a/util/qso.py b/util/qso.py new file mode 100644 index 0000000..960bde6 --- /dev/null +++ b/util/qso.py @@ -0,0 +1,153 @@ +#!/usr/bin/python +import xml.sax +# quantum-simulation.org (QSO) definitions +class Atom: + def __init__(self,name,species,pos,vel): + self.name = name + self.species = species + self.position = pos + self.velocity = vel + +class Species: + def __init__(self,name,href,symbol,atomic_number,mass): + self.name = name + self.href = href + self.symbol = symbol + self.atomic_number = atomic_number + self.mass = mass + +class UnitCell: + def __init__(self): + a = [] + b = [] + c = [] + +class AtomSet: + def __init__(self): + self.atom_list = [] + self.species_list = [] + self.cell = UnitCell() + + def add_atom(self,atom): + self.atom_list.append(atom) + + def add_species(self,species): + # add species to the species list, only if name is not a duplicate + if not self.find_species(species.name): + self.species_list.append(species) + + def find_species(self,species_name): + found = False + for sp in range(len(self.species_list)): + found |= (self.species_list[sp].name == species_name) + return found + +class Sample: + def __init__(self): + self.atoms = AtomSet() + +# The following handler processes the element of +# an XML document and updates the AtomSet data of the Sample +# If multiple instances of are found, the +# handler overwrites the AtomSet data +class QSOAtomSetHandler(xml.sax.handler.ContentHandler): + def __init__(self,sample): + self.s = sample + self.inAtomSet = False + self.inAtom = False + self.inPosition = False + self.inVelocity = False + self.inSpecies = False + self.inSymbol = False + self.inAtomicNumber = False + self.inMass = False + self.buffer = "" + # flag to signal that the first has been processed + self.done_first = False + + def startElement(self, name, attributes): + if name == "atomset": + self.s.atoms.atom_list = [] + self.inAtomSet = True + elif (name == "unit_cell") and self.inAtomSet: + self.s.atoms.cell.a = attributes["a"] + self.s.atoms.cell.b = attributes["b"] + self.s.atoms.cell.c = attributes["c"] + elif (name == "species"): + self.inSpecies = True + self.species_name = "species_name" + if "name" in attributes: + self.species_name = attributes["name"] + self.species_href = self.species_name+"_href" + if "href" in attributes: + self.species_href = attributes["href"] + self.species_symbol = self.species_name+"_symbol" + self.species_atomic_number = self.species_name+"_atomic_number" + self.species_mass = self.species_name+"_mass" + elif (name == "atom") and self.inAtomSet: + self.inAtom = True + self.atom_name = attributes["name"] + self.atom_species = attributes["species"] + sp = Species(self.species_name,self.species_href,self.species_symbol, + self.species_atomic_number,self.species_mass) + self.s.atoms.add_species(sp) + self.atom_position = [] + self.atom_velocity = [] + elif (name == "position") and self.inAtom: + self.buffer = "" + self.inPosition = True + elif (name == "velocity") and self.inAtom: + self.buffer = "" + self.inVelocity = True + elif (name == "symbol") and self.inSpecies: + self.buffer = "" + self.inSymbol = True + elif (name == "atomic_number") and self.inSpecies: + self.buffer = "" + self.inAtomicNumber = True + elif (name == "mass") and self.inSpecies: + self.buffer = "" + self.inMass = True + + def characters(self, data): + if self.inPosition or self.inVelocity or self.inSymbol or self.inAtomicNumber or self.inMass: + self.buffer += data + + def endElement(self, name): + if (name == "atom") and self.inAtomSet: + a = Atom(self.atom_name,self.atom_species,self.atom_position, + self.atom_velocity) + self.s.atoms.add_atom(a) + self.inAtom = False + if (name == "position") and self.inAtom: + pos = self.buffer.split() + x = float(pos[0]) + y = float(pos[1]) + z = float(pos[2]) + self.atom_position = [x,y,z] + self.inPosition = False + if (name == "velocity") and self.inAtom: + vel = self.buffer.split() + vx = float(vel[0]) + vy = float(vel[1]) + vz = float(vel[2]) + self.atom_velocity = [vx,vy,vz] + self.inVelocity = False + elif name == "atomset": + self.done_first = True + self.inAtomSet = False + elif name == "species": + sp = Species(self.species_name,self.species_href,self.species_symbol, + self.species_atomic_number,self.species_mass) + self.s.atoms.add_species(sp) + self.inSpecies = False + elif (name == "symbol") and self.inSpecies: + self.species_symbol = self.buffer + self.inSymbol = False + elif name == ("atomic_number") and self.inSpecies: + self.species_atomic_number = int(self.buffer) + self.inAtomicNumber = False + elif (name == "mass") and self.inSpecies: + self.species_mass = float(self.buffer) + self.inMass = False + diff --git a/util/qso2qbox.py b/util/qso2qbox.py new file mode 100755 index 0000000..8d19050 --- /dev/null +++ b/util/qso2qbox.py @@ -0,0 +1,70 @@ +#!/usr/bin/python +# Convert elements from quantum-simulation.org (QSO) format +# to Qbox input file +# use: qso2qbox.py [-last] {file|URL} +# Default: only the first element is processed +# If using -last, only the last element is processed + +from qso import * +import os.path +import xml.sax +import sys +import urllib2 +import datetime + +def usage(): + print "use: ",sys.argv[0]," [-last] {file|URL}" + sys.exit() + +argc=len(sys.argv) +if ( argc < 2 or argc > 3 ): + usage() + +# check if option "-last" is used +# "-last" option: process all and return only the last +# default: extract first atomset only +first_only = True +input_source = sys.argv[1] +if ( sys.argv[1] == "-last" ): + if ( argc != 3 ): + usage() + first_only = False + input_source = sys.argv[2] + +s = Sample() +parser = xml.sax.make_parser() +handler = QSOAtomSetHandler(s) +parser.setContentHandler(handler) +# test if input_source is a local file +# if not, process as a URL +if ( os.path.isfile(input_source) ): + file = open(input_source) + str = file.read(8192) + while ( str !="" and not (first_only and handler.done_first) ): + parser.feed(str) + str = file.read(8192) + file.close() +else: + # attempt to open as a URL + try: + f = urllib2.urlopen(input_source) + str = f.read(8192) + while ( str !="" and not (first_only and handler.done_first) ): + parser.feed(str) + str = f.read(8192) + f.close() + except (ValueError,urllib2.HTTPError) as e: + print e + sys.exit() + +parser.reset() + +# write Qbox input file +datestr=datetime.datetime.utcnow().isoformat()+'Z' +print "# converted",datestr,"from",input_source +print "set cell ",s.atoms.cell.a,s.atoms.cell.b,s.atoms.cell.c +for sp in s.atoms.species_list: + print "species",sp.name,sp.href +for a in s.atoms.atom_list: + print "atom",a.name,a.species,a.position[0],a.position[1],a.position[2],a.velocity[0],a.velocity[1],a.velocity[2] + diff --git a/util/qso2qe.py b/util/qso2qe.py new file mode 100755 index 0000000..3e9952e --- /dev/null +++ b/util/qso2qe.py @@ -0,0 +1,83 @@ +#!/usr/bin/python +# Convert from quantum-simulation.org format to QuantumEspresso input format +# use: env ECUT=ecut qso2qe.py [-last] {file|URL} + +from qso import * +import sys +import os.path +import urllib2 + +# Get Ecut from environment variable, default=25 +ecut = os.getenv("ECUT",25.0) + +def usage(): + print "use: ",sys.argv[0]," [-last] {file|URL}" + sys.exit() + +argc=len(sys.argv) +if ( argc < 2 or argc > 3 ): + usage() + +# check if option "-last" is used +# "-last" option: process all and return only the last +# default: extract first atomset only +first_only = True +input_source = sys.argv[1] +if ( sys.argv[1] == "-last" ): + if ( argc != 3 ): + usage() + first_only = False + input_source = sys.argv[2] + +s = Sample() +parser = xml.sax.make_parser() +handler = QSOAtomSetHandler(s) +parser.setContentHandler(handler) +# test if input_source is a local file +# if not, process as a URL +if ( os.path.isfile(input_source) ): + file = open(input_source) + str = file.read(8192) + while ( str !="" and not (first_only and handler.done_first) ): + parser.feed(str) + str = file.read(8192) + file.close() +else: + # attempt to open as a URL + try: + f = urllib2.urlopen(input_source) + str = f.read(8192) + while ( str !="" and not (first_only and handler.done_first) ): + parser.feed(str) + str = f.read(8192) + f.close() + except (ValueError,urllib2.HTTPError) as e: + print e + sys.exit() + +parser.reset() + +# write QE input file + +print "&control" +print " calculation = 'scf'" +print " pseudo_dir = './'" +print "/" +print "&system" +print " ibrav=0" +print " nat=",len(s.atoms.atom_list),", ntyp=",len(s.atoms.species_list),"," +print " ecutwfc=",ecut +print "/" +print "&electrons" +print "/" +print "ATOMIC_SPECIES" +for sp in s.atoms.species_list: + print sp.name,sp.mass,sp.href +print "ATOMIC_POSITIONS {bohr}" +for a in s.atoms.atom_list: + print a.species,a.position[0],a.position[1],a.position[2] +print "CELL_PARAMETERS bohr" +print s.atoms.cell.a +print s.atoms.cell.b +print s.atoms.cell.c +print "K_POINTS {gamma}"