Ejemplo n.º 1
0
def parse_cmdline_args(cmdlineargs=None):
    '''Parses command line arguments.

    Args:
        cmdlineargs: List of command line arguments. When None, arguments in
            sys.argv are parsed (Default: None).
    '''
    parser = optparse.OptionParser(usage=USAGE)
    msg = 'file containing lattice vectors (overrides lattice vectors'\
          ' in the geometry file)'
    parser.add_option(
        '-l', '--lattice-file', action='store', help=msg, dest='latticefile')
    msg = 'output file to store the resulting geometry'
    parser.add_option('-o', '--output', action='store', default='-', help=msg)
    options, args = parser.parse_args(cmdlineargs)

    if len(args) != 4:
        raise ScriptError('Incorrect number of arguments')
    infile = args[0]
    reps = []
    for repstr in args[1:4]:
        try:
            reps.append(int(repstr))
        except ValueError:
            msg = "Invalid repetition number '" + repstr + "'."
            raise ScriptError(msg)
    if not (reps[0] > 0 and reps[1] > 0 and reps[2] > 0):
        raise ScriptError('Repetition numbers must be greater than zero')

    return infile, (reps[0], reps[1], reps[2]), options
Ejemplo n.º 2
0
def repeatgen(infile, repeats, options):
    '''Repeats geometry from gen files.

    Args:
        infile: File containing the gen-formatted geometry.
        repeats: (n1, n2, n3) integer tuple containing the repetitions along
            each lattice vector.
        options: Options (e.g. as returned by the command line parser).
    '''

    gen = Gen.fromfile(infile)
    geo = gen.geometry

    latvecs = geo.latvecs
    if options.latticefile:
        latvecs = np.fromfile(options.latticefile, sep=' ')
        if len(latvecs) != 9:
            msg = ('Invalid number of lattice vector components in '
                   + options.latticefile)
            raise ScriptError(msg)
        latvecs.shape = (3, 3)

    if latvecs is None:
        msg = 'No lattice vectors found (neither in gen nor in external file)'
        raise ScriptError(msg)

    newgeo = _repeatgeo(geo, latvecs, repeats)
    newgen = Gen(newgeo, gen.fractional)
    outfile = options.output
    if outfile == '-':
        outfile = sys.stdout
    newgen.tofile(outfile)
Ejemplo n.º 3
0
def parse_cmdline_args(cmdlineargs=None):
    '''Parses command line arguments.

    Args:
        cmdlineargs: List of command line arguments. When None, arguments in
            sys.argv are parsed. (Default: None)
    '''
    parser = optparse.OptionParser(usage=USAGE)
    parser.add_option("-o", "--output", action="store", dest="output",
                      default='-', help="override the name of the output file "
                      "(use '-' for standard out")
    parser.add_option("-c", "--component", action="store", dest="component",
                      type=str, default='I', help="strain type to apply "
                      "posible values being xx, yy, zz, xz, xz, yz or I for "
                      "isotropic (default value: I)")
    options, args = parser.parse_args(cmdlineargs)

    if options.component.lower() not in LABELS:
        msg = "Invalid strain component '" + options.component + "'"
        raise ScriptError(msg)

    if len(args) != 2:
        raise ScriptError("You must specify exactly two arguments "
                          "(input file, strain).")
    infile = args[0]
    try:
        strain = float(args[1])
    except ValueError:
        raise ScriptError("Invalid strain value '" + args[1] + "'")

    if options.component.lower() in ('xx', 'yy', 'zz', 'i') and strain <= -100:
        raise ScriptError("Compressive strain cannot exceed 100%")

    return infile, strain, options
Ejemplo n.º 4
0
def parse_cmdline_args(cmdlineargs=None):
    '''Parses command line arguments.

    Args:
        cmdlineargs: List of command line arguments. When None, arguments in
            sys.argv are parsed. (Default: None)
    '''
    parser = argparse.ArgumentParser(description=USAGE)
    msg = "override the name of the output file (use '-' for standard out)"
    parser.add_argument("-o", "--output", action="store", dest="output",
                        default='-', help=msg)
    msg = "strain type to apply posible values being xx, yy, zz, xz, xz, yz or"\
          " I for isotropic (default value: I)"
    parser.add_argument("-c", "--component", action="store", dest="component",
                        type=str, default='I', help=msg)
    msg = "input file name"
    parser.add_argument("infile", metavar="INPUT", help=msg)
    msg = "strain to apply as positive or negative percentage"
    parser.add_argument("strain", type=float, metavar="STRAIN", help=msg)

    args = parser.parse_args(cmdlineargs)

    if args.component.lower() not in LABELS:
        msg = "Invalid strain component '" + args.component + "'"
        raise ScriptError(msg)

    strain = args.strain

    if args.component.lower() in ('xx', 'yy', 'zz', 'i') and strain <= -100:
        raise ScriptError("Compressive strain cannot exceed 100%")

    return args, strain
Ejemplo n.º 5
0
def gen2cif(args):
    '''Converts the given INPUT file in DFTB+ GEN format to CIF format.

    Args:
        args: Namespace of command line arguments
    '''
    infile = args.infile
    try:
        gen = Gen.fromfile(infile)
    except OSError:
        raise ScriptError('You must enter a valid path to the input file.')

    geometry = gen.geometry
    if not geometry.periodic:
        geometry.setlattice(args.cellsize * np.eye(3))
    cif = Cif(gen.geometry)

    if args.output:
        if args.output == "-":
            outfile = sys.stdout
        else:
            outfile = args.output
    else:
        if infile.endswith(".gen"):
            outfile = infile[:-4] + ".cif"
        else:
            outfile = infile + ".cif"
    cif.tofile(outfile)
Ejemplo n.º 6
0
def xyz2gen(args):
    '''Converts the given INPUT file in XYZ format to DFTB+ GEN format.

    Args:
        args: Namespace of command line arguments
    '''
    infile = args.infile
    try:
        xyz = Xyz.fromfile(infile)
    except OSError:
        raise ScriptError('You must enter a valid path to the input file.')
    geo = xyz.geometry
    if args.lattfile:
        fp = open(args.lattfile, "r")
        tmp = np.fromfile(fp, count=9, dtype=float, sep=" ")
        latvecs = tmp.reshape((3, 3))
        fp.close()
        geo.setlattice(latvecs)
    gen = Gen(geo, fractional=args.fractional)

    if args.output:
        if args.output == "-":
            outfile = sys.stdout
        else:
            outfile = args.output
    else:
        if infile.endswith(".xyz"):
            outfile = infile[:-4] + ".gen"
        else:
            outfile = infile + ".gen"
    gen.tofile(outfile)
Ejemplo n.º 7
0
def gen2xyz(args):
    '''Converts the given INPUT file in DFTB+ GEN format to XYZ format.

    Args:
        args: Namespace of command line arguments
    '''
    infile = args.infile
    try:
        gen = Gen.fromfile(infile)
    except OSError:
        raise ScriptError('You must enter a valid path to the input file.')
    xyz = Xyz(gen.geometry, args.comment)
    if args.output:
        if args.output == "-":
            outfile = sys.stdout
        else:
            outfile = args.output
    else:
        if infile.endswith(".gen"):
            outfile = infile[:-4] + ".xyz"
        else:
            outfile = infile + ".xyz"
    xyz.tofile(outfile)

    if gen.geometry.periodic and args.lattfile:
        fp = open(args.lattfile, "w")
        for vec in gen.geometry.latvecs:
            fp.write("{0:18.10E} {1:18.10E} {2:18.10E}\n".format(*vec))
        fp.close()
Ejemplo n.º 8
0
def parse_cmdline_args(cmdlineargs=None):
    '''Parses command line arguments.

    Args:
        cmdlineargs: List of command line arguments. When None, arguments in
            sys.argv are parsed (Default: None).
    '''
    parser = argparse.ArgumentParser(description=USAGE)
    msg = 'file containing lattice vectors (overrides lattice vectors'\
          ' in the geometry file)'
    parser.add_argument('-l',
                        '--lattice-file',
                        action='store',
                        help=msg,
                        dest='latticefile')
    msg = 'output file to store the resulting geometry'
    parser.add_argument('-o',
                        '--output',
                        action='store',
                        default='-',
                        help=msg)
    msg = 'create a repeat geometry for phonon bandstructure'
    parser.add_argument('-p',
                        '--phonons',
                        action='store_true',
                        default=False,
                        help=msg)
    msg = 'input file name'
    parser.add_argument("infile", metavar="INPUT", help=msg)
    msg = 'repetition along the first lattice vector'
    parser.add_argument('n1', type=int, metavar="N1", help=msg)
    msg = 'repetition along the second lattice vector'
    parser.add_argument('n2', type=int, metavar="N2", help=msg)
    msg = 'repetition along the third lattice vector'
    parser.add_argument('n3', type=int, metavar="N3", help=msg)

    args = parser.parse_args(cmdlineargs)

    if not (args.n1 > 0 and args.n2 > 0 and args.n3 > 0):
        raise ScriptError('Repetition numbers must be greater than zero')
    if args.phonons:
        if (args.n1 % 2 == 0 or args.n2 % 2 == 0 or args.n3 % 2 == 0):
            raise ScriptError('Repetition numbers must be odd numbers')

    return args
Ejemplo n.º 9
0
def dp_bands(args):
    '''Converts band structure information of DFTB+ output to NXY-format.

    Args:
        args: Namespace of command line arguments
    '''
    infile = args.infile
    outprefix = args.outprefix

    try:
        bandout = BandOut.fromfile(infile)
    except OSError:
        raise ScriptError('You must enter a valid path to the input file.')

    if args.spinsep:
        # Create filename for each spin-channel
        fnames = [
            "{0}_s{1:d}.dat".format(outprefix, ispin)
            for ispin in range(1, bandout.nspin + 1)
        ]
        plotvals = bandout.eigvalarray[:, :, :, 0]
    else:
        # Put all eigenvalues in one channel, if no spin separation required
        eigvals = bandout.eigvalarray[:, :, :, 0]
        plotvals = np.empty(
            (1, eigvals.shape[1], eigvals.shape[2] * eigvals.shape[0]),
            dtype=float)
        for ispin in range(bandout.nspin):
            istart = ispin * bandout.nstate
            iend = (ispin + 1) * bandout.nstate
            plotvals[0, :, istart:iend] = eigvals[ispin, :, :]
        fnames = [
            outprefix + "_tot.dat",
        ]

    if args.enum:
        formstr0 = "{0:d} "
        tmp = [
            "{" + str(ii) + ":18.10E}"
            for ii in range(1, plotvals.shape[2] + 1)
        ]
        formstr = formstr0 + " ".join(tmp) + "\n"
    else:
        tmp = ["{" + str(ii) + ":18.10E}" for ii in range(plotvals.shape[2])]
        formstr = " ".join(tmp) + "\n"

    for iout, data in enumerate(plotvals):
        fp = open(fnames[iout], "w")
        for ik, kdata in enumerate(data):
            if args.enum:
                fp.write(formstr.format(ik + 1, *kdata))
            else:
                fp.write(formstr.format(*kdata))
        fp.close()
Ejemplo n.º 10
0
def repeatgen(args):
    '''Repeats geometry from gen files.

    Args:
        args: Namespace of command line arguments
    '''
    infile = args.infile
    repeats = [args.n1, args.n2, args.n3]

    try:
        gen = Gen.fromfile(infile)
    except OSError:
        raise ScriptError('You must enter a valid path to the input file.')
    geo = gen.geometry

    latvecs = geo.latvecs
    if args.latticefile:
        latvecs = np.fromfile(args.latticefile, sep=' ')
        if len(latvecs) != 9:
            msg = ('Invalid number of lattice vector components in ' +
                   args.latticefile)
            raise ScriptError(msg)
        latvecs.shape = (3, 3)

    if latvecs is None:
        msg = 'No lattice vectors found (neither in gen nor in external file)'
        raise ScriptError(msg)

    if args.phonons:
        newgeo = _repeatgeo2(geo, latvecs, repeats)
    else:
        newgeo = _repeatgeo(geo, latvecs, repeats)

    newgen = Gen(newgeo, gen.fractional)
    outfile = args.output
    if outfile == '-':
        outfile = sys.stdout
    newgen.tofile(outfile)
Ejemplo n.º 11
0
def straingen(args, strain):
    '''Strains a geometry from a gen file.

    Args:
        args: Namespace of command line arguments
        strain: Strain to apply
    '''
    infile = args.infile
    try:
        gen = Gen.fromfile(infile)
    except OSError:
        raise ScriptError('You must enter a valid path to the input file.')
    geometry = gen.geometry

    strainmtx = np.zeros((3, 3), dtype=float)
    for jj in range(3):
        strainmtx[jj][jj] = 1.0

    components = LABELS[args.component.lower()]

    for ii in components:
        strainmtx[VOIGHT[ii][0]][VOIGHT[ii][1]] += 0.005 * strain
        strainmtx[VOIGHT[ii][1]][VOIGHT[ii][0]] += 0.005 * strain

    if geometry.latvecs is not None:
        geometry.latvecs = np.dot(geometry.latvecs, strainmtx)

    geometry.coords = np.dot(geometry.coords, strainmtx)

    if args.output:
        if args.output == "-":
            outfile = sys.stdout
        else:
            outfile = args.output
    else:
        if infile.endswith(".gen"):
            outfile = infile
        else:
            outfile = infile + ".gen"

    gen = Gen(geometry, fractional=gen.fractional)
    gen.tofile(outfile)
Ejemplo n.º 12
0
def parse_arguments(cmdlineargs=None):
    '''Parses command line arguments.

    Args:
        cmdlineargs: List of command line arguments. When None, arguments in
            sys.argv are parsed (Default: None).
    '''
    parser = argparse.ArgumentParser(description=USAGE)

    msg = "grid separation (default: {0:.2f})".format(DEFAULT_GRID_SEPARATION)
    parser.add_argument("-g",
                        "--gridres",
                        type=float,
                        dest="gridres",
                        default=DEFAULT_GRID_SEPARATION,
                        help=msg)

    msg = "create pdos or occupation weighted dos"
    parser.add_argument("-w",
                        "--weight-occ",
                        action="store_true",
                        dest="occweight",
                        default=False,
                        help=msg)

    msg = "broadening function (default: gauss)"
    parser.add_argument("-f",
                        "--broadening-function",
                        dest="broadening",
                        choices=BROADENING_FUNCTIONS,
                        default=GAUSS_BROADENING,
                        help=msg)

    msg = "order of mp function"
    parser.add_argument("-o", "--mporder", type=int, dest="mporder", help=msg)

    msg = "broadening width sigma (default: gauss {:.2f}, fermi {:.2f}, "\
          "mp {:.2f})".format(DEFAULT_WIDTHS[GAUSS_BROADENING],
                             DEFAULT_WIDTHS[FERMI_BROADENING],
                             DEFAULT_WIDTHS[MP_BROADENING])
    parser.add_argument("-b",
                        "--broadening-width",
                        type=float,
                        metavar="WIDTH",
                        dest="broadwidth",
                        help=msg,
                        default=-1.0)

    msg = "number of sigmas after which the broadening function is considered "\
          "to be zero (default: gauss {0:.2f}, fermi {1:.2f}, mp {1:.2f})"\
           .format(DEFAULT_RANGES[GAUSS_BROADENING],
                   DEFAULT_RANGES[FERMI_BROADENING],
                   DEFAULT_RANGES[MP_BROADENING])
    parser.add_argument("-s",
                        "--sigma-range",
                        type=float,
                        metavar="RANGE",
                        dest="broadrange",
                        default=-1.0,
                        help=msg)

    msg = "turn on verbose operation"
    parser.add_argument("-v",
                        "--verbose",
                        action="store_true",
                        dest="verbose",
                        default=False,
                        help=msg)

    msg = "input file name"
    parser.add_argument("infile", metavar="INPUT", help=msg)

    msg = "output file name"
    parser.add_argument("outfile", metavar="OUTPUT", help=msg)

    args = parser.parse_args(cmdlineargs)

    if args.mporder:
        if args.broadening != 'mp':
            msg = '--mporder can only be set when --broadening-function=mp.'
            raise ScriptError(msg)
        if args.mporder < 1:
            raise ScriptError(msg)

    infile = args.infile
    outfile = args.outfile
    broadening = args.broadening

    if args.broadwidth < 0.0:
        sigma = DEFAULT_WIDTHS[broadening]
    else:
        sigma = args.broadwidth

    if args.broadrange < 0.0:
        sigmarange = DEFAULT_RANGES[broadening]
    else:
        sigmarange = args.broadrange

    return args, broadening, sigma, sigmarange, infile, outfile
Ejemplo n.º 13
0
def dp_dos(args, broadening, sigma, sigmarange, infile, outfile):
    '''convolves the eigenlevels with a broadening function to produce nice
       DOS/PDOS curves.

    Args:
        args: Containing the obtained parsed arguments.
        broadening: Specified broadening width sigma.
        sigma: Broadening width
        sigmarange: number of sigmas after which the broadening function is
                    considered to be zero
        infile: File containing the DFTB+ band structure information.
        outfile: Output file name
    '''
    try:
        bandout = BandOut.fromfile(infile)
    except OSError:
        raise ScriptError('You must enter a valid path to the input file.')
    eigvals = bandout.eigvalarray
    if not args.occweight:
        eigvals[:, :, :, 1] = 1.0

    if broadening == FERMI_BROADENING:
        aa = 0.5 / sigma
        bb = 1.0 / sigma
        broadening_function = lambda x: 1.0 / (1.0 + np.cosh(bb * x))
    elif broadening == GAUSS_BROADENING:
        aa = 1.0 / (sigma * np.sqrt(np.pi))
        bb = -1.0 / sigma**2
        broadening_function = lambda x: np.exp(bb * x * x)
    else:  # Methfessel-Paxton
        aa = 1.0 / sigma
        bb = 1.0 / sigma
        order = args.mporder + 1  # order = 0 => Gaussian
        coefs = np.zeros(2 * order, dtype=float)
        for ii in range(order):
            coefs[2*ii] = ((-1)**ii) / (math.factorial(ii) * (4**ii) \
                                        * math.sqrt(math.pi))
        broadening_function = lambda x: H.hermval(bb * x, coefs) \
                              * np.exp(-x * x * bb * bb)

    dsigma = sigmarange * sigma
    gridres = args.gridres

    minval = np.min(eigvals[:, :, :, 0]) - dsigma
    maxval = np.max(eigvals[:, :, :, 0]) + dsigma

    if args.verbose:
        if broadening == GAUSS_BROADENING:
            print("Gaussian broadening")
        elif broadening == FERMI_BROADENING:
            print("Fermi-function compatible broadening")
        else:
            print("Methfessel-Paxton compatible broadening")
        print("Broadening by {0:.2f} eV".format(sigma))
        if args.occweight:
            print("Weighting DOS by second column of data")
        print("Plotting from {0:.2f} eV to {1:.2f} eV".format(minval, maxval))
        print("Sigma window is : {0:.2f} eV with a grid resolution of {1:.2f}".
              format(dsigma, gridres))

    # First and last grid points, x-grid
    xmin = np.floor((minval) / gridres) * gridres
    xmax = np.ceil((maxval) / gridres) * gridres
    xvals = np.arange(xmin, xmax + gridres, gridres, dtype=float)
    nval = len(xvals)

    # Empty container for y-values
    yvals = np.zeros((bandout.nspin, nval), dtype=float)

    # Calculate broadened values around each state on the grid.
    for ispin in range(bandout.nspin):
        for ik in range(bandout.nkpt):
            prefac = aa * bandout.kweights[ispin, ik]
            for eigval, occ in eigvals[ispin, ik]:
                # Grid points for the current curve (first, last)
                ilower = int(np.floor((eigval - dsigma - xmin) / gridres))
                iupper = int(np.ceil((eigval + dsigma - xmin) / gridres))
                dx = eigval - xvals[ilower:iupper + 1]
                yvals[ispin, ilower:iupper + 1] += ((prefac * occ) *
                                                    broadening_function(dx))
    # Write resulting DOS
    fp = open(outfile, "w")
    if bandout.nspin == 1:
        for xx, yy in zip(xvals, yvals[0]):
            fp.write("{0:18.10E} {1:18.10E}\n".format(xx, yy))
    else:
        ytotal = np.sum(yvals, axis=0)
        formstr0 = "{0:18.10E} "
        tmp = [
            "{" + "{0:d}".format(ii) + ":18.10E}"
            for ii in range(1, bandout.nspin + 2)
        ]
        formstr = formstr0 + " ".join(tmp) + "\n"
        nvals = len(xvals)
        for ii in range(nvals):
            fp.write(formstr.format(xvals[ii], ytotal[ii], *yvals[:, ii]))
    fp.close()