Documentation

Organize Related Block Parameter Definitions in Structures

When you use numeric MATLAB® variables to set block parameter values in a model, large models can accumulate many variables, increasing the effort of maintenance and causing the variable names to grow in length.

Instead, you can organize these parameter values into structures. Each structure is a single variable and each field of the structure stores a numeric parameter value. You can assign meaningful names to the structures, substructures, and fields to indicate the purpose of each value.

Use structures to:

  • Reduce the number of workspace variables that you must maintain.

  • Avoid name conflicts between workspace variables.

    You cannot create two variables that have the same name in the same scope, such as in the base workspace. When you create structures, you must provide each field a name, but multiple structures can each contain a field that uses the same name. Therefore, you can use each structure and substructure as a namespace that prevents the field names from conflicting with each other and with other variable names in the same scope.

  • Logically group sets of block parameter values. For example, use nested structures to clearly identify the parameter values that each subsystem or referenced model uses.

If you use mask parameters or model arguments to pass parameter values to the components of a system, you can use structures to reduce the number of individual mask parameters or model arguments that you must maintain. Instead of passing multiple variables, you can pass a single structure variable.

For basic information about creating and manipulating MATLAB structures, see Structures. For basic information about setting block parameter values in a model, see Set Block Parameter Values.

To use structures to initialize bus signals, see Specify Initial Conditions for Bus Signals.

Create and Use Parameter Structure

This example shows how to create and use a parameter structure in a model.

The example model f14 uses multiple variables from the base workspace to set block parameter values. For example, when you open the model, it creates the variables Zw, Mw, and Mq in the base workspace. To organize these variables into a single structure variable:

  1. At the command prompt, open the example model.

    f14

  2. At the command prompt, create the parameter structure myGains. Set the field values by using the values of the target variables.

    myGains.Zw = Zw;
    myGains.Mw = Mw;
    myGains.Mq = Mq;

  3. In the Model Explorer, on the Model Hierarchy pane, click Base Workspace. In the Contents pane, right-click the variable Mq and select Find Where Used.

  4. In the Select a system dialog box, click the node f14 and click OK. Click OK when asked about updating the diagram.

  5. In the Contents pane, right-click the row corresponding to the block labeled Gain1 and select Properties. The Gain1 block dialog box opens.

  6. Change the value of the Gain parameter from Mq to myGains.Mq and click OK.

  7. In the Contents pane, right-click the row corresponding to the Transfer Fcn.1 block and select Properties.

  8. Change the value of the Denominator coefficients parameter from [1,-Mq] to [1,-myGains.Mq] and click OK.

  9. In the Model Hierarchy pane, click Base Workspace. Use Find Where Used to locate the blocks that use the variables Mw and Zw. In the block dialog boxes, replace the references to the variable names according to the table.

    Variable NameReplacement Name
    MwmyGains.Mw
    ZwmyGains.Zw

  10. Clear the old variables.

    clear Zw Mw Mq

Each of the modified block parameters now uses a field of the myGains structure. The numeric value of each structure field is equal to the value of the corresponding variable that you cleared.

You can use the functions Simulink.BlockDiagram.createVarStruct and Simulink.BlockDiagram.applyVarStruct to migrate a model to use a single parameter structure instead of multiple workspace variables. For an example, see Migration to Structure Parameters.

Manage Structure Variables

To create, modify, and view a variable whose value is a structure, you can use the Model Explorer whether you store the variable in the base workspace, a model workspace, or a data dictionary. To view and modify the field values in the structure, open the Variable Editor. For more information, see Edit and Manage Workspace Variables Used by Models.

Define Parameter Hierarchy by Creating Nested Structures

To further organize block parameter values, create a hierarchy of nested structures.

For example, suppose that you create subsystems named SubsystemA and SubsystemB in your model. You use variables such as Offset_SubsystemA and Offset_SubsystemB to set block parameter values in the subsystems.

Gain_SubsystemA = 15.23;
Offset_SubsystemA = 89;
Init_SubsystemA = 0.59;

Coeffs_SubsystemB = [5.32 7.99];
Offset_SubsystemB = 57;
Init1_SubsystemB = 1.76;
Init2_SubsystemB = 2.76;

Create a parameter structure that contains a substructure for each subsystem. Use the values of the existing variables to set the field values.

myParams = struct(...
    'SubsystemA',struct(...
        'Gain',Gain_SubsystemA,...
        'Offset',Offset_SubsystemA,...
        'Init',Init_SubsystemA),...
    'SubsystemB',struct(...
        'Coeffs',Coeffs_SubsystemB,...
        'Offset',Offset_SubsystemB,...
        'Init1',Init1_SubsystemB,...
        'Init2',Init2_SubsystemB)...
);

The single structure variable myParams contains all of the parameter information for the blocks in the subsystems. Because each substructure acts as a namespace, you can define the Offset field more than once.

To use the Offset field from the substructure SubsystemB as the value of a block parameter, specify the parameter value in the block dialog box as the expression myParams.SubsystemB.Offset.

Group Multiple Parameter Structures into an Array

To organize parameter structures that have similar characteristics, you can create a single variable whose value is an array of structures. This technique helps you to parameterize a model that contains multiple instances of an algorithm, such as a library subsystem or a referenced model that uses model arguments.

Suppose that you create two identical subsystems in a model.

Suppose that the blocks in each subsystem require three numeric values to set parameter values. Create an array of two structures to store the values.

myParams(1).Gain = 15.23;
myParams(1).Offset = 89;
myParams(1).Init = 0.59;

myParams(2).Gain = 11.93;
myParams(2).Offset = 57;
myParams(2).Init = 2.76;

Each structure in the array stores the three parameter values for one of the subsystems.

To set the value of a block parameter in one of the subsystems, specify an expression that references a field of one of the structures in the array. For example, use the expression myParams(2).Init.

Organize Parameter Values for Reusable Components and Iterative Algorithms

You can also partition an array of structures in a For Each Subsystem block. This technique helps you to organize workspace variables when a model executes an algorithm repeatedly, for example by iterating the algorithm over a vector signal. For an example, see Repeat an Algorithm Using a For Each Subsystem.

If you use model arguments to specify different parameter values across multiple instances of a referenced model, you can use arrays of structures to organize the model argument values. In the referenced model workspace, create a structure variable and configure the model to use the structure as a model argument. Use the fields of the structure to set block parameter values in the model. Then, create an array of structures in the base workspace or a data dictionary to which the parent model or models are linked. In the parent model or models, use each of the structures in the array as the value of the model argument in a Model block. Each structure in the array stores the parameter values for one instance of the referenced model.

The example model sldemo_mdlref_datamngt contains three instances (masked Model blocks) of the referenced model sldemo_mdlref_counter_datamngt. The base workspace variables IC1, IC2, Param1, and Param2 are Simulink.Parameter objects whose values are structures. The parent model uses these variables to set the values of mask parameters on the Model blocks. Since IC1 is structurally identical to IC2, and Param1 to Param2, you can combine these four structures into two arrays of structures.

  1. Open the example parent model.

    sldemo_mdlref_datamngt

    The model creates the four Simulink.Parameter objects in the base workspace.

  2. Open the example referenced model.

    sldemo_mdlref_counter_datamngt

    The model workspace defines two model arguments, CounterICs and CounterParams, whose values are structures. The blocks in the model use the fields of these structures to set parameter values.

  3. In the model sldemo_mdlref_datamngt, double-click each of the Model blocks, which opens the mask dialog boxes. Each mask uses a different combination of the four parameter objects from the base workspace to set the model argument values in the Model blocks.

  4. At the command prompt, view the values of the parameter objects from the base workspace.

    Param1.Value
    IC1.Value

    ans = 
    
         Increment: 1
        LowerLimit: -20
        UpperLimit: 20
    
    
    ans = 
    
                Count: 0
        OverflowState: InRange

    The value of each parameter object is a structure. The structures in Param2 and IC2 have the same fields as the structures in Param1 and IC1 but different field values.

  5. Combine the four parameter objects into two parameter objects whose values are arrays of structures.

    % Create a new parameter object by copying Param1.
    Param = Param1.copy;
    
    % Use the structure in Param2 as the second structure in the new object.
    Param.Value(2) = Param2.Value;
    % The value of Param is now an array of two structures.
    
    % Delete the old objects Param1 and Param2.
    clear Param1 Param2
    
    % Create a new parameter object by copying IC1.
    % Use the structure in IC2 as the second structure in the new object.
    IC = IC1.copy;
    IC.Value(2) = IC2.Value;
    clear IC1 IC2

  6. In the parent model, double-click each of the Model blocks. In the mask dialog boxes, replace the parameter values according to the table.

    Previous ValueNew Value
    Param1Param(1)
    IC1IC(1)
    Param2Param(2)
    IC2IC(2)

Each Model block sets the value of the model argument CounterICs by using one of the structures in the array IC. Similarly, each block sets the value of CounterParams by using one of the structures in Param.

Explicitly Specify Field Data Types

To use a structure or array of structures to organize parameter values that use a data type other than double, you can explicitly specify the type when you create the structure. When you create the structure, use typed expressions such as single(15.23) to specify the field values.

myParams.Gain = single(15.23);

If you want to change the field value later, you must remember to explicitly specify the type again. If you do not specify the type, the field value uses the data type double instead:

myParams.Gain = 15.23;
% The field 'Gain' now uses the data type 'double' instead of 'single'.

To preserve the type specification, you can use subscripted assignment to assign a new value to the field:

% Assign value of type 'single'.
myParams.Gain = single(15.23);

% Assign new value while retaining type 'single'.
myParams.Gain(:) = 11.79;

To match a fixed-point data type, set the field value by using an fi object.

Control Field Data Types and Characteristics by Creating Parameter Object

A Simulink.Parameter object allows you to separate the value of a block parameter from its data type. If you use a parameter object to store a structure or array of structures, you can create a Simulink.Bus object to use as the data type of the entire structure.

You can use the bus object and the parameter object to explicitly control:

  • The data type of each field. When you use this technique, you do not have to remember to use typed expressions or subscripted assignment to set the field values.

  • The complexity, dimensions, and units of each field.

  • The minimum and maximum value of each field if the field represents a tunable parameter value.

  • The shape of the entire structure. The shape of the structure is the number, names, and hierarchy of fields.

  • The tunability of the structure in the code that you generate from the model.

  1. Create a parameter structure myParams.

    myParams = struct(...
        'SubsystemA',struct(...
            'Gain',15.23,...
            'Offset',89,...
            'Init',0.59),...
        'SubsystemB',struct(...
            'Coeffs',[5.32 7.99],...
            'Offset',57,...
            'Init1',1.76,...
            'Init2',2.76)...
    );

  2. Use the function Simulink.Bus.createObject to create Simulink.Bus objects that represent the structure and substructures.

    Simulink.Bus.createObject(myParams)
    

    Because myParams contains two unique substructures, the function creates three Simulink.Bus objects: one named slBus1 to represent the parent structure myParams, one named SubsystemA for the substructure SubsystemA, and one named SubsystemB for the substructure SubsystemB.

  3. Rename the bus object slBus1 as myParamsType.

    myParamsType = slBus1;
    clear slBus1

  4. Store the structure myParams in a Simulink.Parameter object.

    myParams = Simulink.Parameter(myParams);

    The Value property of the parameter object contains the structure.

  5. Set the data type of the parameter object to the bus object myParamsType.

    myParams.DataType = 'Bus: myParamsType';

  6. Open the Bus Editor to view the bus objects.

    buseditor

  7. In the Model Hierarchy pane, click the node SubsystemA. In the Contents pane, set the field data types according to the figure.

  8. Optionally, set the field data types for the substructure SubsystemB.

The parameter object myParams stores the parameter structure. The data type of the parameter object is the bus object myParamsType. Prior to simulation and code generation, the parameter object casts the field values to the data types that you specified in the bus object.

To use one of the fields to set a block parameter value, specify an expression such as myParams.SubsystemB.Init1.

To access the field values at the command prompt, use the Value property of the parameter object. Because the bus object controls the field data types, you do not need to use a typed expression to set the field value.

myParams.Value.SubsystemA.Gain = 12.79;

The bus object strictly controls the field characteristics and the shape of the structure. For example, if you set the value of the two-element field myParams.SubsystemB.Coeffs to a three-element array, the model generates an error when you set a block parameter value. To change the dimensions of the field, modify the element Coeffs in the bus object SubsystemB.

To manipulate bus objects after you create them, see Modify Bus Objects and Save and Import Bus Objects.

Match Field Data Type with Signal Data Type

Suppose that you use the field myParams.SubsystemA.Gain to set the value of the Gain parameter in a Gain block. If you want the data type of the field to match the data type of the output signal of the block, consider using a Simulink.AliasType or a Simulink.NumericType object to set the data type of the field and the signal. If you do not use a data type object, you must remember to change the data type of the field whenever you change the data type of the signal.

  1. At the command prompt, create a Simulink.AliasType object that represents the data type single.

    myType = Simulink.AliasType;
    myType.BaseType = 'single';

  2. In the Gain block dialog box, on the Signal Attributes tab, set Output data type to myType.

  3. At the command prompt, open the Bus Editor.

    buseditor

  4. In the Model Hierarchy pane, select the bus object SubsystemA. In the Contents pane, set the data type of the field Gain to myType.

Now, both the output signal of the Gain block and the structure field myParams.SubsystemA.Gain use the data type that you specify by using the BaseType property of myType.

For more information about data type objects, see Simulink.AliasType and Simulink.NumericType.

Enforce Uniformity in an Array of Structures

All of the structures in an array of structures must have the same hierarchy of fields. Each field in the hierarchy must have the same characteristics throughout the array. You can use a parameter object and a bus object to enforce this uniformity among the structures.

To use a parameter object to represent an array of parameter structures, set the value of the object to the array of structures:

% Create array of structures.
myParams(1).Gain = 15.23;
myParams(1).Offset = 89;
myParams(1).Init = 0.59;
myParams(2).Gain = 11.93;
myParams(2).Offset = 57;
myParams(2).Init = 2.76;

% Create bus object.
Simulink.Bus.createObject(myParams);
myParamsType = slBus1;
clear slBus1

% Create parameter object and set data type.
myParams = Simulink.Parameter(myParams);
myParams.DataType = 'Bus: myParamsType';

To use one of the fields to set a block parameter value, specify an expression such as myParams(2).Offset.

To access the field values at the command prompt, use the Value property of the parameter object.

myParams.Value(2).Offset = 129;

Create a Structure of Constant-Valued Signals

You can use a structure in a Constant block to create a single bus signal that transmits multiple numeric constants. For more information, see Constant. For information about bus signals, see Buses.

Considerations Before Migrating to Parameter Structures

Before you migrate a model to use parameter structures, discover all of the blocks in the target model and in other models that use the variables that you intend to replace.

For example, suppose two blocks in a model use the workspace variable myVar. If you create a structure myParams with a field myVar, and set the parameter value in only one of the blocks to myParams.myVar, the other block continues to use the variable myVar. If you delete myVar, the model generates an error because the remaining block requires the deleted variable.

To discover all of the blocks that use a variable:

  1. Open all models that might use the variable. If the models are in a model reference hierarchy, you can open only the top model.

  2. Right-click the variable in the Model Explorer Contents pane and select Find Where Used. The Model Explorer displays all of the blocks that use the variable.

You can discover variable usage only in models that are open. Before you migrate to parameter structures, open all models that might use the target variables. For more information about determining variable usage in a model, see Finding Blocks That Use a Specific Variable.

Alternatively, you can refrain from deleting myVar. However, if you change the value of the myParams.myVar structure field, you must remember to change the value of myVar to match.

Parameter Structures in the Generated Code

You can configure parameter structures to appear in the generated code as structures and arrays of structures. For information about generating code with structure parameters, see Organize Block Parameter Values into Structures in the Generated Code.

Parameter Structure Limitations

  • The value of a field that you use to set a block parameter must be numeric or of an enumerated type. The value of a field can be a real or complex scalar, vector, or multidimensional array.

  • If the value of any of the fields of a structure is a multidimensional array, you cannot tune any of the field values during simulation.

  • All of the structures in an array of structures must have the same hierarchy of fields. Each field in the hierarchy must have the same characteristics throughout the array:

    • Field name

    • Numeric data type, such as single or int32

    • Complexity

    • Dimensions

    Suppose that you define an array of two structures.

    paramStructArray = ...
    [struct('sensor1',int16(7),'sensor2',single(9.23)) ...
     struct('sensor1',int32(9),'sensor2',single(11.71))];

    You cannot use any of the fields in a block parameter because the field sensor1 uses a different data type in each structure.

  • Parameter structures do not support context-sensitive data typing in the generated code. If the parameter structure is tunable in the code, the fields of the structure use the numeric data types that you specify by using either typed expressions or a Simulink.Bus object. If you do not use typed expressions or a Simulink.Bus object, the fields of the structure use the double data type.

Package Shared Breakpoint and Table Data for Lookup Tables

When you share data between lookup table blocks, consider using Simulink.LookupTable and Simulink.Breakpoint objects instead of structures to store and group the data. This technique improves model readability by clearly identifying the data as parts of a lookup table and explicitly associating breakpoint data with table data. See Package Shared Breakpoint and Table Data for Lookup Tables.

Related Examples

Was this topic helpful?