diff --git a/src/rxn_network/reactions/computed.py b/src/rxn_network/reactions/computed.py
index 6e98fc9b..6c5df92e 100644
--- a/src/rxn_network/reactions/computed.py
+++ b/src/rxn_network/reactions/computed.py
@@ -78,14 +78,21 @@ def balance(
lowest_num_errors=lowest_num_errors,
)
- def get_new_temperature(self, new_temperature: float) -> ComputedReaction:
+ def get_new_temperature(
+ self, new_temperature: float, entries_at_temp: dict[Composition, ComputedEntry] = None
+ ) -> ComputedReaction:
"""Returns a new reaction with the temperature changed.
Args:
new_temperature: New temperature in Kelvin
+ entries_at_temp: A map of precomputed entries to draw from when recalculating this
+ entry at a new temperature
"""
try:
- new_entries = [e.get_new_temperature(new_temperature) for e in self.entries]
+ if entries_at_temp is None:
+ new_entries = [e.get_new_temperature(new_temperature) for e in self.entries]
+ else:
+ new_entries = [entries_at_temp.get(e.composition) for e in self.entries]
except AttributeError as e:
raise AttributeError(
"One or more of the entries in the reaction is not associated with a"
diff --git a/src/rxn_network/reactions/open.py b/src/rxn_network/reactions/open.py
index 93ee1a09..70c8e5d2 100644
--- a/src/rxn_network/reactions/open.py
+++ b/src/rxn_network/reactions/open.py
@@ -104,21 +104,26 @@ def balance( # type: ignore
return ComputedReaction(**kwargs) if not chempots else cls(chempots=chempots, **kwargs)
- def get_new_temperature(self, new_temperature: float) -> OpenComputedReaction:
+ def get_new_temperature(self, new_temperature: float, entries_at_temp: dict | None) -> OpenComputedReaction:
"""Returns a new reaction with the temperature changed.
Args:
new_temperature: New temperature in Kelvin
+ entries_at_temp: A dictionary mapping entry compositions to Entry objects with energies
+ computed at the new temperature. Use this to avoid recomputing entries if you are
+ applying this method to many reactions.
"""
try:
- new_entries = [e.get_new_temperature(new_temperature) for e in self.entries]
+ if entries_at_temp is None:
+ new_entries = [e.get_new_temperature(new_temperature) for e in self.entries]
+ else:
+ new_entries = [entries_at_temp.get(e.composition) for e in self.entries]
except AttributeError as e:
raise AttributeError(
"One or more of the entries in the reaction is not associated with a"
" temperature. Please use the GibbsComputedEntry class for all entries"
" in the reaction."
) from e
-
return OpenComputedReaction(
new_entries,
self.coefficients,
diff --git a/src/rxn_network/reactions/plotting.py b/src/rxn_network/reactions/plotting.py
index 0fc31417..f14c22ea 100644
--- a/src/rxn_network/reactions/plotting.py
+++ b/src/rxn_network/reactions/plotting.py
@@ -145,17 +145,7 @@ def get_label_and_units(name):
if plot_pareto:
fig.add_trace(scatter)
- hovertemplate = (
- "%{hovertext}
"
- "
"
- f"{x}"
- ": %{x:.3f}"
- f" {x_units}"
- "
"
- f"{y}"
- ": %{y:.3f}"
- f" {y_units}"
- )
+ hovertemplate = f"%{{hovertext}}
{x}: %{{x:.3f}} {x_units}
{y}: %{{y:.3f}} {y_units}"
if z is not None:
hovertemplate = hovertemplate + "
" + f"{z}" + ": %{z:.3f}" + f" {z_units}
"
diff --git a/src/rxn_network/reactions/reaction_set.py b/src/rxn_network/reactions/reaction_set.py
index 81099ef8..a8ef34e1 100644
--- a/src/rxn_network/reactions/reaction_set.py
+++ b/src/rxn_network/reactions/reaction_set.py
@@ -540,11 +540,35 @@ def set_new_temperature(self, new_temp: float) -> ReactionSet:
The new ReactionSet containing the recalculated reactions.
"""
new_rxns = []
- for rxn in self.get_rxns():
- new_rxns.append(rxn.get_new_temperature(new_temp))
+ entries = {e.composition: e.get_new_temperature(new_temp) for e in self.entries}
+ for rxn in tqdm(list(self.get_rxns())):
+ new_rxns.append(rxn.get_new_temperature(new_temp, entries))
return ReactionSet.from_rxns(new_rxns, open_elem=self.open_elem, chempot=self.chempot)
+ def compute_at_temperatures(self, temp_list: list[int]) -> dict[int, ReactionSet]:
+ """Recomputes reaction energies at each temperature in a list of temperatures.
+
+ Args:
+ temp_list : List[int]
+ The list of temperatures at which new `ReactionSet`s should be generated.``
+
+ Returns:
+ Dict[int, ReactionSet]
+ A mapping of temperature to `ReactionSet` with reaction energies computed at
+ that temperature.
+ """
+ all_rxns = list(self.get_rxns())
+ result = {}
+ for t in tqdm(temp_list, desc="Computing reaction energies..."):
+ new_rxns = []
+ entries = {e.composition: e.get_new_temperature(t) for e in self.entries}
+ for rxn in all_rxns:
+ new_rxns.append(rxn.get_new_temperature(t, entries))
+
+ result[t] = ReactionSet.from_rxns(new_rxns, open_elem=self.open_elem, chempot=self.chempot)
+ return result
+
def _get_rxns_by_indices(self, idxs) -> Iterable[ComputedReaction | OpenComputedReaction]:
"""Return a list of reactions with the given indices."""
for size, idx_arr in idxs.items():