Skip to content

Add PNNL material composition library - #4134

Open
paulromano wants to merge 13 commits into
openmc-dev:developfrom
paulromano:pnnl-material-library
Open

paulromano wants to merge 13 commits into
openmc-dev:developfrom
paulromano:pnnl-material-library

Conversation

@paulromano

Copy link
Copy Markdown
Contributor

Description

This PR builds on and supersedes #2105 (many thanks to @shimwell for his work on that!), adding the material compositions from the PNNL Compendium of Material Composition Data for Radiation Transport Modeling accessible through a new from_library classmethod on the Material class. For example:

salt_water = openmc.Material.from_library('Salt Water')

The library contains 411 materials and is stored as a compact JSON file rather than an OpenMC XML file. Most compositions are recorded by element and are expanded through Material.add_element, so the selected natural isotopes are compatible with the user's active cross-section library. This avoids failures such as requesting O18 from a library that does not provide it.

The compendium also defines isotope-specific compositions that cannot be represented faithfully as natural elements. The implementation therefore uses a hybrid policy: natural elements remain elemental, while explicitly specified isotopes are retained for the 45 affected materials. Of those materials, 29 combine natural and isotope-specific elements and 16 are entirely isotope-specific.

Data sources

The original source for the values in this PR is the machine-readable PNNL compendium JSON (siteVersion 0.1.1), obtained from a pinned revision of the PyNE materials-compendium mirror. The generated OpenMC JSON records the source URL, revision, site version, and checksum so that its provenance is preserved and the conversion is reproducible. I'm planning on submitting a separate PR to the data repo with the conversion script so as not to pollute the main repo here. The associated human-readable reference is PNNL-15870 Rev. 2, Compendium of Material Composition Data for Radiation Transport Modeling. The compendium website is supposed to be https://compendium.cwmd.pnnl.gov, but that URL doesn't seem to work at present.

Comparison with PNNL-15870 Rev. 2

The PDF comparison was performed systematically by locating all 411 numbered material sections and extracting each density and elemental atom-fraction table. It independently identified the same 45 isotope-specific materials as the JSON. Exact numeric comparison found the following differences:

Comparison Result
Densities 20 exact differences: 19 are consistent with displayed rounding; LYSO differs substantively (7.3 g/cm³ in JSON and 7.25 g/cm³ in the PDF).
Elemental atom fractions 96 exact differences: 93 are final-digit/display-rounding differences and 3 materials differ substantively, as detailed below.
Explicit isotope fractions All 51 isotope-specific elemental components match.

The substantive material differences are:

Material PNNL JSON Rev. 2 PDF Treatment in this PR
Iron Boride (Fe2B) B = 1/3, Fe = 2/3 The elemental table reverses the B and Fe fractions. Keep the JSON values; they agree with the stated Fe2B formula.
LYSO Density 7.3 g/cm³; O = 0.5, Si = 0.1, Y = 0.2, Lu = 0.2; no Ce Density 7.25 g/cm³; O = 0.621875, Si = 0.124375, Y = 0.012438, Lu = 0.236313, Ce = 0.005 Keep the JSON values, including its omission of Ce, because JSON is the designated source of record.
Stainless Steel 304L A distinct 304L elemental composition The PDF table appears to repeat the Stainless Steel 304 composition. Keep the distinct JSON 304L composition.

Other observed differences are consistent with the PDF displaying fewer digits. For example, the JSON densities for Salt Water are 1.2098648484824486 at 0 degrees C and 1.0223941310230285 at 20 degrees C, whereas the PDF displays 1.209865 and 1.022394, respectively. No PDF-based corrections or overrides are applied by this PR.

Checklist

  • I have performed a self-review of my own code
  • I have run clang-format (version 18) on any C++ source files (if applicable)
  • I have followed the style guidelines for Python source files (if applicable)
  • I have made corresponding changes to the documentation (if applicable)
  • I have added tests that prove my fix is effective or that my feature works (if applicable)

@paulromano
paulromano requested a review from shimwell September 15, 2026 21:54
@shimwell

Copy link
Copy Markdown
Member

Super to see this made my day. I forget what the original blocker for that old PR was but I have now closed it. Perhaps we were planning to add some element expansion the the CPP side. Perhaps that is no longer needed.

Does anyone know if we can suggests the bugs fixes upstream. I think PNNL material compendium is now fairly popular in codes and I worry different fixes are applied.

@shimwell shimwell self-assigned this Sep 16, 2026
Comment on lines +2058 to +2061
"O": 0.5,
"Si": 0.1,
"Y": 0.2,
"Lu": 0.2

@shimwell shimwell Sep 16, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Page 168 of https://www.osti.gov/servlets/purl/1782721/ has the Ce included and different numbers for this entry and I can see the idea to use the json as the source of truth but this one is really wrong. Even the name mentions '0.5 atom% Cerium' but it has no Cerium in the current definition. Perhaps best to fix it upstream by emailing pnnl authors and asking for an updated json, or not include it

Suggested change
"O": 0.5,
"Si": 0.1,
"Y": 0.2,
"Lu": 0.2
"O": 0.621875,
"Si": 0.124375,
"Y": 0.012438,
"Lu": 0.236313,
"Ce": 0.005

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This case is discussed in the PR description. Generally, I've picked the JSON file to be ground "truth" because in the other cases of discrepancies, the PDF appears to be wrong and the JSON file right. However, looking into this LYSO material a bit, it is a scintillation material that is only effective when doped with Ce, so I think having the version that includes Ce is the correct thing to do. I'll get this updated.

Comment thread openmc/data/material_libraries/pnnl_v2.json Outdated
@shimwell

Copy link
Copy Markdown
Member

Ideas for a follow up PR, give the users some way to search the collection without going to the source code

@shimwell

Copy link
Copy Markdown
Member

Ok I have another idea about the materials that are different in the pdf and the json. How about they print out a small warning to users saying this material is defined differently in the official json and pdf please check your resulting composition

@paulromano

Copy link
Copy Markdown
Contributor Author

The differences in Fe2B and SS304L are, in my opinion, pretty clearly errors in the PDF. The only questionable case was LYSO, but based on my previous comment, it now seems clear that the PDF version should be preferred. So, I don't see a strong motivation to show a warning to the user if we believe we are giving them the correct composition. I agree though we should try to report this to the PNNL authors.

@shimwell

Copy link
Copy Markdown
Member

ok yes so if this PR can be updated to use the pdf LYSO then it is all good to go IMO

@paulromano

Copy link
Copy Markdown
Contributor Author

@shimwell I just made a few updates:

  • Switched LYSO to use PDF composition
  • Added a Material.get_library_material_names() method for getting the names of available materials
  • Added a Material.register_library() method for registering a user's custom library as a JSON file

Let me know if you have any thoughts!

@GuySten

GuySten commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

Checking pnnl_v2.json against PNNL-15870 Rev. 2, eight material names differ from the report by whitespace: the report's headings contain double spaces that the library collapses to one.

  • Glass Scintillator, Li Doped (GS1, GS2, GS3) and the GS10/GSF1/KG1 variants (4 materials)
  • Lutetium Yttrium OxyorthoSilicate: 0.5 atom% Cerium (LYSO)
  • Radiochromic Dye Film, Nylon Base (RDF: NB)
  • Tissue Equivalent-Gas, methane based (TEG: MB) and ... propane based (TEG: PB)

Since from_library matches keys exactly, a name copied out of the report fails:

openmc.Material.from_library('Lutetium Yttrium OxyorthoSilicate:  0.5 atom% Cerium (LYSO)')
# KeyError / "not found in library"

The docs point users at the compendium and say names are case sensitive, so copy-paste from the PDF is the expected workflow, and the failure gives no hint that the only problem is a doubled space.

Suggestion: normalize whitespace on lookup — ' '.join(name.split()) applied to both the stored keys and the queried name — keeping the stored keys and get_library_material_names() output as they are. That fixes all eight without changing the data or the public name list.

@paulromano

Copy link
Copy Markdown
Contributor Author

Good suggestion @GuySten. I've just implemented that

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants