Discover MakerZone

MATLAB and Simulink resources for Arduino, LEGO, and Raspberry Pi

Learn more

Discover what MATLAB® can do for your career.

Opportunities for recent engineering grads.

Apply Today

Thread Subject:
Store Historical Data in Level2 M Function Dwork Vector

Subject: Store Historical Data in Level2 M Function Dwork Vector

From: Tiger

Date: 28 Feb, 2013 22:13:09

Message: 1 of 8

Hi guys,

I made a little experiment to test how Level 2 Matlab Function Dwork vectors work:

Input(1): is the simulation clock, sample time = 1, so you can imagine at every sample time Input(1) = 1, then, 2, then, 3, etc..

Input(2): is a Constant = 10, so you can imagine at every sample time Input(2) = 10, then, 10, then, 10, etc..

At the Output function, I wrote:
if ismember(input(2), Dwork(1)) == 1
    output(1) = 1;
else
    output(1) = 0;
end

At the Update function, I wrote:
Dwork(1) = Input(1); % Assuming that Dwork "saves" every value received by Input(1). I thought that at the 5th sample time, Dwork would be [1, 2, 3, 4, 5].

The graph/scope of the output that I'd like to have is zeros from 0-10, then ones from 11-20. Because from the 10th sample time, and onwards, the value 10 from Input(1) should, always, exist in Dwork(1). However, the output scope was all zeros except at the 11th sample time.

The problem here is that Dwork(1) stores the current value received from Input(1). How can I, please, configure Dwork(1) to keep all the values received from Input(1) throughout the simulation?

I hope my query is clear here, and looking forward your help in that.
______________
Cheers, T

Subject: Store Historical Data in Level2 M Function Dwork Vector

From: Tiger

Date: 28 Feb, 2013 22:18:09

Message: 2 of 8

Hi again, I though of posting here the Level 2 code I did:

function Level2_Testing_Dwork(block)
setup(block);

function setup(block)
% Register number of ports
block.NumInputPorts = 2; %
block.NumOutputPorts = 1;

% Setup port properties to be dynamically inherited
block.SetPreCompInpPortInfoToDynamic;
block.SetPreCompOutPortInfoToDynamic;

% Override input port properties
% Clock
block.InputPort(1).DimensionsMode = 'Fixed';
block.InputPort(1).Dimensions = 1;
block.InputPort(1).DatatypeID = 0; % double
block.InputPort(1).Complexity = 'Real';
block.InputPort(1).DirectFeedthrough = true;
block.InputPort(1).SamplingMode = 'Sample';
% Constant
block.InputPort(2).DimensionsMode = 'Fixed';
block.InputPort(2).Dimensions = 1;
block.InputPort(2).DatatypeID = 0; % double
block.InputPort(2).Complexity = 'Real';
block.InputPort(2).DirectFeedthrough = true;
block.InputPort(2).SamplingMode = 'Sample';

% Override output port properties
% Belongs To?
block.OutputPort(1).DimensionsMode = 'Fixed';
block.OutputPort(1).Dimensions = 1;
block.OutputPort(1).DatatypeID = 0; % double
block.OutputPort(1).Complexity = 'Real';
block.OutputPort(1).SamplingMode = 'Sample';

block.SampleTimes = [-1 0];

% Specify if Accelerator should use TLC or call back into M-file
block.SetAccelRunOnTLC(false);
block.SimStateCompliance = 'DefaultSimState';

% PostPropagationSetup: Setup work areas and state variables. Can also register run-time methods here
block.RegBlockMethod('PostPropagationSetup', @DoPostPropSetup);

% Start: Called in order to initialize state and work area values
block.RegBlockMethod('Start', @Start);

% Outputs: Called to generate block outputs in simulation step
block.RegBlockMethod('Outputs', @Outputs);

% Update: Called to update discrete states during simulation step
block.RegBlockMethod('Update', @Update);

function DoPostPropSetup(block)
% Dwrok vector set-up
block.NumDworks = 1;
% Completed_T_ID.
block.Dwork(1).Name = 'Completed_T_ID';
block.Dwork(1).Dimensions = 1;
block.Dwork(1).DatatypeID = 0; % double
block.Dwork(1).Complexity = 'Real'; % real
block.Dwork(1).UsedAsDiscState = true;

% Register all tunable parameters as runtime parameters.
block.AutoRegRuntimePrms;

function Start(block)
block.Dwork(1).Data = 0;

function Outputs(block)
if ismember(block.InputPort(2).Data, block.Dwork(1).Data) == 1
    block.OutputPort(1).Data = 1;
else
    block.OutputPort(1).Data = 0;
end
        
function Update(block)
block.Dwork(1).Data = block.InputPort(1).Data;

Subject: Store Historical Data in Level2 M Function Dwork Vector

From: Phil Goddard

Date: 1 Mar, 2013 22:17:09

Message: 3 of 8

The code in your original post does what it is supposed to do.
The output will only be non-zero when the DWork vector is equal to 10 (and there's a one period time delay, so the non-zero occurs at the 11th period).

Here you are defining a single (scalar valued) work vector
> block.Dwork(1).Dimensions = 1;

and here
> block.Dwork(1).Data = 0;
and here
> block.Dwork(1).Data = block.InputPort(1).Data;
you are assigning a single number into the work vector.

So why why here
> I thought that at the 5th sample time, Dwork would be [1, 2, 3, 4, 5].

would you expect it to be a vector?

If you want a vector then you need to define it using
block.Dwork(1).Dimensions = 256; %or whatever length of vector you want

And then use standard MATLAB matrix indexing to put elements into the vector,
block.Dwork(1).Data(idx) = newValue;
where idx is an integer index into the matrix defining what element to replace.

Note however that you cannot dynamically resize a Work Vector so you need to define its size during initialization.
If you want to store all historical values then you'll possibly need a very large matrix.

Phil.

Subject: Store Historical Data in Level2 M Function Dwork Vector

From: Tiger

Date: 3 Mar, 2013 15:25:07

Message: 4 of 8

Phil, thanks indeed. I can see now why I was expecting somehing different from what I programmed it, the Dwork, to do.

Is there an exemplary tutorial on how to use use matrix indexing in Level 2 Dwork vectors. I've already started "playing" with my code to do what you suggested, and it'll be a valuable reference, for me, to have a tutorial to liaise to whenever I get stuck on "silly" programming bugs.

Cheerio

Subject: Store Historical Data in Level2 M Function Dwork Vector

From: Tiger

Date: 3 Mar, 2013 18:26:08

Message: 5 of 8

For the benefit of everyone else, if you'd like to store historical values in Dwork vector, and my little experiment above, in my 1st post, is matching what you want to do, then follow the code below. Thanks Phil, my code works now, and the scope outputs ones at the 11th sample time onwards. Although my real application is slightly more complicated than this, but at least I got the foundations right, I'll build on it. In fact, what I want to be able to do, is storing only unique values from Input(1), as I might receive duplicates, which is a waste of, storing-wise, Dwork space.

function Level2_Testing_Dwork(block)
setup(block);

function setup(block)
% Register number of ports
block.NumInputPorts = 2;
block.NumOutputPorts = 1;

% Setup port properties to be dynamically inherited
block.SetPreCompInpPortInfoToDynamic;
block.SetPreCompOutPortInfoToDynamic;

% Override input port properties
% Clock
block.InputPort(1).DimensionsMode = 'Fixed';
block.InputPort(1).Dimensions = 1;
block.InputPort(1).DatatypeID = 0; % double
block.InputPort(1).Complexity = 'Real';
block.InputPort(1).DirectFeedthrough = true;
block.InputPort(1).SamplingMode = 'Sample';
% Constant
block.InputPort(2).DimensionsMode = 'Fixed';
block.InputPort(2).Dimensions = 1;
block.InputPort(2).DatatypeID = 0; % double
block.InputPort(2).Complexity = 'Real';
block.InputPort(2).DirectFeedthrough = true;
block.InputPort(2).SamplingMode = 'Sample';

% Override output port properties
% Belongs To?
block.OutputPort(1).DimensionsMode = 'Fixed';
block.OutputPort(1).Dimensions = 1;
block.OutputPort(1).DatatypeID = 0; % double
block.OutputPort(1).Complexity = 'Real';
block.OutputPort(1).SamplingMode = 'Sample';
block.SampleTimes = [-1 0];

% Specify if Accelerator should use TLC or call back into M-file
block.SetAccelRunOnTLC(false);
block.SimStateCompliance = 'DefaultSimState';

% PostPropagationSetup: Setup work areas and state variables. Can also register run-time methods here
block.RegBlockMethod('PostPropagationSetup', @DoPostPropSetup);

% ProcessParameters: Called in order to allow update of run-time parameters.
block.RegBlockMethod('ProcessParameters', @ProcessPrms);

% Start: Called in order to initialize state and work area values
block.RegBlockMethod('Start', @Start);

% Outputs: Called to generate block outputs in simulation step
block.RegBlockMethod('Outputs', @Outputs);

% Update: Called to update discrete states during simulation step
block.RegBlockMethod('Update', @Update);

function DoPostPropSetup(block)
% Dwrok vector set-up
block.NumDworks = 1;
% Completed_T_ID.
block.Dwork(1).Name = 'Completed_T_ID';
block.Dwork(1).Dimensions = 150; % An arbitrary number.
block.Dwork(1).DatatypeID = 0; % double
block.Dwork(1).Complexity = 'Real'; % real
block.Dwork(1).UsedAsDiscState = true;

% Register all tunable parameters as runtime parameters.
block.AutoRegRuntimePrms;

function ProcessPrms(block)
block.AutoUpdateRuntimePrms;

function Start(block)
block.Dwork(1).Data = zeros(1, 150);

function Outputs(block)
if ismember(block.InputPort(2).Data, block.Dwork(1).Data) == 1
    block.OutputPort(1).Data = 1;
else
    block.OutputPort(1).Data = 0;
end

function Update(block)
first_zero_index = numel(find(block.Dwork(1).Data)) + 1; % Calculating the index of the first zero element in Dwork.
block.Dwork(1).Data(first_zero_index) = block.InputPort(1).Data; % Assigning the newly received value into Dwork's first zero element.

Subject: Store Historical Data in Level2 M Function Dwork Vector

From: Phil Goddard

Date: 4 Mar, 2013 14:33:08

Message: 6 of 8


Your code would be faster if you define a second DWork vector to store the index of the next element to write to.
That will avoid the multiple (costly) calls to find.

> function Update(block)
> first_zero_index = numel(find(block.Dwork(1).Data)) + 1; % Calculating the index of the first zero element in Dwork.

Phil.

Subject: Store Historical Data in Level2 M Function Dwork Vector

From: Tiger

Date: 5 Mar, 2013 20:31:09

Message: 7 of 8

Hi Phil,
Thanks for your posts. In fact my Input(1) usually contains duplicate values. So, my Update Function has to filter-out the dupicates first, then assign the newly received value (and tested against duplication) into the next zero-element in Dwork(1). However, I'm having a bug here, the Dwork(1) fails at storing 2 out of 131 newly received values that are uniqie and have not be previously been stored in Dwork(1) before, yet, after the simulation, I realised that Dwork(1) didn't store them at all. I'm thinking now because of the "costly" 'find' function I'm using, just like what you suggested. I'm not sure to be honest, could it be that? Here's my Update function code:
_________________________________________________________
function Update(block)
first_zero_index = numel(find(block.Dwork(1).Data)) + 1; % Calculating the index of the first zero element in Dwork1(.
if ismember(block.InputPort(1).Data, block.Dwork(1).Data) == 0 % IF newly received Completed_T_ID isn't in Dwork(1).
    block.Dwork(1).Data(first_zero_index) = block.InputPort(1).Data; % Do assig the newly received Complete_T_ID into Dwork's first zero element.
end
_________________________________________________________
Any idea why Dwork(1) didn't store 2 out of 131 unique values (IDs) during simulation. Also, how do you think I can utilise a second Dwork in my code? I get the general idea but, to be honest, not sure what code, other than 'find/numel' I can use for Dwork(1) or Dwork(2). Can you, please, elaborate? Cheers Phil.

Subject: Store Historical Data in Level2 M Function Dwork Vector

From: Tiger

Date: 6 Mar, 2013 02:23:08

Message: 8 of 8

I managed to debug it and found out that the problem resides at having the Level-2 M Function receiving more than one value instantaneously. Thus, Dwork(1) only stores one value and discards the rest. I had to manually change the Service Time of clashing entities so they arrive at the Level-2 function in different time samples.

However, this "quick" solution can be troublesome if I scale-up my system to handle 1000s of entities. Any suggestions, please?

Cheers

Tags for this Thread

What are tags?

A tag is like a keyword or category label associated with each thread. Tags make it easier for you to find threads of interest.

Anyone can tag a thread. Tags are public and visible to everyone.

Contact us