Block callback function in Simulink model cannot access workspace variable when executed with parsim

조회 수: 17 (최근 30일)
I have a Simulink model 'My Model', which uses a 'Check Static Range' block. In this block, assertion is enabled, and a callback function is defined. This function simply has the line of code
SatCount = SatCount+1;
The purpose is to count how many times a signal exceeds bounds.
The model is executed N times in parallel using parsim in wich all of the variables required to run the model are loaded in to the model workspace using code like the following
for p = 1:N
in(p) = Simulink.SimulationInput('My Model');
in(p) = in(p).setVariable('Var1',Var1,'Workspace','My Model');
in(p) = in(p).setVariable('Var2',Var2,'Workspace','My Model');
in(p) = in(p).setVariable('SatCount',0,'Workspace','My Model');
in(p) = in(p).setModelParameter('StopTime',1);
end
out = parsim(in,'ShowProgress', 'on');
When this is executed on a cluster machine using 12 workers, this fails and the following error messages are received
Error evaluating 'AssertionFcn' callback of Checks_SRange block (mask) 'My Model/Saturation Check'.
Callback string is 'evalin('base',callback)'
Caused by:
Unrecognized function or variable 'SatCount'.
I then tried moving the variable SatCount in to the base workspace using,
assignin('base','SatCount',0)
for p = 1:N
in(p) = Simulink.SimulationInput('My Model');
in(p) = in(p).setVariable('Var1',Var1,'Workspace','My Model');
in(p) = in(p).setVariable('Var2',Var2,'Workspace','My Model');
in(p) = in(p).setModelParameter('StopTime',1);
end
out = parsim(in,'ShowProgress', 'on');
But the same error message is received implying that the callback function cannot access the SatCount variable in either the base or model workspaces.
If I execute the same code above on my local workstation which does not have a Parallel Toolbox licence, the code executes correctly and the SatCount variable is updated, implying my local execution is using the base workspace to access SatCount.
Does anyone have an explaination as to why this does not run correctly with the Parallel Toobox?

답변 (3개)

Rahul Kumar
Rahul Kumar 2021년 1월 11일
H David,
Variables specified on the SimulationInput object are not available in model or block callbacks. I would suggest using a PreSimFcn to set SatCount to zero before every simulation
in(p) = in(p).setPreSimFcn(@(~) assignin('base','SatCount', 0));
  댓글 수: 2
David Bye
David Bye 2021년 1월 14일
Rahul,
Thanks for your comment. However when running parsim, it seems the block callback cannot access the variables in either the base or model workspace. I don't know whether you suggestion will work as I have not had time to try it.
I have now decided to disable the callback in the block and instead output an assertion signal. This assert signal feeds in to a 32-bit counter, and the final value is then saved to the model workspace. This works well.
David
Tong Zhao
Tong Zhao 2022년 4월 23일
Rahul: Actually you can grab values from SimulationInput object during PreSimFcn, by accessing the wanted SimulationInput object properties during the PreSimFcn call. This is a nice workaround that worked for me. For example:
function in = my_presimfun(in)
assignin('base','SatCount',in.Variables(1).Value);
end

댓글을 달려면 로그인하십시오.


Nitin Kapgate
Nitin Kapgate 2021년 1월 13일
You can refer to a similar question answered here to resolve your issue. The issue described in this question is very similar to the one that is described in the link provided.

Paul
Paul 2023년 1월 22일
편집: Paul 2023년 1월 23일
Hi David,
I think there is relatively straightforward solution to the original Question (I realize you found an alternative solution).
Basically, transfer variables from the base workspace of Matlab to the base workspace of the worker, run the simulation on the worker where the assertion callback updates the count variable in the base workspace of the worker, then use the PostSimFcn to pull the count variable from the base workspace of the worker into the simulation output.
For example, I have a simulation mysim that drives a Sine wave into a the Check Static Range block with the upper and lower bounds set to +0.5 and -0.5. The assertion callback is: SatCount = SatCount + 1.
Here is the code, run in an m-script.
clear
load_system('mysim')
simIn = Simulink.SimulationInput('mysim');
simIn = setVariable(simIn,'theGain',1); % this variable for a different part of the model. Ignore
simIn = setPostSimFcn(simIn, @(out) simpostfcn(out));
SatCount = 0; % initialize in the Matlab base workspace
out = parsim(simIn,'TransferBaseWorkspaceVariables','on');
function out = simpostfcn(out)
SatCount = evalin('base','SatCount'); % will eval in the base workspace of the worker if run with parsim
out.SatCount = SatCount; % add SatCount to the simulation output
end
After running this code SatCount in the Matlab workspace is unchanged
>> SatCount
SatCount =
0
However, the correct value lives in out (along with other simulation output as normal)
>> out
out =
Simulink.SimulationOutput:
tout: [63x1 double]
y: [1x1 timeseries]
SatCount: [1x1 double]
SimulationMetadata: [1x1 Simulink.SimulationMetadata]
ErrorMessage: [0x0 char]
>> out.SatCount
ans =
38
An altertanative is to use the preSimFcn suggested by @Rahul Kumar, which actually looks cleaner. My focus here was on how to get SatCount returned in the output of parsim.

카테고리

Help CenterFile Exchange에서 Manual Performance Optimization에 대해 자세히 알아보기

제품


릴리스

R2020b

Community Treasure Hunt

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

Start Hunting!

Translated by