Skip to content
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

Open
wants to merge 22 commits into
base: development
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
executable to be used ([#75](https://github.com/watts-dev/watts/pull/75))
* A `verbose` argument has been added to `Plugin.__call__` that controls whether
screen output is printed ([#82](https://github.com/watts-dev/watts/pull/82))
* Develop capability to run WATTS with NEAMS Workbench.

## [0.4.0]

Expand Down
103 changes: 103 additions & 0 deletions doc/source/dev/workbench.rst
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.
227 changes: 227 additions & 0 deletions doc/source/user/workbench.rst
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.

Copy link
Contributor

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.

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::

Copy link
Contributor

Choose a reason for hiding this comment

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

We need a plugin.tmpl template that has all these options listed out that a user can autocomplete.

`code` : Name of the application
Copy link
Contributor

Choose a reason for hiding this comment

The 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"}
Copy link
Contributor

Choose a reason for hiding this comment

The 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.
2 changes: 1 addition & 1 deletion examples/1App_OpenMC_VHTR/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ This example provides a demonstration on how to use WATTS to perform a single SA

- [__watts_exec.py__](watts_exec.py): WATTS workflow for this example. This is the file to execute to run the problem described above.
- [__openmc_template__](openmc_template.py): OpenMC templated model.

- [__watts_wb.son__](watts_wb.son): Workbench input file for this example.
43 changes: 43 additions & 0 deletions examples/1App_OpenMC_VHTR/watts_wb.son
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}
}
}
}
1 change: 1 addition & 0 deletions examples/1App_PyARC_UnitCell/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ This example provides a demonstration on how to use WATTS to perform a single Py
- [__watts_exec.py__](watts_exec.py): WATTS workflow for this example. This is the file to execute to run the problem described above.
- [__pyarc_template__](pyarc_template): PyARC templated input file.
- [__lumped.son__](lumped.son): SON file referenced in PyARC input with description of lumped fission products.
- [__watts_wb.son__](watts_wb.son): Workbench input file for this example.
Loading