2
votes

I'm developing a Modelica library, called "MyLib" (in the OpenModelica environment).

I wrote the following external C module ("ExtTempDataLib.c"):

#ifndef __EXT_LIB_C
#define __EXT_LIB_C

double temperatures [] = {25, 18, 30, 21, 16};

double GetTemperature(int index)
{
    // Modelica indexes start from 1
    return temperatures[index - 1];
}

void SetTemperature(int index, double newTempVal)
{
    // Modelica indexes start from 1
    temperatures[index - 1] = newTempVal;
}

#endif

It implements an array of numerical values ("temperatures") representing temperatures, which can be read/overwritten via the "GetTemperature(...)" and "SetTemperature(...)" functions.

The goal is to provide to the Modelica library a set of global data (i.e. accessible by all models) that are not constant.

Otherwise, I could simply declare the array as a constant inside my "MyData2" Modelica package:

constant Real temperatures [:] = {25, 18, 30, 21, 16};

and then directly access any of its elements (clearly in read-only mode) from any model by simply typing:

MyLib.MyData2.temperatures[index];

The "MyData" Modelica package:

within MyLib;
package MyData

model SingleTemperatureOverwrite
    parameter Integer index = 1 "Temperature data index";
    parameter Real newVal = 50 "New temperature value";
algorithm 
    when initial() then
        MyLib.MyData.SetTemperature(index, newVal);
    end when;
end SingleTemperatureOverwrite;


function GetTemperature
    input Integer index;
    output Real temperature;    
    external "C" temperature = GetTemperature(index);
    annotation(Include = "#include \"ExtTempDataLib.c\"");  
end GetTemperature;


function SetTemperature
    input Integer index;
    input Real newTempVal;
    external "C" SetTemperature(index, newTempVal);
    annotation(Include = "#include \"ExtTempDataLib.c\"");
end SetTemperature;

end MyData;

defines:

  • the "GetTemperature" and "SetTemperature" functions, which call the corresponding external C functions;
  • the "SingleTemperatureOverwrite" model, which, at the initial time, overwrites the array value at the specified index with the specified new value (parameters "index" and "newVal", respectively).

The "Test" Modelica package:

within MyLib;
package Test

model TemperatureTest
    parameter Integer index = 1 "Temperature data index";
    Real temperature (start = 0) "Temperature value";
equation
    temperature = MyLib.MyData.GetTemperature(index);
end TemperatureTest;

end Test;

defines the "TemperatureTest" model, which reads the array value at the specified index (the "index" parameter) and "copies" it to the "temperature" variable.

I created a Modelica test model, including just one instance of "SingleTemperatureOverwrite" and one of "TemperatureTest" ("singleTemperatureOverwrite1" and "temperatureTest1", respectively), leaving all parameters at their default value.

The model compiles and executes correctly but, when I plot the "temperature" variable of "temperatureTest1", instead of getting "50", as I expected, I get "25" (i.e. the starting value of the first element of the array defined in the external C module).

Can somebody please explain me what I'm doing wrong?

3

3 Answers

2
votes

There is no causal link between the two equations so they may execute in an arbitrary order. If you want global, mutable variables in Modelica, I suggest using the inner/outer concept instead of external C. (Or perhaps using external object to enforce execution order)

0
votes

Would the following work for you?

package GlobalParameter
  model ExampleComponent
    outer parameter Real tValue[5];
  end ExampleComponent;

  model TestT
    ExampleComponent component1;
    ExampleComponent component2;
    inner parameter Real tValue=1:5;
  end TestT;
end GlobalParameter;
0
votes

Ok how about this then:

package GlobalParameter

  model SetTValue
    outer Real tValue[5];
    parameter Integer index;
    parameter Real value;
  equation 
    tValue[index] = value;
  end SetTValue;

  model TestT
    SetTValue set1(index=1, value=1);
    SetTValue set2(index=2, value=2);
    SetTValue set3(index=3, value=3);
    SetTValue set4(index=4, value=4);
    SetTValue set5(index=5, value=5);

    inner Real tValue[5];
  end TestT;
end GlobalParameter;

You do not need to make use of component# (where # is 1-5) but could just use them as a way to set elements of tValue.

A disadvantage of this method is that the SetTValue model is not balanced also to set an index you need to create an instance of SetTValue. However this approach avoids using external C code.