def runner_asserter(inp, subject, method, basis, tnm): qc_module_in = "-".join(["psi4", inp["keywords"].get("qc_module", "") ]).strip("-") # returns "psi4"|"psi4-<module>" driver = inp["driver"] reference = inp["keywords"]["reference"] fcae = {"true": "fc", "false": "ae"}[inp["keywords"]["freeze_core"]] if qc_module_in == "psi4-detci" and basis != "cc-pvdz": pytest.skip(f"basis {basis} too big for {qc_module_in}") # <<< Reference Values >>> # ? precedence on next two scf_type = inp.get("corl_type", inp["keywords"].get( "scf_type", "df")) # hard-code of read_options.cc SCF_TYPE mp2_type = inp.get("corl_type", inp["keywords"].get( "mp2_type", "df")) # hard-code of read_options.cc MP2_TYPE if method in ["mp2.5", "mp3"]: mp_type = inp.get("corl_type", inp["keywords"].get( "mp_type", "df")) # hard-code of proc.py run_dfocc MP_TYPE else: mp_type = inp.get("corl_type", inp["keywords"].get( "mp_type", "conv")) # hard-code of read_options.cc MP_TYPE cc_type = inp.get("corl_type", inp["keywords"].get( "cc_type", "conv")) # hard-code of read_options.cc CC_TYPE corl_natural_values = { "hf": "df", # dummy to assure df/cd/conv scf_type refs available "mp2": mp2_type, "mp2.5": mp_type, "mp3": mp_type, "lccd": cc_type, "lccsd": cc_type, "ccsd": cc_type, "ccsd(t)": cc_type, "olccd": cc_type, } corl_type = corl_natural_values[method] natural_ref = {"conv": "pk", "df": "df", "cd": "cd"} scf_type = inp["keywords"].get("scf_type", natural_ref[corl_type]) natural_values = { "pk": "pk", "direct": "pk", "df": "df", "mem_df": "df", "disk_df": "df", "cd": "cd" } scf_type = natural_values[scf_type] atol = 1.0e-6 chash = answer_hash( system=subject.name(), basis=basis, fcae=fcae, scf_type=scf_type, reference=reference, corl_type=corl_type, ) # check all calcs against conventional reference to looser tolerance atol_conv = 3.0e-4 # for df-ccsd. mp2 ok with 1.e-4 chash_conv = answer_hash( system=subject.name(), basis=basis, fcae=fcae, reference=reference, corl_type="conv", scf_type="pk", ) ref_block_conv = std_suite[chash_conv] # <<< Prepare Calculation and Call API >>> driver_call = {"energy": psi4.energy, "gradient": psi4.gradient} psi4.set_options({ # reference generation conv crit # "guess": "sad", # "e_convergence": 10, # "d_convergence": 9, # "r_convergence": 9, # "pcg_convergence": 9, # runtime conv crit "points": 5, }) extra_kwargs = inp["keywords"].pop("function_kwargs", {}) psi4.set_options(inp["keywords"]) if "error" in inp: errtype, errmsg = inp["error"] with pytest.raises(errtype) as e: driver_call[driver](inp["call"], molecule=subject, **extra_kwargs) assert errmsg in str(e.value), f"({errmsg}) not in ({e.value})" return ret, wfn = driver_call[driver](inp["call"], molecule=subject, return_wfn=True, **extra_kwargs) qc_module_out = "psi4-" + ("occ" if wfn.module() == "dfocc" else wfn.module()) # returns "psi4-<module>" # <<< Comparison Tests >>> if qc_module_in != "psi4": assert qc_module_out == qc_module_in, f"QC_MODULE used ({qc_module_in}) != requested ({qc_module_out})" ref_block = std_suite[chash] # qcvars contractual_args = [ qc_module_in, driver, reference, method, corl_type, fcae, ] asserter_args = [ [psi4.core, wfn], ref_block, atol, ref_block_conv, atol_conv, tnm, ] def qcvar_assertions(): print("BLOCK", chash, contractual_args) if method == "hf": _asserter(asserter_args, contractual_args, contractual_hf) elif method == "mp2": _asserter(asserter_args, contractual_args, contractual_mp2) elif method == "mp2.5": _asserter(asserter_args, contractual_args, contractual_mp2) _asserter(asserter_args, contractual_args, contractual_mp3) _asserter(asserter_args, contractual_args, contractual_mp2p5) elif method == "mp3": _asserter(asserter_args, contractual_args, contractual_mp2) _asserter(asserter_args, contractual_args, contractual_mp2p5) _asserter(asserter_args, contractual_args, contractual_mp3) elif method == "lccd": _asserter(asserter_args, contractual_args, contractual_mp2) _asserter(asserter_args, contractual_args, contractual_lccd) elif method == "lccsd": _asserter(asserter_args, contractual_args, contractual_mp2) _asserter(asserter_args, contractual_args, contractual_lccsd) elif method == "ccsd": _asserter(asserter_args, contractual_args, contractual_mp2) _asserter(asserter_args, contractual_args, contractual_ccsd) elif method == "ccsd(t)": _asserter(asserter_args, contractual_args, contractual_mp2) _asserter(asserter_args, contractual_args, contractual_ccsd) _asserter(asserter_args, contractual_args, contractual_ccsd_prt_pr) elif method == "olccd": _asserter(asserter_args, contractual_args, contractual_mp2) _asserter(asserter_args, contractual_args, contractual_olccd) if "wrong" in inp: errmsg, reason = inp["wrong"] with pytest.raises(AssertionError) as e: qcvar_assertions() # print("WRONG", errmsg, reason, str(e.value), "ENDW") assert errmsg in str(e.value) pytest.xfail(reason) qcvar_assertions() # aliases _asserter(asserter_args, contractual_args, contractual_current) # returns tf, errmsg = compare_values( ref_block[f"{method.upper()} TOTAL ENERGY"], wfn.energy(), tnm + " wfn", atol=atol, return_message=True, quiet=True, ) assert compare_values(ref_block[f"{method.upper()} TOTAL ENERGY"], wfn.energy(), tnm + " wfn", atol=atol), errmsg if driver == "energy": assert compare_values(ref_block[f"{method.upper()} TOTAL ENERGY"], ret, tnm + " return") elif driver == "gradient": assert compare_values(ref_block[f"{method.upper()} TOTAL GRADIENT"], wfn.gradient().np, tnm + " grad wfn", atol=atol) assert compare_values(ref_block[f"{method.upper()} TOTAL GRADIENT"], ret.np, tnm + " grad return", atol=atol) # generics # yapf: disable assert compare(ref_block["N BASIS FUNCTIONS"], wfn.nso(), tnm + " nbasis wfn"), f"nbasis {wfn.nso()} != {ref_block['N BASIS FUNCTIONS']}" assert compare(ref_block["N MOLECULAR ORBITALS"], wfn.nmo(), tnm + " nmo wfn"), f"nmo {wfn.nmo()} != {ref_block['N MOLECULAR ORBITALS']}" assert compare(ref_block["N ALPHA ELECTRONS"], wfn.nalpha(), tnm + " nalpha wfn"), f"nalpha {wfn.nalpha()} != {ref_block['N ALPHA ELECTRONS']}" assert compare(ref_block["N BETA ELECTRONS"], wfn.nbeta(), tnm + " nbeta wfn"), f"nbeta {wfn.nbeta()} != {ref_block['N BETA ELECTRONS']}"
def runner_asserter(inp, ref_subject, method, basis, tnm, scramble, frame): qcprog = inp["qc_module"].split("-")[0] qc_module_in = inp["qc_module"] # returns "<qcprog>"|"<qcprog>-<module>" # input-specified routing qc_module_xptd = ( (qcprog + "-" + inp["xptd"]["qc_module"]) if inp.get("xptd", {}).get("qc_module", None) else None ) # expected routing driver = inp["driver"] reference = inp["reference"] fcae = inp["fcae"] mode_options = inp.get("cfg", {}) if qc_module_in == "nwchem-tce" and basis == "cc-pvdz": pytest.skip( f"TCE throwing 'non-Abelian symmetry not permitted' for HF molecule when not C1. fix this a different way than setting C1." ) # <<< Molecule >>> # 1. ref mol: `ref_subject` nicely oriented mol taken from standard_suite_ref.py ref_subject.update_geometry() min_nonzero_coords = np.count_nonzero(np.abs(ref_subject.geometry(np_out=True)) > 1.0e-10) # print( # "MOL 1/REF: ref_subject", # ref_subject.com_fixed(), # ref_subject.orientation_fixed(), # ref_subject.symmetry_from_input(), # ) # with np.printoptions(precision=3, suppress=True): # print(ref_subject.geometry(np_out=True)) if scramble is None: subject = ref_subject ref2in_mill = compute_scramble( subject.natom(), do_resort=False, do_shift=False, do_rotate=False, do_mirror=False ) # identity AlignmentMill else: subject, scramble_data = ref_subject.scramble(**scramble, do_test=False, fix_mode="copy") ref2in_mill = scramble_data["mill"] # with np.printoptions(precision=12, suppress=True): # print(f"ref2in scramble mill= {ref2in_mill}") # print("MOL 2/IN: subject", subject.com_fixed(), subject.orientation_fixed(), subject.symmetry_from_input()) # with np.printoptions(precision=3, suppress=True): # print(subject.geometry(np_out=True)) # 2. input mol: `subject` now ready for `atin.molecule`. may have been scrambled away from nice ref orientation # <<< Reference Values >>> # ? precedence on next two mp2_type = inp.get("corl_type", inp["keywords"].get("mp2_type", "df")) # hard-code of read_options.cc MP2_TYPE mp_type = inp.get("corl_type", inp["keywords"].get("mp_type", "conv")) # hard-code of read_options.cc MP_TYPE ci_type = inp.get("corl_type", inp["keywords"].get("ci_type", "conv")) # hard-code of read_options.cc CI_TYPE cc_type = inp.get("corl_type", inp["keywords"].get("cc_type", "conv")) # hard-code of read_options.cc CC_TYPE corl_natural_values = { "hf": "conv", # dummy to assure df/cd/conv scf_type refs available "mp2": mp2_type, "mp3": mp_type, "mp4(sdq)": mp_type, "mp4": mp_type, "cisd": ci_type, "qcisd": ci_type, "qcisd(t)": ci_type, "fci": ci_type, "lccd": cc_type, "lccsd": cc_type, "ccd": cc_type, "ccsd": cc_type, "ccsd+t(ccsd)": cc_type, "ccsd(t)": cc_type, "a-ccsd(t)": cc_type, "ccsdt-1a": cc_type, "ccsdt-1b": cc_type, "ccsdt-2": cc_type, "ccsdt-3": cc_type, "ccsdt": cc_type, "ccsdt(q)": cc_type, "ccsdtq": cc_type, "pbe": "conv", "b3lyp": "conv", "b3lyp5": "conv", "mrccsdt-1a": cc_type, "mrccsdt-1b": cc_type, "mrccsdt-2": cc_type, "mrccsdt-3": cc_type, } corl_type = corl_natural_values[method] natural_ref = {"conv": "pk", "df": "df", "cd": "cd"} scf_type = inp["keywords"].get("scf_type", natural_ref[corl_type]) natural_values = {"pk": "pk", "direct": "pk", "df": "df", "mem_df": "df", "disk_df": "df", "cd": "cd"} scf_type = natural_values[scf_type] is_dft = method in ["pbe", "b3lyp", "b3lyp5"] # * absolute and relative tolerances function approx as `or` operation. see https://numpy.org/doc/stable/reference/generated/numpy.allclose.html # * can't go lower on atol_e because hit digit limits accessible for reference values # * dz gradients tend to be less accurate than larger basis sets/mols # * analytic Hessian very loose to catch gms/nwc HF Hessian atol_e, rtol_e = 2.0e-7, 1.0e-16 atol_g, rtol_g = 5.0e-7, 2.0e-5 atol_h, rtol_h = 1.0e-5, 2.0e-5 if is_dft: atol_g = 6.0e-6 using_fd = "xptd" in inp and "fd" in inp["xptd"] # T/F: notate fd vs. anal for docs table loose_fd = inp.get("xptd", {}).get("fd", False) # T/F: relax conv crit for 3-pt internal findif fd if loose_fd: if basis == "cc-pvdz": atol_g = 1.0e-4 atol_h, rtol_h = 1.0e-4, 5.0e-4 else: atol_g = 2.0e-5 atol_h, rtol_h = 5.0e-5, 2.0e-4 # VIEW atol_e, atol_g, atol_h, rtol_e, rtol_g, rtol_h = 1.e-9, 1.e-9, 1.e-9, 1.e-16, 1.e-16, 1.e-16 chash = answer_hash( system=subject.name(), basis=basis, fcae=fcae, scf_type=scf_type, reference=reference, corl_type=corl_type, ) ref_block = std_suite[chash] # check all calcs against conventional reference to looser tolerance atol_conv = 1.0e-4 rtol_conv = 1.0e-3 chash_conv = answer_hash( system=subject.name(), basis=basis, fcae=fcae, reference=reference, corl_type="conv", scf_type="pk", ) ref_block_conv = std_suite[chash_conv] # <<< Prepare Calculation and Call API >>> import qcdb driver_call = {"energy": qcdb.energy, "gradient": qcdb.gradient, "hessian": qcdb.hessian} # local_options = {"nnodes": 1, "ncores": 2, "scratch_messy": False, "memory": 4} local_options = {"nnodes": 1, "ncores": 1, "scratch_messy": False, "memory": 10} qcdb.set_options( { # "guess": "sad", # "e_convergence": 8, # "d_convergence": 7, # "r_convergence": 7, "e_convergence": 10, "d_convergence": 9, # "r_convergence": 9, # "points": 5, } ) extra_kwargs = inp["keywords"].pop("function_kwargs", {}) qcdb.set_options(inp["keywords"]) if "error" in inp: errtype, errmatch, reason = inp["error"] with pytest.raises(errtype) as e: driver_call[driver](inp["call"], molecule=subject, local_options=local_options, **extra_kwargs) assert re.search(errmatch, str(e.value)), f"Not found: {errtype} '{errmatch}' in {e.value}" _recorder(qcprog, qc_module_in, driver, method, reference, fcae, scf_type, corl_type, "error", "nyi: " + reason) return ret, wfn = driver_call[driver]( inp["call"], molecule=subject, return_wfn=True, local_options=local_options, mode_options=mode_options, **extra_kwargs ) print("WFN") pp.pprint(wfn) qc_module_out = wfn["provenance"]["creator"].lower() if "module" in wfn["provenance"]: qc_module_out += "-" + wfn["provenance"]["module"] # returns "<qcprog>-<module>" # assert 0, f"{qc_module_xptd=} {qc_module_in=} {qc_module_out=}" # debug # 3. output mol: `wfn.molecule` after calc. orientation for nonscalar quantities may be different from `subject` if fix_=False wfn_molecule = qcdb.Molecule.from_schema(wfn["molecule"]) # print( # "MOL 3/WFN: wfn.mol", # wfn_molecule.com_fixed(), # wfn_molecule.orientation_fixed(), # wfn_molecule.symmetry_from_input(), # ) # with np.printoptions(precision=3, suppress=True): # print(wfn_molecule.geometry(np_out=True)) _, ref2out_mill, _ = ref_subject.B787(wfn_molecule, atoms_map=False, mols_align=True, fix_mode="true", verbose=0) # print(f"{ref2out_mill=}") # print("PREE REF") # print(ref_block["HF TOTAL GRADIENT"]) if subject.com_fixed() and subject.orientation_fixed(): assert frame == "fixed" with np.printoptions(precision=3, suppress=True): assert compare_values( subject.geometry(), wfn_molecule.geometry(), atol=5.0e-8 ), f"coords: atres ({wfn_molecule.geometry(np_out=True)}) != atin ({subject.geometry(np_out=True)})" # 10 too much assert ( ref_subject.com_fixed() and ref_subject.orientation_fixed() and subject.com_fixed() and subject.orientation_fixed() and wfn_molecule.com_fixed() and wfn_molecule.orientation_fixed() ), f"fixed, so all T: {ref_subject.com_fixed()} {ref_subject.orientation_fixed()} {subject.com_fixed()} {subject.orientation_fixed()} {wfn_molecule.com_fixed()} {wfn_molecule.orientation_fixed()}" ref_block = mill_qcvars(ref2in_mill, ref_block) ref_block_conv = mill_qcvars(ref2in_mill, ref_block_conv) else: assert frame == "free" or frame == "" # "": direct from standard_suite_ref.std_molecules with np.printoptions(precision=3, suppress=True): assert compare( min_nonzero_coords, np.count_nonzero(np.abs(wfn_molecule.geometry(np_out=True)) > 1.0e-10), tnm + " !0 coords wfn", ), f"ncoords {wfn_molecule.geometry(np_out=True)} != {min_nonzero_coords}" assert ( (not ref_subject.com_fixed()) and (not ref_subject.orientation_fixed()) and (not subject.com_fixed()) and (not subject.orientation_fixed()) and (not wfn_molecule.com_fixed()) and (not wfn_molecule.orientation_fixed()) ), f"free, so all F: {ref_subject.com_fixed()} {ref_subject.orientation_fixed()} {subject.com_fixed()} {subject.orientation_fixed()} {wfn_molecule.com_fixed()} {wfn_molecule.orientation_fixed()}" if scramble is None: # wfn exactly matches ref_subject and ref_block with np.printoptions(precision=3, suppress=True): assert compare_values( ref_subject.geometry(), wfn_molecule.geometry(), atol=5.0e-8 ), f"coords: atres ({wfn_molecule.geometry(np_out=True)}) != atin ({ref_subject.geometry(np_out=True)})" else: # wfn is "pretty" (max zeros) but likely not exactly ref_block (by axis exchange, phasing, atom shuffling) since Psi4 ref frame is not unique ref_block = mill_qcvars(ref2out_mill, ref_block) ref_block_conv = mill_qcvars(ref2out_mill, ref_block_conv) # print("POST REF") # print(ref_block["HF TOTAL GRADIENT"]) # <<< Comparison Tests >>> assert wfn["success"] is True assert ( wfn["provenance"]["creator"].lower() == qcprog ), f'ENGINE used ({ wfn["provenance"]["creator"].lower()}) != requested ({qcprog})' # qcvars contractual_args = [ qc_module_out, driver, reference, method, corl_type, fcae, ] asserter_args = [ [qcdb, wfn["qcvars"]], ref_block, [atol_e, atol_g, atol_h], [rtol_e, rtol_g, rtol_h], ref_block_conv, atol_conv, rtol_conv, tnm, ] def qcvar_assertions(): print("BLOCK", chash, contractual_args) if method == "hf": _asserter(asserter_args, contractual_args, contractual_hf) elif method == "mp2": _asserter(asserter_args, contractual_args, contractual_mp2) elif method == "mp3": _asserter(asserter_args, contractual_args, contractual_mp2) _asserter(asserter_args, contractual_args, contractual_mp2p5) _asserter(asserter_args, contractual_args, contractual_mp3) elif method == "mp4(sdq)": _asserter(asserter_args, contractual_args, contractual_mp2) _asserter(asserter_args, contractual_args, contractual_mp2p5) _asserter(asserter_args, contractual_args, contractual_mp3) _asserter(asserter_args, contractual_args, contractual_mp4_prsdq_pr) elif method == "mp4": _asserter(asserter_args, contractual_args, contractual_mp2) _asserter(asserter_args, contractual_args, contractual_mp2p5) _asserter(asserter_args, contractual_args, contractual_mp3) _asserter(asserter_args, contractual_args, contractual_mp4_prsdq_pr) _asserter(asserter_args, contractual_args, contractual_mp4) elif method == "cisd": _asserter(asserter_args, contractual_args, contractual_cisd) elif method == "qcisd": _asserter(asserter_args, contractual_args, contractual_mp2) _asserter(asserter_args, contractual_args, contractual_qcisd) elif method == "qcisd(t)": _asserter(asserter_args, contractual_args, contractual_mp2) _asserter(asserter_args, contractual_args, contractual_qcisd) _asserter(asserter_args, contractual_args, contractual_qcisd_prt_pr) elif method == "fci": _asserter(asserter_args, contractual_args, contractual_fci) elif method == "lccd": _asserter(asserter_args, contractual_args, contractual_mp2) _asserter(asserter_args, contractual_args, contractual_lccd) elif method == "lccsd": _asserter(asserter_args, contractual_args, contractual_mp2) _asserter(asserter_args, contractual_args, contractual_lccsd) elif method == "ccd": _asserter(asserter_args, contractual_args, contractual_mp2) _asserter(asserter_args, contractual_args, contractual_ccd) elif method == "ccsd": _asserter(asserter_args, contractual_args, contractual_mp2) _asserter(asserter_args, contractual_args, contractual_ccsd) elif method == "ccsd+t(ccsd)": _asserter(asserter_args, contractual_args, contractual_mp2) _asserter(asserter_args, contractual_args, contractual_ccsd) _asserter(asserter_args, contractual_args, contractual_ccsdpt_prccsd_pr) elif method == "ccsd(t)": _asserter(asserter_args, contractual_args, contractual_mp2) _asserter(asserter_args, contractual_args, contractual_ccsd) _asserter(asserter_args, contractual_args, contractual_ccsd_prt_pr) elif method == "a-ccsd(t)": _asserter(asserter_args, contractual_args, contractual_mp2) _asserter(asserter_args, contractual_args, contractual_ccsd) _asserter(asserter_args, contractual_args, contractual_accsd_prt_pr) elif method == "ccsdt-1a": _asserter(asserter_args, contractual_args, contractual_mp2) _asserter(asserter_args, contractual_args, contractual_ccsdt1a) elif method == "ccsdt-1b": _asserter(asserter_args, contractual_args, contractual_mp2) _asserter(asserter_args, contractual_args, contractual_ccsdt1b) elif method == "ccsdt-2": _asserter(asserter_args, contractual_args, contractual_mp2) _asserter(asserter_args, contractual_args, contractual_ccsdt2) elif method == "ccsdt-3": _asserter(asserter_args, contractual_args, contractual_mp2) _asserter(asserter_args, contractual_args, contractual_ccsdt3) elif method == "ccsdt": _asserter(asserter_args, contractual_args, contractual_mp2) _asserter(asserter_args, contractual_args, contractual_ccsdt) elif method == "ccsdt(q)": _asserter(asserter_args, contractual_args, contractual_mp2) _asserter(asserter_args, contractual_args, contractual_ccsdt) _asserter(asserter_args, contractual_args, contractual_ccsdt_prq_pr) elif method == "ccsdtq": _asserter(asserter_args, contractual_args, contractual_mp2) _asserter(asserter_args, contractual_args, contractual_ccsdtq) # separations here for DFT appropriate when qcvars are labeled by functional if "wrong" in inp: if basis == "cc-pvdz" and contractual_args in [ ["cfour-ecc", "gradient", "rhf", mtd, "conv", "fc"] for mtd in ["ccsdt-1a", "ccsdt-1b", "ccsdt-2", "ccsdt-3"] ]: # these four tests have pass/fail too close for dz to "get it right" with general tolerances pass else: errmatch, reason = inp["wrong"] with pytest.raises(AssertionError) as e: qcvar_assertions() assert errmatch in str(e.value), f"Not found: AssertionError '{errmatch}' for '{reason}' in {e.value}" _recorder( qcprog, qc_module_out, driver, method, reference, fcae, scf_type, corl_type, "wrong", reason + f" First wrong at `{errmatch}`.", ) pytest.xfail(reason) # primary label checks qcvar_assertions() # routing checks if qc_module_in != qcprog: assert qc_module_out == qc_module_in, f"QC_MODULE used ({qc_module_out}) != requested ({qc_module_in})" if qc_module_xptd: assert qc_module_out == qc_module_xptd, f"QC_MODULE used ({qc_module_out}) != expected ({qc_module_xptd})" # aliases checks if is_dft: _asserter(asserter_args, contractual_args, contractual_dft_current) else: _asserter(asserter_args, contractual_args, contractual_current) # returns checks if driver == "energy": assert compare_values( ref_block[f"{method.upper()} TOTAL ENERGY"], wfn["return_result"], tnm + " wfn", atol=atol_e, rtol=rtol_e ) assert compare_values( ref_block[f"{method.upper()} TOTAL ENERGY"], wfn["properties"]["return_energy"], tnm + " prop", atol=atol_e, rtol=rtol_e, ) assert compare_values(ref_block[f"{method.upper()} TOTAL ENERGY"], ret, tnm + " return") elif driver == "gradient": assert compare_values( ref_block[f"{method.upper()} TOTAL GRADIENT"], wfn["return_result"], tnm + " grad wfn", atol=atol_g, rtol=rtol_g, ) assert compare_values( ref_block[f"{method.upper()} TOTAL ENERGY"], wfn["properties"]["return_energy"], tnm + " prop", atol=atol_e, rtol=rtol_e, ) assert compare_values( ref_block[f"{method.upper()} TOTAL GRADIENT"], wfn["properties"]["return_gradient"], tnm + " grad prop", atol=atol_g, rtol=rtol_g, ) assert compare_values( ref_block[f"{method.upper()} TOTAL GRADIENT"], ret, tnm + " grad return", atol=atol_g, rtol=rtol_g ) elif driver == "hessian": assert compare_values( ref_block[f"{method.upper()} TOTAL HESSIAN"], wfn["return_result"], tnm + " hess wfn", atol=atol_h, rtol=rtol_h, ) assert compare_values( ref_block[f"{method.upper()} TOTAL ENERGY"], wfn["properties"]["return_energy"], tnm + " prop", atol=atol_e, rtol=rtol_e, ) # assert compare_values(ref_block[f"{method.upper()} TOTAL GRADIENT"], wfn["properties"]["return_gradient"], tnm + " grad prop", atol=atol_g, rtol=rtol_g) assert compare_values( ref_block[f"{method.upper()} TOTAL HESSIAN"], wfn["properties"]["return_hessian"], tnm + " hess prop", atol=atol_h, rtol=rtol_h, ) assert compare_values( ref_block[f"{method.upper()} TOTAL HESSIAN"], ret, tnm + " hess return", atol=atol_h, rtol=rtol_h ) # generics checks # yapf: disable assert compare(ref_block["N BASIS FUNCTIONS"], wfn["properties"]["calcinfo_nbasis"], tnm + " nbasis wfn"), f"nbasis {wfn['properties']['calcinfo_nbasis']} != {ref_block['N BASIS FUNCTIONS']}" assert compare(ref_block["N MOLECULAR ORBITALS"], wfn["properties"]["calcinfo_nmo"], tnm + " nmo wfn"), f"nmo {wfn['properties']['calcinfo_nmo']} != {ref_block['N MOLECULAR ORBITALS']}" assert compare(ref_block["N ALPHA ELECTRONS"], wfn["properties"]["calcinfo_nalpha"], tnm + " nalpha wfn"), f"nalpha {wfn['properties']['calcinfo_nalpha']} != {ref_block['N ALPHA ELECTRONS']}" assert compare(ref_block["N BETA ELECTRONS"], wfn["properties"]["calcinfo_nbeta"], tnm + " nbeta wfn"), f"nbeta {wfn['properties']['calcinfo_nbeta']} != {ref_block['N BETA ELECTRONS']}" # yapf: enable # record _recorder( qcprog, qc_module_out, driver, method, reference, fcae, scf_type, corl_type, "fd" if using_fd else "pass", "" )