Exemple #1
0
def harvest(in_mol: Molecule, nwout: str, **kwargs) -> Tuple[PreservingDict, None, list, Molecule, str, str]:
    """Parses all the pieces of output from NWChem: the stdout in
    *nwout* Scratch files are not yet considered at this moment.

    Args:
        in_mol (Molecule): Input molecule
        nwout (str): NWChem output molecule
    Returns:
        - (PreservingDict) Variables extracted from the output file in the last complete step
        - (None): Hessian from the last complete step (Not yet implemented)
        - (list): Gradient from the last complete step
        - (Molecule): Molecule from the last complete step
        - (str): Version string
        - (str): Error message, if any
    """

    # Parse the NWChem output
    outPsivar, outMol, outGrad, version, error = harvest_output(nwout)

    # Make sure the input and output molecules are the same
    if outMol:
        if in_mol:
            if abs(outMol.nuclear_repulsion_energy() - in_mol.nuclear_repulsion_energy()) > 1.0e-3:
                raise ValueError(
                    """NWChem outfile (NRE: %f) inconsistent with Psi4 input (NRE: %f)."""
                    % (outMol.nuclear_repulsion_energy(), in_mol.nuclear_repulsion_energy())
                )
    else:
        raise ValueError("""No coordinate information extracted from NWChem output.""")

    return outPsivar, None, outGrad, outMol, version, error
Exemple #2
0
def harvest(in_mol: Molecule, nwout: str, **outfiles) -> Tuple[PreservingDict, None, list, Molecule, str, str]:
    """Parses all the pieces of output from NWChem: the stdout in
    *nwout* Scratch files are not yet considered at this moment.

    Args:
        in_mol (Molecule): Input molecule
        nwout (str): NWChem output molecule
        outfiles (dict): Dictionary of outfile files and their contents
    Returns:
        - (PreservingDict) Variables extracted from the output file in the last complete step
        - (None): Hessian from the last complete step (Not yet implemented)
        - (list): Gradient from the last complete step
        - (Molecule): Molecule from the last complete step
        - (str): Version string
        - (str): Error message, if any
    """

    # Parse the NWChem output
    out_psivar, out_mol, out_grad, version, error = harvest_output(nwout)

    # If available, read higher-accuracy gradients
    #  These were output using a Python Task in NWChem to read them out of the database
    if outfiles.get("nwchem.grad") is not None:
        logger.debug("Reading higher-accuracy gradients")
        out_grad = json.loads(outfiles.get("nwchem.grad"))

    # If available, read the hessian
    out_hess = None
    if outfiles.get("nwchem.hess") is not None:
        out_hess = harvest_hessian(outfiles.get("nwchem.hess"))

    # Make sure the input and output molecules are the same
    if out_mol:
        if in_mol:
            if abs(out_mol.nuclear_repulsion_energy() - in_mol.nuclear_repulsion_energy()) > 1.0e-3:
                raise ValueError(
                    """NWChem outfile (NRE: %f) inconsistent with Psi4 input (NRE: %f)."""
                    % (out_mol.nuclear_repulsion_energy(), in_mol.nuclear_repulsion_energy())
                )
    else:
        raise ValueError("""No coordinate information extracted from NWChem output.""")

    # If present, align the gradients and hessian with the original molecular coordinates
    #  NWChem rotates the coordinates of the input molecule. `out_mol` contains the coordinates for the
    #  rotated molecule, which we can use to determine how to rotate the gradients/hessian
    amol, data = out_mol.align(in_mol, atoms_map=False, mols_align=True, verbose=0)

    mill = data["mill"]  # Retrieve tool with alignment routines

    if out_grad is not None:
        out_grad = mill.align_gradient(np.array(out_grad).reshape(-1, 3))
    if out_hess is not None:
        out_hess = mill.align_hessian(np.array(out_hess))

    return out_psivar, out_hess, out_grad, out_mol, version, error
Exemple #3
0
def harvest(
    in_mol: Molecule, method: str, gamessout: str, **outfiles
) -> Tuple[PreservingDict, Optional[np.ndarray], Optional[np.ndarray], Molecule]:
    """Parses all the pieces of output from gamess: the stdout in
    *gamessout* Scratch files are not yet considered at this moment.
    """
    qcvars, calc_mol, calc_grad, module = harvest_output(gamessout)

    datasections = {}
    if outfiles.get("gamess.dat"):
        datasections = harvest_datfile(outfiles["gamess.dat"])

    calc_hess = None
    if "$HESS" in datasections:
        calc_hess = load_hessian(datasections["$HESS"], dtype="gamess")
        if np.count_nonzero(calc_hess) == 0:
            calc_hess = None

    # Sometimes the hierarchical setting of CURRENT breaks down
    if method == "ccsd+t(ccsd)":
        qcvars["CURRENT CORRELATION ENERGY"] = qcvars["CCSD+T(CCSD) CORRELATION ENERGY"]
        qcvars["CURRENT ENERGY"] = qcvars["CCSD+T(CCSD) TOTAL ENERGY"]

    if calc_mol:
        qcvars["NUCLEAR REPULSION ENERGY"] = str(round(calc_mol.nuclear_repulsion_energy(), 8))
        if in_mol:
            if abs(calc_mol.nuclear_repulsion_energy() - in_mol.nuclear_repulsion_energy()) > 1.0e-3:
                raise ValueError(
                    f"""GAMESS outfile (NRE: {calc_mol.nuclear_repulsion_energy()}) inconsistent with AtomicInput.molecule (NRE: {in_mol.nuclear_repulsion_energy()})."""
                )

        # Frame considerations
        # * `in_mol` built with deliberation and with all fields accessible.
        # * `calc_mol` has the internally consistent geometry frame but otherwise dinky (geom & symbols & maybe chgmult).
        if in_mol.fix_com and in_mol.fix_orientation:
            # Impose input frame if important as signalled by fix_*=T
            return_mol = in_mol
            _, data = calc_mol.align(in_mol, atoms_map=False, mols_align=True, run_mirror=True, verbose=0)
            mill = data["mill"]

        else:
            return_mol, _ = in_mol.align(calc_mol, atoms_map=False, mols_align=True, run_mirror=True, verbose=0)
            mill = qcel.molutil.compute_scramble(
                len(in_mol.symbols), do_resort=False, do_shift=False, do_rotate=False, do_mirror=False
            )  # identity AlignmentMill

        return_grad = None
        if calc_grad is not None:
            return_grad = mill.align_gradient(calc_grad)

        return_hess = None
        if calc_hess is not None:
            return_hess = mill.align_hessian(np.array(calc_hess))

    else:
        raise ValueError("""No coordinate information extracted from gamess output.""")

    return qcvars, return_hess, return_grad, return_mol, module
Exemple #4
0
    def _compute(self, driver):
        logger = logging.getLogger(__name__)
        logger.info("UserComputer only returning provided values")
        E = self.external_energy
        gX = self.external_gradient
        HX = self.external_hessian

        if driver == "hessian":
            if HX is None or gX is None or E is None:
                raise OptError("Must provide hessian, gradient, and energy.")
        elif driver == "gradient":
            if gX is None or E is None:
                raise OptError("Must provide gradient and energy.")
        elif driver == "energy":
            if E is None:
                raise OptError("Must provide energy.")

        result = deepcopy(UserComputer.output_skeleton)
        result["driver"] = driver
        mol = Molecule(**self.molecule)
        result["molecule"] = mol
        NRE = mol.nuclear_repulsion_energy()
        result["properties"]["nuclear_repulsion_energy"] = NRE
        result["extras"]["qcvars"]["NUCLEAR REPULSION ENERGY"] = NRE

        result["properties"]["return_energy"] = E
        result["extras"]["qcvars"]["CURRENT ENERGY"] = E

        if driver in ["gradient", "hessian"]:
            result["extras"]["qcvars"]["CURRENT GRADIENT"] = gX

        if driver == "hessian":
            result["extras"]["qcvars"]["CURRENT HESSIAN"] = HX

        if driver == "energy":
            result["return_result"] = E
        elif driver == "gradient":
            result["return_result"] = gX
        elif driver == "hessian":
            result["return_result"] = HX

        # maybe do this to protect against repeatedly going back for same?
        self.external_energy = None
        self.external_gradient = None
        self.external_hessian = None
        return AtomicResult(**result)
Exemple #5
0
def harvest(
    in_mol: Molecule, method: str, gamessout: str, **outfiles
) -> Tuple[PreservingDict, Optional[np.ndarray], Optional[np.ndarray],
           Molecule]:
    """Parses all the pieces of output from gamess: the stdout in
    *gamessout* Scratch files are not yet considered at this moment.
    """
    qcvars, calc_mol, calc_grad, module = harvest_output(gamessout)

    # Sometimes the hierarchical setting of CURRENT breaks down
    if method == "ccsd+t(ccsd)":
        qcvars["CURRENT CORRELATION ENERGY"] = qcvars[
            "CCSD+T(CCSD) CORRELATION ENERGY"]
        qcvars["CURRENT ENERGY"] = qcvars["CCSD+T(CCSD) TOTAL ENERGY"]

    if calc_mol:
        qcvars["NUCLEAR REPULSION ENERGY"] = str(
            round(calc_mol.nuclear_repulsion_energy(), 8))
        if in_mol:
            if abs(calc_mol.nuclear_repulsion_energy() -
                   in_mol.nuclear_repulsion_energy()) > 1.0e-3:
                raise ValueError(
                    f"""GAMESS outfile (NRE: {calc_mol.nuclear_repulsion_energy()}) inconsistent with AtomicInput.molecule (NRE: {in_mol.nuclear_repulsion_energy()})."""
                )

        return_mol = calc_mol
        amol, data = calc_mol.align(in_mol,
                                    atoms_map=False,
                                    mols_align=True,
                                    verbose=0)
        mill = data["mill"]

        return_grad = None
        if calc_grad is not None:
            return_grad = mill.align_gradient(calc_grad)

        return_hess = None
    else:
        raise ValueError(
            """No coordinate information extracted from gamess output.""")

    return qcvars, return_hess, return_grad, return_mol, module
def test_get_fragment(group_fragments, orient):
    mol = Molecule(
        **{
            "fragments": [[0], [1, 2, 3], [4, 5, 6]],
            "symbols": ["he", "o", "h", "h", "o", "h", "h"],
            # same geom as test_water_orient but with He at origin
            "geometry":
            np.array([
                [0.0, 0.0, 0.0],
                [-1.551007, -0.114520, 0.000000],
                [-1.934259, 0.762503, 0.000000],
                [-0.599677, 0.040712, 0.000000],
                [-0.114520, -1.551007, 10.000000],
                [0.762503, -1.934259, 10.000000],
                [0.040712, -0.599677, 10.000000],
            ]) / qcel.constants.bohr2angstroms,
        })

    assert mol.nelectrons() == 22
    assert compare_values(32.25894779318589,
                          mol.nuclear_repulsion_energy(),
                          atol=1.0e-5)
    assert mol.symbols[0] == "He"

    monomers_nelectrons = [2, 10, 10]
    monomers_nre = [0.0, 9.163830150548483, 9.163830150548483]
    monomers = [
        mol.get_fragment(ifr, group_fragments=group_fragments, orient=orient)
        for ifr in range(3)
    ]
    for fr in range(3):
        assert monomers[fr].nelectrons() == monomers_nelectrons[fr]
        assert compare_values(monomers[fr].nuclear_repulsion_energy(),
                              monomers_nre[fr],
                              "monomer nre",
                              atol=1.0e-5)

    idimers = [(0, 1), (0, 2), (1, 2), (1, 0), (2, 0), (2, 1)]
    dimers_nelectrons = [12, 12, 20, 12, 12, 20]
    dimers_nre = [
        16.8777971, 10.2097206, 23.4990904, 16.8777971, 10.2097206, 23.4990904
    ]
    dimers = [
        mol.get_fragment(rl, group_fragments=group_fragments, orient=orient)
        for rl in idimers
    ]
    for ifr in range(len(idimers)):
        # print('dd', ifr, idimers[ifr], dimers[ifr].nuclear_repulsion_energy(), dimers[ifr].get_hash())
        assert dimers[ifr].nelectrons(
        ) == dimers_nelectrons[ifr], "dimer nelec"
        assert compare_values(dimers[ifr].nuclear_repulsion_energy(),
                              dimers_nre[ifr],
                              "dimer nre",
                              atol=1.0e-5)
    if group_fragments and orient:
        assert dimers[0].get_hash() != dimers[3].get_hash(
        )  # atoms out of order
        assert dimers[1].get_hash() != dimers[4].get_hash(
        )  # atoms out of order
        assert dimers[2].get_hash() == dimers[5].get_hash()
    elif not group_fragments and not orient:
        assert dimers[0].get_hash() == dimers[3].get_hash()
        assert dimers[1].get_hash() == dimers[4].get_hash()
        assert dimers[2].get_hash() == dimers[5].get_hash()
    else:
        assert 0  # lgtm: [py/unreachable-statement]

    ghdimers_nelectrons = [2, 2, 10, 10, 10, 10]
    ghdimers_nre = [
        0.0, 0.0, 9.163830150548483, 9.163830150548483, 9.163830150548483,
        9.163830150548483
    ]
    ghdimers = [
        mol.get_fragment(rl,
                         gh,
                         group_fragments=group_fragments,
                         orient=orient) for rl, gh in idimers
    ]
    for ifr in range(len(idimers)):
        # print('gh', ifr, idimers[ifr], ghdimers[ifr].nuclear_repulsion_energy(), ghdimers[ifr].get_hash())
        assert ghdimers[ifr].nelectrons(
        ) == ghdimers_nelectrons[ifr], "gh dimer nelec"
        assert compare_values(ghdimers[ifr].nuclear_repulsion_energy(),
                              ghdimers_nre[ifr],
                              "gh dimer nre",
                              atol=1.0e-5)

    if group_fragments and orient:
        assert ghdimers[0].get_hash() != ghdimers[3].get_hash(
        )  # diff atoms ghosted
        assert ghdimers[1].get_hash() != ghdimers[4].get_hash(
        )  # diff atoms ghosted
        assert ghdimers[2].get_hash() == ghdimers[5].get_hash()
    elif not group_fragments and not orient:
        assert ghdimers[0].get_hash() != ghdimers[3].get_hash(
        )  # diff atoms ghosted
        assert ghdimers[1].get_hash() != ghdimers[4].get_hash(
        )  # diff atoms ghosted
        assert ghdimers[2].get_hash() != ghdimers[5].get_hash(
        )  # real pattern different
        assert not np.allclose(ghdimers[2].real, ghdimers[5].real)
    else:
        assert 0  # lgtm: [py/unreachable-statement]
Exemple #7
0
def harvest(in_mol: Molecule, outfiles) -> Tuple[PreservingDict, None, None, Molecule, str, str]:
    """Parses all the pieces of output from Madness: the stdout in
    *nwout* Scratch files are not yet considered at this moment.

    Args:
        in_mol (Molecule): Input molecule
        madout (str): Madness output molecule
        outfiles (dict): Dictionary of outfile files and their contents
    Returns:
        - (PreservingDict) Variables extracted from the output file in the last complete step
        - (None): Hessian from the last complete step (Not yet implemented)
        - (None): Gradient from the last complete step (Not yet implemented)
        - (Molecule): Molecule from the last complete step
        - (str): Version string
        - (str): Error message, if any
    """
    out_psivar = PreservingDict()
    # Parse the Madness output
    # This is a weird unpacking but i'm sure i'll find a more elegant way to do this later
    moldft_info = outfiles.get("moldft")
    moldft_outfiles = moldft_info.get("outfiles")
    # At this point scf prints a list of json outputs where each list refers to the scf at givin protocol
    # Here I load the scf_info and calc_info as json
    scf_info = json.loads(moldft_outfiles.get("scf_info.json"))
    calc_info = json.loads(moldft_outfiles.get("calc_info.json"))
    # Write harvest scf_info and harvest calc_info
    out_calc_vars = harvest_calc_info(calc_info)
    out_scf_vars = harvest_scf_info(scf_info)
    out_psivar.update(out_calc_vars)
    out_psivar.update(out_scf_vars)

    if "molresponse" in outfiles.keys():
        molresponse_info = outfiles.get("moldft")
        molresponse_outfiles = molresponse_info.get("outfiles")
        # At this point scf prints a list of json outputs where each list refers to the scf at given protocol
        # Here I load the scf_info and calc_info as json
        response_info = json.loads(molresponse_outfiles.get("respones.json"))
        response_params, response_data_dict = read_molrespone_json(response_info)

    Idontneed_vars, out_mol, out_grad, version, error = harvest_moldft_output(outfiles["moldft"]["stdout"])
    if "molresponse" in outfiles.keys():
        response_psi_var = harvest_response_file(outfiles["molresponse"]["stdout"])
        out_psivar.update(response_psi_var)
    # If available, read higher-accuracy gradients
    #  These were output using a Python Task in Madness to read them out of the database
    if outfiles.get("mad.grad") is not None:
        logger.debug("Reading higher-accuracy gradients")
        out_grad = json.loads(outfiles.get("mad.grad"))
    # If available, read the hessian
    # TODO read in the geometry outputs from a geometry optimization
    # out_mol = None
    out_hess = None
    if outfiles.get("mad.hess") is not None:
        out_hess = harvest_hessian(outfiles.get("mad.hess"))

    # Make sure the input and output molecules are the same
    if out_mol:
        if in_mol:
            if abs(out_mol.nuclear_repulsion_energy() - in_mol.nuclear_repulsion_energy()) > 1.0e-3:
                raise ValueError(
                    """Madness outfile (NRE: %f) inconsistent with MADNESS input (NRE: %f)."""
                    % (out_mol.nuclear_repulsion_energy(), in_mol.nuclear_repulsion_energy())
                )
    # else:
    #    raise ValueError("""No coordinate information extracted from Madness output.""")

    # If present, align the gradients and hessian with the original molecular coordinates
    #  Madness rotates the coordinates of the input molecule. `out_mol` contains the coordinates for the
    #  rotated molecule, which we can use to determine how to rotate the gradients/hessian
    # amol, data = out_mol.align(in_mol, atoms_map=False, mols_align=True, verbose=0)

    # mill = data["mill"]  # Retrieve tool with alignment routines

    # if out_grad is not None:
    #    out_grad = mill.align_gradient(np.array(out_grad).reshape(-1, 3))
    # if out_hess is not None:
    #    out_hess = mill.align_hessian(np.array(out_hess))
    # TODO create a madness json that outputs basic info like the version and github hash?

    return out_psivar, out_hess, out_grad, out_mol, version, error