Skip to content

Commit

Permalink
supersystem_ie_only and levels w/supersystem printing and variables (#13
Browse files Browse the repository at this point in the history
)

* working order

* print and var stuff

* Update multi+ss test

---------

Co-authored-by: Benjamin Pritchard <[email protected]>
  • Loading branch information
loriab and bennybp authored Apr 23, 2024
1 parent 60212b3 commit db63c16
Show file tree
Hide file tree
Showing 10 changed files with 645 additions and 65 deletions.
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"autoDocstring.docstringFormat": "numpy-notypes"
}
10 changes: 1 addition & 9 deletions qcmanybody/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ def build_nbody_compute_list(
for nb in nbodies:
for cp_combos in itertools.combinations(fragment_range, nb):
basis_tuple = tuple(cp_combos)
# TODO vmfc_compute_list and vmfc_level_list are identical, so consolidate
for interior_nbody in range(1, nb + 1):
for x in itertools.combinations(cp_combos, interior_nbody):
combo_tuple = (x, basis_tuple)
Expand Down Expand Up @@ -159,15 +160,6 @@ def build_nbody_compute_list(
compute_list.setdefault(nb, set())
compute_list[nb] |= lst

# Rearrange compute_list from key nb having values to compute all of that nb
# to key nb including values of that nb. Use for counting.
compute_list_count = {x: set() for x in nbodies}
for nb in nbodies:
for nbset in compute_list.values():
for item in nbset:
if len(item[0]) == nb:
compute_list_count[nb].add(item)

compute_dict = {
"all": compute_list,
"cp": cp_compute_list,
Expand Down
67 changes: 54 additions & 13 deletions qcmanybody/manybody.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import logging
import math
from collections import defaultdict
from collections import Counter, defaultdict
from typing import Iterable, Set, Dict, Tuple, Union, Literal, Mapping, Any, Sequence

import numpy as np
Expand Down Expand Up @@ -130,6 +130,43 @@ def compute_map(self) -> Dict[str, Dict[str, Dict[int, Set[FragBasIndex]]]]:

return self.mc_compute_dict

def format_calc_plan(self, sset: str = "all") -> Tuple[str, Dict[str, Dict[int, int]]]:
"""Formulate per-modelchem and per-body job count data and summary text.
Parameters
----------
sset
Among {"all", "nocp", "cp", "vmfc_compute"}, which data structure to return.
Returns
-------
info
A text summary with per- model chemistry and per- n-body-level job counts.
Dict[str, Dict[int, int]]
Data structure with outer key mc-label, inner key 1-indexed n-body, value job count.
"""
# Rearrange compute_list from key nb having values (species) to compute all of that nb
# to key nb having values counting that nb.
compute_list_count = {}
for mc, compute_dict in self.compute_map.items():
compute_list_count[mc] = {}
for sub in compute_dict: # all, nocp, cp, vmfc
all_calcs = set().union(*compute_dict[sub].values())
compute_list_count[mc][sub] = Counter([len(frag) for (frag, _) in all_calcs])

info = []
for mc, counter in compute_list_count.items():
all_counter = counter["all"]
info.append(f" Model chemistry \"{mc}\" (???): {sum(all_counter.values())}")
for nb, count in sorted(all_counter.items()):
other_counts = [f"{sub}: {counter[sub][nb]}" for sub in ["nocp", "cp", "vmfc_compute"]]
info.append(f" Number of {nb}-body computations: {count:6} ({', '.join(other_counts)})")
info.append("")
info = "\n".join(info)

logger.info(info)
return info, {mc: dsset[sset] for mc, dsset in compute_list_count.items()}

def resize_gradient(self, grad: np.ndarray, bas: Tuple[int, ...], *, reverse: bool = False) -> np.ndarray:
return resize_gradient(grad, bas, self.fragment_size_dict, self.fragment_slice_dict, reverse=reverse)

Expand Down Expand Up @@ -476,6 +513,7 @@ def analyze(
component_properties = defaultdict(dict)
all_results = {}
nbody_dict = {}
stdout = ""
# all_results["energy_body_dict"] = {"cp": {1: 0.0}}

for property_label, property_results in component_results_inv.items():
Expand All @@ -492,32 +530,35 @@ def analyze(
all_results.update(r)

for bt in self.bsse_type:
print_nbody_energy(
stdout += print_nbody_energy(
all_results["energy_body_dict"][bt],
f"{bt.upper()}-corrected multilevel many-body expansion",
f"{bt.formal()} ({bt.abbr()})",
self.nfragments,
is_embedded,
self.supersystem_ie_only,
self.max_nbody if self.has_supersystem else None,
)

for property_label in available_properties:
for bt in self.bsse_type:
if not self.has_supersystem: # skipped levels?
nbody_dict.update(
collect_vars(
bt.upper(),
property_label.upper(),
all_results[f"{property_label}_body_dict"][bt],
self.max_nbody,
is_embedded,
self.supersystem_ie_only,
)
nbody_dict.update(
collect_vars(
bt.upper(),
property_label.upper(),
all_results[f"{property_label}_body_dict"][bt],
self.max_nbody,
is_embedded,
self.supersystem_ie_only,
self.has_supersystem,
)
)

all_results["results"] = nbody_dict
all_results["component_properties"] = component_properties

# Make dictionary with "1cp", "2cp", etc
ebd = all_results["energy_body_dict"]
all_results["energy_body_dict"] = {str(k) + bt: v for bt in ebd for k, v in ebd[bt].items()}
all_results["stdout"] = stdout

return all_results
17 changes: 16 additions & 1 deletion qcmanybody/models/manybody_pydv1.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,20 @@ class BsseEnum(str, Enum):
vmfc = "vmfc" # Valiron-Mayer function counterpoise
ssfc = "cp"

def formal(self):
return {
"nocp": "Non-Counterpoise Corrected",
"cp": "Counterpoise Corrected",
"vmfc": "Valiron-Mayer Function Counterpoise",
}[self]

def abbr(self):
return {
"nocp": "NoCP",
"cp": "CP",
"vmfc": "VMFC",
}[self]


FragBasIndex = Tuple[Tuple[int], Tuple[int]]

Expand Down Expand Up @@ -104,7 +118,8 @@ class ManyBodyKeywords(ProtoModel):
# definitive description. appended in Computer
description="Dictionary of different levels of theory for different levels of expansion. Note that the primary "
"method_string is not used when this keyword is given. ``supersystem`` computes all higher order n-body "
"effects up to the number of fragments. A method fills in for any lower unlisted nbody levels. Note that if "
"effects up to the number of fragments; this higher-order correction uses the nocp basis, regardless of "
"bsse_type. A method fills in for any lower unlisted nbody levels. Note that if "
"both this and max_nbody are provided, they must be consistent. Examples: "
"SUPERSYSTEM definition suspect"
"* {1: 'ccsd(t)', 2: 'mp2', 'supersystem': 'scf'} "
Expand Down
13 changes: 9 additions & 4 deletions qcmanybody/models/qcng_computer.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ class ManyBodyComputerQCNG(BaseComputerQCNG):
description=ManyBodyKeywords.__fields__["supersystem_ie_only"].field_info.description,
)
task_list: Dict[str, Any] = {} #MBETaskComputers] = {}
#qcmb_calculator: Optional[Any] = None

# TODO @computed_field(description="Number of distinct fragments comprising full molecular supersystem.")
@property
Expand Down Expand Up @@ -368,7 +369,7 @@ def set_supersystem_ie_only(cls, v: Optional[bool], values) -> bool:
return sio

@classmethod
def from_qcschema_ben(cls, input_model: ManyBodyInput):
def from_qcschema_ben(cls, input_model: ManyBodyInput, build_tasks: bool = True):

computer_model = cls(
molecule=input_model.molecule,
Expand All @@ -387,7 +388,8 @@ def from_qcschema_ben(cls, input_model: ManyBodyInput):
comp_levels = {}
for mc_level_idx, mtd in enumerate(computer_model.levels.values()):
for lvl1 in nb_per_mc[mc_level_idx]:
comp_levels[int(lvl1)] = mtd
key = "supersystem" if lvl1 == "supersystem" else int(lvl1)
comp_levels[key] = mtd

specifications = {}
for mtd, spec in computer_model.input_data.specification.specification.items():
Expand All @@ -406,8 +408,8 @@ def from_qcschema_ben(cls, input_model: ManyBodyInput):
computer_model.supersystem_ie_only,
)

print("\n<<< (ZZ 2) QCManyBody module ManyBodyCalculator >>>")
print(dir(calculator_cls))
if not build_tasks:
return calculator_cls

component_results = {}

Expand Down Expand Up @@ -742,6 +744,8 @@ def get_results(self, client: Optional["qcportal.FractalClient"] = None, externa
ret_gradient = external_results.pop("ret_gradient", None)
nbody_number = external_results.pop("nbody_number")
component_properties = external_results.pop("component_properties")
stdout = external_results.pop("stdout")


# load QCVariables
qcvars = {
Expand Down Expand Up @@ -852,6 +856,7 @@ def get_results(self, client: Optional["qcportal.FractalClient"] = None, externa
'qcvars': qcvars,
},
'return_result': ret_ptype,
"stdout": stdout,
'success': True,
})

Expand Down
Loading

0 comments on commit db63c16

Please sign in to comment.