How to use Cell array as block parameter using setBlockParameter in Simulink?

I apologize if this has be answered before, but I couldn't find anything. I could be using the wrong phrasing to search.
I have a version of the EV example model that comes with the 2022b version of MATLAB. I have my own drive cycles that I would like to run in it. I have those drive cycles in a cell array in the workspace. If I run each cycle one at a time using button simulation commands it works, but if I use the sim commands in a for loop I get an error.
Here is how I currently am doing it:
load_system('EVModel');
param1 = CycleCell{1};
set_param('EVModel/Drive Cycle Source', 'cycleVar', 'Workspace variable');
set_param('EVModel/Drive Cycle Source', 'wsVar', 'param1');
simOut = sim("EVModel");
That code works fine, but the problem is that I have a few hundred cycles to run so I would like to do it in a loop.
Here is what I am trying:
model = 'EVModel';
load_system(model);
simIn(1:length(CycleCell)) = Simulink.SimulationInput(model);
for i = 1:length(CycleCell)
param = CycleCell{i};
simIn(i) = simIn(i).setBlockParameter('EVModel/Drive Cycle Source', 'cycleVar', 'Workspace variable');
simIn(i) = simIn(i).setBlockParameter('EVModel/Drive Cycle Source', 'wsVar', 'param');
end
simOut = parsim(simIn);
For this code I keep getting the error: "Warning: One or more simulations completed with errors. For more information, inspect the
SimulationOutput objects at these indices:".
and in the SimulationOutput object it has: "Error in '<a href="matlab:open_and_hilite_hyperlink ('EVModel/Drive Cycle Source','error')">EVModel/Drive Cycle Source</a>': Failed to evaluate mask initialization commands.Caused by: Dot indexing is not supported for variables of this type."
I cannot find what I am doing wrong. If this is possible, there must be something that I am missing. Also, I do have the Parallel Computing Toolbox.
Any ideas what is wrong?

 Akzeptierte Antwort

Paul
Paul am 17 Mär. 2023
Bearbeitet: Paul am 17 Mär. 2023
Hi David-ucr,
I don't have 2022b and can't find EVModel in 2022a, so can't test. I also couldn't find it on the 2022b Simulink examples page, maybe it comes with a specific blockset?
I think the problem is that parsim basically runs each instance of the simulation in its own little world on each worker, and there is no variable named 'param' in the workspace of the little world. In contrast, when you run the single simulation code, the variable param1 is found by Simulink in the base workspace.
For the workflow you've defined, and assuming that each element of CycleCell is scalar number (again, I can't check because I don't have EVModel), the solution, I think, is to change the second simin assignment to:
simIn(i) = simIn(i).setBlockParameter('EVModel/Drive Cycle Source', 'wsVar', num2str(CycleCell{ii}));
which basically hard-codes the value of each parameter.
Or, use setVariable
param = CycleCell{i};
simIn(i) = simIn(i).setBlockParameter('EVModel/Drive Cycle Source', 'cycleVar', 'Workspace variable');
simIn(i) = simIn(i).setBlockParameter('EVModel/Drive Cycle Source', 'wsVar', 'param');
simIn(i) = simIn(i).setVariable('param',param,'Workspace',model);
Or, if each element of CycleCell is not a scalar number, then maybe this will work
simIn(i) = simIn(i).setBlockParameter('EVModel/Drive Cycle Source', 'wsVar', ['CycleCell{',int2str(ii),'}']);
The parsim command would then be
simOut = parsim(simIn,'TransferBaseWorkspaceVariables','on');
This will transfer CycleCell, and every other variable in the base workspace!, to the little world of each worker, so that the block parameter CycleCell{1}, etc. can be evaluated in each simulation.
If none of these are acceptable, please provide more insight into what's contained in CycleCell, and also a link to the 2022b doc page for EVModel.

6 Kommentare

David-ucr
David-ucr am 17 Mär. 2023
Bearbeitet: David-ucr am 17 Mär. 2023
Thank you! The second method, the "set variable" method is what I needed!
if you are curious, here is the MATLAB EV model, here, I was talking about. I changed mine a little so I am not just running this exact model, but the drive cycle source is basically the same.
Thanks again!
Also, adding the "TransferBaseWorkspaceVariables" in parsim, I needed.
@Paul Hi again,
I noticed one problem but I don't know if it should be a new question or not.
I don't get an error anymore and the simulation runs, but I noticed that all the simulations just use the same drive cycle. I thought they were different because I am able to change the stop time of each simulation. Each drive cycle is a different length of time (similar lengths but not the same). The EVmodel saves the drive cycle velocity that was used in "out" in the "logsout" property.
I tested with only a few drive cycles rather than running through all of them. What happens is that it is using the final cycle stored in "param" after the for loop ends.
Any ideas that could fix this?
Follow up questions are fine.
Don't know what the problem is. I have a simple model that is a Constant block with 'Costant value' = '1', which feeds a Gain block, which feeds a To Workspace block with 'Variable name' = 'y'.
I run the following code:
model = 'mysim';
CycleCell{1} = 10;
CycleCell{2} = 20;
CycleCell{3} = 30;
for ii = 1:numel(CycleCell)
param = CycleCell{ii};
simIn(ii) = Simulink.SimulationInput(model);
simIn(ii) = simIn(ii).setBlockParameter('mysim/Gain', 'Gain', 'param');
simIn(ii) = simIn(ii).setVariable('param',param,'Workspace',model);
end
simOut = parsim(simIn);
simOut.y.Data
And I get the following output, which is exactly as expected
ans =
10
ans =
20
ans =
30
All of your simulations are using CycleCell{end}?
Yes, all my simulations are using "CycleCell{end}."
One difference that I am noticing is that in a "gain" block, if you open the "block parameters" by double-clicking it, the gain has the option to "create variable..." which my drive cycle source does not have the option to do. Here is a picture of the block parameters dialog box for Drive Cycle Source:
In, "Drive cycle Source:" I have workspace variable selected, but I can chose drive cycles that MATLAB has already available. But chosing "workspace variable" from the drop down menu opens the "From workspace:" option. This is where you can type the name of the variable from workspace.
If you look at the "Output sample period (0 for continuous), dt [s]:" at the end of the space there is a veritcal three dots, selecting that allows you to create a variable.
In the Gain block parameters, the "gain" option has those three vertical dots. That must be why it is using the the CycleCell{end} value, because it runs through the for loop where param is set to CycleCell{end}. So now in the "From Workspace:" box, it has "param" and reads that directly from the workspace.
I put in my original question, "if this is possible." I am starting to think this may not be possible.
If I'm following, it seems to me the only way that your results would happen is if, as you say, param was hanging around in the base workspace after the for loop completed, and you either used sim or you used parsim and but parsim couldn't connect to a parallel pool and ran serially in the base workspace. I just don't see how you'd get that result if not connected to the base workspace, as would be the case if actually using a parpool. However, when I ran with a parpool, I ran into different problems (the simulation wouldn't even run), which lead me to ....
The block Drive Cycle Source is a masked subsystem. It appears the either mask parameters or mask initialization code or both don't play nicely with simIn.Variables. It seems like a similar issue discussed in this thread where Rahual Kumar (who I can't find with an @) stated: "Variables specified on the SimulationInput object are not available in model or block callbacks." Seems like a similar issue is happening here with a mask where simIn.Variables are not available when the mask is first initialized. Needless to say, the documentation is nonexistent on this issue as far as I can tell.
As discussed in the linked thread, the (or a) solution is to use the PreSimFcn to define the variable param in the base workspace of the worker (or in the Matlab base workspace if using sim). This code worked for me
CycleCell{1} = [0:10; 0:10].';
CycleCell{2} = [0:10; (0:10)*2].';
CycleCell{3} = [0:10; (0:10)*3].';
% mysim1 is Drive Cycle Source connected to a To Workspace
model = "mysim1";
load_system(model);
blockname = "Drive Cycle Source";
blk = model + "/" + blockname;
% here I retrieved the mask paramters to make sure they were the default
% values, which should be 'FTP75' anda 0x0 empty char array
get_param(blk,'cycleVar')
get_param(blk,'wsVar')
simIn(1:3) = Simulink.SimulationInput(model);
for ii = 1:3
param = CycleCell{ii};
% I tried different ways to setBlockParameter. They all worked.
% simIn(ii) = simIn(ii).setBlockParameter(blk, 'cycleVar', 'Workspace variable');
% simIn(ii) = simIn(ii).setBlockParameter(blk, 'wsVar', 'param');
% simIn(ii) = simIn(ii).setBlockParameter(blk, 'wsVar', 'param');
% simIn(ii) = simIn(ii).setBlockParameter(blk, 'cycleVar', 'Workspace variable');
simIn(ii) = simIn(ii).setBlockParameter(blk, 'cycleVar', 'Workspace variable', blk, 'wsVar','param');
simIn(ii) = simIn(ii).setVariable('param',param,'Workspace',model);
% Here I define the PreSimFcn. See doc for details. I think this
% function runs before anything else, including loading mysim1 into
% the worker. At a minimum, I think it must run before the Drive Cycle Source mask is
% initialized for the first time.
% simIn is automatically passed as the input to the function. All this function
% does is take the value of the first
% variable in simIn.Variables, which has the value of param from the loop, and
% assign that value to a variable named param in the base workspace of the
% worker. It will also assing in the Matlab base workspace if using sim
% instead of parsim.
simIn(ii) = simIn(ii).setPreSimFcn(@(in) assignin('base','param',in.Variables(1).Value));
end
% Here I cleared param to make sure it couldn't affect anything.
clear param
simout = parsim(simIn);
simout had my expected output from each of the three simulations.
@Paul This is the answer! It worked! Thank you! Everything I could think to check to make sure it is working checked out.

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (0)

Kategorien

Produkte

Version

R2022b

Gefragt:

am 17 Mär. 2023

Kommentiert:

am 18 Mär. 2023

Community Treasure Hunt

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

Start Hunting!

Translated by