Skip to content

Commit 7eddc59

Browse files
committed
Fix issues with apps and mcscf
1 parent 9f9ca8b commit 7eddc59

9 files changed

Lines changed: 81 additions & 38 deletions

File tree

forte/apps/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
from .mcscf import run_mcscf
2-
from .hf import run_hf
1+
from .mcscf import mcscf
2+
from .hf import hf

forte/apps/hf.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,21 @@
66
from forte.modules.hf import HF
77

88

9-
def run_hf(geom, basis, state):
9+
def hf(geom, basis, state, e_convergence=1e-8, d_convergence=1e-8, options=None):
1010
charge, multiplicity, sym = parse_state(state)
1111
hf_workflow = Workflow(
1212
[
13-
OptionsFactory(),
13+
# Pass the options to the ForteOptions object
14+
OptionsFactory(options),
15+
# Generate the molecule
1416
MoleculeFactory(geom),
17+
# Generate the state
1518
StateFactory(charge=charge, multiplicity=multiplicity, sym=sym),
16-
HF(basis=basis),
19+
# Run the HF calculation
20+
HF(basis=basis, e_convergence=e_convergence, d_convergence=d_convergence),
1721
],
1822
name="HF Workflow",
1923
)
2024
data = hf_workflow.run()
25+
data.options.set_str("basis", basis)
2126
return data

forte/apps/mcscf.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,20 @@
11
from .apps_helpers import parse_active_space
2-
from .hf import run_hf
2+
from .hf import hf
33
from forte.modules.workflow import Workflow
44
from forte.modules.objects_factory_psi4 import ObjectsFromPsi4
55
from forte.modules.active_space_selector import ActiveSpaceSelector
66
from forte.modules.mcscf import MCSCF
7+
from forte.modules.options_factory import OptionsFactory
78

89

9-
def run_mcscf(geom, basis, state, active_space, solver_type="FCI"):
10-
data = run_hf(geom, basis, state)
10+
def mcscf(active_space, solver_type="FCI", options=None, data=None, geom=None, basis=None, state=None):
11+
if data is None and geom is not None and basis is not None:
12+
# If data is None, create a new data object
13+
data = hf(geom, basis, state, options=options)
14+
elif data is None:
15+
raise ValueError("Either data or geom and basis must be provided.")
16+
17+
# Setup a workflow to run MCSCF
1118
mcscf_workflow = Workflow(
1219
[
1320
# Parse the active space before defining the MOSpaceInfo object
@@ -19,5 +26,8 @@ def run_mcscf(geom, basis, state, active_space, solver_type="FCI"):
1926
],
2027
name="MCSCF Workflow",
2128
)
29+
30+
# Run the workflow
2231
data = mcscf_workflow.run(data)
32+
2333
return data

forte/mcscf/mcscf_2step.cc

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -425,16 +425,7 @@ double MCSCF_2STEP::compute_energy() {
425425
diis_manager.delete_diis_file();
426426
} // end of MCSCF macro iterations
427427

428-
// perform final active space computation using converged orbitals
429-
if (print_ >= PrintLevel::Default)
430-
psi::outfile->Printf("\n\n Performing final CI Calculation using converged orbitals");
431-
432-
as_solver_->set_maxiter(as_maxiter);
433-
as_solver_->set_die_if_not_converged(true);
434-
energy_ =
435-
diagonalize_hamiltonian(cas_grad.active_space_ints(),
436-
{print_, e_conv_, r_conv, options_->get_bool("DUMP_ACTIVE_WFN")});
437-
428+
// Transform the orbitals to canonical or natural basis
438429
if (ints_->integral_type() != Custom) {
439430
// fix orbitals for redundant pairs
440431
rdms = as_solver_->compute_average_rdms(state_weights_map_, 1, RDMsType::spin_free);
@@ -456,6 +447,9 @@ double MCSCF_2STEP::compute_energy() {
456447
semi.semicanonicalize(rdms, false, actv_orb_type, false);
457448
cas_grad.canonicalize_final(semi.Ua());
458449

450+
// after this step, the integrals, CI coefficients, and rdms are no longer valid.
451+
// Below we rediagonalize the Hamiltonian to get the new CI coefficients.
452+
459453
// pass the MO coefficients to the wave function
460454
auto Ca = cas_grad.Ca();
461455
ints_->wfn()->Ca()->copy(Ca);
@@ -518,6 +512,17 @@ double MCSCF_2STEP::compute_energy() {
518512
throw_convergence_error();
519513
}
520514

515+
// Perform final active space computation using converged transformed orbitals
516+
if (der_type_ != "FIRST" or options_->get_str("CORRELATION_SOLVER") != "NONE") {
517+
if (print_ >= PrintLevel::Default)
518+
psi::outfile->Printf("\n\n Performing final CI Calculation using converged orbitals");
519+
as_solver_->set_maxiter(as_maxiter);
520+
as_solver_->set_die_if_not_converged(true);
521+
energy_ = diagonalize_hamiltonian(
522+
cas_grad.active_space_ints(),
523+
{print_, e_conv_, r_conv, options_->get_bool("DUMP_ACTIVE_WFN")});
524+
}
525+
521526
return energy_;
522527
}
523528

forte/modules/active_space_selector.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,13 @@
77

88
class ActiveSpaceSelector(Module):
99
"""
10-
A module to prepare an ActiveSpaceIntegral
10+
A module to prepare the active space for the MCSCF calculation.
11+
This code will use the active space information from the input file to select the active space.
12+
13+
The active space can be specified in several ways:
14+
- active_space = {"nel": 6, "norb": 6} # 6 electrons in 6 orbitals
15+
- active_space = {"nel": 6, "active_orbitals": ["1 A1", "2 A1", "3 A1"]} # 6 electrons in the specified orbitals
16+
- active_space = {"active": [2, 0, 1, 1]} # select 2 x A1, 1 x B1, and 1 x B2 active orbitals
1117
"""
1218

1319
# accept as input a dictionary of string,int list pairs or a list of integers
@@ -19,7 +25,6 @@ def __init__(self, active_space: Union[Dict[str, List[int]], List[int]] = None):
1925
The active space to be used for the calculation
2026
"""
2127
super().__init__()
22-
# assert isinstance(active_space, dict) or isinstance(active_space, list)
2328

2429
self.active_space = active_space
2530

@@ -29,7 +34,7 @@ def _run(self, data: ForteData) -> ForteData:
2934
Selects the active space based on the input
3035
"""
3136

32-
# in the case where we have no active space selection, we just assemble this object from the options
37+
# if no active space is provided, use the options object
3338
self.active_space = self.active_space or self.make_dict_from_data(data)
3439

3540
# select the active space using the information in the active_space dictionary

forte/modules/hf.py

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -55,23 +55,24 @@ def _run(self, data: ForteData) -> ForteData:
5555
molecule.set_multiplicity(state.multiplicity())
5656

5757
# # prepare options for psi4
58-
# scf_type_dict = {
59-
# "CONVENTIONAL": "PK",
60-
# "STD": "PK",
61-
# }
62-
# # convert to psi4 terminology
63-
# int_type = self.model.int_type.upper()
64-
# if int_type in scf_type_dict:
65-
# scf_type = scf_type_dict[int_type]
66-
# else:
67-
# scf_type = int_type
68-
scf_type = "PK"
58+
scf_type_dict = {
59+
"CONVENTIONAL": "PK",
60+
"STD": "PK",
61+
}
62+
# convert to psi4 terminology
63+
int_type = data.options.get_str("int_type")
64+
if int_type in scf_type_dict:
65+
scf_type = scf_type_dict[int_type]
66+
else:
67+
scf_type = int_type
6968

7069
if self.restricted:
7170
ref = "RHF" if state.multiplicity() == 1 else "ROHF"
7271
else:
7372
ref = "UHF"
7473

74+
print(f"HF: using {scf_type} for the SCF calculation")
75+
7576
options = {
7677
"BASIS": self.basis,
7778
"REFERENCE": ref,

forte/modules/objects_factory_psi4.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -368,5 +368,6 @@ def prepare_forte_objects_from_wavefunction(self, data):
368368
# Build Forte SCFInfo object
369369
data.scf_info = SCFInfo(data.psi_wfn)
370370

371-
# Build a map from Forte StateInfo to the weights
372-
data.state_weights_map = make_state_weights_map(data.options, data.mo_space_info)
371+
# Build a map of StateInfo and weights from the Options and MOSpaceInfo objects if not already done elsewhere
372+
if data.state_weights_map is None:
373+
data.state_weights_map = make_state_weights_map(data.options, data.mo_space_info)

tests/pytest/apps/test_hf_app.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ def test_rhf_app():
77
H 0.0 0.0 0.0
88
H 0.0 0.0 1.0
99
"""
10-
data = forte.apps.run_hf(geom=xyz, basis="cc-pVDZ", state={"charge": 0, "multiplicity": 1, "sym": "ag"})
10+
data = forte.apps.hf(geom=xyz, basis="cc-pVDZ", state={"charge": 0, "multiplicity": 1, "sym": "ag"})
1111
assert data.results.value("hf energy") == pytest.approx(-1.10015376479352, 1.0e-10)
1212

1313

tests/pytest/apps/test_mcscf_app.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ def test_mcscf_app1():
77
H 0.0 0.0 0.0
88
H 0.0 0.0 1.5
99
"""
10-
data = forte.apps.run_mcscf(
10+
data = forte.apps.mcscf(
1111
geom=xyz,
1212
basis="cc-pVDZ",
1313
state={"charge": 0, "multiplicity": 1, "sym": "ag"},
@@ -22,7 +22,7 @@ def test_mcscf_app2():
2222
H 0.0 0.0 0.0
2323
H 0.0 0.0 1.5
2424
"""
25-
data = forte.apps.run_mcscf(
25+
data = forte.apps.mcscf(
2626
geom=xyz,
2727
basis="cc-pVDZ",
2828
state={"charge": 0, "multiplicity": 1, "sym": "ag"},
@@ -37,7 +37,7 @@ def test_mcscf_app3():
3737
H 0.0 0.0 0.0
3838
H 0.0 0.0 1.5
3939
"""
40-
data = forte.apps.run_mcscf(
40+
data = forte.apps.mcscf(
4141
geom=xyz,
4242
basis="cc-pVDZ",
4343
state={"charge": 0, "multiplicity": 1, "sym": "ag"},
@@ -48,6 +48,22 @@ def test_mcscf_app3():
4848
data.scf_info.reorder_orbitals([[0, 1, 2], [], [0], [0], [], [1, 0, 2], [0], [0]])
4949

5050

51+
# def test_mcscf_app4():
52+
# xyz = """
53+
# H 0.0 0.0 0.0
54+
# H 0.0 0.0 1.5
55+
# """
56+
# data = forte.apps.run_mcscf(
57+
# geom=xyz,
58+
# basis="cc-pVDZ",
59+
# states=[{"charge": 0, "multiplicity": 1, "sym": "ag", "weights": [0.5, 0.5]}],
60+
# active_space={"active_orbitals": ["1 Ag", "1 B1u"], "nel": 2},
61+
# solver_type="GENCI",
62+
# )
63+
# assert data.results.value("mcscf energy") == pytest.approx(-1.0561253825629822, 1.0e-10)
64+
# data.scf_info.reorder_orbitals([[0, 1, 2], [], [0], [0], [], [1, 0, 2], [0], [0]])
65+
66+
5167
if __name__ == "__main__":
5268
test_mcscf_app1()
5369
test_mcscf_app2()

0 commit comments

Comments
 (0)