3

I would like to export a Modelica model as an FMU for Co-simulation using Dymola 2014. I plan to complete the co-simulation using pyfmi.

To test this I am trying to model fluid flow through a pipe between two fluid boundaries. I would like the pressure of the fluid source to be an input to the model. My plan is to calculate this pressure externally and input to the Modelica model at each timestep.

My initial model with all standard library components is:

model SE_BVP "BVP for stack exchange."
  inner Modelica.Fluid.System system;
  Modelica.Fluid.Pipes.StaticPipe pipe(
    redeclare package Medium = Modelica.Media.Air.MoistAir,
    length=1,
    diameter=1);
  Modelica.Fluid.Sources.Boundary_pT boundary1(nPorts=1, redeclare package
    Medium = Modelica.Media.Air.MoistAir);
  Modelica.Fluid.Sources.Boundary_pT boundary(nPorts=1, redeclare package Medium=
    Modelica.Media.Air.MoistAir, use_p_in=true);
  Modelica.Blocks.Interfaces.RealInput p_in1;

equation
   connect(pipe.port_b, boundary1.ports[1]);
   connect(boundary.ports[1], pipe.port_a);
   connect(boundary.p_in, p_in1);
end SE_BVP;

Which I then wrapped in two test models:

model SE_BVP_test_1
 Real preVal = 101335;
 SE_BVP SE_BVP_1;

equation
 SE_BVP_1.p_in1 = preVal;

end SE_BVP_test_1; 

and with the parameter type, which was done based on the suggestion of @Thierry

model SE_BVP_test_2
  parameter Real preVal = 101335;
  SE_BVP SE_BVP_1;

equation
  SE_BVP_1.p_in1 = preVal;

end SE_BVP_test_2; 

Running these models give me the same results:

No Variable typing.

and

With parameter typing

Both models are working within Dymola.

Now I wish to load the fmu and simulate using pyfmi so I wrote this script:

  import pyfmi
  import numpy as np
  import pylab as P
  import os

  # Define the FMU to test
  fmuDirNam = "SE_BVP_Test_1"  # CS 2.0 type FMU
  fmuNam = fmuDirNam + ".fmu"

  # Define the input var
  inVar = "preVal"

  # Get the path to the FMU
  curr_dir = os.path.dirname(os.path.abspath(__file__))
  par_dir = os.path.dirname(curr_dir)
  path_to_fmu = os.path.join(par_dir, "projectFMUs", fmuDirNam)

  # Load the model
  model = pyfmi.load_fmu(os.path.join(path_to_fmu, fmuNam))

Which fails and gives me the following error:

FMIL: module = FMI2XML, log level = 2: XML element 
'Real': could not parse value for real attribute  
 'start'='pipMod.pipe.flowModel.states[1].p/(gasConstant_Unique7( 
      Modelica.Media.Air.MoistAir.ThermodynamicState(     
 p =

FMIL: module = FMI2XML, log level = 2: XML element 
'Real': could not parse value for   real attribute 
'start'='pipMod.pipe.flowModel.states[2].p/(gasConstant_Unique7(             
Modelica.Media.Air.MoistAir.ThermodynamicState(             
p =

FMIL: module = FMI2XML, log level = 2: XML element 
'Real': could not parse value for real attribute 
'start'='Modelica.Media.Incompressible.TableBased.Polynomials_Temp.evaluate({-4.96717436974791E-11, 5.06626785714286E-08, 1.72937731092437
FMIL: module = FMI2XML, log level = 2: XML element 'Real': could not parse value for real attribute 
'start'='Modelica.Media.Incompressible.TableBased.Polynomials_Temp.evaluate({-4.96717436974791E-11, 5.06626785714286E-08, 1.72937731092437

FMIL: module = FMI2XML, log level = 1: No model structure information available. 
Cannot continue.

FMIL: module = FMI2XML, log level = 1: Parse error at line 2703:
parsing aborted

From the Traceback:

pyfmi.fmi.FMUException: The XML-could not be read. Parse error at line 2703:
parsing aborted

What could be causing this parse error given that the model simulates correctly within Dymola?

  • I tried this also with a CS 1.0 export and raised the same exception albeit with a different module reading the fmu this time.

  • I considered that by removing both the input and parameter tags some mysterious variable issue emerged, but no. Even with the parameter tag as in Test_2 I raise the same exception (CS 2.0).

Summary: Dymola 2014, python 2.7.x, FMI for CO-simulation 2.0

Michael Street
  • 645
  • 1
  • 7
  • 19

5 Answers5

4

@RwardBound: If you want to change parameters during simulations, then I will suggest to use FMI 2.0 rather than FMI 1.0 FMUs. This feature is supported in FMI 2.0. Latest version of Dymola for instance are capable of generating such FMUs. I think that PyFMI also supports FMI 2.0.

All the best, Thierry

  • Thanks, implemented the suggestion. An additional solution is to remove the `parameter` and `input` specifiers completely. Each solution works in Dymola, but parsing of exported FMU fails in pyfmi. – Michael Street Aug 15 '14 at 12:51
3

The problem is due to that the XML produced by Dymola is incorrect. The start attribute for a scalar-variable has to be a value, not an expression, all according to the specification. The specification states that for a real scalar-variable the start value has to be a float and for integers the start value should be an int and so forth. This is also true for both FMI 1.0 and FMI 2.0 (the spec. can be read at https://fmi-standard.org/downloads).

In order to verify that the FMU you get is correct according to the standard there is a tool called the Compliance Checker which is also available at the above mentioned site. This is a great tool to use if you encounter these types of problems in order to rule out that the exporting tool is the cause of the problem.

With Dymola 2015, the XML is correctly generated for the model SE_BVP_test_1 and can be simulated using PyFMI.

Christian Winther
  • 1,113
  • 1
  • 9
  • 17
1

The best practice to test a Dymola model in order to be exported as FMU (or as a Modelica library as well) is to build a top model for testing. Then you can build a simulation environment dedicated to the exported model.

Let's take a simple "divide 10/u" model example:

model div10
  Modelica.Blocks.Math.Division division;
  Modelica.Blocks.Interfaces.RealInput u(start=10);
equation 
  division.u1 = 10;
  connect(division.u2, u);
end div10;

Then you have to create this top model to test your div10 model:

   model div10_tester  
      parameter Real default_u = 2.0;
      div10 div10_1;
    equation 
      div10_1.u = default_u;
    end div10_tester;

Another solution could be to use the "dsu.txt" (Note: if you simulate div10 alone, the start=10 statement will have no effect, as mentionned by your error log : if no "dsu.txt" file => all inputs are set to 0). But this is very limited since it only specifies the start values.

  • Thanks for the post. My problem is that I cannot change `parameter` variables during co-simulation. I would need the variable to be of type `input`, which if I change `input Real default_u = 2.0` in your snippet the code will fail. I don't understand why this value is not used as an initial value throughout the simulation. – Michael Street Aug 14 '14 at 12:48
  • By removing the specifier `parameter` and `input` from the model div10_tester the model will run. – Michael Street Aug 15 '14 at 12:49
1

an easy way to work around that input=0 at initialization is probably to add a max() block to compare your input with some very small number.

For example:

input = max(a very small positive number, input) if your input is always greater than zero. 

If your parameter(input) will switch signs, I believe you are smart enough to find similar ways to do it.

Hang Yu
  • 476
  • 2
  • 14
1

The issue is with the Media model selected. Modelica.Media.Air.MoistAir is a pressure and temperature coupled model of the air state. Therefore the initial values of fluid density, enthalpy, etc. are functions of the boundary pressure. During the export to FMU the start value for the state variables of the fluid within the pipe are written to the XML file as expressions:

<ScalarVariable
   name="SE_BVP_1.pipe.flowModel.rhos[1]"
   valueReference="100663348"
   variability="constant">
<Real
  unit="kg/m3"
  min="0.0"
   start="SE_BVP_1.pipe.flowModel.states[1].p/(gasConstant_Unique7(
     Modelica.Media.Air.MoistAir.ThermodynamicState(
       p = SE_BVP_1.pipe.flowModel.states[1].p,
       T = SE_BVP_1.pipe.flowModel.states[1].T,
       X = {SE_BVP_1.pipe.flowModel.states[1].X[1],
                       SE_BVP_1.pipe.flowModel.states[1].X[2]}
            ))*SE_BVP_1.pipe.flowModel.states[1].T)"/>

Changing the fluid to Buildings.Media.GasesPTDecoupled.MoistAirUnsaturated removes the start value calculation and the XML reads:

<ScalarVariable
   name="SE_BVP_1.pipe.flowModel.rhos[1]"
          valueReference="100663345"
   variability="fixed">
<Real
  unit="kg/m3"
  min="0.0"/>

pyfmi does not evaluate expressions during the parse and instead expects a string that can be formatted to a float.

Michael Street
  • 645
  • 1
  • 7
  • 19