Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions openmc/deplete/keff_search_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ def run(self, x):
root : float
Parameter value that achieves target keff
"""
# This runs before the operator is called for this step, so
# openmc.lib.materials and the operator's AtomNumber still hold the
# previous step's compositions. Push `x` in first, otherwise the search
# runs on stale materials and _update_vec() reverts `x` to them.
self.operator._update_materials_and_nuclides(x)

root = self._search_for_keff()
self._update_vec(x)
return root
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,9 @@ def test_keff_search_control(run_in_tmpdir, model, function, x0, x1, bracket, re

# Use high tolerance here
assert res_test[0].keff_search_root == pytest.approx(res_ref[0].keff_search_root, rel=2)

# The keff search must not clobber the depleted compositions. If the search
# runs against the previous step's materials, the depletion vector is
# reverted to its beginning-of-step values and no fission products appear.
_, xe135 = res_test.get_atoms(model.materials[0], 'Xe135')
assert xe135[-1] > 0.0
25 changes: 25 additions & 0 deletions tests/unit_tests/test_deplete_keff_search_control.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
""" Tests for KeffSearchControl class """

from pathlib import Path
from unittest.mock import Mock

import pytest
import numpy as np

import openmc
import openmc.lib
from openmc.deplete import CoupledOperator
from openmc.deplete.keff_search_control import _KeffSearchControl

CHAIN_PATH = Path(__file__).parents[1] / "chain_simple.xml"

Expand Down Expand Up @@ -114,3 +116,26 @@ def test_integrator_add_keff_search_control(run_in_tmpdir, function, x0, x1, bra
assert integrator._keff_search_control.search_kwargs['x_max'] == bracket[1]
assert integrator._keff_search_control.search_kwargs['k_tol'] == 0.1
assert not integrator._keff_search_control.search_kwargs['output']


def test_materials_updated_before_search(monkeypatch):
"""Test that compositions reach the operator before the keff search runs

The search happens at the beginning of a depletion step, before the
transport operator is called. Without the update, the search uses the
previous step's materials and _update_vec() reverts the depletion vector
to them.
"""
recorder = Mock()
recorder.search.return_value = 0.5
control = _KeffSearchControl(recorder.operator, lambda x: None,
x0=0.0, x1=1.0, bracket=[0.0, 2.0])
monkeypatch.setattr(control, '_search_for_keff', recorder.search)
monkeypatch.setattr(control, '_update_vec', recorder.update_vec)

n = [np.array([1.0, 2.0, 3.0])]

assert control.run(n) == 0.5
assert [c[0] for c in recorder.mock_calls] == [
'operator._update_materials_and_nuclides', 'search', 'update_vec']
assert recorder.mock_calls[0].args[0] is n
Loading