Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
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
2 changes: 1 addition & 1 deletion conda/moose-dev/conda_build_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ moose_wasp:
- moose-wasp 2025.09.18

moose_tools:
- moose-tools 2025.06.26
- moose-tools 2025.10.07

zip_keys:
- mpi
Expand Down
2 changes: 1 addition & 1 deletion conda/moose-dev/meta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# REMEMBER TO UPDATE the .yaml files for the following packages:
# moose/conda_build_config.yaml
# As well as any directions pertaining to modifying those files.
{% set version = "2025.09.18" %}
{% set version = "2025.10.07" %}

package:
name: moose-dev
Expand Down
2 changes: 1 addition & 1 deletion conda/moose/conda_build_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ mpi:
- mpich

moose_dev:
- moose-dev 2025.09.18
- moose-dev 2025.10.07

#### Darwin SDK SYSROOT
CONDA_BUILD_SYSROOT: # [osx]
Expand Down
4 changes: 3 additions & 1 deletion conda/tools/meta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# moose-dev/*
#
# As well as any directions pertaining to modifying those files.
{% set version = "2025.06.26" %}
{% set version = "2025.10.07" %}

package:
name: moose-tools
Expand Down Expand Up @@ -32,6 +32,7 @@ requirements:
- {{ clang_format }}
- {{ clang_tools }}
- deepdiff
- fmpy
- git-lfs <3.5.1
- gitpython
- graphviz
Expand Down Expand Up @@ -75,6 +76,7 @@ test:
imports:
- bs4
- deepdiff
- fmpy
- git
- jinja2
- livereload
Expand Down
2 changes: 2 additions & 0 deletions conda/tools/meta.yaml.template
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ requirements:
- {{ clang_format }}
- {{ clang_tools }}
- deepdiff
- fmpy
- git-lfs <3.5.1
- gitpython
- graphviz
Expand Down Expand Up @@ -75,6 +76,7 @@ test:
imports:
- bs4
- deepdiff
- fmpy
- git
- jinja2
- livereload
Expand Down
145 changes: 145 additions & 0 deletions framework/doc/content/source/controls/MOOSEFMU.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
# MOOSE FMU Interface

The `MOOSEFMU` defines the `Moose2FMU` base class which contains the boilerplate needed to wrap a MOOSE simulation as a Functional Mock-up Unit (FMU). Users only need to implement their own `__init__` and `do_step` methods when deriving from `Moose2FMU`.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
The `MOOSEFMU` defines the `Moose2FMU` base class which contains the boilerplate needed to wrap a MOOSE simulation as a Functional Mock-up Unit (FMU). Users only need to implement their own `__init__` and `do_step` methods when deriving from `Moose2FMU`.
The `MOOSEFMU` defines the `Moose2FMU` Python base class which contains the boilerplate needed to wrap a MOOSE simulation as a Functional Mock-up Unit (FMU). Users only need to implement their own `__init__` and `do_step` methods when deriving from `Moose2FMU`.

Copy link
Contributor

Choose a reason for hiding this comment

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

what standard did you implement for FMU ? 2? 3? do we have the whole standard implemented or partiaL?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We support FMU 2 standard. The whole standard is implemented by pythonFMU and we use that to build MOOSE FMU


### Initialization Parameters

`Moose2FMU` accepts a number of keyword arguments that configure how the
underlying MOOSE simulation is launched and interacted with:

- `flag`: Optional flag that is forwarded to the MOOSE input deck.
Copy link
Contributor

Choose a reason for hiding this comment

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

how to pass multiple?
-flag a -flag b ? or -flag a b ?

Copy link
Contributor

Choose a reason for hiding this comment

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

is the rules for spaces same as for CLI args?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

is the rules for spaces same as for CLI args?

Yes, this is just pass CLI args to MOOSE control. I can add an example here to show it. I keep all the examples in moose_fmu folder. I can refer that here

- `moose_mpi` / `mpi_num`: Configure MPI launching when running distributed
MOOSE executables.
- `moose_executable` / `moose_inputfile`: Path to the simulation binary and the
input file that should be executed inside the FMU.
- `server_name`: Name of the `MooseControl` server block to connect to.
- `max_retries`: Number of times helper utilities will poll the control server
before aborting.
- `dt_tolerance`: Permitted synchronization tolerance between FMU time and the
MOOSE simulation clock.

The class also exposes a ``default_experiment`` that can be customized if the
FMU should advertise a different start/stop time or nominal step size.


### Runtime helpers

`Moose2FMU` provides a small collection of convenience methods that simplify
interacting with a running MOOSE simulation:

- `set_controllable_real` and `set_controllable_vector` push new controllable
Copy link
Contributor

Choose a reason for hiding this comment

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

vectors are controllable now?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In MOOSE web server control, controllable_vector is supported so I just include the option here. Not quiet sure if controllable vector actually used anywhere in the code. Maybe under stochastic tools? Here I just provide APIs we have in MOOSE web server control

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 check, let's get a test

values to the `WebServerControl` system. Values are cached to avoid
redundant updates; pass ``force=True`` to resend a value that was already
applied.
- `sync_with_moose` advances the FMU time until it matches the simulation time
within `dt_tolerance`. Additional synchronization flags can be supplied via
the optional `allowed_flags` argument.
- `ensure_control_listening` verifies the control socket is ready before any
postprocessors or reporters are queried.
- `get_postprocessor_value` and `get_reporter_value` wait for a specific
synchronization flag and return the requested quantity.
- `get_flag_with_retries` normalizes retry logic when polling MOOSE for the
next synchronization flag.

Together these helpers reduce the boilerplate needed inside a custom
`do_step` implementation and make it easier to write robust coupling logic.

### Synchronization and data retrieval flags

`Moose2FMU` coordinates with the running MOOSE simulation through named
`MooseControl` flags. To simplify typical multiapp workflows the base class
waits for a set of synchronization signals by default:

- `INITIAL` and `MULTIAPP_FIXED_POINT_BEGIN` are consumed before attempting to
advance the coupled simulation. `MULTIAPP_FIXED_POINT_BEGIN` is the first flag
raised immediately after the new time step has been computed, so listening
for it gives the FMU the earliest opportunity to synchronize clocks.
- `MULTIAPP_FIXED_POINT_END` is consumed before any reporter or postprocessor
values are retrieved. In a typical execution order controls run ahead of
reporters and postprocessors, and those objects usually execute at
`TIMESTEP_END`. The `MULTIAPP_FIXED_POINT_END` flag fires right after
`TIMESTEP_END`, ensuring the data pulled from MOOSE reflects the updated state
of the current time step.

Any flag string supplied through the `flag` initialization argument is merged
into these defaults, and the higher-level helpers such as
`set_controllable_real`, `set_controllable_vector`, `get_reporter_value`, and
`get_postprocessor_value` also accept per-call `flag` arguments. Passing custom
flags in these locations allows FMUs to react to user-defined synchronization
points while still benefiting from the built-in defaults. Refer to
[SetupInterface.md]for additional details on
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
[SetupInterface.md]for additional details on
[SetupInterface.md] for additional details on

MOOSE execute flags.

### Creating a Custom FMU

Copy link
Contributor

Choose a reason for hiding this comment

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

is there a script you could use a listing from instead?

```python
from MooseFMU import Moose2FMU


class CustomMoose(Moose2FMU):
def __init__(self, **kwargs):
super().__init__(**kwargs)
# register additional inputs/outputs here

def do_step(
self,
current_time: float,
step_size: float,
no_set_fmu_state_prior: bool = False,
) -> bool:
# advance the MOOSE simulation and update outputs
return True
```

A typical step method will synchronize with MOOSE and make use of the helper
utilities described above:

```python
def do_step(self, current_time: float, step_size: float, **_kwargs) -> bool:
moose_time, signal = self.sync_with_moose(current_time, step_size)
if moose_time is None:
return False

if signal == "MULTIAPP_FIXED_POINT_END":
diffused = self.get_postprocessor_value(signal, "diffused", current_time)
if diffused is None:
return False
self.diffused = diffused

self.set_controllable_real("BCs/boundary", 1.0)
return True
```

### Building the FMU

Save the custom class in a Python file and use [`pythonfmu`](https://github.com/NTNU-IHB/PythonFMU) to build the FMU:

```bash
Copy link
Contributor

Choose a reason for hiding this comment

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

so we dont include this package in our conda distrib? not through fmpy?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We include pythonfmu in conda, but to build a MOOSE fmu customized fmu input, output, you still use pythonfmu build command to do that. We don't need to install pythonfmu package every time we want to build fmu

Copy link
Contributor

Choose a reason for hiding this comment

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

I dont see a pythonfmu new package in conda?
Does it come with fmpy?

pythonfmu build custom_moose.py
```

The resulting `.fmu` file can then be imported into any compliant co-simulation environment.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
The resulting `.fmu` file can then be imported into any compliant co-simulation environment.
The resulting `.fmu` file can then be imported into any standard-compliant co-simulation environment.


### Testing the FMU

Sample helper scripts in `test/tests/controls/moose_fmu` demonstrate how to exercise a
generated FMU with [`fmpy`](https://github.com/CATIA-Systems/FMPy):

- `run_fmu.py` runs `MooseTest.fmu` in a stand-alone mode using `simulate_fmu` and
prints the time, `moose_time` and `diffused` outputs.
- `run_fmu_connection.py` shows how to couple `MooseTest.fmu` with another FMU (e.g.,
`Dahlquist.fmu`) and change boundary conditions during the simulation.

To try the examples:

```bash
cd test/tests/controls/moose_fmu
python run_fmu.py # stand‑alone Moose FMU
python run_fmu_connection.py # coupled FMUs example
```

!syntax parameters /Controls/MOOSEFMU

!syntax inputs /Controls/MOOSEFMU

Comment on lines +141 to +144
Copy link
Contributor

Choose a reason for hiding this comment

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

I dont see a MOOSEFMU class registered? this shouldt work, what am I missing

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch, I'll fix it

!syntax children /Controls/MOOSEFMU
Loading