- Index
- » Users
- » phillipmaree
- » Profile
Posts
Posts
Hi Adeel
W.r.t goto reference tags, I am referring to common functionality often used in Matlab Simulink environments. See i.e. http://www.ece.northwestern.edu/local-a … /goto.html for a good reference point on the functionality I am talking about!
Thanks
Phillip
Hi
As ones model becomes more complex (in diagram view), having lines connecting various components becomes very messy.
Does OMEdit have any capability on Goto reference Tags? Or could you suggest some method to accomplish this?
Thanks
Phillip
In your proposed example, it does work, however, it generates incompatible pointer warnings which suggests I might be doing something wrong.
And as comment on your previous comments, I do pass my record by reference (at least from the C side). My C function is defined as:
Code:
void* sample_solver( void* solve_vptr, void* arg_ptr, void* res_ptr )
{
return ((PhotoVoltaicC*)solve_vptr)->sample( (PhotoVoltaicC::ArgSt*)arg_ptr, (PhotoVoltaicC::ResSt*)res_ptr );
}
which match up with the Modelica code as:
Code:
function sample_model
input Solver.PhotovoltaicSolver solver_ptr;
input Solver.Archive.PV.Arg arg;
input Solver.Archive.PV.Res res0;
output Solver.Archive.PV.Res res;
external "C" res = sample_solver(solver_ptr, arg, res0 );
annotation(
Library = "photovoltaic",
LibraryDirectory = "modelica://components/Resources/Library");
end sample_model;
Correct me if I am wrong, but I do pass the record by reference as I did above? Or does Modelica have some syntax to pass a record by reference?
Hi
It seems to me that if one passes a record as argument to external C function with the aim of returning some data in this record, then one ends up with the incompatible pointer warning (see previous post).
I guess it must be due to declaring the record as an output in the function declaration, but then pass it as an input to the external C function?
To get rid of this warning, one can pass the record as input argument to external C function, and then the external C function can return a reference to this record which is assigned to some output defined record variable. See below code snippet (does not generate the incompatible pointer warning):
Code:
function sample_model
input Solver.PhotovoltaicSolver solver_ptr;
input Solver.Archive.PV.Arg arg;
input Solver.Archive.PV.Res res0;
output Solver.Archive.PV.Res res;
external "C" res = sample_solver(solver_ptr, arg, res0 );
annotation(
Library = "photovoltaic",
LibraryDirectory = "modelica://components/Resources/Library");
end sample_model;
This doesn't see seem very eloquent!
If there are other better methods to obtaining the same result, then I would be happy to receive some suggestions in how to implement this.
Thanks,
Phillip
It seems I got it to work apart from a pesky warning about passing of pointer mismatch.
I was wondering if it could be due to poor implementation maybe?
My Extern C function calls are defines as follows:
Code:
function sample_model
input Solver.PhotovoltaicSolver solver_ptr;
input Solver.Archive.PV.Arg arg;
output Solver.Archive.PV.Res res;
external "C" sample_solver(solver_ptr, arg, res );
annotation(
Library = "photovoltaic",
LibraryDirectory = "modelica://components/Resources/Library");
end sample_model;
where the compiles generates the following warning:
Code:
Components.Photovoltaic_functions.c:20:44: warning: incompatible pointer types passing 'Components_Solver_Archive_PV_Res *' to parameter of type 'Components_Solver_Archive_PV_Res **' [-Wincompatible-pointer-types]
sample_solver(_solver_ptr_ext, _arg_ext, &_res_ext);
^~~~~~~~~
./Components.Photovoltaic_functions.h:112:138: note: passing argument to parameter here
extern void sample_solver(void * /*_solver_ptr*/, Components_Solver_Archive_PV_Arg* /*_arg*/, Components_Solver_Archive_PV_Res** /*_res*/);
^
Could be that I pass res as an output which is also an input to sample_solver which cause the referencing warning?
Thanks for thoughts!
Hi
I just used one value as a dummy example. I actually want to return several values (vectors or matrices).
Thanks for the supplied hints! I will check it out!
P
Hi
I try to pass back a struct by reference from a return Extern C function call in OpenModelica.
I have defined a struct in C, and a Record in OM with similar fields, however it seem I still miss some detail in how to get it to work.
I very crude idea of what I am currently doing is:
Code:
record In
Real value;
end In;
record Out
Real value;
end Out;
function extern_func
input In in
output Out out
external "C" out = sample_solver( in )
end extern_func
Input in;
Output out;
equation
in.val = 1;
out = sample_solver( in )
Assumptions:
I assume I pass struct by reference as void* from C.
Thanks for any consideration or pointers!
Phillip
One probable solution (hacked and not portable):
1. Build a shared library of interest being libnmpc.so in this case.
2. Export->FMU which will prompt the usual error of
Code:
/usr/bin/ld: cannot find -lnmpc
3. Go to the generated folder where the FMU export attempt was made. Typically in your work directory
Code:
/home/>USER>/OMEdit
,
4. Enter folder
Code:
/OMEdit/components.mpc/components_mpc.fmutmp/sources
5. ./configure which will prompt on the first try
Code:
configure: error: FMI headers need to be present in the include path.
To solve this export your path where this FMI headers are located, i.e.,
Code:
CPPFLAGS=-I/usr/include/omc/c/fmi/
6. ./configure && make.
7. Make will fail because -Wl,-Bstatic has also been defined for -lnmp and we only have libnmpc.so which depends on libcasadi.so. To resolve this, modify the compiler arguments to include -Wl,-Bdynamic -L<path to nmpc lib> -lnmpc.
8. make which results in a FMU which can be simulated.
Open questions:
1. One needs to created a static link such that the FMU unit is portable. Does this imply I need to compile Casadi as a static library also?
2. Should one add dynamic linking arguments to Casadi and then have a portable FMU that requires Casadi installed on other systems?
Hi
I have tried several of your suggestions with the following observations:
Building static libraries:
1. If I build a static library libnmpc.a, then using applying Export->FMU results in -lnmpc detected. However, the subsequent problem I experience is that the dependent libraries libcasadi.so and libstdc++.so.6 are not found.
2. For the simulation environment, I can pass the latter in Simulation setup -> Compiler Flags = -lcasadi -lstdc++, which enables me to simulate.
NOTE: I have Tools->Options->FMI: "Platforms = static.
Building shared libraries:
1. Building a shared library libnmpc.so enables simulating my model without the need to pass Simulation setup -> Compiler Flags = -lcasadi -lstdc++.
2. Again, I sit with the problem of not detecting lnmpc when I Export->FMU. Setting I have Tools->Options->FMI: "Platforms = dynamic. does not change -Wl,-Bstatic to -Wl,-Bdynamic, nor does it effect the net outcome (not sure if it should).
Using both static and shared libraries:
1. Again for this scenario, I pick up -lnmp, but cannot detect -lcasadi.
Some conclusions:
I still contemplate how to append the dynamic library dependencies libcasadi.so and libstdc++.so.6 to my static library target being libnmpc.a. I am of opinion this should be done by setting some property configured in the CMakelists.txt file. I have tried:
Code:
target_link_libraries (nmpc ${CASADI_LIB})
target_link_libraries (nmpc ${STDCXX_LIB})
but this does not resolve it.
Still open questions:
1. How do one link / bind share libraries (in this example libcasadi.so and libstdc++.so.6) with a static generated library?
Hi
Problem description summary:
I have developed Model which includes a function that makes an extern C call. I supply a shared library (linux *.so file) which are linked to during compilation using OMEdit. I can verify that I can simulate my model. My problem comes when I try to export my model as a FMU unit. It seems the linker cannot resolve / find my shared library when trying to export the simulation to a FMU unit.
Problem description details:
I have formulated an optimal control problem (MPC formulation) in CPP using Casadi (solved with Ipopt) (libcassadi.so is a CPP shared library). In addition, I have created an extern "C" solve function which is a C API to pass arguments to the MPC formulation, and return the optimal control solution.
My mpc.cpp function are defined as:
Code:
#include <casadi/casadi.hpp>
using namespace casadi;
extern "C" double solve( double x1, double x2, double x3 )
{
// Symbols/expressions
MX x = MX::sym("x");
MX y = MX::sym("y");
MX z = MX::sym("z");
MX f = pow(x,2)+100*pow(z,2);
MX g = z+pow(1-x,2)-y;
MXDict nlp; // NLP declaration
nlp["x"]= vertcat(x,y,z); // decision vars
nlp["f"] = f; // objective
nlp["g"] = g; // constraints
// Create solver instance
Function F = nlpsol("F","ipopt",nlp);
// Solve the problem using a guess
F(DMDict{{"x0",DM({2.5,3.0,0.75})},{"ubg",0},{"lbg",0}});
return rand()/RAND_MAX;
}
To compile the latter, I use CMake
Code:
cmake_minimum_required (VERSION 2.6)
project (01_mpc_cstr)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
set ( SRC_DIR ./src/ )
set ( MPC_SRCS ${SRC_DIR}mpc.cpp)
add_library(nmpc MODULE ${MPC_SRCS})
find_library( CASADI_LIB libcasadi.so )
if ( CASADI_LIB )
message( STATUS "Found library: ${CASADI_LIB}" ...)
target_link_libraries (nmpc ${CASADI_LIB})
else ()
message( WARNING "Cannot find library: ${CASADI_LIB}" ...)
endif ()
find_library( STDCXX_LIB libstdc++.so.6 )
if ( STDCXX_LIB )
message( STATUS "Found library: ${STDCXX_LIB}" ...)
target_link_libraries (nmpc ${STDCXX_LIB})
else ()
message( WARNING "Cannot find library: ${STDCXX_LIB}" ...)
endif ()
Next, I use OMEdit to construct my model class and define a function with an external C function call.
Code:
model MPC
function solve
input Real x1, x2 ,x3;
output Real u;
external "C" u = solve(x1, x2 ,x3);
annotation(Library="nmpc", LibraryDirectory="modelica://MPC/Resources/Library")
end solve;
Modelica.Blocks.Interfaces.RealInput x1 annotation( ...
Modelica.Blocks.Interfaces.RealInput x2 annotation( ...
Modelica.Blocks.Interfaces.RealInput x3 annotation( ...
Modelica.Blocks.Interfaces.RealOutput u annotation( ...
algorithm
u := solve(x1, x2, x3);
[color=#ff0000]
end MPC;
Now, using OMEdit, I can successfully compile and simulate the former model.
However, when I want to export the Model to a FMU unit, then I get the following linker error:
Code:
gcc -shared -o MPC.so MPC.o MPC_functions.o MPC_records.o MPC_01exo.o MPC_02nls.o MPC_03lsy.o MPC_04set.o MPC_05evt.o MPC_06inz.o MPC_07dly.o MPC_08bnd.o MPC_09alg.o MPC_10asr.o MPC_11mix.o MPC_12jac.o MPC_13opt.o MPC_14lnz.o MPC_15syn.o MPC_16dae.o MPC_17inl.o MPC_init_fmu.o MPC_FMU.o -L"/home/johannes/01_cstr_introduction/models/MPC" -Wl,-Bstatic "-L/usr/bin/../lib/x86_64-linux-gnu/omc" -Wl,-rpath="/usr/bin/../lib/x86_64-linux-gnu/omc" "-L/usr/bin/../lib/" -Wl,-rpath="/usr/bin/../lib/" "-L/home/johannes/.openmodelica/binaries/MPC" -Wl,-rpath="/home/johannes/.openmodelica/binaries/MPC" "-L/home/johannes/01_cstr_introduction/models/MPC/Resources/Library/x86_64-linux" -Wl,-rpath="/home/johannes/01_cstr_introduction/models/MPC/Resources/Library/x86_64-linux" "-L/home/johannes/01_cstr_introduction/models/MPC/Resources/Library/linux64" -Wl,-rpath="/home/johannes/01_cstr_introduction/models/MPC/Resources/Library/linux64" "-L/home/johannes/01_cstr_introduction/models/MPC/Resources/Library" -Wl,-rpath="/home/johannes/01_cstr_introduction/models/MPC/Resources/Library" -lnmpc -Wl,-Bdynamic -L'/usr/bin/../lib/x86_64-linux-gnu/omc' -Wl,-rpath,'/usr/bin/../lib/x86_64-linux-gnu/omc' -lSimulationRuntimeFMI -Wl,--no-as-needed -Wl,--disable-new-dtags -llapack -lblas -lm -lm -lpthread -rdynamic -Wl,--no-undefined
/usr/bin/ld: cannot find -lnmpc
collect2: error: ld returned 1 exit status
How does the internal export to FMU work?
Any ideas in how to resolve this will be appreciated!
- Index
- » Users
- » phillipmaree
- » Profile