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

External function using output of an other one.

External function using output of an other one.

Hi guys, I have a little problem with the execution of an external C function in openmodelica.
Here is the program that I'm trying to implement :

model ChirpSignal
  record Rec
    Real a1;
    Real a2;
    Real a3;
    Real a4;
    Real a5;

  end Rec;

  function Chirp
    output Rec u1;
 
    external  Chirp(u1) annotation(Library = "Chirp");
  end Chirp;

  function mafonction
    input Rec u;
    output Rec u1;
 
    external u1 = mafonction(u) annotation(Library = "Chirp");
  end mafonction;

  Rec u1;
  Rec u2;
 
equation
  u1 = Chirp();
  u2 = mafonction(u1);
end ChirpSignal;

// the C program is :


typedef struct  {

double id ;
double id1 ;
double id2;
double id3;
double id4;

}rec;


rec* Chirp(rec* test)
{

test->id = 7;
test->id1 = 6;
test->id2 = 5;
test->id3 = 4;
test->id4 = 15;

}

rec* mafonction(rec test,rec* test1)
{

memcpy ( &test1, &test, sizeof(rec) );

return test1;
}


I'm trying to use the output of the first function (Chirp) as input of the second one (mafonction).
the problem is that the values of u1 are not transmitted in the correct order.
for exemple : for u1 I get :
a1 =  7;
a2 = 6;
a3 = 5;
a4 = 4;
a5 = 15;

I'm expecting to have the same for u2, but I get :
a1 =  15;
a2 = 4;
a3 = 5;
a4 = 6;
a5 = 7;

Do you have any Idea why the values are in the reverse order ??  Is there an other way to implement this correctly ?
Thanks for your help.

Edited by: olaama - Jul-23-15 10:02:18

Re: External function using output of an other one.

Help Please !

Re: External function using output of an other one.

Hi,

Your code is wrong both in the C file and in the .mo file. See the attached zip.
Model.zip

Code:


  function mafonction
    input Rec u1;
    output Rec u2;
    // send BOTH u1 and u2 to the external function as that is the way is defined!
    external mafonction(u1, u2) annotation(Library = "Chirp", LibraryDirectory="modelica://ChirpSignal");
  end mafonction;

Code:


rec* mafonction(rec test, rec* test1)
{
  memcpy ( test1, &test, sizeof(rec) );  // no addres of test1, is already a pointer
  return test1;
}

Running model.mos gets you:

Code:


adrpo@ida-liu050 ~/dev/OMTesting/forum/1665
$ /f/OpenModelica1.9.3-v1.9.3-dev-523-g1d963ac/bin/omc +locale=C model.mos
true
""
true
0
""
record SimulationResult
    resultFile = "c:/bin/cygwin/home/adrpo/dev/OMTesting/forum/1665/ChirpSignal_res.mat",
    simulationOptions = "startTime = 0.0, stopTime = 1.0, numberOfIntervals = 500, tolerance = 1e-006, method = 'dassl', fileNamePrefix = 'ChirpSignal', options = '', outputFormat = 'mat', variableFilter = '.*', cflags = '', simflags = ''",
    messages = "",
    timeFrontend = 0.7343596380537807,
    timeBackend = 1.148104848302405,
    timeSimCode = 0.006371707033899545,
    timeTemplates = 0.03741838078879516,
    timeCompile = 3.829548752874621,
    timeSimulation = 0.1699746779308428,
    timeTotal = 5.926586016890105
end SimulationResult;
""
"u1"
7.0
""
6.0
""
5.0
""
4.0
""
15.0
""
"u2"
7.0
""
6.0
""
5.0
""
4.0
""
15.0
""

Cheers,
Adrian Pop/

Attachments:

Re: External function using output of an other one.

Hi Adrian,

First , thank you for your answer.
What you proposed doesn't change anything.
for the error in C code, I totally agree with you. It was just an error while copying the code.
for the OM code : 
"external u1 = mafonction(u) annotation(Library = "Chirp");"  and  "external mafonction(u1, u2) annotation(Library = "Chirp", LibraryDirectory="modelica://ChirpSignal"); " are totally equivalent (at least in this exemple), I still get the same result.

Actually the solution is to declare the first function as impure and pass it as argument of the second one.  :

impure function Chirp
    output Rec u;
 
    external Chirp(u) annotation(Library = "Chirp1", LibraryDirectory = "modelica://ChirpSignal");
  end Chirp;

  function mafonction
    input Rec u1;
    output Rec u2;
 
    external u2 = mafonction(u1) annotation(Library = "Chirp1", LibraryDirectory = "modelica://ChirpSignal");
  end mafonction;

  Rec u2;
equation
  u2 = mafonction(Chirp());
end ChirpSignal;

Try this and tell me what u get (It works just fine).

Anyway, thanks for your Help.

Cheers,
Olaama

Re: External function using output of an other one.

The C code was wrong. you took the address of the pointer when doing memcpy.
And:

Code:


external u1 = mafonction(u) annotation(Library = "Chirp");

is not equivalent to:

Code:


external mafonction(u1, u2) annotation(Library = "Chirp", LibraryDirectory="modelica://ChirpSignal");

are not equivalent!

in the first case we generate u1 = mafonction(u) in the C code and in the second mafonction(u, &u1).
So if your C function is given as having 2 parameters you need to have the second style!
Do a diff of your code and the code in the zip i attached before to see what i changed!

Cheers,
Adrian Pop/

Re: External function using output of an other one.

Hi ,
for the C code I said that I totally agree with u (there was a mistake thank u for reminding me).
for the OM code : OK , I thought it was equivalent . but still, even with what u gave me, the result is the same, the values are in the reverse order.
Have u tried what I gave u ? It works !!

Cheers,
Olaama

Re: External function using output of an other one.

It seems I really don't get what you're saying current/smile
So, is the problem solved now?

The values are reversed when in the .mo file you have out = f(in) and in the C code you have f(in, out)
I guess because the stack is somehow corrupted when the function expects 2 parameters and gets only one.

Re: External function using output of an other one.

Yes, the problem Is solved, the solution is to define the first function in OM like this : "impure function Chirp" instead of "function chirp", and in the equation part you must call it this way

equation
u1 = Chirp();
u2 = mafonction(Chirp());
end ChirpSignal;

//instead of :
/*
u1=Chirp();
u2 = mafonction(u1);
*/

that's it.

Re: External function using output of an other one.

We do evaluate the functions during compilation if they are not declared impure and they have constant inputs.
An alternative is to use +d=nogen,noevalfunc but is better to declare them impure as you did if you don't want them to be evaluated during compile time.

This should not be a problem at all:

Code:


u1=Chirp();
u2 = mafonction(u1);

It does work fine in the zip i attached and not have things in reverse.

Re: External function using output of an other one.

Thank you for your answer ! It was very helpul.

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