Example #1
0
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
Example #2
0
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
Example #3
0
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
Example #4
0
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)
Example #5
0
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