-
Notifications
You must be signed in to change notification settings - Fork 16
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
Add OpenMC depletion settings to input file #177
Conversation
806ff1a
to
6896f02
Compare
bec77b4
to
a33d3c9
Compare
9192e57
to
d138aa5
Compare
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.
I had a few questions and pointed out a few typos I noticed, but overall looks good.
@@ -0,0 +1,21 @@ | |||
from jsonschema import Draft202012Validator, validators | |||
|
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.
Consider adding a comment here describing what this is used for
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.
You mean a doc string for extend_with_default
?
saltproc/app.py
Outdated
@@ -12,6 +12,7 @@ | |||
|
|||
from saltproc import SerpentDepcode, OpenMCDepcode, Simulation, Reactor | |||
from saltproc import Process, Sparger, Separator, Materialflow | |||
from ._schema_default import DefaultValidatingValidator |
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.
How come this is ._schema_default
instead of _schema_default
?
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.
I think this is because _schema_default
is not a module. Maybe @munkm can chime in.
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.
it just means you're importing from the current directory. However, if it's a member of saltproc
you should be able to do from saltproc._schema_default import DefaultValidatingValidator
Separately, is there a more descriptive or less self-referential name for this function?
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.
Yes, let me try DefaultFillingValidator
saltproc/app.py
Outdated
except jsonschema.exceptions.ValidationError: | ||
print("Your input file is improperly structured.\ | ||
Please see saltproc/tests/test.json for an example.") | ||
|
||
j = obj |
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.
Why not continue using obj
instead of switching back to j
notation?
saltproc/openmc_deplete.py
Outdated
@@ -63,12 +62,18 @@ def parse_arguments(): | |||
settings=settings, | |||
tallies=tallies) | |||
|
|||
with open(args.depletion_settings) as f: | |||
depletion_settings = {} |
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.
It doesn't look like this line does anything
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.
It does. It initializes the depletion_settings
dictionary. I think we need to do this so we can get the value provided by depletion_settings = json.load(f)
inside the with
block on line 66-67 in openmc_deplete.py
, but maybe I'm wrong?
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.
You definitely do not need to do this, you're just overwriting an empty dictionary with another dictionary.
depletion_settings = {} |
The situation would be different if you were, say, combining dictionaries. But that doesn't appear to be the case.
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.
okay
tests/conftest.py
Outdated
simulation = _create_simulation_object(object_input[1], depcode, 1, 1) | ||
#db_path=str( | ||
# cwd / | ||
# 'serpent_data' / | ||
# 'tap_reference_db.h5')) | ||
|
||
reactor = _create_reactor_object(object_input[2]) |
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.
Consider adding extra variables i.e. simulation_object = object_input[1]
, that way its clearer what is being pulled from object_input
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.
I agree
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.
okay
old_db_path = simulation.db_path | ||
simulation.db_path = str(Path(simulation.db_path).parents[1] / 'tap_reference_db.h5') | ||
assert simulation.read_k_eds_delta(7) is False | ||
simulation.db_path = old_db_path |
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.
How come the db_path
needs to be updated here?
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.
For consistency if we ever add more tests to test_simulation.py
.
7b87265
to
ffaf326
Compare
@abachma2 @munkm @samgdotson bump |
ca45926
to
9344619
Compare
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.
Have a few things I wasn't certain about, but overall looks good.
Restart simulation from the step when it stopped? | ||
|
||
:type: | ||
``boolean`` | ||
|
||
:default: | ||
``false`` | ||
|
||
|
||
.. _adjust_geo_property: | ||
|
||
``adjust_geo`` | ||
-------------- | ||
|
||
:description: | ||
switch to another geometry when keff drops below 1? |
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.
How come these are questions? Also, switch
should be capitalized
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.
They are questions that the variable is the answer to. Maybe that is confusing though?
saltproc/app.py
Outdated
try: | ||
jsonschema.validate(instance=j, schema=v) | ||
DefaultValidatingValidator(schema).validate(input_parameters) | ||
#jsonschema.validate(instance=j, schema=v) |
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.
This can be removed
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.
good catch/
saltproc/app.py
Outdated
else: | ||
raise ValueError( | ||
f'{depcode_input["codename"]} ' | ||
'is not a supported depletion code') | ||
f'{codename} is not a supported depletion code.' |
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.
I don't see codename
defined in this function, thought I do see depcode_input["codename"]
. Consider changing back to match rest of if
statement, or adding in a codename=
statement prior to the if
statements
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.
good catch
saltproc/app.py
Outdated
if codename == 'openmc': | ||
depletion_settings = depcode_input.pop('depletion_settings') | ||
chain_file_path = depcode_input.pop('chain_file_path') | ||
|
||
depcode = depcode(**depcode_input) | ||
|
||
if codename == 'openmc': | ||
depcode.chain_file_path = chain_file_path | ||
depcode.depletion_settings = depletion_settings | ||
|
||
depcode_input['codename'] = codename |
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.
How come this moved from handling OpenMC and Serpent to only OpenMC? Also, the separation of the if
statements here seems a bit strange. Can this be rewritten into a single if
statement? Consider adding a bit more information to the docstring
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.
It has to do with the SaltProc input file. For Serpent runs, the depcode_input
dictionary consists exclusively of valid keyword arguments for the SerpentDepcode.__init__()
function. However, if we are doing an OpenMC run, there are additional key-value pairs in the depcode_input
dictionary (depletion_settings
and chain_file_path
) that will cause an error if we run depcode(**depcode_input)
without removing them first. However, I now realize what I really should do is just add these variables as optional keyword arguments to OpenMCDepcode.__init__()
.
saltproc/app.py
Outdated
Process SaltProc reactor class input parameters based on the value and | ||
data type of the `num_depsteps` parameter, and throw errors if the input | ||
data type of the `n_depletion_steps` parameter, and throw errors if the input | ||
parameters are incorrect. |
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.
Consider mentioning the added codename
parameter in this docstring
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.
done
saltproc/input_schema.json
Outdated
"default": false} | ||
}, | ||
"default": {}, | ||
"required": ["sim_name", "db_name"] |
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.
How come db_name
is still required? It is given a default value
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.
Good point.
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.
Mostly cosmetic changes. However, there is one issue where the "cumulative" case is confusing.
@@ -0,0 +1,21 @@ | |||
from jsonschema import Draft202012Validator, validators | |||
|
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.
You mean a doc string for extend_with_default
?
saltproc/app.py
Outdated
@@ -12,6 +12,7 @@ | |||
|
|||
from saltproc import SerpentDepcode, OpenMCDepcode, Simulation, Reactor | |||
from saltproc import Process, Sparger, Separator, Materialflow | |||
from ._schema_default import DefaultValidatingValidator |
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.
it just means you're importing from the current directory. However, if it's a member of saltproc
you should be able to do from saltproc._schema_default import DefaultValidatingValidator
Separately, is there a more descriptive or less self-referential name for this function?
@@ -30,22 +34,22 @@ def run(): | |||
simulation.check_restart() | |||
# Run sequence | |||
# Start sequence | |||
for dep_step in range(len(msr.dep_step_length_cumulative)): | |||
print("\n\n\nStep #%i has been started" % (dep_step + 1)) | |||
for step_idx in range(len(msr.depletion_timesteps)): |
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.
Is there a difference between the step index and the step number? I would just call it step
. Though this is purely a stylistic difference.
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.
I'm just trying to be as explicit as possible.
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.
Okay, I don't see a difference but it doesn't hurt.
saltproc/app.py
Outdated
if depcode_input['codename'] == 'serpent': | ||
depcode_input['template_input_file_path'] = str(( | ||
input_path / |
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.
if depcode_input['codename'] == 'serpent': | |
depcode_input['template_input_file_path'] = str(( | |
input_path / | |
if codename == 'serpent': | |
depcode_input['template_input_file_path'] = str(( | |
input_path / |
saltproc/app.py
Outdated
|
||
depcode_input['codename'] = depcode_input['codename'].lower() |
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.
Is this supposed to be
depcode_input['codename'] = depcode_input['codename'].lower() | |
codename = depcode_input['codename'].lower() |
?
saltproc/app.py
Outdated
ts = list(np.diff(depletion_timesteps)) | ||
depletion_timesteps = depletion_timesteps[0] + ts |
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.
ts = list(np.diff(depletion_timesteps)) | |
depletion_timesteps = depletion_timesteps[0] + ts | |
depletion_timesteps = np.cumsum(depletion_timesteps) |
I agree with @LukeSeifert that the expected result is unclear. Possibly use np.cumsum()
?
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.
This is actually coded improperly now that I look at it. What we are supposed to be doing here is converting a cumulative timeseries (1s, 3s, 5s) to a stepwise timeseries (1s, 2s, 2s). But I eneterd this wrong which explains why we were confused. I seem to be missing tests for this function as well so I'll add those
saltproc/openmc_deplete.py
Outdated
@@ -63,12 +62,18 @@ def parse_arguments(): | |||
settings=settings, | |||
tallies=tallies) | |||
|
|||
with open(args.depletion_settings) as f: | |||
depletion_settings = {} |
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.
You definitely do not need to do this, you're just overwriting an empty dictionary with another dictionary.
depletion_settings = {} |
The situation would be different if you were, say, combining dictionaries. But that doesn't appear to be the case.
tests/conftest.py
Outdated
def serpent_depcode(cwd): | ||
"""SerpentDepcode object for unit tests""" | ||
def serpent_runtime(cwd, tmpdir_factory): | ||
"""SaltProc objects for Serpent unit tests""" | ||
saltproc_input = str(cwd / 'serpent_data' / 'tap_input.json') | ||
_, _, _, object_input = read_main_input(saltproc_input) |
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.
We've discussed this before, I think. I don't like the practice of using underscores as variable names. They should have names, even if you're not using them. Also, consider that you might forget the return variables are for this function. Yes you could look it up, but why waste the energy?
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.
Okay, I think I can address this in a way that satisfies both of us.
tests/conftest.py
Outdated
simulation = _create_simulation_object(object_input[1], depcode, 1, 1) | ||
#db_path=str( | ||
# cwd / | ||
# 'serpent_data' / | ||
# 'tap_reference_db.h5')) | ||
|
||
reactor = _create_reactor_object(object_input[2]) |
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.
I agree
0a95c29
to
df31b93
Compare
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.
Everything looks good to me.
review of @samgdotson Co-authored-by: Sam Dotson <[email protected]>
@samgdotson I made some changes based on your comments, and added some tests for additional code coverage. Let me know what you think |
Looping @LukeSeifert back in because I added some new stuff. |
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.
Thanks for making those other changes -- I'm curious about the nested functions.
def extend_with_default(validator_class): | ||
validate_properties = validator_class.VALIDATORS["properties"] | ||
|
||
def set_defaults(validator, properties, instance, schema): | ||
for property, subschema in properties.items(): | ||
if "default" in subschema: | ||
instance.setdefault(property, subschema["default"]) | ||
|
||
for error in validate_properties( | ||
validator, properties, instance, schema, | ||
): | ||
yield error | ||
|
||
return validators.extend( | ||
validator_class, {"properties" : set_defaults}, | ||
) |
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.
I didn't catch this before, but what is the purpose of having nested function definitions? Why not break this into two functions that can both be unit-tested?
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.
I'm not sure. I pulled this block of code from here
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.
@samgdotson I actually created an issue to look into this as there is a bug that exists with the current setup.
@@ -30,22 +34,22 @@ def run(): | |||
simulation.check_restart() | |||
# Run sequence | |||
# Start sequence | |||
for dep_step in range(len(msr.dep_step_length_cumulative)): | |||
print("\n\n\nStep #%i has been started" % (dep_step + 1)) | |||
for step_idx in range(len(msr.depletion_timesteps)): |
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.
Okay, I don't see a difference but it doesn't hurt.
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.
lgtm
…epletion-settings Add OpenMC depletion settings to input file 5b4e60c
…mc-depletion-settings Add OpenMC depletion settings to input file 5b4e60c
Summary of changes
This PR expands the inputfile JSON schema to enable specifying OpenMC depletion settings.
This PR also adds options to the inputfile JSON schema to specify timestep type (cumulative or stepwise) and units, as well as machinery to process these new inputs.
This PR also adds default values to the inputfile JSON schema, and a class to process these default values.
Specifically, this PR:
Depcode
exec_path
: adds a default valuesss2
forcodename == "serpent"
openmc_deplete.py
forcodename == "openmc"
num_depsteps
->n_depletion_steps
codename == 'openmc'
:chain_file_path
depletion_settings
Simulation
db_name
: adds a default value ofsaltproc_results.h5
restart_flag
: adds a default value offalse
adjust_geo
: adds a default value offalse
Reactor
dep_step_length_cumulative
->depletion_timesteps
timestep_units
timestep_type
SerpentDepcode.set_power_load()
to enable use of the new time step parameters.Types of changes
Required for Merging
Associated Issues and PRs
Associated Developers
Checklist for Reviewers
Reviewers should use this link to get to the
Review Checklist before they begin their review.