Ejemplo n.º 1
0
def test_optimization_pass_serialization(water, opti_input, opti_success):
    opti_in = OptimizationInput(initial_molecule=water, **opti_input)
    assert isinstance(opti_in.dict(), dict)
    assert isinstance(opti_in.json(), str)

    opti_out = Optimization(initial_molecule=water, **opti_input, **opti_success)
    assert isinstance(opti_out.dict(), dict)
    assert isinstance(opti_out.json(), str)
Ejemplo n.º 2
0
    def _generate_optimization_input(mol, compute_spec, factory):
        import ast
        from qcelemental.models import OptimizationInput

        # TODO: bug report in openff where `atom_map` is a string
        if isinstance(mol.properties.get('atom_map'), str):
            mol.properties['atom_map'] = ast.literal_eval(
                mol.properties['atom_map'])

        # This block will fail for OFF Toolkit 0.8.4, but succeed for 0.8.4rc1
        try:
            attributes = factory.create_cmiles_metadata(mol)
            qcmol = mol.to_qcschema(extras=attributes)
        # In OFFTK 0.8.4, the CMILES field is automatically populated by this method
        except:
            qcmol = mol.to_qcschema()

        method = compute_spec['method']
        basis = compute_spec['basis']
        program = compute_spec['program']

        # generate optimization inputs
        input_data = OptimizationInput(keywords={
            "coordsys": "dlc",
            "enforce": 0,
            "epsilon": 1e-05,
            "reset": True,
            "qccnv": False,
            "molcnv": False,
            "check": 0,
            "trust": 0.1,
            "tmax": 0.3,
            "maxiter": 300,
            "convergence_set": "gau",
            "program": program
        },
                                       extras={},
                                       protocols={},
                                       input_specification={
                                           "driver": "gradient",
                                           "model": {
                                               "method": method,
                                               "basis": basis,
                                           },
                                           "keywords": {
                                               "maxiter":
                                               200,
                                               "scf_properties": [
                                                   "dipole", "quadrupole",
                                                   "wiberg_lowdin_indices",
                                                   "mayer_indices"
                                               ]
                                           },
                                       },
                                       initial_molecule=qcmol)

        return input_data.dict()
Ejemplo n.º 3
0
def test_nwchem_restart(tmpdir):
    # Make the input file
    input_data = {
        "input_specification": {
            "model": {
                "method": "HF",
                "basis": "sto-3g"
            },
            "keywords": {
                "driver__maxiter": 2,
                "set__driver:linopt": 0
            },
            "extras": {
                "allow_restarts": True
            },
        },
        "initial_molecule": qcng.get_molecule("hydrogen"),
    }
    input_data = OptimizationInput(**input_data)

    # Run an initial step, which should not converge
    local_opts = {"scratch_messy": True, "scratch_directory": str(tmpdir)}
    ret = qcng.compute_procedure(input_data,
                                 "nwchemdriver",
                                 local_options=local_opts,
                                 raise_error=False)
    assert not ret.success

    # Run it again, which should converge
    new_ret = qcng.compute_procedure(input_data,
                                     "nwchemdriver",
                                     local_options=local_opts,
                                     raise_error=True)
    assert new_ret.success
Ejemplo n.º 4
0
def relax_structure(smiles: str,
                    qc_config: QCInputSpecification,
                    compute_config: Optional[Union[TaskConfig, Dict]] = None,
                    compute_connectivity: bool = False,
                    code: str = _code) -> Tuple[str, float]:
    """Compute the atomization energy of a molecule given the SMILES string

    Args:
        smiles (str): SMILES of a molecule
        qc_config (dict): Quantum Chemistry configuration used for evaluating the energy
        compute_config (TaskConfig): Configuration for the quantum chemistry code
        compute_connectivity (bool): Whether we must compute connectivity before calling code
        code (str): Which QC code to use for the evaluation
    Returns:
        (str): Structure of the molecule
        (float): Electronic energy of this molecule
    """
    # Generate 3D coordinates by minimizing MMFF forcefield
    xyz = generate_atomic_coordinates(smiles)
    mol = Molecule.from_data(xyz, dtype='xyz')

    # Generate connectivity, if needed
    if compute_connectivity:
        conn = guess_connectivity(mol.symbols, mol.geometry, default_connectivity=1.0)
        mol = Molecule.from_data({**mol.dict(), 'connectivity': conn})

    # Run the relaxation
    opt_input = OptimizationInput(input_specification=qc_config,
                                  initial_molecule=mol,
                                  keywords={'program': code, 'convergence_set': 'GAU_VERYTIGHT'})
    res: OptimizationResult = \
        compute_procedure(opt_input, 'geometric', local_options=compute_config, raise_error=True)
    return res.final_molecule.to_string('xyz'), res.energies[-1]
Ejemplo n.º 5
0
def test_geometric_retries(failure_engine, input_data):

    failure_engine.iter_modes = ["random_error", "pass", "random_error", "random_error", "pass"]  # Iter 1  # Iter 2
    failure_engine.iter_modes.extend(["pass"] * 20)

    input_data["initial_molecule"] = {
        "symbols": ["He", "He"],
        "geometry": [0, 0, 0, 0, 0, failure_engine.start_distance],
    }
    input_data["input_specification"]["model"] = {"method": "something"}
    input_data["keywords"]["program"] = failure_engine.name

    input_data = OptimizationInput(**input_data)

    ret = qcng.compute_procedure(input_data, "geometric", local_options={"ncores": 13}, raise_error=True)
    assert ret.success is True
    assert ret.trajectory[0].provenance.retries == 1
    assert ret.trajectory[0].provenance.ncores == 13
    assert ret.trajectory[1].provenance.retries == 2
    assert ret.trajectory[1].provenance.ncores == 13
    assert "retries" not in ret.trajectory[2].provenance.dict()

    # Ensure we still fail
    failure_engine.iter_modes = ["random_error", "pass", "random_error", "random_error", "pass"]  # Iter 1  # Iter 2
    ret = qcng.compute_procedure(input_data, "geometric", local_options={"ncores": 13, "retries": 1})
    assert ret.success is False
    assert ret.input_data["trajectory"][0]["provenance"]["retries"] == 1
    assert len(ret.input_data["trajectory"]) == 2
Ejemplo n.º 6
0
def relax_structure(xyz: str,
                    qc_config: QCInputSpecification,
                    charge: int = 0,
                    compute_config: Optional[Union[TaskConfig, Dict]] = None,
                    code: str = _code) -> OptimizationResult:
    """Compute the atomization energy of a molecule given the SMILES string

    Args:
        xyz (str): Structure of a molecule in XYZ format
        qc_config (dict): Quantum Chemistry configuration used for evaluating the energy
        charge (int): Charge of the molecule
        compute_config (TaskConfig): Configuration for the quantum chemistry code, such as parallelization settings
        code (str): Which QC code to use for the evaluation
    Returns:
        (OptimizationResult): Full output from the calculation
    """

    # Parse the molecule
    mol = Molecule.from_data(xyz, dtype='xyz', molecular_charge=charge)

    # Run the relaxation
    if code == "nwchem":
        keywords = {"driver__maxiter": 100, "set__driver:linopt": 0}
        relax_code = "nwchemdriver"
    else:
        keywords = {"program": code}
        relax_code = "geometric"
    opt_input = OptimizationInput(input_specification=qc_config,
                                  initial_molecule=mol,
                                  keywords=keywords)
    return compute_procedure(opt_input,
                             relax_code,
                             local_options=compute_config,
                             raise_error=True)
Ejemplo n.º 7
0
def test_geometric_psi4(input_data):

    input_data["initial_molecule"] = qcng.get_molecule("hydrogen")
    input_data["input_specification"]["model"] = {
        "method": "HF",
        "basis": "sto-3g"
    }
    input_data["input_specification"]["keywords"] = {
        "scf_properties": ["wiberg_lowdin_indices"]
    }
    input_data["keywords"]["program"] = "psi4"

    input_data = OptimizationInput(**input_data)

    ret = qcng.compute_procedure(input_data, "geometric", raise_error=True)
    assert 10 > len(ret.trajectory) > 1

    assert pytest.approx(ret.final_molecule.measure([0, 1]),
                         1.0e-4) == 1.3459150737
    assert ret.provenance.creator.lower() == "geometric"
    assert ret.trajectory[0].provenance.creator.lower() == "psi4"

    # Check keywords passing
    for single in ret.trajectory:
        assert "scf_properties" in single.keywords
        assert "WIBERG_LOWDIN_INDICES" in single.extras["qcvars"]
Ejemplo n.º 8
0
def test_geometric_stdout(input_data):

    input_data["initial_molecule"] = qcng.get_molecule("water")
    input_data["input_specification"]["model"] = {"method": "UFF", "basis": ""}
    input_data["keywords"]["program"] = "rdkit"

    input_data = OptimizationInput(**input_data)

    ret = qcng.compute_procedure(input_data, "geometric", raise_error=True)
    assert ret.success is True
    assert "Converged!" in ret.stdout
Ejemplo n.º 9
0
def test_geometric_rdkit_error(input_data):

    input_data["initial_molecule"] = qcng.get_molecule("water").copy(exclude={"connectivity_"})
    input_data["input_specification"]["model"] = {"method": "UFF", "basis": ""}
    input_data["keywords"]["program"] = "rdkit"

    input_data = OptimizationInput(**input_data)

    ret = qcng.compute_procedure(input_data, "geometric")
    assert ret.success is False
    assert isinstance(ret.error.error_message, str)
Ejemplo n.º 10
0
    def _args_from_optimizationrecord(opt, client):
        from qcelemental.models import OptimizationInput

        # generate optimization inputs
        input_data = OptimizationInput(
            keywords=opt.keywords,
            extras={},
            protocols={},
            input_specification={
                "driver": "gradient",
                "model": {
                    "method": opt.qc_spec.method,
                    "basis": opt.qc_spec.basis,
                },
                "keywords":
                client.query_keywords(opt.qc_spec.keywords)[0].values
            },
            initial_molecule=opt.get_initial_molecule())

        return input_data.dict()
Ejemplo n.º 11
0
def test_run_procedure(tmp_path):
    """Tests qcengine run-procedure with geometric, psi4, and JSON input"""
    def check_result(stdout):
        output = json.loads(stdout)
        assert output["provenance"]["creator"].lower() == "geometric"
        assert output["success"] is True

    inp = {"schema_name": "qcschema_optimization_input",
           "schema_version": 1,
           "keywords": {
               "coordsys": "tric",
               "maxiter": 100,
               "program": "psi4"
           },
           "input_specification": {
               "schema_name": "qcschema_input",
               "schema_version": 1,
               "driver": "gradient",
               "model": {"method": "HF", "basis": "sto-3g"},
               "keywords": {},
           },
           "initial_molecule": get_molecule("hydrogen")}
    inp = OptimizationInput(**inp)

    args = ["run-procedure", "geometric", inp.json()]
    check_result(run_qcengine_cli(args))

    args = ["run-procedure", "geometric", os.path.join(tmp_path, "input.json")]
    with util.disk_files({"input.json": inp.json()}, {}, cwd=tmp_path):
        check_result(run_qcengine_cli(args))

    args = ["run-procedure", "geometric", inp.json()]
    check_result(run_qcengine_cli(args, stdin=inp.json()))
Ejemplo n.º 12
0
def test_berny_stdout(input_data):

    input_data["initial_molecule"] = qcng.get_molecule("water")
    input_data["input_specification"]["model"] = {
        "method": "HF",
        "basis": "sto-3g"
    }
    input_data["keywords"]["program"] = "psi4"

    input_data = OptimizationInput(**input_data)

    ret = qcng.compute_procedure(input_data, "berny", raise_error=True)
    assert ret.success is True
    assert "All criteria matched" in ret.stdout
Ejemplo n.º 13
0
def test_geometric_psi4():
    inp = copy.deepcopy(_base_json)

    inp["initial_molecule"] = dc.get_molecule("hydrogen")
    inp["input_specification"]["model"] = {"method": "HF", "basis": "sto-3g"}
    inp["keywords"]["program"] = "psi4"

    inp = OptimizationInput(**inp)

    ret = dc.compute_procedure(inp, "geometric", raise_error=True)
    assert 10 > len(ret["trajectory"]) > 1

    geom = ret["final_molecule"]["geometry"]
    assert pytest.approx(_bond_dist(geom, 0, 1), 1.e-4) == 1.3459150737
Ejemplo n.º 14
0
def test_geometric_local_options(input_data):

    input_data["initial_molecule"] = qcng.get_molecule("hydrogen")
    input_data["input_specification"]["model"] = {"method": "HF", "basis": "sto-3g"}
    input_data["keywords"]["program"] = "psi4"

    input_data = OptimizationInput(**input_data)

    # Set some extremely large number to test
    ret = qcng.compute_procedure(input_data, "geometric", raise_error=True, local_options={"memory": "5000"})
    assert pytest.approx(ret.trajectory[0].provenance.memory, 1) == 4900

    # Make sure we cleaned up
    assert "_qcengine_local_config" not in ret.input_specification
    assert "_qcengine_local_config" not in ret.trajectory[0].extras
Ejemplo n.º 15
0
def test_optimization_protocols(input_data):

    input_data["initial_molecule"] = qcng.get_molecule("water")
    input_data["input_specification"]["model"] = {"method": "UFF"}
    input_data["keywords"]["program"] = "rdkit"
    input_data["protocols"] = {"trajectory": "initial_and_final"}

    input_data = OptimizationInput(**input_data)

    ret = qcng.compute_procedure(input_data, "geometric", raise_error=True)
    assert ret.success, ret.error.error_message

    assert len(ret.trajectory) == 2
    assert ret.initial_molecule.get_hash() == ret.trajectory[0].molecule.get_hash()
    assert ret.final_molecule.get_hash() == ret.trajectory[1].molecule.get_hash()
Ejemplo n.º 16
0
def test_geometric_psi4():
    inp = copy.deepcopy(_base_json)

    inp["initial_molecule"] = qcng.get_molecule("hydrogen")
    inp["input_specification"]["model"] = {"method": "HF", "basis": "sto-3g"}
    inp["keywords"]["program"] = "psi4"

    inp = OptimizationInput(**inp)

    ret = qcng.compute_procedure(inp, "geometric", raise_error=True)
    assert 10 > len(ret.trajectory) > 1

    assert pytest.approx(ret.final_molecule.measure([0, 1]), 1.e-4) == 1.3459150737
    assert ret.provenance.creator.lower() == "geometric"
    assert ret.trajectory[0].provenance.creator.lower() == "psi4"
Ejemplo n.º 17
0
def test_geometric_stdout():
    inp = copy.deepcopy(_base_json)

    inp["initial_molecule"] = dc.get_molecule("water")
    inp["input_specification"]["model"] = {"method": "UFF", "basis": ""}
    inp["keywords"]["program"] = "rdkit"

    inp = OptimizationInput(**inp)

    ret = dc.compute_procedure(inp, "geometric", raise_error=True)
    assert ret["success"] is True
    assert "Converged!" in ret["stdout"]
    assert ret["stderr"] == "No stderr recieved."

    with pytest.raises(ValueError):
        _ = dc.compute_procedure(inp, "rdkit", raise_error=True)
Ejemplo n.º 18
0
def test_geometric_rdkit_error():
    inp = copy.deepcopy(_base_json)

    inp["initial_molecule"] = dc.get_molecule("water").copy(
        exclude="connectivity")
    inp["input_specification"]["model"] = {"method": "UFF", "basis": ""}
    inp["keywords"]["program"] = "rdkit"

    inp = OptimizationInput(**inp)

    ret = dc.compute_procedure(inp, "geometric")
    assert ret["success"] is False
    assert isinstance(ret["error"]["error_message"], str)

    with pytest.raises(ValueError):
        _ = dc.compute_procedure(inp, "rdkit", raise_error=True)
Ejemplo n.º 19
0
def test_input_through_json(inp, expected):
    with open(os.path.join(os.path.dirname(__file__), inp)) as input_data:
        input_copy = json.load(input_data)
        opt_schema = OptimizationInput(**input_copy)
    
    #optking.run_json_file(os.path.join(os.path.dirname(__file__), inp))
    json_dict = optking.optimize_qcengine(input_copy)

    #For testing purposes. If this works, we have properly returned the output, and added the result
    #to the original file. In order to preserve the form of the test suite, we now resore the input
    #to its original state
    #with open(os.path.join(os.path.dirname(__file__), inp)) as input_data:
    #    json_dict = json.load(input_data)
    assert psi4.compare_values(expected[0], json_dict['trajectory'][-1]['properties']['nuclear_repulsion_energy'], 2,
         "Nuclear repulsion energy")
    assert psi4.compare_values(expected[1], json_dict['trajectory'][-1]['properties']['return_energy'], 6,
        "Reference energy")
Ejemplo n.º 20
0
def test_repr_optimization():

    opt = OptimizationInput(
        **{
            "input_specification": {
                "driver": "gradient",
                "model": {
                    "method": "UFF"
                }
            },
            "initial_molecule": {
                "symbols": ["He"],
                "geometry": [0, 0, 0]
            },
        })

    assert "molecule_hash" in str(opt)
    assert "molecule_hash" in repr(opt)
Ejemplo n.º 21
0
def test_berny_failed_gradient_computation(input_data):

    input_data["initial_molecule"] = qcng.get_molecule("water")
    input_data["input_specification"]["model"] = {
        "method": "HF",
        "basis": "sto-3g"
    }
    input_data["input_specification"]["keywords"] = {
        "badpsi4key": "badpsi4value"
    }
    input_data["keywords"]["program"] = "psi4"

    input_data = OptimizationInput(**input_data)

    ret = qcng.compute_procedure(input_data, "berny", raise_error=False)
    assert isinstance(ret, FailedOperation)
    assert ret.success is False
    assert ret.error.error_type == qcng.exceptions.InputError.error_type
Ejemplo n.º 22
0
def test_geometric_local_options():
    inp = copy.deepcopy(_base_json)

    inp["initial_molecule"] = dc.get_molecule("hydrogen")
    inp["input_specification"]["model"] = {"method": "HF", "basis": "sto-3g"}
    inp["keywords"]["program"] = "psi4"

    inp = OptimizationInput(**inp)

    # Set some extremely large number to test
    ret = dc.compute_procedure(inp,
                               "geometric",
                               raise_error=True,
                               local_options={"memory": "5000"})
    assert pytest.approx(ret["trajectory"][0]["provenance"]["memory"],
                         1) == 4900

    # Make sure we cleaned up
    assert "_qcengine_local_config" not in ret["input_specification"]
    assert "_qcengine_local_config" not in ret["trajectory"][0]
Ejemplo n.º 23
0
def test_nwchem_relax(linopt):
    # Make the input file
    input_data = {
        "input_specification": {
            "model": {
                "method": "HF",
                "basis": "sto-3g"
            },
            "keywords": {
                "set__driver:linopt": linopt
            },
        },
        "initial_molecule": qcng.get_molecule("hydrogen"),
    }
    input_data = OptimizationInput(**input_data)

    # Run the relaxation
    ret = qcng.compute_procedure(input_data, "nwchemdriver", raise_error=True)
    assert 10 > len(ret.trajectory) > 1

    assert pytest.approx(ret.final_molecule.measure([0, 1]),
                         1.0e-4) == 1.3459150737
Ejemplo n.º 24
0
def optimize_psi4(calc_name, program='psi4', dertype=None):
    """
    Wrapper for optimize.optimize() Looks for an active psi4 molecule and optimizes.
    This is the written warning that Optking will try to use psi4 if no program is provided
    Parameters
    ----------
    calc_name: str
        level of theory for optimization. eg MP2
    program: str
        program used for gradients, hessians...

    Returns
    -------
    opt_output: dict
        dictionary serialized MOLSSI OptimizationResult.
        see https://github.com/MolSSI/QCElemental/blob/master/qcelemental/models/procedures.py
    """

    import psi4

    logger = logging.getLogger(__name__)
    mol = psi4.core.get_active_molecule()
    oMolsys = molsys.Molsys.from_psi4_molecule(mol)

    # Get optking options and globals from psi4
    # Look through optking module specific options first. If a global has already appeared
    # in optking's options, don't include as a qc package option

    logger.debug("Getting module and psi4 options for qcschema construction")
    module_options = psi4.driver.p4util.prepare_options_for_modules()
    all_options = psi4.core.get_global_option_list()
    opt_keys = {'program': program}
    qc_keys = {}
    if dertype is not None:
        qc_keys['dertype'] = 0

    optking_options = module_options['OPTKING']
    for opt, optval in optking_options.items():
        if optval['has_changed']:
            opt_keys[opt.lower()] = optval['value']

    for option in all_options:
        if psi4.core.has_global_option_changed(option):
            if option in opt_keys:
                pass
            else:
                qc_keys[option.lower()] = psi4.core.get_global_option(option)

    # Make a qcSchema OptimizationInput
    opt_input = {
        "keywords": opt_keys,
        "initial_molecule": oMolsys.molsys_to_qc_molecule(),
        "input_specification": {
            "model": {
                'basis': qc_keys.pop('basis'),
                'method': calc_name
            },
            "driver": "gradient",
            "keywords": qc_keys
        }
    }

    logger.debug("Creating OptimizationInput")
    opt_input = OptimizationInput(**opt_input)

    # Remove numpy elements to allow at will json serialization
    opt_input = json.loads(json_dumps(opt_input))
    opt_output = copy.deepcopy(opt_input)

    try:
        initialize_options(opt_keys)
        computer = make_computer(opt_input)
        opt_output = optimize(oMolsys, computer)
    except (OptError, KeyError, ValueError, AttributeError) as error:
        opt_output = {
            "success": False,
            "error": {
                "error_type": error.err_type,
                "error_message": error.mesg
            }
        }
        logger.critical(f"Error placed in qcschema: {opt_output}")
    except Exception as error:
        logger.critical(
            "An unknown error has occured and evaded all error checking")

        opt_output = {
            "success": False,
            "error": {
                "error_type": error,
                "error_message": str(error)
            }
        }
        logger.critical(f"Error placed in qcschema: {opt_output}")
    finally:
        opt_input.update({"provenance": optking._optking_provenance_stamp})
        opt_input["provenance"]["routine"] = "optimize_psi4"
        opt_input.update(opt_output)
        return opt_input
Ejemplo n.º 25
0
def initialize_from_psi4(calc_name,
                         program,
                         computer_type,
                         dertype=None,
                         **xtra_opt_params):
    """Gathers information from an active psi4 instance. to cleanly run optking from a
    psithon or psi4api input file

    Parameters
    ----------
    calc_name: str
    computer_type: str
    dertype: Union[int, None]
    program: str
    **xtra_opt_params
        extra keywords which are not recognized by psi4

    Returns
    -------
    params: op.OptParams
    o_molsys: molsys.Molsys
    computer: ComputeWrapper
    opt_input: qcelemental.models.OptimizationInput

    """
    import psi4

    logger = logging.getLogger(__name__)
    mol = psi4.core.get_active_molecule()
    o_molsys, qc_mol = molsys.Molsys.from_psi4(mol)

    # Get optking options and globals from psi4
    # Look through optking module specific options first. If a global has already appeared
    # in optking's options, don't include as a qc package option
    logger.debug("Getting module and psi4 options for qcschema construction")
    module_options = psi4.driver.p4util.prepare_options_for_modules()
    all_options = psi4.core.get_global_option_list()
    opt_keys = {"program": program}

    qc_keys = {}
    if dertype is not None:
        qc_keys["dertype"] = 0

    optking_options = module_options["OPTKING"]
    for opt, optval in optking_options.items():
        if optval["has_changed"]:
            opt_keys[opt.lower()] = optval["value"]

    if xtra_opt_params:
        for xtra_key, xtra_value in xtra_opt_params.items():
            opt_keys[xtra_key.lower()] = xtra_value

    for option in all_options:
        if psi4.core.has_global_option_changed(option):
            if option not in opt_keys:
                qc_keys[option.lower()] = psi4.core.get_global_option(option)

    # Make a qcSchema OptimizationInput
    opt_input = {
        "keywords": opt_keys,
        "initial_molecule": qc_mol,
        "input_specification": {
            "model": {
                "basis": qc_keys.pop("basis"),
                "method": calc_name
            },
            "driver": "gradient",
            "keywords": qc_keys,
        },
    }
    logger.debug("Creating OptimizationInput")

    opt_input = OptimizationInput(**opt_input)
    # Remove numpy elements to allow at will json serialization
    opt_input = json.loads(json_dumps(opt_input))

    initialize_options(opt_keys)
    params = op.Params
    computer = make_computer(opt_input, computer_type)
    return params, o_molsys, computer, opt_input