Esempio n. 1
0
        def action_compute(targets: List[str]):
            del targets

            operator = self.operator.resolve()
            psi = self.psi.resolve()
            expval = self.expval.resolve()
            wave_function = self.wave_function.resolve()

            with tempfile.TemporaryDirectory() as tmpdir:
                with cwd.WorkingDir(tmpdir):
                    self.logger.info("compute expectation value")
                    copy_file(operator, "operator")
                    copy_file(psi, "psi")
                    copy_file(wave_function, "restart")
                    cmd = [
                        "qdtk_expect.x",
                        "-opr",
                        "operator",
                        "-rst",
                        "restart",
                        "-psi",
                        "psi",
                        "-save",
                        "expval",
                    ]
                    self.logger.info("command: %s", " ".join(cmd))
                    env = os.environ.copy()
                    env["OMP_NUM_THREADS"] = env.get("OMP_NUM_THREADS", "1")
                    subprocess.run(cmd, env=env)

                    write_expval_hdf5("expval.h5", *read_expval_ascii("expval"))

                    copy_file("expval.h5", expval)
Esempio n. 2
0
        def action_compute(targets: list[str]):
            del targets

            wave_function = self.wave_function.resolve()
            psi = self.psi.resolve()
            outpath = self.output.resolve()

            with tempfile.TemporaryDirectory() as tmpdir:
                with cwd.WorkingDir(tmpdir):
                    copy_file(psi, "psi")
                    copy_file(wave_function, "restart")

                    results: None | numpy.ndarray = None
                    cmd = [
                        "qdtk_expect.x",
                        "-opr",
                        "operator",
                        "-rst",
                        "restart",
                        "-psi",
                        "psi",
                        "-save",
                        "expval",
                    ]

                    for i, combination in enumerate(self.indices):
                        with open("operator", "w") as fptr:
                            self.func(*combination).get_operator(
                            ).createOperatorFile(fptr, )

                        self.logger.info(f'command: {" ".join(cmd)}')
                        env = os.environ.copy()
                        env["OMP_NUM_THREADS"] = env.get(
                            "OMP_NUM_THREADS", "1")
                        subprocess.run(cmd, env=env)

                        time, values = read_expval_ascii("expval")
                        if results is None:
                            results = numpy.zeros(
                                [len(time), len(self.indices)],
                                dtype=numpy.complex128,
                            )
                        results[:, i] = values
                    with h5py.File(outpath, "w") as fptr:
                        fptr.create_dataset("time", data=time)
                        fptr.create_dataset("indices", data=self.indices)
                        fptr.create_dataset("values", data=results)
Esempio n. 3
0
        def action_compute(targets: List[str]):
            del targets

            wave_function = self.wave_function.resolve()
            psi = self.psi.resolve()
            basis = self.basis.resolve()
            result = self.result.resolve()

            with tempfile.TemporaryDirectory() as tmpdir:
                with cwd.WorkingDir(tmpdir):
                    self.logger.info("perform number state analysis")
                    copy_file(wave_function, "restart")
                    copy_file(basis, "basis")
                    copy_file(psi, "psi")
                    cmd = [
                        "qdtk_analysis.x",
                        "-fixed_ns",
                        "-rst_bra",
                        "basis",
                        "-rst_ket",
                        "restart",
                        "-save",
                        "result",
                        "-psi",
                        "psi",
                    ]
                    self.logger.info("command: %s", " ".join(cmd))
                    env = os.environ.copy()
                    env["OMP_NUM_THREADS"] = env.get("OMP_NUM_THREADS", "1")
                    subprocess.run(cmd, env=env)

                    times, real, imag = inout.read_fixed_ns_ascii("result")
                    wfn = load_wave_function("basis")
                    inout.write_fixed_ns_hdf5(
                        "result.h5",
                        times,
                        real,
                        imag,
                        wfn._tape[1],
                        wfn._tape[3],
                    )

                    with h5py.File("result.h5", "a") as fptr:
                        dset = fptr["fixed_ns"].create_dataset(
                            "total_magnitude",
                            shape=times.shape,
                            dtype=numpy.float64,
                        )
                        dset[:] = numpy.sum((real**2) + (imag**2), axis=1)

                    copy_file("result.h5", result)
Esempio n. 4
0
        def action_compute(targets: List[str]):
            wave_function = self.wave_function.resolve()
            basis = self.basis.resolve()
            result = self.result.resolve()

            with tempfile.TemporaryDirectory() as tmpdir:
                with cwd.WorkingDir(tmpdir):
                    self.logger.info(
                        "compute MCTDHB wave function overlap (static)")
                    copy_file(wave_function, "restart")
                    copy_file(basis, "basis")
                    cmd = [
                        "qdtk_analysis.x",
                        "-fixed_ns",
                        "-rst_bra",
                        "basis",
                        "-rst_ket",
                        "restart",
                        "-save",
                        "result",
                    ]
                    self.logger.info("command: %s", " ".join(cmd))
                    env = os.environ.copy()
                    env["OMP_NUM_THREADS"] = env.get("OMP_NUM_THREADS", "1")
                    subprocess.run(cmd, env=env)

                    _, real, imag = inout.read_fixed_ns_ascii("result")
                    self.logger.info(real.shape)
                    coeffs = load_wave_function("basis").PSI[:real.shape[1]]
                    overlap = (numpy.abs(
                        numpy.sum(
                            numpy.conjugate(coeffs) *
                            (real + 1j * imag)), )**2)
                    self.logger.info("overlap = %f", overlap)

                    with h5py.File(result, "w") as fptr:
                        fptr.create_dataset("overlap",
                                            shape=(1, ),
                                            dtype=numpy.float64)[:] = overlap
Esempio n. 5
0
        def action_run(targets: List[str]):
            del targets

            if not self.path_name.exists():
                self.path_name.mkdir()

            path_temp = self.path_name.resolve().with_name("." +
                                                           self.path_name.name)

            if path_temp.exists():
                path_temp_operator = path_temp / "hamiltonian"
                if not path_temp_operator.exists():
                    self.logger.debug(
                        'temporary operator "%s" does not exist',
                        str(path_temp_operator),
                    )
                    shutil.rmtree(path_temp)
                else:
                    hash_a = hash_file(path_temp_operator)
                    hash_b = hash_file(self.path_hamiltonian.resolve())
                    if hash_a != hash_b:
                        self.logger.debug("operator hashes do not match")
                        shutil.rmtree(path_temp)

            if path_temp.exists():
                path_temp_wfn = path_temp / "initial"
                if not path_temp_wfn.exists():
                    self.logger.debug(
                        'temporary wave function "%s" does not exist',
                        str(path_temp_wfn),
                    )
                    shutil.rmtree(path_temp)
                else:
                    hash_a = hash_file(path_temp_wfn)
                    hash_b = hash_file(self.path_wave_function.resolve())
                    if hash_a != hash_b:
                        self.logger.debug("wave function hashes do not match")
                        shutil.rmtree(path_temp)

            if path_temp.exists():
                self.logger.info("attempt continuation run")
                self.flags["cont"] = True
                self.flags["rstzero"] = False
                self.flag_list.append("-cont")
                try:
                    self.flag_list.remove("-rstzero")
                except ValueError:
                    pass

            with TemporaryDir(path_temp) as tmpdir:
                operator = self.path_hamiltonian.resolve()
                wave_function = self.path_wave_function.resolve()
                output_dir = self.path_name.resolve()
                hdf5_file = self.path_hdf5.resolve()
                diag_gauge_oper = (self.path_diag_gauge_oper.resolve()
                                   if self.path_diag_gauge_oper else None)

                with cwd.WorkingDir(tmpdir.path):
                    self.logger.info("propagate wave function")
                    if not self.flags["cont"]:
                        copy_file(operator, "hamiltonian")
                        copy_file(wave_function, "initial")
                        copy_file(wave_function, "restart")
                    if self.flags.get("gauge",
                                      "standard") == "diagonalization":
                        if not diag_gauge_oper:
                            raise ValueError(
                                "no operator specified for diagonalization gauge",
                            )
                        copy_file(diag_gauge_oper, "gauge_oper")
                    cmd = ["qdtk_propagate.x"] + self.flag_list
                    env = os.environ.copy()
                    env["OMP_NUM_THREADS"] = env.get("OMP_NUM_THREADS", "1")
                    self.logger.info("command: %s", " ".join(cmd))
                    result = subprocess.run(cmd, env=env)
                    if result.returncode != 0:
                        raise RuntimeError("Failed to run qdtk_propagate.x")

                    if self.flags["exact_diag"]:
                        with h5py.File("result.h5", "w") as fptr:
                            add_eigenbasis_to_hdf5(fptr,
                                                   *read_eigenbasis_ascii("."))
                    else:
                        shutil.move("restart", "final.wfn")
                        with h5py.File("result.h5", "w") as fptr:
                            add_gpop_to_hdf5(fptr.create_group("gpop"),
                                             *read_gpop_ascii("gpop"))
                            add_natpop_to_hdf5(
                                fptr.create_group("natpop"),
                                *read_natpop_ascii("natpop"),
                            )
                            add_output_to_hdf5(
                                fptr.create_group("output"),
                                *read_output_ascii("output"),
                            )

                            if "gauge" in self.flags:
                                if self.flags["gauge"] != "standard":
                                    time, error = numpy.loadtxt(
                                        "constraint_error.txt",
                                        unpack=True,
                                    )
                                    group = fptr.create_group(
                                        "constraint_error")
                                    group.create_dataset(
                                        "time",
                                        time.shape,
                                        dtype=time.dtype,
                                    )[:] = time
                                    group.create_dataset(
                                        "error",
                                        error.shape,
                                        dtype=error.dtype,
                                    )[:] = error

                    shutil.move("result.h5", hdf5_file)

                    if self.flags["exact_diag"]:
                        with open("eigenvectors") as fptr:
                            lines = fptr.readlines()
                        if not lines[0].startswith("$tape"):
                            with open("eigenvectors", "w") as fptr:
                                fptr.write("$tape\n")
                                fptr.writelines(lines)

                        if self.flags["eig_tot"]:
                            self.logger.info(
                                "exact diagonalization with one eigenvector, remove last two lines in eigenvectors file",
                            )
                            with open("eigenvectors") as fptr:
                                lines = fptr.readlines()[:-1]
                            with open("eigenvectors", "w") as fptr:
                                fptr.writelines(lines)

                    for fname in self.qdtk_files:
                        copy_file(fname, output_dir / fname)

                    tmpdir.complete = True
Esempio n. 6
0
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "--restart",
        type=Path,
        default=Path("restart"),
        help="path to the restart file",
    )
    parser.add_argument(
        "--operator",
        type=Path,
        default=Path("operator"),
        help="path to the hamiltonian operator",
    )
    parser.add_argument(
        "--psi",
        type=Path,
        default=Path("psi"),
        help="path to the psi file",
    )
    parser.add_argument("--dof1",
                        type=int,
                        default=1,
                        help="first degree of freedom")
    parser.add_argument("--dof2",
                        type=int,
                        default=1,
                        help="second degree of freedom")
    parser.add_argument("-o",
                        "--output",
                        type=Path,
                        help="path for the output file")
    args = parser.parse_args()

    restart_file = Path(args.restart).resolve()
    operator_file = Path(args.operator).resolve()
    psi_file = Path(args.psi).resolve()
    basename = f"dmat2_dof{args.dof1}_dof{args.dof2}"
    if not args.output:
        output_file = Path.cwd() / (basename + "_gridrep.h5")
    else:
        output_file = Path(args.output).resolve()

    with tempfile.TemporaryDirectory() as tmpdir:
        with WorkingDir(tmpdir):
            copy_file(restart_file, "restart")
            copy_file(operator_file, "operator")
            copy_file(psi_file, "psi")
            subprocess.run([
                "qdtk_analysis.x",
                "-dmat2",
                "-rst",
                "restart",
                "-opr",
                "operator",
                "-psi",
                "psi",
                "-dof",
                str(args.dof1),
                "-dofB",
                str(args.dof2),
            ], )
            with h5py.File(output_file, "w") as fptr:
                add_dmat2_gridrep_to_hdf5(
                    fptr,
                    read_dmat2_gridrep_ascii(basename + "_grid"),
                )
Esempio n. 7
0
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("operator",
                        type=Path,
                        help="path of the operator file")
    parser.add_argument("restart", type=Path, help="path of the restart file")
    parser.add_argument("psi", type=Path, help="path of the psi file")
    parser.add_argument("--node", type=int, default=0, help="node to use")
    parser.add_argument("--dof",
                        type=int,
                        default=1,
                        help="degree of freedom to use")
    parser.add_argument(
        "-o",
        "--output",
        type=Path,
        default=Path.cwd() / "dmat.h5",
        help="output file",
    )
    parser.add_argument("--slice", type=str)

    group_diag = parser.add_mutually_exclusive_group()
    group_diag.add_argument(
        "--diagonalize",
        action="store_true",
        help="whether to diagonalize the one-body density matrix",
    )
    group_diag.add_argument(
        "--only-diagonalize",
        action="store_true",
        help="whether to only diagonalize the one-body density matrix",
    )

    parser.add_argument(
        "--only-eigenvalues",
        action="store_true",
        help="whether to only output the eigenvalues",
    )

    group_rep = parser.add_mutually_exclusive_group()
    group_rep.add_argument(
        "--spfrep",
        action="store_true",
        help="use spf representation",
    )
    group_rep.add_argument(
        "--gridrep",
        action="store_true",
        help="use grid representation",
    )

    args = parser.parse_args()
    if args.only_eigenvalues and not (args.diagonalize
                                      or args.only_diagonalize):
        parser.error(
            "--only-eigenvalues only applies when --diagonalize or --only-diagonalize is specified",
        )

    output = args.output.resolve()
    opr = args.operator.resolve()
    rst = args.restart.resolve()
    psi = args.psi.resolve()
    with tempfile.TemporaryDirectory() as tempdir:
        with WorkingDir(tempdir):
            copy_file(opr, "opr")
            copy_file(rst, "rst")

            if args.slice:
                tape, times, psi = read_psi_ascii(psi)

                m = RE_SLICE.match(args.slice)
                if not m:
                    raise RuntimeError(f'Invalid slice format "{args.slice}"')

                start = 0
                end = len(times)
                step = 1
                if m.group(1) != "":
                    start = int(m.group(1))
                if m.group(2) != "":
                    stop = int(m.group(2))
                try:
                    if m.group(3) != "":
                        step = int(m.group(3))
                except IndexError:
                    pass

                indices = [i for i in range(start, end, step)]
                write_psi_ascii("psi", (tape, times[indices], psi[indices]))
            else:
                copy_file(psi, "psi")

            gridrep = args.gridrep or ((not args.gridrep) and
                                       (not args.spfrep))

            cmd = [
                "qdtk_analysis.x",
                "-opr",
                "opr",
                "-rst",
                "rst",
                "-psi",
                "psi",
                "-dmat",
                "-nd",
                str(args.node),
                "-dof",
                str(args.dof),
            ]
            if not gridrep:
                cmd.append("-spfrep")
            if gridrep:
                cmd.append("-gridrep")
            if args.diagonalize:
                cmd.append("-diagonalize")
            if args.only_diagonalize:
                cmd += ["-diagonalize", "-onlydiag"]
            if args.only_eigenvalues:
                cmd.append("-onlyeigval")
            LOGGER.info("cmd: %s", " ".join(cmd))

            subprocess.run(cmd)

            with h5py.File(output, "a") as fptr:
                if not args.only_diagonalize:
                    if gridrep:
                        dmat.add_dmat_gridrep_to_hdf5(
                            fptr,
                            dmat.read_dmat_gridrep_ascii(
                                f"dmat_dof{args.dof}_grid"),
                        )
                    else:
                        dmat.add_dmat_spfrep_to_hdf5(
                            fptr,
                            *dmat.read_dmat_spfrep_ascii(
                                f"dmat_dof{args.dof}_spf"),
                        )

                if args.diagonalize or args.only_diagonalize:
                    dmat.add_dmat_evals_to_hdf5(
                        fptr,
                        *dmat.read_dmat_evals_ascii(
                            f"eval_dmat_dof{args.dof}"),
                    )
                    if not args.only_eigenvalues:
                        if gridrep:
                            dmat.add_dmat_evecs_grid_to_hdf5(
                                fptr,
                                *dmat.read_dmat_evecs_grid_ascii(
                                    f"evec_dmat_dof{args.dof}_grid", ),
                            )
                        else:
                            dmat.add_dmat_evecs_spf_to_hdf5(
                                fptr,
                                *dmat.read_dmat_evecs_spf_ascii(
                                    f"evec_dmat_dof{args.dof}_spf", ),
                            )
Esempio n. 8
0
def compute_reduced_density_matrix(
    wave_function: PathLike,
    output_file: PathLike,
    dvrs: Sequence[DVRSpecification],
    dofs_A: Sequence[int],
    basis_states: Mapping[int, Sequence[ArrayLike]] | None = None,
    threads: int = 1,
):
    # convert paths
    wave_function = Path(wave_function).resolve()
    output_file = Path(output_file).resolve()

    # function to generate basis states for DoF
    def generate_basis_states(dof: int) -> list[ArrayLike]:
        states: list[ArrayLike] = []
        dim = dvrs[dof].get().npoints
        for i in range(dim):
            states.append(numpy.zeros((dim, )))
            states[-1][i] = 1
        return states

    # check/prepare basis states for each DoF
    if basis_states is None:
        # generate basis_states from DVR
        basis_states: dict[int, list[ArrayLike]] = {}
        for dof in dofs_A:
            basis_states[dof] = generate_basis_states(dof)

    else:
        # check that basis_states are consitent with DVR
        for dof in dofs_A:
            # no basis states for DoF -> generate them
            if dof not in basis_states:
                basis_states[dof] = generate_basis_states(dof)

            dim = dvrs[dof].get().npoints

            if len(basis_states[dof]) != dim:
                raise ValueError(
                    f"basis for DoF {dof} is overcomplete or incomplete (got {len(basis_states[dof])} states, expected {dim})",
                )

            for i, state in enumerate(basis_states[dof]):
                if len(state) != dim:
                    raise ValueError(
                        f"basis state {i} of DoF {dof} has wrong size (got {len(state)}, expected {dim})",
                    )

    # compute dimension of reduced density operator
    dim_A = reduce(mul, (len(basis_states[dof]) for dof in basis_states))

    # create storage for results
    results: dict[tuple[int, int], complex] = {}

    with TemporaryDir(
            Path(output_file).parent /
        ("." + Path(output_file).name + ".tmp"), ) as tmpdir:
        with WorkingDir(tmpdir.path):
            # copy wave function file
            copy_file(Path(wave_function), Path.cwd() / "psi")

            # generate a restart file
            tape, times, psi = read_psi_frame_ascii("psi", 0)
            write_psi_ascii("restart", [tape, [times], psi[numpy.newaxis, :]])

            # generate the tasks for the multiprocessing pool
            tasks = ([dvrs, dofs_A, a, state_a, b, state_b]
                     for a, state_a in enumerate(
                         product(*(basis_states[dof] for dof in dofs_A)), )
                     for b, state_b in enumerate(
                         product(*(basis_states[dof] for dof in dofs_A)), )
                     if b <= a)

            with multiprocessing.Pool(threads) as pool:
                for a, b, time, values in pool.starmap(
                        compute_reduced_density_matrix_element,
                        tasks,
                        1,
                ):
                    results[(a, b)] = values

        tmpdir.complete = True

    # convert results to an array
    steps = len(results[(0, 0)])
    results_arr = numpy.zeros((steps, dim_A, dim_A), dtype=numpy.complex128)
    for a in range(dim_A):
        for b in range(a + 1):
            results_arr[:, a, b] = results[(a, b)]

        for b in range(a + 1, dim_A):
            results_arr[:, a, b] = numpy.conjugate(results[(b, a)])

    # create parent directory of output file
    Path(output_file).parent.mkdir(exist_ok=True, parents=True)

    # make sure that results array is a 3rd order tensor
    # first index denotes time
    if len(results_arr.shape) == 2:
        results_arr = results_arr[numpy.newaxis, :, :]

    # store results in a HDF5 file
    with h5py.File(output_file, "w") as fptr:
        fptr.create_dataset("time", data=time)
        fptr.create_dataset("rho_A", data=results_arr)
        fptr.create_dataset("trace",
                            data=numpy.trace(results_arr, axis1=1, axis2=2))
        for dof in dofs_A:
            fptr.create_dataset(
                f"basis_states_{dof}",
                data=numpy.array(basis_states[dof]),
            )
Esempio n. 9
0
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("input", type=Path, help="path for the input file")
    parser.add_argument(
        "-o",
        "--output",
        type=Path,
        default=None,
        help="path for the video file",
    )
    parser.add_argument(
        "-f",
        "--fps",
        type=float,
        default=5,
        help="frames per second for the video",
    )
    parser.add_argument(
        "--dpi",
        type=int,
        default=600,
        help="resolution (dpi) of the individual frames",
    )
    parser.add_argument(
        "-j",
        "--jobs",
        type=int,
        default=os.cpu_count(),
        help="number of threads to use to create the individual frames",
    )
    args = parser.parse_args()

    times, x1, x2, dmat2 = read_dmat2_gridrep_hdf5(args.input)
    X2, X1 = numpy.meshgrid(x2, x1)

    num_digits = len(str(len(times)))

    if args.output:
        output = args.output.resolve()
    else:
        output = args.input.with_suffix(".mp4").resolve()

    with tempfile.TemporaryDirectory() as tmpdir:
        with WorkingDir(tmpdir):
            with multiprocessing.Pool(args.jobs) as pool:
                pool.map(
                    partial(
                        render_frame,
                        times=times,
                        dmat2=dmat2,
                        X1=X1,
                        X2=X2,
                        num_digits=num_digits,
                        dpi=args.dpi,
                    ),
                    [i for i, _ in enumerate(times)],
                )

            cmd = [
                "ffmpeg",
                "-y",
                "-framerate",
                str(args.fps),
                "-i",
                "%0" + str(num_digits) + "d.png",
                "out.mp4",
            ]
            LOGGER.info("ffmpeg command: %s", " ".join(cmd))
            subprocess.run(cmd)
            LOGGER.info("copy file: out.mp4 -> %s", str(output))
            copy_file("out.mp4", output)