Пример #1
0
def test_simple():
    cp2k_generator = CP2KInputGenerator(DEFAULT_CP2K_INPUT_XML)

    with open(TEST_DIR.joinpath("inputs/test01.json"), "r") as fhandle:
        tree = json.load(fhandle)

    lines = list(cp2k_generator.line_iter(tree))
    assert any("&GLOBAL" in line for line in lines)
Пример #2
0
def test_simplified_input():
    ryaml = pytest.importorskip("ruamel.yaml")
    yaml = ryaml.YAML()

    cp2k_generator = CP2KInputGenerator(DEFAULT_CP2K_INPUT_XML)

    with open(TEST_DIR.joinpath("inputs/NaCl-BS.simplified.yaml"), "r") as fhandle:
        tree = yaml.load(fhandle)

    lines = list(cp2k_generator.line_iter(tree))
    with open(TEST_DIR.joinpath("inputs/NaCl-BS.simplified.inp"), "r") as fhandle:
        assert lines == [line.strip("\n") for line in fhandle.readlines()]
Пример #3
0
def test_roundtrip_simplified():
    cp2k_parser = CP2KInputParserSimplified(DEFAULT_CP2K_INPUT_XML)
    with open(TEST_DIR.joinpath("inputs/test01.inp"), "r") as fhandle:
        ref_tree = cp2k_parser.parse(fhandle)

    cp2k_generator = CP2KInputGenerator(DEFAULT_CP2K_INPUT_XML)
    fhandle = io.StringIO("\n".join(cp2k_generator.line_iter(ref_tree)))

    # reinitialize parser and generators to clear any internal state they might have
    cp2k_parser = CP2KInputParserSimplified(DEFAULT_CP2K_INPUT_XML)
    fhandle.name = "StringIO"  # add a filename (required by parser for context)

    assert cp2k_parser.parse(fhandle) == ref_tree
Пример #4
0
    def write_cp2k_inputs(self, filename: str) -> None:
        """Write the current state of the inputs to the passed file name.

        Creates the standard cp2k input format. Overwrites anything present.

        Parameters
        ----------
        filename
            The file to write the input to
        """
        with open(filename, 'w') as f:
            cp2k_gen = CP2KInputGenerator()
            for line in cp2k_gen.line_iter(self.cp2k_dict):
                f.write(f"{line}\n")
Пример #5
0
def test_roundtrip2_canonical():
    cp2k_parser = CP2KInputParser(DEFAULT_CP2K_INPUT_XML)
    with open(TEST_DIR.joinpath("inputs/test04.inp"), "r") as fhandle:
        ref_tree = cp2k_parser.parse(fhandle)
        ref_tree["+force_eval"][0]["+subsys"]["+kind"].sort(
            key=lambda d: d["_"])

    cp2k_generator = CP2KInputGenerator(DEFAULT_CP2K_INPUT_XML)
    fhandle = io.StringIO("\n".join(cp2k_generator.line_iter(ref_tree)))

    # reinitialize parser and generators to clear any internal state they might have
    cp2k_parser = CP2KInputParser(DEFAULT_CP2K_INPUT_XML)
    fhandle.name = "StringIO"  # add a filename (required by parser for context)

    tree = cp2k_parser.parse(fhandle)
    tree["+force_eval"][0]["+subsys"]["+kind"].sort(key=lambda d: d["_"])

    assert tree == ref_tree
Пример #6
0
def tocp2k(fhandle, yaml):
    """
    Generate a CP2K input file based on JSON (or YAML) file
    """

    if yaml:
        from ruamel.yaml import YAML

        yaml = YAML()

        tree = yaml.load(fhandle)
    else:

        tree = json.load(fhandle)

    cp2k_generator = CP2KInputGenerator()

    for line in cp2k_generator.line_iter(tree):
        print(line)
Пример #7
0
def write_cp2k(fhandle, project_name, atoms, tree):
    """Merge the new the atoms structure with the configuration tree to a new CP2K input file.

    :param fhandle: open file handle to which the routine will write to
    :param project_name: the project name to use (CP2K uses that as prefix for generated files)i
    :param atoms: the Atoms objects to use
    :param tree: the configuration tree as returned from CP2KInputParser
    """
    from cp2k_input_tools.generator import CP2KInputGenerator

    generator = CP2KInputGenerator()

    tree["+global"]["run_type"] = "ENERGY_FORCE"
    tree["+global"]["project_name"] = project_name

    force_eval = tree["+force_eval"][0]
    subsys = force_eval["+subsys"]

    # if the original input contained scaled positions, continue with scaled positions
    if subsys["+coord"].get("scaled", False):
        cp2k_coord = {
            "scaled":
            True,
            "*": [
                "{sym} {x} {y} {z}".format(sym=sym,
                                           x=coord[0],
                                           y=coord[1],
                                           z=coord[2])
                for sym, coord in zip(atoms.get_chemical_symbols(),
                                      atoms.get_scaled_positions())
            ],
        }
    # ... otherwise use absolute positions
    else:
        cp2k_coord = {
            "*": [
                "{sym} {x} {y} {z}".format(sym=sym,
                                           x=coord[0],
                                           y=coord[1],
                                           z=coord[2])
                for sym, coord in zip(atoms.get_chemical_symbols(),
                                      atoms.get_positions())
            ],
        }

    subsys["+cell"]["a"] = list(atoms.get_cell()[0])
    subsys["+cell"]["b"] = list(atoms.get_cell()[1])
    subsys["+cell"]["c"] = list(atoms.get_cell()[2])
    subsys["+cell"][
        "periodic"] = "XYZ"  # anything else does not make much sense

    subsys["+coord"] = cp2k_coord  # overwriting the coordinates

    if "+print" not in force_eval:
        force_eval["+print"] = {}
    if "+forces" not in force_eval["+print"]:
        force_eval["+print"]["+forces"] = {}
    force_eval["+print"]["+forces"][
        "filename"] = "forces"  # uses the project name as base with 'forces' as suffix

    for line in generator.line_iter(tree):
        fhandle.write("{line}\n".format(line=line))
Пример #8
0
def cp2kgen(fhandle, expressions, base_dir, canonical, var_values):
    """
    Generates variations of the given CP2K input file

    Examples for generator expressions:

    "force_eval/dft/mgrid/cutoff=[300,400,500,800]", "force_eval/subsys/cell/a/0=10.0"
    """

    if canonical:
        cp2k_parser = CP2KInputParser(base_dir=base_dir, key_trafo=str.lower)
    else:
        cp2k_parser = CP2KInputParserSimplified(base_dir=base_dir,
                                                key_trafo=str.lower)

    tree = cp2k_parser.parse(fhandle, dict(var_values))

    # list of substitutions/transformations to apply
    substitutions = []

    for expression in expressions:
        try:
            kpath, value = expression.split("=", maxsplit=1)
        except ValueError:
            raise ValueError(
                "an expression must be of the form 'path/to/key=...'"
            ) from None

        if re.match(r"^\[.+\]$", value):
            values = [v.strip() for v in value.strip("[]").split(",")]
            substitutions += [(kpath, values)]
        else:
            substitutions += [(kpath, [value])]

    fpath = pathlib.Path(fhandle.name)
    onameprefix = fpath.stem
    onamesuffix = fpath.suffix

    # first generate a list of list of tuples [ [(key/a, 10), (key/a, 20), ...], [(key/b, 100), ...], ...]
    for substtuple in itertools.product(*[[(k, v) for v in values]
                                          for k, values in substitutions]):
        # ... then iterate over the cartesian product
        curr_tree = deepcopy(tree)  # create a full copy of the initial tree
        onameparts = []  # output name parts
        for kpath, value in substtuple:
            ref = curr_tree

            sections = kpath.split("/")
            for section in sections[:-1]:
                if isinstance(ref, list):
                    section = int(
                        section
                    )  # if we encounter a list, convert the respective path element
                ref = ref[
                    section]  # exploit Python using references into dicts/lists

            attr = sections[-1]
            if isinstance(ref, (list, tuple)):
                attr = int(attr)

            if isinstance(ref, tuple):
                # we only get tuples for keywords which can take multiple words, hence this should be safe
                lref = list(ref)
                lref[attr] = value
                ref = tuple(lref)
            else:
                ref[attr] = value

            # take only the attribute name
            onameparts += [f"{attr}_{value}"]

        opath = pathlib.Path(
            f"{onameprefix}-{'-'.join(onameparts)}{onamesuffix}")
        print(f"Writing '{opath}'...")

        with opath.open("w") as fouthandle:
            fouthandle.write(
                f"! Generated with the CP2K input tool cp2kgen v{__version__}\n! "
            )
            fouthandle.write(" \\\n!   ".join(f"'{arg}'" for arg in sys.argv))
            fouthandle.write("\n")
            cp2k_generator = CP2KInputGenerator()
            for line in cp2k_generator.line_iter(curr_tree):
                fouthandle.write(f"{line}\n")