-
Notifications
You must be signed in to change notification settings - Fork 20
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
NEAMS Workbench #85
base: development
Are you sure you want to change the base?
NEAMS Workbench #85
Changes from all commits
ec4b451
ccafae0
02a7498
14f047e
3edd695
ec8b6fe
7e983aa
b71c8e2
98a7476
fe294b0
5334fb6
72ac4f9
043e314
dc27ddb
68e7ffe
d722a62
b8f9d93
4ae5ad7
6dd0eb4
193c444
50abc5e
0d09d32
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
.. devguide_workbench: | ||
|
||
Adding Application to Workbench | ||
------------------------------- | ||
|
||
If you wish to use WATTS on the NEAMS Workbench with a code | ||
that is not already available, adding the code can be done quite easily. | ||
|
||
First, you have to develop a plugin for the code and add it to WATTS following | ||
the steps described previously. Once the plugin is available, you can then add it | ||
to `watts_ui.py`. | ||
|
||
In the `run_direct()` function, you will need to add an `elif` statement as follows, | ||
|
||
.. code-block:: | ||
|
||
elif plugin['code'].upper() == '<name_of_new_code>': | ||
app_plugin = watts.name_of_new_plugin( | ||
template_file=plugin['template'], | ||
executable=exec, | ||
extra_inputs=plugin['extra_inputs'], | ||
extra_template_inputs=plugin['extra_template_inputs'], | ||
show_stdout=plugin['show_stdout'], | ||
show_stderr=plugin['show_stderr']) | ||
|
||
Note tha additional steps might be necessary here depending on the code that | ||
is being added. | ||
|
||
If the plugin is developed to be similar to the other plugins on WATTS, | ||
no other changes are necessary to `watts_ui.py`. Otherwise, the developer | ||
is responsible for making sure that `watt_ui.py` can read the results | ||
produced by the plugin. Within `run_direct()`, the results from the plugin | ||
should be extracted and saved to `watts_params` as individual entries. This | ||
is required for the coupling and data-transfer between different codes. | ||
|
||
Next, the `watts.sch` file needs to be updated. The name of the new code needs | ||
to be added to the `code` block as follows:: | ||
|
||
watts{ | ||
plugins{ | ||
plugin{ | ||
code{ | ||
Description = "[Required] All - Name of application" | ||
... | ||
ValEnums=[PyARC RELAP5 ... <name_of_new_code>] | ||
} | ||
} | ||
} | ||
} | ||
|
||
Note that the name used for the new code used here must match that used in | ||
`watts_ui.py`. | ||
|
||
Adding new plugin options | ||
+++++++++++++++++++++++++ | ||
|
||
Any additional options needed by the plugin can be added under the `plugin` | ||
block as follows:: | ||
|
||
watts{ | ||
plugins{ | ||
plugin{ | ||
additional_plugin_option{ | ||
Description = "[optional] New_code - Description of the new option" | ||
MinOccurs=0 | ||
MaxOccurs=1 | ||
ValType=String | ||
InputTmpl="plugin.additional_plugin_option" | ||
} | ||
} | ||
} | ||
} | ||
|
||
Note that `MinOccurs` and `MaxOccurs` represent the minimum and maximum occurences of | ||
this option, `ValType` is the input type of the new option, and `InputTmpl` is the | ||
template file for the new option located in the `etc/templates` directory. Template | ||
file is optional but highly recommended as it provides a template or example to other users. | ||
|
||
If new plugin options are added, the `create_plugins()` function in `watts_ui.py` must | ||
be updated. The function essentially creates a nested Python dictionary that contains one | ||
or more individual dictionaries where each individual dictionary stores the information | ||
of each plugin. The function utilizes a series of `if` statements to decide what information | ||
should be stored for each plugin. | ||
|
||
If the input of the new option is a string, the new option can be added as follows :: | ||
|
||
if plg.new_option_name is not None: | ||
nested_plugins['new_option_name'] = str( | ||
plg.new_option_name.value).strip('\"') | ||
|
||
If the input is a list :: | ||
|
||
if plg.new_option_name is not None: | ||
nested_plugins['new_option_name'] = convert_to_list(plg.new_option_name) | ||
|
||
If the input is a bool :: | ||
|
||
nested_plugins['new_option_name'] = False | ||
|
||
if plg.new_option_name is not None and str(plg.new_option_name.value).capitalize() == 'True': | ||
nested_plugins['new_option_name'] = True | ||
|
||
Similar approach can be used for plugin options of different input types. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,227 @@ | ||
.. _workbench: | ||
|
||
Setup WATTS in NEAMS Workbench Environment | ||
------------------------------------------ | ||
|
||
The `NEAMS Workbench <https://www.ornl.gov/onramp/neams-workbench>` is a tool | ||
that facilitates the use of multiple tools in analysis | ||
by providing a commom user interface for model creation, review, execution, output, | ||
and visualization for integrated codes. Instructions on how to download and install | ||
Workbench can be found on the Workbench | ||
`Gitlab repository <https://code.ornl.gov/neams-workbench/downloads>`. | ||
|
||
To set up WATTS in the Workbench environment, you first need to first provide the path to | ||
where Workbench is installed in `workbench.sh` under the `scripts` directory. You can | ||
then run `setup_conda_wb.sh` under the same directory to set up WATTS within | ||
the Workbench environment. | ||
|
||
Optional: To install OpenMC in the Workbench environemnt, run `setup_openmc.sh`. | ||
|
||
To finish setting up WATTS, open Workbench and go to the `File` tab at the top-left corner | ||
then select `Configurations` from the drop menu. In the `Application configurations` | ||
window, click `Add` on the top most row then select `Watts` from the pop-up window. | ||
In the list of `Application Options`, input the path of `watts_ui.py` to `Executable`. | ||
The file should exist by default in `/watts/src/watt_ui/`. Next, click `Load Grammar`. | ||
Click `OK` to complete the setup. | ||
|
||
Optional: Environment variables can be added be added under `Run Environment`. | ||
|
||
WATTS Workbench Input File | ||
++++++++++++++++++++++++++ | ||
|
||
To create a new WATTS input file in Workbench, go to `File`, select `New File`, | ||
and select `WATTS files (*.son)` from the drop down menu. An existing `*.son` | ||
file can also be dragged and dropped to the Workbench window. | ||
|
||
The WATTS input file utilizes a hierarchical block-based system where a block | ||
is defined with opening and closing curly braces `{ }`. A `watts` block is first | ||
created within which other blocks and variables can be defined. | ||
|
||
Plugins | ||
~~~~~~~ | ||
|
||
The `plugins` block is required. Within the `plugins` blocks are | ||
`plugin` sub-blocks where WATTS plugins are defined. | ||
|
||
.. code-block:: text | ||
plugins{ | ||
plugin(ID1){ | ||
code = moose | ||
template = "sam_template" | ||
exec_dir = SAM_DIR | ||
exec_name = "sam-opt" | ||
extra_inputs=["file1", "file2", "file3"] | ||
extra_template_inputs=["template1", "template2", "template3"] | ||
show_stderr = False | ||
show_stdout = False | ||
} | ||
|
||
plugin(ID2){ | ||
code = PyARC | ||
template = "pyarc_template" | ||
executable = "path/to/pyarc/executable" | ||
show_stderr = False | ||
show_stdout = False | ||
} | ||
} | ||
|
||
Multiple `plugin` sub-blocks can be defined within the `plugins` block where | ||
each plugin is given a unique identity, as represented by `(ID1)` and `(ID2)` | ||
in the snippet above. For each sub-block the basic inputs are:: | ||
|
||
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. We need a |
||
`code` : Name of the application | ||
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. it would be nice to have list of options, if required or optional, etc. In fact, I can show you how such documentation can be automatically generated with Workbench (and maybe added to this documentation) |
||
`template` : Name of the template file | ||
`show_stderr` : Option to display error | ||
`show_stdout` : Option to display output | ||
`exec_dir` : Environment variable that points to the directory in which the application's executable is stored | ||
`extra_inputs` : Additional non-templated input files | ||
`extra_template_inputs` : Additional tempalted input files | ||
`exec_name` : Name of the executable | ||
`executable` : Path to the executable | ||
|
||
Note that user must provide either BOTH `exec_dir` and `exec_name` or | ||
ONLY `executable`. Additionally, there are application-specific inputs | ||
that can be provided to the plugins such as:: | ||
|
||
`extra_args` (multiple apps) : Extra arguments to applications | ||
'transfer_params' (multiple apps) : Output to transfer between applications for multi-apps run | ||
`plotfl_to_csv` (RELAP5) : Option to convert `plotfl` file to `csv` file | ||
`conv_channel` (SAS) : Path to `CHANNELtoCSV.x` | ||
`conv_primar4` (SAS) : Path to `PRIMAR4toCSV.x` | ||
`auto_link_files` (Dakota) : List of files for Dakota to link automatically | ||
`scores` (OpenMC) : List of filters for tallies | ||
`score_names` (OpenMC) : List of user-given names for tally filters | ||
|
||
Currently all applications/codes already integrated to WATTS can be run on Workbench, these include | ||
PyARC, OpenMC, SERPENT, ABCE, MCNP, MOOSE, SAS, Dakota, Serpent, and RELAP5. | ||
|
||
For OpenMC, multiple `scores` can be provided at once. If provided, the number of `score_names` must be the | ||
same as the number of `scores`. For instance, :: | ||
|
||
scores = ["elastic", "nu-fission"] | ||
score_names = ["total_elastic_scatter_rate", "total_fission_neutron_prod"] | ||
|
||
and there are N tallies where N > 1, then the outputs of the run will be named as:: | ||
|
||
total_elastic_scatter_rate_1, total_elastic_scatter_rate_2, ..., total_elastic_scatter_rate_N | ||
total_fission_neutron_prod_1, total_fission_neutron_prod_2, ..., total_fission_neutron_prod_N | ||
|
||
If `score_names` is not provided, `scores` will be used as the base name for the outputs. | ||
|
||
Workflow level | ||
~~~~~~~~~~~~~~ | ||
|
||
The `workflow_level1` block is required. The plugin to be used is specified | ||
by the `plugin` keyword:: | ||
|
||
plugin = ID1 | ||
|
||
where 'ID1' is the ID of the plugin provided in the `plugins` block. When performing | ||
a multi-app run where more than one plugins are used, the sequence of the run is | ||
determined by the order of plugins. For example, when the order of the plugins is:: | ||
|
||
plugin = ID1 | ||
plugin = ID2 | ||
|
||
Workbench will run ID1 first then ID2. On the other than, when the order is :: | ||
|
||
plugin = ID2 | ||
plugin = ID1 | ||
|
||
Workbench will instead run ID1 first then ID2. | ||
|
||
The`variable` sub-block is where the values of the templated variables are | ||
specified, as shown below:: | ||
|
||
variables{ | ||
param(T_inlet) {value = 873.15} | ||
param(T_outlet) {value = 1000.15} | ||
param(flow_area) {value = 3.14e-4} | ||
param(component_name) {value = pipe1} | ||
param(Dh) {value = 1 unit = m} | ||
param(location) {list = [top bottom left right]} | ||
param(length) {list = [3.0 5.0 7.0 10.0]} | ||
param(T_mean) {func = "0.5 * ( T_inlet + T_outlet )"} | ||
param(wall_bc) {bool = "True"} | ||
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. We should develop different param templates that show the different options (param.value.tmpl, param.list.tmpl, param.func.tmpl, param.bool.tmpl, etc.) |
||
} | ||
|
||
Each `param` has a unique ID represented by the string in the parantheses | ||
shown in the snippet above. A `param` can accept different types of inputs | ||
depending on the provided key word provided. The `value` keyword is used | ||
for when a numeric or a string is provided. A `unit` keyword can be added | ||
if a user intends to utilize WATTS' internal unit-conversion capability. | ||
The `list` keyword is used for a list of numerics or strings. The `bool` | ||
keyword is used for booleans. The `func` keyword is used when a user | ||
intends to perform arithmetic with existing `param`. Note that each elemet | ||
in `func` must be separated by a space. | ||
|
||
Execution | ||
+++++++++ | ||
|
||
Three types of executions can be performed by WATTS on Workbench, namely | ||
direct execution, parametric study, and Picard iteration. | ||
|
||
Direct execution | ||
~~~~~~~~~~~~~~~~ | ||
|
||
Direct execution is the simplest execution type. The user only needs to | ||
provide `workflow_dir`, `plugins` block, and `workflow_level1` block to | ||
perform direct execution. | ||
|
||
Parametric study | ||
~~~~~~~~~~~~~~~~ | ||
|
||
To perform parametric study, a `parametric` block needs to be added to | ||
the `workflow_level1` block as follows:: | ||
|
||
workflow_level1{ | ||
plugin = ID1 | ||
variables{ | ||
param(He_inlet_temp) {value = 873.15} | ||
param(He_outlet_temp) {value = 1023.15} | ||
... | ||
} | ||
parametric{ | ||
changing_params = "heat_source" | ||
changing_values = [0, 1e5, 2e5, 3e5] | ||
} | ||
} | ||
|
||
where `changing_params` is the parameter whose values are varied and | ||
`changing_values` is a list of intended varied values. | ||
|
||
Picard iteration | ||
~~~~~~~~~~~~~~~~ | ||
|
||
To perform Picard iteration, the `iteration` block needs to be added | ||
to the `workflow_level1` block:: | ||
|
||
workflow_level1{ | ||
plugin = ID1 | ||
variables{ | ||
param(He_inlet_temp) {value = 873.15} | ||
param(He_outlet_temp) {value = 1023.15} | ||
... | ||
} | ||
iteration{ | ||
plugin = ID2 | ||
nmax = 10 | ||
convergence_params = "keff" | ||
convergence_criteria = 0.0001 | ||
to_sub_params = ["avg_Tf_1" "avg_Tf_2" "avg_Tf_3" "avg_Tf_4" "avg_Tf_5"] | ||
to_main_params = ["Init_P_1" "Init_P_2" "Init_P_3" "Init_P_4" "Init_P_5"] | ||
} | ||
} | ||
|
||
`plugin` in the `iteration` block is the plugin ID (ID2 in this example) of the | ||
application that will be used along with the the first plugin (ID1 in this example) | ||
to perform iteration. `nmax` is the maximum number of iterations, | ||
`convergence_params` is the parameter used for evaluating convergence, | ||
`convergence_criteria` is the tolerance for | ||
convergence, `to_sub_params` and `to_main_params` are lists of parameters whose | ||
values are iterated between the two applications where they each must have at least | ||
one parameter. Note that the parameter supplied to `convergence_params` must be | ||
an output from the second plugin. For instance, in the above example, "keff" is | ||
an output produced by the plugin of "ID2". Note that the choice of "keff" in | ||
this example is arbitrary and `convergence_params` should be chosen according to | ||
the applications used and the objective of iteration runs. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
watts{ | ||
plugins{ | ||
plugin(ID1){ | ||
code = openmc | ||
template = "openmc_template.py" | ||
scores = ["nu-fission"] % Name of scores for OpenMC tallies. | ||
score_names = ["power"] % A more representative name for the scores. Optional but might be necessary for score names with | ||
% hyphens because Jinja and Workbench have difficulties reading hyphens. | ||
} | ||
} | ||
|
||
workflow_level1{ | ||
plugin = ID1 | ||
variables{ | ||
param(ax_ref) {value = 2.0} | ||
param(num_cool_pins) {value = 24} | ||
param(num_fuel_pins) {value = 44} | ||
param(Height_FC) {value = 2.0} | ||
param(Lattice_pitch) {value = 2.0} | ||
param(FuelPin_rad) {value = 0.9} | ||
param(cool_hole_rad) {value = 0.6} | ||
param(Coolant_channel_diam) {value = 0.012} | ||
param(Graphite_thickness) {value = 0.5} | ||
param(Assembly_pitch) {value = 17.3205080756887} | ||
param(lbp_rad) {value = 0.25} | ||
param(mod_ext_rad) {value = 0.90} | ||
param(shell_thick) {value = 0.05} | ||
param(liner_thick) {value = 0.007} | ||
param(control_pin_rad) {value = 9.9, unit = mm} | ||
param(cl) {value = 160.0} | ||
param(pf) {value = 40.0} | ||
param(temp) {value = 725.0} | ||
param(temp_F1) {value = 725.0} | ||
param(temp_F2) {value = 725.0} | ||
param(temp_F3) {value = 725.0} | ||
param(temp_F4) {value = 725.0} | ||
param(temp_F5) {value = 725.0} | ||
param(use_sab) = {bool = True} | ||
param(use_sab_BeO) = {bool = True} | ||
param(use_sab_YH2) = {bool = False} | ||
} | ||
} | ||
} |
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.
the setup worked great - very straightforward.