Main Content

Log Signals in For-Each Subsystems

The approach you use to log data for a signal in a for-each subsystem depends on whether the signal is a:

  • Nonbus signal — Log directly in a for-each subsystem.

  • A bus or array of buses — Use one of these approaches:

    • Use a Bus Selector block to select the signals you want to log and mark those signals for signal logging. This approach works well for many models.

    • Attach the signal to an Outport block and log the signal outside of the for-each subsystem. Use this approach when you want to log a whole bus, and that bus includes many bus elements.

Note

You cannot log buses directly in a for-each subsystem.

You cannot log a signal inside a referenced model that is inside a for-each subsystem if either of these conditions exists:

  • The for-each subsystem is in a model simulating in rapid accelerator mode.

  • The for-each subsystem is at the root-level of a model that is referenced by a Model block in accelerator mode.

The data for each logged signal in a for-each subsystem is saved in a separate Dataset element as a Simulink.SimulationData.Signal object. The format of the logged signal data depends on how you set the Dataset signal format configuration parameter:

  • If the setting is timeseries, then each signal object contains an array of MATLAB® timeseries objects. The array keeps the data from different for-each iteration separate.

  • If the setting is timetable, then each signal object contains a cell array of MATLAB timetable objects. The dimensions of this array match the number of for-each iterations. For example, if the for-each subsystem has three iterations, then the logged data has a 3x1 array of timeseries or timetable objects. Each layer of nesting adds another dimensions to the logged data if you use nested for-each subsystems.

Log Signal in Nested For-Each Subsystem

Open the model ex_loginsideforeach_nested.

mdl = "ex_loginsideforeach_nested";
open_system(mdl)

The ex_loginsideforeach_nested model has a 2x3 constant block connected to a for-each subsystem connected to a Terminator block.

In the Simulink® Editor, open the For Each Subsystem1 block. Inside that subsystem, open the For Each Subsystem2 block.

Inside the For Each Subsystem2 block the input is connected to a Unit Delay block which is connected to an Outport block. The signal is named nestedDelay.

Simulate the model.

sim(mdl);

Examine the signal logging data for the first iteration of the top subsystem and the third iteration of the bottom subsystem. The 2x3 timeseries results from two iterations at the first for-each level and three iterations at the second (nested) level.

logsout.get('nestedDelay')
ans = 
  Simulink.SimulationData.Signal
  Package: Simulink.SimulationData

  Properties:
              Name: 'nestedDelay'
    PropagatedName: ''
         BlockPath: [1x1 Simulink.SimulationData.BlockPath]
          PortType: 'outport'
         PortIndex: 1
            Values: [2x3 timeseries]

Return the values of the nestedDelay object.

logsout.get('nestedDelay').Values(1,3)
  timeseries

  Common Properties:
            Name: 'nestedDelay'
            Time: [5x1 double]
        TimeInfo: tsdata.timemetadata
            Data: [1x1x5 double]
        DataInfo: tsdata.datametadata

Log Buses in For-Each Subsystem

This example logs two buses, LIMITBUS and COUNTERBUS, in a for-each subsystem using signal logging. The elements of LIMITBUS are logged individually inside the for-each subsystem. The COUNTERBUS data is logged outside the for-each subsystem.

Open the ex_for_each_log_bus model.

mdl = "ex_for_each_log_bus";
open_system(mdl)

The top-model has a Constant block connected to a For Each Subsystem connected to a Terminator block.

In the Simulink® Editor, open the For Each Subsystem block.

To log the elements of LIMITBUS separately inside the for-each subsystem, the bus is connected to a Bus Selector block. Then, the individual signals are marked for logging.

To log COUNTERBUS outside the for-each subsystem, the bus data is output to the top-level model using an Outport block. Then, the OutsideForEach bus is marked for logging in the top-level model. To have the bus cross the subsystem boundary, the Bus Creator block that creates COUNTERBUS has the Output data type parameter set to Bus: COUNTERBUS and the Output as nonvirtual bus check box selected.

The for-each subsystem model

Simulate the model.

out1 = sim('ex_for_each_log_bus');

Examine the signal logging output logsout. Signal logging logs data in Dataset format. By default, the data for each logged signal or bus element is stored in the Dataset object as a timeseries.

out1.logsout
ans = 
Simulink.SimulationData.Dataset 'logsout' with 3 elements

                         Name                      BlockPath                                
                         ________________________  ________________________________________ 
    1  [1x1 Signal]      OutsideForEach            ex_for_each_log_bus/For Each Subsystem  
    2  [1x1 Signal]      <lower_saturation_limit>  ...g_bus/For Each Subsystem/Bus Selector
    3  [1x1 Signal]      <upper_saturation_limit>  ...g_bus/For Each Subsystem/Bus Selector

  - Use braces { } to access, modify, or add elements using index.

Access the <lower_saturation_limit> object, which is logged inside the for-each subsystem, using curly braces to get the second element in the Dataset object logsout.

lowerLimTS = out1.logsout{2}
lowerLimTS = 
  Simulink.SimulationData.Signal
  Package: Simulink.SimulationData

  Properties:
              Name: '<lower_saturation_limit>'
    PropagatedName: ''
         BlockPath: [1x1 Simulink.SimulationData.BlockPath]
          PortType: 'outport'
         PortIndex: 2
            Values: [3x1 timeseries]

lowerLimTS.Values
  3x1 timeseries array with properties:

    Events
    Name
    UserData
    Data
    DataInfo
    Time
    TimeInfo
    Quality
    QualityInfo
    IsTimeFirst
    TreatNaNasMissing
    Length

Access the OutsideForEach object, which is logged outside the for-each subsystem, using curly braces to get the first element in the Dataset object logsout.

outsideTS = out1.logsout{1}
outsideTS = 
  Simulink.SimulationData.Signal
  Package: Simulink.SimulationData

  Properties:
              Name: 'OutsideForEach'
    PropagatedName: ''
         BlockPath: [1x1 Simulink.SimulationData.BlockPath]
          PortType: 'outport'
         PortIndex: 1
            Values: [3x1 struct]

outsideTS.Values
ans=3×1 struct array with fields:
    data
    limits

If the Dataset signal format is timetable, then the software stores each logged signal or bus element in the Dataset object as a timetable. Specify the Dataset signal format as timetable. Then, simulate the model again.

out2 = sim('ex_for_each_log_bus','DatasetSignalFormat','timetable');

The data for the <lower_saturation_limit> object and the OutsideForEach object is now stored as a timetable.

lowerLimTT = out2.logsout{2}
lowerLimTT = 
  Simulink.SimulationData.Signal
  Package: Simulink.SimulationData

  Properties:
              Name: '<lower_saturation_limit>'
    PropagatedName: ''
         BlockPath: [1x1 Simulink.SimulationData.BlockPath]
          PortType: 'outport'
         PortIndex: 2
            Values: {3x1 cell}

lowerLimTT.Values
ans=3×1 cell array
    {1x1 timetable}
    {1x1 timetable}
    {1x1 timetable}

outsideTT = out2.logsout{1}
outsideTT = 
  Simulink.SimulationData.Signal
  Package: Simulink.SimulationData

  Properties:
              Name: 'OutsideForEach'
    PropagatedName: ''
         BlockPath: [1x1 Simulink.SimulationData.BlockPath]
          PortType: 'outport'
         PortIndex: 1
            Values: [3x1 struct]

outsideTT.Values
ans=3×1 struct array with fields:
    data
    limits

See Also

Blocks

Functions

Related Topics