How to interface C with Modelica?

59 views Asked by At

Background

I am learning Modelica lang and following Modelica By Example, page by page, and have arrived at interpolation. The software-in-the-loop page has a similar approach, using C scripts in Modelica: SITL.

I am using OpenModelica Connection Editor to run the MBE scripts, which are written in VS Code (I'm open to other approaches). However, I am struggling to interface the two languages, in both situations.

Here are my SITL scripts, as per MBE:

Model

model HysteresisEmbeddedControl "A control strategy that uses embedded C code"
  type HeatCapacitance=Real(unit="J/K");
  type Temperature=Real(unit="K");
  type Heat=Real(unit="W");
  type Mass=Real(unit="kg");
  type HeatTransferCoefficient=Real(unit="W/K");
  parameter HeatCapacitance C=1.0;
  parameter HeatTransferCoefficient h=2.0;
  parameter Heat Qcapacity=25.0;
  parameter Temperature Tamb=285;
  parameter Temperature Tbar=295;
  Temperature T;
  Heat Q;
initial equation
  T = Tbar+5;
equation
  when sample(0, 0.01) then
    Q = computeHeat(T, Tbar, Qcapacity);
  end when;
  C*der(T) = Q-h*(T-Tamb);
end HysteresisEmbeddedControl;

Function

impure function computeHeat "Modelica wrapper for an embedded C controller"
  input Real T;
  input Real Tbar;
  input Real Q;
  output Real heat;
  external "C" annotation (Include="#include \"ComputeHeat.c\"",
    IncludeDirectory="C:\dev\OpenModelica\modelica_by_example\working_with_C\SITL\ComputeHeat.c");
end computeHeat;

C Script

#ifndef _COMPUTE_HEAT_C_
#define _COMPUTE_HEAT_C_

#define UNINITIALIZED -1
#define ON 1
#define OFF 0

double
computeHeat(double T, double Tbar, double Q) {
  static int state = UNINITIALIZED;
  if (state==UNINITIALIZED) {
    if (T>Tbar) state = OFF;
    else state = ON;
  }
  if (state==OFF && T<Tbar-2) state = ON;
  if (state==ON && T>Tbar+2) state = OFF;

  if (state==ON) return Q;
  else return 0;
}

#endif

Error

In file included from HysteresisEmbeddedControl_functions.c:7:
./HysteresisEmbeddedControl_includes.h:7:10: fatal error: 'ComputeHeat.c' file not found
#include "ComputeHeat.c"
         ^~~~~~~~~~~~~~~
1 error generated.
mingw32-make: *** [<builtin>: HysteresisEmbeddedControl_functions.o] Error 1
mingw32-make: *** Waiting for unfinished jobs....
mingw32-make: Leaving directory 'C:/Users/szuddas/AppData/Local/Temp/OPENMO~1/OMEdit/HYSTER~2'
Compilation process failed. Exited with code 0x00000002.

My Assumptions

I believe the problem is to do with paths of the scripts, and I probably need to better set up my modelica dev environment. I've used some C before but only covered the basics, and that was a few years ago. However, I don't believe this problem originates from the C code, more likely where the scripts are vs where they should be. Open to suggestions on all these fronts.

Where I was going wrong

The MBE book assumes you're using the MBE library, installed within OpenModelica itself. I was writing my own scripts, rather than running the scripts made in the library. In the MBE library, the C script was being called from a subdirectory where the Modelica script itself was located. When using the MBE library itself, it worked!

Where I'm still stuck

Despite getting the script working, I'm stuck with calling the C script. I've adjusted the \ and called both of the following:


IncludeDirectory="C:\dev\OpenModelica\modelica_by_example\working_with_C\SITL\ComputeHeat.c");

and


IncludeDirectory="C:\dev\OpenModelica\modelica_by_example\working_with_C\SITL");

I still do not understand why it's not being called in my script which is not part of the MBE library, considering I'm giving it the direct path.

0

There are 0 answers