|
| 1 | +******************************************************* |
| 2 | +Guideline on how to develop a FMU using component-model |
| 3 | +******************************************************* |
| 4 | + |
| 5 | +The development process follows the steps |
| 6 | + |
| 7 | +#. Develop a functional model using Python (>=3.10.) as a Python class. Called *basic model* here. |
| 8 | +#. Thoroughly test the basic model. |
| 9 | +#. Define the FMU interface using component-model functions |
| 10 | +#. Build the FMU calling `Model.build()`, optionally overwriting optional argument of the model class. |
| 11 | +#. Test the FMU standalone, e.g. using the `FMPy` package or in conjunction with other FMUs using the `sim-explorer` package. |
| 12 | + |
| 13 | +Develop a basic model |
| 14 | +===================== |
| 15 | +Define a functional model as a Python class. We refer to this model as the *basic model*. |
| 16 | +At this stage the emerging model class does not need to refer to the `component-model` package. |
| 17 | +In fact it is **not recommended** to derive the basic model from `Model`class of component-model. |
| 18 | +The basic model might import any Python package (e.g. numpy), as needed to satisfy the functionality. |
| 19 | + |
| 20 | +Testing the basic model |
| 21 | +======================= |
| 22 | +The basic model should be thoroughly tested. |
| 23 | +This cannot be emphasised too much, as test possibilities and feadback is limited in the FMU domain, |
| 24 | +while Python offers proper test and debugging facilities. |
| 25 | + |
| 26 | + |
| 27 | +Defining the FMU interface |
| 28 | +========================== |
| 29 | +A FMU interface must be added to the model prior to package the model as FMU. This concerns basically |
| 30 | + |
| 31 | +* component model parameters, i.e. settings which can be changed prior to a simulation run, but are typically constant during the run |
| 32 | +* component model input variables, i.e. variables which can be changed based on the output from other component models |
| 33 | +* component model output variables, i.e. results which are provided to any connected component model, or the system. |
| 34 | + |
| 35 | +Defining the interface is done like |
| 36 | + |
| 37 | +.. code-block:: Python |
| 38 | +
|
| 39 | + class <basic-model>_FMU(Model, <basic-model>): |
| 40 | + def __init__(self, <basic_model_args, **kwargs): |
| 41 | + Model.__init__(self,name,description,author,version, kwargs) |
| 42 | + <basic-model>.__init__(<basic-model-args>) |
| 43 | +
|
| 44 | +
|
| 45 | +Virtual derivatives |
| 46 | +------------------- |
| 47 | +Running component models in scenarios it is often necessary to change variables during the simulation run. |
| 48 | +As in the reality it is often not a good idea to step values in huge steps, as this resembles a 'hammer stroke', |
| 49 | +which the system might not tolerate. The simulation dynamics does often not handle such a situation properly either. |
| 50 | +It is therefore often necessary to ramp up or down values to the desired final values, |
| 51 | +i.e. changing the derivative of the input variable to a non-zero value |
| 52 | +until the desired value of the parent variable is reached and then setting the derivative back to zero. |
| 53 | + |
| 54 | +It is cumbersome to introduce derivative variables for every parent variable which might be changed during the simulation. |
| 55 | +Therefore. component-model introduces the concept of *virtual derivatives*, |
| 56 | +which are derivative interface variables which are not linked to variables in the basic model. |
| 57 | +When defining such variables and setting them to non-zero values, |
| 58 | +the parent variable is changed with the given slope at every time step, |
| 59 | +i.e. |
| 60 | + |
| 61 | +`<parent-variable> += d<parent-variable>/dt * <step-size>` |
| 62 | + |
| 63 | +where `d<parent-variable>/dt` is the non-zero derivative value (slope). |
| 64 | + |
| 65 | +In practical terms, virtual derivatives are defined using FMI structured variables syntax: |
| 66 | + |
| 67 | +.. code-block:: Python |
| 68 | +
|
| 69 | + Variable( name='der(<parent-variable-name>)', causality='input', variability='continuous', ...) |
| 70 | +
|
| 71 | +Explicit specification of the arguments `owner` and `local_name` should be avoided. |
| 72 | +Specification of `local_name` changes the virtual derivative into a non-virtual derivative, |
| 73 | +i.e. the variable is expected to exist in the basic model. |
| 74 | +The `on_step` argument is automatically set to change the parent variable at every time step if the derivative is non-zero. |
| 75 | +Explicitly overwriting the automatic `on_step` function is allowed at one's own expense. |
| 76 | + |
| 77 | + |
| 78 | +Building the FMU |
| 79 | +================ |
| 80 | + |
| 81 | +Testing the FMU |
| 82 | +=============== |
0 commit comments