coder and error passing handles to extrinsic functions

40 views (last 30 days)
Hi all,
I have written some code in matlab using a primary function that calls fsolve and a subfunction for passing extra arguments to the function being solved.
function out1 = RxCase2(pin1,pin2,pin3,pT,pVpore,options)%#codegen
global in2 in3 T Vpore
in2=pin2;
in3=pin3;
T=pT;
Vpore=pVpore;
varlogic = logical([1 1 0 1 0 0]);
pin1(varlogic) = feval('fsolve',@NLeqset2,pin1(varlogic),options);
out1 = TotalSol2(pin1);
...
function [out1,out2] = NLeqset2(in1)
global in2 in3 T Vpore
...
function out1 = TotalSol2(in1)
global in2 T Vpore
...
However I get the error 'Function handles cannot be passed to extrinsic functions' when compiling. This function does work as a native matlab function.
I also tried coder.extrinsic('fsolve'), but it seems that I can't pass the function handle to the fsolve() routine. I am running into problems because it seems most ways to pass extra parameters use function handles, fsolve needs to be passed @NLeqset2, and the coder is not compatible with fsolve() (only fzero which works by calling it without feval; i.e something like fzero(@NLeqset,x0)).
Does anyone have any suggestions on how to pass the arguments to the subfunction and pass the subfunction to fsolve() in a way that can be compiled?
  1 Comment
Santosh Gnanasekar
Santosh Gnanasekar on 27 May 2019
Iam as well trying to construct the similar function
MainFn.png But didnt work. Could you please help me out ?SubFn.png

Sign in to comment.

Accepted Answer

Mike Hosea
Mike Hosea on 26 Sep 2011
You need to refactor your code so that you don't pass function handles across the extrinsic function call boundary. Instead of calling FSOLVE as an extrinsic function, call your own function extrinsically and pass all the data that it needs to run FSOLVE and then to return data to your MATLAB Coder environment. Within your function, use anonymous functions or whatever.
function y = ex1(x,c) %#codegen
% Show how to call extrinsic functions that require function handles.
% This function will be compiled:
% codegen ex1 -args {zeros(2,1),0}
coder.extrinsic('mysolve');
% Some compiled calculations would normally go here. For this illustration,
% we simply copy x to x0.
x0 = x;
% Declare the output type of the extrinsic call so that the data can be
% marshaled back into the C execution environment.
y1 = zeros(size(x0));
% We pass to mysolver all the data it needs to construct the call to
% FSOLVE. This call will be from the C execution environment into the
% MATLAB execution environment. We pass only data, but we pass all the
% data needed to define the problem to be solved in the extrinsic function.
y1 = mysolve(x0,c);
% Some compiled calculations would normally go here. For this illustration
% we just copy y1 to y.
y = y1;
And in a separate file, mysolve.m:
function y = mysolve(x0,c)
% This function is NOT compiled.
% Construct function to be solved:
f = @(x)myfun(x,c);
y = fsolve(f,x0);
function F = myfun(x,c)
% This function can be defined either here, in a separate (not-compiled)
% MATLAB file, or even built as a mex file using a separate MATLAB Coder
% project.
F = [ 2*x(1) - x(2) - exp(c*x(1))
-x(1) + 2*x(2) - exp(c*x(2))];
Running this:
>> codegen ex1 -args {zeros(2,1),0}
>> ex1([-5;5],-1)
Obviously, since mysolve.m is not compiled, you can do anything in it that works in MATLAB. -- Mike
  4 Comments
Joseph
Joseph on 14 Oct 2011
It does work kinda. I have to run the non-compiled version before running the compiled version to initialize the global variables for some reason unknown to me. It already knows the type but will say it is receiving a 0x0 matrix and expects the size that I gave during the options. It seems as though the globals must be initialized before the function runs, even if the globals are set in the function before they are used. So the uncompiled version acts as defining the globals during the function call and then I can use the mex function. Otherwise I need to explicitly generate the global variables before calling the mex function, that is if I dont want to run the non-compiled version first.
Hetvi Patel
Hetvi Patel on 21 Mar 2020
[Tv,ZV] = ode15s (fcn, t_v, ZV0, solver_options);
solver_options = odeset ('Mass', TM_Matrix, 'MassSingular', 'yes');
fcn = @(t,T) Thermomodel_fcnDAE(T, L_Matrix, Pv_Vektor, T_ref_Pv, T_K);
[Tv,ZV] = ode15s (fcn, t_v, ZV0, solver_options);
function dT = Thermomodel_fcnDAE(T, L_Matrix, Pv_Vektor, T_ref_Pv, T_K)
global count_fcn
global Pv_out
count_fcn = count_fcn + 1;
Pv_out = Pv_Vektor;
Pv_out(1) = Pv_Vektor(1)*(1+3.9/1000*(T(1)-T_ref_Pv));
Pv_out(2) = Pv_Vektor(2)*(1+3.9/1000*(T(2)-T_ref_Pv));
dT = L_Matrix * [T; T_K] + Pv_out;
end
when i am trying to call this equations in simulink using matlab function,i am getting error calling odeset function as it is just a solver,how to do that?

Sign in to comment.

More Answers (0)

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!