def icsd_cif_b(filename): from os.path import basename from numpy import dot, transpose from pylada.crystal import Structure, primitive from . import readCif rdr = readCif.CifReader(0, filename) # buglevel = 0 vaspMap = rdr.getVaspMap() cellBasis = vaspMap['cellBasis'] structure = Structure( transpose(cellBasis), scale=1, name=basename(filename)) usyms = vaspMap['uniqueSyms'] posVecs = vaspMap['posVecs'] # multiplicities = num atoms of each type. mults = [len(x) for x in posVecs] # For each unique type of atom ... for ii in range(len(usyms)): # For each atom of that type ... for jj in range(mults[ii]): atpos = dot(transpose(cellBasis), posVecs[ii][jj]) structure.add_atom(atpos[0], atpos[1], atpos[2], usyms[ii]) prim = primitive(structure) logger.info(" crystal/read: icsd_cif_b: structure: %s" % structure) return prim
def icsd_cif_a(filename): """ Reads lattice from the ICSD \*cif files. It will not work in the case of other \*cif. It is likely to produce wrong output if the site occupations are fractional. If the occupation is > 0.5 it will treat it as 1 and in the case occupation < 0.5 it will treat it as 0 and it will accept all occupation = 0.5 as 1 and create a mess! """ from pylada import logger import re from os.path import basename from numpy.linalg import norm from numpy import array, transpose from numpy import pi, sin, cos, sqrt, dot lines = open(filename, 'r').readlines() logger.info("crystal/read: icsd_cif_a: %s" % filename) sym_big = 0 sym_end = 0 pos_big = 0 pos_end = 0 for l in lines: x = l.split() if len(x) > 0: # CELL if x[0] == '_cell_length_a': if '(' in x[-1]: index = x[-1].index('(') else: index = len(x[-1]) a = float(x[-1][:index]) if x[0] == '_cell_length_b': if '(' in x[-1]: index = x[-1].index('(') else: index = len(x[-1]) b = float(x[-1][:index]) if x[0] == '_cell_length_c': if '(' in x[-1]: index = x[-1].index('(') else: index = len(x[-1]) c = float(x[-1][:index]) if x[0] == '_cell_angle_alpha': if '(' in x[-1]: index = x[-1].index('(') else: index = len(x[-1]) alpha = float(x[-1][:index]) if x[0] == '_cell_angle_beta': if '(' in x[-1]: index = x[-1].index('(') else: index = len(x[-1]) beta = float(x[-1][:index]) if x[0] == '_cell_angle_gamma': if '(' in x[-1]: index = x[-1].index('(') else: index = len(x[-1]) gamma = float(x[-1][:index]) # SYMMETRY OPERATIONS if len(x) > 0 and x[0] == '_symmetry_equiv_pos_as_xyz': sym_big = lines.index(l) if len(x) > 0 and x[0] == '_atom_type_symbol': sym_end = lines.index(l) # WYCKOFF POSITIONS if len(x) > 0 and x[0] == '_atom_site_attached_hydrogens': pos_big = lines.index(l) if len(x) > 0 and x[0] == '_atom_site_B_iso_or_equiv': pos_big = lines.index(l) if len(x) > 0 and x[0] == '_atom_site_U_iso_or_equiv': pos_big = lines.index(l) if len(x) > 0 and x[0] == '_atom_site_0_iso_or_equiv': pos_big = lines.index(l) # if pos_end == 0 and l in ['\n', '\r\n'] and lines.index(l) > pos_big: if pos_end == 0 and pos_big > 0 \ and (l in ['\n', '\r\n'] or l.startswith('#')) \ and lines.index(l) > pos_big: pos_end = lines.index(l) # _symmetry_equiv_pos_* lines are like: # 1 'x, x-y, -z+1/2' logger.debug("crystal/read: icsd_cif_a: sym_big: %s" % sym_big) logger.debug("crystal/read: icsd_cif_a: sym_end: %s" % sym_end) symm_ops = ['(' + x.split()[1][1:] + x.split()[2] + x.split()[3][:-1] + ')' for x in lines[sym_big + 1:sym_end - 1]] logger.debug("crystal/read: icsd_cif_a: symm_ops a: %s" % symm_ops) # ['(x,x-y,-z+1/2)', '(-x+y,y,-z+1/2)', ...] # Insert decimal points after integers symm_ops = [re.sub(r'(\d+)', r'\1.', x) for x in symm_ops] logger.debug("crystal/read: icsd_cif_a: symm_ops b: %s" % symm_ops) # ['(x,x-y,-z+1./2.)', '(-x+y,y,-z+1./2.)', ...] # _atom_site_* lines are like: # Mo1 Mo4+ 2 c 0.3333 0.6667 0.25 1. 0 logger.debug("crystal/read: icsd_cif_a: pos_big: %s" % pos_big) logger.debug("crystal/read: icsd_cif_a: pos_end: %s" % pos_end) wyckoff = [[x.split()[0], [x.split()[4], x.split()[5], x.split()[6]], x.split()[7]] for x in lines[pos_big + 1:pos_end]] logger.debug("crystal/read: icsd_cif_a: wyckoff a: %s" % wyckoff) # [['Mo1', ['0.3333', '0.6667', '0.25'], '1.'], ['S1', ['0.3333', '0.6667', '0.621(4)'], '1.']] wyckoff = [w for w in wyckoff if int(float(w[-1][:4]) + 0.5) != 0] logger.debug("crystal/read: icsd_cif_a: wyckoff b: %s" % wyckoff) # [['Mo1', ['0.3333', '0.6667', '0.25'], '1.'], ['S1', ['0.3333', '0.6667', '0.621(4)'], '1.']] # Setting up a good wyckoff list for w in wyckoff: # Strip trailing numerals from w[0] == 'Mo1' pom = 0 for i in range(len(w[0])): try: int(w[0][i]) if pom == 0: pom = i except: pass w[0] = w[0][:pom] # Strip trailing standard uncertainty, if any, from w[1], ..., w[3] for i in range(3): if '(' in w[1][i]: index = w[1][i].index('(') else: index = len(w[1][i]) w[1][i] = float(w[1][i][:index]) # Delete w[4] del w[-1] ########################################## # List of unique symbols ["Mo", "S"] symbols = list({w[0] for w in wyckoff}) logger.debug("crystal/read: icsd_cif_a: symbols: %s" % symbols) # List of position vectors for each symbol positions = [[] for i in range(len(symbols))] for w in wyckoff: symbol = w[0] x, y, z = w[1][0], w[1][1], w[1][2] logger.debug("symbol: %s x: %s y: %s z: %s" % (symbol, x, y, z)) for i in range(len(symm_ops)): # Set pom = new position based on symmetry transform pom = list(eval(symm_ops[i])) logger.debug("i: %s pom a: %s" % (i, pom)) # [0.3333, -0.3334, 0.25] # Move positions to range [0,1]: for j in range(len(pom)): if pom[j] < 0.: pom[j] = pom[j] + 1. if pom[j] >= 0.999: pom[j] = pom[j] - 1. logger.debug("i: %s pom b: %s" % (i, pom)) # [0.3333, 0.6666, 0.25] # If pom is not in positions[symbol], append pom if not any(norm(array(u) - array(pom)) < 0.01 for u in positions[symbols.index(symbol)]): ix = symbols.index(symbol) positions[ix].append(pom) logger.debug("new positions for %s: %s" % (symbol, repr(positions[ix]))) ################ CELL #################### a1 = a * array([1., 0., 0.]) a2 = b * array([cos(gamma * pi / 180.), sin(gamma * pi / 180.), 0.]) c1 = c * cos(beta * pi / 180.) c2 = c / sin(gamma * pi / 180.) * (-cos(beta * pi / 180.) * cos(gamma * pi / 180.) + cos(alpha * pi / 180.)) a3 = array([c1, c2, sqrt(c**2 - (c1**2 + c2**2))]) cell = array([a1, a2, a3]) logger.debug("crystal/read: icsd_cif_a: a1: %s" % a1) logger.debug("crystal/read: icsd_cif_a: a2: %s" % a2) logger.debug("crystal/read: icsd_cif_a: a3: %s" % a3) ########################################## from pylada.crystal import Structure, primitive logger.debug("crystal/read: icsd_cif_a: cell: %s" % cell) structure = Structure( transpose(cell), scale=1, name=basename(filename)) for i in range(len(symbols)): logger.debug("crystal/read: icsd_cif_a: i: %s symbol: %s len(position): %i" % ( i, symbols[i], len(positions[i]) )) # crystal/read: i: 0 symbol: Mo len position: 2 for j in range(len(positions[i])): atpos = dot(transpose(cell), positions[i][j]) logger.debug("j: %s pos: %s" % (j, positions[i][j])) logger.debug("atpos: " % atpos) # j: 0 pos: [0.3333, 0.6666000000000001, 0.25] # atpos: [ 6.32378655e-16 1.81847148e+00 3.07500000e+00] structure.add_atom(atpos[0], atpos[1], atpos[2], symbols[i]) logger.info("crystal/read: icsd_cif_a: structure: %s" % structure) prim = primitive(structure) logger.info("crystal/read: icsd_cif_a: primitive structure: %s" % prim) return prim
def main(): import re from sys import path as python_path from os.path import exists from argparse import ArgumentParser from pylada import jobfolder from pylada.process.mpi import create_global_comm import pylada # below would go additional imports. parser = ArgumentParser(prog="runone", description=re.sub("\\s+", " ", __doc__[1:])) parser.add_argument('--logging', dest="logging", default="critical", type=str, help="Debug level.") parser.add_argument('--testValidProgram', dest="testValidProgram", default=None, type=str, help="testValidProgram") parser.add_argument("--jobid", dest="names", nargs='+', type=str, help="Job name", metavar="N") parser.add_argument("--ppath", dest="ppath", default=None, help="Directory to add to python path", metavar="Directory") parser.add_argument('--nbprocs', dest="nbprocs", default=pylada.default_comm['n'], type=int, help="Number of processors with which to launch job.") parser.add_argument('--ppn', dest="ppn", default=pylada.default_comm['ppn'], type=int, help="Number of processors with which to launch job.") parser.add_argument('--timeout', dest="timeout", default=300, type=int, help="Time to wait for job-dictionary to becom available " "before timing out (in seconds). A negative or null " "value implies forever. Defaults to 5mn.") parser.add_argument('pickle', metavar='FILE', type=str, help='Path to a job-folder.') try: options = parser.parse_args() except SystemExit: return from pylada import logger logger.setLevel(level=options.logging.upper()) from pylada.misc import setTestValidProgram tstPgm = options.testValidProgram if tstPgm.lower() == 'none': tstPgm = None setTestValidProgram(tstPgm) from pylada.misc import testValidProgram # additional path to look into. if options.ppath is not None: python_path.append(options.ppath) if not exists(options.pickle): print("Could not find file {0}.".format(options.pickle)) return # Set up mpi processes. pylada.default_comm['ppn'] = options.ppn pylada.default_comm['n'] = options.nbprocs if testValidProgram == None: create_global_comm(options.nbprocs) # Sets pylada.default_comm else: pylada.default_comm = None # use testValidProgram timeout = None if options.timeout <= 0 else options.timeout jobfolder = jobfolder.load(options.pickle, timeout=timeout) print((' ipy/lau/scattered_script: jobfolder: %s' % jobfolder)) print((' ipy/lau/scattered_script: options: %s' % options)) for name in options.names: logger.info('ipy/lau/scattered_script: testValidProgram: %s' % testValidProgram) logger.info('ipy/lau/scattered_script: name: %s' % name) logger.info('ipy/lau/scattered_script: jobfolder[name]: %s' % jobfolder[name]) logger.info('ipy/lau/scattered_script: type(jobfolder[name]): %s' % type(jobfolder[name])) logger.info( 'ipy/lau/scattered_script: jobfolder[name].compute: %s' % jobfolder[name].compute) logger.info( 'ipy/lau/scattered_script: type(jobfolder[name].compute): %s' \ % type(jobfolder[name].compute)) logger.info('ipy/lau/scattered_script: before compute for name: %s' % name) comm = pylada.default_comm if testValidProgram != None: comm = None jobfolder[name].compute(comm=comm, outdir=name) logger.info('ipy/lau/scattered_script: after compute for name: %s' % name)
def icsd_cif_a(filename, make_primitive=True): """ Reads lattice from the ICSD \*cif files. It will not work in the case of other \*cif. It is likely to produce wrong output if the site occupations are fractional. If the occupation is > 0.5 it will treat it as 1 and in the case occupation < 0.5 it will treat it as 0 and it will accept all occupation = 0.5 as 1 and create a mess! """ from pylada import logger import re from copy import deepcopy from os.path import basename from numpy.linalg import norm from numpy import array, transpose from numpy import pi, sin, cos, sqrt, dot lines = open(filename, 'r').readlines() logger.info("crystal/read: icsd_cif_a: %s" % filename) sym_big = 0 sym_end = 0 pos_big = 0 pos_end = 0 for l in lines: x = l.split() if len(x) > 0: # CELL if x[0] == '_cell_length_a': if '(' in x[-1]: index = x[-1].index('(') else: index = len(x[-1]) a = float(x[-1][:index]) if x[0] == '_cell_length_b': if '(' in x[-1]: index = x[-1].index('(') else: index = len(x[-1]) b = float(x[-1][:index]) if x[0] == '_cell_length_c': if '(' in x[-1]: index = x[-1].index('(') else: index = len(x[-1]) c = float(x[-1][:index]) if x[0] == '_cell_angle_alpha': if '(' in x[-1]: index = x[-1].index('(') else: index = len(x[-1]) alpha = float(x[-1][:index]) if x[0] == '_cell_angle_beta': if '(' in x[-1]: index = x[-1].index('(') else: index = len(x[-1]) beta = float(x[-1][:index]) if x[0] == '_cell_angle_gamma': if '(' in x[-1]: index = x[-1].index('(') else: index = len(x[-1]) gamma = float(x[-1][:index]) # SYMMETRY OPERATIONS if len(x) > 0 and x[0] == '_symmetry_equiv_pos_as_xyz': sym_big = lines.index(l) if len(x) > 0 and x[0] == '_atom_type_symbol': sym_end = lines.index(l) # WYCKOFF POSITIONS if len(x) > 0 and x[0] == '_atom_site_attached_hydrogens': pos_big = lines.index(l) if len(x) > 0 and x[0] == '_atom_site_B_iso_or_equiv': pos_big = lines.index(l) if len(x) > 0 and x[0] == '_atom_site_U_iso_or_equiv': pos_big = lines.index(l) if len(x) > 0 and x[0] == '_atom_site_0_iso_or_equiv': pos_big = lines.index(l) # if pos_end == 0 and l in ['\n', '\r\n'] and lines.index(l) > pos_big: if pos_end == 0 and pos_big > 0 \ and (l in ['\n', '\r\n'] or l.startswith('#')) \ and lines.index(l) > pos_big: pos_end = lines.index(l) # _symmetry_equiv_pos_* lines are like: # 1 'x, x-y, -z+1/2' logger.debug("crystal/read: icsd_cif_a: sym_big: %s" % sym_big) logger.debug("crystal/read: icsd_cif_a: sym_end: %s" % sym_end) symm_ops = ['(' + x.split()[1][1:] + x.split()[2] + x.split()[3][:-1] + ')' for x in lines[sym_big + 1:sym_end - 1]] logger.debug("crystal/read: icsd_cif_a: symm_ops a: %s" % symm_ops) # ['(x,x-y,-z+1/2)', '(-x+y,y,-z+1/2)', ...] # Insert decimal points after integers symm_ops = [re.sub(r'(\d+)', r'\1.', x) for x in symm_ops] logger.debug("crystal/read: icsd_cif_a: symm_ops b: %s" % symm_ops) # ['(x,x-y,-z+1./2.)', '(-x+y,y,-z+1./2.)', ...] # _atom_site_* lines are like: # Mo1 Mo4+ 2 c 0.3333 0.6667 0.25 1. 0 logger.debug("crystal/read: icsd_cif_a: pos_big: %s" % pos_big) logger.debug("crystal/read: icsd_cif_a: pos_end: %s" % pos_end) wyckoff = [[x.split()[0], [x.split()[4], x.split()[5], x.split()[6]], x.split()[7]] for x in lines[pos_big + 1:pos_end]] logger.debug("crystal/read: icsd_cif_a: wyckoff a: %s" % wyckoff) # [['Mo1', ['0.3333', '0.6667', '0.25'], '1.'], ['S1', ['0.3333', '0.6667', '0.621(4)'], '1.']] wyckoff = [w for w in wyckoff if int(float(w[-1][:4]) + 0.5) != 0] logger.debug("crystal/read: icsd_cif_a: wyckoff b: %s" % wyckoff) # [['Mo1', ['0.3333', '0.6667', '0.25'], '1.'], ['S1', ['0.3333', '0.6667', '0.621(4)'], '1.']] # Setting up a good wyckoff list for w in wyckoff: # Strip trailing numerals from w[0] == 'Mo1' pom = 0 for i in range(len(w[0])): try: int(w[0][i]) if pom == 0: pom = i except: pass w[0] = w[0][:pom] # Strip trailing standard uncertainty, if any, from w[1], ..., w[3] for i in range(3): if '(' in w[1][i]: index = w[1][i].index('(') else: index = len(w[1][i]) w[1][i] = float(w[1][i][:index]) # Delete w[4] del w[-1] ########################################## # List of unique symbols ["Mo", "S"] symbols = list({w[0] for w in wyckoff}) logger.debug("crystal/read: icsd_cif_a: symbols: %s" % symbols) # List of position vectors for each symbol positions = [[] for i in range(len(symbols))] for w in wyckoff: symbol = w[0] x, y, z = w[1][0], w[1][1], w[1][2] logger.debug("symbol: %s x: %s y: %s z: %s" % (symbol, x, y, z)) for i in range(len(symm_ops)): # Set pom = new position based on symmetry transform pom = list(eval(symm_ops[i])) logger.debug("i: %s pom a: %s" % (i, pom)) # [0.3333, -0.3334, 0.25] # Move positions to range [0,1]: for j in range(len(pom)): if pom[j] < 0.: pom[j] = pom[j] + 1. if pom[j] >= 0.999: pom[j] = pom[j] - 1. logger.debug("i: %s pom b: %s" % (i, pom)) # [0.3333, 0.6666, 0.25] # If pom is not in positions[symbol], append pom if not any(norm(array(u) - array(pom)) < 0.01 for u in positions[symbols.index(symbol)]): ix = symbols.index(symbol) positions[ix].append(pom) logger.debug("new positions for %s: %s" % (symbol, repr(positions[ix]))) ################ CELL #################### a1 = a * array([1., 0., 0.]) a2 = b * array([cos(gamma * pi / 180.), sin(gamma * pi / 180.), 0.]) c1 = c * cos(beta * pi / 180.) c2 = c / sin(gamma * pi / 180.) * (-cos(beta * pi / 180.) * cos(gamma * pi / 180.) + cos(alpha * pi / 180.)) a3 = array([c1, c2, sqrt(c**2 - (c1**2 + c2**2))]) cell = array([a1, a2, a3]) logger.debug("crystal/read: icsd_cif_a: a1: %s" % a1) logger.debug("crystal/read: icsd_cif_a: a2: %s" % a2) logger.debug("crystal/read: icsd_cif_a: a3: %s" % a3) ########################################## from pylada.crystal import Structure, primitive logger.debug("crystal/read: icsd_cif_a: cell: %s" % cell) structure = Structure( transpose(cell), scale=1, name=basename(filename)) for i in range(len(symbols)): logger.debug("crystal/read: icsd_cif_a: i: %s symbol: %s len(position): %i" % ( i, symbols[i], len(positions[i]) )) # crystal/read: i: 0 symbol: Mo len position: 2 for j in range(len(positions[i])): atpos = dot(transpose(cell), positions[i][j]) logger.debug("j: %s pos: %s" % (j, positions[i][j])) logger.debug("atpos: " % atpos) # j: 0 pos: [0.3333, 0.6666000000000001, 0.25] # atpos: [ 6.32378655e-16 1.81847148e+00 3.07500000e+00] structure.add_atom(atpos[0], atpos[1], atpos[2], symbols[i]) logger.info("crystal/read: icsd_cif_a: structure: %s" % structure) if make_primitive: prim = primitive(structure) else: prim = deepcopy(structure) logger.info("crystal/read: icsd_cif_a: primitive structure: %s" % prim) return prim