Hey everyone,
I should have started posting updates for GSoC Working Period a week ago, but some difficulties in grasping how to do things properly, along with some of my academic research tasks, prevented me from having something worth publishing. I apologize for that.
On the bright side, when I decided to look for some material about Xcos blocks (what I should have done from the beginning), instead of trying to figure out everything by looking at the code, I quickly stumbled upon this document detailing pretty much anything I needed on Scilab’s side.
Scilab/Xcos block structure
As it turns out, the way each type of Xcos block operates is basically defined by 2 functions: a interfacing and a computational one. Both implement their respective standardized interfaces, in a way that the simulator handles any block as a black box with inputs and outputs, without being aware of its internals.
The interfacing function, always written in Scilab language, builds the pop-up window listing the modifiable properties for a given block. It also acts as a glue between generic simulation (time updates and numerical solvers) code and the specific computation code for that block. Its implementation for OpenModelica integration will be covered in more detail in the future.
(Properties window for "Random Delay" Xcos block)
Computational funtions could be written in either C or Scilab language, which defines the block type (4 or 5, respectively, with lower values being used for legacy block types). In the case of Modelica blocks, as there is no Scilab code generation available for OMCompiler, we must implement a C function with signature like:
Where scicos_block is a generic block data structure type, declared in the header scicos_block4.h:
The integer flag informs the current calculation stage, as our function can be called many times during a single simulator iteration, for different purposes. Each stage flag value is indicative which fields from the scicos_block parameter should be considered as inputs, and how the function is expected to fill the outputs:
flags | inputs | outputs | description |
---|---|---|---|
0 | t, nevprt, x, z, inptr, mode, phase | xd, res | compute the derivative of continuous time state |
1 | t, nevprt, x, z, inptr, mode, phase | outptr | compute the outputs of the block |
2 | t, nevprt>0, x, z, inptr | x, z | update states due to external activation |
2 | t, nevprt=-1, x, z, inptr, jroot | x, z | update states due to internal zero-crossing |
3 | t, x, z, inptr, jroot | evout | program activation output delay times |
4 | t, x, z | x, z, outptr | initialize states and other initializations |
5 | x, z, inptr | x, z, outptr | final call to block for ending the simulation |
6 | t, nevprt, x, z, inptr, mode, phase | x, z, outptr | reinitialization (if needed) |
7 | only used for internally implicit blocks | ||
9 | t, phase=1, nevprt, x, z, inptr | g, mode | compute zero-crossing surfaces and set modes |
9 | t, phase=2, nevprt, x, z, inptr | g | compute zero-crossing surfaces |
10 | t, nevprt, x, z, inptr, mode, phase | res | compute jacobian matrix |
Hooking things up
Currently in Scilab, its customized modelicac compiler is able to generate an implementation of the computational function directly from Modelica code. For OMCompiler, one is only able to generate a FMI2 interface implementation, so some generic wrapper code is needed.
From now on, I plan to (as soon as possible) start writing this wrapper and showing you how FMI2 calls are performed for each one of the simulation stages.
Thanks for sticking with me one more time. See Ya !