There are certain requirements for setting the size of an array to a parameter in Modelica. This post has a closer look into what these requirements are.
A simple example
Figure 1 is a simple example of sizing vector b with parameter n.
In the example in Figure 1 it appears that n is a parameter, however during translation n is evaluated so effectively n is replaced with the value 2. To clarify this behaviour, use annotation (Evaluate=true) after the size parameter as in Figure 2.
As Modelica does not support variable array sizes after translation the sizing parameter needs to be a literal value.
Attempting to read an array from a XML file
In the following example the ExternData library is used to read data from an XML file.
The example in Figure 3 is an example where an array of unknown size is attempted to be read from an XML file.
In this example xmlfile is an external object. At initialisation the xmlfile constructor is called and xmlfile is allocated a pointer to an external structure. So xmlfile is assigned at initialisation and not at translation.
numberOfTanks is assigned with the xmlfile.getArraySize1D() function. This function is defined as Functions.XML.getArraySize1D(xml=xml) in ExternData.XMLFile where xml is set to xmlfile.
Hence numberOfTanks is dependent on the parameter xmlfile which cannot be evaluated, and so numberOfTanks cannot be evaluated; hence the model cannot translate.
Reading an array of unknown size from a XML file
To get around the errors in Figure 3 the ExternData XML reader has to be modified. This can be done by creating a separate XML reader library that makes use of the ExternData XML reader functions; however, it stores the xmlFile structure inside the external C code.
The full details of this workaround XML reader is beyond the scope of this blog post. However, the Modelica code is provided below to show how the sizing parameter will be read.
Unfortunately the lack of external object makes working with more than one XML file more complex and in this example only one XML file can be read by a model. Also at termination the destructor has to be called from the Modelica code; this is done using ReadOneXMLNoObject.XMLdestructor().
The ReadOneXMLNoObject.getArraySize1D() function used to set numberOfTanks contains only literal values, so this parameter can be evaluated at translation.
The example in Figure 4 reads the XML file in Figure 5.
Once this model is translated the “multiTank.tankHeights” array element in Figure 5 can be modified between simulations. However, if the size of this array is modified then the model will have to be re-translated.
The source code for the example above can be downloaded from here.
- The sizing parameter should use annotation (Evaluate=true)
- This sizing parameter must be able to be evaluated during translation.
Written by: Garron Fish – Chief Engineer