use scatteredInterpolant variable in embedded matlab function in simulink - matlab

Is there any way to do i.e.
Surface = scatteredInterpolant(measurement_xz(:,1)*1E-3,measurement_xz(:,2)*1E-3,measurement_xz(:,3));
where measurement_xz is some data in a startup script for my simulink model and then use Surface in an embedded matlab function in the simulink model, i.e.
///embedded matlab function
function V = fcn(x,z)
V = Surface(x,z);
?
When I i.e. try to use Surface as a parameter for V like
function V = fcn(x,z,Surface)
V = Surface(x,z);
with Surface set as parameter in the Ports and data manager I get the error
Expression 'Surface' for initial value of data 'Surface' must
evaluate to a numeric or logical.

What you are trying to do is not supported by the Matlab Function block, MATLAB is unable to generate code for it. The problems are:
You are trying to access the variable Surface which is not visible in the scope
scatteredInterpolant is not supported at all for code generation (at least in my MATLAB version, might be improved in recent Versions).
To fix this on a code level, you could switch to interpreted MATLAB code. This can be done either switching to a Interpreded MATLAB block or using coder.extrinsic. It is a quick and simple fix, but I recommend not to do this because it will probably result in a slow model. Instead I recommend to switch to a lookup table, which is also capable of interpolating.

Related

Solving ODEs inside a Subsystem in Simulink

I'm trying to figure out how to solve a system of ODEs inside a subsystem in a Simulink model. Basically, each call to this subsystem, which happens at each tick of the simulation clock (fixed-step), entails solving the ODEs. So there's like a different "clock" for the subsystem.
I have an M-file that implements the function for the system of ODEs. Currently, I have a MATLAB Function block for that. It needs a lot of parameters that I can get from the base workspace (via evalin and using coder.extrinsic('evalin') at the beginning). But I'm not allowed to define function_handle objects or inner functions to parameterize the function that is used by ode*. I think that if I'm able to solve the ODEs in this block, I'll have solved my problem. But those restrictions are "ruining" it.
I'd appreciate if you have any ideas of how to accomplish this. I welcome different approaches.
Thank you.
EDIT
A simple example is given below. It attempts to solve the van der Pol equation by changing the mu parameter randomly. This is the main idea I have at the moment, which doesn't work because of the problems mentioned above.
This is the main model with the subsystem:
This is the subsystem:
This is the MATLAB Function block implementation (note that there's an error in the # symbol, since defining function_handle objects isn't allowed):
Just use the MATLAB Function block as a wrapper. Put the bulk of your code into a "standard" MATLAB function (i.e. one callable from MATLAB, not the MATLAB Function block) and call that function (after defining it as coder.extrinsic) from the MATLAB Function block.
This will be a bit more complex than Phil Goddard's solution. The advantage is that it will allow you to generate standalone code, if necessary, whereas extrinsic functions are not compatible with standalone code generation.
The functions ode23 and ode45 are supported for code generation as of MATLAB R2014b so this applies if your MATLAB release is at least that new. Supposing so, the main limitation you are seeing is that anonymous functions are not supported for code generation.
Simulate Anonymous Function Parameters with Persistent Variables
However, these parameterized anonymous functions can be simulated using a normal function with a persistent. To simulate your function with the parameter mu, make a MATLAB file odefcn.m:
function x = odefcn(t,y)
%#codegen
persistent mu;
if isempty(mu)
% Adjust based on actual size, type and complexity
mu = 0;
end
if ischar(t) && strcmp(t,'set')
% Syntax to set parameter
mu = y;
else
x = [y(2); mu*(1-y(1)^2)*y(2)-y(1)];
end
Then in the MATLAB Function Block, use:
function y = fcn(mu)
%#codegen
% Set parameter
odefcn('set',mu);
% Solve ODE
[~,Y] = ode45(#odefcn,[0, 20], [2; 0]);
y = Y(end,1);
That should work both for simulation and for code generation. You can just add more arguments to odefcn if you need more parameters.

MATLAB regress function and Normalizing Data

I am trying to perform a multiple linear regression in MATLAB using the regress function, and I am using a number of different variables that involve different scales and units. I am assume the answer to this question is yes, but should I normalize each variable before running the regression? I'm not sure if MATLAB does so automatically. Thanks for the help!
Yes, you should. If you want to normalize it between 0 and 1, you could use mat2gray function (assuming "vector" as your list of variables).
norm_vect = mat2gray(vector);
This function is used to convert matrix into an image, but works well if you don't want to write yours. You also can use a simple normalization like:
for i = 1:length(vector)
norm_vect(i) = (vector(i)-min(vector))/(max(vector)-min(vector));
end

Matlab, SCIP and Opti Toolbox

I am using the Opti Toolbox, a free optimization toolbox for Matlab. I am solving a Mixed Integer Nonlinear Program, a MINLP. Inside the Opti Toolbox, the MINLP solver used is SCIP.
I define my own objective as a separate function (fun argument in Opti), and this function needs to call other matlab functions which take double arguments.
The problem is that whenever Opti invokes my function to evaluate the objective, it first calls it using a vector of 'scipvar' objects and then it calls it again using a vector of 'double' objects. My obj function does not work with the scipvar objects, it returns an error.
I tried (just for testing) setting the output of my function for something fixed when the type is 'scipvar', and for the actual real thing when the type is 'double', and this doesn't work, changing the fixed value actually changes the final optimal value.
I basically need to convert a scipvar object to double, is this possible? Or is there any other alternative?
Thank you.
Ok, so after enlightenment by J. Currie, an Opti toolbox developer, I understood the cause of the problem above.
The first call to the objective with a vector of scipvar variables is actually a parser sweeping the objective function to see if it can be properly mapped to something that can be handled by SCIP. I reimplemented the objective function to use only methods allowed by scip - obtained by typing methods(scipvar) in matlab:
abs dot log minus mrdivide norm power rdivide sqrt times
display exp log10 mpower mtimes plus prod scipvar sum uminus
Once the objective could be parsed by scip my problem worked fine.

Evaluating a surface fit (sfit) using mixed scalar/vector inputs in MATLAB

Consider the following 3D surface:
I have fitted an equation to this surface using cftool (MATLAB 2014a) after constructing the appropriate meshgrid matrices (XX,YY,ZZ such that ZZ=f(XX,YY)). At some later point I wanted to evaluate the fit over a "line", e.g. sfit_eq(3:0.01:5,600) but MATLAB refused to give me a result, claiming that there's a dimension mismatch between the inputs (Error while trying to evaluate FITTYPE function obj: Dimensions of matrices being concatenated are not consistent.).
While it can be easily resolved using repmat or meshgrid, I'm wondering - is there a way to evaluate the sfit directly using inputs of inconsistent dimensions (in other words - let it bother with the data gridding if such is required)?
I decided to revisit this problem today (this time, in MATLAB 2015a).
My initial thought was to get the desired result using a mixture of bsxfun and #feval which I didn't seem to get quite right. But then I noticed that in this version of MATLAB it just works the way I wanted it to.
I guess this problem may be solved by simply upgrading to a newer version of MATLAB.

Matlab ode solver algebreic calculation

I have an ODE model in Matlab coded as a function. I integrate the ODE's over time using ode15s. After the solver has finished, I calculate algebraically, a new variable that's a fraction of the sum of the other variables output by the model.
For example:
dA/dt = xxxxx
dB/dt = xxxxx
dC/dt = xxxxx
this gets integrated and returns an array of columns for dA,dB,dC. From the output I calculate:
model_result = A/(A+B+C).
for the whole time course), and plot this vector of values vs time.
However, I also need to perform sensitivity analysis on the model, for which I've used the modified ODE15s on the Mathworks repository. I need to be able to set "model_result" above as the objective function for the sensitivity calculations.
I attempted to calculate model_result inside the function, and have it returned as another variable, but obviously this doesn't work as the integrator returns the integrated value, rather than the algebraically calculated value.
Is it possible to have algebraic values returned by an ODE solver in Matlab?
If not, does anybody have any idea how to perform this kind of sensitivity analysis?
thanks for any help. I'm quite new to modelling so apologies if I'm using all the wrong terms!