@@ -84,7 +84,12 @@ def get_microxs_and_flux(
8484 reactions listed in the depletion chain file are used.
8585 energies : iterable of float or str
8686 Energy group boundaries in [eV] or the name of the group structure.
87- If left as None energies will default to [0.0, 100e6]
87+ If left as None, no energy filter is applied to the flux tally. When
88+ `reaction_rate_mode` is "direct", these boundaries define the output
89+ flux and microscopic cross section energy group structure. When
90+ `reaction_rate_mode` is "flux", these boundaries define the multigroup
91+ flux tally used to collapse continuous-energy cross sections; returned
92+ fluxes and microscopic cross sections are one-group.
8893 reaction_rate_mode : {"direct", "flux"}, optional
8994 The "direct" method tallies reaction rates directly (per energy
9095 group). The "flux" method tallies a multigroup flux spectrum and then
@@ -110,7 +115,9 @@ def get_microxs_and_flux(
110115 reaction_rate_opts : dict, optional
111116 When `reaction_rate_mode="flux"`, allows selecting a subset of
112117 nuclide/reaction pairs to be computed via direct reaction-rate tallies
113- (per energy group). Supported keys: "nuclides", "reactions".
118+ over one energy bin spanning the full `energies` range. Supported keys:
119+ "nuclides", "reactions". If "reactions" are specified without
120+ "nuclides", all selected nuclides are used.
114121
115122 Returns
116123 -------
@@ -139,10 +146,14 @@ def get_microxs_and_flux(
139146 nuclides = [nuc .name for nuc in chain .nuclides
140147 if nuc .name in nuclides_with_data ]
141148
142- # Set up the reaction rate and flux tallies
149+ # Set up the reaction rate and flux tallies. When energies are omitted, no
150+ # energy filter is needed for the transport calculation. A one-group energy
151+ # range is still needed later if flux collapse is requested.
152+ collapse_energies = energies
143153 if energies is None :
144- energies = [0.0 , 100.0e6 ]
145- if isinstance (energies , str ):
154+ energy_filter = None
155+ collapse_energies = [0.0 , 100.0e6 ]
156+ elif isinstance (energies , str ):
146157 energy_filter = openmc .EnergyFilter .from_group_structure (energies )
147158 else :
148159 energy_filter = openmc .EnergyFilter (energies )
@@ -172,8 +183,11 @@ def get_microxs_and_flux(
172183 rr_reactions = list (reactions )
173184 elif reaction_rate_mode == 'flux' and reaction_rate_opts :
174185 opts = reaction_rate_opts or {}
175- rr_nuclides = list (opts .get ('nuclides' , []))
176186 rr_reactions = list (opts .get ('reactions' , []))
187+ if rr_reactions :
188+ rr_nuclides = list (opts .get ('nuclides' , nuclides ))
189+ else :
190+ rr_nuclides = list (opts .get ('nuclides' , []))
177191 # Keep only requested pairs within overall sets
178192 if rr_nuclides :
179193 rr_nuclides = [n for n in rr_nuclides if n in set (nuclides )]
@@ -182,7 +196,7 @@ def get_microxs_and_flux(
182196
183197 # Use 1-group energy filter for RR in flux mode
184198 has_rr = bool (rr_nuclides and rr_reactions )
185- if has_rr and reaction_rate_mode == 'flux' :
199+ if has_rr and reaction_rate_mode == 'flux' and energy_filter is not None :
186200 rr_energy_filter = openmc .EnergyFilter (
187201 [energy_filter .values [0 ], energy_filter .values [- 1 ]])
188202 else :
@@ -194,14 +208,18 @@ def get_microxs_and_flux(
194208 model .tallies = []
195209 for i , domain_filter in enumerate (domain_filters ):
196210 flux_tally = openmc .Tally (name = f'MicroXS flux { i } ' )
197- flux_tally .filters = [domain_filter , energy_filter ]
211+ flux_tally .filters = [domain_filter ]
212+ if energy_filter is not None :
213+ flux_tally .filters .append (energy_filter )
198214 flux_tally .scores = ['flux' ]
199215 model .tallies .append (flux_tally )
200216 flux_tallies .append (flux_tally )
201217
202218 if has_rr :
203219 rr_tally = openmc .Tally (name = f'MicroXS RR { i } ' )
204- rr_tally .filters = [domain_filter , rr_energy_filter ]
220+ rr_tally .filters = [domain_filter ]
221+ if rr_energy_filter is not None :
222+ rr_tally .filters .append (rr_energy_filter )
205223 rr_tally .nuclides = rr_nuclides
206224 rr_tally .multiply_density = False
207225 rr_tally .scores = rr_reactions
@@ -255,8 +273,12 @@ def get_microxs_and_flux(
255273 all_flux_arrays = []
256274 for flux_tally in flux_tallies :
257275 # Get flux values and make energy groups last dimension
258- flux = flux_tally .get_reshaped_data () # (domains, groups, 1, 1)
259- flux = np .moveaxis (flux , 1 , - 1 ) # (domains, 1, 1, groups)
276+ flux = flux_tally .get_reshaped_data ()
277+ if energy_filter is None :
278+ flux = flux [..., np .newaxis ] # (domains, 1, 1, groups)
279+ else :
280+ # (domains, groups, 1, 1) -> (domains, 1, 1, groups)
281+ flux = np .moveaxis (flux , 1 , - 1 )
260282 all_flux_arrays .append (flux )
261283 fluxes .extend (flux .squeeze ((1 , 2 )))
262284
@@ -266,8 +288,15 @@ def get_microxs_and_flux(
266288 for flux_arr , rr_tally in zip (all_flux_arrays , rr_tallies ):
267289 flux = flux_arr
268290 # Get reaction rates and make energy groups last dimension
269- reaction_rates = rr_tally .get_reshaped_data () # (domains, groups, nuclides, reactions)
270- reaction_rates = np .moveaxis (reaction_rates , 1 , - 1 ) # (domains, nuclides, reactions, groups)
291+ reaction_rates = rr_tally .get_reshaped_data ()
292+ if rr_energy_filter is None :
293+ # (domains, nuclides, reactions) ->
294+ # (domains, nuclides, reactions, groups)
295+ reaction_rates = reaction_rates [..., np .newaxis ]
296+ else :
297+ # (domains, groups, nuclides, reactions) ->
298+ # (domains, nuclides, reactions, groups)
299+ reaction_rates = np .moveaxis (reaction_rates , 1 , - 1 )
271300
272301 # If RR is 1-group, sum flux over groups
273302 if reaction_rate_mode == "flux" :
@@ -279,16 +308,20 @@ def get_microxs_and_flux(
279308 direct_micros .extend (
280309 MicroXS (xs_i , rr_nuclides , rr_reactions ) for xs_i in xs )
281310
282- # If using flux mode, compute flux-collapsed microscopic XS
283311 if reaction_rate_mode == 'flux' :
312+ # Compute flux-collapsed microscopic XS
284313 flux_micros = [MicroXS .from_multigroup_flux (
285- energies = energies ,
314+ energies = collapse_energies ,
286315 multigroup_flux = flux_i ,
287316 chain_file = chain_file ,
288317 nuclides = nuclides ,
289318 reactions = reactions
290319 ) for flux_i in fluxes ]
291320
321+ # We need to return one-group fluxes to match the microscopic cross
322+ # sections, which are always one-group by virtue of the collapse
323+ fluxes = [flux .sum (keepdims = True ) for flux in fluxes ]
324+
292325 # Decide which micros to use and merge if needed
293326 if reaction_rate_mode == 'flux' and rr_tallies :
294327 micros = [m1 .merge (m2 ) for m1 , m2 in zip (flux_micros , direct_micros )]
0 commit comments