-
Notifications
You must be signed in to change notification settings - Fork 596
Add derivative tally based k_eff search support for material perturbations #3690
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
pranavkantgaur
wants to merge
16
commits into
openmc-dev:develop
Choose a base branch
from
pranavkantgaur:980_k_search_tally_dervs
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+1,292
−15
Open
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
24e1c13
add grsecant changes and test script with copilot
pranavkantgaur 9bd6b03
revert synthetic points and add derivative constraints copilot
pranavkantgaur 61440e1
add fixes for derivative scaling
pranavkantgaur dfeff9b
add gradient descent
pranavkantgaur 316012a
add geom search test, uncertainity weighing in GD
pranavkantgaur 02a3aa2
add flag for deriv uncertainity
pranavkantgaur a39c80c
add flag for off derv. uncertainity only but not derivatives
pranavkantgaur 1111ee9
Merge branch 'openmc-dev:develop' into 980_k_search_tally_dervs
pranavkantgaur 8ed9137
remove GD and add tests
pranavkantgaur 7068d64
remove derivative feature flags
pranavkantgaur a9234bb
Added unit tests for tally derivatives extension in keff_search
mvineetmenon 797f9b9
move tally obj. instantiation to model class
pranavkantgaur 31fc281
move compare script to examples dir
pranavkantgaur a715325
Merge branch 'openmc-dev:develop' into 980_k_search_tally_dervs
pranavkantgaur 7922510
update test assertions, model creation and file rename
pranavkantgaur 1cdd179
update comments
pranavkantgaur File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,211 @@ | ||
| # keff_search with Derivative Tallies | ||
|
|
||
| This example demonstrates the derivative-accelerated k-effective search capability in OpenMC, which uses gradient information from derivative tallies to significantly speed up convergence during criticality searches. | ||
|
|
||
| ## Overview | ||
|
|
||
| The `Model.keff_search()` method can leverage derivative tallies to compute sensitivities (dk/dx) with respect to material properties, enabling faster and more robust convergence compared to traditional derivative-free methods. This feature is inspired by the methodology developed by Sterling Harper in "Calculating Reaction Rate Derivatives in Monte Carlo Neutron Transport" (https://dspace.mit.edu/bitstream/handle/1721.1/106690/969775837-MIT.pdf). | ||
|
|
||
| This example compares: | ||
|
|
||
| 1. **GRsecant (baseline)**: Standard gradient-free search using only k-effective values | ||
| 2. **Least Squares with Derivatives**: Enhanced search using both k-effective values and derivative constraints | ||
|
|
||
| ## Key Features | ||
|
|
||
| - **Automatic derivative tally setup**: No manual tally configuration required | ||
| - **Automatic derivative normalization**: Handles derivatives with very large magnitudes (e.g., O(10²⁰) for ppm-scale derivatives) | ||
| - **Generic derivative support**: Works with supported derivative variables: | ||
| - `nuclide_density`: Perturbations to specific nuclide concentrations ✓ **Fully supported** | ||
| - `density`: Material mass density changes ✓ **Fully supported** | ||
| - `temperature`: Doppler temperature effects ⚠️ **Limited support** (see below) | ||
|
|
||
| ### Temperature Derivative Limitations | ||
|
|
||
| Temperature derivatives in OpenMC have **significant limitations** that make them impractical for most k-eff search applications: | ||
|
|
||
| 1. **Requires Windowed Multipole (WMP) data**: Temperature derivatives are only computed when using multipole cross section representation. Standard tabulated cross sections (HDF5, ACE) at discrete temperatures do not support analytical temperature derivatives. | ||
|
|
||
| 2. **Limited energy range**: Derivatives are only valid within the resolved resonance energy range where the multipole approximation is applicable (~1 eV to ~10 keV for most materials). Outside this range, derivatives return zero. | ||
|
|
||
| 3. **Not implemented for interpolated cross sections**: If using OpenMC's temperature interpolation feature (`settings.temperature_method = 'interpolation'`), temperature derivatives are not computed from the interpolation - only from multipole data. | ||
|
|
||
| 4. **Sparse multipole data availability**: Very few nuclides in standard nuclear data libraries include WMP data. Most reactor applications would have insufficient coverage. | ||
|
|
||
| **Recommendation**: For k-eff searches involving temperature changes, use the standard derivative-free search (set `use_derivative_tallies=False`) rather than attempting to use temperature derivatives. The limitations above make temperature derivatives unreliable for reactor-scale criticality searches. | ||
|
|
||
| ## Files | ||
|
|
||
| - `test_tally_deriv_keff_search.py`: Comprehensive comparison script demonstrating two search problems: | ||
| 1. **Boron concentration search**: Finding critical boron concentration in PWR coolant (nuclide_density derivative) | ||
| 2. **Fuel density search**: Finding critical fuel density for densification scenarios (density derivative) | ||
|
|
||
| ## Quick Start | ||
|
|
||
| ### Basic Usage | ||
|
|
||
| ```bash | ||
| python test_tally_deriv_keff_search.py | ||
| ``` | ||
|
|
||
| This will run both test cases and display comparison results showing: | ||
| - Final converged parameter values | ||
| - Number of Monte Carlo runs required | ||
| - Total batches executed | ||
| - Elapsed time | ||
| - Efficiency gains relative to baseline | ||
|
|
||
| ### Expected Output | ||
|
|
||
| The script displays: | ||
| 1. Physical constants and conversion factors | ||
| 2. Progress for each iteration (parameter value, k-effective, derivative) | ||
| 3. Final results table comparing GRsecant vs Least Squares | ||
| 4. Efficiency analysis showing speedup and resource savings | ||
|
|
||
| ## Test Cases | ||
|
|
||
| ### Test Case 1: Boron Concentration Search | ||
|
|
||
| **Problem**: Find the boron concentration (in ppm) in PWR coolant to achieve a target k-effective of 1.20 | ||
|
|
||
| **Physics**: | ||
| - Boron-10 is a strong thermal neutron absorber | ||
| - Small changes in concentration significantly affect reactivity | ||
|
|
||
| **Derivative Type**: `nuclide_density` for B10 | ||
|
|
||
| **Key Challenge**: Derivatives are O(10¹⁶-10²⁰) due to unit conversion from atoms/cm³ to ppm. Automatic normalization handles this transparently. | ||
|
|
||
| ### Test Case 2: Fuel Density Search | ||
|
|
||
| **Problem**: Find the fuel density (g/cm³) to achieve a target k-effective of 1.17 | ||
|
|
||
| **Physics**: | ||
| - Fuel densification (aging) or swelling affects neutron moderation | ||
| - Density changes affect both fission rates and neutron leakage | ||
|
|
||
| **Derivative Type**: `density` for fuel material | ||
|
|
||
| **Key Advantage**: Derivatives are O(1), making gradient information highly effective without unit conversion complexity. | ||
|
|
||
| ## Understanding the Results | ||
|
|
||
| ### When Derivatives Help Most | ||
|
|
||
| 1. **Non-linear relationships**: When parameter-to-keff mapping is complex | ||
| 2. **Large search ranges**: When initial guesses are far from solution | ||
| 3. **High-precision requirements**: When tight convergence tolerances are needed | ||
| 4. **Expensive evaluations**: When each MC run is computationally costly | ||
|
|
||
| ### Convergence Indicators | ||
|
|
||
| The script prints iteration details: | ||
| ``` | ||
| Iteration 1: batches=45, x=500, keff=1.15234 +/- 0.00234, dk/dx=2.3e+16 | ||
| ``` | ||
|
|
||
| - `x`: Current parameter value | ||
| - `keff`: Computed k-effective with uncertainty | ||
| - `dk/dx`: Derivative (sensitivity) extracted from tallies | ||
|
|
||
| ## Implementation Details | ||
|
|
||
| ### Automatic Derivative Tally Setup | ||
|
|
||
| When `use_derivative_tallies=True`, the `keff_search` method automatically: | ||
| 1. Adds base tallies (nu-fission, absorption) | ||
| 2. Adds derivative tallies for the specified variable | ||
| 3. Extracts derivatives from statepoint files | ||
| 4. Normalizes derivatives for numerical stability | ||
| 5. Incorporates derivative constraints into least-squares fitting | ||
|
|
||
| **No manual tally configuration required!** | ||
|
|
||
| ### Derivative Normalization | ||
|
|
||
| Large derivatives (e.g., dk/dppm ~ 10²⁰) are automatically normalized using the geometric mean of recent derivative magnitudes: | ||
|
|
||
| ``` | ||
| deriv_scale = exp(mean(log(|dk/dx|))) | ||
| ``` | ||
|
|
||
| This ensures numerical stability without requiring manual scaling by the user. | ||
|
|
||
| ### Unit Conversion | ||
|
|
||
| For `nuclide_density` derivatives, OpenMC computes dk/dN (where N is number density in atoms/cm³). If your search parameter is in different units (e.g., ppm), provide a conversion function: | ||
|
|
||
| ```python | ||
| deriv_to_x_func=lambda deriv: deriv * conversion_factor | ||
| ``` | ||
|
|
||
| For other derivative types (`density`, `temperature`), no conversion is typically needed. | ||
|
|
||
| ## API Summary | ||
|
|
||
| ### Minimal Code Pattern | ||
|
|
||
| ```python | ||
| import openmc | ||
| import openmc.model | ||
|
|
||
| # 1. Build a model with configurable parameters | ||
| def build_model(boron_ppm=1000): | ||
| # Define materials | ||
| fuel = openmc.Material(material_id=1) | ||
| fuel.set_density('g/cm3', 10.31341) | ||
| fuel.add_element('U', 1., enrichment=1.6) | ||
| fuel.add_element('O', 2.) | ||
|
|
||
| coolant = openmc.Material(material_id=3) | ||
| coolant.set_density('g/cm3', 0.741) | ||
| coolant.add_element('H', 2.) | ||
| coolant.add_element('O', 1.) | ||
| coolant.add_element('B', boron_ppm * 1e-6) | ||
|
|
||
| # Define geometry and settings... | ||
| # (see test_tally_deriv_keff_search.py for complete example) | ||
|
|
||
| return openmc.model.Model(geometry, materials, settings) | ||
|
|
||
| # 2. Define parameter modifier function | ||
| def set_boron_ppm(ppm, model): | ||
| """Modify boron concentration in coolant.""" | ||
| coolant = model.materials[2] | ||
| coolant.remove_element('H') | ||
| coolant.remove_element('O') | ||
| coolant.remove_element('B') | ||
| coolant.set_density('g/cm3', 0.741) | ||
| coolant.add_element('H', 2.) | ||
| coolant.add_element('O', 1.) | ||
| coolant.add_element('B', ppm * 1e-6) | ||
| model.export_to_xml() | ||
|
|
||
| # 3. Run search with derivative tallies (added automatically!) | ||
| model = build_model(boron_ppm=1000) | ||
|
|
||
| result = model.keff_search( | ||
| func=lambda x: set_boron_ppm(x, model), | ||
| x0=500.0, | ||
| x1=1500.0, | ||
| target=1.20, | ||
| k_tol=1e-3, | ||
| sigma_final=3e-3, | ||
| maxiter=10, | ||
| use_derivative_tallies=True, | ||
| deriv_variable='nuclide_density', | ||
| deriv_material=3, | ||
| deriv_nuclide='B10' | ||
| ) | ||
| ``` | ||
|
|
||
| ### Key Parameters | ||
|
|
||
| - `use_derivative_tallies` (bool): Enable derivative-accelerated search | ||
| - `deriv_variable` (str): `'density'`, `'nuclide_density'`, or `'temperature'` | ||
| - `deriv_material` (int): Material ID to perturb | ||
| - `deriv_nuclide` (str): Nuclide name (required for `nuclide_density`) | ||
| - `deriv_to_x_func` (callable): Unit conversion function (optional) | ||
|
|
||
|
|
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The examples you added are nice but imo a better place for them should be in the openmc-notebooks repository. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| """ | ||
| keff_search with derivative tallies example. | ||
|
|
||
| This example demonstrates derivative-accelerated criticality searches using | ||
| OpenMC's derivative tally capability. See README.md for detailed documentation. | ||
| """ |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See comment above.