') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); Add Serpent depletion conversion script by drewejohnson · Pull Request #19 · openmc-dev/data · GitHub
Skip to content

Add Serpent depletion conversion script - #19

Closed
drewejohnson wants to merge 2 commits into
openmc-dev:masterfrom
drewejohnson:serpent-chain
Closed

Add Serpent depletion conversion script#19
drewejohnson wants to merge 2 commits into
openmc-dev:masterfrom
drewejohnson:serpent-chain

Conversation

@drewejohnson

Copy link
Copy Markdown
Contributor

Creates an equivalent depletion chain using decay and fission yield files distributed with Serpent. Some steps are taken to clean up and fix a few issues. The fixes are detailed in the script and here for completeness.

First, the files appear to be ENDF-6 formatted files concatenated together. Unfortunately, there is a TEND record after each dataset, so :func:openmc.data.endf.get_evaluations will only read and return the first evaluation. For this reason, we must read the file until all records have been found manually.

Secondly, the decay file does not have a tape indent (TPID) record, which can throw off the first reading. This exception can be caught, but it currently involves skipping the first item in the file. At the time of this writing, this skipped item contains the decay data for a
neutron.

Lastly, there is a single negative uncertainty in the Co-55 k-shell conversion energies. This quantity is not used in the depletion chain, but it must be altered to prevent downstream failures.

Supports reading in an additional chain file and applying branching ratios prior to exiting.

Postscript

I am very open to suggestions on this. I tried making a fake decay file with a blank line at the top to get around
https://github.com/openmc-dev/openmc/blob/3f5373c71bd8331a18c61637214fb2372dcd47b3/openmc/data/endf.py#L408-L413
with out a lot of success.

Post-postscript

Also, the code is formatted with black which explains some of the lines with just closing parenthesis or single-argument lines.

shimwelland others added 2 commits January 19, 2020 21:41
Creates an equivalent depletion chain using decay and fission yield
files distributed with Serpent. Some steps are taken to clean up and
fix a few issues. The fixes are detailed in the script and here for
completeness.
First, the files appear to be ENDF-6 formatted files concatenated
together. Unfortunately, there is a TEND record after each dataset,
so :func:`openmc.data.endf.get_evaluations` will only read and return
the first evaluation. For this reason, we must read the file until
all records have been found manually.
Secondly, the decay file does not have a tape indent (TPID) record,
which can throw off the first reading. This exception can be caught,
but it currently involves skipping the first item in the file. At the
time of this writing, this skipped item contains the decay data for a
neutron.
Lastly, there is a single negative uncertainty in the Co-55 k-shell
conversion energies. This quantity is not used in the depletion chain,
but it must be altered to prevent downstream failures.
Supports reading in an additional chain file and applying branching
ratios prior to exiting.

@paulromanopaulromano left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

So the Serpent files sss_endfb7.dec and sss_endfb7.nfy are just directly from ENDF/B-VII.0. In the case of the decay file, it's literally byte for byte the same. For the fission yields, ENDF/B-VII.0 gives as separate files; the Serpent version just concatenates them (running cat *.endf > sss_endfb7.nfy gives a file with the exact same size as the actual one). So, I think it would be more appropriate to call this script generate_endfb70_chain.py, and have it download the decay/fission yield sublibraries as some of the other scripts do. It looks like the original neutron data distributed with Serpent is also from ENDF/B-VII.0, so this script could get that data as well. I'm not sure what the difference would be between that and using ENDF/B-VII.1 data.

if ev.gnd_name == "Co55":
# Fix negative uncertainty
sec = ev.section[8, 457]
ev.section[8, 457] = "0".join([sec[:762], sec[764:]])

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I believe this should be

Suggested change
ev.section[8, 457] ="0".join([sec[:762], sec[764:]])
ev.section[8, 457] ="0".join([sec[:762], sec[764:]])

no?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Sure enough, there is a space in your comment as well. I was a little confused why a character was missing. Will fix that in the next iteration

raise NotADirectoryError(neutron_dir)

if args.output.exists() and not args.output.is_file():
raise IOError(f"{args.output} exists but is not a file")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

IOError no longer exists (if you go to a Python prompt and type IOError, it will give you OSError)

Suggested change
raiseIOError(f"{args.output} exists but is not a file")
raiseOSError(f"{args.output} exists but is not a file")

@drewejohnson

Copy link
Copy Markdown
ContributorAuthor

I think we could go about it two ways that would be, as you pointed out, identical. If the user wants to use the same files as provided by Serpent without the download, I think that should be supported. Alternatively, downloading the files also makes sense, as the data are identical. If anything, downloading the separate files would make processing the fission yield files less of a hackworkaround.

Would it make sense to :

  1. accept a decay file, downloading ENDF/B-VII.0 data if not given, and
  2. accept a fission yield file, downloading ENDF/B-VII.0 data if not given

I do think using the same neutron data as Serpent would be more consistent. What do you think about downloading the ENDF/B-VII.0 neutron data if the neutron_dir argument is not provided?

@paulromano

Copy link
Copy Markdown
Contributor

Yeah, I think just downloading the decay/fission product libraries is cleaner and avoids the TPID issue. I'm fine having the script download the VII.0 neutron data.

A contrarian viewpoint -- instead of providing a way for users to use old/bad/wrong data in OpenMC, why don't we tell them to use ENDF/B-VII.1 decay/fission product libraries in Serpent if they really want to compare? Having just gone through this myself, it really is as simple as just concatenating the ENDF files and telling Serpent where to find them.

@drewejohnson

Copy link
Copy Markdown
ContributorAuthor

Closing this in favor of the general script proposed in #23

Sign up for freeto 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

@drewejohnson@paulromano@shimwell