示例#1
0
parser.add_argument("-d", "--datafile",
                    type = str,
                    help = "The simulation data file",
                    nargs = "?",
                    default = GD.file_resultdatafile)

parser.add_argument("-b", "--blockid",
                    type = str,
                    help = "The data block to handle",
                    nargs = "*",
                    default = ["all"])

args = parser.parse_args()

# Read file with simulation data
iom = IOManager()
iom.open_file(filename=args.datafile)

# Which blocks to handle
blockids = iom.get_block_ids()
if "all" not in args.blockid:
    blockids = [bid for bid in args.blockid if bid in blockids]

# Iterate over all blocks
for blockid in blockids:
    if iom.has_wavefunction(blockid=blockid):
        print("Deleting grid and wavefunction data in block '{}'".format(blockid))
        iom.delete_wavefunction(blockid=blockid)
        if iom.has_grid(blockid=blockid):
            iom.delete_grid(blockid=blockid)
示例#2
0
Compute the eigen transformation of some simulation results.

@author: R. Bourquin
@copyright: Copyright (C) 2012 R. Bourquin
@license: Modified BSD License
"""

import sys

from WaveBlocksND import IOManager
from WaveBlocksND import GlobalDefaults as GD


if __name__ == "__main__":

    iomc = IOManager()
    iome = IOManager()

    # Read file with simulation data
    try:
        filename = sys.argv[1]
    except IndexError:
        filename = GD.file_resultdatafile

    iomc.open_file(filename=filename)

    # New file for eigen transformed data
    P = iomc.load_parameters()
    iome.create_file(P, filename=filename[:-5]+"_eigen.hdf5")

    # Iterate over all groups
示例#3
0
def compute_eigenstate(parameters,
                       filename="eigenstates.hdf5",
                       computepq=True,
                       computePQ=True):
    r"""
    Special variables necessary in configuration:

    * eigenstate_of_level (default: 0)
    * eigenstates_indices (default: [0])
    * starting_point (default: (2, ..., 2))
    * hawp_template
    * innerproduct
    """
    D = parameters["dimension"]

    if "eigenstate_of_level" in parameters:
        N = parameters["eigenstate_of_level"]
    else:
        # Upper-most potential surface
        N = 0

    # Create output file now, in case this fails we did not waste computation time
    IOM = IOManager()
    IOM.create_file(filename)

    # Save the simulation parameters
    IOM.add_parameters()
    IOM.save_parameters(parameters)

    gid = IOM.create_group()

    BF = BlockFactory()
    # Create the potential
    V = BF.create_potential(parameters)
    V.calculate_local_quadratic()

    # Compute position and momentum
    if computepq:
        # Minimize the potential to find q0
        f = lambda x: real((squeeze(V.evaluate_at(x)[N])))
        # Start with an offset because exact 0.0 values can give
        # issues, especially with the Hessian evaluation. This way
        # the minimizer will always stay away from zero a tiny bit.
        # The current starting point can give issues if the potential
        # is stationary at the point (2, ..., 2) but that is less likely.
        if "starting_point" in parameters:
            x0 = atleast_1d(parameters["starting_point"])
        else:
            x0 = 0.5 * ones(D)

        q0 = fmin(f, x0, xtol=1e-12)
        q0 = q0.reshape((D, 1))

        # We are at the minimum with no momentum
        p0 = zeros_like(q0)
    else:
        if "q0" in parameters:
            q0 = atleast_2d(parameters["q0"])
        else:
            q0 = zeros((D, 1))
        if "p0" in parameters:
            p0 = atleast_2d(parameters["p0"])
        else:
            p0 = zeros((D, 1))

    # Compute spreads
    if computePQ:
        # Q_0 = H^(-1/4)
        H = V.evaluate_hessian_at(q0)
        Q0 = inv(sqrtm(sqrtm(H)))
        # P_0 = i Q_0^(-1)
        P0 = 1.0j * inv(Q0)
    else:
        if "Q0" in parameters:
            Q0 = atleast_2d(parameters["Q0"])
        else:
            Q0 = identity(D)
        if "P0" in parameters:
            P0 = atleast_2d(parameters["P0"])
        else:
            P0 = 1.0j * inv(Q0)

    # The parameter set Pi
    print(70 * "-")
    print("Parameter values are:")
    print("---------------------")
    print(" q0:")
    print(str(q0))
    print(" p0:")
    print(str(p0))
    print(" Q0:")
    print(str(Q0))
    print(" P0:")
    print(str(P0))
    # Consistency check
    print(" Consistency check:")
    print("   P^T Q - Q^T P  =?=  0")
    print(dot(P0.T, Q0) - dot(Q0.T, P0))
    print("   Q^H P - P^H Q  =?=  2i")
    print(
        dot(transpose(conjugate(Q0)), P0) - dot(transpose(conjugate(P0)), Q0))

    # Next find the new coefficients c'
    HAWP = BF.create_wavepacket(parameters["hawp_template"])

    # Set the parameter values
    Pi = HAWP.get_parameters()
    Pi[0] = q0
    Pi[1] = p0
    Pi[2] = Q0
    Pi[3] = P0
    HAWP.set_parameters(Pi)

    # Next compute the matrix M_ij = <phi_i | T + V | phi_j>
    # The potential part
    HQ = BF.create_inner_product(parameters["innerproduct"])

    opV = lambda x, q, entry: V.evaluate_at(x, entry=entry)
    MV = HQ.build_matrix(HAWP, operator=opV)

    # The kinetic part
    MT = zeros_like(MV, dtype=complexfloating)
    GR = GradientHAWP()
    BS = HAWP.get_basis_shapes(component=N)

    vects = {}
    for i in BS:
        z = zeros_like(HAWP.get_coefficient_vector(), dtype=complexfloating)
        HAWP.set_coefficient_vector(z)
        HAWP.set_coefficient(N, i, 1.0)
        Kn, cnew = GR.apply_gradient(HAWP, component=N, as_packet=False)
        vects[i] = cnew

    for j in BS:
        for k in BS:
            cj = vects[j]
            ck = vects[k]
            entry = 0.5 * squeeze(sum(conjugate(cj) * ck))
            MT[BS[j], BS[k]] = entry

    # Find eigenvalues and eigenvectors of the whole matrix
    M = MT + MV
    ew, ev = eigh(M)
    ind = argsort(ew)

    # Build the requested energy levels and states
    if "eigenstates_indices" in parameters:
        states = parameters["eigenstates_indices"]
    else:
        # Groundstate only
        states = [0]

    BS = HAWP.get_basis_shapes(component=0)

    KEY = ("q", "p", "Q", "P", "S", "adQ")

    print(70 * "-")
    for state in states:
        if state > BS.get_basis_size():
            print(
                "Warning: can not compute energy level {} with basis size of {}"
                .format((state, BS)))
            continue

        index = ind[state]

        coeffs = ev[:, index]
        energy = ew[index]

        # Try to resolve ambiguities in sign
        imax = argmax(abs(coeffs))
        a = abs(angle(coeffs[imax]))
        if a > pi / 2.0:
            coeffs *= -1

        print("State: {}".format(state))
        print("Energy: {}".format(energy))
        print("Coefficients: \n")
        print(str(coeffs))
        print(70 * "-")

        HAWP.set_coefficient_vector(coeffs.reshape((-1, 1)))

        # Save all the wavepacket data
        bid = IOM.create_block(groupid=gid)
        IOM.add_wavepacket(parameters, blockid=bid, key=KEY)
        IOM.save_wavepacket(HAWP, 0, blockid=bid, key=KEY)

    IOM.finalize()

    # TODO: Find better criterion
    if norm(q0) > 1000:
        print("+----------------------------------+")
        print("| Run-away minimum?                |")
        print("| Maybe try different:             |")
        print("|   starting_point = [x0, y0, ...] |")
        print("+----------------------------------+")
示例#4
0
def load_from_file(filepath, blockid=0, timestep=0, sizeK=None):
    r"""Utility script to load wavepacket parameters and coefficients
    from another simulation result in a form suitable for the input
    configuration of a new simulation. This is (mainly) used
    to start simulations with previously computed eigenstates.

    :param filepath: The path to the `.hdf5` file from which data will be read.
    :param blockid: The `datablock` from which to read the data.
                    Default is the block with `blockid=0`.
    :param timestep: Load the data corresponding to the given `timestep`.
                     The default timestep is `0`.
    :param sizeK: Load at most 'sizeK' many coefficients. Note that the order
                  is defined by the linearization mapping :math:`\mu` of the
                  packet's current basis shape. We then pick the first `sizeK`
                  ones.
    """
    IOM = IOManager()
    IOM.open_file(filepath)

    # Check if we have data
    tg = IOM.load_wavepacket_timegrid(blockid=blockid)
    if timestep not in tg:
        raise ValueError("No data for timestep {}".format(timestep))

    # Load data and assemble packet
    BF = BlockFactory()

    # Basis shapes
    BS_descr = IOM.load_wavepacket_basisshapes(blockid=blockid)
    BS = {}
    for ahash, descr in BS_descr.items():
        BS[ahash] = BF.create_basis_shape(descr)

    # Create a packet
    wpd = IOM.load_wavepacket_description(blockid=blockid)
    HAWP = BF.create_wavepacket(wpd)

    # Data
    ha, ci = IOM.load_wavepacket_coefficients(blockid=blockid,
                                              timestep=timestep,
                                              get_hashes=True)
    Pi = IOM.load_wavepacket_parameters(blockid=blockid, timestep=timestep)

    HAWP.set_parameters(Pi)
    HAWP.set_basis_shapes([BS[int(h)] for h in ha])
    HAWP.set_coefficients(ci)

    # Reformat data
    C = []

    for n in range(HAWP.get_number_components()):
        B = HAWP.get_basis_shapes(component=n)
        cn = HAWP.get_coefficients(component=n)
        l = []
        for i in range(B.get_basis_size()):
            l.append((B[i], cn[i, 0]))
        C.append(l)

    if sizeK is not None:
        # We load at most 'sizeK' coefficients.
        # Note that this does NOT specify which
        # ones in terms of multi-indices.
        C = [c[:sizeK] for c in C]

    return Pi, C