Beispiel #1
0
def _geometry_block(outstr, indict, atom_props):
    # Geometry
    outstr += "EXTERNAL\n"  # we assume external geometry
    # Geometry Optional Keywords (including optimisation)
    for keyword in get_keys(indict, ["geometry", "info_print"], []):
        outstr += "{}\n".format(keyword)
    for keyword in get_keys(indict, ["geometry", "info_external"], []):
        outstr += "{}\n".format(keyword)
    if "optimise" in indict.get("geometry", {}):
        outstr += "OPTGEOM\n"
        outstr += format_value(indict, ["geometry", "optimise", "type"])
        unfixed = atom_props.get("unfixed", [])
        if unfixed:
            outstr += "FRAGMENT\n"
            outstr += "{}\n".format(len(unfixed))
            outstr += " ".join([str(a) for a in sorted(unfixed)]) + " \n"
        outstr += format_value(indict, ["geometry", "optimise", "hessian"])
        outstr += format_value(indict, ["geometry", "optimise", "gradient"])
        for keyword in get_keys(indict, ["geometry", "optimise", "info_print"],
                                []):
            outstr += "{}\n".format(keyword)
        outstr += format_value(indict, ["geometry", "optimise", "convergence"])
        outstr += "ENDOPT\n"

    # Geometry End
    outstr += "END\n"
    return outstr
def _read_geom_block(lines, output_dict, schema):
    while lines[0].strip() not in ["OPTGEOM", "END"]:

        line = _pop_line(lines)

        if line in [
                "FIELD", "FIELDCON", "CPHF", "ELASTCON", "EOS", "FREQCALC",
                "ANHARM", "CONFCNT", "CONFRAND", "RUNCONFS", "MOLEBSSE",
                "ATOMBSSE"
        ]:
            raise NotImplementedError("Geometry Block: {}".format(line))
        elif line in get_keys(
                schema, [
                    "properties", "geometry", "properties", "info_print",
                    "items", "enum"
                ],
                raise_error=True):
            _append_key(output_dict, "geometry.info_print", line)
        elif line in get_keys(
                schema, [
                    "properties", "geometry", "properties", "info_external",
                    "items", "enum"
                ],
                raise_error=True):
            _append_key(output_dict, "geometry.info_external", line)
def _read_geomopt_block(atom_props, line, lines, output_dict, schema):
    if lines[0].strip().startswith("END"):
        output_dict["geometry.optimise"] = True
    while not lines[0].strip().startswith("END"):
        line = _pop_line(lines)

        if line in ["EXTPRESS"]:
            raise NotImplementedError("GeomOpt Block: {}".format(line))
        elif line in get_keys(
                schema, [
                    "properties", "geometry", "properties", "optimise",
                    "properties", "type", "enum"
                ],
                raise_error=True):
            output_dict["geometry.optimise.type"] = line
        elif line in get_keys(
                schema, [
                    "properties", "geometry", "properties", "optimise",
                    "properties", "hessian", "enum"
                ],
                raise_error=True):
            output_dict["geometry.optimise.hessian"] = line
        elif line in get_keys(
                schema, [
                    "properties", "geometry", "properties", "optimise",
                    "properties", "gradient", "enum"
                ],
                raise_error=True):
            output_dict["geometry.optimise.gradient"] = line
        elif line in get_keys(
                schema, [
                    "properties", "geometry", "properties", "optimise",
                    "properties", "info_print", "items", "enum"
                ],
                raise_error=True):
            _append_key(output_dict, "geometry.optimise.info_print", line)
        elif line in get_keys(
                schema, [
                    "properties", "geometry", "properties", "optimise",
                    "properties", "convergence", "properties"
                ],
                raise_error=True).keys():
            key = "geometry.optimise.convergence.{}".format(line)
            line = _pop_line(lines)
            try:
                output_dict[key] = int(line)
            except ValueError:
                output_dict[key] = float(line)
        elif line == "FRAGMENT":
            val, line = _get_atom_prop(lines, "fragment")
            atom_props["fragment"] = val
        else:
            raise NotImplementedError("OPTGEOM block: {}".format(line))
    line = _pop_line(lines, 2)
    return line
Beispiel #4
0
def _hamiltonian_block(outstr, indict, atom_props):
    # Hamiltonian Optional Keywords
    outstr += format_value(indict, ["scf", "single"])
    # DFT Optional Block
    if get_keys(indict, ["scf", "dft"], False):

        outstr += "DFT\n"

        xc = get_keys(indict, ["scf", "dft", "xc"], raise_error=True)
        if isinstance(xc, (tuple, list)):
            if len(xc) == 2:
                outstr += "CORRELAT\n"
                outstr += "{}\n".format(xc[0])
                outstr += "EXCHANGE\n"
                outstr += "{}\n".format(xc[1])
        else:
            outstr += format_value(indict, ["scf", "dft", "xc"])

        if get_keys(indict, ["scf", "dft", "SPIN"], False):
            outstr += "SPIN\n"

        outstr += format_value(indict, ["scf", "dft", "grid"])
        outstr += format_value(indict, ["scf", "dft", "grid_weights"])
        outstr += format_value(indict, ["scf", "dft", "numerical"])

        outstr += "END\n"

    # # K-POINTS (SHRINK\nPMN Gilat)
    outstr += "SHRINK\n"
    outstr += "{0} {1}\n".format(
        *get_keys(indict, ["scf", "k_points"], raise_error=True))
    # ATOMSPIN
    spins = []
    for anum in atom_props.get("spin_alpha", []):
        spins.append((anum, 1))
    for anum in atom_props.get("spin_beta", []):
        spins.append((anum, -1))
    if spins:
        outstr += "ATOMSPIN\n"
        outstr += "{}\n".format(len(spins))
        for anum, spin in sorted(spins):
            outstr += "{0} {1}\n".format(anum, spin)

    # SCF/Other Optional Keywords
    outstr += format_value(indict, ["scf", "numerical"])
    outstr += format_value(indict, ["scf", "fock_mixing"])
    outstr += format_value(indict, ["scf", "spinlock"])
    for keyword in get_keys(indict, ["scf", "post_scf"], []):
        outstr += "{}\n".format(keyword)

    # Hamiltonian and SCF End
    outstr += "END\n"
    return outstr
def _read_dft_block(lines, output_dict, schema):
    correlat = None
    exchange = None
    while lines[0].strip() != "END":
        line = _pop_line(lines)
        if line == "SPIN":
            output_dict["scf.dft.SPIN"] = True
        elif line in get_keys(
                schema, [
                    "properties", "scf", "properties", "dft", "properties",
                    "xc", "oneOf", 1, "enum"
                ],
                raise_error=True):
            output_dict["scf.dft.xc"] = line
        elif line == "CORRELAT":
            line = _pop_line(lines)
            correlat = line
        elif line == "EXCHANGE":
            line = _pop_line(lines)
            exchange = line
        elif line == "LSRSH-PBE":
            line = _pop_line(lines)
            output_dict["scf.dft.xc.LSRSH-PBE"] = _split_line(line)
        elif line in get_keys(
                schema, [
                    "properties", "scf", "properties", "dft", "properties",
                    "grid", "enum"
                ],
                raise_error=True):
            output_dict["scf.dft.grid"] = line
        elif line in get_keys(
                schema, [
                    "properties", "scf", "properties", "dft", "properties",
                    "grid_weights", "enum"
                ],
                raise_error=True):
            output_dict["scf.dft.grid_weights"] = line
        elif line in get_keys(
                schema, [
                    "properties", "scf", "properties", "dft", "properties",
                    "numerical", "properties"
                ],
                raise_error=True).keys():
            key = line
            line = _pop_line(lines)
            output_dict["scf.dft.numerical.{}".format(key)] = _split_line(line)
        else:
            raise NotImplementedError("DFT Block: {}".format(line))
    if (correlat, exchange) != (None, None):
        if None in (correlat, exchange):
            raise IOError("found only one of CORRELAT EXCHANGE: {} {}".format(
                correlat, exchange))
        output_dict["scf.dft.xc"] = (exchange, correlat)
def _read_hamiltonian_block(atom_props, lines, output_dict, schema):

    sblock = ["properties", "scf", "properties"]

    while lines[0].strip() != "END":
        line = _pop_line(lines)
        if line == "DFT":
            _read_dft_block(lines, output_dict, schema)

            line = _pop_line(lines)
        elif line == "SHRINK":
            line = _pop_line(lines)
            try:
                kis, kisp = line.split()
                kis = int(kis)
                kisp = int(kisp)
            except ValueError:
                raise IOError(
                    "expecting SHRINK in form 'is isp': {}".format(line))
            output_dict["scf.k_points"] = (kis, kisp)
        elif line in get_keys(
                schema, sblock + ["single", "enum"], raise_error=True):
            output_dict["scf.single"] = line
        elif line in get_keys(
                schema, sblock + ["numerical", "properties"],
                raise_error=True).keys():
            key = line
            if get_keys(
                    schema,
                    sblock + ["numerical", "properties", key, "type"],
                    raise_error=True) == "boolean":
                output_dict["scf.numerical.{}".format(key)] = True
            else:
                line = _pop_line(lines)
                output_dict["scf.numerical.{}".format(key)] = _split_line(line)
        elif line in get_keys(
                schema, sblock + ["post_scf", "items", "enum"],
                raise_error=True):
            _append_key(output_dict, "scf.post_scf", line)
        elif line in get_keys(
                schema, sblock + ["spinlock", "properties"],
                raise_error=True).keys():
            key = line
            line = _pop_line(lines)
            output_dict["scf.spinlock.{}".format(key)] = _split_line(line)
        elif line in get_keys(
                schema,
                sblock + ["fock_mixing", "oneOf", 0, "enum"],
                raise_error=True):
            output_dict["scf.fock_mixing"] = line
        elif line == "BROYDEN":
            line = _pop_line(lines)
            output_dict["scf.fock_mixing.BROYDEN"] = _split_line(line)
        elif line == "ATOMSPIN":
            val, line = _get_atom_prop(lines, "atomspin")
            atom_props["spin_alpha"] = val[0]
            atom_props["spin_beta"] = val[1]
        else:
            raise NotImplementedError("Hamiltonian Block: {}".format(line))
Beispiel #7
0
def write_input(indict, basis_sets, atom_props=None):
    """write input of a validated input dictionary

    :param indict: dictionary of input
    :param basis_sets: list of basis set strings or objects with `content` property
    :param atom_props: dictionary of atom ids with specific properties ("spin_alpha", "spin_beta", "unfixed", "ghosts")
    :return:
    """
    # validation
    validate_with_json(indict)
    if not basis_sets:
        raise ValueError("there must be at least one basis set")
    elif not (all([isinstance(b, six.string_types) for b in basis_sets])
              or all([hasattr(b, "content") for b in basis_sets])):
        raise ValueError(
            "basis_sets must be either all strings or all objects with a `content` property"
        )
    if atom_props is None:
        atom_props = {}
    if not set(atom_props.keys()).issubset(
        ["spin_alpha", "spin_beta", "unfixed", "ghosts"]):
        raise ValueError(
            "atom_props should only contain: 'spin_alpha', 'spin_beta', 'unfixed', 'ghosts'"
        )
    # validate that a index isn't in both spin_alpha and spin_beta
    allspin = atom_props.get("spin_alpha", []) + atom_props.get(
        "spin_beta", [])
    if len(set(allspin)) != len(allspin):
        raise ValueError(
            "a kind cannot be in both spin_alpha and spin_beta: {}".format(
                allspin))

    outstr = ""

    # Title
    title = get_keys(indict, ["title"], "CRYSTAL run")
    outstr += "{}\n".format(" ".join(title.splitlines()))  # must be one line

    outstr = _geometry_block(outstr, indict, atom_props)

    outstr = _basis_set_block(outstr, indict, basis_sets, atom_props)

    outstr = _hamiltonian_block(outstr, indict, atom_props)

    return outstr
Beispiel #8
0
def format_value(dct, keys):
    """return the value + a new line, or empty string if keys not found"""
    value = get_keys(dct, keys, None)
    if value is None:
        return ""
    if isinstance(value, dict):
        outstr = ""
        for keyword in value.keys():
            args = value[keyword]
            if isinstance(args, bool):
                if args:
                    outstr += "{}\n".format(keyword)
            elif isinstance(args, (list, tuple)):
                outstr += "{0}\n{1}\n".format(keyword,
                                              " ".join([str(a) for a in args]))
            else:
                outstr += "{0}\n{1}\n".format(keyword, args)
        return outstr

    return "{}\n".format(value)
def _read_basis_block(atom_props, basis_sets, lines, output_dict, schema):
    basis_lines = []
    while not lines[0].startswith("99 "):
        line = _pop_line(lines)
        basis_lines.append(line)
        try:
            anum, nshells = line.split()  # pylint: disable=unused-variable
            nshells = int(nshells)
        except ValueError:
            raise IOError("expected 'anum nshells': {}".format(line))
        for i in range(nshells):
            line = _pop_line(lines)
            basis_lines.append(line)
            try:
                btype, stype, nfuncs, _, _ = line.split()
                btype, stype, nfuncs = [int(i) for i in [btype, stype, nfuncs]]
                # charge, scale = [float(i) for i in [charge, scale]]
            except ValueError:
                raise IOError(
                    "expected 'btype, stype, nfuncs, charge, scale': {}".
                    format(line))
            if btype == 0:
                for _ in range(nfuncs):
                    line = _pop_line(lines)
                    basis_lines.append(line)
        basis_sets.append("\n".join(basis_lines))
        basis_lines = []
    line = _pop_line(lines)
    while lines[0].strip() != "END":
        line = _pop_line(lines)
        if line in get_keys(
                schema, ["properties", "basis_set", "properties"],
                raise_error=True).keys():
            output_dict["basis_set.{}".format(line)] = True
        elif line == "GHOSTS":
            val, line = _get_atom_prop(lines, "ghosts")
            atom_props["ghosts"] = val
        else:
            raise NotImplementedError("Basis Set Block: {}".format(line))