diff --git a/openmc/data/data.py b/openmc/data/data.py index 8c0ed63728..45a4406dbe 100644 --- a/openmc/data/data.py +++ b/openmc/data/data.py @@ -216,10 +216,9 @@ def water_density(temperature, pressure=0.1013): The density is calculated from a polynomial fit using equations and values from the 2012 version of the IAPWS-IF97 formulation. Only the equations - for region 1 are implemented here. - - Results are invalid for water vapor; pressures above 100 [MPa]; and - temperatures below 273.15 [K], above 623.15 [K], or above saturation. + for region 1 are implemented here. Region 1 is limited to liquid water + below 100 [MPa] with a temperature above 273.15 [K], below 623.15 [K], and + below saturation. Reference: International Association for the Properties of Water and Steam, "Revised Release on the IAPWS Industrial Formulation 1997 for the diff --git a/openmc/material.py b/openmc/material.py index 32b7d3a80d..e409d6536c 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -973,73 +973,3 @@ class Materials(cv.CheckedList): # Write the XML Tree to the materials.xml file tree = ET.ElementTree(root_element) tree.write(path, xml_declaration=True, encoding='utf-8') - - -def make_boric_acid(boron_ppm, temperature=293., pressure=0.1013, density=None, - **kwargs): - """Return a Material with the composition of boric acid. - - The water density can either be given directly, or it can be determined from - a temperature and pressure. - - Parameters - ---------- - boron_ppm : float - The weight fraction in parts-per-million of elemental boron in the acid. - temperature : float - Water temperature in [K] used to compute water density. - pressure : float - Water pressure in [MPa] used to compute water density. - density : float - Water density in [g / cm^3]. If specified, this value overrides the - temperature and pressure arguments. - **kwargs - All keyword arguments are passed to the created Material object. - - Returns - ------- - openmc.Material - - """ - # Set the density of water, either from an explicitly given density or from - # temperature and pressure. - if density is not None: - water_density = density - else: - water_density = openmc.data.water_density(temperature, pressure) - - # Compute the density of the boric acid. - acid_density = water_density / (1 - boron_ppm * 1e-6) - - # Compute the molar mass of pure water. - hydrogen = openmc.Element('H') - oxygen = openmc.Element('O') - M_H2O = 0.0 - for iso_name, frac, junk in hydrogen.expand(2.0, 'ao'): - M_H2O += frac * openmc.data.atomic_mass(iso_name) - for iso_name, frac, junk in oxygen.expand(1.0, 'ao'): - M_H2O += frac * openmc.data.atomic_mass(iso_name) - - # Compute the molar mass of boron. - boron = openmc.Element('B') - M_B = 0.0 - for iso_name, frac, junk in boron.expand(1.0, 'ao'): - M_B += frac * openmc.data.atomic_mass(iso_name) - - # Compute the number fractions of each element. - frac_H2O = (1 - boron_ppm * 1e-6) / M_H2O - frac_H = 2 * frac_H2O - frac_O = frac_H2O - frac_B = boron_ppm * 1e-6 / M_B - - # Build the material. - if density is None: - out = openmc.Material(temperature=temperature, **kwargs) - else: - out = openmc.Material(**kwargs) - out.add_element('H', frac_H, 'ao') - out.add_element('O', frac_O, 'ao') - out.add_element('B', frac_B, 'ao') - out.set_density('g/cc', acid_density) - out.add_s_alpha_beta('c_H_in_H2O') - return out diff --git a/openmc/model/funcs.py b/openmc/model/funcs.py index 6013f6caee..b8984ada03 100644 --- a/openmc/model/funcs.py +++ b/openmc/model/funcs.py @@ -5,6 +5,7 @@ from numbers import Real from openmc import XPlane, YPlane, Plane, ZCylinder from openmc.checkvalue import check_type, check_value +import openmc.data def get_rectangular_prism(width, height, axis='z', origin=(0., 0.), @@ -252,6 +253,100 @@ def get_hexagonal_prism(edge_length=1., orientation='y', origin=(0., 0.), return prism +def make_borated_water(boron_ppm, temperature=293., pressure=0.1013, + temp_unit='K', press_unit='MPa', density=None, **kwargs): + """Return a Material with the composition of boron dissolved in water. + + The water density can be determined from a temperature and pressure, or it + can be set directly. + + The concentration of boron has no effect on the stoichometric ratio of H + and O---they are fixed at 2-1. + + Parameters + ---------- + boron_ppm : float + The weight fraction in parts-per-million of elemental boron in the + water. + temperature : float + Temperature in [K] used to compute water density. + pressure : float + Pressure in [MPa] used to compute water density. + temp_unit : str + The units used for the `temperature` argument. Valid units are 'K', + 'C', and 'F'. + press_unit : str + The units used for the `pressure` argument. Valid units are 'MPa' and + 'psi'. + density : float + Water density in [g / cm^3]. If specified, this value overrides the + temperature and pressure arguments. + **kwargs + All keyword arguments are passed to the created Material object. + + Returns + ------- + openmc.Material + + """ + # Perform any necessary unit conversions. + check_value('temperature unit', temp_unit, ('K', 'C', 'F')) + if temp_unit == 'K': + T = temperature + elif temp_unit == 'C': + T = temperature + 273.15 + elif temp_unit == 'F': + T = (temperature + 459.67) * 5.0 / 9.0 + check_value('pressure unit', press_unit, ('MPa', 'psi')) + if press_unit == 'MPa': + P = pressure + elif press_unit == 'psi': + P = pressure * 0.006895 + + # Set the density of water, either from an explicitly given density or from + # temperature and pressure. + if density is not None: + water_density = density + else: + water_density = openmc.data.water_density(T, P) + + # Compute the density of the solution. + solution_density = water_density / (1 - boron_ppm * 1e-6) + + # Compute the molar mass of pure water. + hydrogen = openmc.Element('H') + oxygen = openmc.Element('O') + M_H2O = 0.0 + for iso_name, frac, junk in hydrogen.expand(2.0, 'ao'): + M_H2O += frac * openmc.data.atomic_mass(iso_name) + for iso_name, frac, junk in oxygen.expand(1.0, 'ao'): + M_H2O += frac * openmc.data.atomic_mass(iso_name) + + # Compute the molar mass of boron. + boron = openmc.Element('B') + M_B = 0.0 + for iso_name, frac, junk in boron.expand(1.0, 'ao'): + M_B += frac * openmc.data.atomic_mass(iso_name) + + # Compute the number fractions of each element. + frac_H2O = (1 - boron_ppm * 1e-6) / M_H2O + frac_H = 2 * frac_H2O + frac_O = frac_H2O + frac_B = boron_ppm * 1e-6 / M_B + + # Build the material. + if density is None: + out = openmc.Material(temperature=T, **kwargs) + else: + out = openmc.Material(**kwargs) + out.add_element('H', frac_H, 'ao') + out.add_element('O', frac_O, 'ao') + out.add_element('B', frac_B, 'ao') + out.set_density('g/cc', solution_density) + out.add_s_alpha_beta('c_H_in_H2O') + return out + + def subdivide(surfaces): """Create regions separated by a series of surfaces. diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index 38495cb1ab..295153a9c1 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -141,9 +141,9 @@ def test_materials(run_in_tmpdir): mats.export_to_xml() -def test_boric_acid(): +def test_borated_water(): # Test against reference values from the BEAVRS benchmark. - m = openmc.make_boric_acid(975, 566.5, 15.51, material_id=50) + m = openmc.model.make_borated_water(975, 566.5, 15.51, material_id=50) assert m.density == pytest.approx(0.7405, 1e-3) assert m.temperature == pytest.approx(566.5) assert m._sab[0][0] == 'c_H_in_H2O' @@ -154,6 +154,14 @@ def test_boric_acid(): assert nuc_dens[nuclide][1] == pytest.approx(ref_dens[nuclide], 1e-2) assert m.id == 50 - # Make sure the density override works - m = openmc.make_boric_acid(975, 566.5, 15.51, 0.9) + # Test the Celsius conversion. + m = openmc.model.make_borated_water(975, 293.35, 15.51, 'C') + assert m.density == pytest.approx(0.7405, 1e-3) + + # Test Fahrenheit and psi conversions. + m = openmc.model.make_borated_water(975, 560.0, 2250.0, 'F', 'psi') + assert m.density == pytest.approx(0.7405, 1e-3) + + # Test the density override + m = openmc.model.make_borated_water(975, 566.5, 15.51, density=0.9) assert m.density == pytest.approx(0.9, 1e-3)