Skip to content

Add reactivity control to coupled transport-depletion analyses #2693

Open
church89 wants to merge 86 commits intoopenmc-dev:developfrom
openmsr:batchwise_pr
Open

Add reactivity control to coupled transport-depletion analyses #2693
church89 wants to merge 86 commits intoopenmc-dev:developfrom
openmsr:batchwise_pr

Conversation

@church89
Copy link
Contributor

@church89 church89 commented Sep 14, 2023

Description

This pr adds the capability to perform batch-wise reactivity control during a coupled transport-depletion analysis.
It effectively runs an iterative search_for_keff sub-step algorithm to maintain keff equal to 1 (or some other user defined targets) as a function of some user defined model parameter to update, before calculating the BOS from the transport run and proceed with the depletion step.
The model variable to parametrize during the sub-step can be of geometrical (e.g. control rod position) or material (e.g. refuel) nature, acting on a openmc.Cell and openmc.Material, respectively.

A batch-wise scheme can be added to an integrator instance and a coupled transport-depletion simulation can be run like this:

...
...
op = openmc.deplete.CoupledOperator(model)
integrator = openmc.deplete.CECMIntegrator(op, timesteps , power)
integrator.add_batchwise(cell, 'translation', axis = 2, bracket = [-4, 4], bracket_limit = [-100,20])
integrator.integrate()

where cell is an openmc.Cell conveniently defined that can be translated along the z-axis during the run.

Checklist

  • I have performed a self-review of my own code
  • I have run clang-format 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)

Copy link
Contributor

@drewejohnson drewejohnson left a comment

Choose a reason for hiding this comment

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

@church89 thank you for this lengthy and useful PR! I think this is going to unlock a lot of doors for people and provide a lot of value. I haven't done a full review but I wanted to get some of my larger thoughts out first, make sure we understand the vision and goal, and then refine my review as we go.

Some simple things

  • Please re-evaluate the docstrings you've added to align with the numpydoc spec Otherwise our built documentation isn't going to process this properly
  • Please run a python formatter like black to make sure your code adheres to pep8 formatting style like the dev guide requests
  • Please consolidate property setters / getters / validators. I think it's going to be easier for us in the long run to maintain / add validators if we do validation on things like self.tol if all validation is done in property setters

Maybe a larger lift: I think the high-level class and method name, using batch wise, might not communicate what we want to communicate. My rationale is I believe this engages after a full transport simulation, while openmc uses the "batch" terminology to mean generations of particles in a given transport simulation - docs

so users who already are configuring an openmc run to have so many inactive / active generations per batch may expect this search to be performed more often than it is actually performed.

But, based on your PR message

It effectively runs an iterative search_for_keff sub-step algorithm to maintain keff equal to 1 (or some other user defined targets) as a function of some user defined model parameter to update, before calculating the BOS from the transport run

and my non-exhaustive review, I could be wrong. If we are making changes to the model during batches of active generations, then this name makes sense. But if we are not, I would encourage us to consider new names.

I hope to have time in the next week or so for a more detailed review, but I wanted to get something out the door to let you know I've seen this, I believe it's valuable, and I have some (hopefully) low-hanging requests

res_test = openmc.deplete.Results(path_test)
res_ref = openmc.deplete.Results(path_reference)

# Use high tolerance here
Copy link
Contributor

Choose a reason for hiding this comment

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

Oof a 2% relative tolerance is high. But we've got a stochastic code, and probably wanting to get the simulation to converge reasonably quickly.

I'd like to see a tighter tolerance but I understand that might not be tenable.

church89 and others added 2 commits February 5, 2024 12:43
Co-authored-by: Andrew Johnson <drewejohnson@users.noreply.github.com>
@church89
Copy link
Contributor Author

church89 commented Feb 5, 2024

Hi @drewejohnson, thanks for starting this review. I've begun to address your comments/suggestions.

I can see how batchwise might create some confusion. The routine acts in between a transport and a depletion step, so an alternatives could be stepwise to maintain the general purpose.
Otherwise, we might think of linking the concepts of depletion and criticality, as ultimately is what it does, like depletion_critical , criticality_depletion or something similar.

@church89
Copy link
Contributor Author

church89 commented Aug 1, 2025

Thanks @paulromano for getting back to this PR. Looks reasonable to me to separate the search_for_keff bit and then maybe rename the ReactivityController to something like OperatorReactivityController or DepletionReactivityController that wraps around it.
Let me know if there is anything I can do to help you with the search_for_keff PR.

@lewisgross1296
Copy link
Contributor

Just wanted to check in and see how this is going. I am very interested in critical searches before depletion steps. Seems the tests are passing, but perhaps this was waiting for #3569 to be merged?

Tagging @gonuke to stay in the loop

Copy link
Contributor

@paulromano paulromano left a comment

Choose a reason for hiding this comment

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

@church89 Now that #3569 has been merged, can you update this PR based on the earlier discussion? It also looks like there are some conflicts that need to be resolved. Let me know if I can help at all!

@church89
Copy link
Contributor Author

@paulromano this PR has finally been refactored and simplified a lot based on the awesome #3569 and earlier discussions. Haven't fully tested it yet but you can go through it when you have some time and tell me what you think!

Copy link
Contributor

@paulromano paulromano left a comment

Choose a reason for hiding this comment

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

Thanks for the updates on this PR @church89! Regarding the name of this feature, I think it would be more explicit to have:

  • Integrator.add_keff_search
  • KeffSearchControl

Also, since KeffSearchControl doesn't appear to be something users would instantiate directly, I think it should be an internal class (_KeffSearchControl) that is really an implementation detail (which gives us the freedom to change it later on if we want).

There are a few items that need to be addressed below:

Updated atom density vector synchronized across all ranks
"""
for rank in range(comm.size):
number_i = comm.bcast(self.operator.number, root=rank)
Copy link
Contributor

Choose a reason for hiding this comment

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

If the density change is being made through openmc.lib, wouldn't this end up resetting the densities to what they were before since operator.number doesn't get updated?

Comment on lines 97 to 109
if root < self.kwargs['x_min']:
warn(
f"keff search result ({root:.6f}) is below the lower bracket bound "
f"({self.kwargs['x_min']:.6f}). Clamping to bracket lower bound.",
UserWarning
)

elif root > self.kwargs['x_max']:
warn(
f"keff search result ({root:.6f}) is above the upper bracket bound "
f"({self.kwargs['x_max']:.6f}). Clamping to bracket upper bound.",
UserWarning
)
Copy link
Contributor

Choose a reason for hiding this comment

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

It says it's being clamped but I don't actually see any clamping below?

@church89
Copy link
Contributor Author

Hi @paulromano thanks for the comments. I've addressed now all of them and as suggested I've renamed the class to KeffSearchControl and made it private, exposing only the integrator.add_keff_search_control method.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants