MATLAB Answers

How do I resolve the problem "Nonscalar arrays of function handles are not allowed; use cell arrays instead." associated with this code? Thanks

42 views (last 30 days)
mahya pv
mahya pv on 4 May 2018
Answered: Bjorn Gustavsson on 4 May 2018
function [sys, x0, str, ts] = IEEE80211a_udg(t, x, u, varargin)
% IEEE80211a_UDG User-defined graphics for IEEE 802.11a model.
% Plot data u in MATLAB figure.
% u is assumed to be Nx2; first column real-part, second column imag-part.
% Can also pass additional parameters to plot function
switch varargin{1}
case 3
sys = []; % mdlOutput - unused
case 2
sys = mdlUpdate(t, x, u, varargin{:});
case 0
[sys, x0, str, ts] = mdlInitializeSizes;
case 9
sys=mdlTerminate;
otherwise
feval(varargin{:});
end
% -----------------------------------------------------------
function [sys, x0, str, ts] = mdlInitializeSizes
blk = get_param(gcb, 'parent');
sizes = simsizes;
sizes.NumInputs = -1;
sizes.NumOutputs = 0;
sizes.NumSampleTimes = 1;
sys = simsizes(sizes);
x0 = []; % states
str = ''; % state ordering strings
ts = [-1 1]; % inherited sample time, fixed in minor steps
% initialize block data
bd = get_param(blk, 'userdata');
bd.firstcall = true;
bd.figTag = blk;
bd.graphicsName = get_param(blk, 'graphicsName');
bd.plotFcnHandle = str2func(bd.graphicsName);
bd.cellArrayMode = strcmp(get_param(blk, 'convertMode'), 'cell array');
set_param(blk, 'userdata', bd);
% ------------------------------------------------------------
function sys = mdlUpdate(t, x, u, flag, params)
% Faster implementation of: blk=gcb;
cs = get_param(0, 'CurrentSystem');
cb = get_param(cs, 'CurrentBlock');
sfcn = [cs '/' cb];
blk = get_param(sfcn, 'parent');
sys = [];
bd = get_param(blk, 'userdata');
% Need to check for figure every update
bd.fig = findobj('type', 'figure', 'tag', bd.figTag);
if isempty(bd.fig)
% figure is not open
bd.firstcall = true;
else
% figure is open
if bd.firstcall
% get axes handles
[bd.axes, bd.multiple_axes] = get_axes_handles(bd.fig);
end
[M, N] = size(u);
u_complex = u(:, 1:N/2) + j*u(:, N/2+1:N);
input_names = params{1};
other_params = params{2:length(params)};
other_params_exist = ~isempty(other_params);
plot_data = convert_simulink_vector(u_complex, input_names, bd.cellArrayMode);
if other_params_exist
feval(bd.plotFcnHandle, plot_data, bd.axes, bd.firstcall, other_params);
else
feval(bd.plotFcnHandle, plot_data, bd.axes, bd.firstcall)
end
bd.firstcall = false;
end
set_param(blk, 'userdata', bd);
% ---------------------------------------------------------------
function sys = mdlTerminate
sys = [];
%--------------------------------------------------------------------------
function data = convert_simulink_vector(u, input_names, cellArrayMode);
% CONVERT_SIMULINK_VECTOR
%
% u: Nx1 input vector, containing data corresponding to multiple matrices
% (see format below)
% input_names: cell array containing names (strings) of the above matrices
%
% u uses format [s1; v1; s2; v2; s2; v3; ...]
% where sn is a scalar, and vn is a (sn x 1) vector
% The nth name in input_names corresponds to vector vn
num_inputs = length(input_names);
if num_inputs == 1
data = u(2:end, :);
return
end
length_u = length(u);
if cellArrayMode
data = cell(1, num_inputs);
else
data = cell2struct(cell(1, num_inputs), input_names, 2);
end
idx = 1;
for i = 1:num_inputs
L = u(idx);
v = u(idx+1 : idx+L, :);
if cellArrayMode
data{i} = v;
else
data = setfield( data, input_names{i}, v );
end
idx = idx + L + 1;
end
%--------------------------------------------------------------------------
function [haxes, multi] = get_axes_handles(fig);
% returns axes handles
% if there is only one axes, axes is a handle
% if more, axes is a structure of handles, with fieldnames corresponding to
% axes tags.
% multi: true if more than one axes
c = get(fig, 'children');
multi = (length(c)>1);
if ~multi
haxes = c;
else
t = get(c, 'tag');
h = num2cell(c);
x = [t(:).'; h(:).'];
haxes = struct(x{:});
end

Answers (1)

Bjorn Gustavsson
Bjorn Gustavsson on 4 May 2018
If you need an array of function handles you have to use something like this:
% Define:
fcn_array{1} = @(t,x,k,w) 12*sin(k*x-w*t);
fcn_array{2} = @(alpha,x) exp(-abs(alpha*x));
% Use:
wave_amplitude = fcn_array{1}(12,23,4/pi,4.04e6);
damping_factor = fcn_array{2}(0.01,23);
Sometimes I've created crashes with too much manipulation of the cell-array function handles, but that was ~5 matlab-releases ago.
The reason you have to go through this method is that with "an array of function handles you get confusion about what is array indices and what is function arguments.
HTH

Tags

Community Treasure Hunt

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

Start Hunting!