77import tempfile
88from copy import deepcopy
99
10- from pandas import DataFrame , read_csv
10+ from pandas import DataFrame , read_csv , Series
1111import numpy as np
1212
1313from openmc .checkvalue import check_type , check_value , check_iterable_type
1414from openmc .exceptions import DataError
15- from openmc .mgxs import EnergyGroups , ArbitraryXS , FissionXS
16- from openmc import Tallies , StatePoint , Materials
15+ from openmc import StatePoint , Materials
1716import openmc
1817from .chain import Chain , REACTIONS
1918from .coupled_operator import _find_cross_sections , _get_nuclides_with_data
@@ -67,26 +66,36 @@ def from_model(cls,
6766 Cross section data in [b]
6867
6968 """
70- groups = EnergyGroups (energy_bounds )
71-
7269 # Set up the reaction tallies
7370 original_tallies = model .tallies
7471 original_materials = deepcopy (model .materials )
75- tallies = Tallies ()
7672 xs = {}
77- reactions , diluted_materials = cls ._add_dilute_nuclides (chain_file ,
78- model ,
79- dilute_initial )
73+ reactions , burnable_nucs , diluted_materials = cls ._add_dilute_nuclides (
74+ chain_file , model , dilute_initial )
8075 model .materials = diluted_materials
8176
82- for rx in reactions :
83- if rx == 'fission' :
84- xs [rx ] = FissionXS (domain = reaction_domain ,
85- energy_groups = groups , by_nuclide = True )
86- else :
87- xs [rx ] = ArbitraryXS (rx , domain = reaction_domain ,
88- energy_groups = groups , by_nuclide = True )
89- tallies += xs [rx ].tallies .values ()
77+ energy_filter = openmc .EnergyFilter (energy_bounds )
78+ if isinstance (reaction_domain , openmc .Material ):
79+ domain_filter = openmc .MaterialFilter ([reaction_domain ])
80+ elif isinstance (reaction_domain , openmc .Cell ):
81+ domain_filter = openmc .CellFilter ([reaction_domain ])
82+ elif isinstance (reaction_domain , openmc .Universe ):
83+ domain_filter = openmc .UniverseFilter ([reaction_domain ])
84+ else :
85+ raise ValueError (f"Unsupported domain type: { type (reaction_domain )} " )
86+
87+ # TODO: Right now, we use all nuclides from the material but it probably
88+ # should be based on the burnable nuclides
89+ rr_tally = openmc .Tally (name = 'MicroXS RR' )
90+ rr_tally .filters = [domain_filter , energy_filter ]
91+ rr_tally .nuclides = reaction_domain .get_nuclides ()
92+ rr_tally .multiply_density = False
93+ rr_tally .scores = reactions
94+
95+ flux_tally = openmc .Tally (name = 'MicroXS flux' )
96+ flux_tally .filters = [domain_filter , energy_filter ]
97+ flux_tally .scores = ['flux' ]
98+ tallies = openmc .Tallies ([rr_tally , flux_tally ])
9099
91100 model .tallies = tallies
92101
@@ -98,14 +107,22 @@ def from_model(cls,
98107 statepoint_path = model .run (** run_kwargs )
99108
100109 with StatePoint (statepoint_path ) as sp :
101- for rx in xs :
102- xs [rx ].load_from_statepoint (sp )
110+ rr_tally = sp .tallies [rr_tally .id ]
111+ rr_tally ._read_results ()
112+ flux_tally = sp .tallies [flux_tally .id ]
113+ flux_tally ._read_results ()
114+
115+ # Get reaction rates and flux values
116+ reaction_rates = rr_tally .mean .sum (axis = 0 ) # (nuclides, reactions)
117+ flux = flux_tally .mean [0 , 0 , 0 ]
118+
119+ # Divide RR by flux to get microscopic cross sections
120+ xs = reaction_rates / flux
103121
104- # Build the DataFrame
122+ # Build Series objects
105123 series = {}
106- for rx in xs :
107- df = xs [rx ].get_pandas_dataframe (xs_type = 'micro' )
108- series [rx ] = df .set_index ('nuclide' )['mean' ]
124+ for i , rx in enumerate (reactions ):
125+ series [rx ] = Series (xs [..., i ], index = rr_tally .nuclides )
109126
110127 # Revert to the original tallies and materials
111128 model .tallies = original_tallies
@@ -170,7 +187,7 @@ def _add_dilute_nuclides(cls, chain_file, model, dilute_initial):
170187 dilute_density )
171188 diluted_materials .append (material )
172189
173- return reactions , diluted_materials
190+ return reactions , burnable_nucs , diluted_materials
174191
175192 @classmethod
176193 def from_array (cls , nuclides , reactions , data ):
0 commit comments