Ejemplo n.º 1
0
def parser(name, data):
    """ Parse CPMD Input file """
    tmol = Molecule(name)
    tparam = deepcopy(param["default"])
    tparam["name"] = name
    i = 0
    ibrav = '14'
    symmetries = {'ISOLATED': '0',
                  'CUBIC': '1',
                  'FACE CENTERED CUBIC': '2',
                  'FCC': '2',
                  'BODY CENTERED CUBIC': '3',
                  'BCC': '3',
                  'HEXAGONAL': '4',
                  'TRIGONAL': '5',
                  'RHOMBOHEDRAL': '5',
                  'TETRAGONAL': '6',
                  'BODY CENTERED TETRAGONAL': '7',
                  'BCT': '7',
                  'ORTHORHOMBIC': '8',
                  'MONOCLINIC': '12',
                  'TRICLINIC': '14'}
    fmt = 'bohr'
    unitvec = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
    scalevec = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
    types = []
    while i < len(data):
        if data[i][0] == '!' or data[i].split() == []:
            i += 1
        elif '&' in data[i] and data[i].strip() != "&END":
            # start recording namelist
            nl = data[i].strip()
            i += 1
            while "&END" not in data[i]:
                if nl == "&SYSTEM" and "ANGSTROM" in data[i]:
                    fmt = "angstrom"
                elif nl == "&SYSTEM" and "KPOINTS" in data[i]:
                    if "MONKHORST" in data[i]:
                        kpoints = data[i + 1].split()
                        if "SHIFT=" in data[i]:
                            kpoints += data[i].split("SHIFT=")[1].split()[0:3]
                        else:
                            kpoints += ['0', '0', '0']
                        tmol.setKpoints('active', 'mpg')
                        tmol.setKpoints('mpg', kpoints)
                        i += 1
                    else:
                        kpoints = []
                        crystal = False
                        bands = False
                        if "SCALED" in data[i]:
                            crystal = True
                        if "BANDS" in data[i]:
                            bands = True
                            j = 1
                            line = data[i + j].split()
                            while not all([float(k) == 0 for k in line]):
                                kpoints.append(line[1:4] + [line[0]])
                                kpoints.append(line[4:] + ['0'])
                                j += 1
                                line = data[i + j].split()
                            i += j
                        else:
                            nk = int(data[i + 1])
                            for j in range(nk):
                                kpoints.append(data[i + j + 2].split())
                            i += 1 + nk
                        tmol.setKpoints('active', 'discrete')
                        tmol.setKpoints('discrete', kpoints)
                        tmol.setKpoints('options',
                                        {'crystal': crystal, 'bands': bands})
                elif nl == "&SYSTEM" and "SCALE" in data[i]:
                    if "CARTESIAN" in data[i]:
                        fmt = "alat"
                    else:
                        fmt = "crystal"
                    for token in data[i].strip().split():
                        if 'S=' in token:
                            scalevec[0][0] = 1 / float(token.strip('S='))
                            scalevec[1][1] = 1 / float(token.strip('S='))
                            scalevec[2][2] = 1 / float(token.strip('S='))
                        elif 'SX=' in token:
                            scalevec[0][0] = 1 / float(token.strip('SX='))
                        elif 'SY=' in token:
                            scalevec[1][1] = 1 / float(token.strip('SY='))
                        elif 'SZ=' in token:
                            scalevec[2][2] = 1 / float(token.strip('SZ='))
                elif nl == "&SYSTEM" and "SYMMETRY" in data[i]:
                    arg = data[i + 1].strip()
                    if arg.isdigit():
                        ibrav = arg
                    else:
                        ibrav = symmetries[arg]
                    i += 1
                elif nl == "&SYSTEM" and "CELL" in data[i]:
                    cell = list(map(float, data[i + 1].split()))
                    if "VECTORS" in data[i]:
                        while len(cell) < 9:
                            i += 1
                            cell += list(map(float, data[i + 1].split()))
                        ibrav = '-2'
                    else:
                        # cell = [a,b/a,c/a,cos(alpha),cos(beta),cos(gamma)]
                        a, b, c, alpha, beta, gamma = cell
                        tmol.setCellDim(a)
                        if "ABSOLUTE" in data[i]:
                            # cell = [a, b, c, ...]
                            b = b / a
                            c = c / a
                        if "DEGREE" in data[i]:
                            # cell = [..., alpha, beta, gamma]
                            alpha, beta, gamma =\
                                map(cos, map(deg2rad, [alpha, beta, gamma]))
                    i += 1
                elif nl == "&ATOMS" and data[i][0] == '*':
                    atype = regex('[-_.]', data[i][1:].strip())[0]
                    while atype in types:
                        if not atype[-1].isdigit():
                            atype += "1"
                        else:
                            atype = atype[:-1] + str(int(atype[-1]) + 1)
                    types.append(atype)
                    tmol.pse[atype]['CPPP'] = data[i][1:].strip()
                    tmol.pse[atype]['CPNL'] = data[i + 1].strip()
                    nat = int(data[i + 2])
                    for j in range(nat):
                        tmol.newAtom(atype, data[i + 3 + j].split()[:3])
                    i += 2 + nat
                elif nl == "&ATOMS" and "CONSTRAINTS" in data[i]:
                    # parse coordinate-fixes
                    j = 1
                    constraints = ""
                    line = data[i + j]
                    while "END" not in line:
                        if "FIX" in line and ("ALL" in line or "QM" in line):
                            for at in range(tmol.nat):
                                tmol.setAtom(at, fix=[True, True, True])
                        elif "FIX" in line and "ELEM" in line:
                            j += 1
                            vals = data[i + j].split()
                            Z = int(vals.pop(0))
                            if "SEQ" in line:
                                beg = int(vals.pop(0)) - 1
                                end = int(vals.pop(0))
                                r = range(beg, end)
                            else:
                                r = range(tmol.nat)
                            for at in r:
                                if tmol.pse[tmol.getAtom(at)[0]]["Z"] == Z:
                                    tmol.setAtom(at, fix=[True, True, True])
                        elif "FIX" in line and "PPTY" in line:
                            j += 1
                            vals = data[i + j].split()
                            PP = int(vals.pop(0)) - 1
                            if "SEQ" in line:
                                beg = int(vals.pop(0)) - 1
                                end = int(vals.pop(0))
                                r = range(beg, end)
                            else:
                                r = range(tmol.nat)
                            for at in r:
                                if tmol.getAtom(at)[0] == types[PP]:
                                    tmol.setAtom(at, fix=[True, True, True])
                        elif "FIX" in line and "SEQ" in line:
                            j += 1
                            vals = data[i + j].split()
                            for at in range(int(vals[0]) - 1, int(vals[1])):
                                tmol.setAtom(at, fix=[True, True, True])
                        elif "FIX" in line and "ATOM" in line:
                            j += 1
                            vals = data[i + j].split()
                            count = int(vals.pop(0))
                            for k in range(count):
                                if not vals:
                                    j += 1
                                    vals = data[i + j].split()
                                tmol.setAtom(int(vals.pop(0)) - 1,
                                             fix=[True, True, True])
                        elif "FIX" in line and "COOR" in line:
                            j += 1
                            vals = data[i + j].split()
                            count = int(vals.pop(0))
                            for k in range(count):
                                j += 1
                                fixcoord = list(map(int, data[i + j].split()))
                                tmol.setAtom(fixcoord[0] - 1, fix=[
                                    bool(not fixcoord[1]),
                                    bool(not fixcoord[2]),
                                    bool(not fixcoord[3])])
                        elif line.strip():
                            constraints += line
                        j += 1
                        line = data[i + j]
                    if constraints:
                        tparam[nl] += "CONSTRAINTS\n" + constraints +\
                                      "END CONSTRAINTS\n"
                    i += j
                elif nl == "&ATOMS" and "ISOTOPE" in data[i]:
                    j = 0
                    for t in types:
                        j += 1
                        mass = data[i + j].strip()
                        tmol.pse[t]['m'] = float(mass)
                    i += j
                else:
                    tparam[nl] += data[i]
                i += 1
        else:
            i += 1
    # apply cell vec (scale SX etc.)
    if scalevec != unitvec:
        tmol.setVec(scalevec, scale=True)
        tmol.setVec(unitvec)
    # parse cell parameters
    if ibrav == '-2':
        tmol.setVec([cell[0:3], cell[3:6], cell[6:9]])
    elif ibrav == '1':
        # simple cubic
        pass
    elif ibrav == '2':
        # face centered cubic
        tmol.setVec([[-0.5, 0, 0.5], [0, 0.5, 0.5], [-0.5, 0.5, 0]])
    elif ibrav == '3':
        # body centered cubic
        tmol.setVec([[0.5, 0.5, 0.5], [-0.5, 0.5, 0.5], [-0.5, -0.5, 0.5]])
    elif ibrav == '4':
        # hexagonal
        tmol.setVec([[1, 0, 0], [-0.5, sqrt(3) * 0.5, 0], [0, 0, c]])
    elif ibrav == '5':
        # trigonal
        tx = sqrt((1 - alpha) / 2)
        ty = sqrt((1 - alpha) / 6)
        tz = sqrt((1 + 2 * alpha) / 3)
        tmol.setVec([[tx, -ty, tz], [0, 2 * ty, tz], [-tx, -ty, tz]])
    elif ibrav == '6':
        # simple tetragonal
        tmol.setVec([[1, 0, 0], [0, 1, 0], [0, 0, c]])
    elif ibrav == '7':
        # body centered tetragonal
        tmol.setVec([[0.5, -0.5, c * 0.5],
                     [0.5, 0.5, c * 0.5],
                     [-0.5, -0.5, c * 0.5]])
    elif ibrav == '0' or ibrav == '8':
        # simple orthorhombic
        tmol.setVec([[1, 0, 0], [0, b, 0], [0, 0, c]])
    elif ibrav == '12':
        # simple monoclinic
        tmol.setVec([[1, 0, 0],
                     [b * alpha, b * sqrt(1 - alpha**2), 0],
                     [0, 0, c]])
    elif ibrav == '14':
        # triclinic
        singam = sqrt(1 - gamma**2)
        tmol.setVec([[1, 0, 0], [b * gamma, b * singam, 0],
                     [c * beta, c * (alpha - beta * gamma) / singam,
                      c * sqrt(1 + 2 * alpha * beta * gamma - alpha * alpha -
                               beta * beta - gamma * gamma) / singam]])
    # scale alat with explicit vectors
    if fmt == 'alat' and ibrav == '-2':
        vec = tmol.getVec()
        a = sqrt(vec[0][0] * vec[0][0] + vec[0][1] *
                 vec[0][1] + vec[0][2] * vec[0][2])
        b = sqrt(vec[1][0] * vec[1][0] + vec[1][1] *
                 vec[1][1] + vec[1][2] * vec[1][2])
        c = sqrt(vec[2][0] * vec[2][0] + vec[2][1] *
                 vec[2][1] + vec[2][2] * vec[2][2])
        tmol.setVec([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
        tmol.setVec([[a, 0, 0], [0, b, 0], [0, 0, c]], scale=True)
        tmol.setVec(vec)
    # scale crystal, alat /w symmetry, angstrom-atoms
    tmol.setFmt(fmt, scale=True)
    # scale angstrom-cell
    tmol.setCellDim(tmol.getCellDim(fmt='bohr'), fmt=fmt)
    return tmol, tparam