Ejemplo n.º 1
0
def _process_hessian(H_blocks, B_blocks, massweighter, print_lvl):
    """Perform post-construction processing for the Hessian.
       Statements need to be printed, and the Hessian must be transformed.

    Parameters
    ---------
    H_blocks : list of ndarray
        A list of blocks of the Hessian per irrep, in mass-weighted salcs.
        Each is dimension # cdsalcs-in-irrep by # cdsalcs-in-irrep.
    B_blocks : list of ndarray
        A block of the B matrix per irrep, which transforms CdSalcs to Cartesians.
        Each is dimensions # cdsalcs-in-irrep by # cartesians.
    massweighter : ndarray
        The mass associated with each atomic coordinate.
        Dimension 3 * natom. Due to x, y, z, values appear in groups of three.
    print_lvl : int
        The level of printing information requested by the user.

    Returns
    -------
    Hx : ndarray
        The Hessian in non-mass weighted cartesians.
    """

    # We have the Hessian in each irrep! The final task is to perform coordinate transforms.
    H = block_diagonal_array(*H_blocks)
    B = np.vstack(B_blocks)

    if print_lvl >= 3:
        core.print_out(
            "\n    Force constant matrix for all computed irreps in mass-weighted SALCS.\n"
        )
        core.print_out("\n{}\n".format(np.array_str(H, **array_format)))

    # Transform the massweighted Hessian from the CdSalc basis to Cartesians.
    # The Hessian is the matrix not of a linear transformation, but of a (symmetric) bilinear form
    # As such, the change of basis is formula A' = Xt A X, no inverses!
    # More conceptually, it's A'_kl = A_ij X_ik X_jl; Each index transforms linearly.
    Hx = np.dot(np.dot(B.T, H), B)
    if print_lvl >= 3:
        core.print_out(
            "\n    Force constants in mass-weighted Cartesian coordinates.\n")
        core.print_out("\n{}\n".format(np.array_str(Hx, **array_format)))

    # Un-massweight the Hessian.
    Hx = np.transpose(Hx / massweighter) / massweighter

    if print_lvl >= 3:
        core.print_out("\n    Force constants in Cartesian coordinates.\n")
        core.print_out("\n{}\n".format(np.array_str(Hx, **array_format)))

    if print_lvl:
        core.print_out(
            "\n-------------------------------------------------------------\n"
        )

    return Hx
Ejemplo n.º 2
0
def _process_hessian(H_blocks, B_blocks, massweighter, print_lvl):
    """Perform post-construction processing for the Hessian.
       Statements need to be printed, and the Hessian must be transformed.

    Parameters
    ----------
    H_blocks : list of ndarray
        A list of blocks of the Hessian per irrep, in mass-weighted salcs.
        Each is dimension # cdsalcs-in-irrep by # cdsalcs-in-irrep.
    B_blocks : list of ndarray
        A block of the B matrix per irrep, which transforms CdSalcs to Cartesians.
        Each is dimensions # cdsalcs-in-irrep by # cartesians.
    massweighter : ndarray
        The mass associated with each atomic coordinate.
        Dimension 3 * natom. Due to x, y, z, values appear in groups of three.
    print_lvl : int
        The level of printing information requested by the user.

    Returns
    -------
    Hx : ndarray
        The Hessian in non-mass weighted cartesians.
    """

    # We have the Hessian in each irrep! The final task is to perform coordinate transforms.
    H = p4util.block_diagonal_array(*H_blocks)
    B = np.vstack(B_blocks)

    if print_lvl >= 3:
        core.print_out("\n    Force constant matrix for all computed irreps in mass-weighted SALCS.\n")
        core.print_out("\n{}\n".format(np.array_str(H, **array_format)))

    # Transform the massweighted Hessian from the CdSalc basis to Cartesians.
    # The Hessian is the matrix not of a linear transformation, but of a (symmetric) bilinear form
    # As such, the change of basis is formula A' = Xt A X, no inverses!
    # More conceptually, it's A'_kl = A_ij X_ik X_jl; Each index transforms linearly.
    Hx = np.dot(np.dot(B.T, H), B)
    if print_lvl >= 3:
        core.print_out("\n    Force constants in mass-weighted Cartesian coordinates.\n")
        core.print_out("\n{}\n".format(np.array_str(Hx, **array_format)))

    # Un-massweight the Hessian.
    Hx = np.transpose(Hx / massweighter) / massweighter

    if print_lvl >= 3:
        core.print_out("\n    Force constants in Cartesian coordinates.\n")
        core.print_out("\n{}\n".format(np.array_str(Hx, **array_format)))

    if print_lvl:
        core.print_out("\n-------------------------------------------------------------\n")

    return Hx
Ejemplo n.º 3
0
def _process_hessian(H_blocks: List[np.ndarray], B_blocks: List[np.ndarray],
                     massweighter: np.ndarray, print_lvl: int) -> np.ndarray:
    """Perform post-construction processing for the Hessian.
       Statements need to be printed, and the Hessian must be transformed.

    Parameters
    ----------
    H_blocks
        A list of blocks of the Hessian per irrep, in mass-weighted salcs.
        Each is (nsalc_in_irrep, nsalc_in_irrep)
    B_blocks
        A block of the B matrix per irrep, which transforms CdSalcs to Cartesians.
        Each is (nsalc_in_irrep, 3 * nat)
    massweighter
        The mass associated with each atomic coordinate.
        (3 * nat, ) Due to x, y, z, values appear in groups of three.
    print_lvl
        The level of printing information requested by the user.

    Returns
    -------
    Hx
        The Hessian in non-mass weighted cartesians.
    """

    # Handle empty case (atom)
    if not H_blocks and not B_blocks:
        nat3 = massweighter.size
        return np.zeros((nat3, nat3), dtype=np.float64)

    # We have the Hessian in each irrep! The final task is to perform coordinate transforms.
    H = p4util.block_diagonal_array(*H_blocks)
    B = np.vstack(B_blocks)

    if print_lvl >= 3:
        core.print_out(
            "\n    Force constant matrix for all computed irreps in mass-weighted SALCS.\n"
        )
        core.print_out("\n{}\n".format(nppp10(H)))

    # Transform the massweighted Hessian from the CdSalc basis to Cartesians.
    # The Hessian is the matrix not of a linear transformation, but of a (symmetric) bilinear form
    # As such, the change of basis is formula A' = Xt A X, no inverses!
    # More conceptually, it's A'_kl = A_ij X_ik X_jl; Each index transforms linearly.
    Hx = np.dot(np.dot(B.T, H), B)
    if print_lvl >= 3:
        core.print_out(
            "\n    Force constants in mass-weighted Cartesian coordinates.\n")
        core.print_out("\n{}\n".format(nppp10(Hx)))

    # Un-massweight the Hessian.
    Hx = np.transpose(Hx / massweighter) / massweighter

    if print_lvl >= 3:
        core.print_out("\n    Force constants in Cartesian coordinates.\n")
        core.print_out("\n{}\n".format(nppp10(Hx)))

    if print_lvl:
        core.print_out(
            "\n-------------------------------------------------------------\n"
        )

    return Hx