1+ from pathlib import Path
2+
3+ import h5py
4+ import pytest
5+
16import openmc
7+ import openmc .lib
28import openmc .stats
39
410
511def test_export_to_xml (run_in_tmpdir ):
12+
13+ tmp_properties_file = 'properties_test.h5'
14+
615 s = openmc .Settings (run_mode = 'fixed source' , batches = 1000 , seed = 17 )
716 s .generations_per_batch = 10
817 s .inactive = 100
@@ -22,7 +31,7 @@ def test_export_to_xml(run_in_tmpdir):
2231 s .surf_source_read = {'path' : 'surface_source_1.h5' }
2332 s .surf_source_write = {'surface_ids' : [2 ], 'max_particles' : 200 }
2433 s .surface_grazing_ratio = 0.7
25- s .surface_grazing_cutoff = 0.1
34+ s .surface_grazing_cutoff = 0.1
2635 s .confidence_intervals = True
2736 s .ptables = True
2837 s .plot_seed = 100
@@ -45,6 +54,7 @@ def test_export_to_xml(run_in_tmpdir):
4554 s .tabular_legendre = {'enable' : True , 'num_points' : 50 }
4655 s .temperature = {'default' : 293.6 , 'method' : 'interpolation' ,
4756 'multipole' : True , 'range' : (200. , 1000. )}
57+ s .properties_file = tmp_properties_file
4858 s .trace = (10 , 1 , 20 )
4959 s .track = [(1 , 1 , 1 ), (2 , 1 , 1 )]
5060 s .ufs_mesh = mesh
@@ -88,6 +98,7 @@ def test_export_to_xml(run_in_tmpdir):
8898 # Make sure exporting XML works
8999 s .export_to_xml ()
90100
101+
91102 # Generate settings from XML
92103 s = openmc .Settings .from_xml ()
93104 assert s .run_mode == 'fixed source'
@@ -111,7 +122,7 @@ def test_export_to_xml(run_in_tmpdir):
111122 assert s .surf_source_read ['path' ].name == 'surface_source_1.h5'
112123 assert s .surf_source_write == {'surface_ids' : [2 ], 'max_particles' : 200 }
113124 assert s .surface_grazing_ratio == 0.7
114- assert s .surface_grazing_cutoff == 0.1
125+ assert s .surface_grazing_cutoff == 0.1
115126 assert s .confidence_intervals
116127 assert s .ptables
117128 assert s .plot_seed == 100
@@ -134,6 +145,7 @@ def test_export_to_xml(run_in_tmpdir):
134145 assert s .tabular_legendre == {'enable' : True , 'num_points' : 50 }
135146 assert s .temperature == {'default' : 293.6 , 'method' : 'interpolation' ,
136147 'multipole' : True , 'range' : [200. , 1000. ]}
148+ assert s .properties_file == Path (tmp_properties_file )
137149 assert s .trace == [10 , 1 , 20 ]
138150 assert s .track == [(1 , 1 , 1 ), (2 , 1 , 1 )]
139151 assert isinstance (s .ufs_mesh , openmc .RegularMesh )
@@ -178,3 +190,59 @@ def test_export_to_xml(run_in_tmpdir):
178190 assert s .max_secondaries == 1_000_000
179191 assert s .source_rejection_fraction == 0.01
180192 assert s .free_gas_threshold == 800.0
193+
194+
195+ def test_properties_file_load (tmp_path , mpi_intracomm ):
196+ model = openmc .examples .pwr_assembly ()
197+
198+ # Session 1: export a structurally valid properties file via the C++ API,
199+ # then collect the cell/material structure so we can patch it with h5py.
200+ cell_instances = {} # {cell_id: n_instances} — material cells only
201+ mat_densities = {} # {mat_id: original atom/b-cm density}
202+
203+ props_path = tmp_path / 'properties.h5'
204+ with openmc .lib .TemporarySession (model , intracomm = mpi_intracomm ):
205+ openmc .lib .export_properties (str (props_path ))
206+ for cell_id , cell in openmc .lib .cells .items ():
207+ try :
208+ cell .fill # raises NotImplementedError for non-material cells
209+ cell_instances [cell_id ] = cell .num_instances
210+ except NotImplementedError :
211+ pass
212+ for mat_id , mat in openmc .lib .materials .items ():
213+ mat_densities [mat_id ] = mat .get_density ('atom/b-cm' )
214+
215+ assert any (n > 1 for n in cell_instances .values ())
216+
217+ # Patch the exported properties file overwriting temperatures
218+ # with per-instance values and scale material atom densities.
219+ density_factor = 0.75
220+ with h5py .File (props_path , 'r+' ) as f :
221+ cells_grp = f ['geometry/cells' ]
222+ for cell_id , n in cell_instances .items ():
223+ cell_grp = cells_grp [f'cell { cell_id } ' ]
224+ del cell_grp ['temperature' ]
225+ cell_grp .create_dataset (
226+ 'temperature' , data = [500.0 + 5.0 * i for i in range (n )]
227+ )
228+
229+ for mat_id , orig_density in mat_densities .items ():
230+ f ['materials' ][f'material { mat_id } ' ].attrs ['atom_density' ] = \
231+ orig_density * density_factor
232+
233+ # now apply the newly patched properties file using the settings
234+ # and load the model again, checking that the new temperature and
235+ # density values match those in the new file
236+ model .settings .properties_file = props_path
237+
238+ with openmc .lib .TemporarySession (model , intracomm = mpi_intracomm ):
239+ for cell_id , n in cell_instances .items ():
240+ cell = openmc .lib .cells [cell_id ]
241+ for i in range (n ):
242+ assert cell .get_temperature (i ) == pytest .approx (500.0 + 5.0 * i )
243+
244+ for mat_id , orig_density in mat_densities .items ():
245+ mat = openmc .lib .materials [mat_id ]
246+ assert mat .get_density ('atom/b-cm' ) == pytest .approx (
247+ orig_density * density_factor , rel = 1e-5
248+ )
0 commit comments