Archived OpenModelica forums. Posting is disabled.

Alternative forums include GitHub discussions or StackOverflow (make sure to read the Stack Overflow rules; you need to have well-formed questions)


Forgot password? | Forgot username? | Register

Code generation for non-linear systems

Code generation for non-linear systems

Hi,

I am not sure wheter I am correct, but it appears as OpenModelica generates inccorect code for the solving of non-linear systems.

In the generated C code a function is called from "functionAlgebraics" which calls a macro (start_nonlinear_system(68)) leading to the definition of the variable: double nls_fvec[68].
Later on a solver macro (solve_nonlinear_system) is called with a function pointer to some function which apperas to calculate some residual values. In this functions the results are written to a pointer pointing to nls_fvec. Here seems to be the problem, as some values are written beyond the allocated space (in my case up to index 74). I am not sure wheter I am correct here, as in some models the simulation runs correctly. However, I have a model where this seems to cause a segmentation fault crashing the simulation program.

Im am using OpenModelica (r11077).

Regards,

Michael

Edited by: mburisch - Feb-10-12 13:34:00

Re: Code generation for non-linear systems

Could you provide a model that shows this behaviour? I have not seen this in any code myself and need a starting point if I'm going to fix it.
Writing to a variable beyond this limit is pointless since the nonlinear solver will not consider this and you will either get wrong result or a crash.

Re: Code generation for non-linear systems

This only happends in one of our larger model under certain conditions. I will try to make a small model showing this behaviour.

Regards,
Michael

Re: Code generation for non-linear systems

Note: I have compiled the model using the gcc option "-fstack-protector-all" to check for buffer overflows and it reported an error (stack smashing) during execution.

Re: Code generation for non-linear systems

I was able to create a small model which reproduces the error. In my case the generated function "eqFunction_6" declares a non-linear system with with an array of size 12. In "residualFunc6", however, this array is accessed at index 15. Although for me this does not give a run-time error, it does corrupts the stack.

As uploading does not work for me, I post the model here:

Code:


package Medium
  function h_pt
    input Real p;
    input Real t;
    output Real h;
  algorithm
    h := t;
  end h_pt;
 
  function d_ph
    input Real p;
    input Real h;
    output Real d;
  algorithm
    d := h;
  end d_ph; 
end Medium;

connector Port
  flow Real mf;
  Real p;
  stream Real h;
end Port;


model Pipe
  Port port_a, port_b;
  Real loopPressure;
   
protected
  Real density;
  Real outputPressure;
 
  function func
    input Real inputPressure;
    input Real density;
    output Real outputPressure;
    output Real loopPressure;
  algorithm
    loopPressure := inputPressure;
    outputPressure := inputPressure;
  end func;

equation
  density = Medium.d_ph(port_a.p, port_a.h);
  (outputPressure, loopPressure) = func(port_a.p, density);

  port_a.mf + port_b.mf = 0;
  port_b.p = outputPressure;
  port_a.h = inStream(port_b.h);
  port_b.h = inStream(port_a.h);
end Pipe;

model Split
  Port port_a, port_b, port_c;
equation
  connect(port_a, port_b);
  connect(port_a, port_c); 
end Split;

model Join
  Port port_a, port_b, port_c;
  final parameter Real epsFlow = 1e-15;
equation
  port_a.mf + port_b.mf + port_c.mf = 0;
  port_b.p = min(port_a.p, port_c.p);
  port_a.h = (max(port_b.mf, epsFlow) * inStream(port_b.h) + max(port_c.mf, epsFlow) * inStream(port_c.h)) / (max(port_b.mf, epsFlow) + max(port_c.mf, epsFlow));
  port_b.h = (max(port_a.mf, epsFlow) * inStream(port_a.h) + max(port_c.mf, epsFlow) * inStream(port_c.h)) / (max(port_a.mf, epsFlow) + max(port_c.mf, epsFlow));
  port_c.h = (max(port_a.mf, epsFlow) * inStream(port_a.h) + max(port_b.mf, epsFlow) * inStream(port_b.h)) / (max(port_a.mf, epsFlow) + max(port_b.mf, epsFlow));
end Join; 

model Boundary
  Port port;
  Real t;
  Real mf;
  Real p;
equation
  port.mf = mf;
  port.p = p;
  port.h = Medium.h_pt(p, t);
end Boundary;

model Test
  Split[numberOfSplits - 1] split;
  Join[numberOfSplits - 1] join;                                                                 
  Pipe[numberOfSplits] pipe;
   
  Boundary source;
  Boundary sink;
   
  parameter Integer numberOfSplits = 2;   
  parameter Integer numberOfLoops = 10;
   
equation 
  source.mf = -10;
  source.p = 100000;
  source.t = 300;
  sink.t = 300;
 
  // Grid:
  //  split
  // --+--+---
  //   |  |  | pipe
  // --+--+---
  //  join
 
  connect(source.port, split[1].port_a);
 
  for i in 1:numberOfSplits - 1 loop
    connect(split[i].port_c, pipe[i].port_a);
    connect(pipe[i].port_b, join[i].port_c);

    split[i].port_c.mf = -source.port.mf / numberOfSplits;   
  end for;
 
 
  for i in 1:numberOfSplits - 2 loop
    connect(split[i].port_b, split[i + 1].port_a);
    connect(join[i + 1].port_b, join[i].port_a);
  end for; 
   
  connect(split[numberOfSplits - 1].port_b, pipe[numberOfSplits].port_a);
  connect(pipe[numberOfSplits].port_b, join[numberOfSplits - 1].port_a);
 
  connect(join[1].port_b, sink.port);
end Test;

I am using OpenModelica for Windows (r11098)

Regards,
Michael

Re: Code generation for non-linear systems

Thanks. Added a tl;dr; bug report here: http://openmodelica.org:8080/cb/issue/1692

Re: Code generation for non-linear systems

Seems to work with the new tearing implementation: https://trac.openmodelica.org/OpenModelica/ticket/1692

Re: Code generation for non-linear systems

Hey everybody,

Could anybody tell me how to generate c code for a model in modelica?

Thanks

There are 0 guests and 0 other users also viewing this topic
You are here: