Add OpenMC depletion settings to input file#177
Conversation
806ff1a to
6896f02
Compare
bec77b4 to
a33d3c9
Compare
9192e57 to
d138aa5
Compare
LukeSeifert
left a comment
There was a problem hiding this comment.
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.
Consider adding a comment here describing what this is used for
There was a problem hiding this comment.
You mean a doc string for extend_with_default?
saltproc/app.py
Outdated
|
|
||
| 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.
How come this is ._schema_default instead of _schema_default?
There was a problem hiding this comment.
I think this is because _schema_default is not a module. Maybe @munkm can chime in.
There was a problem hiding this comment.
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.
Yes, let me try DefaultFillingValidator
saltproc/app.py
Outdated
| 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.
Why not continue using obj instead of switching back to j notation?
saltproc/openmc_deplete.py
Outdated
| tallies=tallies) | ||
|
|
||
| with open(args.depletion_settings) as f: | ||
| depletion_settings = {} |
There was a problem hiding this comment.
It doesn't look like this line does anything
There was a problem hiding this comment.
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.
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
| 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.
Consider adding extra variables i.e. simulation_object = object_input[1], that way its clearer what is being pulled from object_input
| 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.
How come the db_path needs to be updated here?
There was a problem hiding this comment.
For consistency if we ever add more tests to test_simulation.py.
7b87265 to
ffaf326
Compare
|
@abachma2 @munkm @samgdotson bump |
ca45926 to
9344619
Compare
LukeSeifert
left a comment
There was a problem hiding this comment.
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.
How come these are questions? Also, switch should be capitalized
There was a problem hiding this comment.
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) |
saltproc/app.py
Outdated
| 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.
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
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.
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.
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.
Consider mentioning the added codename parameter in this docstring
saltproc/input_schema.json
Outdated
| "default": false} | ||
| }, | ||
| "default": {}, | ||
| "required": ["sim_name", "db_name"] |
There was a problem hiding this comment.
How come db_name is still required? It is given a default value
samgdotson
left a comment
There was a problem hiding this comment.
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.
You mean a doc string for extend_with_default?
saltproc/app.py
Outdated
|
|
||
| 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.
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?
| # 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.
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.
I'm just trying to be as explicit as possible.
There was a problem hiding this comment.
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.
| 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
| simulation_input = input_parameters['simulation'] | ||
| reactor_input = input_parameters['reactor'] | ||
|
|
||
| depcode_input['codename'] = depcode_input['codename'].lower() |
There was a problem hiding this comment.
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.
| 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.
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
| tallies=tallies) | ||
|
|
||
| with open(args.depletion_settings) as f: | ||
| depletion_settings = {} |
There was a problem hiding this comment.
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_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.
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.
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]) |
0a95c29 to
df31b93
Compare
LukeSeifert
left a comment
There was a problem hiding this comment.
Everything looks good to me.
review of @samgdotson Co-authored-by: Sam Dotson <sgd2@illinois.edu>
|
@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. |
samgdotson
left a comment
There was a problem hiding this comment.
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.
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.
I'm not sure. I pulled this block of code from here
There was a problem hiding this comment.
@samgdotson I actually created an issue to look into this as there is a bug that exists with the current setup.
| # 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.
Okay, I don't see a difference but it doesn't hurt.
…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:
Depcodeexec_path: adds a default valuesss2forcodename == "serpent"openmc_deplete.pyforcodename == "openmc"num_depsteps->n_depletion_stepscodename == 'openmc':chain_file_pathdepletion_settingsSimulationdb_name: adds a default value ofsaltproc_results.h5restart_flag: adds a default value offalseadjust_geo: adds a default value offalseReactordep_step_length_cumulative->depletion_timestepstimestep_unitstimestep_typeSerpentDepcode.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.