11from __future__ import annotations
22from collections .abc import Iterable , Sequence
33import copy
4- from functools import lru_cache
4+ from functools import cache
55from pathlib import Path
66import math
77from numbers import Integral , Real
@@ -160,7 +160,7 @@ def is_initialized(self) -> bool:
160160 return False
161161
162162 @property
163- @lru_cache ( maxsize = None )
163+ @cache
164164 def _materials_by_id (self ) -> dict :
165165 """Dictionary mapping material ID --> material"""
166166 if self .materials :
@@ -170,14 +170,14 @@ def _materials_by_id(self) -> dict:
170170 return {mat .id : mat for mat in mats }
171171
172172 @property
173- @lru_cache ( maxsize = None )
173+ @cache
174174 def _cells_by_id (self ) -> dict :
175175 """Dictionary mapping cell ID --> cell"""
176176 cells = self .geometry .get_all_cells ()
177177 return {cell .id : cell for cell in cells .values ()}
178178
179179 @property
180- @lru_cache ( maxsize = None )
180+ @cache
181181 def _cells_by_name (self ) -> dict [int , openmc .Cell ]:
182182 # Get the names maps, but since names are not unique, store a set for
183183 # each name key. In this way when the user requests a change by a name,
@@ -190,7 +190,7 @@ def _cells_by_name(self) -> dict[int, openmc.Cell]:
190190 return result
191191
192192 @property
193- @lru_cache ( maxsize = None )
193+ @cache
194194 def _materials_by_name (self ) -> dict [int , openmc .Material ]:
195195 if self .materials is None :
196196 mats = self .geometry .get_all_materials ().values ()
@@ -203,6 +203,37 @@ def _materials_by_name(self) -> dict[int, openmc.Material]:
203203 result [mat .name ].add (mat )
204204 return result
205205
206+ def add_kinetics_parameters_tallies (self , num_groups : int | None = None ):
207+ """Add tallies for calculating kinetics parameters using the IFP method.
208+
209+ This method adds tallies to the model for calculating two kinetics
210+ parameters, the generation time and the effective delayed neutron
211+ fraction (beta effective). After a model is run, these parameters can be
212+ determined through the :meth:`openmc.StatePoint.ifp_results` method.
213+
214+ Parameters
215+ ----------
216+ num_groups : int, optional
217+ Number of precursor groups to filter the delayed neutron fraction.
218+ If None, only the total effective delayed neutron fraction is
219+ tallied.
220+
221+ """
222+ if not any ('ifp-time-numerator' in t .scores for t in self .tallies ):
223+ gen_time_tally = openmc .Tally (name = 'IFP time numerator' )
224+ gen_time_tally .scores = ['ifp-time-numerator' ]
225+ self .tallies .append (gen_time_tally )
226+ if not any ('ifp-beta-numerator' in t .scores for t in self .tallies ):
227+ beta_tally = openmc .Tally (name = 'IFP beta numerator' )
228+ beta_tally .scores = ['ifp-beta-numerator' ]
229+ if num_groups is not None :
230+ beta_tally .filters = [openmc .DelayedGroupFilter (list (range (1 , num_groups + 1 )))]
231+ self .tallies .append (beta_tally )
232+ if not any ('ifp-denominator' in t .scores for t in self .tallies ):
233+ denom_tally = openmc .Tally (name = 'IFP denominator' )
234+ denom_tally .scores = ['ifp-denominator' ]
235+ self .tallies .append (denom_tally )
236+
206237 @classmethod
207238 def from_xml (
208239 cls ,
0 commit comments